Skip to content

Commit

Permalink
tappsbt: test decode handling of global Unknowns
Browse files Browse the repository at this point in the history
In this commit, we add a new test to ensure that if a Packet is missing
the Unknown values we need to identify VPackets, the decoder fails. We
also check that decoding does not fail if Unknown values unrelated to
VPackets are included.
  • Loading branch information
jharveyb committed Nov 7, 2024
1 parent 29a24de commit 33d6840
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions tappsbt/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"testing"

"github.com/btcsuite/btcd/btcutil/psbt"
"github.com/lightninglabs/taproot-assets/address"
"github.com/lightninglabs/taproot-assets/asset"
"github.com/lightninglabs/taproot-assets/commitment"
Expand Down Expand Up @@ -69,6 +70,73 @@ func assertEqualPackets(t *testing.T, expected, actual *VPacket) {
}
}

// TestGlobalUnknownFields tests that the global Unknown fields mandatory for a
// valid VPacket are present for an encoded VPacket. We also test that when
// decoding a VPacket from a Packet, a Packet with missing mandatory fields is
// rejected, and extra global Unknown fields are permitted.
func TestGlobalUnknownFields(t *testing.T) {
// Make a random packet.
pkg := RandPacket(t, false, false)

// An encoded valid packet should have exactly three global Unknown
// fields.
packet, err := pkg.EncodeAsPsbt()
require.NoError(t, err)
require.Len(t, packet.Unknowns, 3)

// Specifically, the isVirtual marker, HRP, and Version must be present.
requiredKeys := [][]byte{
PsbtKeyTypeGlobalTapIsVirtualTx,
PsbtKeyTypeGlobalTapChainParamsHRP,
PsbtKeyTypeGlobalTapPsbtVersion,
}
for _, key := range requiredKeys {
_, err := findCustomFieldsByKeyPrefix(packet.Unknowns, key)
require.NoError(t, err)
}

// Decoding a VPacket from this minimal Packet must succeed.
_, err = NewFromPsbt(packet)
require.NoError(t, err)

var packetBuf bytes.Buffer
err = packet.Serialize(&packetBuf)
require.NoError(t, err)

cloneBuffer := func(b *bytes.Buffer) *bytes.Buffer {
return bytes.NewBuffer(bytes.Clone(b.Bytes()))
}

// If we remove a mandatory VPacket field from the Packet, decoding
// must fail.
invalidPacketBytes := cloneBuffer(&packetBuf)
invalidPacket, err := psbt.NewFromRawBytes(invalidPacketBytes, false)
require.NoError(t, err)

invalidPacket.Unknowns = invalidPacket.Unknowns[1:]
_, err = NewFromPsbt(invalidPacket)
require.Error(t, err)

// If we add a global Unknown field to the valid Packet, decoding must
// still succeed.
extraPacketBytes := cloneBuffer(&packetBuf)
extraPacket, err := psbt.NewFromRawBytes(extraPacketBytes, false)
require.NoError(t, err)

// The VPacket global Unknown keys start at 0x70, so we'll use a key
// value very far from that.
extraUnknown := &psbt.Unknown{
Key: []byte{0xaa},
Value: []byte("really_cool_unknown_value"),
}
extraPacket.Unknowns = append(extraPacket.Unknowns, extraUnknown)

// The decoded VPacket should not contain the extra Unknown field, but
// the decoder should succeed.
_, err = NewFromPsbt(extraPacket)
require.NoError(t, err)
}

// TestEncodingDecoding tests the decoding of a virtual packet from raw bytes.
func TestEncodingDecoding(t *testing.T) {
t.Parallel()
Expand Down

0 comments on commit 33d6840

Please sign in to comment.