From a4f89b130804c4b247a8ee3ce4701260d88b0e73 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 14:15:32 +0200 Subject: [PATCH 01/10] itest: sync itest names and test function names --- itest/addrs_test.go | 1 + itest/assets_test.go | 4 +++- itest/{reissuance_test.go => re-issuance_test.go} | 0 itest/send_test.go | 4 ++-- itest/test_list_on_test.go | 8 ++++---- itest/universe_test.go | 4 ++++ 6 files changed, 14 insertions(+), 7 deletions(-) rename itest/{reissuance_test.go => re-issuance_test.go} (100%) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index 5d864b7f1..2f139f2e3 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" ) +// testAddresses tests the various RPC calls related to addresses. func testAddresses(t *harnessTest) { // First, mint a few assets, so we have some to create addresses for. // We mint all of them in individual batches to avoid needing to sign diff --git a/itest/assets_test.go b/itest/assets_test.go index 223139f1a..b8ceaeaf4 100644 --- a/itest/assets_test.go +++ b/itest/assets_test.go @@ -103,7 +103,9 @@ func copyRequests(reqs []*mintrpc.MintAssetRequest) []*mintrpc.MintAssetRequest return copied } -func mintAssets(t *harnessTest) { +// testMintAssets tests that we're able to mint assets, retrieve their proofs +// and that we're able to import the proofs into a new node. +func testMintAssets(t *harnessTest) { rpcSimpleAssets := mintAssetsConfirmBatch(t, t.tarod, simpleAssets) rpcIssuableAssets := mintAssetsConfirmBatch(t, t.tarod, issuableAssets) diff --git a/itest/reissuance_test.go b/itest/re-issuance_test.go similarity index 100% rename from itest/reissuance_test.go rename to itest/re-issuance_test.go diff --git a/itest/send_test.go b/itest/send_test.go index 9ea5e7270..c5e2b0390 100644 --- a/itest/send_test.go +++ b/itest/send_test.go @@ -126,9 +126,9 @@ func testBasicSend(t *harnessTest) { wg.Wait() } -// testSendPassiveAsset tests that we can properly send assets which were +// testBasicSendPassiveAsset tests that we can properly send assets which were // passive assets during a previous send. -func testSendPassiveAsset(t *harnessTest) { +func testBasicSendPassiveAsset(t *harnessTest) { ctxb := context.Background() // Mint two different assets. diff --git a/itest/test_list_on_test.go b/itest/test_list_on_test.go index 14e4cc3ea..845b7b309 100644 --- a/itest/test_list_on_test.go +++ b/itest/test_list_on_test.go @@ -6,7 +6,7 @@ package itest var testCases = []*testCase{ { name: "mint assets", - test: mintAssets, + test: testMintAssets, }, { name: "asset name collision raises mint error", @@ -32,7 +32,7 @@ var testCases = []*testCase{ }, { name: "basic send passive asset", - test: testSendPassiveAsset, + test: testBasicSendPassiveAsset, }, { name: "multi input send non-interactive single ID", @@ -51,7 +51,7 @@ var testCases = []*testCase{ test: testCollectibleSend, }, { - name: "reissuance", + name: "re-issuance", test: testReIssuance, }, { @@ -59,7 +59,7 @@ var testCases = []*testCase{ test: testMintMultiAssetGroups, }, { - name: "re-issuance asset amount overflow", + name: "re-issuance amount overflow", test: testReIssuanceAmountOverflow, }, { diff --git a/itest/universe_test.go b/itest/universe_test.go index d62285392..7ec56902b 100644 --- a/itest/universe_test.go +++ b/itest/universe_test.go @@ -15,6 +15,8 @@ import ( "golang.org/x/exp/maps" ) +// testUniverseSync tests that we're able to properly sync the universe state +// between two nodes. func testUniverseSync(t *harnessTest) { // First, we'll create out usual set of simple and also issuable // assets. @@ -121,6 +123,8 @@ func testUniverseSync(t *harnessTest) { assertUniverseLeavesEqual(t.t, uniIDs, t.tarod, bob) } +// testUniverseREST tests that we're able to properly query the universe state +// via the REST interface. func testUniverseREST(t *harnessTest) { // Mint a few assets that we then want to inspect in the universe. rpcSimpleAssets := mintAssetsConfirmBatch(t, t.tarod, simpleAssets) From 16d39421063594f9feb12ac93b52256538be1078 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 14:15:33 +0200 Subject: [PATCH 02/10] multi: move spew.Sdump() to trace logs, fix typos --- rpcserver.go | 3 ++- tarofreighter/chain_porter.go | 8 +++---- tarogarden/caretaker.go | 6 +++--- universe/syncer.go | 40 +++++++++++++++++++++-------------- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 3950932ed..3d0772404 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1132,7 +1132,8 @@ func (r *rpcServer) AddrReceives(ctx context.Context, addr.AssetID[:], err) } - rpcsLog.Infof("group: %v", spew.Sdump(assetGroup)) + rpcsLog.Tracef("Listing receives for group: %v", + spew.Sdump(assetGroup)) addr.AttachGenesis(*assetGroup.Genesis) diff --git a/tarofreighter/chain_porter.go b/tarofreighter/chain_porter.go index b9ffb658d..4b8ea391d 100644 --- a/tarofreighter/chain_porter.go +++ b/tarofreighter/chain_porter.go @@ -208,7 +208,7 @@ func (p *ChainPorter) resumePendingParcel(pkg *OutboundParcel) { err := p.advanceState(&restartSendPkg) if err != nil { // TODO(roasbef): no req to send the error back to here - log.Warnf("unable to advance state machine: %v", err) + log.Warnf("Unable to advance state machine: %v", err) return } } @@ -230,7 +230,7 @@ func (p *ChainPorter) taroPorter() { // possible. err := p.advanceState(sendPkg) if err != nil { - log.Warnf("unable to advance state machine: %v", + log.Warnf("Unable to advance state machine: %v", err) req.kit().errChan <- err continue @@ -284,8 +284,8 @@ func (p *ChainPorter) waitForTransferTxConf(pkg *sendPackage) error { } if confEvent == nil { - return fmt.Errorf("got empty package tx confirmation event in " + - "batch") + return fmt.Errorf("got empty package tx confirmation event " + + "in batch") } return nil diff --git a/tarogarden/caretaker.go b/tarogarden/caretaker.go index 9c89b8110..e45881483 100644 --- a/tarogarden/caretaker.go +++ b/tarogarden/caretaker.go @@ -375,8 +375,8 @@ func (b *BatchCaretaker) seedlingsToAssetSprouts(ctx context.Context, taroOutputIndex uint32) (*commitment.TaroCommitment, error) { log.Infof("BatchCaretaker(%x): mapping %v seedlings to asset sprouts, "+ - "with genesis_point=%v", b.batchKey[:], len(b.cfg.Batch.Seedlings), - genesisPoint) + "with genesis_point=%v", b.batchKey[:], + len(b.cfg.Batch.Seedlings), genesisPoint) newAssets := make([]*asset.Asset, 0, len(b.cfg.Batch.Seedlings)) @@ -550,7 +550,7 @@ func (b *BatchCaretaker) stateStep(currentState BatchState) (BatchState, error) // First, we'll turn all the seedlings into actual taro assets. taroCommitment, err := b.seedlingsToAssetSprouts( - ctx, genesisPoint, uint32(b.anchorOutputIndex), + ctx, genesisPoint, b.anchorOutputIndex, ) if err != nil { return 0, fmt.Errorf("unable to map seedlings to "+ diff --git a/universe/syncer.go b/universe/syncer.go index ccad806dd..ffc81f0b1 100644 --- a/universe/syncer.go +++ b/universe/syncer.go @@ -11,12 +11,12 @@ import ( ) var ( - // ErrUnsupportedSync is returned when a syncer is asked to async in a way - // that it does not support. + // ErrUnsupportedSync is returned when a syncer is asked to async in a + // way that it does not support. ErrUnsupportedSync = fmt.Errorf("unsupported sync type") ) -// SimplerSyncCfg contains all the configuration needed to create a new +// SimpleSyncCfg contains all the configuration needed to create a new // SimpleSyncer. type SimpleSyncCfg struct { // LocalDiffEngine is the diff engine tied to a local Universe @@ -39,7 +39,7 @@ type SimpleSyncer struct { cfg SimpleSyncCfg } -// NewSimplerSyncer creates a new SimpleSyncer instance. +// NewSimpleSyncer creates a new SimpleSyncer instance. func NewSimpleSyncer(cfg SimpleSyncCfg) *SimpleSyncer { return &SimpleSyncer{ cfg: cfg, @@ -60,7 +60,8 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, // If we have a specific set of Universes to sync, then we'll fetch the // roots for each of them. case len(idsToSync) != 0: - log.Infof("Fetching %v roots for IDs: %v", len(idsToSync), + log.Infof("Fetching %v roots", len(idsToSync)) + log.Tracef("Fetching %v roots for IDs: %v", len(idsToSync), spew.Sdump(idsToSync)) // We'll use an error group to fetch each Universe root we need @@ -97,7 +98,9 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, targetRoots := chanutils.Collect(rootsToSync) - log.Infof("Obtained %v roots from remote Universe server: %v", + log.Infof("Obtained %v roots from remote Universe server", + len(targetRoots)) + log.Tracef("Obtained %v roots from remote Universe server: %v", len(targetRoots), spew.Sdump(targetRoots)) // Now that we know the set of Universes we need to sync, we'll execute @@ -106,9 +109,7 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, err = chanutils.ParSlice(ctx, targetRoots, func(ctx context.Context, remoteRoot BaseRoot) error { // First, we'll compare the remote root against the local root. uniID := remoteRoot.ID - localRoot, err := s.cfg.LocalDiffEngine.RootNode( - ctx, uniID, - ) + localRoot, err := s.cfg.LocalDiffEngine.RootNode(ctx, uniID) switch { // If we don't have this root, then we don't have anything to // compare to so we'll proceed as normal. @@ -148,8 +149,11 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, // keys that need to be synced. keysToFetch := chanutils.SetDiff(remoteUnikeys, localUnikeys) - log.Infof("UniverseRoot(%v): diff_size=%v, diff=%v", - uniID.String(), len(keysToFetch), spew.Sdump(keysToFetch)) + log.Infof("UniverseRoot(%v): diff_size=%v", uniID.String(), + len(keysToFetch)) + log.Tracef("UniverseRoot(%v): diff_size=%v, diff=%v", + uniID.String(), len(keysToFetch), + spew.Sdump(keysToFetch)) // Now that we know where the divergence is, we can fetch the // issuance proofs from the remote party. @@ -173,8 +177,10 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, // TODO(roasbeef): inclusion w/ root here, also that // it's the expected asset ID - log.Infof("UniverseRoot(%v): inserting new leaf for key=%v", - uniID.String(), spew.Sdump(key)) + log.Infof("UniverseRoot(%v): inserting new leaf", + uniID.String()) + log.Tracef("UniverseRoot(%v): inserting new leaf for "+ + "key=%v", uniID.String(), spew.Sdump(key)) // TODO(roasbeef): this is actually giving a lagging // proof for each of them @@ -193,7 +199,7 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, return err } - log.Infof("Universe sync for UniverseRoot(%v) complete, %v "+ + log.Infof("Universe sync for UniverseRoot(%v) complete, %d "+ "new leaves inserted", uniID.String(), len(keysToFetch)) // TODO(roabseef): sanity check local and remote roots match @@ -207,8 +213,10 @@ func (s *SimpleSyncer) executeSync(ctx context.Context, diffEngine DiffEngine, NewLeafProofs: chanutils.Collect(newLeaves), } - log.Infof("Sync for UniverseRoot(%v) complete! New "+ - "universe_root=%v", uniID.String(), spew.Sdump(remoteRoot)) + log.Infof("Sync for UniverseRoot(%v) complete!", uniID.String()) + log.Tracef("Sync for UniverseRoot(%v) complete! New "+ + "universe_root=%v", uniID.String(), + spew.Sdump(remoteRoot)) return nil }) From 005a775635cb44ccc0615cfd3c3073f914c6d35e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 14:15:35 +0200 Subject: [PATCH 03/10] itest: refactor address test to use grouped assets --- itest/addrs_test.go | 64 ++++++++++++++------------------------------- itest/assertions.go | 14 +++++----- 2 files changed, 28 insertions(+), 50 deletions(-) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index 2f139f2e3..bc7c71d44 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -3,7 +3,6 @@ package itest import ( "bytes" "context" - "fmt" "github.com/lightninglabs/taro/taropsbt" "github.com/lightninglabs/taro/tarorpc" @@ -20,7 +19,9 @@ func testAddresses(t *harnessTest) { // for multiple internal asset transfers when only sending one of them // to an external address. rpcAssets := mintAssetsConfirmBatch( - t, t.tarod, []*mintrpc.MintAssetRequest{simpleAssets[0]}, + t, t.tarod, []*mintrpc.MintAssetRequest{ + simpleAssets[0], issuableAssets[0], + }, ) ctxb := context.Background() @@ -40,8 +41,7 @@ func testAddresses(t *harnessTest) { require.NoError(t.t, secondTarod.stop(true)) }() - var addresses []*tarorpc.Addr - for _, a := range rpcAssets { + for idx, a := range rpcAssets { // In order to force a split, we don't try to send the full // asset. addr, err := secondTarod.NewAddr(ctxt, &tarorpc.NewAddrRequest{ @@ -49,7 +49,6 @@ func testAddresses(t *harnessTest) { Amt: a.Amount - 1, }) require.NoError(t.t, err) - addresses = append(addresses, addr) assertAddrCreated(t.t, secondTarod, a, addr) @@ -61,49 +60,26 @@ func testAddresses(t *harnessTest) { // Make sure that eventually we see a single event for the // address. - assertAddrEvent(t.t, secondTarod, addr) - } + assertAddrEvent(t.t, secondTarod, addr, 1, statusDetected) - // Mine a block to make sure the events are marked as confirmed. - _ = mineBlocks(t, t.lndHarness, 1, len(rpcAssets))[0] + // Mine a block to make sure the events are marked as confirmed. + mineBlocks(t, t.lndHarness, 1, 1) - // Eventually the events should be marked as confirmed. - err := wait.NoError(func() error { - resp, err := secondTarod.AddrReceives( - ctxt, &tarorpc.AddrReceivesRequest{}, - ) - require.NoError(t.t, err) - require.Len(t.t, resp.Events, len(rpcAssets)) - - for _, event := range resp.Events { - if event.Status != statusConfirmed { - return fmt.Errorf("got status %v, wanted %v", - resp.Events[0].Status, statusConfirmed) - } - } - - return nil - }, defaultWaitTimeout/2) - require.NoError(t.t, err) - - // To complete the transfer, we'll export the proof from the sender and - // import it into the receiver for each asset set. - for i, rpcAsset := range rpcAssets { - receiverAddr := addresses[i] - - assetGen := rpcAsset.AssetGenesis + // Eventually the event should be marked as confirmed. + assertAddrEvent(t.t, secondTarod, addr, 1, statusConfirmed) + // To complete the transfer, we'll export the proof from the + // sender and import it into the receiver for each asset set. sendProof( - t, t.tarod, secondTarod, receiverAddr.ScriptKey, - assetGen, + t, t.tarod, secondTarod, addr.ScriptKey, a.AssetGenesis, ) - } - // Make sure we have imported and finalized all proofs. - assertNonInteractiveRecvComplete(t, secondTarod, len(rpcAssets)) + // Make sure we have imported and finalized all proofs. + assertNonInteractiveRecvComplete(t, secondTarod, idx+1) + } // Now sanity check that we can actually list the transfer. - err = wait.NoError(func() error { + err := wait.NoError(func() error { resp, err := t.tarod.ListTransfers( ctxt, &tarorpc.ListTransfersRequest{}, ) @@ -193,10 +169,10 @@ func testMultiAddress(t *harnessTest) { t.Logf("Got response from sending assets: %v", sendRespJSON) // Make sure that eventually we see a single event for the address. - assertAddrEvent(t.t, bob, bobAddr1) - assertAddrEvent(t.t, bob, bobAddr2) - assertAddrEvent(t.t, alice, aliceAddr1) - assertAddrEvent(t.t, alice, aliceAddr2) + assertAddrEvent(t.t, bob, bobAddr1, 1, statusDetected) + assertAddrEvent(t.t, bob, bobAddr2, 1, statusDetected) + assertAddrEvent(t.t, alice, aliceAddr1, 1, statusDetected) + assertAddrEvent(t.t, alice, aliceAddr2, 1, statusDetected) // Mine a block to make sure the events are marked as confirmed. _ = mineBlocks(t, t.lndHarness, 1, 1)[0] diff --git a/itest/assertions.go b/itest/assertions.go index ed48eaf27..aa491fae0 100644 --- a/itest/assertions.go +++ b/itest/assertions.go @@ -276,7 +276,9 @@ func assertAddrCreated(t *testing.T, tarod *tarodHarness, // assertAddrEvent makes sure the given address was detected by the given // daemon. -func assertAddrEvent(t *testing.T, tarod *tarodHarness, addr *tarorpc.Addr) { +func assertAddrEvent(t *testing.T, tarod *tarodHarness, addr *tarorpc.Addr, + numEvents int, expectedStatus tarorpc.AddrEventStatus) { + ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) defer cancel() @@ -291,14 +293,14 @@ func assertAddrEvent(t *testing.T, tarod *tarodHarness, addr *tarorpc.Addr) { return err } - if len(resp.Events) != 1 { - return fmt.Errorf("got %d events, wanted 1", - len(resp.Events)) + if len(resp.Events) != numEvents { + return fmt.Errorf("got %d events, wanted %d", + len(resp.Events), numEvents) } - if resp.Events[0].Status != statusDetected { + if resp.Events[0].Status != expectedStatus { return fmt.Errorf("got status %v, wanted %v", - resp.Events[0].Status, statusDetected) + resp.Events[0].Status, expectedStatus) } eventJSON, err := formatProtoJSON(resp.Events[0]) From fc59c3893a592e17c7ac614445a3d061ff3289e4 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 14:42:45 +0200 Subject: [PATCH 04/10] itest: refactor multi address test to use grouped assets --- itest/addrs_test.go | 40 ++++++++++++++++++++++++++++------------ itest/assertions.go | 16 +++++++++------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/itest/addrs_test.go b/itest/addrs_test.go index bc7c71d44..279c3ad95 100644 --- a/itest/addrs_test.go +++ b/itest/addrs_test.go @@ -103,10 +103,14 @@ func testAddresses(t *harnessTest) { func testMultiAddress(t *harnessTest) { // First, mint an asset, so we have one to create addresses for. rpcAssets := mintAssetsConfirmBatch( - t, t.tarod, []*mintrpc.MintAssetRequest{simpleAssets[0]}, + t, t.tarod, []*mintrpc.MintAssetRequest{ + simpleAssets[0], issuableAssets[0], + }, ) mintedAsset := rpcAssets[0] + mintedGroupAsset := rpcAssets[1] genInfo := mintedAsset.AssetGenesis + groupGenInfo := mintedGroupAsset.AssetGenesis ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) @@ -126,6 +130,18 @@ func testMultiAddress(t *harnessTest) { require.NoError(t.t, bob.stop(true)) }() + runMultiSendTest(ctxt, t, alice, bob, genInfo, mintedAsset, 0, 1) + runMultiSendTest( + ctxt, t, alice, bob, groupGenInfo, mintedGroupAsset, 1, 2, + ) +} + +// runMultiSendTest runs a test that sends assets to multiple addresses at the +// same time. +func runMultiSendTest(ctxt context.Context, t *harnessTest, alice, + bob *tarodHarness, genInfo *tarorpc.GenesisInfo, + mintedAsset *tarorpc.Asset, runIdx, numRuns int) { + // In order to force a split, we don't try to send the full asset. const sendAmt = 100 var bobAddresses []*tarorpc.Addr @@ -178,11 +194,11 @@ func testMultiAddress(t *harnessTest) { _ = mineBlocks(t, t.lndHarness, 1, 1)[0] // Eventually the events should be marked as confirmed. - assertAddrReceives(t.t, bob, 2, statusConfirmed) + assertAddrEventByStatus(t.t, bob, statusConfirmed, 2) // For local addresses, we should already have the proof in the DB at // this point, so the status should go to completed directly. - assertAddrReceives(t.t, alice, 2, statusCompleted) + assertAddrEventByStatus(t.t, alice, statusCompleted, numRuns*2) // To complete the transfer, we'll export the proof from the sender and // import it into the receiver for each asset set. This should not be @@ -193,8 +209,8 @@ func testMultiAddress(t *harnessTest) { } // Make sure we have imported and finalized all proofs. - assertNonInteractiveRecvComplete(t, bob, 2) - assertNonInteractiveRecvComplete(t, alice, 2) + assertNonInteractiveRecvComplete(t, bob, numRuns*2) + assertNonInteractiveRecvComplete(t, alice, numRuns*2) // Now sanity check that we can actually list the transfer. const ( @@ -207,14 +223,14 @@ func testMultiAddress(t *harnessTest) { ctxt, &tarorpc.ListTransfersRequest{}, ) require.NoError(t.t, err) - require.Len(t.t, resp.Transfers, len(rpcAssets)) - require.Len(t.t, resp.Transfers[0].Outputs, numOutputs) - firstOut := resp.Transfers[0].Outputs[0] + require.Len(t.t, resp.Transfers, numRuns) + + transfer := resp.Transfers[runIdx] + require.Len(t.t, transfer.Outputs, numOutputs) + firstOut := transfer.Outputs[0] require.EqualValues(t.t, changeAmt, firstOut.Amount) - firstIn := resp.Transfers[0].Inputs[0] - require.Equal( - t.t, rpcAssets[0].AssetGenesis.AssetId, firstIn.AssetId, - ) + firstIn := transfer.Inputs[0] + require.Equal(t.t, genInfo.AssetId, firstIn.AssetId) return nil }, defaultTimeout/2) diff --git a/itest/assertions.go b/itest/assertions.go index aa491fae0..5da64f96c 100644 --- a/itest/assertions.go +++ b/itest/assertions.go @@ -312,10 +312,10 @@ func assertAddrEvent(t *testing.T, tarod *tarodHarness, addr *tarorpc.Addr, require.NoError(t, err) } -// assertAddrReceives makes sure the given number of events with the given -// status were received. -func assertAddrReceives(t *testing.T, tarod *tarodHarness, numEvents int, - expectedStatus tarorpc.AddrEventStatus) { +// assertAddrEventByStatus makes sure the given number of events exist with the +// given status. +func assertAddrEventByStatus(t *testing.T, tarod *tarodHarness, + filterStatus tarorpc.AddrEventStatus, numEvents int) { ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) @@ -323,15 +323,17 @@ func assertAddrReceives(t *testing.T, tarod *tarodHarness, numEvents int, err := wait.NoError(func() error { resp, err := tarod.AddrReceives( - ctxt, &tarorpc.AddrReceivesRequest{}, + ctxt, &tarorpc.AddrReceivesRequest{ + FilterStatus: filterStatus, + }, ) require.NoError(t, err) require.Len(t, resp.Events, numEvents) for _, event := range resp.Events { - if event.Status != expectedStatus { + if event.Status != filterStatus { return fmt.Errorf("got status %v, wanted %v", - resp.Events[0].Status, expectedStatus) + resp.Events[0].Status, filterStatus) } } From f334e84bbb6c45f23613849d6e5bdabef0ab6254 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 15:04:31 +0200 Subject: [PATCH 05/10] itest: refactor full value test to use grouped assets --- itest/assertions.go | 16 ++++---- itest/collectible_split_test.go | 5 ++- itest/full_value_split_test.go | 72 ++++++++++++++++++++------------- itest/re-issuance_test.go | 2 +- itest/round_trip_send_test.go | 12 ++++-- 5 files changed, 64 insertions(+), 43 deletions(-) diff --git a/itest/assertions.go b/itest/assertions.go index 5da64f96c..57adab1a9 100644 --- a/itest/assertions.go +++ b/itest/assertions.go @@ -531,20 +531,22 @@ func assertBalanceByGroup(t *testing.T, tarod *tarodHarness, hexGroupKey string, require.Equal(t, amt, balance.Balance) } -// assertTransfers asserts that the value of each transfer initiated on the +// assertTransfer asserts that the value of each transfer initiated on the // given daemon is correct. -func assertTransfers(t *testing.T, tarod *tarodHarness, amts []uint64) { +func assertTransfer(t *testing.T, tarod *tarodHarness, transferIdx, + numTransfers int, outputAmounts []uint64) { + ctxb := context.Background() transferResp, err := tarod.ListTransfers( ctxb, &tarorpc.ListTransfersRequest{}, ) require.NoError(t, err) - require.Len(t, transferResp.Transfers, len(amts)) + require.Len(t, transferResp.Transfers, numTransfers) - // TODO(jhb): Extend to support multi-asset transfers - for i, transfer := range transferResp.Transfers { - require.Len(t, transfer.Outputs, 2) - require.Equal(t, amts[i], transfer.Outputs[0].Amount) + transfer := transferResp.Transfers[transferIdx] + require.Len(t, transfer.Outputs, len(outputAmounts)) + for i := range transfer.Outputs { + require.Equal(t, outputAmounts[i], transfer.Outputs[i].Amount) } } diff --git a/itest/collectible_split_test.go b/itest/collectible_split_test.go index a89d488fb..4ee241acf 100644 --- a/itest/collectible_split_test.go +++ b/itest/collectible_split_test.go @@ -119,10 +119,11 @@ func testCollectibleSend(t *harnessTest) { // Check the final state of both nodes. The main node should list 2 // zero-value transfers. and Bob should have 1. The main node should // show a balance of zero, and Bob should hold the total asset supply. - assertTransfers(t.t, t.tarod, []uint64{0, 0}) + assertTransfer(t.t, t.tarod, 0, 2, []uint64{0, fullAmount}) + assertTransfer(t.t, t.tarod, 1, 2, []uint64{0, fullAmount}) assertBalanceByID(t.t, t.tarod, genInfo.AssetId, 0) - assertTransfers(t.t, secondTarod, []uint64{0}) + assertTransfer(t.t, secondTarod, 0, 1, []uint64{0, fullAmount}) assertBalanceByID(t.t, secondTarod, genInfo.AssetId, fullAmount) // The second daemon should list one group with one asset. diff --git a/itest/full_value_split_test.go b/itest/full_value_split_test.go index a6faeee3c..2c6093cb7 100644 --- a/itest/full_value_split_test.go +++ b/itest/full_value_split_test.go @@ -14,12 +14,19 @@ func testFullValueSend(t *harnessTest) { // First, we'll make an normal assets with enough units to allow us to // send it around a few times. rpcAssets := mintAssetsConfirmBatch( - t, t.tarod, []*mintrpc.MintAssetRequest{simpleAssets[0]}, + t, t.tarod, []*mintrpc.MintAssetRequest{ + simpleAssets[0], issuableAssets[0], + }, ) - genInfo := rpcAssets[0].AssetGenesis + mintedAsset := rpcAssets[0] + mintedGroupAsset := rpcAssets[1] + genInfo := mintedAsset.AssetGenesis + groupGenInfo := mintedGroupAsset.AssetGenesis ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -34,13 +41,27 @@ func testFullValueSend(t *harnessTest) { require.NoError(t.t, secondTarod.stop(true)) }() + runFullValueSendTests( + ctxt, t, t.tarod, secondTarod, genInfo, mintedAsset, 0, 1, + ) + runFullValueSendTests( + ctxt, t, t.tarod, secondTarod, groupGenInfo, mintedGroupAsset, + 1, 2, + ) +} + +// runFullValueSendTests runs the full value send tests for a single asset. +func runFullValueSendTests(ctxt context.Context, t *harnessTest, alice, + bob *tarodHarness, genInfo *tarorpc.GenesisInfo, + mintedAsset *tarorpc.Asset, runIdx, numRuns int) { + // Next, we'll attempt to complete three transfers of the full value of // the asset between our main node and Bob. var ( numSends = 3 - senderTransferIdx = 0 - receiverTransferIdx = 0 - fullAmount = rpcAssets[0].Amount + senderTransferIdx = runIdx * 2 + receiverTransferIdx = runIdx * 1 + fullAmount = mintedAsset.Amount receiverAddr *tarorpc.Addr err error ) @@ -50,51 +71,43 @@ func testFullValueSend(t *harnessTest) { // start with Bob receiving the asset, then sending it back // to the main node, and so on. if i%2 == 0 { - receiverAddr, err = secondTarod.NewAddr( - ctxb, &tarorpc.NewAddrRequest{ + receiverAddr, err = bob.NewAddr( + ctxt, &tarorpc.NewAddrRequest{ AssetId: genInfo.AssetId, Amt: fullAmount, }, ) require.NoError(t.t, err) - assertAddrCreated( - t.t, secondTarod, rpcAssets[0], receiverAddr, - ) - sendResp := sendAssetsToAddr(t, t.tarod, receiverAddr) + assertAddrCreated(t.t, bob, mintedAsset, receiverAddr) + sendResp := sendAssetsToAddr(t, alice, receiverAddr) confirmAndAssertOutboundTransfer( - t, t.tarod, sendResp, genInfo.AssetId, + t, alice, sendResp, genInfo.AssetId, []uint64{0, fullAmount}, senderTransferIdx, senderTransferIdx+1, ) _ = sendProof( - t, t.tarod, secondTarod, receiverAddr.ScriptKey, - genInfo, + t, alice, bob, receiverAddr.ScriptKey, genInfo, ) senderTransferIdx++ } else { - receiverAddr, err = t.tarod.NewAddr( - ctxb, &tarorpc.NewAddrRequest{ + receiverAddr, err = alice.NewAddr( + ctxt, &tarorpc.NewAddrRequest{ AssetId: genInfo.AssetId, Amt: fullAmount, }, ) require.NoError(t.t, err) - assertAddrCreated( - t.t, t.tarod, rpcAssets[0], receiverAddr, - ) - sendResp := sendAssetsToAddr( - t, secondTarod, receiverAddr, - ) + assertAddrCreated(t.t, alice, mintedAsset, receiverAddr) + sendResp := sendAssetsToAddr(t, bob, receiverAddr) confirmAndAssertOutboundTransfer( - t, secondTarod, sendResp, genInfo.AssetId, + t, bob, sendResp, genInfo.AssetId, []uint64{0, fullAmount}, receiverTransferIdx, receiverTransferIdx+1, ) _ = sendProof( - t, secondTarod, t.tarod, receiverAddr.ScriptKey, - genInfo, + t, bob, alice, receiverAddr.ScriptKey, genInfo, ) receiverTransferIdx++ } @@ -103,9 +116,10 @@ func testFullValueSend(t *harnessTest) { // Check the final state of both nodes. The main node should list 2 // zero-value transfers. and Bob should have 1. The main node should // show a balance of zero, and Bob should hold the total asset supply. - assertTransfers(t.t, t.tarod, []uint64{0, 0}) - assertBalanceByID(t.t, t.tarod, genInfo.AssetId, 0) + assertTransfer(t.t, alice, runIdx*2, numRuns*2, []uint64{0, fullAmount}) + assertTransfer(t.t, alice, runIdx*2+1, numRuns*2, []uint64{0, fullAmount}) + assertBalanceByID(t.t, alice, genInfo.AssetId, 0) - assertTransfers(t.t, secondTarod, []uint64{0}) - assertBalanceByID(t.t, secondTarod, genInfo.AssetId, fullAmount) + assertTransfer(t.t, bob, runIdx, numRuns, []uint64{0, fullAmount}) + assertBalanceByID(t.t, bob, genInfo.AssetId, fullAmount) } diff --git a/itest/re-issuance_test.go b/itest/re-issuance_test.go index b4b456f4b..e74691b72 100644 --- a/itest/re-issuance_test.go +++ b/itest/re-issuance_test.go @@ -81,7 +81,7 @@ func testReIssuance(t *harnessTest) { // Check the state of both nodes. The first node should show one // zero-value transfer representing the send of the collectible. - assertTransfers(t.t, t.tarod, []uint64{0}) + assertTransfer(t.t, t.tarod, 0, 1, []uint64{0, 1}) assertBalanceByID(t.t, t.tarod, collectGenInfo.AssetId, 0) // The second node should show a balance of 1 for exactly one group. diff --git a/itest/round_trip_send_test.go b/itest/round_trip_send_test.go index ce3de3884..a87f93ba2 100644 --- a/itest/round_trip_send_test.go +++ b/itest/round_trip_send_test.go @@ -112,10 +112,14 @@ func testRoundTripSend(t *harnessTest) { // Check the final state of both nodes. Each node should list // one transfer, and Alice should have 3/4 of the total units. err = wait.NoError(func() error { - assertTransfers(t.t, t.tarod, []uint64{bobAmt}) - assertBalanceByID(t.t, t.tarod, genInfo.AssetId, bobAmt+aliceAmt) - - assertTransfers(t.t, secondTarod, []uint64{aliceAmt}) + assertTransfer(t.t, t.tarod, 0, 1, []uint64{bobAmt, bobAmt}) + assertBalanceByID( + t.t, t.tarod, genInfo.AssetId, bobAmt+aliceAmt, + ) + + assertTransfer( + t.t, secondTarod, 0, 1, []uint64{aliceAmt, aliceAmt}, + ) assertBalanceByID(t.t, secondTarod, genInfo.AssetId, aliceAmt) return nil From 2b4f95a4fad7c6667cd8abe155f20bf252950640 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 15:25:14 +0200 Subject: [PATCH 06/10] itest: refactor psbt script test to extract common code --- itest/psbt_test.go | 144 +++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 78 deletions(-) diff --git a/itest/psbt_test.go b/itest/psbt_test.go index 7192838e2..9937b59ce 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcwallet/waddrmgr" "github.com/lightninglabs/taro" "github.com/lightninglabs/taro/address" "github.com/lightninglabs/taro/asset" @@ -31,9 +32,12 @@ func testPsbtScriptHashLockSend(t *harnessTest) { t, t.tarod, []*mintrpc.MintAssetRequest{simpleAssets[0]}, ) + mintedAsset := rpcAssets[0] genInfo := rpcAssets[0].AssetGenesis ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -49,8 +53,9 @@ func testPsbtScriptHashLockSend(t *harnessTest) { }() var ( - alice = t.tarod - bob = secondTarod + alice = t.tarod + bob = secondTarod + numUnits = uint64(10) ) // We need to derive two keys, one for the new script key and one for @@ -67,43 +72,10 @@ func testPsbtScriptHashLockSend(t *harnessTest) { ) rootHash := tapscript.ControlBlock.RootHash(leaf1.Script) - controlBlockBytes, err := tapscript.ControlBlock.ToBytes() - require.NoError(t.t, err) - - bobAssetScriptKey, err := tapscript.TaprootKey() - require.NoError(t.t, err) - - t.Logf("Bob destination key %x (internal %x, root %x)", - bobAssetScriptKey.SerializeCompressed(), - bobScriptKey.PubKey.SerializeCompressed(), rootHash[:]) - - // Next, we'll attempt to complete a transfer with PSBTs from our main - // node to Bob. - const numUnits = 10 - bobAddr, err := bob.NewAddr(ctxb, &tarorpc.NewAddrRequest{ - AssetId: genInfo.AssetId, - Amt: numUnits, - ScriptKey: &tarorpc.ScriptKey{ - PubKey: schnorr.SerializePubKey(bobAssetScriptKey), - KeyDesc: lndKeyDescToTaro(bobScriptKey.RawKey), - TapTweak: rootHash[:], - }, - InternalKey: lndKeyDescToTaro(bobInternalKey), - }) - require.NoError(t.t, err) - assertAddrCreated(t.t, bob, rpcAssets[0], bobAddr) - - // Send the asset to Bob using the script key with an actual script - // tree. - sendResp := sendAssetsToAddr(t, alice, bobAddr) - - changeUnits := rpcAssets[0].Amount - numUnits - confirmAndAssertOutboundTransfer( - t, alice, sendResp, genInfo.AssetId, - []uint64{changeUnits, numUnits}, 0, 1, + sendToTapscriptAddr( + ctxt, t, alice, bob, numUnits, genInfo, mintedAsset, + bobScriptKey, bobInternalKey, tapscript, rootHash, ) - _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) - assertNonInteractiveRecvComplete(t, bob, 1) // Now try to send back those assets using the PSBT flow. aliceAddr, err := alice.NewAddr(ctxb, &tarorpc.NewAddrRequest{ @@ -124,6 +96,8 @@ func testPsbtScriptHashLockSend(t *harnessTest) { // We don't need to sign anything as we're going to spend with a // pre-image to the script lock. + controlBlockBytes, err := tapscript.ControlBlock.ToBytes() + require.NoError(t.t, err) senderOut := fundedPacket.Outputs[0].Asset senderOut.PrevWitnesses[0].TxWitness = [][]byte{ preImage, leaf1.Script, controlBlockBytes, @@ -146,7 +120,7 @@ func testPsbtScriptHashLockSend(t *harnessTest) { require.NoError(t.t, err) // Now we'll attempt to complete the transfer. - sendResp, err = bob.AnchorVirtualPsbts( + sendResp, err := bob.AnchorVirtualPsbts( ctxb, &wrpc.AnchorVirtualPsbtsRequest{ VirtualPsbts: [][]byte{b.Bytes()}, }, @@ -179,9 +153,12 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { t, t.tarod, []*mintrpc.MintAssetRequest{simpleAssets[0]}, ) + mintedAsset := rpcAssets[0] genInfo := rpcAssets[0].AssetGenesis ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -197,8 +174,9 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { }() var ( - alice = t.tarod - bob = secondTarod + alice = t.tarod + bob = secondTarod + numUnits = uint64(10) ) // We need to derive two keys, one for the new script key and one for @@ -216,43 +194,10 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { ) rootHash := tapscript.ControlBlock.RootHash(leaf2.Script) - controlBlockBytes, err := tapscript.ControlBlock.ToBytes() - require.NoError(t.t, err) - - bobAssetScriptKey, err := tapscript.TaprootKey() - require.NoError(t.t, err) - - t.Logf("Bob destination key %x (internal %x, root %x)", - bobAssetScriptKey.SerializeCompressed(), - bobScriptKey.PubKey.SerializeCompressed(), rootHash[:]) - - // Next, we'll attempt to complete a transfer with PSBTs from our main - // node to Bob. - const numUnits = 10 - bobAddr, err := bob.NewAddr(ctxb, &tarorpc.NewAddrRequest{ - AssetId: genInfo.AssetId, - Amt: numUnits, - ScriptKey: &tarorpc.ScriptKey{ - PubKey: schnorr.SerializePubKey(bobAssetScriptKey), - KeyDesc: lndKeyDescToTaro(bobScriptKey.RawKey), - TapTweak: rootHash[:], - }, - InternalKey: lndKeyDescToTaro(bobInternalKey), - }) - require.NoError(t.t, err) - assertAddrCreated(t.t, bob, rpcAssets[0], bobAddr) - - // Send the asset to Bob using the script key with an actual script - // tree. - sendResp := sendAssetsToAddr(t, alice, bobAddr) - - changeUnits := rpcAssets[0].Amount - numUnits - confirmAndAssertOutboundTransfer( - t, alice, sendResp, genInfo.AssetId, - []uint64{changeUnits, numUnits}, 0, 1, + sendToTapscriptAddr( + ctxt, t, alice, bob, numUnits, genInfo, mintedAsset, + bobScriptKey, bobInternalKey, tapscript, rootHash, ) - _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) - assertNonInteractiveRecvComplete(t, bob, 1) // Now try to send back those assets using the PSBT flow. aliceAddr, err := alice.NewAddr(ctxb, &tarorpc.NewAddrRequest{ @@ -273,6 +218,8 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { // We can now ask the wallet to sign the script path, since we only need // a signature. + controlBlockBytes, err := tapscript.ControlBlock.ToBytes() + require.NoError(t.t, err) fundedPacket.Inputs[0].TaprootMerkleRoot = rootHash[:] fundedPacket.Inputs[0].TaprootLeafScript = []*psbt.TaprootTapLeafScript{ { @@ -297,7 +244,7 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { require.Contains(t.t, signedResp.SignedInputs, uint32(0)) // Now we'll attempt to complete the transfer. - sendResp, err = bob.AnchorVirtualPsbts( + sendResp, err := bob.AnchorVirtualPsbts( ctxb, &wrpc.AnchorVirtualPsbtsRequest{ VirtualPsbts: [][]byte{signedResp.SignedPsbt}, }, @@ -976,3 +923,44 @@ func deriveKeys(t *testing.T, tarod *tarodHarness) (asset.ScriptKey, return *scriptKey, internalKeyLnd } + +func sendToTapscriptAddr(ctx context.Context, t *harnessTest, alice, + bob *tarodHarness, numUnits uint64, genInfo *tarorpc.GenesisInfo, + mintedAsset *tarorpc.Asset, bobScriptKey asset.ScriptKey, + bobInternalKey keychain.KeyDescriptor, tapscript *waddrmgr.Tapscript, + rootHash []byte) { + + bobAssetScriptKey, err := tapscript.TaprootKey() + require.NoError(t.t, err) + + t.Logf("Bob destination key %x (internal %x, root %x)", + bobAssetScriptKey.SerializeCompressed(), + bobScriptKey.PubKey.SerializeCompressed(), rootHash) + + // Next, we'll attempt to complete a transfer with PSBTs from our main + // node to Bob. + bobAddr, err := bob.NewAddr(ctx, &tarorpc.NewAddrRequest{ + AssetId: genInfo.AssetId, + Amt: numUnits, + ScriptKey: &tarorpc.ScriptKey{ + PubKey: schnorr.SerializePubKey(bobAssetScriptKey), + KeyDesc: lndKeyDescToTaro(bobScriptKey.RawKey), + TapTweak: rootHash, + }, + InternalKey: lndKeyDescToTaro(bobInternalKey), + }) + require.NoError(t.t, err) + assertAddrCreated(t.t, bob, mintedAsset, bobAddr) + + // Send the asset to Bob using the script key with an actual script + // tree. + sendResp := sendAssetsToAddr(t, alice, bobAddr) + + changeUnits := mintedAsset.Amount - numUnits + confirmAndAssertOutboundTransfer( + t, alice, sendResp, genInfo.AssetId, + []uint64{changeUnits, numUnits}, 0, 1, + ) + _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) + assertNonInteractiveRecvComplete(t, bob, 1) +} From 51dab479df9bb94b7d7f5c63d826f2b77c360143 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 15:25:31 +0200 Subject: [PATCH 07/10] itest: change one psbt script test to use grouped assets Since both psbt script tests are very similar in their nature and only differ in the tapscript path taken when spending the asset, we get extra coverage when using a grouped asset for one of them. --- itest/psbt_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/itest/psbt_test.go b/itest/psbt_test.go index 9937b59ce..dcd336bfd 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -150,7 +150,7 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { // First, we'll make a normal asset with enough units to allow us to // send it around a few times. rpcAssets := mintAssetsConfirmBatch( - t, t.tarod, []*mintrpc.MintAssetRequest{simpleAssets[0]}, + t, t.tarod, []*mintrpc.MintAssetRequest{issuableAssets[0]}, ) mintedAsset := rpcAssets[0] From 4bff5f9dbd0cfe722eef03d13b5ffd373548c78e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 16:36:48 +0200 Subject: [PATCH 08/10] itest: refactor psbt tests to extract more common code --- itest/psbt_test.go | 179 +++++++++++++++++---------------------------- 1 file changed, 69 insertions(+), 110 deletions(-) diff --git a/itest/psbt_test.go b/itest/psbt_test.go index dcd336bfd..bd42753e8 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -295,6 +295,8 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { chainParams := &address.RegressionNetTaro ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -340,7 +342,7 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { // our sender node to our receiver, using the full amount. fundResp := fundPacket(t, sender, vPkt) signResp, err := sender.SignVirtualPsbt( - ctxb, &wrpc.SignVirtualPsbtRequest{ + ctxt, &wrpc.SignVirtualPsbtRequest{ FundedPsbt: fundResp.FundedPsbt, }, ) @@ -348,7 +350,7 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { // Now we'll attempt to complete the transfer. sendResp, err := sender.AnchorVirtualPsbts( - ctxb, &wrpc.AnchorVirtualPsbtsRequest{ + ctxt, &wrpc.AnchorVirtualPsbtsRequest{ VirtualPsbts: [][]byte{signResp.SignedPsbt}, }, ) @@ -371,7 +373,7 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { ) senderAssets, err := sender.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) @@ -387,7 +389,7 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { require.Len(t.t, senderAssets.Assets, numSenderAssets) receiverAssets, err := receiver.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) require.Len(t.t, receiverAssets.Assets, numReceiverAssets) @@ -398,27 +400,12 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { } // Finally, make sure we can still send out the passive asset. + passiveAsset := rpcAssets[1] passiveGen := rpcAssets[1].AssetGenesis - bobAddr, err := secondTarod.NewAddr( - ctxb, &tarorpc.NewAddrRequest{ - AssetId: passiveGen.AssetId, - Amt: rpcAssets[1].Amount, - }, - ) - require.NoError(t.t, err) - - assertAddrCreated(t.t, secondTarod, rpcAssets[1], bobAddr) - sendResp := sendAssetsToAddr(t, t.tarod, bobAddr) - confirmAndAssertOutboundTransfer( - t, t.tarod, sendResp, passiveGen.AssetId, - []uint64{0, rpcAssets[1].Amount}, 2, 3, + sendAssetAndAssert( + ctxt, t, t.tarod, secondTarod, passiveAsset.Amount, 0, + passiveGen, passiveAsset, 2, 3, 1, ) - _ = sendProof( - t, t.tarod, secondTarod, bobAddr.ScriptKey, passiveGen, - ) - - // There's only one non-interactive receive event. - assertNonInteractiveRecvComplete(t, secondTarod, 1) } // testPsbtInteractiveSplitSend tests that we can properly send assets back @@ -448,6 +435,8 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { chainParams := &address.RegressionNetTaro ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -509,7 +498,7 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { // our sender node to our receiver, using the partial amount. fundResp := fundPacket(t, sender, vPkt) signResp, err := sender.SignVirtualPsbt( - ctxb, &wrpc.SignVirtualPsbtRequest{ + ctxt, &wrpc.SignVirtualPsbtRequest{ FundedPsbt: fundResp.FundedPsbt, }, ) @@ -517,7 +506,7 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { // Now we'll attempt to complete the transfer. sendResp, err := sender.AnchorVirtualPsbts( - ctxb, &wrpc.AnchorVirtualPsbtsRequest{ + ctxt, &wrpc.AnchorVirtualPsbtsRequest{ VirtualPsbts: [][]byte{signResp.SignedPsbt}, }, ) @@ -535,7 +524,7 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { ) senderAssets, err := sender.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) @@ -559,34 +548,19 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { require.Len(t.t, senderAssets.Assets, numSenderAssets) receiverAssets, err := receiver.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) require.Len(t.t, receiverAssets.Assets, numReceiverAssets) } // Finally, make sure we can still send out the passive asset. + passiveAsset := rpcAssets[1] passiveGen := rpcAssets[1].AssetGenesis - bobAddr, err := secondTarod.NewAddr( - ctxb, &tarorpc.NewAddrRequest{ - AssetId: passiveGen.AssetId, - Amt: rpcAssets[1].Amount, - }, - ) - require.NoError(t.t, err) - - assertAddrCreated(t.t, secondTarod, rpcAssets[1], bobAddr) - sendResp := sendAssetsToAddr(t, t.tarod, bobAddr) - confirmAndAssertOutboundTransfer( - t, t.tarod, sendResp, passiveGen.AssetId, - []uint64{0, rpcAssets[1].Amount}, 2, 3, + sendAssetAndAssert( + ctxt, t, t.tarod, secondTarod, passiveAsset.Amount, 0, + passiveGen, passiveAsset, 2, 3, 1, ) - _ = sendProof( - t, t.tarod, secondTarod, bobAddr.ScriptKey, passiveGen, - ) - - // There's only one non-interactive receive event. - assertNonInteractiveRecvComplete(t, secondTarod, 1) } // testPsbtInteractiveTapscriptSibling tests that we can send assets to an @@ -602,6 +576,8 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { chainParams := &address.RegressionNetTaro ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -647,7 +623,7 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { // bob, using the partial amount. fundResp := fundPacket(t, alice, vPkt) signResp, err := alice.SignVirtualPsbt( - ctxb, &wrpc.SignVirtualPsbtRequest{ + ctxt, &wrpc.SignVirtualPsbtRequest{ FundedPsbt: fundResp.FundedPsbt, }, ) @@ -655,7 +631,7 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { // Now we'll attempt to complete the transfer. sendResp, err := alice.AnchorVirtualPsbts( - ctxb, &wrpc.AnchorVirtualPsbtsRequest{ + ctxt, &wrpc.AnchorVirtualPsbtsRequest{ VirtualPsbts: [][]byte{signResp.SignedPsbt}, }, ) @@ -671,13 +647,13 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { ) senderAssets, err := alice.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) require.Len(t.t, senderAssets.Assets, 1) receiverAssets, err := bob.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) require.Len(t.t, receiverAssets.Assets, 1) @@ -691,23 +667,10 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) { t.Logf("Got bob assets: %s", assetsJSON) // And finally, make sure we can spend the asset again. - aliceAddr, err := alice.NewAddr(ctxb, &tarorpc.NewAddrRequest{ - AssetId: genInfo.AssetId, - Amt: sendAmt / 2, - }) - require.NoError(t.t, err) - - assertAddrCreated(t.t, alice, rpcAssets[0], aliceAddr) - sendResp = sendAssetsToAddr(t, bob, aliceAddr) - confirmAndAssertOutboundTransfer( - t, bob, sendResp, genInfo.AssetId, - []uint64{sendAmt / 2, sendAmt / 2}, 0, 1, + sendAssetAndAssert( + ctxt, t, bob, alice, sendAmt/2, sendAmt/2, genInfo, + rpcAssets[0], 0, 1, 1, ) - _ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo) - - // There's only one receive event (since only non-interactive sends - // appear in that RPC output). - assertNonInteractiveRecvComplete(t, alice, 1) } // testPsbtMultiSend tests that we can properly send assets to multiple @@ -737,6 +700,8 @@ func testPsbtMultiSend(t *harnessTest) { chainParams := &address.RegressionNetTaro ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() // Now that we have the asset created, we'll make a new node that'll // serve as the node which'll receive the assets. @@ -800,7 +765,7 @@ func testPsbtMultiSend(t *harnessTest) { // our sender node to our receiver, using the partial amount. fundResp := fundPacket(t, sender, vPkt) signResp, err := sender.SignVirtualPsbt( - ctxb, &wrpc.SignVirtualPsbtRequest{ + ctxt, &wrpc.SignVirtualPsbtRequest{ FundedPsbt: fundResp.FundedPsbt, }, ) @@ -808,7 +773,7 @@ func testPsbtMultiSend(t *harnessTest) { // Now we'll attempt to complete the transfer. sendResp, err := sender.AnchorVirtualPsbts( - ctxb, &wrpc.AnchorVirtualPsbtsRequest{ + ctxt, &wrpc.AnchorVirtualPsbtsRequest{ VirtualPsbts: [][]byte{signResp.SignedPsbt}, }, ) @@ -833,65 +798,32 @@ func testPsbtMultiSend(t *harnessTest) { ) senderAssets, err := sender.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) require.Len(t.t, senderAssets.Assets, 4) receiverAssets, err := receiver.ListAssets( - ctxb, &tarorpc.ListAssetRequest{}, + ctxt, &tarorpc.ListAssetRequest{}, ) require.NoError(t.t, err) require.Len(t.t, receiverAssets.Assets, 2) // Next, we make sure we can still send out the passive asset. + passiveAsset := rpcAssets[1] passiveGen := rpcAssets[1].AssetGenesis - bobAddr, err := secondTarod.NewAddr( - ctxb, &tarorpc.NewAddrRequest{ - AssetId: passiveGen.AssetId, - Amt: rpcAssets[1].Amount, - }, - ) - require.NoError(t.t, err) - - assertAddrCreated(t.t, secondTarod, rpcAssets[1], bobAddr) - sendResp = sendAssetsToAddr(t, t.tarod, bobAddr) - confirmAndAssertOutboundTransfer( - t, t.tarod, sendResp, passiveGen.AssetId, - []uint64{0, rpcAssets[1].Amount}, 1, 2, - ) - _ = sendProof( - t, t.tarod, secondTarod, bobAddr.ScriptKey, passiveGen, + sendAssetAndAssert( + ctxt, t, t.tarod, secondTarod, passiveAsset.Amount, 0, + passiveGen, passiveAsset, 1, 2, 1, ) - // There's only one receive event (since only non-interactive sends - // appear in that RPC output). - assertNonInteractiveRecvComplete(t, secondTarod, 1) - // And finally, we make sure that we can send out one of the asset UTXOs // that shared the anchor output and the other one is treated as a // passive asset. - bobAddr, err = secondTarod.NewAddr( - ctxb, &tarorpc.NewAddrRequest{ - AssetId: genInfo.AssetId, - Amt: outputAmounts[2], - }, + sendAssetAndAssert( + ctxt, t, t.tarod, secondTarod, outputAmounts[2], 0, + genInfo, rpcAssets[0], 2, 3, 2, ) - require.NoError(t.t, err) - - assertAddrCreated(t.t, secondTarod, rpcAssets[0], bobAddr) - sendResp = sendAssetsToAddr(t, t.tarod, bobAddr) - confirmAndAssertOutboundTransfer( - t, t.tarod, sendResp, genInfo.AssetId, - []uint64{0, outputAmounts[2]}, 2, 3, - ) - _ = sendProof( - t, t.tarod, secondTarod, bobAddr.ScriptKey, genInfo, - ) - - // There are now two receive events (since only non-interactive sends - // appear in that RPC output). - assertNonInteractiveRecvComplete(t, secondTarod, 2) } func deriveKeys(t *testing.T, tarod *tarodHarness) (asset.ScriptKey, @@ -964,3 +896,30 @@ func sendToTapscriptAddr(ctx context.Context, t *harnessTest, alice, _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) assertNonInteractiveRecvComplete(t, bob, 1) } + +func sendAssetAndAssert(ctx context.Context, t *harnessTest, alice, + bob *tarodHarness, numUnits, change uint64, + genInfo *tarorpc.GenesisInfo, mintedAsset *tarorpc.Asset, + outTransferIdx, numOutTransfers, numInTransfers int) { + + // And finally, we make sure that we can send out one of the asset UTXOs + // that shared the anchor output and the other one is treated as a + // passive asset. + bobAddr, err := bob.NewAddr(ctx, &tarorpc.NewAddrRequest{ + AssetId: genInfo.AssetId, + Amt: numUnits, + }) + require.NoError(t.t, err) + + assertAddrCreated(t.t, bob, mintedAsset, bobAddr) + sendResp := sendAssetsToAddr(t, alice, bobAddr) + confirmAndAssertOutboundTransfer( + t, alice, sendResp, genInfo.AssetId, + []uint64{change, numUnits}, outTransferIdx, numOutTransfers, + ) + _ = sendProof(t, alice, bob, bobAddr.ScriptKey, genInfo) + + // There are now two receive events (since only non-interactive sends + // appear in that RPC output). + assertNonInteractiveRecvComplete(t, bob, numInTransfers) +} From bc9f53b2dcfbfaada2ca1cdda7d6f1be6821764a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 16:40:16 +0200 Subject: [PATCH 09/10] itest: refactor psbt tests to use grouped assets --- itest/psbt_test.go | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/itest/psbt_test.go b/itest/psbt_test.go index bd42753e8..e4b1ab4ca 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -292,7 +292,6 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { ) genInfo := rpcAssets[0].AssetGenesis - chainParams := &address.RegressionNetTaro ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) @@ -311,11 +310,23 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { require.NoError(t.t, secondTarod.stop(true)) }() + runPsbtInteractiveFullValueSendTest( + ctxt, t, t.tarod, secondTarod, genInfo, rpcAssets[0], + rpcAssets[1], 1, 0, + ) + +} + +func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, + alice, bob *tarodHarness, genInfo *tarorpc.GenesisInfo, + mintedAsset, passiveAsset *tarorpc.Asset, numRuns, runIdx int) { + var ( - sender = t.tarod - receiver = secondTarod - id [32]byte - fullAmt = rpcAssets[0].Amount + sender = alice + receiver = bob + id [32]byte + fullAmt = mintedAsset.Amount + chainParams = &address.RegressionNetTaro ) copy(id[:], genInfo.AssetId) @@ -382,7 +393,7 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { // has the passive asset left. numSenderAssets := 1 numReceiverAssets := 1 - if sender == secondTarod { + if sender == bob { numSenderAssets = 0 numReceiverAssets = 2 } @@ -400,10 +411,9 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { } // Finally, make sure we can still send out the passive asset. - passiveAsset := rpcAssets[1] - passiveGen := rpcAssets[1].AssetGenesis + passiveGen := passiveAsset.AssetGenesis sendAssetAndAssert( - ctxt, t, t.tarod, secondTarod, passiveAsset.Amount, 0, + ctxt, t, alice, bob, passiveAsset.Amount, 0, passiveGen, passiveAsset, 2, 3, 1, ) } From 53f24c23d00636e7ff6b46c017467286916e2556 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 5 May 2023 16:59:24 +0200 Subject: [PATCH 10/10] itest: refactor more psbt tests to use grouped assets --- itest/psbt_test.go | 150 ++++++++++++++++++++++++++++++++----- itest/test_list_on_test.go | 16 +++- 2 files changed, 145 insertions(+), 21 deletions(-) diff --git a/itest/psbt_test.go b/itest/psbt_test.go index e4b1ab4ca..976278a52 100644 --- a/itest/psbt_test.go +++ b/itest/psbt_test.go @@ -268,9 +268,10 @@ func testPsbtScriptCheckSigSend(t *harnessTest) { t.Logf("Got alice assets: %s", assetsJSON) } -// testPsbtInteractiveFullValueSend tests that we can properly send assets back -// and forth, using the full amount, between nodes with the use of PSBTs. -func testPsbtInteractiveFullValueSend(t *harnessTest) { +// testPsbtNormalInteractiveFullValueSend tests that we can properly send normal +// assets back and forth, using the full amount, between nodes with the use of +// PSBTs. +func testPsbtNormalInteractiveFullValueSend(t *harnessTest) { // First, we'll make a normal asset with a bunch of units that we are // going to send backand forth. We're also minting a passive asset that // should remain where it is. @@ -291,7 +292,8 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { }, ) - genInfo := rpcAssets[0].AssetGenesis + mintedAsset := rpcAssets[0] + genInfo := mintedAsset.AssetGenesis ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) @@ -311,15 +313,66 @@ func testPsbtInteractiveFullValueSend(t *harnessTest) { }() runPsbtInteractiveFullValueSendTest( - ctxt, t, t.tarod, secondTarod, genInfo, rpcAssets[0], - rpcAssets[1], 1, 0, + ctxt, t, t.tarod, secondTarod, genInfo, mintedAsset, + rpcAssets[1], + ) +} + +// testPsbtGroupedInteractiveFullValueSend tests that we can properly send +// grouped assets back and forth, using the full amount, between nodes with the +// use of PSBTs. +func testPsbtGroupedInteractiveFullValueSend(t *harnessTest) { + // First, we'll make a normal asset with a bunch of units that we are + // going to send backand forth. We're also minting a passive asset that + // should remain where it is. + rpcAssets := mintAssetsConfirmBatch( + t, t.tarod, []*mintrpc.MintAssetRequest{ + issuableAssets[0], + // Our "passive" asset. + { + Asset: &mintrpc.MintAsset{ + AssetType: tarorpc.AssetType_NORMAL, + Name: "itestbuxx-passive", + AssetMeta: &tarorpc.AssetMeta{ + Data: []byte("some metadata"), + }, + Amount: 123, + }, + }, + }, ) + mintedAsset := rpcAssets[0] + genInfo := mintedAsset.AssetGenesis + + ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() + + // Now that we have the asset created, we'll make a new node that'll + // serve as the node which'll receive the assets. + secondTarod := setupTarodHarness( + t.t, t, t.lndHarness.Bob, t.universeServer, + func(params *tarodHarnessParams) { + params.startupSyncNode = t.tarod + params.startupSyncNumAssets = len(rpcAssets) + }, + ) + defer func() { + require.NoError(t.t, secondTarod.stop(true)) + }() + + runPsbtInteractiveFullValueSendTest( + ctxt, t, t.tarod, secondTarod, genInfo, mintedAsset, + rpcAssets[1], + ) } +// runPsbtInteractiveFullValueSendTest runs a single test of sending an asset +// back and forth between two nodes using PSBTs and the full amount. func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, alice, bob *tarodHarness, genInfo *tarorpc.GenesisInfo, - mintedAsset, passiveAsset *tarorpc.Asset, numRuns, runIdx int) { + mintedAsset, passiveAsset *tarorpc.Asset) { var ( sender = alice @@ -418,9 +471,60 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest, ) } -// testPsbtInteractiveSplitSend tests that we can properly send assets back -// and forth, using the full amount, between nodes with the use of PSBTs. -func testPsbtInteractiveSplitSend(t *harnessTest) { +// testPsbtNormalInteractiveSplitSend tests that we can properly send normal +// assets back and forth, using the full amount, between nodes with the use of +// PSBTs. +func testPsbtNormalInteractiveSplitSend(t *harnessTest) { + // First, we'll make a normal asset with a bunch of units that we are + // going to send backand forth. We're also minting a passive asset that + // should remain where it is. + rpcAssets := mintAssetsConfirmBatch( + t, t.tarod, []*mintrpc.MintAssetRequest{ + simpleAssets[0], + // Our "passive" asset. + { + Asset: &mintrpc.MintAsset{ + AssetType: tarorpc.AssetType_NORMAL, + Name: "itestbuxx-passive", + AssetMeta: &tarorpc.AssetMeta{ + Data: []byte("some metadata"), + }, + Amount: 123, + }, + }, + }, + ) + + mintedAsset := rpcAssets[0] + genInfo := rpcAssets[0].AssetGenesis + + ctxb := context.Background() + ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) + defer cancel() + + // Now that we have the asset created, we'll make a new node that'll + // serve as the node which'll receive the assets. + secondTarod := setupTarodHarness( + t.t, t, t.lndHarness.Bob, t.universeServer, + func(params *tarodHarnessParams) { + params.startupSyncNode = t.tarod + params.startupSyncNumAssets = len(rpcAssets) + }, + ) + defer func() { + require.NoError(t.t, secondTarod.stop(true)) + }() + + runPsbtInteractiveSplitSendTest( + ctxt, t, t.tarod, secondTarod, genInfo, mintedAsset, + rpcAssets[1], + ) +} + +// testPsbtGroupedInteractiveSplitSend tests that we can properly send grouped +// assets back and forth, using the full amount, between nodes with the use of +// PSBTs. +func testPsbtGroupedInteractiveSplitSend(t *harnessTest) { // First, we'll make a normal asset with a bunch of units that we are // going to send backand forth. We're also minting a passive asset that // should remain where it is. @@ -441,8 +545,8 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { }, ) + mintedAsset := rpcAssets[0] genInfo := rpcAssets[0].AssetGenesis - chainParams := &address.RegressionNetTaro ctxb := context.Background() ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout) @@ -461,12 +565,25 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { require.NoError(t.t, secondTarod.stop(true)) }() + runPsbtInteractiveSplitSendTest( + ctxt, t, t.tarod, secondTarod, genInfo, mintedAsset, + rpcAssets[1], + ) +} + +// runPsbtInteractiveSplitSendTest runs a single test of sending an asset +// back and forth between two nodes using PSBTs and a split amount. +func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest, + alice, bob *tarodHarness, genInfo *tarorpc.GenesisInfo, + mintedAsset, passiveAsset *tarorpc.Asset) { + var ( - sender = t.tarod - receiver = secondTarod - senderSum = rpcAssets[0].Amount + sender = alice + receiver = bob + senderSum = mintedAsset.Amount receiverSum = uint64(0) id [32]byte + chainParams = &address.RegressionNetTaro ) copy(id[:], genInfo.AssetId) @@ -565,10 +682,9 @@ func testPsbtInteractiveSplitSend(t *harnessTest) { } // Finally, make sure we can still send out the passive asset. - passiveAsset := rpcAssets[1] - passiveGen := rpcAssets[1].AssetGenesis + passiveGen := passiveAsset.AssetGenesis sendAssetAndAssert( - ctxt, t, t.tarod, secondTarod, passiveAsset.Amount, 0, + ctxt, t, alice, bob, passiveAsset.Amount, 0, passiveGen, passiveAsset, 2, 3, 1, ) } diff --git a/itest/test_list_on_test.go b/itest/test_list_on_test.go index 845b7b309..3b35a2fd9 100644 --- a/itest/test_list_on_test.go +++ b/itest/test_list_on_test.go @@ -79,12 +79,20 @@ var testCases = []*testCase{ test: testPsbtScriptCheckSigSend, }, { - name: "psbt interactive full value send", - test: testPsbtInteractiveFullValueSend, + name: "psbt normal interactive full value send", + test: testPsbtNormalInteractiveFullValueSend, }, { - name: "psbt interactive split send", - test: testPsbtInteractiveSplitSend, + name: "psbt grouped interactive full value send", + test: testPsbtGroupedInteractiveFullValueSend, + }, + { + name: "psbt normal interactive split send", + test: testPsbtNormalInteractiveSplitSend, + }, + { + name: "psbt grouped interactive split send", + test: testPsbtGroupedInteractiveSplitSend, }, { name: "psbt interactive tapscript sibling",