Skip to content

Commit a1bd7ce

Browse files
committed
proof: test genesis, group key reveal verification
1 parent 947272d commit a1bd7ce

File tree

5 files changed

+143
-58
lines changed

5 files changed

+143
-58
lines changed

proof/append_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func runAppendTransitionTest(t *testing.T, assetType asset.Type, amt uint64,
110110

111111
// Start with a minted genesis asset.
112112
genesisProof, senderPrivKey := genRandomGenesisWithProof(
113-
t, assetType, &amt, nil, true, nil, nil, assetVersion,
113+
t, assetType, &amt, nil, true, nil, nil, nil, nil, assetVersion,
114114
)
115115
genesisBlob, err := EncodeAsProofFile(&genesisProof)
116116
require.NoError(t, err)

proof/mint_test.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,8 @@ func TestNewMintingBlobs(t *testing.T) {
3636
assetGenesis := asset.RandGenesis(t, asset.Collectible)
3737
assetGenesis.MetaHash = metaReveal.MetaHash()
3838
assetGenesis.OutputIndex = 0
39-
protoAsset := asset.NewAssetNoErr(
40-
t, assetGenesis, 1, 0, 0,
41-
asset.NewScriptKeyBip86(genesisScriptKey), nil,
42-
)
43-
44-
assetGroupKey := asset.RandGroupKey(t, assetGenesis, protoAsset)
4539
tapCommitment, _, err := commitment.Mint(
46-
assetGenesis, assetGroupKey, &commitment.AssetDetails{
40+
assetGenesis, nil, &commitment.AssetDetails{
4741
Type: asset.Collectible,
4842
ScriptKey: genesisScriptKey,
4943
Amount: nil,
@@ -53,6 +47,23 @@ func TestNewMintingBlobs(t *testing.T) {
5347
)
5448
require.NoError(t, err)
5549

50+
// Add a group anchor with a custom tapscript root to the set of minted
51+
// assets. We cannot make this type of asset with commitment.Mint, so
52+
// we create it manually and then insert it into the tap commitment.
53+
groupedGenesis := asset.RandGenesis(t, asset.Normal)
54+
groupedGenesis.FirstPrevOut = assetGenesis.FirstPrevOut
55+
groupedGenesis.MetaHash = metaReveal.MetaHash()
56+
groupedGenesis.OutputIndex = 0
57+
// Issue here with one branch of useHashLock
58+
groupedAsset := asset.AssetCustomGroupKey(
59+
t, test.RandBool(), false, false, true, groupedGenesis,
60+
)
61+
62+
groupedAssetTree, err := commitment.NewAssetCommitment(groupedAsset)
63+
require.NoError(t, err)
64+
err = tapCommitment.Upsert(groupedAssetTree)
65+
require.NoError(t, err)
66+
5667
internalKey := test.SchnorrPubKey(t, genesisPrivKey)
5768
tapscriptRoot := tapCommitment.TapscriptRoot(nil)
5869
taprootKey := txscript.ComputeTaprootOutputKey(
@@ -89,11 +100,10 @@ func TestNewMintingBlobs(t *testing.T) {
89100
0, chaincfg.MainNetParams.GenesisHash, merkleRoot, 0, 0,
90101
)
91102

92-
newAsset := tapCommitment.CommittedAssets()[0]
93-
assetScriptKey := newAsset.ScriptKey
94-
103+
assetScriptKey := asset.NewScriptKeyBip86(genesisScriptKey)
95104
metaReveals := map[asset.SerializedKey]*MetaReveal{
96-
asset.ToSerialized(assetScriptKey.PubKey): metaReveal,
105+
asset.ToSerialized(assetScriptKey.PubKey): metaReveal,
106+
asset.ToSerialized(groupedAsset.ScriptKey.PubKey): metaReveal,
97107
}
98108

99109
// The NewMintingBlobs will return an error if the generated proof is

proof/proof.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ var (
5656
// proof for a genesis asset has a non-zero meta hash, but doesn't have
5757
// a meta reveal.
5858
ErrGenesisRevealMetaRevealRequired = errors.New("genesis meta reveal " +
59-
"reveal required")
59+
"required")
6060

6161
// ErrGenesisRevealMetaHashMismatch is an error returned if an asset
6262
// proof for a genesis asset has a genesis reveal where the meta hash
@@ -70,12 +70,6 @@ var (
7070
ErrGenesisRevealOutputIndexMismatch = errors.New("genesis reveal " +
7171
"output index mismatch")
7272

73-
// ErrGenesisRevealTypeMismatch is an error returned if an asset proof
74-
// for a genesis asset has a genesis reveal where the asset type doesn't
75-
// match the proof TLV field.
76-
ErrGenesisRevealTypeMismatch = errors.New("genesis reveal type " +
77-
"mismatch")
78-
7973
// ErrNonGenesisAssetWithGroupKeyReveal is an error returned if an asset
8074
// proof for a non-genesis asset contains a group key reveal.
8175
ErrNonGenesisAssetWithGroupKeyReveal = errors.New("non genesis asset " +

proof/proof_test.go

Lines changed: 111 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/btcsuite/btcd/txscript"
2121
"github.com/btcsuite/btcd/wire"
2222
"github.com/davecgh/go-spew/spew"
23+
"github.com/decred/dcrd/dcrec/secp256k1/v4"
2324
"github.com/lightninglabs/taproot-assets/asset"
2425
"github.com/lightninglabs/taproot-assets/commitment"
2526
"github.com/lightninglabs/taproot-assets/internal/test"
@@ -338,8 +339,9 @@ func TestProofEncoding(t *testing.T) {
338339

339340
func genRandomGenesisWithProof(t testing.TB, assetType asset.Type,
340341
amt *uint64, tapscriptPreimage *commitment.TapscriptPreimage,
341-
noMetaHash bool, metaReveal *MetaReveal,
342-
genesisMutator genMutator,
342+
noMetaHash bool, metaReveal *MetaReveal, genesisMutator genMutator,
343+
genesisRevealMutator genRevealMutator,
344+
groupRevealMutator groupRevealMutator,
343345
assetVersion asset.Version) (Proof, *btcec.PrivateKey) {
344346

345347
t.Helper()
@@ -372,13 +374,17 @@ func genRandomGenesisWithProof(t testing.TB, assetType asset.Type,
372374
asset.WithAssetVersion(assetVersion),
373375
)
374376
assetGroupKey := asset.RandGroupKey(t, assetGenesis, protoAsset)
375-
groupKeyReveal := asset.GroupKeyReveal{
377+
groupKeyReveal := &asset.GroupKeyReveal{
376378
RawKey: asset.ToSerialized(
377379
assetGroupKey.RawKey.PubKey,
378380
),
379381
TapscriptRoot: assetGroupKey.TapscriptRoot,
380382
}
381383

384+
if groupRevealMutator != nil {
385+
groupRevealMutator(groupKeyReveal)
386+
}
387+
382388
tapCommitment, assets, err := commitment.Mint(
383389
assetGenesis, assetGroupKey, &commitment.AssetDetails{
384390
Type: assetType,
@@ -436,6 +442,11 @@ func genRandomGenesisWithProof(t testing.TB, assetType asset.Type,
436442
txMerkleProof, err := NewTxMerkleProof([]*wire.MsgTx{genesisTx}, 0)
437443
require.NoError(t, err)
438444

445+
genReveal := &assetGenesis
446+
if genesisRevealMutator != nil {
447+
genReveal = genesisRevealMutator(genReveal)
448+
}
449+
439450
return Proof{
440451
PrevOut: assetGenesis.FirstPrevOut,
441452
BlockHeader: *blockHeader,
@@ -455,13 +466,17 @@ func genRandomGenesisWithProof(t testing.TB, assetType asset.Type,
455466
MetaReveal: metaReveal,
456467
ExclusionProofs: nil,
457468
AdditionalInputs: nil,
458-
GenesisReveal: &assetGenesis,
459-
GroupKeyReveal: &groupKeyReveal,
469+
GenesisReveal: genReveal,
470+
GroupKeyReveal: groupKeyReveal,
460471
}, genesisPrivKey
461472
}
462473

463474
type genMutator func(*asset.Genesis)
464475

476+
type groupRevealMutator func(*asset.GroupKeyReveal)
477+
478+
type genRevealMutator func(*asset.Genesis) *asset.Genesis
479+
465480
func TestGenesisProofVerification(t *testing.T) {
466481
t.Parallel()
467482

@@ -476,15 +491,18 @@ func TestGenesisProofVerification(t *testing.T) {
476491
amount := uint64(5000)
477492

478493
testCases := []struct {
479-
name string
480-
assetType asset.Type
481-
amount *uint64
482-
assetVersion asset.Version
483-
tapscriptPreimage *commitment.TapscriptPreimage
484-
metaReveal *MetaReveal
485-
noMetaHash bool
486-
genesisMutator genMutator
487-
expectedErr error
494+
name string
495+
assetType asset.Type
496+
amount *uint64
497+
assetVersion asset.Version
498+
tapscriptPreimage *commitment.TapscriptPreimage
499+
metaReveal *MetaReveal
500+
noMetaHash bool
501+
noGroup bool
502+
genesisMutator genMutator
503+
genesisRevealMutator genRevealMutator
504+
groupRevealMutator groupRevealMutator
505+
expectedErr error
488506
}{
489507
{
490508
name: "collectible genesis",
@@ -584,6 +602,78 @@ func TestGenesisProofVerification(t *testing.T) {
584602
assetType: asset.Collectible,
585603
expectedErr: ErrGenesisRevealMetaRevealRequired,
586604
},
605+
{
606+
name: "missing genesis reveal",
607+
assetType: asset.Collectible,
608+
noMetaHash: true,
609+
genesisRevealMutator: func(
610+
g *asset.Genesis) *asset.Genesis {
611+
612+
return nil
613+
},
614+
expectedErr: ErrGenesisRevealRequired,
615+
},
616+
{
617+
name: "genesis reveal asset ID mismatch",
618+
assetType: asset.Normal,
619+
amount: &amount,
620+
noMetaHash: true,
621+
genesisRevealMutator: func(
622+
g *asset.Genesis) *asset.Genesis {
623+
624+
gCopy := *g
625+
gCopy.Tag += "mismatch"
626+
return &gCopy
627+
},
628+
expectedErr: ErrGenesisRevealAssetIDMismatch,
629+
},
630+
{
631+
name: "genesis reveal prev out mismatch",
632+
assetType: asset.Collectible,
633+
genesisRevealMutator: func(
634+
g *asset.Genesis) *asset.Genesis {
635+
636+
gCopy := *g
637+
gCopy.FirstPrevOut = test.RandOp(t)
638+
return &gCopy
639+
},
640+
expectedErr: ErrGenesisRevealPrevOutMismatch,
641+
},
642+
{
643+
name: "genesis reveal output index mismatch",
644+
assetType: asset.Normal,
645+
amount: &amount,
646+
noMetaHash: true,
647+
genesisRevealMutator: func(
648+
g *asset.Genesis) *asset.Genesis {
649+
650+
gCopy := *g
651+
gCopy.OutputIndex = uint32(
652+
test.RandInt[int32](),
653+
)
654+
return &gCopy
655+
},
656+
expectedErr: ErrGenesisRevealOutputIndexMismatch,
657+
},
658+
{
659+
name: "group key reveal invalid key",
660+
assetType: asset.Collectible,
661+
noMetaHash: true,
662+
groupRevealMutator: func(gkr *asset.GroupKeyReveal) {
663+
gkr.RawKey[0] = 0x01
664+
},
665+
expectedErr: secp256k1.ErrPubKeyInvalidFormat,
666+
},
667+
{
668+
name: "group key reveal mismatched tweaked key",
669+
assetType: asset.Normal,
670+
amount: &amount,
671+
noMetaHash: true,
672+
groupRevealMutator: func(gkr *asset.GroupKeyReveal) {
673+
gkr.TapscriptRoot = test.RandBytes(32)
674+
},
675+
expectedErr: ErrGroupKeyRevealMismatch,
676+
},
587677
}
588678

589679
testVectors := &TestVectors{}
@@ -595,6 +685,7 @@ func TestGenesisProofVerification(t *testing.T) {
595685
tt, tc.assetType, tc.amount,
596686
tc.tapscriptPreimage, tc.noMetaHash,
597687
tc.metaReveal, tc.genesisMutator,
688+
tc.genesisRevealMutator, tc.groupRevealMutator,
598689
tc.assetVersion,
599690
)
600691
_, err := genesisProof.Verify(
@@ -635,7 +726,7 @@ func TestProofBlockHeaderVerification(t *testing.T) {
635726
t.Parallel()
636727

637728
proof, _ := genRandomGenesisWithProof(
638-
t, asset.Collectible, nil, nil, true, nil, nil, 0,
729+
t, asset.Collectible, nil, nil, true, nil, nil, nil, nil, 0,
639730
)
640731

641732
// Create a base reference for the block header and block height. We
@@ -793,7 +884,7 @@ func TestProofReplacement(t *testing.T) {
793884
amt := uint64(i + 1)
794885
assetVersion := asset.Version(i % 2)
795886
lotsOfProofs[i], _ = genRandomGenesisWithProof(
796-
t, asset.Normal, &amt, nil, false, nil, nil,
887+
t, asset.Normal, &amt, nil, false, nil, nil, nil, nil,
797888
assetVersion,
798889
)
799890
}
@@ -822,7 +913,7 @@ func TestProofReplacement(t *testing.T) {
822913
// We'll generate a random proof, and then replace a random
823914
// proof in the file with it.
824915
proof, _ := genRandomGenesisWithProof(
825-
t, asset.Normal, &amt, nil, false, nil, nil,
916+
t, asset.Normal, &amt, nil, false, nil, nil, nil, nil,
826917
assetVersion,
827918
)
828919
idx := test.RandIntn(numProofs)
@@ -836,15 +927,15 @@ func TestProofReplacement(t *testing.T) {
836927
// boundary conditions).
837928
amt := uint64(1337)
838929
firstProof, _ := genRandomGenesisWithProof(
839-
t, asset.Normal, &amt, nil, false, nil, nil, asset.V1,
930+
t, asset.Normal, &amt, nil, false, nil, nil, nil, nil, asset.V1,
840931
)
841932
err = f.ReplaceProofAt(0, firstProof)
842933
require.NoError(t, err)
843934
assertIndex(0, 1337)
844935

845936
amt = uint64(2016)
846937
lastProof, _ := genRandomGenesisWithProof(
847-
t, asset.Normal, &amt, nil, false, nil, nil, asset.V0,
938+
t, asset.Normal, &amt, nil, false, nil, nil, nil, nil, asset.V0,
848939
)
849940
err = f.ReplaceProofAt(uint32(f.NumProofs()-1), lastProof)
850941
require.NoError(t, err)
@@ -870,7 +961,7 @@ func BenchmarkProofEncoding(b *testing.B) {
870961

871962
// Start with a minted genesis asset.
872963
genesisProof, _ := genRandomGenesisWithProof(
873-
b, asset.Normal, &amt, nil, false, nil, nil, asset.V0,
964+
b, asset.Normal, &amt, nil, false, nil, nil, nil, nil, asset.V0,
874965
)
875966

876967
// We create a file with 10k proofs (the same one) and test encoding/

proof/verifier.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -285,20 +285,12 @@ func (p *Proof) verifyGenesisReveal() error {
285285
return ErrGenesisRevealRequired
286286
}
287287

288-
// The genesis reveal determines the ID of an asset, so make sure it is
289-
// consistent.
290-
assetID := p.Asset.ID()
291-
if reveal.ID() != assetID {
292-
return ErrGenesisRevealAssetIDMismatch
293-
}
294-
295-
// We also make sure the genesis reveal is consistent with the TLV
296-
// fields in the state transition proof.
288+
// Make sure the genesis reveal is consistent with the TLV fields in
289+
// the state transition proof.
297290
if reveal.FirstPrevOut != p.PrevOut {
298291
return ErrGenesisRevealPrevOutMismatch
299292
}
300293

301-
// TODO(roasbeef): enforce practical limit on size of meta reveal
302294
// If this asset has an empty meta reveal, then the meta hash must be
303295
// empty. Otherwise, the meta hash must match the meta reveal.
304296
var proofMeta [asset.MetaHashLen]byte
@@ -318,8 +310,13 @@ func (p *Proof) verifyGenesisReveal() error {
318310
return ErrGenesisRevealOutputIndexMismatch
319311
}
320312

321-
if reveal.Type != p.Asset.Type {
322-
return ErrGenesisRevealTypeMismatch
313+
// The genesis reveal determines the ID of an asset, so make sure it is
314+
// consistent. Since the asset ID commits to all fields of the genesis,
315+
// this is equivalent to checking equality for the genesis tag and type
316+
// fields that have not yet been verified.
317+
assetID := p.Asset.ID()
318+
if reveal.ID() != assetID {
319+
return ErrGenesisRevealAssetIDMismatch
323320
}
324321

325322
return nil
@@ -341,14 +338,7 @@ func (p *Proof) verfyGenesisGroupKey(groupVerifier GroupVerifier) error {
341338
// the same key as the group key specified for the asset.
342339
func (p *Proof) verifyGroupKeyReveal() error {
343340
groupKey := p.Asset.GroupKey
344-
if groupKey == nil {
345-
return ErrGroupKeyRequired
346-
}
347-
348341
reveal := p.GroupKeyReveal
349-
if reveal == nil {
350-
return ErrGroupKeyRevealRequired
351-
}
352342

353343
revealedKey, err := reveal.GroupPubKey(p.Asset.ID())
354344
if err != nil {

0 commit comments

Comments
 (0)