Skip to content

Commit 7b0541a

Browse files
committed
itest: add test for local universe proof delivery
1 parent 440a57b commit 7b0541a

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

itest/addrs_test.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
tap "github.com/lightninglabs/taproot-assets"
99
"github.com/lightninglabs/taproot-assets/fn"
1010
"github.com/lightninglabs/taproot-assets/internal/test"
11+
"github.com/lightninglabs/taproot-assets/proof"
1112
"github.com/lightninglabs/taproot-assets/tappsbt"
1213
"github.com/lightninglabs/taproot-assets/taprpc"
1314
wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
@@ -512,6 +513,8 @@ func runMultiSendTest(ctxt context.Context, t *harnessTest, alice,
512513
require.NoError(t.t, err)
513514
}
514515

516+
// sendProof manually exports a proof from the given source node and imports it
517+
// using the development only ImportProof RPC on the destination node.
515518
func sendProof(t *harnessTest, src, dst *tapdHarness, scriptKey []byte,
516519
genInfo *taprpc.GenesisInfo) *tapdevrpc.ImportProofResponse {
517520

@@ -543,6 +546,85 @@ func sendProof(t *harnessTest, src, dst *tapdHarness, scriptKey []byte,
543546
return importResp
544547
}
545548

549+
// sendProofUniRPC manually exports a proof from the given source node and
550+
// imports it using the universe related InsertProof RPC on the destination
551+
// node.
552+
func sendProofUniRPC(t *harnessTest, src, dst *tapdHarness, scriptKey []byte,
553+
genInfo *taprpc.GenesisInfo) *unirpc.AssetProofResponse {
554+
555+
ctxb := context.Background()
556+
557+
var proofResp *taprpc.ProofFile
558+
waitErr := wait.NoError(func() error {
559+
resp, err := src.ExportProof(ctxb, &taprpc.ExportProofRequest{
560+
AssetId: genInfo.AssetId,
561+
ScriptKey: scriptKey,
562+
})
563+
if err != nil {
564+
return err
565+
}
566+
567+
proofResp = resp
568+
return nil
569+
}, defaultWaitTimeout)
570+
require.NoError(t.t, waitErr)
571+
572+
t.Logf("Importing proof %x using InsertProof", proofResp.RawProofFile)
573+
574+
f := proof.File{}
575+
err := f.Decode(bytes.NewReader(proofResp.RawProofFile))
576+
require.NoError(t.t, err)
577+
578+
lastProof, err := f.LastProof()
579+
require.NoError(t.t, err)
580+
581+
var lastProofBytes bytes.Buffer
582+
err = lastProof.Encode(&lastProofBytes)
583+
require.NoError(t.t, err)
584+
asset := lastProof.Asset
585+
586+
proofType := universe.ProofTypeTransfer
587+
if asset.IsGenesisAsset() {
588+
proofType = universe.ProofTypeIssuance
589+
}
590+
591+
uniID := universe.Identifier{
592+
AssetID: asset.ID(),
593+
ProofType: proofType,
594+
}
595+
if asset.GroupKey != nil {
596+
uniID.GroupKey = &asset.GroupKey.GroupPubKey
597+
}
598+
599+
rpcUniID, err := tap.MarshalUniID(uniID)
600+
require.NoError(t.t, err)
601+
602+
outpoint := &unirpc.Outpoint{
603+
HashStr: lastProof.AnchorTx.TxHash().String(),
604+
Index: int32(lastProof.InclusionProof.OutputIndex),
605+
}
606+
607+
importResp, err := dst.InsertProof(ctxb, &unirpc.AssetProof{
608+
Key: &unirpc.UniverseKey{
609+
Id: rpcUniID,
610+
LeafKey: &unirpc.AssetKey{
611+
Outpoint: &unirpc.AssetKey_Op{
612+
Op: outpoint,
613+
},
614+
ScriptKey: &unirpc.AssetKey_ScriptKeyBytes{
615+
ScriptKeyBytes: scriptKey,
616+
},
617+
},
618+
},
619+
AssetLeaf: &unirpc.AssetLeaf{
620+
Proof: lastProofBytes.Bytes(),
621+
},
622+
})
623+
require.NoError(t.t, err)
624+
625+
return importResp
626+
}
627+
546628
// sendAssetsToAddr spends the given input asset and sends the amount specified
547629
// in the address to the Taproot output derived from the address.
548630
func sendAssetsToAddr(t *harnessTest, sender *tapdHarness,

itest/send_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,67 @@ func testSendMultipleCoins(t *harnessTest) {
13741374
AssertNonInteractiveRecvComplete(t.t, secondTapd, 5)
13751375
}
13761376

1377+
// testSendNoCourierUniverseImport tests that we can send assets to a node that
1378+
// has no courier, and then manually transfer the proof to the receiving using
1379+
// the universe proof import RPC method.
1380+
func testSendNoCourierUniverseImport(t *harnessTest) {
1381+
ctxb := context.Background()
1382+
1383+
// First, we'll make a normal assets with enough units.
1384+
rpcAssets := MintAssetsConfirmBatch(
1385+
t.t, t.lndHarness.Miner.Client, t.tapd,
1386+
[]*mintrpc.MintAssetRequest{simpleAssets[0]},
1387+
)
1388+
1389+
firstAsset := rpcAssets[0]
1390+
genInfo := firstAsset.AssetGenesis
1391+
1392+
// Now that we have the asset created, we'll make a new node that'll
1393+
// serve as the node which'll receive the assets. We turn off the proof
1394+
// courier by supplying a dummy implementation.
1395+
secondTapd := setupTapdHarness(
1396+
t.t, t, t.lndHarness.Bob, t.universeServer,
1397+
func(params *tapdHarnessParams) {
1398+
params.proofCourier = &proof.MockProofCourier{}
1399+
},
1400+
)
1401+
defer func() {
1402+
require.NoError(t.t, secondTapd.stop(!*noDelete))
1403+
}()
1404+
1405+
// Next, we'll attempt to transfer some amount of assets[0] to the
1406+
// receiving node.
1407+
numUnitsSend := uint64(1200)
1408+
1409+
// Get a new address (which accepts the first asset) from the
1410+
// receiving node.
1411+
receiveAddr, err := secondTapd.NewAddr(ctxb, &taprpc.NewAddrRequest{
1412+
AssetId: genInfo.AssetId,
1413+
Amt: numUnitsSend,
1414+
})
1415+
require.NoError(t.t, err)
1416+
AssertAddrCreated(t.t, secondTapd, firstAsset, receiveAddr)
1417+
1418+
// Send the assets to the receiving node.
1419+
sendResp := sendAssetsToAddr(t, t.tapd, receiveAddr)
1420+
1421+
// Assert that the outbound transfer was confirmed.
1422+
expectedAmtAfterSend := firstAsset.Amount - numUnitsSend
1423+
ConfirmAndAssertOutboundTransfer(
1424+
t.t, t.lndHarness.Miner.Client, t.tapd, sendResp,
1425+
genInfo.AssetId,
1426+
[]uint64{expectedAmtAfterSend, numUnitsSend}, 0, 1,
1427+
)
1428+
1429+
// Since we disabled proof couriers, we need to manually transfer the
1430+
// proof from the sender to the receiver now. We use the universe RPC
1431+
// InsertProof method to do this.
1432+
sendProofUniRPC(t, t.tapd, secondTapd, receiveAddr.ScriptKey, genInfo)
1433+
1434+
// And now, the transfer should be completed on the receiver side too.
1435+
AssertNonInteractiveRecvComplete(t.t, secondTapd, 1)
1436+
}
1437+
13771438
// addProofTestVectorFromFile adds a proof test vector by extracting it from the
13781439
// proof file found at the given asset ID and script key.
13791440
func addProofTestVectorFromFile(t *testing.T, testName string,

itest/test_list_on_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ var testCases = []*testCase{
7676
test: testOfflineReceiverEventuallyReceives,
7777
proofCourierType: proof.HashmailCourierType,
7878
},
79+
{
80+
name: "addr send no proof courier with local universe import",
81+
test: testSendNoCourierUniverseImport,
82+
},
7983
{
8084
name: "basic send passive asset",
8185
test: testBasicSendPassiveAsset,

0 commit comments

Comments
 (0)