Skip to content

Commit

Permalink
asset: update DeepEqual to work with asset v1 (segwit)
Browse files Browse the repository at this point in the history
The asset version v1 (segwit) allows an asset to be committed without
the TxWitness field. Therefore, when comparing two such assets, we must
also ignore the TxWitness field.

If we don't do this, then the deep equal check when creating a proof for
a split asset fails when checking if the split root asset was committed
to the root tree.
  • Loading branch information
guggero committed Jan 29, 2024
1 parent 478e2bb commit 3e7d61d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
34 changes: 29 additions & 5 deletions asset/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,10 @@ func (w *Witness) Decode(r io.Reader) error {
return stream.Decode(r)
}

// DeepEqual returns true if this witness is equal with the given witness.
func (w *Witness) DeepEqual(o *Witness) bool {
// DeepEqual returns true if this witness is equal with the given witness. If
// the skipTxWitness boolean is set, the TxWitness field of the Witness is not
// compared.
func (w *Witness) DeepEqual(skipTxWitness bool, o *Witness) bool {
if w == nil || o == nil {
return w == o
}
Expand All @@ -436,11 +438,17 @@ func (w *Witness) DeepEqual(o *Witness) bool {
return false
}

if !reflect.DeepEqual(w.TxWitness, o.TxWitness) {
if !w.SplitCommitment.DeepEqual(o.SplitCommitment) {
return false
}

return w.SplitCommitment.DeepEqual(o.SplitCommitment)
// If we're not comparing the TxWitness, we're done. This might be
// useful when comparing witnesses of segregated witness version assets.
if skipTxWitness {
return true
}

return reflect.DeepEqual(w.TxWitness, o.TxWitness)
}

// ScriptVersion denotes the asset script versioning scheme.
Expand Down Expand Up @@ -1398,6 +1406,20 @@ func (a *Asset) Copy() *Asset {

// DeepEqual returns true if this asset is equal with the given asset.
func (a *Asset) DeepEqual(o *Asset) bool {
return a.deepEqual(false, o)
}

// DeepEqualAllowSegWitIgnoreTxWitness returns true if this asset is equal with
// the given asset, ignoring the TxWitness field of the Witness if the asset
// version is v1.
func (a *Asset) DeepEqualAllowSegWitIgnoreTxWitness(o *Asset) bool {
return a.deepEqual(true, o)
}

// deepEqual returns true if this asset is equal with the given asset. The
// allowSegWitIgnoreTxWitness flag is used to determine whether the TxWitness
// field of the Witness should be ignored if the asset version is v1.
func (a *Asset) deepEqual(allowSegWitIgnoreTxWitness bool, o *Asset) bool {
if a.Version != o.Version {
return false
}
Expand Down Expand Up @@ -1437,7 +1459,9 @@ func (a *Asset) DeepEqual(o *Asset) bool {
}

for i := range a.PrevWitnesses {
if !a.PrevWitnesses[i].DeepEqual(&o.PrevWitnesses[i]) {
oPrevWitness := &o.PrevWitnesses[i]
skipTxWitness := a.Version == V1 && allowSegWitIgnoreTxWitness
if !a.PrevWitnesses[i].DeepEqual(skipTxWitness, oPrevWitness) {
return false
}
}
Expand Down
8 changes: 7 additions & 1 deletion proof/append.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,13 @@ func CreateTransitionProof(prevOut wire.OutPoint,
}

// Make sure the committed asset matches the root asset exactly.
if !committedRoot.DeepEqual(rootAsset) {
// We allow the TxWitness to mismatch for assets with version 1
// as they would not include the witness when the proof is
// created.
if !committedRoot.DeepEqualAllowSegWitIgnoreTxWitness(
rootAsset,
) {

return nil, fmt.Errorf("root asset mismatch")
}

Expand Down

0 comments on commit 3e7d61d

Please sign in to comment.