From 5b1443a9551dadaf21868a9998b49e438ad6972f Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Tue, 10 Aug 2021 11:27:13 +0100 Subject: [PATCH] adjusting tx input sig size to a max of 71 bytes for a total of 107 per input. Adjusting fee calcs for bytes and std to do the calc in one place to avoid rounding issues --- txchange.go | 43 ++++++++++--------------------------------- txchange_test.go | 8 ++++---- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/txchange.go b/txchange.go index 5c26ddf9..7b8dadd8 100644 --- a/txchange.go +++ b/txchange.go @@ -82,17 +82,11 @@ func (tx *Tx) change(s *bscript.Script, f []*Fee, newOutput bool) (uint64, bool, tx.AddOutput(&Output{Satoshis: 0, LockingScript: s}) } - var preSignedFeeRequired uint64 - if preSignedFeeRequired, err = tx.getPreSignedFeeRequired(f); err != nil { + var txFee uint64 + if txFee, err = tx.getTransactionFees(f); err != nil { return 0, false, err } - - var expectedUnlockingScriptFees uint64 - if expectedUnlockingScriptFees, err = tx.getExpectedUnlockingScriptFees(f); err != nil { - return 0, false, err - } - - available -= preSignedFeeRequired + expectedUnlockingScriptFees + available -= txFee return available, true, nil } @@ -114,46 +108,29 @@ func (tx *Tx) canAddChange(available uint64, standardFees *Fee) bool { return available >= changeOutputFee } -func (tx *Tx) getPreSignedFeeRequired(f []*Fee) (uint64, error) { +func (tx *Tx) getTransactionFees(f []*Fee) (uint64, error) { standardBytes, dataBytes := tx.getStandardAndDataBytes() - standardFee, err := ExtractStandardFee(f) if err != nil { return 0, err } - + for _, in := range tx.Inputs { + if !in.PreviousTxScript.IsP2PKH() { + return 0, errors.New("non-P2PKH input used in the tx - unsupported") + } + standardBytes += 107 // = 1 oppushdata + 70-71 sig + 1 sighash + 1 oppushdata + 33 public key + } fr := standardBytes * standardFee.MiningFee.Satoshis / standardFee.MiningFee.Bytes - var dataFee *Fee if dataFee, err = ExtractDataFee(f); err != nil { return 0, err } - fr += dataBytes * dataFee.MiningFee.Satoshis / dataFee.MiningFee.Bytes return uint64(fr), nil } -func (tx *Tx) getExpectedUnlockingScriptFees(f []*Fee) (uint64, error) { - - standardFee, err := ExtractStandardFee(f) - if err != nil { - return 0, err - } - - var expectedBytes int - - for _, in := range tx.Inputs { - if !in.PreviousTxScript.IsP2PKH() { - return 0, errors.New("non-P2PKH input used in the tx - unsupported") - } - expectedBytes += 109 // = 1 oppushdata + 70-73 sig + 1 sighash + 1 oppushdata + 33 public key - } - - return uint64(expectedBytes * standardFee.MiningFee.Satoshis / standardFee.MiningFee.Bytes), nil -} - func (tx *Tx) getStandardAndDataBytes() (standardBytes, dataBytes int) { // Subtract the value of each output as well as keeping track of data Outputs for _, out := range tx.Outputs { diff --git a/txchange_test.go b/txchange_test.go index 6e04ad06..d4b83acb 100644 --- a/txchange_test.go +++ b/txchange_test.go @@ -155,18 +155,18 @@ func TestTx_Change(t *testing.T) { assert.NoError(t, err) assert.Equal(t, - "0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006a473044022054ec562aefb1d5b4483906b0fa728a951b81944d8a82c2be1c6e7ea67e8c34b702200c2657c5d2a744d138bfb4204c579de20e984d680695823cba3fb7a0346b3c19412102c8803fdd437d902f08e3c2344cb33065c99d7c99982018ff9f7219c3dd352ff0ffffffff03f4010000000000001976a9147a1980655efbfec416b2b0c663a7b3ac0b6a25d288ac000000000000000011006a02686903686f770361726503796f757a010000000000001976a91484e50b300b009833b297dc671817c79b5459da1d88ac00000000", + "0100000001760595866e99c1ce920197844740f5598b34763878696371d41b3a7c0a65b0b7000000006a473044022034d403376154060bbbb4f828df545bfc23dd1174ef5ea626668ea31cec860b4702206a95c559bc612e7fc3746ce18456a6301ff16fd285798d4fbcfbd1c71e34047e412102c8803fdd437d902f08e3c2344cb33065c99d7c99982018ff9f7219c3dd352ff0ffffffff03f4010000000000001976a9147a1980655efbfec416b2b0c663a7b3ac0b6a25d288ac000000000000000011006a02686903686f770361726503796f757b010000000000001976a91484e50b300b009833b297dc671817c79b5459da1d88ac00000000", tx.String(), ) feePaid := tx.TotalInputSatoshis() - tx.TotalOutputSatoshis() - assert.Equal(t, uint64(122), feePaid) + assert.Equal(t, uint64(121), feePaid) txSize := len(tx.Bytes()) assert.Equal(t, 251, txSize) feeRate := float64(feePaid) / float64(txSize) - assert.Equal(t, 0.4860557768924303, feeRate) + assert.Equal(t, 0.4820717131474104, feeRate) }) t.Run("spend entire utxo - basic - change address", func(t *testing.T) { @@ -298,7 +298,7 @@ func TestTx_Change(t *testing.T) { assert.ElementsMatch(t, []int{0, 1}, is) assert.Equal(t, 2, len(is)) - assert.Equal(t, "01000000028ee20a442cdbcc9f9f927d9c2c9370e611675ebc24c064e8e94508ec8eca889e000000006b483045022100fa52a44cd8010ba646a8df6bac6e5e8aa93f24439521c2ce1c8fe6550e73c1750220636e30d757702a6777d8310090962d4bac2b3fd634127856d51b184f5c702c8f4121034aaeabc056f33fd960d1e43fc8a0672723af02f275e54c31381af66a334634caffffffff42eaf7bdddc797a0beb97717ff8846f03c963fb5fe15a2b555b9cbd477b0254e000000006b483045022100c201fd55ef33525b3eb0557fac77408b8ec7f6ea5b00d08512df105172f992d60220753b21519a416dcbeaf1a501d9c36de2aea9c83c6d258320500371819d0758e14121034aaeabc056f33fd960d1e43fc8a0672723af02f275e54c31381af66a334634caffffffff01c62b0000000000001976a9147824dec00be2c45dad83c9b5e9f5d7ef05ba3cf988ac00000000", tx.String()) + assert.Equal(t, "01000000028ee20a442cdbcc9f9f927d9c2c9370e611675ebc24c064e8e94508ec8eca889e000000006b483045022100f88298f5a380244dd5b91f70be99394f8e562d2a61976ca8cf2aaeb381ee6e6a0220069243fc951061b624cf96124263b857a65a53400846080b543e4a8c16e097ce4121034aaeabc056f33fd960d1e43fc8a0672723af02f275e54c31381af66a334634caffffffff42eaf7bdddc797a0beb97717ff8846f03c963fb5fe15a2b555b9cbd477b0254e000000006b483045022100afa7a986e6e0faf725a9779fe8e61fd19b5973544dc7707fd758cdd45912332a0220760fe07fc8610d867be5281f29778e3cd1a18a6eef74470d0f1a4ede95c848924121034aaeabc056f33fd960d1e43fc8a0672723af02f275e54c31381af66a334634caffffffff01c82b0000000000001976a9147824dec00be2c45dad83c9b5e9f5d7ef05ba3cf988ac00000000", tx.String()) }) }