kaspad/mining/policy_test.go
2018-07-22 15:53:06 +03:00

188 lines
5.9 KiB
Go

// Copyright (c) 2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package mining
import (
"encoding/hex"
"fmt"
"testing"
"github.com/daglabs/btcd/blockdag"
"github.com/daglabs/btcd/btcec"
"github.com/daglabs/btcd/dagconfig"
"github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/txscript"
"github.com/daglabs/btcd/wire"
"github.com/daglabs/btcutil"
)
// newHashFromStr converts the passed big-endian hex string into a
// daghash.Hash. It only differs from the one available in daghash in that
// it panics on an error since it will only (and must only) be called with
// hard-coded, and therefore known good, hashes.
func newHashFromStr(hexStr string) *daghash.Hash {
hash, err := daghash.NewHashFromStr(hexStr)
if err != nil {
panic("invalid hash in source file: " + hexStr)
}
return hash
}
// hexToBytes converts the passed hex string into bytes and will panic if there
// is an error. This is only provided for the hard-coded constants so errors in
// the source code can be detected. It will only (and must only) be called with
// hard-coded values.
func hexToBytes(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
panic("invalid hex in source file: " + s)
}
return b
}
// newUtxoViewpoint returns a new utxo view populated with outputs of the
// provided source transactions as if there were available at the respective
// block height specified in the heights slice. The length of the source txns
// and source tx heights must match or it will panic.
func newUtxoViewpoint(sourceTxns []*wire.MsgTx, sourceTxHeights []int32) *blockdag.UtxoViewpoint {
if len(sourceTxns) != len(sourceTxHeights) {
panic("each transaction must have its block height specified")
}
view := blockdag.NewUtxoViewpoint()
for i, tx := range sourceTxns {
view.AddTxOuts(btcutil.NewTx(tx), sourceTxHeights[i])
}
return view
}
func createTxIn(originTx *wire.MsgTx, outputIndex uint32) *wire.TxIn {
var prevOut *wire.OutPoint
if originTx != nil {
originTxHash := originTx.TxHash()
prevOut = wire.NewOutPoint(&originTxHash, 0)
} else {
prevOut = &wire.OutPoint{
Hash: daghash.Hash{},
Index: 0xFFFFFFFF,
}
}
return wire.NewTxIn(prevOut, nil)
}
func createTransaction(value int64, originTx *wire.MsgTx, originTxoutputIndex uint32, sigScript []byte) (*wire.MsgTx, error) {
lookupKey := func(a btcutil.Address) (*btcec.PrivateKey, bool, error) {
// Ordinarily this function would involve looking up the private
// key for the provided address, but since the only thing being
// signed in this example uses the address associated with the
// private key from above, simply return it with the compressed
// flag set since the address is using the associated compressed
// public key.
return privKey, true, nil
}
tx := wire.NewMsgTx(wire.TxVersion)
tx.AddTxIn(createTxIn(originTx, originTxoutputIndex))
pkScript, err := txscript.PayToAddrScript(addr)
if err != nil {
fmt.Println(err)
return nil, err
}
txOut := wire.NewTxOut(value, pkScript)
tx.AddTxOut(txOut)
if sigScript == nil {
sigScript, err = txscript.SignTxOutput(&dagconfig.MainNetParams,
tx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll,
txscript.KeyClosure(lookupKey), nil, nil)
}
tx.TxIn[0].SignatureScript = sigScript
return tx, nil
}
// TestCalcPriority ensures the priority calculations work as intended.
func TestCalcPriority(t *testing.T) {
// commonSourceTx1 is a valid transaction used in the tests below as an
// input to transactions that are having their priority calculated.
//
// From block 7 in main blockchain.
// tx 0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9
commonSourceTx1, err := createTransaction(5000000000, nil, 0, hexToBytes("04ffff001d0134"))
if err != nil {
t.Errorf("Error with creating source tx: %v", err)
}
// commonRedeemTx1 is a valid transaction used in the tests below as the
// transaction to calculate the priority for.
//
// It originally came from block 170 in main blockchain.
commonRedeemTx1, err := createTransaction(5000000000, commonSourceTx1, 0, nil)
if err != nil {
t.Errorf("Error with creating redeem tx: %v", err)
}
tests := []struct {
name string // test description
tx *wire.MsgTx // tx to calc priority for
utxoView *blockdag.UtxoViewpoint // inputs to tx
nextHeight int32 // height for priority calc
want float64 // expected priority
}{
{
name: "one height 7 input, prio tx height 169",
tx: commonRedeemTx1,
utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
[]int32{7}),
nextHeight: 169,
want: 1.5576923076923077e+10,
},
{
name: "one height 100 input, prio tx height 169",
tx: commonRedeemTx1,
utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
[]int32{100}),
nextHeight: 169,
want: 6.634615384615385e+09,
},
{
name: "one height 7 input, prio tx height 100000",
tx: commonRedeemTx1,
utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
[]int32{7}),
nextHeight: 100000,
want: 9.61471153846154e+12,
},
{
name: "one height 100 input, prio tx height 100000",
tx: commonRedeemTx1,
utxoView: newUtxoViewpoint([]*wire.MsgTx{commonSourceTx1},
[]int32{100}),
nextHeight: 100000,
want: 9.60576923076923e+12,
},
}
for i, test := range tests {
got := CalcPriority(test.tx, test.utxoView, test.nextHeight)
if got != test.want {
t.Errorf("CalcPriority #%d (%q): unexpected priority "+
"got %v want %v", i, test.name, got, test.want)
continue
}
}
}
var privKeyBytes, _ = hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
"d4f8720ee63e502ee2869afab7de234b80c")
var privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
var pubKeyHash = btcutil.Hash160(pubKey.SerializeCompressed())
var addr, err = btcutil.NewAddressPubKeyHash(pubKeyHash,
&dagconfig.MainNetParams)