diff --git a/go.mod b/go.mod index 19987e8a7..c647825a7 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/lightninglabs/pool v0.6.5-beta.0.20250305125211-4e860ec4e77f github.com/lightninglabs/pool/auctioneerrpc v1.1.3-0.20250305125211-4e860ec4e77f github.com/lightninglabs/pool/poolrpc v1.0.1-0.20250305125211-4e860ec4e77f - github.com/lightninglabs/taproot-assets v0.5.2-0.20250424162728-b6000498210d + github.com/lightninglabs/taproot-assets v0.5.2-0.20250501125658-7b383050ae89 github.com/lightningnetwork/lnd v0.19.0-beta.rc3 github.com/lightningnetwork/lnd/cert v1.2.2 github.com/lightningnetwork/lnd/clock v1.1.1 diff --git a/go.sum b/go.sum index 3443d3720..957154320 100644 --- a/go.sum +++ b/go.sum @@ -1171,8 +1171,8 @@ github.com/lightninglabs/pool/poolrpc v1.0.1-0.20250305125211-4e860ec4e77f h1:5p github.com/lightninglabs/pool/poolrpc v1.0.1-0.20250305125211-4e860ec4e77f/go.mod h1:lGs2hSVZ+GFpdv3btaIl9icG5/gz7BBRfvmD2iqqNl0= github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display h1:w7FM5LH9Z6CpKxl13mS48idsu6F+cEZf0lkyiV+Dq9g= github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -github.com/lightninglabs/taproot-assets v0.5.2-0.20250424162728-b6000498210d h1:8WcOFToO9iY62c6ghbAaJfVP8qudzdrK89OXiOri9K4= -github.com/lightninglabs/taproot-assets v0.5.2-0.20250424162728-b6000498210d/go.mod h1:6kQm7VC4yWAwczJaxfOWlCOQ4TuzfCLUkGKBwVONN7k= +github.com/lightninglabs/taproot-assets v0.5.2-0.20250501125658-7b383050ae89 h1:7GvIZniLBZC2/kAJDJu9HFwpMY1I9pUehVwp2AvFSpE= +github.com/lightninglabs/taproot-assets v0.5.2-0.20250501125658-7b383050ae89/go.mod h1:wna/k7WVVj2GixVEDuhdremUo7hBwhfzHl11YGw9g/E= github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY= github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= github.com/lightningnetwork/lnd v0.19.0-beta.rc3 h1:XWMlyZvBrp69AnQqrshLOOPZjOl4hFWR1RD4ceCXt9k= diff --git a/itest/assets_test.go b/itest/assets_test.go index 8ab67e598..cbe6b0731 100644 --- a/itest/assets_test.go +++ b/itest/assets_test.go @@ -11,8 +11,6 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" @@ -87,7 +85,7 @@ func createTestAssetNetwork(t *harnessTest, net *NetworkHarness, charlieTap, fundingScriptTree := tapscript.NewChannelFundingScriptTree() fundingScriptKey := fundingScriptTree.TaprootKey - fundingScriptTreeBytes := fundingScriptKey.SerializeCompressed() + fundingScriptKeyBytes := fundingScriptKey.SerializeCompressed() // We need to send some assets to Dave, so he can fund an asset channel // with Yara. @@ -207,54 +205,52 @@ func createTestAssetNetwork(t *harnessTest, net *NetworkHarness, charlieTap, daveAssetBalance := assetSendAmount - daveFundingAmount erinAssetBalance := assetSendAmount - erinFundingAmount - // After opening the channels, the asset balance of the funding nodes - // should have been decreased with the funding amount. The asset with - // the funding output was imported into the asset DB but are kept out of - // the balance reporting by tapd. - assertAssetBalance(t.t, charlieTap, assetID, charlieAssetBalance) - assertAssetBalance(t.t, daveTap, assetID, daveAssetBalance) - assertAssetBalance(t.t, erinTap, assetID, erinAssetBalance) - - // There should only be a single asset piece for Charlie, the one in the - // channel. - assertNumAssetOutputs(t.t, charlieTap, assetID, 1) - assertAssetExists( - t.t, charlieTap, assetID, charlieFundingAmount, - fundingScriptKey, false, true, true, + // Assert that we see the funding outputs in the wallet. + itest.AssertBalances( + t.t, charlieTap, charlieFundingAmount, + itest.WithAssetID(assetID), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes), ) - - // Dave should just have one asset piece, since we used the full amount - // for the channel opening. - assertNumAssetOutputs(t.t, daveTap, assetID, 1) - assertAssetExists( - t.t, daveTap, assetID, daveFundingAmount, fundingScriptKey, - false, true, true, + itest.AssertBalances( + t.t, daveTap, daveFundingAmount, itest.WithAssetID(assetID), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes), + ) + itest.AssertBalances( + t.t, erinTap, erinFundingAmount, itest.WithAssetID(assetID), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes), ) - // Erin should just have two equally sized asset pieces, the change and - // the funding transaction. - assertNumAssetOutputs(t.t, erinTap, assetID, 2) - assertAssetExists( - t.t, erinTap, assetID, assetSendAmount-erinFundingAmount, nil, - true, false, false, + // After opening the channels, the asset balance of the funding nodes + // should have been decreased with the funding amount. + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), ) - assertAssetExists( - t.t, erinTap, assetID, erinFundingAmount, fundingScriptKey, - false, true, true, + itest.AssertBalances( + t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID), ) // Assert that the proofs for both channels has been uploaded to the // designated Universe server. assertUniverseProofExists( - t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes, + t.t, universeTap, assetID, groupKey, fundingScriptKeyBytes, fmt.Sprintf("%v:%v", fundRespCD.Txid, fundRespCD.OutputIndex), ) assertUniverseProofExists( - t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes, + t.t, universeTap, assetID, groupKey, fundingScriptKeyBytes, fmt.Sprintf("%v:%v", fundRespDY.Txid, fundRespDY.OutputIndex), ) assertUniverseProofExists( - t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes, + t.t, universeTap, assetID, groupKey, fundingScriptKeyBytes, fmt.Sprintf("%v:%v", fundRespEF.Txid, fundRespEF.OutputIndex), ) @@ -433,71 +429,74 @@ func createTestAssetNetworkGroupKey(ctx context.Context, t *harnessTest, ) require.NoError(t.t, err) fundingScriptKey1 := fundingTree1.TaprootKey - fundingScriptTreeBytes1 := fundingScriptKey1.SerializeCompressed() + fundingScriptKeyBytes1 := fundingScriptKey1.SerializeCompressed() fundingTree2, err := tapscript.NewChannelFundingScriptTreeUniqueID( id2, ) require.NoError(t.t, err) fundingScriptKey2 := fundingTree2.TaprootKey - fundingScriptTreeBytes2 := fundingScriptKey2.SerializeCompressed() - - // TODO(guggero): Those asset balances should be 1, 1, 0, 0 - // respectively, but because we now have unique script keys, we need - // https://github.com/lightninglabs/taproot-assets/pull/1198 first. - assertAssetBalance(t.t, charlieTap, assetID1, 25001) - assertAssetBalance(t.t, charlieTap, assetID2, 25001) - assertAssetBalance(t.t, erinTap, assetID1, 25000) - assertAssetBalance(t.t, erinTap, assetID2, 25000) - - // There should be two asset pieces for Charlie for both asset IDs, one - // in the channel and one with a single unit from the burn. - assertNumAssetOutputs(t.t, charlieTap, assetID1, 2) - assertNumAssetOutputs(t.t, charlieTap, assetID2, 2) - assertAssetExists( - t.t, charlieTap, assetID1, charlieFundingAmount/2, - fundingScriptKey1, false, true, true, - ) - assertAssetExists( - t.t, charlieTap, assetID1, 1, nil, true, false, false, - ) - assertAssetExists( - t.t, charlieTap, assetID2, charlieFundingAmount/2, - fundingScriptKey2, false, true, true, - ) - assertAssetExists( - t.t, charlieTap, assetID2, 1, nil, true, false, false, - ) - - // Erin should just have one output for each asset ID, the one in the - // channel. - assertNumAssetOutputs(t.t, erinTap, assetID1, 1) - assertNumAssetOutputs(t.t, erinTap, assetID2, 1) - assertAssetExists( - t.t, erinTap, assetID1, erinFundingAmount/2, fundingScriptKey1, - false, true, true, - ) - assertAssetExists( - t.t, erinTap, assetID2, erinFundingAmount/2, fundingScriptKey2, - false, true, true, - ) + fundingScriptKeyBytes2 := fundingScriptKey2.SerializeCompressed() + + // We expect the funding outputs to be in the wallet. + itest.AssertBalances( + t.t, charlieTap, charlieFundingAmount/2, + itest.WithAssetID(assetID1), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes1), + ) + itest.AssertBalances( + t.t, charlieTap, charlieFundingAmount/2, + itest.WithAssetID(assetID2), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes2), + ) + itest.AssertBalances( + t.t, erinTap, erinFundingAmount/2, itest.WithAssetID(assetID1), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes1), + ) + itest.AssertBalances( + t.t, erinTap, erinFundingAmount/2, itest.WithAssetID(assetID2), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithNumUtxos(1), + itest.WithScriptKey(fundingScriptKeyBytes2), + ) + + // There should be no directly spendable asset balance remaining, except + // for the 1 asset left over from the burn on Charlie. + itest.AssertBalances( + t.t, charlieTap, 1, itest.WithAssetID(assetID1), + itest.WithNumUtxos(1), + ) + itest.AssertBalances( + t.t, charlieTap, 1, itest.WithAssetID(assetID2), + itest.WithNumUtxos(1), + ) + + // Erin only has the funding output for the channel with Fabia. + itest.AssertBalances(t.t, erinTap, 0, itest.WithAssetID(assetID1)) + itest.AssertBalances(t.t, erinTap, 0, itest.WithAssetID(assetID1)) // Assert that the proofs for both channels has been uploaded to the // designated Universe server. assertUniverseProofExists( - t.t, universeTap, assetID1, groupKey, fundingScriptTreeBytes1, + t.t, universeTap, assetID1, groupKey, fundingScriptKeyBytes1, fmt.Sprintf("%v:%v", fundRespCD.Txid, fundRespCD.OutputIndex), ) assertUniverseProofExists( - t.t, universeTap, assetID2, groupKey, fundingScriptTreeBytes2, + t.t, universeTap, assetID2, groupKey, fundingScriptKeyBytes2, fmt.Sprintf("%v:%v", fundRespCD.Txid, fundRespCD.OutputIndex), ) assertUniverseProofExists( - t.t, universeTap, assetID1, groupKey, fundingScriptTreeBytes1, + t.t, universeTap, assetID1, groupKey, fundingScriptKeyBytes1, fmt.Sprintf("%v:%v", fundRespEF.Txid, fundRespEF.OutputIndex), ) assertUniverseProofExists( - t.t, universeTap, assetID2, groupKey, fundingScriptTreeBytes2, + t.t, universeTap, assetID2, groupKey, fundingScriptKeyBytes2, fmt.Sprintf("%v:%v", fundRespEF.Txid, fundRespEF.OutputIndex), ) @@ -569,34 +568,6 @@ func sendAssetsAndAssert(ctx context.Context, t *harnessTest, itest.AssertNonInteractiveRecvComplete(t.t, recipient, numTransfers) } -func assertNumAssetUTXOs(t *testing.T, tapdClient *tapClient, - numUTXOs int) *taprpc.ListUtxosResponse { - - ctxb := context.Background() - - var clientUTXOs *taprpc.ListUtxosResponse - err := wait.NoError(func() error { - var err error - clientUTXOs, err = tapdClient.ListUtxos( - ctxb, &taprpc.ListUtxosRequest{}, - ) - if err != nil { - return err - } - - if len(clientUTXOs.ManagedUtxos) != numUTXOs { - return fmt.Errorf("expected %v UTXO, got %d", numUTXOs, - len(clientUTXOs.ManagedUtxos)) - } - - return nil - }, defaultTimeout) - require.NoErrorf(t, err, "failed to assert UTXOs: %v, last state: %v", - err, clientUTXOs) - - return clientUTXOs -} - func locateAssetTransfers(t *testing.T, tapdClient *tapClient, txid chainhash.Hash) *taprpc.AssetTransfer { @@ -1944,12 +1915,10 @@ func defaultCoOpCloseBalanceCheck(t *testing.T, local, remote *HarnessNode, ) localTapd := newTapClient(t, local) - - scriptKey, err := btcec.ParsePubKey(scriptKeyBytes) - require.NoError(t, err) - assertAssetExists( - t, localTapd, assetID, a.Amount, scriptKey, true, - true, false, + itest.AssertBalances( + t, localTapd, a.Amount, itest.WithAssetID(assetID), + itest.WithScriptKeyType(asset.ScriptKeyBip86), + itest.WithScriptKey(scriptKeyBytes), ) } @@ -1985,12 +1954,10 @@ func defaultCoOpCloseBalanceCheck(t *testing.T, local, remote *HarnessNode, ) remoteTapd := newTapClient(t, remote) - - scriptKey, err := btcec.ParsePubKey(scriptKeyBytes) - require.NoError(t, err) - assertAssetExists( - t, remoteTapd, assetID, a.Amount, scriptKey, true, - true, false, + itest.AssertBalances( + t, remoteTapd, a.Amount, itest.WithAssetID(assetID), + itest.WithScriptKeyType(asset.ScriptKeyBip86), + itest.WithScriptKey(scriptKeyBytes), ) } } @@ -2062,12 +2029,10 @@ func initiatorZeroAssetBalanceCoOpBalanceCheck(t *testing.T, _, ) remoteTapd := newTapClient(t, remote) - - scriptKey, err := btcec.ParsePubKey(scriptKeyBytes) - require.NoError(t, err) - assertAssetExists( - t, remoteTapd, assetID, a.Amount, scriptKey, true, - true, false, + itest.AssertBalances( + t, remoteTapd, a.Amount, itest.WithAssetID(assetID), + itest.WithScriptKeyType(asset.ScriptKeyBip86), + itest.WithScriptKey(scriptKeyBytes), ) } } @@ -2182,72 +2147,6 @@ func connectRPCWithMac(ctx context.Context, hostPort, tlsCertPath, return grpc.DialContext(ctx, hostPort, opts...) } -func assertAssetBalance(t *testing.T, client *tapClient, assetID []byte, - expectedBalance uint64) { - - t.Helper() - - ctxb := context.Background() - ctxt, cancel := context.WithTimeout(ctxb, shortTimeout) - defer cancel() - - req := &taprpc.ListBalancesRequest{ - GroupBy: &taprpc.ListBalancesRequest_AssetId{ - AssetId: true, - }, - } - - var lastBalances *taprpc.ListBalancesResponse - err := wait.NoError(func() error { - assetIDBalances, err := client.ListBalances(ctxt, req) - if err != nil { - return err - } - - lastBalances = assetIDBalances - - assetIDFound := false - for _, balance := range assetIDBalances.AssetBalances { - if !bytes.Equal(balance.AssetGenesis.AssetId, assetID) { - continue - } - - assetIDFound = true - if expectedBalance != balance.Balance { - return fmt.Errorf("expected balance %d, got %d", - expectedBalance, balance.Balance) - } - } - - if expectedBalance > 0 && !assetIDFound { - return fmt.Errorf("expected balance %d, got 0", - expectedBalance) - } - return nil - }, shortTimeout) - if err != nil { - listAssetsResp, err2 := client.ListAssets( - ctxb, &taprpc.ListAssetRequest{}, - ) - require.NoError(t, err2) - - t.Logf("Failed to assert expected balance of %d for asset ID "+ - "%x: %v", expectedBalance, assetID, err) - - t.Logf("Last balances: %v", toProtoJSON(t, lastBalances)) - t.Logf("Current assets: %v", toProtoJSON(t, listAssetsResp)) - - utxos, err3 := client.ListUtxos( - ctxb, &taprpc.ListUtxosRequest{}, - ) - require.NoError(t, err3) - - t.Logf("Current UTXOs: %v", toProtoJSON(t, utxos)) - - t.Fatalf("Failed to assert balance: %v", err) - } -} - func spendableBalance(client *tapClient, assetID, groupKey []byte) (uint64, error) { @@ -2329,104 +2228,6 @@ func assertSpendableBalance(t *testing.T, client *tapClient, assetID, } } -func assertNumAssetOutputs(t *testing.T, client *tapClient, assetID []byte, - numPieces int) { - - ctxb := context.Background() - ctxt, cancel := context.WithTimeout(ctxb, shortTimeout) - defer cancel() - - resp, err := client.ListAssets(ctxt, &taprpc.ListAssetRequest{ - IncludeLeased: true, - }) - require.NoError(t, err) - - var outputs []*taprpc.Asset - for _, a := range resp.Assets { - if !bytes.Equal(a.AssetGenesis.AssetId, assetID) { - continue - } - - outputs = append(outputs, a) - } - - require.Len(t, outputs, numPieces) -} - -func assertAssetExists(t *testing.T, client *tapClient, assetID []byte, - amount uint64, scriptKey *btcec.PublicKey, scriptKeyLocal, - scriptKeyKnown, scriptKeyHasScript bool) *taprpc.Asset { - - t.Helper() - - var a *taprpc.Asset - err := wait.NoError(func() error { - var err error - a, err = assetExists( - t, client, assetID, amount, scriptKey, scriptKeyLocal, - scriptKeyKnown, scriptKeyHasScript, - ) - return err - }, shortTimeout) - require.NoError(t, err) - - return a -} - -func assetExists(t *testing.T, client *tapClient, assetID []byte, - amount uint64, scriptKey *btcec.PublicKey, scriptKeyLocal, - scriptKeyKnown, scriptKeyHasScript bool) (*taprpc.Asset, error) { - - ctxb := context.Background() - ctxt, cancel := context.WithTimeout(ctxb, shortTimeout) - defer cancel() - - resp, err := client.ListAssets(ctxt, &taprpc.ListAssetRequest{ - IncludeLeased: true, - }) - if err != nil { - return nil, err - } - - for _, a := range resp.Assets { - if !bytes.Equal(a.AssetGenesis.AssetId, assetID) { - continue - } - - if amount != a.Amount { - continue - } - - if scriptKey != nil { - xOnlyKey, _ := schnorr.ParsePubKey( - schnorr.SerializePubKey(scriptKey), - ) - xOnlyKeyBytes := xOnlyKey.SerializeCompressed() - if !bytes.Equal(xOnlyKeyBytes, a.ScriptKey) { - continue - } - } - - if scriptKeyLocal != a.ScriptKeyIsLocal { - continue - } - - if scriptKeyKnown != a.ScriptKeyDeclaredKnown { - continue - } - - if scriptKeyHasScript != a.ScriptKeyHasScriptPath { - continue - } - - // Success, we have found the asset we're looking for. - return a, nil - } - - return nil, fmt.Errorf("asset with given criteria (amount=%d) not "+ - "found in list, got: %v", amount, toProtoJSON(t, resp)) -} - func logBalance(t *testing.T, nodes []*HarnessNode, assetID []byte, occasion string) { diff --git a/itest/litd_custom_channels_test.go b/itest/litd_custom_channels_test.go index c50d91467..10449e518 100644 --- a/itest/litd_custom_channels_test.go +++ b/itest/litd_custom_channels_test.go @@ -635,11 +635,22 @@ func testCustomChannels(ctx context.Context, net *NetworkHarness, erinAssetBalance += 4 fabiaAssetBalance -= 4 yaraAssetBalance -= 1 - assertAssetBalance(t.t, charlieTap, assetID, charlieAssetBalance) - assertAssetBalance(t.t, daveTap, assetID, daveAssetBalance) - assertAssetBalance(t.t, erinTap, assetID, erinAssetBalance) - assertAssetBalance(t.t, fabiaTap, assetID, fabiaAssetBalance) - assertAssetBalance(t.t, yaraTap, assetID, yaraAssetBalance) + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, fabiaTap, fabiaAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, yaraTap, yaraAssetBalance, itest.WithAssetID(assetID), + ) // ------------ // Test case 10: We now open a new asset channel and close it again, to @@ -683,61 +694,56 @@ func testCustomChannels(ctx context.Context, net *NetworkHarness, ) // Charlie should still have four asset pieces, two with the same size. - assertNumAssetOutputs(t.t, charlieTap, assetID, 2) - assertAssetExists( - t.t, charlieTap, assetID, charlieAssetBalance-fundingAmount, - nil, true, false, false, - ) - assertAssetExists( - t.t, charlieTap, assetID, fundingAmount, nil, true, true, - false, + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), itest.WithNumUtxos(2), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) // Dave should have two outputs, one from the initial channel with Yara // and one from the remaining amount of the channel with Charlie. - assertNumAssetOutputs(t.t, daveTap, assetID, 2) - daveFirstChannelRemainder := daveFundingAmount - - yaraInvoiceAssetAmount1 + 1 - assertAssetExists( - t.t, daveTap, assetID, daveFirstChannelRemainder, nil, true, - true, false, - ) - assertAssetExists( - t.t, daveTap, assetID, - daveAssetBalance-daveFirstChannelRemainder, nil, true, true, - false, + itest.AssertBalances( + t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(2), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) // Fabia and Yara should all have a single output each, just what was // left over from the initial channel. - assertNumAssetOutputs(t.t, fabiaTap, assetID, 1) - assertAssetExists( - t.t, fabiaTap, assetID, fabiaAssetBalance, nil, true, true, - false, + itest.AssertBalances( + t.t, fabiaTap, fabiaAssetBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) - assertNumAssetOutputs(t.t, yaraTap, assetID, 1) - assertAssetExists( - t.t, yaraTap, assetID, yaraAssetBalance, nil, true, true, false, + itest.AssertBalances( + t.t, yaraTap, yaraAssetBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) // Erin didn't use all of his assets when opening the channel, so he // should have two outputs, the change from the channel opening and the // remaining amount after closing the channel. - assertNumAssetOutputs(t.t, erinTap, assetID, 2) - erinChange := startAmount - erinFundingAmount - assertAssetExists( - t.t, erinTap, assetID, erinAssetBalance-erinChange, nil, true, - true, false, - ) - assertAssetExists( - t.t, erinTap, assetID, erinChange, nil, true, false, false, + itest.AssertBalances( + t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(2), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) // The asset balances should still remain unchanged. - assertAssetBalance(t.t, charlieTap, assetID, charlieAssetBalance) - assertAssetBalance(t.t, daveTap, assetID, daveAssetBalance) - assertAssetBalance(t.t, erinTap, assetID, erinAssetBalance) - assertAssetBalance(t.t, fabiaTap, assetID, fabiaAssetBalance) + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, fabiaTap, fabiaAssetBalance, itest.WithAssetID(assetID), + ) } // testCustomChannelsGroupedAsset tests that we can create a network with custom @@ -1071,11 +1077,22 @@ func testCustomChannelsGroupedAsset(ctx context.Context, net *NetworkHarness, erinAssetBalance += 4 fabiaAssetBalance -= 4 yaraAssetBalance -= 1 - assertAssetBalance(t.t, charlieTap, assetID, charlieAssetBalance) - assertAssetBalance(t.t, daveTap, assetID, daveAssetBalance) - assertAssetBalance(t.t, erinTap, assetID, erinAssetBalance) - assertAssetBalance(t.t, fabiaTap, assetID, fabiaAssetBalance) - assertAssetBalance(t.t, yaraTap, assetID, yaraAssetBalance) + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, fabiaTap, fabiaAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, yaraTap, yaraAssetBalance, itest.WithAssetID(assetID), + ) // ------------ // Test case 10: We now open a new asset channel and close it again, to @@ -1118,25 +1135,27 @@ func testCustomChannelsGroupedAsset(ctx context.Context, net *NetworkHarness, universeTap, assertDefaultCoOpCloseBalance(false, false), ) - // Charlie should still have four asset pieces, two with the same size. - assertAssetExists( - t.t, charlieTap, assetID, charlieAssetBalance-fundingAmount, - nil, true, false, false, - ) - assertAssetExists( - t.t, charlieTap, assetID, fundingAmount, nil, true, true, - false, - ) - // Charlie should have asset outputs: the leftover change from the // channel funding, and the new close output. - assertNumAssetOutputs(t.t, charlieTap, assetID, 2) + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), itest.WithNumUtxos(2), + ) // The asset balances should still remain unchanged. - assertAssetBalance(t.t, charlieTap, assetID, charlieAssetBalance) - assertAssetBalance(t.t, daveTap, assetID, daveAssetBalance) - assertAssetBalance(t.t, erinTap, assetID, erinAssetBalance) - assertAssetBalance(t.t, fabiaTap, assetID, fabiaAssetBalance) + itest.AssertBalances( + t.t, charlieTap, charlieAssetBalance, + itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, daveTap, daveAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, erinTap, erinAssetBalance, itest.WithAssetID(assetID), + ) + itest.AssertBalances( + t.t, fabiaTap, fabiaAssetBalance, itest.WithAssetID(assetID), + ) } // testCustomChannelsGroupTranchesForceClose tests that we can successfully open @@ -1799,8 +1818,9 @@ func testCustomChannelsForceClose(ctx context.Context, net *NetworkHarness, // Charlie's balance should reflect that the funding asset is now // excluded from balance reporting by tapd. - assertAssetBalance( - t.t, charlieTap, assetID, itestAsset.Amount-fundingAmount, + itest.AssertBalances( + t.t, charlieTap, itestAsset.Amount-fundingAmount, + itest.WithAssetID(assetID), ) // Make sure that Charlie properly uploaded funding proof to the @@ -1941,13 +1961,14 @@ func testCustomChannelsForceClose(ctx context.Context, net *NetworkHarness, // Both sides should now reflect their updated asset balances. daveBalance := uint64(numPayments * keySendAmount) charlieBalance := itestAsset.Amount - daveBalance - assertAssetBalance(t.t, daveTap, assetID, daveBalance) - assertAssetBalance(t.t, charlieTap, assetID, charlieBalance) - - // Dave should have a single managed UTXO that shows he has a new asset - // UTXO he can use. - assertNumAssetUTXOs(t.t, daveTap, 1) - assertNumAssetUTXOs(t.t, charlieTap, 2) + itest.AssertBalances( + t.t, daveTap, daveBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + ) + itest.AssertBalances( + t.t, charlieTap, charlieBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(2), + ) // We'll make sure Dave can spend his asset UTXO by sending it all but // one unit to Zane (the universe). @@ -2098,8 +2119,9 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness, // Charlie's balance should reflect that the funding asset is now // excluded from balance reporting by tapd. - assertAssetBalance( - t.t, charlieTap, assetID, itestAsset.Amount-fundingAmount, + itest.AssertBalances( + t.t, charlieTap, itestAsset.Amount-fundingAmount, + itest.WithAssetID(assetID), itest.WithNumUtxos(1), ) // Make sure that Charlie properly uploaded funding proof to the @@ -2209,15 +2231,12 @@ func testCustomChannelsBreach(ctx context.Context, net *NetworkHarness, // Charlie's balance should now be the same as before the breach // attempt: the amount he minted at the very start. charlieBalance := itestAsset.Amount - assertAssetBalance(t.t, charlieTap, assetID, charlieBalance) + itest.AssertBalances( + t.t, charlieTap, charlieBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(3), + ) t.Logf("Charlie balance after breach: %d", charlieBalance) - - // Charlie should now have 2 total UTXOs: the change from the funding - // output, and now the sweep output from the justice transaction. - charlieUTXOs := assertNumAssetUTXOs(t.t, charlieTap, 2) - - t.Logf("Charlie UTXOs after breach: %v", toProtoJSON(t.t, charlieUTXOs)) } // testCustomChannelsLiquidtyEdgeCasesCore is the core logic of the liquidity @@ -3008,25 +3027,22 @@ func testCustomChannelsBalanceConsistency(ctx context.Context, charlieBalance := cents.Amount // Charlie should have a single balance output with the full balance. - assertAssetBalance(t.t, charlieTap, assetID, cents.Amount) + itest.AssertBalances( + t.t, charlieTap, cents.Amount, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + ) // The script key should be local to charlie, and the script key should // be known. It is after all the asset he just minted himself. - scriptKeyLocal := true - scriptKeyKnown := false - scriptKeyHasScriptPath := false - - scriptKey, err := schnorr.ParsePubKey(cents.ScriptKey[1:]) - require.NoError(t.t, err) - assertAssetExists( - t.t, charlieTap, assetID, charlieBalance, - scriptKey, scriptKeyLocal, scriptKeyKnown, - scriptKeyHasScriptPath, + itest.AssertBalances( + t.t, charlieTap, cents.Amount, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), itest.WithScriptKey(cents.ScriptKey), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) fundingScriptTree := tapscript.NewChannelFundingScriptTree() fundingScriptKey := fundingScriptTree.TaprootKey - fundingScriptTreeBytes := fundingScriptKey.SerializeCompressed() + fundingScriptKeyBytes := fundingScriptKey.SerializeCompressed() fundRespCD, err := charlieTap.FundChannel( ctx, &tchrpc.FundChannelRequest{ @@ -3052,28 +3068,22 @@ func testCustomChannelsBalanceConsistency(ctx context.Context, // Tapd should not report any balance for Charlie, since the asset is // used in a funding transaction. It should also not report any balance // for Dave. All those balances are reported through channel balances. - assertAssetBalance(t.t, charlieTap, assetID, 0) - assertAssetBalance(t.t, daveTap, assetID, 0) + itest.AssertBalances(t.t, charlieTap, 0, itest.WithAssetID(assetID)) + itest.AssertBalances(t.t, daveTap, 0, itest.WithAssetID(assetID)) // There should only be a single asset piece for Charlie, the one in the // channel. - assertNumAssetOutputs(t.t, charlieTap, assetID, 1) - - // The script key should now not be local anymore, since he funded a - // channel with it. Charlie does still know the script key though. - scriptKeyLocal = false - scriptKeyKnown = true - scriptKeyHasScriptPath = true - assertAssetExists( - t.t, charlieTap, assetID, charlieBalance, - fundingScriptKey, scriptKeyLocal, scriptKeyKnown, - scriptKeyHasScriptPath, + itest.AssertBalances( + t.t, charlieTap, charlieBalance, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + itest.WithScriptKeyType(asset.ScriptKeyScriptPathChannel), + itest.WithScriptKey(fundingScriptKeyBytes), ) // Assert that the proofs for both channels has been uploaded to the // designated Universe server. assertUniverseProofExists( - t.t, universeTap, assetID, groupKey, fundingScriptTreeBytes, + t.t, universeTap, assetID, groupKey, fundingScriptKeyBytes, fmt.Sprintf("%v:%v", fundRespCD.Txid, fundRespCD.OutputIndex), ) @@ -3095,8 +3105,8 @@ func testCustomChannelsBalanceConsistency(ctx context.Context, // Tapd should still not report balances for Charlie and Dave, since // they are still locked up in the funding transaction. - assertAssetBalance(t.t, charlieTap, assetID, 0) - assertAssetBalance(t.t, daveTap, assetID, 0) + itest.AssertBalances(t.t, charlieTap, 0, itest.WithAssetID(assetID)) + itest.AssertBalances(t.t, daveTap, 0, itest.WithAssetID(assetID)) // Send 10k sats from Charlie to Dave. Dave needs the sats to be able to // send assets. @@ -3111,8 +3121,8 @@ func testCustomChannelsBalanceConsistency(ctx context.Context, // Tapd should still not report balances for Charlie and Dave, since // they are still locked up in the funding transaction. - assertAssetBalance(t.t, charlieTap, assetID, 0) - assertAssetBalance(t.t, daveTap, assetID, 0) + itest.AssertBalances(t.t, charlieTap, 0, itest.WithAssetID(assetID)) + itest.AssertBalances(t.t, daveTap, 0, itest.WithAssetID(assetID)) // We will now close the channel. t.Logf("Close the channel between Charlie and Dave...") @@ -3127,25 +3137,16 @@ func testCustomChannelsBalanceConsistency(ctx context.Context, // Charlie should have a single balance output with the balance 250 less // than the total amount minted. - assertAssetBalance(t.t, charlieTap, assetID, charlieBalance-250) - assertAssetBalance(t.t, daveTap, assetID, 250) - - // The script key should now be local to both Charlie and Dave, since - // the channel was closed. - scriptKeyLocal = true - scriptKeyKnown = true - scriptKeyHasScriptPath = false - assertAssetExists( - t.t, charlieTap, assetID, charlieBalance-250, - nil, scriptKeyLocal, scriptKeyKnown, scriptKeyHasScriptPath, + itest.AssertBalances( + t.t, charlieTap, charlieBalance-250, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) - assertAssetExists( - t.t, daveTap, assetID, 250, - nil, scriptKeyLocal, scriptKeyKnown, scriptKeyHasScriptPath, + itest.AssertBalances( + t.t, daveTap, 250, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + itest.WithScriptKeyType(asset.ScriptKeyBip86), ) - - assertNumAssetOutputs(t.t, charlieTap, assetID, 1) - assertNumAssetOutputs(t.t, daveTap, assetID, 1) } // testCustomChannelsSingleAssetMultiInput tests whether it is possible to fund @@ -3197,7 +3198,11 @@ func testCustomChannelsSingleAssetMultiInput(ctx context.Context, t.Logf("Universes synced between all nodes, distributing assets...") // Charlie should have two balance outputs with the full balance. - assertAssetBalance(t.t, charlieTap, assetID, cents.Amount) + itest.AssertBalances( + t.t, charlieTap, cents.Amount, itest.WithAssetID(assetID), + itest.WithNumUtxos(1), + itest.WithScriptKeyType(asset.ScriptKeyBip86), + ) // Send assets to Dave so he can fund a channel. halfCentsAmount := cents.Amount / 2 @@ -3257,8 +3262,8 @@ func testCustomChannelsSingleAssetMultiInput(ctx context.Context, // Tapd should not report any balance for Charlie, since the asset is // used in a funding transaction. It should also not report any balance // for Dave. All those balances are reported through channel balances. - assertAssetBalance(t.t, charlieTap, assetID, 0) - assertAssetBalance(t.t, daveTap, assetID, 0) + itest.AssertBalances(t.t, charlieTap, 0, itest.WithAssetID(assetID)) + itest.AssertBalances(t.t, daveTap, 0, itest.WithAssetID(assetID)) // Make sure the channel shows the correct asset information. assertAssetChan(