Skip to content

Commit 99b8f86

Browse files
authored
Merge pull request #730 from lightninglabs/proof-courier-shortcut
[2/2] proof: allow proof courier to short cut with local archive
2 parents 1ca17f6 + ca77ce5 commit 99b8f86

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2350
-1179
lines changed

asset/asset.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import (
1010
"io"
1111
"reflect"
1212
"strings"
13+
"time"
1314
"unicode"
1415
"unicode/utf8"
1516

1617
"github.com/btcsuite/btcd/blockchain"
1718
"github.com/btcsuite/btcd/btcec/v2"
1819
"github.com/btcsuite/btcd/btcec/v2/schnorr"
1920
"github.com/btcsuite/btcd/btcutil/psbt"
21+
"github.com/btcsuite/btcd/chaincfg/chainhash"
2022
"github.com/btcsuite/btcd/txscript"
2123
"github.com/btcsuite/btcd/wire"
2224
"github.com/lightninglabs/lndclient"
@@ -1621,3 +1623,53 @@ func ValidateAssetName(name string) error {
16211623

16221624
return nil
16231625
}
1626+
1627+
// ChainAsset is a wrapper around the base asset struct that includes
1628+
// information detailing where in the chain the asset is currently anchored.
1629+
type ChainAsset struct {
1630+
*Asset
1631+
1632+
// IsSpent indicates whether the above asset was previously spent.
1633+
IsSpent bool
1634+
1635+
// AnchorTx is the transaction that anchors this chain asset.
1636+
AnchorTx *wire.MsgTx
1637+
1638+
// AnchorBlockHash is the blockhash that mined the anchor tx.
1639+
AnchorBlockHash chainhash.Hash
1640+
1641+
// AnchorBlockHeight is the height of the block that mined the anchor
1642+
// tx.
1643+
AnchorBlockHeight uint32
1644+
1645+
// AnchorOutpoint is the outpoint that commits to the asset.
1646+
AnchorOutpoint wire.OutPoint
1647+
1648+
// AnchorInternalKey is the raw internal key that was used to create the
1649+
// anchor Taproot output key.
1650+
AnchorInternalKey *btcec.PublicKey
1651+
1652+
// AnchorMerkleRoot is the Taproot merkle root hash of the anchor output
1653+
// the asset was committed to. If there is no Tapscript sibling, this is
1654+
// equal to the Taproot Asset root commitment hash.
1655+
AnchorMerkleRoot []byte
1656+
1657+
// AnchorTapscriptSibling is the serialized preimage of a Tapscript
1658+
// sibling, if there was one. If this is empty, then the
1659+
// AnchorTapscriptSibling hash is equal to the Taproot root hash of the
1660+
// anchor output.
1661+
AnchorTapscriptSibling []byte
1662+
1663+
// AnchorLeaseOwner is the identity of the application that currently
1664+
// has a lease on this UTXO. If empty/nil, then the UTXO is not
1665+
// currently leased. A lease means that the UTXO is being
1666+
// reserved/locked to be spent in an upcoming transaction and that it
1667+
// should not be available for coin selection through any of the wallet
1668+
// RPCs.
1669+
AnchorLeaseOwner [32]byte
1670+
1671+
// AnchorLeaseExpiry is the expiry of the lease. If the expiry is nil or
1672+
// the time is in the past, then the lease is not valid and the UTXO is
1673+
// available for coin selection.
1674+
AnchorLeaseExpiry *time.Time
1675+
}

cmd/tapcli/universe.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/hex"
66
"fmt"
77

8+
"github.com/btcsuite/btcd/wire"
89
tap "github.com/lightninglabs/taproot-assets"
910
"github.com/lightninglabs/taproot-assets/fn"
1011
"github.com/lightninglabs/taproot-assets/proof"
@@ -456,7 +457,7 @@ func parseAssetKey(ctx *cli.Context) (*unirpc.AssetKey, error) {
456457
return nil, fmt.Errorf("outpoint and script key must be set")
457458
}
458459

459-
outpoint, err := tap.UnmarshalOutpoint(ctx.String(outpointName))
460+
outpoint, err := wire.NewOutPointFromString(ctx.String(outpointName))
460461
if err != nil {
461462
return nil, err
462463
}

itest/addrs_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66

77
"github.com/btcsuite/btcd/btcec/v2/schnorr"
8+
"github.com/btcsuite/btcd/wire"
89
tap "github.com/lightninglabs/taproot-assets"
910
"github.com/lightninglabs/taproot-assets/fn"
1011
"github.com/lightninglabs/taproot-assets/internal/test"
@@ -515,16 +516,34 @@ func runMultiSendTest(ctxt context.Context, t *harnessTest, alice,
515516

516517
// sendProof manually exports a proof from the given source node and imports it
517518
// using the development only ImportProof RPC on the destination node.
518-
func sendProof(t *harnessTest, src, dst *tapdHarness, scriptKey []byte,
519+
func sendProof(t *harnessTest, src, dst *tapdHarness,
520+
sendResp *taprpc.SendAssetResponse, scriptKey []byte,
519521
genInfo *taprpc.GenesisInfo) *tapdevrpc.ImportProofResponse {
520522

521523
ctxb := context.Background()
522524

525+
// We need to find the outpoint of the asset we sent to the address.
526+
var outpoint *taprpc.OutPoint
527+
for _, out := range sendResp.Transfer.Outputs {
528+
if bytes.Equal(out.ScriptKey, scriptKey) {
529+
wireOutPoint, err := wire.NewOutPointFromString(
530+
out.Anchor.Outpoint,
531+
)
532+
require.NoError(t.t, err)
533+
534+
outpoint = &taprpc.OutPoint{
535+
Txid: wireOutPoint.Hash[:],
536+
OutputIndex: wireOutPoint.Index,
537+
}
538+
}
539+
}
540+
523541
var proofResp *taprpc.ProofFile
524542
waitErr := wait.NoError(func() error {
525543
resp, err := src.ExportProof(ctxb, &taprpc.ExportProofRequest{
526544
AssetId: genInfo.AssetId,
527545
ScriptKey: scriptKey,
546+
Outpoint: outpoint,
528547
})
529548
if err != nil {
530549
return err

itest/psbt_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func testPsbtScriptHashLockSend(t *harnessTest) {
132132
// This is an interactive/PSBT based transfer, so we do need to manually
133133
// send the proof from the sender to the receiver because the proof
134134
// courier address gets lost in the address->PSBT conversion.
135-
_ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo)
135+
_ = sendProof(t, bob, alice, sendResp, aliceAddr.ScriptKey, genInfo)
136136
AssertNonInteractiveRecvComplete(t.t, alice, 1)
137137

138138
aliceAssets, err := alice.ListAssets(ctxb, &taprpc.ListAssetRequest{
@@ -258,7 +258,7 @@ func testPsbtScriptCheckSigSend(t *harnessTest) {
258258
// This is an interactive/PSBT based transfer, so we do need to manually
259259
// send the proof from the sender to the receiver because the proof
260260
// courier address gets lost in the address->PSBT conversion.
261-
_ = sendProof(t, bob, alice, aliceAddr.ScriptKey, genInfo)
261+
_ = sendProof(t, bob, alice, sendResp, aliceAddr.ScriptKey, genInfo)
262262
AssertNonInteractiveRecvComplete(t.t, alice, 1)
263263

264264
aliceAssets, err := alice.ListAssets(ctxb, &taprpc.ListAssetRequest{
@@ -434,7 +434,7 @@ func runPsbtInteractiveFullValueSendTest(ctxt context.Context, t *harnessTest,
434434
// This is an interactive transfer, so we do need to manually
435435
// send the proof from the sender to the receiver.
436436
_ = sendProof(
437-
t, sender, receiver,
437+
t, sender, receiver, sendResp,
438438
receiverScriptKey.PubKey.SerializeCompressed(), genInfo,
439439
)
440440

@@ -647,7 +647,7 @@ func runPsbtInteractiveSplitSendTest(ctxt context.Context, t *harnessTest,
647647
// This is an interactive transfer, so we do need to manually
648648
// send the proof from the sender to the receiver.
649649
_ = sendProof(
650-
t, sender, receiver,
650+
t, sender, receiver, sendResp,
651651
receiverScriptKey.PubKey.SerializeCompressed(), genInfo,
652652
)
653653

@@ -769,7 +769,7 @@ func testPsbtInteractiveTapscriptSibling(t *harnessTest) {
769769
// This is an interactive transfer, so we do need to manually send the
770770
// proof from the sender to the receiver.
771771
_ = sendProof(
772-
t, alice, bob,
772+
t, alice, bob, sendResp,
773773
receiverScriptKey.PubKey.SerializeCompressed(), genInfo,
774774
)
775775

@@ -916,11 +916,11 @@ func testPsbtMultiSend(t *harnessTest) {
916916
// This is an interactive transfer, so we do need to manually send the
917917
// proof from the sender to the receiver.
918918
_ = sendProof(
919-
t, sender, receiver,
919+
t, sender, receiver, sendResp,
920920
receiverScriptKey1.PubKey.SerializeCompressed(), genInfo,
921921
)
922922
_ = sendProof(
923-
t, sender, receiver,
923+
t, sender, receiver, sendResp,
924924
receiverScriptKey2.PubKey.SerializeCompressed(), genInfo,
925925
)
926926

@@ -1158,7 +1158,7 @@ func testMultiInputPsbtSingleAssetID(t *harnessTest) {
11581158
// This is an interactive transfer. Therefore, we will manually transfer
11591159
// the proof from the sender to the receiver.
11601160
_ = sendProof(
1161-
t, secondaryTapd, primaryTapd,
1161+
t, secondaryTapd, primaryTapd, sendResp,
11621162
primaryNodeScriptKey.PubKey.SerializeCompressed(), genInfo,
11631163
)
11641164

@@ -1233,7 +1233,7 @@ func testMultiInputPsbtSingleAssetID(t *harnessTest) {
12331233
// This is an interactive transfer. Therefore, we will manually transfer
12341234
// the proof from the sender to the receiver.
12351235
_ = sendProof(
1236-
t, secondaryTapd, primaryTapd,
1236+
t, secondaryTapd, primaryTapd, sendResp,
12371237
primaryNodeScriptKey.PubKey.SerializeCompressed(), genInfo,
12381238
)
12391239

itest/round_trip_send_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func testRoundTripSend(t *harnessTest) {
127127
// recipient's output is the second one.
128128
bobToAliceOutput := transferResp.Transfers[0].Outputs[1]
129129
bobToAliceAnchor := bobToAliceOutput.Anchor
130-
outpoint, err := ParseOutPoint(bobToAliceAnchor.Outpoint)
130+
outpoint, err := wire.NewOutPointFromString(bobToAliceAnchor.Outpoint)
131131
require.NoError(t.t, err)
132132

133133
internalKey, err := btcec.ParsePubKey(bobToAliceAnchor.InternalKey)

itest/test_list_on_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ var testCases = []*testCase{
4141
test: testReOrgMintAndSend,
4242
},
4343
{
44-
name: "basic send unidirectional",
44+
name: "basic send unidirectional hashmail courier",
4545
test: testBasicSendUnidirectional,
4646
proofCourierType: proof.HashmailCourierType,
4747
},
@@ -54,7 +54,8 @@ var testCases = []*testCase{
5454
test: testRestartReceiverCheckBalance,
5555
},
5656
{
57-
name: "resume pending package send",
57+
name: "resume pending package send hashmail " +
58+
"courier",
5859
test: testResumePendingPackageSend,
5960
proofCourierType: proof.HashmailCourierType,
6061
},
@@ -72,7 +73,8 @@ var testCases = []*testCase{
7273
test: testReattemptFailedReceiveUniCourier,
7374
},
7475
{
75-
name: "offline receiver eventually receives",
76+
name: "offline receiver eventually receives " +
77+
"hashmail courier",
7678
test: testOfflineReceiverEventuallyReceives,
7779
proofCourierType: proof.HashmailCourierType,
7880
},
@@ -81,7 +83,7 @@ var testCases = []*testCase{
8183
test: testSendNoCourierUniverseImport,
8284
},
8385
{
84-
name: "basic send passive asset",
86+
name: "basic send passive asset hashmail courier",
8587
test: testBasicSendPassiveAsset,
8688
proofCourierType: proof.HashmailCourierType,
8789
},
@@ -123,7 +125,7 @@ var testCases = []*testCase{
123125
test: testMintMultiAssetGroups,
124126
},
125127
{
126-
name: "sending multi asset groups",
128+
name: "sending multi asset groups hashmail courier",
127129
test: testMultiAssetGroupSend,
128130
proofCourierType: proof.HashmailCourierType,
129131
},

itest/universe_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/btcsuite/btcd/btcec/v2"
1313
"github.com/btcsuite/btcd/btcec/v2/schnorr"
14+
"github.com/btcsuite/btcd/wire"
1415
tap "github.com/lightninglabs/taproot-assets"
1516
"github.com/lightninglabs/taproot-assets/asset"
1617
"github.com/lightninglabs/taproot-assets/fn"
@@ -150,7 +151,7 @@ func testUniverseSync(t *harnessTest) {
150151
// query for that asset with the compressed script key.
151152
firstAssetID := rpcSimpleAssets[0].AssetGenesis.AssetId
152153
firstScriptKey := hex.EncodeToString(rpcSimpleAssets[0].ScriptKey)
153-
firstOutpoint, err := tap.UnmarshalOutpoint(
154+
firstOutpoint, err := wire.NewOutPointFromString(
154155
rpcSimpleAssets[0].ChainAnchor.AnchorOutpoint,
155156
)
156157
require.NoError(t.t, err)
@@ -326,7 +327,7 @@ func testUniverseManualSync(t *harnessTest) {
326327

327328
// We should also be able to fetch an asset from Bob's Universe, and
328329
// query for that asset with the compressed script key.
329-
firstOutpoint, err := tap.UnmarshalOutpoint(
330+
firstOutpoint, err := wire.NewOutPointFromString(
330331
firstAsset.ChainAnchor.AnchorOutpoint,
331332
)
332333
require.NoError(t.t, err)

itest/utils.go

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ package itest
22

33
import (
44
"context"
5-
"fmt"
6-
"strconv"
7-
"strings"
85
"testing"
96
"time"
107

@@ -48,34 +45,10 @@ func CopyRequests(
4845
return copied
4946
}
5047

51-
// ParseOutPoint
52-
func ParseOutPoint(s string) (*wire.OutPoint, error) {
53-
split := strings.Split(s, ":")
54-
if len(split) != 2 {
55-
return nil, fmt.Errorf("expecting outpoint to be in format " +
56-
"of: txid:index")
57-
}
58-
59-
index, err := strconv.ParseInt(split[1], 10, 32)
60-
if err != nil {
61-
return nil, fmt.Errorf("unable to decode output index: %v", err)
62-
}
63-
64-
txid, err := chainhash.NewHashFromStr(split[0])
65-
if err != nil {
66-
return nil, fmt.Errorf("unable to parse hex string: %v", err)
67-
}
68-
69-
return &wire.OutPoint{
70-
Hash: *txid,
71-
Index: uint32(index),
72-
}, nil
73-
}
74-
7548
// ParseGenInfo converts a taprpc.GenesisInfo into its asset.Genesis
7649
// counterpart.
7750
func ParseGenInfo(t *testing.T, genInfo *taprpc.GenesisInfo) *asset.Genesis {
78-
genPoint, err := ParseOutPoint(genInfo.GenesisPoint)
51+
genPoint, err := wire.NewOutPointFromString(genInfo.GenesisPoint)
7952
require.NoError(t, err)
8053

8154
parsedGenesis := asset.Genesis{

0 commit comments

Comments
 (0)