Skip to content

Commit

Permalink
asset+proof: update GroupKeyRevealDecoder to handle multiple versions
Browse files Browse the repository at this point in the history
Enhance the GroupKeyRevealDecoder to first attempt decoding as
GroupKeyRevealV0. If this fails with a specific expected error,
fallback to decoding as GroupKeyRevealV1.
  • Loading branch information
ffranr committed Dec 10, 2024
1 parent 3927d7b commit edb5d85
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 6 deletions.
9 changes: 8 additions & 1 deletion asset/asset.go
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,13 @@ type GroupVirtualTx struct {
TweakedKey btcec.PublicKey
}

var (
// ErrGroupKeyRevealDecodeVersion is returned when the group key reveal
// version does not
ErrGroupKeyRevealDecodeVersion = errors.New("invalid decode version " +
"for group key reveal")
)

// GroupKeyReveal represents the data used to derive the adjusted key that
// uniquely identifies an asset group.
type GroupKeyReveal interface {
Expand Down Expand Up @@ -1244,7 +1251,7 @@ func (g *GroupKeyRevealV0) Decode(r io.Reader, buf *[8]byte, l uint64) error {
// is essential to prevent misinterpreting V1 and later group key
// reveals as V0.
if l > btcec.PubKeyBytesLenCompressed+sha256.Size {
return tlv.ErrRecordTooLarge
return ErrGroupKeyRevealDecodeVersion
}

if l < btcec.PubKeyBytesLenCompressed {
Expand Down
49 changes: 44 additions & 5 deletions proof/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package proof

import (
"bytes"
"errors"
"fmt"
"io"
"math"
Expand Down Expand Up @@ -483,14 +484,52 @@ func GroupKeyRevealDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
return tlv.NewTypeForEncodingErr(val, "GroupKeyReveal")
}

// Use a TeeReader to capture the read bytes, enabling the construction
// of a new reader for subsequent decoding attempts.
var readBuf bytes.Buffer
teeReader := io.TeeReader(r, &readBuf)

// Attempt decoding with GroupKeyRevealV0.
var gkrV0 asset.GroupKeyRevealV0
err := gkrV0.Decode(r, buf, l)
var (
gkrV0 asset.GroupKeyRevealV0
scratchBufV0 [8]byte
)

err := gkrV0.Decode(teeReader, &scratchBufV0, l)
if err != nil {
// If the error is not related to versioning, return the error.
errIsVersionRelated := errors.Is(
err, asset.ErrGroupKeyRevealDecodeVersion,
)
if !errIsVersionRelated {
return fmt.Errorf("group key reveal V0 decode "+
"error: %w", err)
}
}

// If the decoding was successful, set the value, the scratch buffer,
// and return.
if err == nil {
*typ = &gkrV0
*buf = scratchBufV0
return nil
}

// Attempt decoding with GroupKeyRevealV1.
var (
gkrV1 asset.GroupKeyRevealV1
scratchBufV1 [8]byte
newReader = bytes.NewReader(readBuf.Bytes())
)

err = gkrV1.Decode(newReader, &scratchBufV1, l)
if err != nil {
return fmt.Errorf("group key reveal V0 decode error: %w", err)
return fmt.Errorf("group key reveal V1 decode error: %w", err)
}

// If the decoding was successful, set the value and return.
*typ = &gkrV0
// If the decoding was successful, set the value, the scratch buffer,
// and return.
*typ = &gkrV1
*buf = scratchBufV1
return nil
}

0 comments on commit edb5d85

Please sign in to comment.