11package types
22
33import (
4+ "github.com/btcsuite/btcd/blockchain"
5+ "github.com/btcsuite/btcd/btcutil"
46 "github.com/btcsuite/btcd/btcutil/psbt"
57 "github.com/btcsuite/btcd/chaincfg/chainhash"
6- "github.com/btcsuite/btcd/txscript "
8+ "github.com/btcsuite/btcd/mempool "
79 "github.com/btcsuite/btcd/wire"
810
911 btcbridgetypes "github.com/sideprotocol/side/x/btcbridge/types"
@@ -13,18 +15,15 @@ const (
1315 // default tx version
1416 TxVersion = 2
1517
16- // default sig hash type
17- DefaultSigHashType = txscript .SigHashDefault
18-
19- // default fee rate
20- DefaultFeeRate = int64 (1 )
18+ // default maximum allowed transaction weight
19+ MaxTransactionWeight = 400000
2120)
2221
2322// BuildPsbt builds a psbt from the given params
24- func BuildPsbt (utxos []* btcbridgetypes.UTXO , recipientPkScript []byte , feeRate int64 ) (* psbt.Packet , error ) {
23+ func BuildPsbt (utxos []* btcbridgetypes.UTXO , recipientPkScript []byte , feeRate int64 , witnessSize int ) (* psbt.Packet , error ) {
2524 txOut := wire .NewTxOut (0 , recipientPkScript )
2625
27- unsignedTx , err := BuildUnsignedTransaction (utxos , txOut , feeRate )
26+ unsignedTx , err := BuildUnsignedTransaction (utxos , txOut , feeRate , witnessSize )
2827 if err != nil {
2928 return nil , err
3029 }
@@ -35,15 +34,14 @@ func BuildPsbt(utxos []*btcbridgetypes.UTXO, recipientPkScript []byte, feeRate i
3534 }
3635
3736 for i , utxo := range utxos {
38- p .Inputs [i ].SighashType = DefaultSigHashType
3937 p .Inputs [i ].WitnessUtxo = wire .NewTxOut (int64 (utxo .Amount ), utxo .PubKeyScript )
4038 }
4139
4240 return p , nil
4341}
4442
4543// BuildUnsignedTransaction builds an unsigned tx from the given params
46- func BuildUnsignedTransaction (utxos []* btcbridgetypes.UTXO , txOut * wire.TxOut , feeRate int64 ) (* wire.MsgTx , error ) {
44+ func BuildUnsignedTransaction (utxos []* btcbridgetypes.UTXO , txOut * wire.TxOut , feeRate int64 , witnessSize int ) (* wire.MsgTx , error ) {
4745 tx := wire .NewMsgTx (TxVersion )
4846
4947 inAmount := int64 (0 )
@@ -56,19 +54,19 @@ func BuildUnsignedTransaction(utxos []*btcbridgetypes.UTXO, txOut *wire.TxOut, f
5654
5755 tx .AddTxOut (txOut )
5856
59- fee := btcbridgetypes . GetTxVirtualSize (tx , utxos ) * feeRate
57+ fee := GetTxVirtualSize (tx , witnessSize ) * feeRate
6058
6159 change := inAmount - outAmount - fee
6260 if change <= 0 {
63- return nil , ErrFailedToBuildTx
61+ return nil , ErrInsufficientUTXOs
6462 }
6563
6664 txOut .Value += change
6765 if btcbridgetypes .IsDustOut (txOut ) {
68- return nil , ErrFailedToBuildTx
66+ return nil , ErrDustOutput
6967 }
7068
71- if err := btcbridgetypes . CheckTransactionWeight (tx , utxos ); err != nil {
69+ if err := CheckTransactionWeight (tx , witnessSize ); err != nil {
7270 return nil , err
7371 }
7472
@@ -89,3 +87,36 @@ func AddUTXOToTx(tx *wire.MsgTx, utxo *btcbridgetypes.UTXO) {
8987
9088 tx .AddTxIn (txIn )
9189}
90+
91+ // GetTxVirtualSize gets the virtual size of the given tx.
92+ func GetTxVirtualSize (tx * wire.MsgTx , witnessSize int ) int64 {
93+ newTx := PopulateTxWithDummyWitness (tx , witnessSize )
94+
95+ return mempool .GetTxVirtualSize (btcutil .NewTx (newTx ))
96+ }
97+
98+ // CheckTransactionWeight checks if the weight of the given tx exceeds the allowed maximum weight
99+ func CheckTransactionWeight (tx * wire.MsgTx , witnessSize int ) error {
100+ newTx := PopulateTxWithDummyWitness (tx , witnessSize )
101+
102+ weight := blockchain .GetTransactionWeight (btcutil .NewTx (newTx ))
103+ if weight > MaxTransactionWeight {
104+ return ErrMaxTransactionWeightExceeded
105+ }
106+
107+ return nil
108+ }
109+
110+ // PopulateTxWithDummyWitness populates the given tx with the dummy witness
111+ func PopulateTxWithDummyWitness (tx * wire.MsgTx , witnessSize int ) * wire.MsgTx {
112+ newTx := tx .Copy ()
113+
114+ for _ , txIn := range newTx .TxIn {
115+ if len (txIn .Witness ) == 0 {
116+ dummyWitness := make ([]byte , witnessSize )
117+ txIn .Witness = wire.TxWitness {dummyWitness }
118+ }
119+ }
120+
121+ return newTx
122+ }
0 commit comments