Skip to content

Commit 65eb88f

Browse files
committed
proof: verify stxo proofs if present in v0 proofs
Because we do not bump the proof version yet, but we still create v1 proofs, we at least verify them if they are present.
1 parent 608bed8 commit 65eb88f

File tree

2 files changed

+76
-9
lines changed

2 files changed

+76
-9
lines changed

proof/verifier.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,12 @@ func (p *Proof) verifyInclusionProof() (*commitment.TapCommitment, error) {
206206
ErrStxoInputProofMissing)
207207
}
208208

209-
// We ignore the STXO proofs if the proof signals version 0, or if there
210-
// are no STXO proofs present (because they're not needed for this type
211-
// of asset).
212-
if p.IsVersionV0() || !hasStxoProofs {
209+
// We ignore the STXO proofs if they're not needed for this type of
210+
// asset or if there are no STXO proofs. At this point we can be sure
211+
// that if they are needed they also are present (because of the check
212+
// above). If they are not needed, but still present we verify them for
213+
// good measure.
214+
if !p.Asset.IsTransferRoot() || !hasStxoProofs {
213215
return v0Commitment, nil
214216
}
215217

@@ -292,7 +294,7 @@ func (p *Proof) verifyExclusionProofs() (*commitment.TapCommitmentVersion,
292294
maps.Clone(p2trOutputs),
293295
)
294296
if err != nil {
295-
return nil, fmt.Errorf("error veryfying v0 exclusion proof: %w",
297+
return nil, fmt.Errorf("error verifying v0 exclusion proof: %w",
296298
err)
297299
}
298300

@@ -318,10 +320,12 @@ func (p *Proof) verifyExclusionProofs() (*commitment.TapCommitmentVersion,
318320
ErrStxoInputProofMissing)
319321
}
320322

321-
// We ignore the STXO proofs if the proof signals version 0, or if there
322-
// are no STXO proofs present (because they're not needed for this type
323-
// of asset).
324-
if p.IsVersionV0() || !hasStxoProofs {
323+
// We ignore the STXO proofs if they're not needed for this type of
324+
// asset or if there are no STXO proofs. At this point we can be sure
325+
// that if they are needed they also are present (because of the check
326+
// above). If they are not needed, but still present we verify them for
327+
// good measure.
328+
if !p.Asset.IsTransferRoot() || !hasStxoProofs {
325329
return assertVersionConsistency(commitVersions)
326330
}
327331

proof/verifier_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,44 @@ func TestVerifyV1InclusionProof(t *testing.T) {
453453
},
454454
expectedErrContains: "error verifying STXO proof: invalid " +
455455
"taproot proof",
456+
}, {
457+
name: "valid v0 and invalid v1 proofs but with v0 version",
458+
makeProof: func(t *testing.T) []*Proof {
459+
p, rootCommitments := makeV0InclusionProof(t)
460+
461+
// We add an STXO asset to the root commitment.
462+
_, key := addV1InclusionProof(
463+
t, p[0], rootCommitments[0], withAddStxoProof(),
464+
withUpdateAnchorTx(),
465+
)
466+
467+
// At this point both proofs are valid. But we want to
468+
// invalidate just the v1 proof, so we replace it by one
469+
// that is derived from a different commitment. We can
470+
// achieve that by downgrading the commitment and
471+
// re-deriving the same proof, without updating the
472+
// anchor output transaction.
473+
clonedCommitment, err := rootCommitments[0].Downgrade()
474+
require.NoError(t, err)
475+
476+
_, v1ProofOld, err := clonedCommitment.Proof(
477+
asset.EmptyGenesisID,
478+
p[0].Asset.AssetCommitmentKey(),
479+
)
480+
require.NoError(t, err)
481+
482+
cp := p[0].InclusionProof.CommitmentProof
483+
cp.STXOProofs[key] = *v1ProofOld
484+
485+
// We now have a invalid v1 proof, but the proof's
486+
// version is still set to 0. We do however expect the
487+
// verification to fail, since the v1 proof is present
488+
// and will be verified..
489+
490+
return p
491+
},
492+
expectedErrContains: "error verifying STXO proof: invalid " +
493+
"taproot proof",
456494
}, {
457495
name: "stxo proof missing",
458496
makeProof: func(t *testing.T) []*Proof {
@@ -670,6 +708,31 @@ func TestVerifyV1ExclusionProof(t *testing.T) {
670708

671709
return p
672710
},
711+
}, {
712+
name: "invalid v1 exclusion proof but with v0 version",
713+
makeProof: func(t *testing.T) []*Proof {
714+
p, _ := makeV0InclusionProof(t)
715+
716+
// We now correctly prove that the asset isn't in the
717+
// second output.
718+
emptyCommitment, err := commitment.NewTapCommitment(nil)
719+
require.NoError(t, err)
720+
721+
addV0ExclusionOutput(
722+
t, p[0], emptyCommitment,
723+
p[0].Asset.TapCommitmentKey(),
724+
p[0].Asset.AssetCommitmentKey(), internalKey, 1,
725+
)
726+
727+
randAsset := makeTransferAsset(t)
728+
addV1ExclusionProof(
729+
t, p[0], *randAsset, emptyCommitment, 1,
730+
)
731+
732+
return p
733+
},
734+
expectedErrContains: "error verifying v1 exclusion proof: " +
735+
"missing STXO asset for key",
673736
}, {
674737
name: "multiple assets with an exclusion proof each",
675738
makeProof: func(t *testing.T) []*Proof {

0 commit comments

Comments
 (0)