Skip to content

Commit

Permalink
Merge pull request #67 from lightninglabs/grouped-assets-itest
Browse files Browse the repository at this point in the history
itest: add more test cases that use grouped assets
  • Loading branch information
Roasbeef committed May 9, 2023
2 parents 97e1753 + 53f24c2 commit 005ca01
Show file tree
Hide file tree
Showing 15 changed files with 465 additions and 351 deletions.
105 changes: 49 additions & 56 deletions itest/addrs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package itest
import (
"bytes"
"context"
"fmt"

"github.com/lightninglabs/taro/taropsbt"
"github.com/lightninglabs/taro/tarorpc"
Expand All @@ -13,13 +12,16 @@ 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
// 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()
Expand All @@ -39,16 +41,14 @@ 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{
AssetId: a.AssetGenesis.AssetId,
Amt: a.Amount - 1,
})
require.NoError(t.t, err)
addresses = append(addresses, addr)

assertAddrCreated(t.t, secondTarod, a, addr)

Expand All @@ -60,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{},
)
Expand All @@ -126,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)
Expand All @@ -149,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
Expand Down Expand Up @@ -192,20 +185,20 @@ 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]

// 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
Expand All @@ -216,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 (
Expand All @@ -230,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)
Expand Down
46 changes: 26 additions & 20 deletions itest/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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])
Expand All @@ -310,26 +312,28 @@ 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)
defer cancel()

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)
}
}

Expand Down Expand Up @@ -527,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)
}
}

Expand Down
4 changes: 3 additions & 1 deletion itest/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
5 changes: 3 additions & 2 deletions itest/collectible_split_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading

0 comments on commit 005ca01

Please sign in to comment.