From a96a16f110e6c892d8eed35f396d8e037104bd92 Mon Sep 17 00:00:00 2001 From: Jonathan Harvey-Buschel Date: Mon, 25 Nov 2024 16:46:57 -0500 Subject: [PATCH] itest: add AltLeaves in PSBT ping-pong tests --- itest/assertions.go | 53 +++++++++++++++++++++++++++++++++++++++++++++ itest/psbt_test.go | 39 ++++++++++++++++++++++++++++----- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/itest/assertions.go b/itest/assertions.go index ca8b4042d..fd21bfd33 100644 --- a/itest/assertions.go +++ b/itest/assertions.go @@ -521,6 +521,59 @@ func AssertAssetProofs(t *testing.T, tapClient taprpc.TaprootAssetsClient, return exportResp.RawProofFile } +// AssertProofAltLeaves makes sure that, for a given asset, the latest proof +// commits to an expected set of altLeaves. +func AssertProofAltLeaves(t *testing.T, tapClient taprpc.TaprootAssetsClient, + a *taprpc.Asset, leafMap map[string][]*asset.Asset) { + + t.Helper() + ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() + + // Fetch the latest proof for the given asset. + scriptKey := a.ScriptKey + proofReq := taprpc.ExportProofRequest{ + AssetId: a.AssetGenesis.AssetId, + ScriptKey: scriptKey, + } + exportResp, err := tapClient.ExportProof(ctxt, &proofReq) + require.NoError(t, err) + + decodeReq := taprpc.DecodeProofRequest{ + RawProof: exportResp.RawProofFile, + } + decodeResp, err := tapClient.DecodeProof(ctxt, &decodeReq) + require.NoError(t, err) + + // Check if we expect the asset to be anchored alongside alt leaves or + // not. E.x. a passive asset created inside the freighter will not be + // anchored with any alt leaves. + altLeavesBytes := decodeResp.DecodedProof.AltLeaves + expectedAltLeaves, ok := leafMap[string(scriptKey)] + emptyAltLeaves := len(altLeavesBytes) == 0 + + require.Equal(t, ok, !emptyAltLeaves) + if emptyAltLeaves { + return + } + + // If we have altLeaves, decode them and check that they match the + // expected leaves. + var ( + r = bytes.NewReader(altLeavesBytes) + l = uint64(len(altLeavesBytes)) + scratch [8]byte + val []asset.AltLeafAsset + ) + + require.NoError(t, asset.AltLeavesDecoder(r, &val, &scratch, l)) + asset.CompareAltLeaves(t, asset.ToAltLeaves(expectedAltLeaves), val) + t.Logf("matching alt leaves for: %v, %x, %x: %d leaves", + a.ChainAnchor.AnchorOutpoint, a.AssetGenesis.AssetId, + a.ScriptKey, len(val)) +} + // AssertMintingProofs make sure the asset minting proofs contain all the // correct reveal information. func AssertMintingProofs(t *testing.T, tapd *tapdHarness, diff --git a/itest/psbt_test.go b/itest/psbt_test.go index 3b3665a44..839853cd6 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -608,12 +608,19 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, receiverScriptKey, receiverAnchorIntKeyDesc := DeriveKeys( t.t, receiver, ) + receiverScriptKeyBytes := receiverScriptKey.PubKey. + SerializeCompressed() vPkt := tappsbt.ForInteractiveSend( id, fullAmt, receiverScriptKey, 0, 0, 0, - receiverAnchorIntKeyDesc, asset.V0, - chainParams, + receiverAnchorIntKeyDesc, asset.V0, chainParams, ) + altLeaves := asset.RandAltLeaves(t.t, true) + leafMap := map[string][]*asset.Asset{ + string(receiverScriptKeyBytes): altLeaves, + } + err := vPkt.Outputs[0].SetAltLeaves(altLeaves) + require.NoError(t.t, err) // Next, we'll attempt to complete a transfer with PSBTs from // our sender node to our receiver, using the full amount. @@ -644,8 +651,8 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, // This is an interactive transfer, so we do need to manually // send the proof from the sender to the receiver. _ = sendProof( - t, sender, receiver, sendResp, - receiverScriptKey.PubKey.SerializeCompressed(), genInfo, + t, sender, receiver, sendResp, receiverScriptKeyBytes, + genInfo, ) senderAssets, err := sender.ListAssets( @@ -674,6 +681,12 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, t.t, receivedAssets, genInfo.Name, genInfo.MetaHash, AssetAmountCheck(fullAmt), ) + + // Check that the altLeaves from the receiver's vPacket were set + // by the sender correctly. + for _, asset := range receiverAssets.Assets { + AssertProofAltLeaves(t.t, receiver, asset, leafMap) + } } // Finally, make sure we can still send out the passive asset. @@ -822,11 +835,19 @@ func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest, receiverScriptKey, receiverAnchorIntKeyDesc := DeriveKeys( t.t, receiver, ) + receiverScriptKeyBytes := receiverScriptKey.PubKey. + SerializeCompressed() vPkt := tappsbt.ForInteractiveSend( id, sendAmt, receiverScriptKey, 0, 0, 0, receiverAnchorIntKeyDesc, asset.V0, chainParams, ) + altLeaves := asset.RandAltLeaves(t.t, true) + leafMap := map[string][]*asset.Asset{ + string(receiverScriptKeyBytes): altLeaves, + } + err := vPkt.Outputs[0].SetAltLeaves(altLeaves) + require.NoError(t.t, err) // Next, we'll attempt to complete a transfer with PSBTs from // our sender node to our receiver, using the partial amount. @@ -857,8 +878,8 @@ func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest, // This is an interactive transfer, so we do need to manually // send the proof from the sender to the receiver. _ = sendProof( - t, sender, receiver, sendResp, - receiverScriptKey.PubKey.SerializeCompressed(), genInfo, + t, sender, receiver, sendResp, receiverScriptKeyBytes, + genInfo, ) senderAssets, err := sender.ListAssets( @@ -890,6 +911,12 @@ func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest, ) require.NoError(t.t, err) require.Len(t.t, receiverAssets.Assets, numReceiverAssets) + + // Check that the altLeaves from the receiver's vPacket were set + // by the sender correctly. + for _, asset := range receiverAssets.Assets { + AssertProofAltLeaves(t.t, receiver, asset, leafMap) + } } // Finally, make sure we can still send out the passive asset.