Skip to content

Commit

Permalink
tapfreighter: add PrepareAnchoringTemplate function
Browse files Browse the repository at this point in the history
  • Loading branch information
guggero committed Feb 13, 2024
1 parent 9ad5819 commit 120d5f0
Showing 1 changed file with 98 additions and 0 deletions.
98 changes: 98 additions & 0 deletions tapfreighter/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -1764,3 +1764,101 @@ func copyPsbt(packet *psbt.Packet) (*psbt.Packet, error) {

return psbt.NewFromRawBytes(&buf, false)
}

// PrepareAnchoringTemplate creates a BTC level PSBT packet that can be used to
// anchor the given virtual packets. The PSBT packet is created with the
// necessary inputs and outputs to anchor the virtual packets, but without any
// signatures.
func PrepareAnchoringTemplate(
vPackets []*tappsbt.VPacket) (*psbt.Packet, error) {

// Create output skeleton from the allocations.
var maxOutputIndex uint32
for _, vPkt := range vPackets {
for _, vOut := range vPkt.Outputs {
if vOut.AnchorOutputIndex > maxOutputIndex {
maxOutputIndex = vOut.AnchorOutputIndex
}
}
}

txTemplate := wire.NewMsgTx(2)
for i := uint32(0); i <= maxOutputIndex; i++ {
txTemplate.AddTxOut(createDummyOutput())
}

btcPacket, err := psbt.NewFromUnsignedTx(txTemplate)
if err != nil {
return nil, fmt.Errorf("unable to make psbt packet: %w", err)
}

// Populate output keys and values.
for _, vPkt := range vPackets {
for _, vOut := range vPkt.Outputs {
btcOut := &btcPacket.Outputs[vOut.AnchorOutputIndex]

btcOut.TaprootInternalKey = schnorr.SerializePubKey(
vOut.AnchorOutputInternalKey,
)

// TODO: Using the TaprootTapTree for storing the
// encode sibling preimage is wrong! We should require
// the full Tapscript tree to be provided and encode it
// in the BIP-0174 manner.
siblingBytes, _, err := commitment.MaybeEncodeTapscriptPreimage(
vOut.AnchorOutputTapscriptSibling,
)
if err != nil {
return nil, fmt.Errorf("unable to encode "+
"sibling preimage: %w", err)
}
btcOut.TaprootTapTree = siblingBytes
}
}

// Populate inputs.
for pIdx := range vPackets {
for iIdx := range vPackets[pIdx].Inputs {
vIn := vPackets[pIdx].Inputs[iIdx]
anchor := vIn.Anchor

if HasInput(btcPacket.UnsignedTx, vIn.PrevID.OutPoint) {
continue
}

btcPacket.Inputs = append(btcPacket.Inputs, psbt.PInput{
WitnessUtxo: &wire.TxOut{
Value: int64(anchor.Value),
PkScript: anchor.PkScript,
},
SighashType: anchor.SigHashType,
Bip32Derivation: anchor.Bip32Derivation,
TaprootBip32Derivation: anchor.TrBip32Derivation,
TaprootInternalKey: schnorr.SerializePubKey(
anchor.InternalKey,
),
TaprootMerkleRoot: anchor.MerkleRoot,
})
btcPacket.UnsignedTx.TxIn = append(
btcPacket.UnsignedTx.TxIn, &wire.TxIn{
PreviousOutPoint: vIn.PrevID.OutPoint,
},
)

}
}

return btcPacket, nil
}

// HasInput returns true if the given transaction has an input that spends the
// given outpoint.
func HasInput(tx *wire.MsgTx, outpoint wire.OutPoint) bool {
for _, in := range tx.TxIn {
if in.PreviousOutPoint == outpoint {
return true
}
}

return false
}

0 comments on commit 120d5f0

Please sign in to comment.