github.com/btcsuite/btcd@v0.24.0/mining/policy_test.go (about)

     1  // Copyright (c) 2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package mining
     6  
     7  import (
     8  	"encoding/hex"
     9  	"testing"
    10  
    11  	"github.com/btcsuite/btcd/blockchain"
    12  	"github.com/btcsuite/btcd/btcutil"
    13  	"github.com/btcsuite/btcd/chaincfg/chainhash"
    14  	"github.com/btcsuite/btcd/wire"
    15  )
    16  
    17  // newHashFromStr converts the passed big-endian hex string into a
    18  // chainhash.Hash.  It only differs from the one available in chainhash in that
    19  // it panics on an error since it will only (and must only) be called with
    20  // hard-coded, and therefore known good, hashes.
    21  func newHashFromStr(hexStr string) *chainhash.Hash {
    22  	hash, err := chainhash.NewHashFromStr(hexStr)
    23  	if err != nil {
    24  		panic("invalid hash in source file: " + hexStr)
    25  	}
    26  	return hash
    27  }
    28  
    29  // hexToBytes converts the passed hex string into bytes and will panic if there
    30  // is an error.  This is only provided for the hard-coded constants so errors in
    31  // the source code can be detected. It will only (and must only) be called with
    32  // hard-coded values.
    33  func hexToBytes(s string) []byte {
    34  	b, err := hex.DecodeString(s)
    35  	if err != nil {
    36  		panic("invalid hex in source file: " + s)
    37  	}
    38  	return b
    39  }
    40  
    41  // newUtxoViewpoint returns a new utxo view populated with outputs of the
    42  // provided source transactions as if there were available at the respective
    43  // block height specified in the heights slice.  The length of the source txns
    44  // and source tx heights must match or it will panic.
    45  func newUtxoViewpoint(sourceTxns []*wire.MsgTx, sourceTxHeights []int32) *blockchain.UtxoViewpoint {
    46  	if len(sourceTxns) != len(sourceTxHeights) {
    47  		panic("each transaction must have its block height specified")
    48  	}
    49  
    50  	view := blockchain.NewUtxoViewpoint()
    51  	for i, tx := range sourceTxns {
    52  		view.AddTxOuts(btcutil.NewTx(tx), sourceTxHeights[i])
    53  	}
    54  	return view
    55  }
    56  
    57  // TestCalcPriority ensures the priority calculations work as intended.
    58  func TestCalcPriority(t *testing.T) {
    59  	// commonSourceTx1 is a valid transaction used in the tests below as an
    60  	// input to transactions that are having their priority calculated.
    61  	//
    62  	// From block 7 in main blockchain.
    63  	// tx 0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9
    64  	commonSourceTx1 := &wire.MsgTx{
    65  		Version: 1,
    66  		TxIn: []*wire.TxIn{{
    67  			PreviousOutPoint: wire.OutPoint{
    68  				Hash:  chainhash.Hash{},
    69  				Index: wire.MaxPrevOutIndex,
    70  			},
    71  			SignatureScript: hexToBytes("04ffff001d0134"),
    72  			Sequence:        0xffffffff,
    73  		}},
    74  		TxOut: []*wire.TxOut{{
    75  			Value: 5000000000,
    76  			PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c5" +
    77  				"3bc1eb68a382e97b1482ecad7b148a6909a5cb2e0ead" +
    78  				"dfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8" +
    79  				"643f656b412a3ac"),
    80  		}},
    81  		LockTime: 0,
    82  	}
    83  
    84  	// commonRedeemTx1 is a valid transaction used in the tests below as the
    85  	// transaction to calculate the priority for.
    86  	//
    87  	// It originally came from block 170 in main blockchain.
    88  	commonRedeemTx1 := &wire.MsgTx{
    89  		Version: 1,
    90  		TxIn: []*wire.TxIn{{
    91  			PreviousOutPoint: wire.OutPoint{
    92  				Hash: *newHashFromStr("0437cd7f8525ceed232435" +
    93  					"9c2d0ba26006d92d856a9c20fa0241106ee5" +
    94  					"a597c9"),
    95  				Index: 0,
    96  			},
    97  			SignatureScript: hexToBytes("47304402204e45e16932b8af" +
    98  				"514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5f" +
    99  				"b8cd410220181522ec8eca07de4860a4acdd12909d83" +
   100  				"1cc56cbbac4622082221a8768d1d0901"),
   101  			Sequence: 0xffffffff,
   102  		}},
   103  		TxOut: []*wire.TxOut{{
   104  			Value: 1000000000,
   105  			PkScript: hexToBytes("4104ae1a62fe09c5f51b13905f07f06" +
   106  				"b99a2f7159b2225f374cd378d71302fa28414e7aab37" +
   107  				"397f554a7df5f142c21c1b7303b8a0626f1baded5c72" +
   108  				"a704f7e6cd84cac"),
   109  		}, {
   110  			Value: 4000000000,
   111  			PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c5" +
   112  				"3bc1eb68a382e97b1482ecad7b148a6909a5cb2e0ead" +
   113  				"dfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8" +
   114  				"643f656b412a3ac"),
   115  		}},
   116  		LockTime: 0,
   117  	}
   118  
   119  	tests := []struct {
   120  		name       string                    // test description
   121  		tx         *wire.MsgTx               // tx to calc priority for
   122  		utxoView   *blockchain.UtxoViewpoint // inputs to tx
   123  		nextHeight int32                     // height for priority calc
   124  		want       float64                   // expected priority
   125  	}{
   126  		{
   127  			name: "one height 7 input, prio tx height 169",
   128  			tx:   commonRedeemTx1,
   129  			utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
   130  				[]int32{7}),
   131  			nextHeight: 169,
   132  			want:       5e9,
   133  		},
   134  		{
   135  			name: "one height 100 input, prio tx height 169",
   136  			tx:   commonRedeemTx1,
   137  			utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
   138  				[]int32{100}),
   139  			nextHeight: 169,
   140  			want:       2129629629.6296296,
   141  		},
   142  		{
   143  			name: "one height 7 input, prio tx height 100000",
   144  			tx:   commonRedeemTx1,
   145  			utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
   146  				[]int32{7}),
   147  			nextHeight: 100000,
   148  			want:       3086203703703.7036,
   149  		},
   150  		{
   151  			name: "one height 100 input, prio tx height 100000",
   152  			tx:   commonRedeemTx1,
   153  			utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
   154  				[]int32{100}),
   155  			nextHeight: 100000,
   156  			want:       3083333333333.3335,
   157  		},
   158  	}
   159  
   160  	for i, test := range tests {
   161  		got := CalcPriority(test.tx, test.utxoView, test.nextHeight)
   162  		if got != test.want {
   163  			t.Errorf("CalcPriority #%d (%q): unexpected priority "+
   164  				"got %v want %v", i, test.name, got, test.want)
   165  			continue
   166  		}
   167  	}
   168  }