github.com/lbryio/lbcd@v0.22.119/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/lbryio/lbcd/blockchain" 12 "github.com/lbryio/lbcd/chaincfg/chainhash" 13 "github.com/lbryio/lbcd/wire" 14 btcutil "github.com/lbryio/lbcutil" 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 }