Skip to content

Commit 5c5fcf8

Browse files
committed
tappsbt: add AltLeaves to VInput and VOutput
1 parent 0319458 commit 5c5fcf8

File tree

3 files changed

+56
-3
lines changed

3 files changed

+56
-3
lines changed

tappsbt/decode.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ func (i *VInput) decode(pIn psbt.PInput) error {
179179
}, {
180180
key: PsbtKeyTypeInputTapAssetProof,
181181
decoder: proofDecoder(&i.Proof),
182+
}, {
183+
key: PsbtKeyTypeInputAltLeaves,
184+
decoder: altLeavesDecoder(&i.AltLeaves),
182185
}}
183186

184187
for idx := range mapping {
@@ -308,8 +311,10 @@ func (o *VOutput) decode(pOut psbt.POutput, txOut *wire.TxOut) error {
308311
{
309312
key: PsbtKeyTypeOutputTapAssetRelativeLockTime,
310313
decoder: tlvDecoder(&o.RelativeLockTime, tlv.DUint64),
311-
},
312-
}
314+
}, {
315+
key: PsbtKeyTypeOutputTapAltLeaves,
316+
decoder: altLeavesDecoder(&o.AltLeaves),
317+
}}
313318

314319
for idx := range mapping {
315320
unknown, err := findCustomFieldsByKeyPrefix(
@@ -366,6 +371,17 @@ func proofDecoder(p **proof.Proof) decoderFunc {
366371
}
367372
}
368373

374+
// altLeavesDecoder returns a decoder function that can handle nil alt leaves.
375+
func altLeavesDecoder(a *[]AltLeafAsset) decoderFunc {
376+
return func(key, byteVal []byte) error {
377+
if len(byteVal) == 0 {
378+
return nil
379+
}
380+
381+
return tlvDecoder(a, asset.AltLeavesDecoder)(key, byteVal)
382+
}
383+
}
384+
369385
// assetDecoder returns a decoder function that can handle nil assets.
370386
func assetDecoder(a **asset.Asset) decoderFunc {
371387
return func(key, byteVal []byte) error {

tappsbt/encode.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ func (i *VInput) encode() (psbt.PInput, error) {
185185
{
186186
key: PsbtKeyTypeInputTapAssetProof,
187187
encoder: proofEncoder(i.Proof),
188+
}, {
189+
key: PsbtKeyTypeInputAltLeaves,
190+
encoder: altLeavesEncoder(i.AltLeaves),
188191
},
189192
}
190193

@@ -300,6 +303,9 @@ func (o *VOutput) encode(coinType uint32) (psbt.POutput, *wire.TxOut, error) {
300303
{
301304
key: PsbtKeyTypeOutputTapAssetRelativeLockTime,
302305
encoder: tlvEncoder(&o.RelativeLockTime, tlv.EUint64),
306+
}, {
307+
key: PsbtKeyTypeOutputTapAltLeaves,
308+
encoder: altLeavesEncoder(o.AltLeaves),
303309
},
304310
}
305311

@@ -377,6 +383,18 @@ func proofEncoder(p *proof.Proof) encoderFunc {
377383
}
378384
}
379385

386+
// altLeavesEncoder is an encoder that does nothing if the given alt leaf slice
387+
// is nil.
388+
func altLeavesEncoder(a []AltLeafAsset) encoderFunc {
389+
if a == nil {
390+
return func([]byte) ([]*customPsbtField, error) {
391+
return nil, nil
392+
}
393+
}
394+
395+
return tlvEncoder(&a, asset.AltLeavesEncoder)
396+
}
397+
380398
// assetEncoder is an encoder that does nothing if the given asset is nil.
381399
func assetEncoder(a *asset.Asset) encoderFunc {
382400
if a == nil {

tappsbt/interface.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ var (
4242
PsbtKeyTypeInputTapAnchorTapscriptSibling = []byte{0x78}
4343
PsbtKeyTypeInputTapAsset = []byte{0x79}
4444
PsbtKeyTypeInputTapAssetProof = []byte{0x7a}
45+
PsbtKeyTypeInputAltLeaves = []byte{0x7b}
4546

4647
PsbtKeyTypeOutputTapType = []byte{0x70}
4748
PsbtKeyTypeOutputTapIsInteractive = []byte{0x71}
@@ -57,6 +58,7 @@ var (
5758
PsbtKeyTypeOutputTapAssetProofSuffix = []byte{0x7b}
5859
PsbtKeyTypeOutputTapAssetLockTime = []byte{0x7c}
5960
PsbtKeyTypeOutputTapAssetRelativeLockTime = []byte{0x7d}
61+
PsbtKeyTypeOutputTapAltLeaves = []byte{0x7e}
6062
)
6163

6264
// The following keys are used as custom fields on the BTC level anchor
@@ -104,6 +106,9 @@ type bip32DerivationPredicate func(*psbt.Bip32Derivation) bool
104106
// BIP-0032 derivation paths.
105107
type taprootBip32DerivationPredicate func(*psbt.TaprootBip32Derivation) bool
106108

109+
// AltLeafAsset is an AltLeaf backed by an Asset object.
110+
type AltLeafAsset = asset.AltLeaf[*asset.Asset]
111+
107112
var (
108113
// VOutIsSplitRoot is a predicate that returns true if the virtual
109114
// output is a split root output.
@@ -370,6 +375,12 @@ type VInput struct {
370375
// Proof is a transition proof that proves the asset being spent was
371376
// committed to in the anchor transaction above.
372377
Proof *proof.Proof
378+
379+
// AltLeaves represent data used to construct an Asset commitment, that
380+
// will be inserted in the input anchor Tap commitment. These
381+
// data-carrying leaves are used for a purpose distinct from
382+
// representing individual Taproot Assets.
383+
AltLeaves []AltLeafAsset
373384
}
374385

375386
// Copy creates a deep copy of the VInput.
@@ -382,7 +393,8 @@ func (i *VInput) Copy() *VInput {
382393
// We never expect the individual fields of the proof to change
383394
// while it is assigned to a virtual input. So not deep copying
384395
// it here is fine.
385-
Proof: i.Proof,
396+
Proof: i.Proof,
397+
AltLeaves: asset.CopyAltLeaves(i.AltLeaves),
386398
}
387399
}
388400

@@ -563,6 +575,12 @@ type VOutput struct {
563575
// since the header information needs to be added once the anchor
564576
// transaction was confirmed in a block.
565577
ProofSuffix *proof.Proof
578+
579+
// AltLeaves represent data used to construct an Asset commitment, that
580+
// will be inserted in the output anchor Tap commitment. These
581+
// data-carrying leaves are used for a purpose distinct from
582+
// representing individual Taproot Assets.
583+
AltLeaves []AltLeafAsset
566584
}
567585

568586
// Copy creates a deep copy of the VOutput.
@@ -590,6 +608,7 @@ func (o *VOutput) Copy() *VOutput {
590608
ScriptKey: o.ScriptKey,
591609
ProofDeliveryAddress: o.ProofDeliveryAddress,
592610
ProofSuffix: o.ProofSuffix,
611+
AltLeaves: asset.CopyAltLeaves(o.AltLeaves),
593612
}
594613
}
595614

0 commit comments

Comments
 (0)