Skip to content

Commit add6bb4

Browse files
author
ffranr
authored
Merge pull request #1364 from lightninglabs/trustless-swap-uni-rpc
taprpc: Add new taprpc.RegisterTransfer RPC as a safe alternative to devrpc.ImportProof
2 parents bf9fbad + 7113c3c commit add6bb4

22 files changed

+2110
-890
lines changed

cmd/commands/proofs.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var proofCommands = []cli.Command{
2222
Subcommands: []cli.Command{
2323
verifyProofCommand,
2424
decodeProofCommand,
25+
unpackProofFileCommand,
2526
exportProofCommand,
2627
proveOwnershipCommand,
2728
verifyOwnershipCommand,
@@ -145,7 +146,56 @@ func decodeProof(ctx *cli.Context) error {
145146

146147
resp, err := client.DecodeProof(ctxc, req)
147148
if err != nil {
148-
return fmt.Errorf("unable to verify file: %w", err)
149+
return fmt.Errorf("unable to decode file: %w", err)
150+
}
151+
152+
printRespJSON(resp)
153+
return nil
154+
}
155+
156+
var unpackProofFileCommand = cli.Command{
157+
Name: "unpack",
158+
ShortName: "u",
159+
Usage: "unpack a Taproot Asset proof file into individual raw " +
160+
"proofs",
161+
Description: `
162+
Unpacks a taproot asset proof file that contains the full provenance of
163+
an asset into its individual raw proofs, in the order they appear in the
164+
proof file.
165+
`,
166+
Flags: []cli.Flag{
167+
cli.StringFlag{
168+
Name: proofPathName,
169+
Usage: "the path to the proof file on disk; use the " +
170+
"dash character (-) to read from stdin instead",
171+
},
172+
},
173+
Action: unpackProofFile,
174+
}
175+
176+
func unpackProofFile(ctx *cli.Context) error {
177+
ctxc := getContext()
178+
client, cleanUp := getClient(ctx)
179+
defer cleanUp()
180+
181+
if !ctx.IsSet(proofPathName) {
182+
_ = cli.ShowCommandHelp(ctx, "unpack")
183+
return nil
184+
}
185+
186+
filePath := lncfg.CleanAndExpandPath(ctx.String(proofPathName))
187+
rawFile, err := readFile(filePath)
188+
if err != nil {
189+
return fmt.Errorf("unable to read proof file: %w", err)
190+
}
191+
192+
resp, err := client.UnpackProofFile(
193+
ctxc, &taprpc.UnpackProofFileRequest{
194+
RawProofFile: rawFile,
195+
},
196+
)
197+
if err != nil {
198+
return fmt.Errorf("unable to unpack file: %w", err)
149199
}
150200

151201
printRespJSON(resp)

itest/addrs_test.go

Lines changed: 27 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"context"
66

7-
"github.com/btcsuite/btcd/btcec/v2"
87
"github.com/btcsuite/btcd/btcec/v2/schnorr"
98
"github.com/btcsuite/btcd/wire"
109
tap "github.com/lightninglabs/taproot-assets"
@@ -19,7 +18,6 @@ import (
1918
"github.com/lightninglabs/taproot-assets/taprpc"
2019
wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
2120
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
22-
"github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc"
2321
unirpc "github.com/lightninglabs/taproot-assets/taprpc/universerpc"
2422
"github.com/lightninglabs/taproot-assets/universe"
2523
"github.com/lightningnetwork/lnd/lntest/wait"
@@ -184,7 +182,7 @@ func testAddresses(t *harnessTest) {
184182
},
185183
Amount: 22,
186184
}
187-
manualAsset, mintProof := ManualMintSimpleAsset(
185+
manualAsset, mintProofBlob, mintOP := ManualMintSimpleAsset(
188186
t, t.lndHarness.Alice, t.tapd, commitment.TapCommitmentV0, &req,
189187
)
190188

@@ -193,12 +191,11 @@ func testAddresses(t *harnessTest) {
193191
respJSON, err := formatProtoJSON(manualAsset)
194192
require.NoError(t.t, err)
195193

196-
t.Logf("manually minted asset: %s", respJSON)
194+
t.Logf("Manually minted asset: %s", respJSON)
197195

198196
// Import the issuance proof to the second node so we can try to receive
199197
// it.
200-
_, err = secondTapd.ImportProof(ctxb, mintProof)
201-
require.NoError(t.t, err)
198+
ImportProofFileDeprecated(t, secondTapd, mintProofBlob, mintOP)
202199

203200
// Trying to receive the new asset to a version 0 address should
204201
// succeed.
@@ -776,7 +773,9 @@ func testUnknownTlvType(t *harnessTest) {
776773
require.NoError(t.t, charlie.stop(!*noDelete))
777774
}()
778775

779-
importProof(t, charlie, modifiedBlob, genInfo.GenesisPoint)
776+
ImportProofFileDeprecated(
777+
t, charlie, modifiedBlob, genInfo.GenesisPoint,
778+
)
780779

781780
// When we export it again, it should have the same TLV types.
782781
transferProof2 := exportProof(
@@ -844,10 +843,10 @@ func testUnknownTlvType(t *harnessTest) {
844843
// using the development only ImportProof RPC on the destination node.
845844
func sendProof(t *harnessTest, src, dst *tapdHarness,
846845
sendResp *taprpc.SendAssetResponse, scriptKey []byte,
847-
genInfo *taprpc.GenesisInfo) *tapdevrpc.ImportProofResponse {
846+
genInfo *taprpc.GenesisInfo) {
848847

849848
proofResp := exportProof(t, src, sendResp, scriptKey, genInfo)
850-
return importProof(t, dst, proofResp.RawProofFile, genInfo.GenesisPoint)
849+
ImportProofFile(t, dst, proofResp.RawProofFile)
851850
}
852851

853852
// exportProof manually exports a proof from the given source node for a
@@ -856,8 +855,6 @@ func exportProof(t *harnessTest, src *tapdHarness,
856855
sendResp *taprpc.SendAssetResponse, scriptKey []byte,
857856
genInfo *taprpc.GenesisInfo) *taprpc.ProofFile {
858857

859-
ctxb := context.Background()
860-
861858
// We need to find the outpoint of the asset we sent to the address.
862859
var outpoint *taprpc.OutPoint
863860
for _, out := range sendResp.Transfer.Outputs {
@@ -874,212 +871,44 @@ func exportProof(t *harnessTest, src *tapdHarness,
874871
}
875872
}
876873

877-
var proofResp *taprpc.ProofFile
878-
waitErr := wait.NoError(func() error {
879-
resp, err := src.ExportProof(ctxb, &taprpc.ExportProofRequest{
880-
AssetId: genInfo.AssetId,
881-
ScriptKey: scriptKey,
882-
Outpoint: outpoint,
883-
})
884-
if err != nil {
885-
return err
886-
}
887-
888-
proofResp = resp
889-
return nil
890-
}, defaultWaitTimeout)
891-
require.NoError(t.t, waitErr)
892-
893-
return proofResp
874+
return ExportProofFile(t.t, src, genInfo.AssetId, scriptKey, outpoint)
894875
}
895876

896-
// importProof manually imports a proof using the development only ImportProof
897-
// RPC.
898-
func importProof(t *harnessTest, dst *tapdHarness, rawFile []byte,
899-
genesisPoint string) *tapdevrpc.ImportProofResponse {
900-
901-
t.Logf("Importing proof %x", rawFile)
902-
903-
ctxb := context.Background()
904-
importResp, err := dst.ImportProof(ctxb, &tapdevrpc.ImportProofRequest{
905-
ProofFile: rawFile,
906-
GenesisPoint: genesisPoint,
907-
})
908-
require.NoError(t.t, err)
909-
910-
return importResp
911-
}
912-
913-
// sendUniProof manually exports a proof from the given source using the
914-
// universe RPCs and then imports it into the destination node.
915-
func sendUniProof(t *harnessTest, src, dst *tapdHarness, scriptKey []byte,
916-
genInfo *taprpc.GenesisInfo, group *taprpc.AssetGroup,
917-
outpoint string) *tapdevrpc.ImportProofResponse {
918-
919-
ctxb := context.Background()
920-
ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout)
921-
defer cancel()
922-
923-
fetchUniProof := func(ctx context.Context,
924-
loc proof.Locator) (proof.Blob, error) {
925-
926-
uniID := universe.Identifier{
927-
AssetID: *loc.AssetID,
928-
}
929-
if loc.GroupKey != nil {
930-
uniID.GroupKey = loc.GroupKey
931-
}
932-
933-
rpcUniID, err := tap.MarshalUniID(uniID)
934-
require.NoError(t.t, err)
935-
936-
op := &unirpc.Outpoint{
937-
HashStr: loc.OutPoint.Hash.String(),
938-
Index: int32(loc.OutPoint.Index),
939-
}
940-
scriptKeyBytes := loc.ScriptKey.SerializeCompressed()
941-
942-
uniProof, err := src.QueryProof(ctx, &unirpc.UniverseKey{
943-
Id: rpcUniID,
944-
LeafKey: &unirpc.AssetKey{
945-
Outpoint: &unirpc.AssetKey_Op{
946-
Op: op,
947-
},
948-
ScriptKey: &unirpc.AssetKey_ScriptKeyBytes{
949-
ScriptKeyBytes: scriptKeyBytes,
950-
},
951-
},
952-
})
953-
if err != nil {
954-
return nil, err
955-
}
956-
957-
return uniProof.AssetLeaf.Proof, nil
958-
}
959-
960-
var assetID asset.ID
961-
copy(assetID[:], genInfo.AssetId)
962-
963-
scriptPubKey, err := btcec.ParsePubKey(scriptKey)
964-
require.NoError(t.t, err)
965-
966-
op, err := wire.NewOutPointFromString(outpoint)
967-
require.NoError(t.t, err)
968-
969-
loc := proof.Locator{
970-
AssetID: &assetID,
971-
ScriptKey: *scriptPubKey,
972-
OutPoint: op,
973-
}
974-
975-
if group != nil {
976-
groupKey, err := btcec.ParsePubKey(group.TweakedGroupKey)
977-
require.NoError(t.t, err)
978-
979-
loc.GroupKey = groupKey
980-
}
877+
// transferProofUniRPC manually exports a proof from the given source using the
878+
// universe RPCs and then inserts it into the destination node's universe.
879+
func transferProofUniRPC(t *harnessTest, src, dst *tapdHarness,
880+
scriptKey []byte, genInfo *taprpc.GenesisInfo, group *taprpc.AssetGroup,
881+
outpoint string) *unirpc.AssetProofResponse {
981882

982-
var proofFile *proof.File
983-
err = wait.NoError(func() error {
984-
proofFile, err = proof.FetchProofProvenance(
985-
ctxt, nil, loc, fetchUniProof,
986-
)
987-
return err
988-
}, defaultWaitTimeout)
989-
require.NoError(t.t, err)
990-
991-
var buf bytes.Buffer
992-
err = proofFile.Encode(&buf)
993-
require.NoError(t.t, err)
994-
995-
t.Logf("Importing proof %x", buf.Bytes())
883+
proofFile := ExportProofFileFromUniverse(
884+
t.t, src, genInfo.AssetId, scriptKey, outpoint, group,
885+
)
996886

997-
importResp, err := dst.ImportProof(ctxb, &tapdevrpc.ImportProofRequest{
998-
ProofFile: buf.Bytes(),
999-
GenesisPoint: genInfo.GenesisPoint,
1000-
})
887+
lastProof, err := proofFile.RawLastProof()
1001888
require.NoError(t.t, err)
1002889

1003-
return importResp
890+
return InsertProofIntoUniverse(t.t, dst, lastProof)
1004891
}
1005892

1006-
// sendProofUniRPC manually exports a proof from the given source node and
1007-
// imports it using the universe related InsertProof RPC on the destination
1008-
// node.
1009-
func sendProofUniRPC(t *harnessTest, src, dst *tapdHarness, scriptKey []byte,
893+
// transferProofNormalExportUniInsert manually exports a proof from the given
894+
// source node and imports it using the universe related InsertProof RPC on the
895+
// destination node.
896+
func transferProofNormalExportUniInsert(t *harnessTest, src, dst *tapdHarness,
897+
scriptKey []byte,
1010898
genInfo *taprpc.GenesisInfo) *unirpc.AssetProofResponse {
1011899

1012-
ctxb := context.Background()
1013-
1014-
var proofResp *taprpc.ProofFile
1015-
waitErr := wait.NoError(func() error {
1016-
resp, err := src.ExportProof(ctxb, &taprpc.ExportProofRequest{
1017-
AssetId: genInfo.AssetId,
1018-
ScriptKey: scriptKey,
1019-
})
1020-
if err != nil {
1021-
return err
1022-
}
1023-
1024-
proofResp = resp
1025-
return nil
1026-
}, defaultWaitTimeout)
1027-
require.NoError(t.t, waitErr)
900+
proofResp := ExportProofFile(t.t, src, genInfo.AssetId, scriptKey, nil)
1028901

1029902
t.Logf("Importing proof %x using InsertProof", proofResp.RawProofFile)
1030903

1031904
f := proof.File{}
1032905
err := f.Decode(bytes.NewReader(proofResp.RawProofFile))
1033906
require.NoError(t.t, err)
1034907

1035-
lastProof, err := f.LastProof()
1036-
require.NoError(t.t, err)
1037-
1038-
var lastProofBytes bytes.Buffer
1039-
err = lastProof.Encode(&lastProofBytes)
1040-
require.NoError(t.t, err)
1041-
asset := lastProof.Asset
1042-
1043-
proofType := universe.ProofTypeTransfer
1044-
if asset.IsGenesisAsset() {
1045-
proofType = universe.ProofTypeIssuance
1046-
}
1047-
1048-
uniID := universe.Identifier{
1049-
AssetID: asset.ID(),
1050-
ProofType: proofType,
1051-
}
1052-
if asset.GroupKey != nil {
1053-
uniID.GroupKey = &asset.GroupKey.GroupPubKey
1054-
}
1055-
1056-
rpcUniID, err := tap.MarshalUniID(uniID)
1057-
require.NoError(t.t, err)
1058-
1059-
outpoint := &unirpc.Outpoint{
1060-
HashStr: lastProof.AnchorTx.TxHash().String(),
1061-
Index: int32(lastProof.InclusionProof.OutputIndex),
1062-
}
1063-
1064-
importResp, err := dst.InsertProof(ctxb, &unirpc.AssetProof{
1065-
Key: &unirpc.UniverseKey{
1066-
Id: rpcUniID,
1067-
LeafKey: &unirpc.AssetKey{
1068-
Outpoint: &unirpc.AssetKey_Op{
1069-
Op: outpoint,
1070-
},
1071-
ScriptKey: &unirpc.AssetKey_ScriptKeyBytes{
1072-
ScriptKeyBytes: scriptKey,
1073-
},
1074-
},
1075-
},
1076-
AssetLeaf: &unirpc.AssetLeaf{
1077-
Proof: lastProofBytes.Bytes(),
1078-
},
1079-
})
908+
lastProof, err := f.RawLastProof()
1080909
require.NoError(t.t, err)
1081910

1082-
return importResp
911+
return InsertProofIntoUniverse(t.t, dst, lastProof)
1083912
}
1084913

1085914
// sendOptions is a struct that holds a SendAssetRequest and an

itest/assets_test.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/lightninglabs/taproot-assets/taprpc"
2222
wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
2323
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
24-
"github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc"
2524
"github.com/lightningnetwork/lnd/lnrpc"
2625
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
2726
"github.com/stretchr/testify/require"
@@ -238,11 +237,7 @@ func transferAssetProofs(t *harnessTest, src, dst *tapdHarness,
238237
proofFile := AssertAssetProofs(
239238
t.t, src, chainClient, existingAsset,
240239
)
241-
_, err := dst.ImportProof(ctxt, &tapdevrpc.ImportProofRequest{
242-
ProofFile: proofFile,
243-
GenesisPoint: gen.GenesisPoint,
244-
})
245-
require.NoError(t.t, err)
240+
ImportProofFileDeprecated(t, dst, proofFile, gen.GenesisPoint)
246241
}
247242

248243
listResp, err := dst.ListAssets(

0 commit comments

Comments
 (0)