Skip to content

Commit 820f4a8

Browse files
committed
itest: add test to ensure multi-input PSBT spend works for asset ID
This commit adds a tests to ensure that we can correctly construct and spend a multi-input full value PSBT where each input has the same asset ID.
1 parent 1414ba8 commit 820f4a8

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

itest/psbt_test.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,163 @@ func testPsbtMultiSend(t *harnessTest) {
953953
)
954954
}
955955

956+
// testMultiInputPsbtSingleAssetID tests to ensure that we can correctly
957+
// construct and spend a multi-input full value PSBT where each input has the
958+
// same asset ID.
959+
//
960+
// The test works as follows:
961+
// 1. Mint an asset on the primary tapd node.
962+
// 2. Send the asset to a secondary tapd node in two different send events.
963+
// 3. Send the asset back to the primary tapd node in a single multi-input PSBT
964+
// send event.
965+
func testMultiInputPsbtSingleAssetID(t *harnessTest) {
966+
var (
967+
ctxb = context.Background()
968+
primaryTapd = t.tapd
969+
)
970+
971+
// Mint a single asset.
972+
rpcAssets := MintAssetsConfirmBatch(
973+
t.t, t.lndHarness.Miner.Client, primaryTapd,
974+
[]*mintrpc.MintAssetRequest{simpleAssets[0]},
975+
)
976+
rpcAsset := rpcAssets[0]
977+
978+
// Set up a node that will serve as the final multi input PSBT sender
979+
// node.
980+
secondaryTapd := setupTapdHarness(
981+
t.t, t, t.lndHarness.Bob, t.universeServer,
982+
)
983+
defer func() {
984+
require.NoError(t.t, secondaryTapd.stop(!*noDelete))
985+
}()
986+
987+
// First of two send events from primary (minting) node to secondary
988+
// node.
989+
genInfo := rpcAsset.AssetGenesis
990+
addr, err := secondaryTapd.NewAddr(
991+
ctxb, &taprpc.NewAddrRequest{
992+
AssetId: genInfo.AssetId,
993+
Amt: 1000,
994+
},
995+
)
996+
require.NoError(t.t, err)
997+
AssertAddrCreated(t.t, secondaryTapd, rpcAsset, addr)
998+
999+
// Send the assets to the secondary node.
1000+
sendResp := sendAssetsToAddr(t, primaryTapd, addr)
1001+
1002+
ConfirmAndAssertOutboundTransfer(
1003+
t.t, t.lndHarness.Miner.Client, primaryTapd, sendResp,
1004+
genInfo.AssetId, []uint64{4000, 1000}, 0, 1,
1005+
)
1006+
1007+
AssertNonInteractiveRecvComplete(t.t, secondaryTapd, 1)
1008+
1009+
// Second of two send events from primary (minting) node to the
1010+
// secondary node.
1011+
addr, err = secondaryTapd.NewAddr(
1012+
ctxb, &taprpc.NewAddrRequest{
1013+
AssetId: genInfo.AssetId,
1014+
Amt: 4000,
1015+
},
1016+
)
1017+
require.NoError(t.t, err)
1018+
AssertAddrCreated(t.t, secondaryTapd, rpcAsset, addr)
1019+
1020+
// Send the assets to the secondary node.
1021+
sendResp = sendAssetsToAddr(t, primaryTapd, addr)
1022+
1023+
ConfirmAndAssertOutboundTransfer(
1024+
t.t, t.lndHarness.Miner.Client, primaryTapd, sendResp,
1025+
genInfo.AssetId, []uint64{0, 4000}, 1, 2,
1026+
)
1027+
1028+
AssertNonInteractiveRecvComplete(t.t, secondaryTapd, 2)
1029+
1030+
t.Logf("Two separate send events complete, now attempting to send " +
1031+
"back the full amount in a single multi-input PSBT send event")
1032+
1033+
// Ensure that the primary node has no assets before we begin.
1034+
primaryNodeAssets, err := primaryTapd.ListAssets(
1035+
ctxb, &taprpc.ListAssetRequest{},
1036+
)
1037+
require.NoError(t.t, err)
1038+
require.Empty(t.t, primaryNodeAssets.Assets)
1039+
1040+
// We need to derive two keys for the receiver node, one for the new
1041+
// script key and one for the internal key.
1042+
receiverScriptKey, receiverAnchorIntKeyDesc := deriveKeys(
1043+
t.t, primaryTapd,
1044+
)
1045+
1046+
var assetId asset.ID
1047+
copy(assetId[:], genInfo.AssetId)
1048+
1049+
var (
1050+
chainParams = &address.RegressionNetTap
1051+
sendAmt = uint64(5000)
1052+
)
1053+
1054+
vPkt := tappsbt.ForInteractiveSend(
1055+
assetId, sendAmt, receiverScriptKey, 0,
1056+
receiverAnchorIntKeyDesc, asset.V0, chainParams,
1057+
)
1058+
1059+
// Next, we'll attempt to fund the PSBT.
1060+
fundResp := fundPacket(t, secondaryTapd, vPkt)
1061+
signResp, err := secondaryTapd.SignVirtualPsbt(
1062+
ctxb, &wrpc.SignVirtualPsbtRequest{
1063+
FundedPsbt: fundResp.FundedPsbt,
1064+
},
1065+
)
1066+
require.NoError(t.t, err)
1067+
1068+
// And finally anchor the PSBT in the BTC chain to complete the
1069+
// transfer.
1070+
sendResp, err = secondaryTapd.AnchorVirtualPsbts(
1071+
ctxb, &wrpc.AnchorVirtualPsbtsRequest{
1072+
VirtualPsbts: [][]byte{signResp.SignedPsbt},
1073+
},
1074+
)
1075+
require.NoError(t.t, err)
1076+
1077+
var (
1078+
currentTransferIdx = 0
1079+
numTransfers = 1
1080+
numOutputs = 1
1081+
)
1082+
ConfirmAndAssetOutboundTransferWithOutputs(
1083+
t.t, t.lndHarness.Miner.Client, secondaryTapd,
1084+
sendResp, genInfo.AssetId,
1085+
[]uint64{sendAmt}, currentTransferIdx, numTransfers,
1086+
numOutputs,
1087+
)
1088+
1089+
// This is an interactive transfer. Therefore, we will manually transfer
1090+
// the proof from the sender to the receiver.
1091+
_ = sendProof(
1092+
t, secondaryTapd, primaryTapd,
1093+
receiverScriptKey.PubKey.SerializeCompressed(), genInfo,
1094+
)
1095+
1096+
// Finally, we make sure that the primary node has the asset.
1097+
primaryNodeAssets, err = primaryTapd.ListAssets(
1098+
ctxb, &taprpc.ListAssetRequest{},
1099+
)
1100+
require.NoError(t.t, err)
1101+
require.Len(t.t, primaryNodeAssets.Assets, 1)
1102+
1103+
// Ensure that the asset is the one we expect.
1104+
primaryNodeAsset := primaryNodeAssets.Assets[0]
1105+
1106+
require.Equal(t.t, primaryNodeAsset.Amount, sendAmt)
1107+
1108+
var foundAssetId asset.ID
1109+
copy(foundAssetId[:], primaryNodeAsset.AssetGenesis.AssetId)
1110+
require.Equal(t.t, assetId, foundAssetId)
1111+
}
1112+
9561113
func deriveKeys(t *testing.T, tapd *tapdHarness) (asset.ScriptKey,
9571114
keychain.KeyDescriptor) {
9581115

itest/test_list_on_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ var testCases = []*testCase{
167167
name: "psbt multi send",
168168
test: testPsbtMultiSend,
169169
},
170+
{
171+
name: "multi input psbt single asset id",
172+
test: testMultiInputPsbtSingleAssetID,
173+
},
170174
{
171175
name: "universe REST API",
172176
test: testUniverseREST,

0 commit comments

Comments
 (0)