Files
ark/common/bitcointree/pending.go
Louis Singer 12d666bfdf Move redeem transactions creation client-side (#388)
* move OOR transaction creation client-side

* robust redeem tx checks

* optimize GetVtxos db call

* rename CompleteAsyncPayment --> SubmitRedeemTx

* fix permissions.go
2024-11-25 13:38:04 +01:00

81 lines
1.8 KiB
Go

package bitcointree
import (
"fmt"
"github.com/ark-network/ark/common"
"github.com/btcsuite/btcd/btcutil/psbt"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
)
func BuildRedeemTx(
vtxos []common.VtxoInput,
outputs []*wire.TxOut,
feeAmount int64,
) (string, error) {
if len(vtxos) <= 0 {
return "", fmt.Errorf("missing vtxos")
}
ins := make([]*wire.OutPoint, 0, len(vtxos))
witnessUtxos := make(map[int]*wire.TxOut)
tapscripts := make(map[int]*psbt.TaprootTapLeafScript)
for index, vtxo := range vtxos {
rootHash := vtxo.Tapscript.ControlBlock.RootHash(vtxo.Tapscript.RevealedScript)
taprootKey := txscript.ComputeTaprootOutputKey(UnspendableKey(), rootHash)
vtxoOutputScript, err := common.P2TRScript(taprootKey)
if err != nil {
return "", err
}
witnessUtxos[index] = &wire.TxOut{
Value: vtxo.Amount,
PkScript: vtxoOutputScript,
}
ctrlBlockBytes, err := vtxo.Tapscript.ControlBlock.ToBytes()
if err != nil {
return "", err
}
tapscripts[index] = &psbt.TaprootTapLeafScript{
ControlBlock: ctrlBlockBytes,
Script: vtxo.Tapscript.RevealedScript,
LeafVersion: txscript.BaseLeafVersion,
}
ins = append(ins, vtxo.Outpoint)
}
if feeAmount >= outputs[len(outputs)-1].Value {
return "", fmt.Errorf("redeem tx fee is higher than the amount of the change receiver")
}
sequences := make([]uint32, len(ins))
for i := range sequences {
sequences[i] = wire.MaxTxInSequenceNum
}
redeemPtx, err := psbt.New(
ins, outputs, 2, 0, sequences,
)
if err != nil {
return "", err
}
for i := range redeemPtx.Inputs {
redeemPtx.Inputs[i].WitnessUtxo = witnessUtxos[i]
redeemPtx.Inputs[i].TaprootLeafScript = []*psbt.TaprootTapLeafScript{tapscripts[i]}
}
redeemTx, err := redeemPtx.B64Encode()
if err != nil {
return "", err
}
return redeemTx, nil
}