lnd_taproot_test.go 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971
  1. package itest
  2. import (
  3. "bytes"
  4. "crypto/sha256"
  5. "encoding/hex"
  6. "testing"
  7. "github.com/btcsuite/btcd/blockchain"
  8. "github.com/btcsuite/btcd/btcec/v2"
  9. "github.com/btcsuite/btcd/btcec/v2/schnorr"
  10. "github.com/btcsuite/btcd/btcutil"
  11. "github.com/btcsuite/btcd/btcutil/psbt"
  12. "github.com/btcsuite/btcd/chaincfg/chainhash"
  13. "github.com/btcsuite/btcd/txscript"
  14. "github.com/btcsuite/btcd/wire"
  15. "github.com/lightningnetwork/lnd/funding"
  16. "github.com/lightningnetwork/lnd/input"
  17. "github.com/lightningnetwork/lnd/lnrpc"
  18. "github.com/lightningnetwork/lnd/lnrpc/chainrpc"
  19. "github.com/lightningnetwork/lnd/lnrpc/signrpc"
  20. "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
  21. "github.com/lightningnetwork/lnd/lntest"
  22. "github.com/lightningnetwork/lnd/lntest/node"
  23. "github.com/lightningnetwork/lnd/lnwallet/chainfee"
  24. "github.com/stretchr/testify/require"
  25. )
  26. const (
  27. testTaprootKeyFamily = 77
  28. testAmount = 800_000
  29. signMethodBip86 = signrpc.SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND_BIP0086
  30. signMethodRootHash = signrpc.SignMethod_SIGN_METHOD_TAPROOT_KEY_SPEND
  31. signMethodTapscript = signrpc.SignMethod_SIGN_METHOD_TAPROOT_SCRIPT_SPEND
  32. )
  33. var (
  34. hexDecode = func(keyStr string) []byte {
  35. keyBytes, _ := hex.DecodeString(keyStr)
  36. return keyBytes
  37. }
  38. dummyInternalKey, _ = btcec.ParsePubKey(hexDecode(
  39. "03464805f5468e294d88cf15a3f06aef6c89d63ef1bd7b42db2e0c74c1ac" +
  40. "eb90fe",
  41. ))
  42. )
  43. // testTaproot ensures that the daemon can send to and spend from taproot (p2tr)
  44. // outputs.
  45. func testTaproot(ht *lntest.HarnessTest) {
  46. testTaprootSendCoinsKeySpendBip86(ht, ht.Alice)
  47. testTaprootComputeInputScriptKeySpendBip86(ht, ht.Alice)
  48. testTaprootSignOutputRawScriptSpend(ht, ht.Alice)
  49. testTaprootSignOutputRawScriptSpend(
  50. ht, ht.Alice, txscript.SigHashSingle,
  51. )
  52. testTaprootSignOutputRawKeySpendBip86(ht, ht.Alice)
  53. testTaprootSignOutputRawKeySpendBip86(
  54. ht, ht.Alice, txscript.SigHashSingle,
  55. )
  56. testTaprootSignOutputRawKeySpendRootHash(ht, ht.Alice)
  57. muSig2Versions := []signrpc.MuSig2Version{
  58. signrpc.MuSig2Version_MUSIG2_VERSION_V040,
  59. signrpc.MuSig2Version_MUSIG2_VERSION_V100RC2,
  60. }
  61. for _, version := range muSig2Versions {
  62. testTaprootMuSig2KeySpendBip86(ht, ht.Alice, version)
  63. testTaprootMuSig2KeySpendRootHash(ht, ht.Alice, version)
  64. testTaprootMuSig2ScriptSpend(ht, ht.Alice, version)
  65. testTaprootMuSig2CombinedLeafKeySpend(ht, ht.Alice, version)
  66. testMuSig2CombineKey(ht, ht.Alice, version)
  67. }
  68. testTaprootImportTapscriptFullTree(ht, ht.Alice)
  69. testTaprootImportTapscriptPartialReveal(ht, ht.Alice)
  70. testTaprootImportTapscriptRootHashOnly(ht, ht.Alice)
  71. testTaprootImportTapscriptFullKey(ht, ht.Alice)
  72. }
  73. // testTaprootSendCoinsKeySpendBip86 tests sending to and spending from
  74. // p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
  75. // internally uses the ComputeInputScript method for signing.
  76. func testTaprootSendCoinsKeySpendBip86(ht *lntest.HarnessTest,
  77. alice *node.HarnessNode) {
  78. // We'll start the test by sending Alice some coins, which she'll use to
  79. // send to herself on a p2tr output.
  80. ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
  81. // Let's create a p2tr address now.
  82. p2trResp := alice.RPC.NewAddress(&lnrpc.NewAddressRequest{
  83. Type: AddrTypeTaprootPubkey,
  84. })
  85. // Assert this is a segwit v1 address that starts with bcrt1p.
  86. require.Contains(
  87. ht, p2trResp.Address, ht.Miner.ActiveNet.Bech32HRPSegwit+"1p",
  88. )
  89. // Send the coins from Alice's wallet to her own, but to the new p2tr
  90. // address.
  91. alice.RPC.SendCoins(&lnrpc.SendCoinsRequest{
  92. Addr: p2trResp.Address,
  93. Amount: 0.5 * btcutil.SatoshiPerBitcoin,
  94. TargetConf: 6,
  95. })
  96. txid := ht.Miner.AssertNumTxsInMempool(1)[0]
  97. // Wait until bob has seen the tx and considers it as owned.
  98. p2trOutputIndex := ht.GetOutputIndex(txid, p2trResp.Address)
  99. op := &lnrpc.OutPoint{
  100. TxidBytes: txid[:],
  101. OutputIndex: uint32(p2trOutputIndex),
  102. }
  103. ht.AssertUTXOInWallet(alice, op, "")
  104. // Mine a block to clean up the mempool.
  105. ht.MineBlocksAndAssertNumTxes(1, 1)
  106. // Let's sweep the whole wallet to a new p2tr address, making sure we
  107. // can sign transactions with v0 and v1 inputs.
  108. p2trResp = alice.RPC.NewAddress(&lnrpc.NewAddressRequest{
  109. Type: lnrpc.AddressType_TAPROOT_PUBKEY,
  110. })
  111. alice.RPC.SendCoins(&lnrpc.SendCoinsRequest{
  112. Addr: p2trResp.Address,
  113. SendAll: true,
  114. TargetConf: 6,
  115. })
  116. // Make sure the coins sent to the address are confirmed correctly,
  117. // including the confirmation notification.
  118. confirmAddress(ht, alice, p2trResp.Address)
  119. }
  120. // testTaprootComputeInputScriptKeySpendBip86 tests sending to and spending from
  121. // p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
  122. // internally uses the ComputeInputScript method for signing.
  123. func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest,
  124. alice *node.HarnessNode) {
  125. // We'll start the test by sending Alice some coins, which she'll use
  126. // to send to herself on a p2tr output.
  127. ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
  128. // Let's create a p2tr address now.
  129. p2trAddr, p2trPkScript := newAddrWithScript(
  130. ht, alice, lnrpc.AddressType_TAPROOT_PUBKEY,
  131. )
  132. // Send the coins from Alice's wallet to her own, but to the new p2tr
  133. // address.
  134. req := &lnrpc.SendCoinsRequest{
  135. Addr: p2trAddr.String(),
  136. Amount: testAmount,
  137. TargetConf: 6,
  138. }
  139. alice.RPC.SendCoins(req)
  140. // Wait until bob has seen the tx and considers it as owned.
  141. txid := ht.Miner.AssertNumTxsInMempool(1)[0]
  142. p2trOutputIndex := ht.GetOutputIndex(txid, p2trAddr.String())
  143. op := &lnrpc.OutPoint{
  144. TxidBytes: txid[:],
  145. OutputIndex: uint32(p2trOutputIndex),
  146. }
  147. ht.AssertUTXOInWallet(alice, op, "")
  148. p2trOutpoint := wire.OutPoint{
  149. Hash: *txid,
  150. Index: uint32(p2trOutputIndex),
  151. }
  152. // Mine a block to clean up the mempool.
  153. ht.MineBlocksAndAssertNumTxes(1, 1)
  154. // We'll send the coins back to a p2wkh address.
  155. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  156. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  157. )
  158. // Create fee estimation for a p2tr input and p2wkh output.
  159. feeRate := chainfee.SatPerKWeight(12500)
  160. estimator := input.TxWeightEstimator{}
  161. estimator.AddTaprootKeySpendInput(txscript.SigHashDefault)
  162. estimator.AddP2WKHOutput()
  163. estimatedWeight := int64(estimator.Weight())
  164. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  165. tx := wire.NewMsgTx(2)
  166. tx.TxIn = []*wire.TxIn{{
  167. PreviousOutPoint: p2trOutpoint,
  168. }}
  169. value := int64(testAmount - requiredFee)
  170. tx.TxOut = []*wire.TxOut{{
  171. PkScript: p2wkhPkScript,
  172. Value: value,
  173. }}
  174. var buf bytes.Buffer
  175. require.NoError(ht, tx.Serialize(&buf))
  176. utxoInfo := []*signrpc.TxOut{{
  177. PkScript: p2trPkScript,
  178. Value: testAmount,
  179. }}
  180. signReq := &signrpc.SignReq{
  181. RawTxBytes: buf.Bytes(),
  182. SignDescs: []*signrpc.SignDescriptor{{
  183. Output: utxoInfo[0],
  184. InputIndex: 0,
  185. Sighash: uint32(txscript.SigHashDefault),
  186. }},
  187. PrevOutputs: utxoInfo,
  188. }
  189. signResp := alice.RPC.ComputeInputScript(signReq)
  190. tx.TxIn[0].Witness = signResp.InputScripts[0].Witness
  191. // Serialize, weigh and publish the TX now, then make sure the
  192. // coins are sent and confirmed to the final sweep destination address.
  193. publishTxAndConfirmSweep(
  194. ht, alice, tx, estimatedWeight,
  195. &chainrpc.SpendRequest{
  196. Outpoint: &chainrpc.Outpoint{
  197. Hash: p2trOutpoint.Hash[:],
  198. Index: p2trOutpoint.Index,
  199. },
  200. Script: p2trPkScript,
  201. },
  202. p2wkhAddr.String(),
  203. )
  204. }
  205. // testTaprootSignOutputRawScriptSpend tests sending to and spending from p2tr
  206. // script addresses using the script path with the SignOutputRaw RPC.
  207. func testTaprootSignOutputRawScriptSpend(ht *lntest.HarnessTest,
  208. alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
  209. // For the next step, we need a public key. Let's use a special family
  210. // for this.
  211. req := &walletrpc.KeyReq{KeyFamily: testTaprootKeyFamily}
  212. keyDesc := alice.RPC.DeriveNextKey(req)
  213. leafSigningKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes)
  214. require.NoError(ht, err)
  215. // Let's create a taproot script output now. This is a hash lock with a
  216. // simple preimage of "foobar".
  217. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  218. // Let's add a second script output as well to test the partial reveal.
  219. leaf2 := testScriptSchnorrSig(ht.T, leafSigningKey)
  220. inclusionProof := leaf1.TapHash()
  221. tapscript := input.TapscriptPartialReveal(
  222. dummyInternalKey, leaf2, inclusionProof[:],
  223. )
  224. taprootKey, err := tapscript.TaprootKey()
  225. require.NoError(ht, err)
  226. // Send some coins to the generated tapscript address.
  227. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  228. // Spend the output again, this time back to a p2wkh address.
  229. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  230. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  231. )
  232. // Create fee estimation for a p2tr input and p2wkh output.
  233. feeRate := chainfee.SatPerKWeight(12500)
  234. estimator := input.TxWeightEstimator{}
  235. estimator.AddTapscriptInput(
  236. input.TaprootSignatureWitnessSize, tapscript,
  237. )
  238. estimator.AddP2WKHOutput()
  239. estimatedWeight := int64(estimator.Weight())
  240. sigHash := txscript.SigHashDefault
  241. if len(sigHashType) != 0 {
  242. sigHash = sigHashType[0]
  243. // If a non-default sighash is used, then we'll need to add an
  244. // extra byte to account for the sighash that doesn't exist in
  245. // the default case.
  246. estimatedWeight++
  247. }
  248. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  249. tx := wire.NewMsgTx(2)
  250. tx.TxIn = []*wire.TxIn{{
  251. PreviousOutPoint: p2trOutpoint,
  252. }}
  253. value := int64(testAmount - requiredFee)
  254. tx.TxOut = []*wire.TxOut{{
  255. PkScript: p2wkhPkScript,
  256. Value: value,
  257. }}
  258. var buf bytes.Buffer
  259. require.NoError(ht, tx.Serialize(&buf))
  260. utxoInfo := []*signrpc.TxOut{{
  261. PkScript: p2trPkScript,
  262. Value: testAmount,
  263. }}
  264. // Before we actually sign, we want to make sure that we get an error
  265. // when we try to sign for a Taproot output without specifying all UTXO
  266. // information.
  267. signReq := &signrpc.SignReq{
  268. RawTxBytes: buf.Bytes(),
  269. SignDescs: []*signrpc.SignDescriptor{{
  270. Output: utxoInfo[0],
  271. InputIndex: 0,
  272. KeyDesc: keyDesc,
  273. Sighash: uint32(sigHash),
  274. WitnessScript: leaf2.Script,
  275. SignMethod: signMethodTapscript,
  276. }},
  277. }
  278. err = alice.RPC.SignOutputRawErr(signReq)
  279. require.Contains(
  280. ht, err.Error(), "error signing taproot output, transaction "+
  281. "input 0 is missing its previous outpoint information",
  282. )
  283. // We also want to make sure we get an error when we don't specify the
  284. // correct signing method.
  285. signReq = &signrpc.SignReq{
  286. RawTxBytes: buf.Bytes(),
  287. SignDescs: []*signrpc.SignDescriptor{{
  288. Output: utxoInfo[0],
  289. InputIndex: 0,
  290. KeyDesc: keyDesc,
  291. Sighash: uint32(sigHash),
  292. WitnessScript: leaf2.Script,
  293. }},
  294. PrevOutputs: utxoInfo,
  295. }
  296. err = alice.RPC.SignOutputRawErr(signReq)
  297. require.Contains(
  298. ht, err.Error(), "selected sign method witness_v0 is not "+
  299. "compatible with given pk script 5120",
  300. )
  301. // Do the actual signing now.
  302. signReq = &signrpc.SignReq{
  303. RawTxBytes: buf.Bytes(),
  304. SignDescs: []*signrpc.SignDescriptor{{
  305. Output: utxoInfo[0],
  306. InputIndex: 0,
  307. KeyDesc: keyDesc,
  308. Sighash: uint32(sigHash),
  309. WitnessScript: leaf2.Script,
  310. SignMethod: signMethodTapscript,
  311. }},
  312. PrevOutputs: utxoInfo,
  313. }
  314. signResp := alice.RPC.SignOutputRaw(signReq)
  315. // We can now assemble the witness stack.
  316. controlBlockBytes, err := tapscript.ControlBlock.ToBytes()
  317. require.NoError(ht, err)
  318. sig := signResp.RawSigs[0]
  319. if len(sigHashType) != 0 {
  320. sig = append(sig, byte(sigHashType[0]))
  321. }
  322. tx.TxIn[0].Witness = wire.TxWitness{
  323. sig, leaf2.Script, controlBlockBytes,
  324. }
  325. // Serialize, weigh and publish the TX now, then make sure the
  326. // coins are sent and confirmed to the final sweep destination address.
  327. publishTxAndConfirmSweep(
  328. ht, alice, tx, estimatedWeight,
  329. &chainrpc.SpendRequest{
  330. Outpoint: &chainrpc.Outpoint{
  331. Hash: p2trOutpoint.Hash[:],
  332. Index: p2trOutpoint.Index,
  333. },
  334. Script: p2trPkScript,
  335. },
  336. p2wkhAddr.String(),
  337. )
  338. }
  339. // testTaprootSignOutputRawKeySpendBip86 tests that a tapscript address can
  340. // also be spent using the key spend path through the SignOutputRaw RPC using a
  341. // BIP0086 key spend only commitment.
  342. func testTaprootSignOutputRawKeySpendBip86(ht *lntest.HarnessTest,
  343. alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
  344. // For the next step, we need a public key. Let's use a special family
  345. // for this.
  346. req := &walletrpc.KeyReq{KeyFamily: testTaprootKeyFamily}
  347. keyDesc := alice.RPC.DeriveNextKey(req)
  348. internalKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes)
  349. require.NoError(ht, err)
  350. // We want to make sure we can still use a tweaked key, even if it ends
  351. // up being essentially double tweaked because of the taproot root hash.
  352. dummyKeyTweak := sha256.Sum256([]byte("this is a key tweak"))
  353. internalKey = input.TweakPubKeyWithTweak(internalKey, dummyKeyTweak[:])
  354. // Our taproot key is a BIP0086 key spend only construction that just
  355. // commits to the internal key and no root hash.
  356. taprootKey := txscript.ComputeTaprootKeyNoScript(internalKey)
  357. // Send some coins to the generated tapscript address.
  358. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  359. // Spend the output again, this time back to a p2wkh address.
  360. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  361. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  362. )
  363. sigHash := txscript.SigHashDefault
  364. if len(sigHashType) != 0 {
  365. sigHash = sigHashType[0]
  366. }
  367. // Create fee estimation for a p2tr input and p2wkh output.
  368. feeRate := chainfee.SatPerKWeight(12500)
  369. estimator := input.TxWeightEstimator{}
  370. estimator.AddTaprootKeySpendInput(sigHash)
  371. estimator.AddP2WKHOutput()
  372. estimatedWeight := int64(estimator.Weight())
  373. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  374. tx := wire.NewMsgTx(2)
  375. tx.TxIn = []*wire.TxIn{{
  376. PreviousOutPoint: p2trOutpoint,
  377. }}
  378. value := int64(testAmount - requiredFee)
  379. tx.TxOut = []*wire.TxOut{{
  380. PkScript: p2wkhPkScript,
  381. Value: value,
  382. }}
  383. var buf bytes.Buffer
  384. require.NoError(ht, tx.Serialize(&buf))
  385. utxoInfo := []*signrpc.TxOut{{
  386. PkScript: p2trPkScript,
  387. Value: testAmount,
  388. }}
  389. signReq := &signrpc.SignReq{
  390. RawTxBytes: buf.Bytes(),
  391. SignDescs: []*signrpc.SignDescriptor{{
  392. Output: utxoInfo[0],
  393. InputIndex: 0,
  394. KeyDesc: keyDesc,
  395. SingleTweak: dummyKeyTweak[:],
  396. Sighash: uint32(sigHash),
  397. SignMethod: signMethodBip86,
  398. }},
  399. PrevOutputs: utxoInfo,
  400. }
  401. signResp := alice.RPC.SignOutputRaw(signReq)
  402. sig := signResp.RawSigs[0]
  403. if len(sigHashType) != 0 {
  404. sig = append(sig, byte(sigHash))
  405. }
  406. tx.TxIn[0].Witness = wire.TxWitness{sig}
  407. // Serialize, weigh and publish the TX now, then make sure the
  408. // coins are sent and confirmed to the final sweep destination address.
  409. publishTxAndConfirmSweep(
  410. ht, alice, tx, estimatedWeight,
  411. &chainrpc.SpendRequest{
  412. Outpoint: &chainrpc.Outpoint{
  413. Hash: p2trOutpoint.Hash[:],
  414. Index: p2trOutpoint.Index,
  415. },
  416. Script: p2trPkScript,
  417. },
  418. p2wkhAddr.String(),
  419. )
  420. }
  421. // testTaprootSignOutputRawKeySpendRootHash tests that a tapscript address can
  422. // also be spent using the key spend path through the SignOutputRaw RPC using a
  423. // tapscript root hash.
  424. func testTaprootSignOutputRawKeySpendRootHash(ht *lntest.HarnessTest,
  425. alice *node.HarnessNode) {
  426. // For the next step, we need a public key. Let's use a special family
  427. // for this.
  428. req := &walletrpc.KeyReq{KeyFamily: testTaprootKeyFamily}
  429. keyDesc := alice.RPC.DeriveNextKey(req)
  430. internalKey, err := btcec.ParsePubKey(keyDesc.RawKeyBytes)
  431. require.NoError(ht, err)
  432. // We want to make sure we can still use a tweaked key, even if it ends
  433. // up being essentially double tweaked because of the taproot root hash.
  434. dummyKeyTweak := sha256.Sum256([]byte("this is a key tweak"))
  435. internalKey = input.TweakPubKeyWithTweak(internalKey, dummyKeyTweak[:])
  436. // Let's create a taproot script output now. This is a hash lock with a
  437. // simple preimage of "foobar".
  438. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  439. rootHash := leaf1.TapHash()
  440. taprootKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:])
  441. // Send some coins to the generated tapscript address.
  442. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  443. // Spend the output again, this time back to a p2wkh address.
  444. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  445. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  446. )
  447. // Create fee estimation for a p2tr input and p2wkh output.
  448. feeRate := chainfee.SatPerKWeight(12500)
  449. estimator := input.TxWeightEstimator{}
  450. estimator.AddTaprootKeySpendInput(txscript.SigHashDefault)
  451. estimator.AddP2WKHOutput()
  452. estimatedWeight := int64(estimator.Weight())
  453. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  454. tx := wire.NewMsgTx(2)
  455. tx.TxIn = []*wire.TxIn{{
  456. PreviousOutPoint: p2trOutpoint,
  457. }}
  458. value := int64(testAmount - requiredFee)
  459. tx.TxOut = []*wire.TxOut{{
  460. PkScript: p2wkhPkScript,
  461. Value: value,
  462. }}
  463. var buf bytes.Buffer
  464. require.NoError(ht, tx.Serialize(&buf))
  465. utxoInfo := []*signrpc.TxOut{{
  466. PkScript: p2trPkScript,
  467. Value: testAmount,
  468. }}
  469. signReq := &signrpc.SignReq{
  470. RawTxBytes: buf.Bytes(),
  471. SignDescs: []*signrpc.SignDescriptor{{
  472. Output: utxoInfo[0],
  473. InputIndex: 0,
  474. KeyDesc: keyDesc,
  475. SingleTweak: dummyKeyTweak[:],
  476. Sighash: uint32(txscript.SigHashDefault),
  477. TapTweak: rootHash[:],
  478. SignMethod: signMethodRootHash,
  479. }},
  480. PrevOutputs: utxoInfo,
  481. }
  482. signResp := alice.RPC.SignOutputRaw(signReq)
  483. tx.TxIn[0].Witness = wire.TxWitness{
  484. signResp.RawSigs[0],
  485. }
  486. // Serialize, weigh and publish the TX now, then make sure the
  487. // coins are sent and confirmed to the final sweep destination address.
  488. publishTxAndConfirmSweep(
  489. ht, alice, tx, estimatedWeight,
  490. &chainrpc.SpendRequest{
  491. Outpoint: &chainrpc.Outpoint{
  492. Hash: p2trOutpoint.Hash[:],
  493. Index: p2trOutpoint.Index,
  494. },
  495. Script: p2trPkScript,
  496. },
  497. p2wkhAddr.String(),
  498. )
  499. }
  500. // testTaprootMuSig2KeySpendBip86 tests that a combined MuSig2 key can also be
  501. // used as a BIP-0086 key spend only key.
  502. func testTaprootMuSig2KeySpendBip86(ht *lntest.HarnessTest,
  503. alice *node.HarnessNode, version signrpc.MuSig2Version) {
  504. // We're not going to commit to a script. So our taproot tweak will be
  505. // empty and just specify the necessary flag.
  506. taprootTweak := &signrpc.TaprootTweakDesc{
  507. KeySpendOnly: true,
  508. }
  509. keyDesc1, keyDesc2, keyDesc3, allPubKeys := deriveSigningKeys(
  510. ht, alice, version,
  511. )
  512. _, taprootKey, sessResp1, sessResp2, sessResp3 := createMuSigSessions(
  513. ht, alice, taprootTweak, keyDesc1, keyDesc2, keyDesc3,
  514. allPubKeys, version,
  515. )
  516. // Send some coins to the generated tapscript address.
  517. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  518. // Spend the output again, this time back to a p2wkh address.
  519. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  520. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  521. )
  522. // Create fee estimation for a p2tr input and p2wkh output.
  523. feeRate := chainfee.SatPerKWeight(12500)
  524. estimator := input.TxWeightEstimator{}
  525. estimator.AddTaprootKeySpendInput(txscript.SigHashDefault)
  526. estimator.AddP2WKHOutput()
  527. estimatedWeight := int64(estimator.Weight())
  528. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  529. tx := wire.NewMsgTx(2)
  530. tx.TxIn = []*wire.TxIn{{
  531. PreviousOutPoint: p2trOutpoint,
  532. }}
  533. value := int64(testAmount - requiredFee)
  534. tx.TxOut = []*wire.TxOut{{
  535. PkScript: p2wkhPkScript,
  536. Value: value,
  537. }}
  538. var buf bytes.Buffer
  539. require.NoError(ht, tx.Serialize(&buf))
  540. utxoInfo := []*signrpc.TxOut{{
  541. PkScript: p2trPkScript,
  542. Value: testAmount,
  543. }}
  544. // We now need to create the raw sighash of the transaction, as that
  545. // will be the message we're signing collaboratively.
  546. prevOutputFetcher := txscript.NewCannedPrevOutputFetcher(
  547. utxoInfo[0].PkScript, utxoInfo[0].Value,
  548. )
  549. sighashes := txscript.NewTxSigHashes(tx, prevOutputFetcher)
  550. sigHash, err := txscript.CalcTaprootSignatureHash(
  551. sighashes, txscript.SigHashDefault, tx, 0, prevOutputFetcher,
  552. )
  553. require.NoError(ht, err)
  554. // Now that we have the transaction prepared, we need to start with the
  555. // signing. We simulate all three parties here, so we need to do
  556. // everything three times. But because we're going to use session 1 to
  557. // combine everything, we don't need its response, as it will store its
  558. // own signature.
  559. signReq := &signrpc.MuSig2SignRequest{
  560. SessionId: sessResp1.SessionId,
  561. MessageDigest: sigHash,
  562. }
  563. alice.RPC.MuSig2Sign(signReq)
  564. signReq = &signrpc.MuSig2SignRequest{
  565. SessionId: sessResp2.SessionId,
  566. MessageDigest: sigHash,
  567. Cleanup: true,
  568. }
  569. signResp2 := alice.RPC.MuSig2Sign(signReq)
  570. signReq = &signrpc.MuSig2SignRequest{
  571. SessionId: sessResp3.SessionId,
  572. MessageDigest: sigHash,
  573. Cleanup: true,
  574. }
  575. signResp3 := alice.RPC.MuSig2Sign(signReq)
  576. // Luckily only one of the signers needs to combine the signature, so
  577. // let's do that now.
  578. combineReq := &signrpc.MuSig2CombineSigRequest{
  579. SessionId: sessResp1.SessionId,
  580. OtherPartialSignatures: [][]byte{
  581. signResp2.LocalPartialSignature,
  582. signResp3.LocalPartialSignature,
  583. },
  584. }
  585. combineResp := alice.RPC.MuSig2CombineSig(combineReq)
  586. require.Equal(ht, true, combineResp.HaveAllSignatures)
  587. require.NotEmpty(ht, combineResp.FinalSignature)
  588. sig, err := schnorr.ParseSignature(combineResp.FinalSignature)
  589. require.NoError(ht, err)
  590. require.True(ht, sig.Verify(sigHash, taprootKey))
  591. tx.TxIn[0].Witness = wire.TxWitness{
  592. combineResp.FinalSignature,
  593. }
  594. // Serialize, weigh and publish the TX now, then make sure the
  595. // coins are sent and confirmed to the final sweep destination address.
  596. publishTxAndConfirmSweep(
  597. ht, alice, tx, estimatedWeight,
  598. &chainrpc.SpendRequest{
  599. Outpoint: &chainrpc.Outpoint{
  600. Hash: p2trOutpoint.Hash[:],
  601. Index: p2trOutpoint.Index,
  602. },
  603. Script: p2trPkScript,
  604. },
  605. p2wkhAddr.String(),
  606. )
  607. }
  608. // testTaprootMuSig2KeySpendRootHash tests that a tapscript address can also be
  609. // spent using a MuSig2 combined key.
  610. func testTaprootMuSig2KeySpendRootHash(ht *lntest.HarnessTest,
  611. alice *node.HarnessNode, version signrpc.MuSig2Version) {
  612. // We're going to commit to a script as well. This is a hash lock with a
  613. // simple preimage of "foobar". We need to know this upfront so, we can
  614. // specify the taproot tweak with the root hash when creating the Musig2
  615. // signing session.
  616. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  617. rootHash := leaf1.TapHash()
  618. taprootTweak := &signrpc.TaprootTweakDesc{
  619. ScriptRoot: rootHash[:],
  620. }
  621. keyDesc1, keyDesc2, keyDesc3, allPubKeys := deriveSigningKeys(
  622. ht, alice, version,
  623. )
  624. _, taprootKey, sessResp1, sessResp2, sessResp3 := createMuSigSessions(
  625. ht, alice, taprootTweak, keyDesc1, keyDesc2, keyDesc3,
  626. allPubKeys, version,
  627. )
  628. // Send some coins to the generated tapscript address.
  629. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  630. // Spend the output again, this time back to a p2wkh address.
  631. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  632. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  633. )
  634. // Create fee estimation for a p2tr input and p2wkh output.
  635. feeRate := chainfee.SatPerKWeight(12500)
  636. estimator := input.TxWeightEstimator{}
  637. estimator.AddTaprootKeySpendInput(txscript.SigHashDefault)
  638. estimator.AddP2WKHOutput()
  639. estimatedWeight := int64(estimator.Weight())
  640. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  641. tx := wire.NewMsgTx(2)
  642. tx.TxIn = []*wire.TxIn{{
  643. PreviousOutPoint: p2trOutpoint,
  644. }}
  645. value := int64(testAmount - requiredFee)
  646. tx.TxOut = []*wire.TxOut{{
  647. PkScript: p2wkhPkScript,
  648. Value: value,
  649. }}
  650. var buf bytes.Buffer
  651. require.NoError(ht, tx.Serialize(&buf))
  652. utxoInfo := []*signrpc.TxOut{{
  653. PkScript: p2trPkScript,
  654. Value: testAmount,
  655. }}
  656. // We now need to create the raw sighash of the transaction, as that
  657. // will be the message we're signing collaboratively.
  658. prevOutputFetcher := txscript.NewCannedPrevOutputFetcher(
  659. utxoInfo[0].PkScript, utxoInfo[0].Value,
  660. )
  661. sighashes := txscript.NewTxSigHashes(tx, prevOutputFetcher)
  662. sigHash, err := txscript.CalcTaprootSignatureHash(
  663. sighashes, txscript.SigHashDefault, tx, 0, prevOutputFetcher,
  664. )
  665. require.NoError(ht, err)
  666. // Now that we have the transaction prepared, we need to start with the
  667. // signing. We simulate all three parties here, so we need to do
  668. // everything three times. But because we're going to use session 1 to
  669. // combine everything, we don't need its response, as it will store its
  670. // own signature.
  671. req := &signrpc.MuSig2SignRequest{
  672. SessionId: sessResp1.SessionId,
  673. MessageDigest: sigHash,
  674. }
  675. alice.RPC.MuSig2Sign(req)
  676. req = &signrpc.MuSig2SignRequest{
  677. SessionId: sessResp2.SessionId,
  678. MessageDigest: sigHash,
  679. Cleanup: true,
  680. }
  681. signResp2 := alice.RPC.MuSig2Sign(req)
  682. req = &signrpc.MuSig2SignRequest{
  683. SessionId: sessResp3.SessionId,
  684. MessageDigest: sigHash,
  685. Cleanup: true,
  686. }
  687. signResp3 := alice.RPC.MuSig2Sign(req)
  688. // Luckily only one of the signers needs to combine the signature, so
  689. // let's do that now.
  690. combineReq := &signrpc.MuSig2CombineSigRequest{
  691. SessionId: sessResp1.SessionId,
  692. OtherPartialSignatures: [][]byte{
  693. signResp2.LocalPartialSignature,
  694. signResp3.LocalPartialSignature,
  695. },
  696. }
  697. combineResp := alice.RPC.MuSig2CombineSig(combineReq)
  698. require.Equal(ht, true, combineResp.HaveAllSignatures)
  699. require.NotEmpty(ht, combineResp.FinalSignature)
  700. sig, err := schnorr.ParseSignature(combineResp.FinalSignature)
  701. require.NoError(ht, err)
  702. require.True(ht, sig.Verify(sigHash, taprootKey))
  703. tx.TxIn[0].Witness = wire.TxWitness{
  704. combineResp.FinalSignature,
  705. }
  706. // Serialize, weigh and publish the TX now, then make sure the
  707. // coins are sent and confirmed to the final sweep destination address.
  708. publishTxAndConfirmSweep(
  709. ht, alice, tx, estimatedWeight,
  710. &chainrpc.SpendRequest{
  711. Outpoint: &chainrpc.Outpoint{
  712. Hash: p2trOutpoint.Hash[:],
  713. Index: p2trOutpoint.Index,
  714. },
  715. Script: p2trPkScript,
  716. },
  717. p2wkhAddr.String(),
  718. )
  719. }
  720. // testTaprootMuSig2ScriptSpend tests that a tapscript address with an internal
  721. // key that is a MuSig2 combined key can also be spent using the script path.
  722. func testTaprootMuSig2ScriptSpend(ht *lntest.HarnessTest,
  723. alice *node.HarnessNode, version signrpc.MuSig2Version) {
  724. // We're going to commit to a script and spend the output using the
  725. // script. This is a hash lock with a simple preimage of "foobar". We
  726. // need to know this upfront so, we can specify the taproot tweak with
  727. // the root hash when creating the Musig2 signing session.
  728. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  729. rootHash := leaf1.TapHash()
  730. taprootTweak := &signrpc.TaprootTweakDesc{
  731. ScriptRoot: rootHash[:],
  732. }
  733. keyDesc1, keyDesc2, keyDesc3, allPubKeys := deriveSigningKeys(
  734. ht, alice, version,
  735. )
  736. internalKey, taprootKey, _, _, _ := createMuSigSessions(
  737. ht, alice, taprootTweak, keyDesc1, keyDesc2, keyDesc3,
  738. allPubKeys, version,
  739. )
  740. // Because we know the internal key and the script we want to spend, we
  741. // can now create the tapscript struct that's used for assembling the
  742. // control block and fee estimation.
  743. tapscript := input.TapscriptFullTree(internalKey, leaf1)
  744. // Send some coins to the generated tapscript address.
  745. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  746. // Spend the output again, this time back to a p2wkh address.
  747. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  748. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  749. )
  750. // Create fee estimation for a p2tr input and p2wkh output.
  751. feeRate := chainfee.SatPerKWeight(12500)
  752. estimator := input.TxWeightEstimator{}
  753. estimator.AddTapscriptInput(
  754. len([]byte("foobar"))+len(leaf1.Script)+1, tapscript,
  755. )
  756. estimator.AddP2WKHOutput()
  757. estimatedWeight := int64(estimator.Weight())
  758. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  759. tx := wire.NewMsgTx(2)
  760. tx.TxIn = []*wire.TxIn{{
  761. PreviousOutPoint: p2trOutpoint,
  762. }}
  763. value := int64(testAmount - requiredFee)
  764. tx.TxOut = []*wire.TxOut{{
  765. PkScript: p2wkhPkScript,
  766. Value: value,
  767. }}
  768. // We can now assemble the witness stack.
  769. controlBlockBytes, err := tapscript.ControlBlock.ToBytes()
  770. require.NoError(ht, err)
  771. tx.TxIn[0].Witness = wire.TxWitness{
  772. []byte("foobar"),
  773. leaf1.Script,
  774. controlBlockBytes,
  775. }
  776. // Serialize, weigh and publish the TX now, then make sure the
  777. // coins are sent and confirmed to the final sweep destination address.
  778. publishTxAndConfirmSweep(
  779. ht, alice, tx, estimatedWeight,
  780. &chainrpc.SpendRequest{
  781. Outpoint: &chainrpc.Outpoint{
  782. Hash: p2trOutpoint.Hash[:],
  783. Index: p2trOutpoint.Index,
  784. },
  785. Script: p2trPkScript,
  786. },
  787. p2wkhAddr.String(),
  788. )
  789. }
  790. // testTaprootMuSig2CombinedLeafKeySpend tests that a MuSig2 combined key can be
  791. // used for an OP_CHECKSIG inside a tap script leaf spend.
  792. func testTaprootMuSig2CombinedLeafKeySpend(ht *lntest.HarnessTest,
  793. alice *node.HarnessNode, version signrpc.MuSig2Version) {
  794. // We're using the combined MuSig2 key in a script leaf. So we need to
  795. // derive the combined key first, before we can build the script.
  796. keyDesc1, keyDesc2, keyDesc3, allPubKeys := deriveSigningKeys(
  797. ht, alice, version,
  798. )
  799. req := &signrpc.MuSig2CombineKeysRequest{
  800. AllSignerPubkeys: allPubKeys,
  801. Version: version,
  802. }
  803. combineResp := alice.RPC.MuSig2CombineKeys(req)
  804. combinedPubKey, err := schnorr.ParsePubKey(combineResp.CombinedKey)
  805. require.NoError(ht, err)
  806. // We're going to commit to a script and spend the output using the
  807. // script. This is just an OP_CHECKSIG with the combined MuSig2 public
  808. // key.
  809. leaf := testScriptSchnorrSig(ht.T, combinedPubKey)
  810. tapscript := input.TapscriptPartialReveal(dummyInternalKey, leaf, nil)
  811. taprootKey, err := tapscript.TaprootKey()
  812. require.NoError(ht, err)
  813. // Send some coins to the generated tapscript address.
  814. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  815. // Spend the output again, this time back to a p2wkh address.
  816. p2wkhAddr, p2wkhPkScript := newAddrWithScript(
  817. ht, alice, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  818. )
  819. // Create fee estimation for a p2tr input and p2wkh output.
  820. feeRate := chainfee.SatPerKWeight(12500)
  821. estimator := input.TxWeightEstimator{}
  822. estimator.AddTapscriptInput(
  823. input.TaprootSignatureWitnessSize, tapscript,
  824. )
  825. estimator.AddP2WKHOutput()
  826. estimatedWeight := int64(estimator.Weight())
  827. requiredFee := feeRate.FeeForWeight(estimatedWeight)
  828. tx := wire.NewMsgTx(2)
  829. tx.TxIn = []*wire.TxIn{{
  830. PreviousOutPoint: p2trOutpoint,
  831. }}
  832. value := int64(testAmount - requiredFee)
  833. tx.TxOut = []*wire.TxOut{{
  834. PkScript: p2wkhPkScript,
  835. Value: value,
  836. }}
  837. var buf bytes.Buffer
  838. require.NoError(ht, tx.Serialize(&buf))
  839. utxoInfo := []*signrpc.TxOut{{
  840. PkScript: p2trPkScript,
  841. Value: testAmount,
  842. }}
  843. // Do the actual signing now.
  844. _, _, sessResp1, sessResp2, sessResp3 := createMuSigSessions(
  845. ht, alice, nil, keyDesc1, keyDesc2, keyDesc3, allPubKeys,
  846. version,
  847. )
  848. require.NoError(ht, err)
  849. // We now need to create the raw sighash of the transaction, as that
  850. // will be the message we're signing collaboratively.
  851. prevOutputFetcher := txscript.NewCannedPrevOutputFetcher(
  852. utxoInfo[0].PkScript, utxoInfo[0].Value,
  853. )
  854. sighashes := txscript.NewTxSigHashes(tx, prevOutputFetcher)
  855. sigHash, err := txscript.CalcTapscriptSignaturehash(
  856. sighashes, txscript.SigHashDefault, tx, 0, prevOutputFetcher,
  857. leaf,
  858. )
  859. require.NoError(ht, err)
  860. // Now that we have the transaction prepared, we need to start with the
  861. // signing. We simulate all three parties here, so we need to do
  862. // everything three times. But because we're going to use session 1 to
  863. // combine everything, we don't need its response, as it will store its
  864. // own signature.
  865. signReq := &signrpc.MuSig2SignRequest{
  866. SessionId: sessResp1.SessionId,
  867. MessageDigest: sigHash,
  868. }
  869. alice.RPC.MuSig2Sign(signReq)
  870. signReq = &signrpc.MuSig2SignRequest{
  871. SessionId: sessResp2.SessionId,
  872. MessageDigest: sigHash,
  873. Cleanup: true,
  874. }
  875. signResp2 := alice.RPC.MuSig2Sign(signReq)
  876. // Before we have all partial signatures, we shouldn't get a final
  877. // signature back.
  878. combineReq := &signrpc.MuSig2CombineSigRequest{
  879. SessionId: sessResp1.SessionId,
  880. OtherPartialSignatures: [][]byte{
  881. signResp2.LocalPartialSignature,
  882. },
  883. }
  884. combineSigResp := alice.RPC.MuSig2CombineSig(combineReq)
  885. require.False(ht, combineSigResp.HaveAllSignatures)
  886. require.Empty(ht, combineSigResp.FinalSignature)
  887. signReq = &signrpc.MuSig2SignRequest{
  888. SessionId: sessResp3.SessionId,
  889. MessageDigest: sigHash,
  890. }
  891. signResp3 := alice.RPC.MuSig2Sign(signReq)
  892. // We manually clean up session 3, just to make sure that works as well.
  893. cleanReq := &signrpc.MuSig2CleanupRequest{
  894. SessionId: sessResp3.SessionId,
  895. }
  896. alice.RPC.MuSig2Cleanup(cleanReq)
  897. // A second call to that cleaned up session should now fail with a
  898. // specific error.
  899. signReq = &signrpc.MuSig2SignRequest{
  900. SessionId: sessResp3.SessionId,
  901. MessageDigest: sigHash,
  902. }
  903. err = alice.RPC.MuSig2SignErr(signReq)
  904. require.Contains(ht, err.Error(), "not found")
  905. // Luckily only one of the signers needs to combine the signature, so
  906. // let's do that now.
  907. combineReq = &signrpc.MuSig2CombineSigRequest{
  908. SessionId: sessResp1.SessionId,
  909. OtherPartialSignatures: [][]byte{
  910. signResp3.LocalPartialSignature,
  911. },
  912. }
  913. combineResp1 := alice.RPC.MuSig2CombineSig(combineReq)
  914. require.Equal(ht, true, combineResp1.HaveAllSignatures)
  915. require.NotEmpty(ht, combineResp1.FinalSignature)
  916. sig, err := schnorr.ParseSignature(combineResp1.FinalSignature)
  917. require.NoError(ht, err)
  918. require.True(ht, sig.Verify(sigHash, combinedPubKey))
  919. // We can now assemble the witness stack.
  920. controlBlockBytes, err := tapscript.ControlBlock.ToBytes()
  921. require.NoError(ht, err)
  922. tx.TxIn[0].Witness = wire.TxWitness{
  923. combineResp1.FinalSignature,
  924. leaf.Script,
  925. controlBlockBytes,
  926. }
  927. // Serialize, weigh and publish the TX now, then make sure the
  928. // coins are sent and confirmed to the final sweep destination address.
  929. publishTxAndConfirmSweep(
  930. ht, alice, tx, estimatedWeight,
  931. &chainrpc.SpendRequest{
  932. Outpoint: &chainrpc.Outpoint{
  933. Hash: p2trOutpoint.Hash[:],
  934. Index: p2trOutpoint.Index,
  935. },
  936. Script: p2trPkScript,
  937. },
  938. p2wkhAddr.String(),
  939. )
  940. }
  941. // testTaprootImportTapscriptScriptSpend tests importing p2tr script addresses
  942. // using the script path with the full tree known.
  943. func testTaprootImportTapscriptFullTree(ht *lntest.HarnessTest,
  944. alice *node.HarnessNode) {
  945. // For the next step, we need a public key. Let's use a special family
  946. // for this.
  947. _, internalKey, derivationPath := deriveInternalKey(ht, alice)
  948. // Let's create a taproot script output now. This is a hash lock with a
  949. // simple preimage of "foobar".
  950. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  951. // Let's add a second script output as well to test the partial reveal.
  952. leaf2 := testScriptSchnorrSig(ht.T, internalKey)
  953. tapscript := input.TapscriptFullTree(internalKey, leaf1, leaf2)
  954. tree := txscript.AssembleTaprootScriptTree(leaf1, leaf2)
  955. rootHash := tree.RootNode.TapHash()
  956. taprootKey, err := tapscript.TaprootKey()
  957. require.NoError(ht, err)
  958. // Import the scripts and make sure we get the same address back as we
  959. // calculated ourselves.
  960. req := &walletrpc.ImportTapscriptRequest{
  961. InternalPublicKey: schnorr.SerializePubKey(internalKey),
  962. Script: &walletrpc.ImportTapscriptRequest_FullTree{
  963. FullTree: &walletrpc.TapscriptFullTree{
  964. AllLeaves: []*walletrpc.TapLeaf{{
  965. LeafVersion: uint32(
  966. leaf1.LeafVersion,
  967. ),
  968. Script: leaf1.Script,
  969. }, {
  970. LeafVersion: uint32(
  971. leaf2.LeafVersion,
  972. ),
  973. Script: leaf2.Script,
  974. }},
  975. },
  976. },
  977. }
  978. importResp := alice.RPC.ImportTapscript(req)
  979. calculatedAddr, err := btcutil.NewAddressTaproot(
  980. schnorr.SerializePubKey(taprootKey), harnessNetParams,
  981. )
  982. require.NoError(ht, err)
  983. require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
  984. // Send some coins to the generated tapscript address.
  985. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  986. p2trOutputRPC := &lnrpc.OutPoint{
  987. TxidBytes: p2trOutpoint.Hash[:],
  988. OutputIndex: p2trOutpoint.Index,
  989. }
  990. ht.AssertUTXOInWallet(alice, p2trOutputRPC, "imported")
  991. ht.AssertWalletAccountBalance(alice, "imported", testAmount, 0)
  992. // Funding a PSBT from an imported script is not yet possible. So we
  993. // basically need to add all information manually for the wallet to be
  994. // able to sign for it.
  995. utxo := &wire.TxOut{
  996. Value: testAmount,
  997. PkScript: p2trPkScript,
  998. }
  999. clearWalletImportedTapscriptBalance(
  1000. ht, alice, utxo, p2trOutpoint, internalKey, derivationPath,
  1001. rootHash[:],
  1002. )
  1003. }
  1004. // testTaprootImportTapscriptPartialReveal tests importing p2tr script addresses
  1005. // for which we only know part of the tree.
  1006. func testTaprootImportTapscriptPartialReveal(ht *lntest.HarnessTest,
  1007. alice *node.HarnessNode) {
  1008. // For the next step, we need a public key. Let's use a special family
  1009. // for this.
  1010. _, internalKey, derivationPath := deriveInternalKey(ht, alice)
  1011. // Let's create a taproot script output now. This is a hash lock with a
  1012. // simple preimage of "foobar".
  1013. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  1014. // Let's add a second script output as well to test the partial reveal.
  1015. leaf2 := testScriptSchnorrSig(ht.T, internalKey)
  1016. leaf2Hash := leaf2.TapHash()
  1017. tapscript := input.TapscriptPartialReveal(
  1018. internalKey, leaf1, leaf2Hash[:],
  1019. )
  1020. rootHash := tapscript.ControlBlock.RootHash(leaf1.Script)
  1021. taprootKey, err := tapscript.TaprootKey()
  1022. require.NoError(ht, err)
  1023. // Import the scripts and make sure we get the same address back as we
  1024. // calculated ourselves.
  1025. req := &walletrpc.ImportTapscriptRequest{
  1026. InternalPublicKey: schnorr.SerializePubKey(internalKey),
  1027. Script: &walletrpc.ImportTapscriptRequest_PartialReveal{
  1028. PartialReveal: &walletrpc.TapscriptPartialReveal{
  1029. RevealedLeaf: &walletrpc.TapLeaf{
  1030. LeafVersion: uint32(leaf1.LeafVersion),
  1031. Script: leaf1.Script,
  1032. },
  1033. FullInclusionProof: leaf2Hash[:],
  1034. },
  1035. },
  1036. }
  1037. importResp := alice.RPC.ImportTapscript(req)
  1038. calculatedAddr, err := btcutil.NewAddressTaproot(
  1039. schnorr.SerializePubKey(taprootKey), harnessNetParams,
  1040. )
  1041. require.NoError(ht, err)
  1042. require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
  1043. // Send some coins to the generated tapscript address.
  1044. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  1045. p2trOutputRPC := &lnrpc.OutPoint{
  1046. TxidBytes: p2trOutpoint.Hash[:],
  1047. OutputIndex: p2trOutpoint.Index,
  1048. }
  1049. ht.AssertUTXOInWallet(alice, p2trOutputRPC, "imported")
  1050. ht.AssertWalletAccountBalance(alice, "imported", testAmount, 0)
  1051. // Funding a PSBT from an imported script is not yet possible. So we
  1052. // basically need to add all information manually for the wallet to be
  1053. // able to sign for it.
  1054. utxo := &wire.TxOut{
  1055. Value: testAmount,
  1056. PkScript: p2trPkScript,
  1057. }
  1058. clearWalletImportedTapscriptBalance(
  1059. ht, alice, utxo, p2trOutpoint, internalKey, derivationPath,
  1060. rootHash,
  1061. )
  1062. }
  1063. // testTaprootImportTapscriptRootHashOnly tests importing p2tr script addresses
  1064. // for which we only know the root hash.
  1065. func testTaprootImportTapscriptRootHashOnly(ht *lntest.HarnessTest,
  1066. alice *node.HarnessNode) {
  1067. // For the next step, we need a public key. Let's use a special family
  1068. // for this.
  1069. _, internalKey, derivationPath := deriveInternalKey(ht, alice)
  1070. // Let's create a taproot script output now. This is a hash lock with a
  1071. // simple preimage of "foobar".
  1072. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  1073. rootHash := leaf1.TapHash()
  1074. tapscript := input.TapscriptRootHashOnly(internalKey, rootHash[:])
  1075. taprootKey, err := tapscript.TaprootKey()
  1076. require.NoError(ht, err)
  1077. // Import the scripts and make sure we get the same address back as we
  1078. // calculated ourselves.
  1079. req := &walletrpc.ImportTapscriptRequest{
  1080. InternalPublicKey: schnorr.SerializePubKey(internalKey),
  1081. Script: &walletrpc.ImportTapscriptRequest_RootHashOnly{
  1082. RootHashOnly: rootHash[:],
  1083. },
  1084. }
  1085. importResp := alice.RPC.ImportTapscript(req)
  1086. calculatedAddr, err := btcutil.NewAddressTaproot(
  1087. schnorr.SerializePubKey(taprootKey), harnessNetParams,
  1088. )
  1089. require.NoError(ht, err)
  1090. require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
  1091. // Send some coins to the generated tapscript address.
  1092. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  1093. p2trOutputRPC := &lnrpc.OutPoint{
  1094. TxidBytes: p2trOutpoint.Hash[:],
  1095. OutputIndex: p2trOutpoint.Index,
  1096. }
  1097. ht.AssertUTXOInWallet(alice, p2trOutputRPC, "imported")
  1098. ht.AssertWalletAccountBalance(alice, "imported", testAmount, 0)
  1099. // Funding a PSBT from an imported script is not yet possible. So we
  1100. // basically need to add all information manually for the wallet to be
  1101. // able to sign for it.
  1102. utxo := &wire.TxOut{
  1103. Value: testAmount,
  1104. PkScript: p2trPkScript,
  1105. }
  1106. clearWalletImportedTapscriptBalance(
  1107. ht, alice, utxo, p2trOutpoint, internalKey, derivationPath,
  1108. rootHash[:],
  1109. )
  1110. }
  1111. // testTaprootImportTapscriptFullKey tests importing p2tr script addresses for
  1112. // which we only know the full Taproot key.
  1113. func testTaprootImportTapscriptFullKey(ht *lntest.HarnessTest,
  1114. alice *node.HarnessNode) {
  1115. // For the next step, we need a public key. Let's use a special family
  1116. // for this.
  1117. _, internalKey, derivationPath := deriveInternalKey(ht, alice)
  1118. // Let's create a taproot script output now. This is a hash lock with a
  1119. // simple preimage of "foobar".
  1120. leaf1 := testScriptHashLock(ht.T, []byte("foobar"))
  1121. tapscript := input.TapscriptFullTree(internalKey, leaf1)
  1122. rootHash := leaf1.TapHash()
  1123. taprootKey, err := tapscript.TaprootKey()
  1124. require.NoError(ht, err)
  1125. // Import the scripts and make sure we get the same address back as we
  1126. // calculated ourselves.
  1127. req := &walletrpc.ImportTapscriptRequest{
  1128. InternalPublicKey: schnorr.SerializePubKey(taprootKey),
  1129. Script: &walletrpc.ImportTapscriptRequest_FullKeyOnly{
  1130. FullKeyOnly: true,
  1131. },
  1132. }
  1133. importResp := alice.RPC.ImportTapscript(req)
  1134. calculatedAddr, err := btcutil.NewAddressTaproot(
  1135. schnorr.SerializePubKey(taprootKey), harnessNetParams,
  1136. )
  1137. require.NoError(ht, err)
  1138. require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
  1139. // Send some coins to the generated tapscript address.
  1140. p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
  1141. p2trOutputRPC := &lnrpc.OutPoint{
  1142. TxidBytes: p2trOutpoint.Hash[:],
  1143. OutputIndex: p2trOutpoint.Index,
  1144. }
  1145. ht.AssertUTXOInWallet(alice, p2trOutputRPC, "imported")
  1146. ht.AssertWalletAccountBalance(alice, "imported", testAmount, 0)
  1147. // Funding a PSBT from an imported script is not yet possible. So we
  1148. // basically need to add all information manually for the wallet to be
  1149. // able to sign for it.
  1150. utxo := &wire.TxOut{
  1151. Value: testAmount,
  1152. PkScript: p2trPkScript,
  1153. }
  1154. clearWalletImportedTapscriptBalance(
  1155. ht, alice, utxo, p2trOutpoint, internalKey, derivationPath,
  1156. rootHash[:],
  1157. )
  1158. }
  1159. // clearWalletImportedTapscriptBalance manually assembles and then attempts to
  1160. // sign a TX to sweep funds from an imported tapscript address.
  1161. func clearWalletImportedTapscriptBalance(ht *lntest.HarnessTest,
  1162. hn *node.HarnessNode, utxo *wire.TxOut, outPoint wire.OutPoint,
  1163. internalKey *btcec.PublicKey, derivationPath []uint32,
  1164. rootHash []byte) {
  1165. _, sweepPkScript := newAddrWithScript(
  1166. ht, hn, lnrpc.AddressType_WITNESS_PUBKEY_HASH,
  1167. )
  1168. output := &wire.TxOut{
  1169. PkScript: sweepPkScript,
  1170. Value: utxo.Value - 1000,
  1171. }
  1172. packet, err := psbt.New(
  1173. []*wire.OutPoint{&outPoint}, []*wire.TxOut{output}, 2, 0,
  1174. []uint32{0},
  1175. )
  1176. require.NoError(ht, err)
  1177. // We have everything we need to know to sign the PSBT.
  1178. in := &packet.Inputs[0]
  1179. in.Bip32Derivation = []*psbt.Bip32Derivation{{
  1180. PubKey: internalKey.SerializeCompressed(),
  1181. Bip32Path: derivationPath,
  1182. }}
  1183. in.TaprootBip32Derivation = []*psbt.TaprootBip32Derivation{{
  1184. XOnlyPubKey: schnorr.SerializePubKey(internalKey),
  1185. Bip32Path: derivationPath,
  1186. }}
  1187. in.SighashType = txscript.SigHashDefault
  1188. in.TaprootMerkleRoot = rootHash
  1189. in.WitnessUtxo = utxo
  1190. var buf bytes.Buffer
  1191. require.NoError(ht, packet.Serialize(&buf))
  1192. // Sign the manually funded PSBT now.
  1193. signResp := hn.RPC.SignPsbt(&walletrpc.SignPsbtRequest{
  1194. FundedPsbt: buf.Bytes(),
  1195. })
  1196. signedPacket, err := psbt.NewFromRawBytes(
  1197. bytes.NewReader(signResp.SignedPsbt), false,
  1198. )
  1199. require.NoError(ht, err)
  1200. // We should be able to finalize the PSBT and extract the sweep TX now.
  1201. err = psbt.MaybeFinalizeAll(signedPacket)
  1202. require.NoError(ht, err)
  1203. sweepTx, err := psbt.Extract(signedPacket)
  1204. require.NoError(ht, err)
  1205. buf.Reset()
  1206. err = sweepTx.Serialize(&buf)
  1207. require.NoError(ht, err)
  1208. // Publish the sweep transaction and then mine it as well.
  1209. hn.RPC.PublishTransaction(&walletrpc.Transaction{
  1210. TxHex: buf.Bytes(),
  1211. })
  1212. // Mine one block which should contain the sweep transaction.
  1213. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0]
  1214. sweepTxHash := sweepTx.TxHash()
  1215. ht.Miner.AssertTxInBlock(block, &sweepTxHash)
  1216. }
  1217. // testScriptHashLock returns a simple bitcoin script that locks the funds to
  1218. // a hash lock of the given preimage.
  1219. func testScriptHashLock(t *testing.T, preimage []byte) txscript.TapLeaf {
  1220. builder := txscript.NewScriptBuilder()
  1221. builder.AddOp(txscript.OP_DUP)
  1222. builder.AddOp(txscript.OP_HASH160)
  1223. builder.AddData(btcutil.Hash160(preimage))
  1224. builder.AddOp(txscript.OP_EQUALVERIFY)
  1225. script1, err := builder.Script()
  1226. require.NoError(t, err)
  1227. return txscript.NewBaseTapLeaf(script1)
  1228. }
  1229. // testScriptSchnorrSig returns a simple bitcoin script that locks the funds to
  1230. // a Schnorr signature of the given public key.
  1231. func testScriptSchnorrSig(t *testing.T,
  1232. pubKey *btcec.PublicKey) txscript.TapLeaf {
  1233. builder := txscript.NewScriptBuilder()
  1234. builder.AddData(schnorr.SerializePubKey(pubKey))
  1235. builder.AddOp(txscript.OP_CHECKSIG)
  1236. script2, err := builder.Script()
  1237. require.NoError(t, err)
  1238. return txscript.NewBaseTapLeaf(script2)
  1239. }
  1240. // newAddrWithScript returns a new address and its pkScript.
  1241. func newAddrWithScript(ht *lntest.HarnessTest, node *node.HarnessNode,
  1242. addrType lnrpc.AddressType) (btcutil.Address, []byte) {
  1243. p2wkhResp := node.RPC.NewAddress(&lnrpc.NewAddressRequest{
  1244. Type: addrType,
  1245. })
  1246. p2wkhAddr, err := btcutil.DecodeAddress(
  1247. p2wkhResp.Address, harnessNetParams,
  1248. )
  1249. require.NoError(ht, err)
  1250. p2wkhPkScript, err := txscript.PayToAddrScript(p2wkhAddr)
  1251. require.NoError(ht, err)
  1252. return p2wkhAddr, p2wkhPkScript
  1253. }
  1254. // sendToTaprootOutput sends coins to a p2tr output of the given taproot key and
  1255. // mines a block to confirm the coins.
  1256. func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode,
  1257. taprootKey *btcec.PublicKey) (wire.OutPoint, []byte) {
  1258. tapScriptAddr, err := btcutil.NewAddressTaproot(
  1259. schnorr.SerializePubKey(taprootKey), harnessNetParams,
  1260. )
  1261. require.NoError(ht, err)
  1262. p2trPkScript, err := txscript.PayToAddrScript(tapScriptAddr)
  1263. require.NoError(ht, err)
  1264. // Send some coins to the generated tapscript address.
  1265. req := &lnrpc.SendCoinsRequest{
  1266. Addr: tapScriptAddr.String(),
  1267. Amount: testAmount,
  1268. TargetConf: 6,
  1269. }
  1270. hn.RPC.SendCoins(req)
  1271. // Wait until the TX is found in the mempool.
  1272. txid := ht.Miner.AssertNumTxsInMempool(1)[0]
  1273. p2trOutputIndex := ht.GetOutputIndex(txid, tapScriptAddr.String())
  1274. p2trOutpoint := wire.OutPoint{
  1275. Hash: *txid,
  1276. Index: uint32(p2trOutputIndex),
  1277. }
  1278. // Make sure the transaction is recognized by our wallet and has the
  1279. // correct output type.
  1280. var outputDetail *lnrpc.OutputDetail
  1281. walletTxns := hn.RPC.GetTransactions(&lnrpc.GetTransactionsRequest{
  1282. StartHeight: 0,
  1283. EndHeight: -1,
  1284. })
  1285. require.NotEmpty(ht, walletTxns.Transactions)
  1286. for _, tx := range walletTxns.Transactions {
  1287. if tx.TxHash != txid.String() {
  1288. continue
  1289. }
  1290. for outputIdx, out := range tx.OutputDetails {
  1291. if out.Address != tapScriptAddr.String() {
  1292. continue
  1293. }
  1294. outputDetail = tx.OutputDetails[outputIdx]
  1295. break
  1296. }
  1297. }
  1298. require.NotNil(ht, outputDetail, "transaction not found in wallet")
  1299. require.Equal(
  1300. ht, lnrpc.OutputScriptType_SCRIPT_TYPE_WITNESS_V1_TAPROOT,
  1301. outputDetail.OutputType,
  1302. )
  1303. // Clear the mempool.
  1304. ht.MineBlocksAndAssertNumTxes(1, 1)
  1305. return p2trOutpoint, p2trPkScript
  1306. }
  1307. // publishTxAndConfirmSweep is a helper function that publishes a transaction
  1308. // after checking its weight against an estimate. After asserting the given
  1309. // spend request, the given sweep address' balance is verified to be seen as
  1310. // funds belonging to the wallet.
  1311. func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode,
  1312. tx *wire.MsgTx, estimatedWeight int64,
  1313. spendRequest *chainrpc.SpendRequest, sweepAddr string) {
  1314. ht.Helper()
  1315. // Before we publish the tx that spends the p2tr transaction, we want to
  1316. // register a spend listener that we expect to fire after mining the
  1317. // block.
  1318. _, currentHeight := ht.Miner.GetBestBlock()
  1319. // For a Taproot output we cannot leave the outpoint empty. Let's make
  1320. // sure the API returns the correct error here.
  1321. req := &chainrpc.SpendRequest{
  1322. Script: spendRequest.Script,
  1323. HeightHint: uint32(currentHeight),
  1324. }
  1325. spendClient := node.RPC.RegisterSpendNtfn(req)
  1326. // The error is only thrown when trying to read a message.
  1327. _, err := spendClient.Recv()
  1328. require.Contains(
  1329. ht, err.Error(),
  1330. "cannot register witness v1 spend request without outpoint",
  1331. )
  1332. // Now try again, this time with the outpoint set.
  1333. req = &chainrpc.SpendRequest{
  1334. Outpoint: spendRequest.Outpoint,
  1335. Script: spendRequest.Script,
  1336. HeightHint: uint32(currentHeight),
  1337. }
  1338. spendClient = node.RPC.RegisterSpendNtfn(req)
  1339. var buf bytes.Buffer
  1340. require.NoError(ht, tx.Serialize(&buf))
  1341. // Since Schnorr signatures are fixed size, we must be able to estimate
  1342. // the size of this transaction exactly.
  1343. txWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx))
  1344. require.Equal(ht, estimatedWeight, txWeight)
  1345. txReq := &walletrpc.Transaction{
  1346. TxHex: buf.Bytes(),
  1347. }
  1348. node.RPC.PublishTransaction(txReq)
  1349. // Make sure the coins sent to the address are confirmed correctly,
  1350. // including the confirmation notification.
  1351. confirmAddress(ht, node, sweepAddr)
  1352. // We now expect our spend event to go through.
  1353. spendMsg, err := spendClient.Recv()
  1354. require.NoError(ht, err)
  1355. spend := spendMsg.GetSpend()
  1356. require.NotNil(ht, spend)
  1357. require.Equal(ht, spend.SpendingHeight, uint32(currentHeight+1))
  1358. }
  1359. // confirmAddress makes sure that a transaction in the mempool spends funds to
  1360. // the given address. It also checks that a confirmation notification for the
  1361. // address is triggered when the transaction is mined.
  1362. func confirmAddress(ht *lntest.HarnessTest, hn *node.HarnessNode,
  1363. addrString string) {
  1364. // Wait until the tx that sends to the address is found.
  1365. txid := ht.Miner.AssertNumTxsInMempool(1)[0]
  1366. // Wait until bob has seen the tx and considers it as owned.
  1367. addrOutputIndex := ht.GetOutputIndex(txid, addrString)
  1368. op := &lnrpc.OutPoint{
  1369. TxidBytes: txid[:],
  1370. OutputIndex: uint32(addrOutputIndex),
  1371. }
  1372. ht.AssertUTXOInWallet(hn, op, "")
  1373. // Before we confirm the transaction, let's register a confirmation
  1374. // listener for it, which we expect to fire after mining a block.
  1375. parsedAddr, err := btcutil.DecodeAddress(addrString, harnessNetParams)
  1376. require.NoError(ht, err)
  1377. addrPkScript, err := txscript.PayToAddrScript(parsedAddr)
  1378. require.NoError(ht, err)
  1379. _, currentHeight := ht.Miner.GetBestBlock()
  1380. req := &chainrpc.ConfRequest{
  1381. Script: addrPkScript,
  1382. Txid: txid[:],
  1383. HeightHint: uint32(currentHeight),
  1384. NumConfs: 1,
  1385. IncludeBlock: true,
  1386. }
  1387. confClient := hn.RPC.RegisterConfirmationsNtfn(req)
  1388. // Mine another block to clean up the mempool.
  1389. ht.MineBlocksAndAssertNumTxes(1, 1)
  1390. // We now expect our confirmation to go through, and also that the
  1391. // block was specified.
  1392. confMsg, err := confClient.Recv()
  1393. require.NoError(ht, err)
  1394. conf := confMsg.GetConf()
  1395. require.NotNil(ht, conf)
  1396. require.Equal(ht, conf.BlockHeight, uint32(currentHeight+1))
  1397. require.NotNil(ht, conf.RawBlock)
  1398. // We should also be able to decode the raw block.
  1399. var blk wire.MsgBlock
  1400. require.NoError(ht, blk.Deserialize(bytes.NewReader(conf.RawBlock)))
  1401. }
  1402. // deriveSigningKeys derives three signing keys and returns their descriptors,
  1403. // as well as the public keys in the Schnorr serialized format.
  1404. func deriveSigningKeys(ht *lntest.HarnessTest, node *node.HarnessNode,
  1405. version signrpc.MuSig2Version) (*signrpc.KeyDescriptor,
  1406. *signrpc.KeyDescriptor, *signrpc.KeyDescriptor, [][]byte) {
  1407. // For muSig2 we need multiple keys. We derive three of them from the
  1408. // same wallet, just so we know we can also sign for them again.
  1409. req := &walletrpc.KeyReq{KeyFamily: testTaprootKeyFamily}
  1410. keyDesc1 := node.RPC.DeriveNextKey(req)
  1411. pubKey1, err := btcec.ParsePubKey(keyDesc1.RawKeyBytes)
  1412. require.NoError(ht, err)
  1413. keyDesc2 := node.RPC.DeriveNextKey(req)
  1414. pubKey2, err := btcec.ParsePubKey(keyDesc2.RawKeyBytes)
  1415. require.NoError(ht, err)
  1416. keyDesc3 := node.RPC.DeriveNextKey(req)
  1417. pubKey3, err := btcec.ParsePubKey(keyDesc3.RawKeyBytes)
  1418. require.NoError(ht, err)
  1419. // Now that we have all three keys we can create three sessions, one
  1420. // for each of the signers. This would of course normally not happen on
  1421. // the same node.
  1422. var allPubKeys [][]byte
  1423. switch version {
  1424. case signrpc.MuSig2Version_MUSIG2_VERSION_V040:
  1425. allPubKeys = [][]byte{
  1426. schnorr.SerializePubKey(pubKey1),
  1427. schnorr.SerializePubKey(pubKey2),
  1428. schnorr.SerializePubKey(pubKey3),
  1429. }
  1430. case signrpc.MuSig2Version_MUSIG2_VERSION_V100RC2:
  1431. allPubKeys = [][]byte{
  1432. pubKey1.SerializeCompressed(),
  1433. pubKey2.SerializeCompressed(),
  1434. pubKey3.SerializeCompressed(),
  1435. }
  1436. }
  1437. return keyDesc1, keyDesc2, keyDesc3, allPubKeys
  1438. }
  1439. // createMuSigSessions creates a MuSig2 session with three keys that are
  1440. // combined into a single key. The same node is used for the three signing
  1441. // participants but a separate key is generated for each session. So the result
  1442. // should be the same as if it were three different nodes.
  1443. func createMuSigSessions(ht *lntest.HarnessTest, node *node.HarnessNode,
  1444. taprootTweak *signrpc.TaprootTweakDesc,
  1445. keyDesc1, keyDesc2, keyDesc3 *signrpc.KeyDescriptor,
  1446. allPubKeys [][]byte, version signrpc.MuSig2Version) (*btcec.PublicKey,
  1447. *btcec.PublicKey, *signrpc.MuSig2SessionResponse,
  1448. *signrpc.MuSig2SessionResponse, *signrpc.MuSig2SessionResponse) {
  1449. // Make sure that when not specifying a version we get an error, since
  1450. // it is mandatory.
  1451. err := node.RPC.MuSig2CreateSessionErr(&signrpc.MuSig2SessionRequest{})
  1452. require.ErrorContains(ht, err, "unknown MuSig2 version")
  1453. // Create the actual session with the version specified.
  1454. sessResp1 := node.RPC.MuSig2CreateSession(&signrpc.MuSig2SessionRequest{
  1455. KeyLoc: keyDesc1.KeyLoc,
  1456. AllSignerPubkeys: allPubKeys,
  1457. TaprootTweak: taprootTweak,
  1458. Version: version,
  1459. })
  1460. require.Equal(ht, version, sessResp1.Version)
  1461. // Make sure the version is returned correctly.
  1462. require.Equal(ht, version, sessResp1.Version)
  1463. // Now that we have the three keys in a combined form, we want to make
  1464. // sure the tweaking for the taproot key worked correctly. We first need
  1465. // to parse the combined key without any tweaks applied to it. That will
  1466. // be our internal key. Once we know that, we can tweak it with the
  1467. // tapHash of the script root hash. We should arrive at the same result
  1468. // as the API.
  1469. combinedKey, err := schnorr.ParsePubKey(sessResp1.CombinedKey)
  1470. require.NoError(ht, err)
  1471. // When combining the key without creating a session, we expect the same
  1472. // combined key to be created.
  1473. expectedCombinedKey := combinedKey
  1474. // Without a tweak, the internal key is equal to the combined key.
  1475. internalKey := combinedKey
  1476. // If there is a tweak, then there is the internal, pre-tweaked combined
  1477. // key and the taproot key which is fully tweaked.
  1478. if taprootTweak != nil {
  1479. internalKey, err = schnorr.ParsePubKey(
  1480. sessResp1.TaprootInternalKey,
  1481. )
  1482. require.NoError(ht, err)
  1483. // We now know the taproot key. The session with the tweak
  1484. // applied should produce the same key!
  1485. expectedCombinedKey = txscript.ComputeTaprootOutputKey(
  1486. internalKey, taprootTweak.ScriptRoot,
  1487. )
  1488. require.Equal(
  1489. ht, schnorr.SerializePubKey(expectedCombinedKey),
  1490. schnorr.SerializePubKey(combinedKey),
  1491. )
  1492. }
  1493. // Same with the combine keys RPC, no version specified should give us
  1494. // an error.
  1495. err = node.RPC.MuSig2CombineKeysErr(&signrpc.MuSig2CombineKeysRequest{})
  1496. require.ErrorContains(ht, err, "unknown MuSig2 version")
  1497. // We should also get the same keys when just calling the
  1498. // MuSig2CombineKeys RPC.
  1499. combineReq := &signrpc.MuSig2CombineKeysRequest{
  1500. AllSignerPubkeys: allPubKeys,
  1501. TaprootTweak: taprootTweak,
  1502. Version: version,
  1503. }
  1504. combineResp := node.RPC.MuSig2CombineKeys(combineReq)
  1505. require.Equal(
  1506. ht, schnorr.SerializePubKey(expectedCombinedKey),
  1507. combineResp.CombinedKey,
  1508. )
  1509. require.Equal(
  1510. ht, schnorr.SerializePubKey(internalKey),
  1511. combineResp.TaprootInternalKey,
  1512. )
  1513. require.Equal(ht, version, combineResp.Version)
  1514. // Everything is good so far, let's continue with creating the signing
  1515. // session for the other two participants.
  1516. req := &signrpc.MuSig2SessionRequest{
  1517. KeyLoc: keyDesc2.KeyLoc,
  1518. AllSignerPubkeys: allPubKeys,
  1519. OtherSignerPublicNonces: [][]byte{
  1520. sessResp1.LocalPublicNonces,
  1521. },
  1522. TaprootTweak: taprootTweak,
  1523. Version: version,
  1524. }
  1525. sessResp2 := node.RPC.MuSig2CreateSession(req)
  1526. require.Equal(ht, sessResp1.CombinedKey, sessResp2.CombinedKey)
  1527. require.Equal(ht, version, sessResp2.Version)
  1528. req = &signrpc.MuSig2SessionRequest{
  1529. KeyLoc: keyDesc3.KeyLoc,
  1530. AllSignerPubkeys: allPubKeys,
  1531. OtherSignerPublicNonces: [][]byte{
  1532. sessResp1.LocalPublicNonces,
  1533. sessResp2.LocalPublicNonces,
  1534. },
  1535. TaprootTweak: taprootTweak,
  1536. Version: version,
  1537. }
  1538. sessResp3 := node.RPC.MuSig2CreateSession(req)
  1539. require.Equal(ht, sessResp2.CombinedKey, sessResp3.CombinedKey)
  1540. require.Equal(ht, version, sessResp3.Version)
  1541. require.Equal(ht, true, sessResp3.HaveAllNonces)
  1542. // We need to distribute the rest of the nonces.
  1543. nonceReq := &signrpc.MuSig2RegisterNoncesRequest{
  1544. SessionId: sessResp1.SessionId,
  1545. OtherSignerPublicNonces: [][]byte{
  1546. sessResp2.LocalPublicNonces,
  1547. sessResp3.LocalPublicNonces,
  1548. },
  1549. }
  1550. nonceResp1 := node.RPC.MuSig2RegisterNonces(nonceReq)
  1551. require.True(ht, nonceResp1.HaveAllNonces)
  1552. nonceReq = &signrpc.MuSig2RegisterNoncesRequest{
  1553. SessionId: sessResp2.SessionId,
  1554. OtherSignerPublicNonces: [][]byte{
  1555. sessResp3.LocalPublicNonces,
  1556. },
  1557. }
  1558. nonceResp2 := node.RPC.MuSig2RegisterNonces(nonceReq)
  1559. require.True(ht, nonceResp2.HaveAllNonces)
  1560. return internalKey, combinedKey, sessResp1, sessResp2, sessResp3
  1561. }
  1562. // testTaprootCoopClose asserts that if both peers signal ShutdownAnySegwit,
  1563. // then a taproot closing addr is used. Otherwise, we shouldn't expect one to
  1564. // be used.
  1565. func testTaprootCoopClose(ht *lntest.HarnessTest) {
  1566. // We'll start by making two new nodes, and funding a channel between
  1567. // them.
  1568. carol := ht.NewNode("Carol", nil)
  1569. ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
  1570. dave := ht.NewNode("Dave", nil)
  1571. ht.EnsureConnected(carol, dave)
  1572. chanAmt := funding.MaxBtcFundingAmount
  1573. pushAmt := btcutil.Amount(100000)
  1574. satPerVbyte := btcutil.Amount(1)
  1575. // We'll now open a channel between Carol and Dave.
  1576. chanPoint := ht.OpenChannel(
  1577. carol, dave, lntest.OpenChannelParams{
  1578. Amt: chanAmt,
  1579. PushAmt: pushAmt,
  1580. SatPerVByte: satPerVbyte,
  1581. },
  1582. )
  1583. // We'll now close out the channel and obtain the closing TXID.
  1584. closingTxid := ht.CloseChannel(carol, chanPoint)
  1585. // assertTaprootDeliveryUsed returns true if a Taproot addr was used in
  1586. // the co-op close transaction.
  1587. assertTaprootDeliveryUsed := func(closingTxid *chainhash.Hash) bool {
  1588. tx := ht.Miner.GetRawTransaction(closingTxid)
  1589. for _, txOut := range tx.MsgTx().TxOut {
  1590. if !txscript.IsPayToTaproot(txOut.PkScript) {
  1591. return false
  1592. }
  1593. }
  1594. return true
  1595. }
  1596. // We expect that the closing transaction only has P2TR addresses.
  1597. require.True(ht, assertTaprootDeliveryUsed(closingTxid),
  1598. "taproot addr not used!")
  1599. // Now we'll bring Eve into the mix, Eve is running older software that
  1600. // doesn't understand Taproot.
  1601. eveArgs := []string{"--protocol.no-any-segwit"}
  1602. eve := ht.NewNode("Eve", eveArgs)
  1603. ht.EnsureConnected(carol, eve)
  1604. // We'll now open up a chanel again between Carol and Eve.
  1605. chanPoint = ht.OpenChannel(
  1606. carol, eve, lntest.OpenChannelParams{
  1607. Amt: chanAmt,
  1608. PushAmt: pushAmt,
  1609. SatPerVByte: satPerVbyte,
  1610. },
  1611. )
  1612. // We'll now close out this channel and expect that no Taproot
  1613. // addresses are used in the co-op close transaction.
  1614. closingTxid = ht.CloseChannel(carol, chanPoint)
  1615. require.False(ht, assertTaprootDeliveryUsed(closingTxid),
  1616. "taproot addr shouldn't be used!")
  1617. }
  1618. // testMuSig2CombineKey makes sure that combining a key with MuSig2 returns the
  1619. // correct result according to the MuSig2 version specified.
  1620. func testMuSig2CombineKey(ht *lntest.HarnessTest, alice *node.HarnessNode,
  1621. version signrpc.MuSig2Version) {
  1622. testVector040Key1 := hexDecode(
  1623. "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE0" +
  1624. "36F9",
  1625. )
  1626. testVector040Key2 := hexDecode(
  1627. "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502B" +
  1628. "A659",
  1629. )
  1630. testVector040Key3 := hexDecode(
  1631. "3590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038" +
  1632. "CA66",
  1633. )
  1634. testVector100Key1 := hexDecode(
  1635. "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BC" +
  1636. "E036F9",
  1637. )
  1638. testVector100Key2 := hexDecode(
  1639. "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B50" +
  1640. "2BA659",
  1641. )
  1642. testVector100Key3 := hexDecode(
  1643. "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D0" +
  1644. "38CA66",
  1645. )
  1646. var allPubKeys [][]byte
  1647. switch version {
  1648. case signrpc.MuSig2Version_MUSIG2_VERSION_V040:
  1649. allPubKeys = [][]byte{
  1650. testVector040Key1, testVector040Key2, testVector040Key3,
  1651. }
  1652. case signrpc.MuSig2Version_MUSIG2_VERSION_V100RC2:
  1653. allPubKeys = [][]byte{
  1654. testVector100Key1, testVector100Key2, testVector100Key3,
  1655. }
  1656. }
  1657. resp := alice.RPC.MuSig2CombineKeys(&signrpc.MuSig2CombineKeysRequest{
  1658. AllSignerPubkeys: allPubKeys,
  1659. TaprootTweak: &signrpc.TaprootTweakDesc{
  1660. KeySpendOnly: true,
  1661. },
  1662. Version: version,
  1663. })
  1664. expectedFinalKey040 := hexDecode(
  1665. "5b257b4e785d61157ef5303051f45184bd5cb47bc4b4069ed4dd453645" +
  1666. "9cb83b",
  1667. )
  1668. expectedPreTweakKey040 := hexDecode(
  1669. "d70cd69a2647f7390973df48cbfa2ccc407b8b2d60b08c5f1641185c79" +
  1670. "98a290",
  1671. )
  1672. expectedFinalKey100 := hexDecode(
  1673. "79e6c3e628c9bfbce91de6b7fb28e2aec7713d377cf260ab599dcbc40e54" +
  1674. "2312",
  1675. )
  1676. expectedPreTweakKey100 := hexDecode(
  1677. "789d937bade6673538f3e28d8368dda4d0512f94da44cf477a505716d26a" +
  1678. "1575",
  1679. )
  1680. switch version {
  1681. case signrpc.MuSig2Version_MUSIG2_VERSION_V040:
  1682. require.Equal(ht, expectedFinalKey040, resp.CombinedKey)
  1683. require.Equal(
  1684. ht, expectedPreTweakKey040, resp.TaprootInternalKey,
  1685. )
  1686. case signrpc.MuSig2Version_MUSIG2_VERSION_V100RC2:
  1687. require.Equal(ht, expectedFinalKey100, resp.CombinedKey)
  1688. require.Equal(
  1689. ht, expectedPreTweakKey100, resp.TaprootInternalKey,
  1690. )
  1691. }
  1692. }