mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-10-14 00:59:33 +00:00
[DEV-337] enusre transaction not overuse gas (#152)
* [DEV-312] Take in account subnetwork's GAS limit, when adding transactions to block. Try to do that optimally. * [DEV-312] Fixed GAS overusage calculation * [DEV-337] Make sure that a transaction that uses more gas than the total allowed for sub-network * [DEV-337] Moved transaction GAS check to mempool * [DEV-337] Added Unit test for gas usage in transaction * [DEV-337] Fixed build * [DEV-337] Fixed tests stuff * [DEV-337] Removed TODO comment
This commit is contained in:
parent
41d1a08365
commit
e76ce06acd
@ -894,7 +894,7 @@ func TestFinality(t *testing.T) {
|
|||||||
}
|
}
|
||||||
msgBlock := wire.NewMsgBlock(bh)
|
msgBlock := wire.NewMsgBlock(bh)
|
||||||
blockHeight := parents.maxHeight() + 1
|
blockHeight := parents.maxHeight() + 1
|
||||||
coinbaseTx, err := createCoinbaseTx(blockHeight, 1, extraNonce, dag.dagParams)
|
coinbaseTx, err := createCoinbaseTxForTest(blockHeight, 1, extraNonce, dag.dagParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,10 @@ const (
|
|||||||
// sorted by sub-network
|
// sorted by sub-network
|
||||||
ErrTransactionsNotSorted
|
ErrTransactionsNotSorted
|
||||||
|
|
||||||
|
// ErrInvalidGas transaction wants to use more GAS than allowed
|
||||||
|
// by subnetwork
|
||||||
|
ErrInvalidGas
|
||||||
|
|
||||||
// ErrSubNetwork indicates that a block doesn't adhere to the sub-network
|
// ErrSubNetwork indicates that a block doesn't adhere to the sub-network
|
||||||
// registry rules
|
// registry rules
|
||||||
ErrSubNetworkRegistry
|
ErrSubNetworkRegistry
|
||||||
@ -265,6 +269,7 @@ var errorCodeStrings = map[ErrorCode]string{
|
|||||||
ErrWithDiff: "ErrWithDiff",
|
ErrWithDiff: "ErrWithDiff",
|
||||||
ErrFinality: "ErrFinality",
|
ErrFinality: "ErrFinality",
|
||||||
ErrTransactionsNotSorted: "ErrTransactionsNotSorted",
|
ErrTransactionsNotSorted: "ErrTransactionsNotSorted",
|
||||||
|
ErrInvalidGas: "ErrInvalidGas",
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the ErrorCode as a human-readable name.
|
// String returns the ErrorCode as a human-readable name.
|
||||||
|
@ -57,6 +57,7 @@ func TestErrorCodeStringer(t *testing.T) {
|
|||||||
{ErrWithDiff, "ErrWithDiff"},
|
{ErrWithDiff, "ErrWithDiff"},
|
||||||
{ErrFinality, "ErrFinality"},
|
{ErrFinality, "ErrFinality"},
|
||||||
{ErrTransactionsNotSorted, "ErrTransactionsNotSorted"},
|
{ErrTransactionsNotSorted, "ErrTransactionsNotSorted"},
|
||||||
|
{ErrInvalidGas, "ErrInvalidGas"},
|
||||||
{0xffff, "Unknown ErrorCode (65535)"},
|
{0xffff, "Unknown ErrorCode (65535)"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,13 +2,12 @@ package blockdag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"github.com/daglabs/btcd/dagconfig"
|
|
||||||
"github.com/daglabs/btcd/util"
|
|
||||||
"github.com/daglabs/btcd/wire"
|
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
"github.com/daglabs/btcd/dagconfig"
|
||||||
|
"github.com/daglabs/btcd/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSubNetworkRegistry tests the full sub-network registry flow. In this test:
|
// TestSubNetworkRegistry tests the full sub-network registry flow. In this test:
|
||||||
@ -25,89 +24,11 @@ func TestSubNetworkRegistry(t *testing.T) {
|
|||||||
t.Fatalf("Failed to setup DAG instance: %v", err)
|
t.Fatalf("Failed to setup DAG instance: %v", err)
|
||||||
}
|
}
|
||||||
defer teardownFunc()
|
defer teardownFunc()
|
||||||
blockTime := time.Unix(dag.genesis.timestamp, 0)
|
|
||||||
extraNonce := int64(0)
|
|
||||||
|
|
||||||
buildNextBlock := func(parents blockSet, txs []*wire.MsgTx) (*util.Block, error) {
|
_, err = RegisterSubnetworkForTest(dag, 12345)
|
||||||
// We need to change the blockTime to keep all block hashes unique
|
|
||||||
blockTime = blockTime.Add(time.Second)
|
|
||||||
|
|
||||||
// We need to change the extraNonce to keep coinbase hashes unique
|
|
||||||
extraNonce++
|
|
||||||
|
|
||||||
bh := &wire.BlockHeader{
|
|
||||||
Version: 1,
|
|
||||||
Bits: dag.genesis.bits,
|
|
||||||
ParentHashes: parents.hashes(),
|
|
||||||
Timestamp: blockTime,
|
|
||||||
}
|
|
||||||
msgBlock := wire.NewMsgBlock(bh)
|
|
||||||
blockHeight := parents.maxHeight() + 1
|
|
||||||
coinbaseTx, err := createCoinbaseTx(blockHeight, 1, extraNonce, dag.dagParams)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_ = msgBlock.AddTransaction(coinbaseTx)
|
|
||||||
|
|
||||||
for _, tx := range txs {
|
|
||||||
_ = msgBlock.AddTransaction(tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return util.NewBlock(msgBlock), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
addBlockToDAG := func(block *util.Block) (*blockNode, error) {
|
|
||||||
dag.dagLock.Lock()
|
|
||||||
defer dag.dagLock.Unlock()
|
|
||||||
|
|
||||||
err = dag.maybeAcceptBlock(block, BFNone)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return dag.index.LookupNode(block.Hash()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
currentNode := dag.genesis
|
|
||||||
|
|
||||||
// Create a block with a valid sub-network registry transaction
|
|
||||||
gasLimit := uint64(12345)
|
|
||||||
registryTx := wire.NewMsgTx(wire.TxVersion)
|
|
||||||
registryTx.SubNetworkID = wire.SubNetworkRegistry
|
|
||||||
registryTx.Payload = make([]byte, 8)
|
|
||||||
binary.LittleEndian.PutUint64(registryTx.Payload, gasLimit)
|
|
||||||
|
|
||||||
// Add it to the DAG
|
|
||||||
registryBlock, err := buildNextBlock(setFromSlice(currentNode), []*wire.MsgTx{registryTx})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not build registry block: %s", err)
|
t.Fatalf("could not register network: %s", err)
|
||||||
}
|
|
||||||
currentNode, err = addBlockToDAG(registryBlock)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not add registry block to DAG: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add 2*finalityInterval to ensure the registry transaction is finalized
|
|
||||||
for currentNode.blueScore < 2*finalityInterval {
|
|
||||||
nextBlock, err := buildNextBlock(setFromSlice(currentNode), []*wire.MsgTx{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not create block: %s", err)
|
|
||||||
}
|
|
||||||
currentNode, err = addBlockToDAG(nextBlock)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not add block to DAG: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that the sub-network had been successfully registered by trying
|
|
||||||
// to retrieve its gas limit.
|
|
||||||
mostRecentlyRegisteredSubNetworkID := dag.lastSubNetworkID - 1
|
|
||||||
limit, err := dag.GasLimit(mostRecentlyRegisteredSubNetworkID)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not retrieve gas limit: %s", err)
|
|
||||||
}
|
|
||||||
if limit != gasLimit {
|
|
||||||
t.Fatalf("unexpected gas limit. want: %d, got: %d", gasLimit, limit)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
package blockdag
|
package blockdag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/daglabs/btcd/dagconfig"
|
||||||
|
"github.com/daglabs/btcd/dagconfig/daghash"
|
||||||
"github.com/daglabs/btcd/database"
|
"github.com/daglabs/btcd/database"
|
||||||
_ "github.com/daglabs/btcd/database/ffldb" // blank import ffldb so that its init() function runs before tests
|
_ "github.com/daglabs/btcd/database/ffldb" // blank import ffldb so that its init() function runs before tests
|
||||||
"github.com/daglabs/btcd/txscript"
|
"github.com/daglabs/btcd/txscript"
|
||||||
|
"github.com/daglabs/btcd/util"
|
||||||
"github.com/daglabs/btcd/wire"
|
"github.com/daglabs/btcd/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -94,3 +99,134 @@ func DAGSetup(dbName string, config Config) (*BlockDAG, func(), error) {
|
|||||||
}
|
}
|
||||||
return dag, teardown, nil
|
return dag, teardown, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpTrueScript is script returning TRUE
|
||||||
|
var OpTrueScript = []byte{txscript.OpTrue}
|
||||||
|
|
||||||
|
// createCoinbaseTxForTest returns a coinbase transaction with the requested number of
|
||||||
|
// outputs paying an appropriate subsidy based on the passed block height to the
|
||||||
|
// address associated with the harness. It automatically uses a standard
|
||||||
|
// signature script that starts with the block height
|
||||||
|
func createCoinbaseTxForTest(blockHeight int32, numOutputs uint32, extraNonce int64, params *dagconfig.Params) (*wire.MsgTx, error) {
|
||||||
|
// Create standard coinbase script.
|
||||||
|
coinbaseScript, err := txscript.NewScriptBuilder().
|
||||||
|
AddInt64(int64(blockHeight)).AddInt64(extraNonce).Script()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := wire.NewMsgTx(wire.TxVersion)
|
||||||
|
tx.AddTxIn(&wire.TxIn{
|
||||||
|
// Coinbase transactions have no inputs, so previous outpoint is
|
||||||
|
// zero hash and max index.
|
||||||
|
PreviousOutPoint: *wire.NewOutPoint(&daghash.Hash{},
|
||||||
|
wire.MaxPrevOutIndex),
|
||||||
|
SignatureScript: coinbaseScript,
|
||||||
|
Sequence: wire.MaxTxInSequenceNum,
|
||||||
|
})
|
||||||
|
totalInput := CalcBlockSubsidy(blockHeight, params)
|
||||||
|
amountPerOutput := totalInput / uint64(numOutputs)
|
||||||
|
remainder := totalInput - amountPerOutput*uint64(numOutputs)
|
||||||
|
for i := uint32(0); i < numOutputs; i++ {
|
||||||
|
// Ensure the final output accounts for any remainder that might
|
||||||
|
// be left from splitting the input amount.
|
||||||
|
amount := amountPerOutput
|
||||||
|
if i == numOutputs-1 {
|
||||||
|
amount = amountPerOutput + remainder
|
||||||
|
}
|
||||||
|
tx.AddTxOut(&wire.TxOut{
|
||||||
|
PkScript: OpTrueScript,
|
||||||
|
Value: amount,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterSubnetworkForTest is used to register network on DAG with specified GAS limit.
|
||||||
|
func RegisterSubnetworkForTest(dag *BlockDAG, gasLimit uint64) (subNetworkID uint64, err error) {
|
||||||
|
blockTime := time.Unix(dag.genesis.timestamp, 0)
|
||||||
|
extraNonce := int64(0)
|
||||||
|
|
||||||
|
buildNextBlock := func(parents blockSet, txs []*wire.MsgTx) (*util.Block, error) {
|
||||||
|
// We need to change the blockTime to keep all block hashes unique
|
||||||
|
blockTime = blockTime.Add(time.Second)
|
||||||
|
|
||||||
|
// We need to change the extraNonce to keep coinbase hashes unique
|
||||||
|
extraNonce++
|
||||||
|
|
||||||
|
bh := &wire.BlockHeader{
|
||||||
|
Version: 1,
|
||||||
|
Bits: dag.genesis.bits,
|
||||||
|
ParentHashes: parents.hashes(),
|
||||||
|
Timestamp: blockTime,
|
||||||
|
}
|
||||||
|
msgBlock := wire.NewMsgBlock(bh)
|
||||||
|
blockHeight := parents.maxHeight() + 1
|
||||||
|
coinbaseTx, err := createCoinbaseTxForTest(blockHeight, 1, extraNonce, dag.dagParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_ = msgBlock.AddTransaction(coinbaseTx)
|
||||||
|
|
||||||
|
for _, tx := range txs {
|
||||||
|
_ = msgBlock.AddTransaction(tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.NewBlock(msgBlock), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
addBlockToDAG := func(block *util.Block) (*blockNode, error) {
|
||||||
|
dag.dagLock.Lock()
|
||||||
|
defer dag.dagLock.Unlock()
|
||||||
|
|
||||||
|
err = dag.maybeAcceptBlock(block, BFNone)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dag.index.LookupNode(block.Hash()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
currentNode := dag.genesis
|
||||||
|
|
||||||
|
// Create a block with a valid sub-network registry transaction
|
||||||
|
registryTx := wire.NewMsgTx(wire.TxVersion)
|
||||||
|
registryTx.SubNetworkID = wire.SubNetworkRegistry
|
||||||
|
registryTx.Payload = make([]byte, 8)
|
||||||
|
binary.LittleEndian.PutUint64(registryTx.Payload, gasLimit)
|
||||||
|
|
||||||
|
// Add it to the DAG
|
||||||
|
registryBlock, err := buildNextBlock(setFromSlice(currentNode), []*wire.MsgTx{registryTx})
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not build registry block: %s", err)
|
||||||
|
}
|
||||||
|
currentNode, err = addBlockToDAG(registryBlock)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not add registry block to DAG: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add 2*finalityInterval to ensure the registry transaction is finalized
|
||||||
|
for currentNode.blueScore < 2*finalityInterval {
|
||||||
|
nextBlock, err := buildNextBlock(setFromSlice(currentNode), []*wire.MsgTx{})
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not create block: %s", err)
|
||||||
|
}
|
||||||
|
currentNode, err = addBlockToDAG(nextBlock)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not add block to DAG: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the sub-network had been successfully registered by trying
|
||||||
|
// to retrieve its gas limit.
|
||||||
|
mostRecentlyRegisteredSubNetworkID := dag.lastSubNetworkID - 1
|
||||||
|
limit, err := dag.GasLimit(mostRecentlyRegisteredSubNetworkID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("could not retrieve gas limit: %s", err)
|
||||||
|
}
|
||||||
|
if limit != gasLimit {
|
||||||
|
return 0, fmt.Errorf("unexpected gas limit. want: %d, got: %d", gasLimit, limit)
|
||||||
|
}
|
||||||
|
return mostRecentlyRegisteredSubNetworkID, nil
|
||||||
|
}
|
||||||
|
@ -7,13 +7,10 @@ import (
|
|||||||
|
|
||||||
"github.com/daglabs/btcd/dagconfig"
|
"github.com/daglabs/btcd/dagconfig"
|
||||||
"github.com/daglabs/btcd/dagconfig/daghash"
|
"github.com/daglabs/btcd/dagconfig/daghash"
|
||||||
"github.com/daglabs/btcd/txscript"
|
|
||||||
"github.com/daglabs/btcd/util"
|
"github.com/daglabs/btcd/util"
|
||||||
"github.com/daglabs/btcd/wire"
|
"github.com/daglabs/btcd/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var OpTrueScript = []byte{txscript.OpTrue}
|
|
||||||
|
|
||||||
// TestUTXOCollection makes sure that utxoCollection cloning and string representations work as expected.
|
// TestUTXOCollection makes sure that utxoCollection cloning and string representations work as expected.
|
||||||
func TestUTXOCollection(t *testing.T) {
|
func TestUTXOCollection(t *testing.T) {
|
||||||
hash0, _ := daghash.NewHashFromStr("0000000000000000000000000000000000000000000000000000000000000000")
|
hash0, _ := daghash.NewHashFromStr("0000000000000000000000000000000000000000000000000000000000000000")
|
||||||
@ -799,46 +796,6 @@ func TestDiffUTXOSet_addTx(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createCoinbaseTx returns a coinbase transaction with the requested number of
|
|
||||||
// outputs paying an appropriate subsidy based on the passed block height to the
|
|
||||||
// address associated with the harness. It automatically uses a standard
|
|
||||||
// signature script that starts with the block height
|
|
||||||
func createCoinbaseTx(blockHeight int32, numOutputs uint32, extraNonce int64, params *dagconfig.Params) (*wire.MsgTx, error) {
|
|
||||||
// Create standard coinbase script.
|
|
||||||
coinbaseScript, err := txscript.NewScriptBuilder().
|
|
||||||
AddInt64(int64(blockHeight)).AddInt64(extraNonce).Script()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tx := wire.NewMsgTx(wire.TxVersion)
|
|
||||||
tx.AddTxIn(&wire.TxIn{
|
|
||||||
// Coinbase transactions have no inputs, so previous outpoint is
|
|
||||||
// zero hash and max index.
|
|
||||||
PreviousOutPoint: *wire.NewOutPoint(&daghash.Hash{},
|
|
||||||
wire.MaxPrevOutIndex),
|
|
||||||
SignatureScript: coinbaseScript,
|
|
||||||
Sequence: wire.MaxTxInSequenceNum,
|
|
||||||
})
|
|
||||||
totalInput := CalcBlockSubsidy(blockHeight, params)
|
|
||||||
amountPerOutput := totalInput / uint64(numOutputs)
|
|
||||||
remainder := totalInput - amountPerOutput*uint64(numOutputs)
|
|
||||||
for i := uint32(0); i < numOutputs; i++ {
|
|
||||||
// Ensure the final output accounts for any remainder that might
|
|
||||||
// be left from splitting the input amount.
|
|
||||||
amount := amountPerOutput
|
|
||||||
if i == numOutputs-1 {
|
|
||||||
amount = amountPerOutput + remainder
|
|
||||||
}
|
|
||||||
tx.AddTxOut(&wire.TxOut{
|
|
||||||
PkScript: OpTrueScript,
|
|
||||||
Value: amount,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return tx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestApplyUTXOChanges(t *testing.T) {
|
func TestApplyUTXOChanges(t *testing.T) {
|
||||||
// Create a new database and dag instance to run tests against.
|
// Create a new database and dag instance to run tests against.
|
||||||
dag, teardownFunc, err := DAGSetup("TestApplyUTXOChanges", Config{
|
dag, teardownFunc, err := DAGSetup("TestApplyUTXOChanges", Config{
|
||||||
@ -857,9 +814,9 @@ func TestApplyUTXOChanges(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cbTx, err := createCoinbaseTx(1, 1, 0, dag.dagParams)
|
cbTx, err := createCoinbaseTxForTest(1, 1, 0, dag.dagParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("createCoinbaseTx: %v", err)
|
t.Errorf("createCoinbaseTxForTest: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
chainedTx := wire.NewMsgTx(wire.TxVersion)
|
chainedTx := wire.NewMsgTx(wire.TxVersion)
|
||||||
@ -924,9 +881,9 @@ func TestDiffFromTx(t *testing.T) {
|
|||||||
fus := &FullUTXOSet{
|
fus := &FullUTXOSet{
|
||||||
utxoCollection: utxoCollection{},
|
utxoCollection: utxoCollection{},
|
||||||
}
|
}
|
||||||
cbTx, err := createCoinbaseTx(1, 1, 0, &dagconfig.SimNetParams)
|
cbTx, err := createCoinbaseTxForTest(1, 1, 0, &dagconfig.SimNetParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("createCoinbaseTx: %v", err)
|
t.Errorf("createCoinbaseTxForTest: %v", err)
|
||||||
}
|
}
|
||||||
fus.AddTx(cbTx, 1)
|
fus.AddTx(cbTx, 1)
|
||||||
node := &blockNode{height: 2} //Fake node
|
node := &blockNode{height: 2} //Fake node
|
||||||
|
@ -187,7 +187,7 @@ func CheckTransactionSanity(tx *util.Tx) error {
|
|||||||
|
|
||||||
// A transaction must not exceed the maximum allowed block payload when
|
// A transaction must not exceed the maximum allowed block payload when
|
||||||
// serialized.
|
// serialized.
|
||||||
serializedTxSize := tx.MsgTx().SerializeSize()
|
serializedTxSize := msgTx.SerializeSize()
|
||||||
if serializedTxSize > wire.MaxBlockPayload {
|
if serializedTxSize > wire.MaxBlockPayload {
|
||||||
str := fmt.Sprintf("serialized transaction is too big - got "+
|
str := fmt.Sprintf("serialized transaction is too big - got "+
|
||||||
"%d, max %d", serializedTxSize, wire.MaxBlockPayload)
|
"%d, max %d", serializedTxSize, wire.MaxBlockPayload)
|
||||||
|
@ -657,6 +657,24 @@ func (mp *TxPool) maybeAcceptTransaction(tx *util.Tx, isNew, rateLimit, rejectDu
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that transaction does not overuse GAS
|
||||||
|
msgTx := tx.MsgTx()
|
||||||
|
if msgTx.SubNetworkID == 0 {
|
||||||
|
return nil, nil, txRuleError(wire.RejectInvalid, "Subnetwork 0 is not permited in transaction")
|
||||||
|
} else if msgTx.SubNetworkID != wire.SubNetworkDAGCoin {
|
||||||
|
gasLimit, err := mp.cfg.DAG.GasLimit(msgTx.SubNetworkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
if msgTx.Gas > gasLimit {
|
||||||
|
str := fmt.Sprintf("transaction wants more gas %v, than allowed %v",
|
||||||
|
msgTx.Gas, gasLimit)
|
||||||
|
return nil, nil, dagRuleError(blockdag.RuleError{
|
||||||
|
ErrorCode: blockdag.ErrInvalidGas,
|
||||||
|
Description: str})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A standalone transaction must not be a coinbase transaction.
|
// A standalone transaction must not be a coinbase transaction.
|
||||||
if blockdag.IsCoinBase(tx) {
|
if blockdag.IsCoinBase(tx) {
|
||||||
str := fmt.Sprintf("transaction %v is an individual coinbase",
|
str := fmt.Sprintf("transaction %v is an individual coinbase",
|
||||||
|
@ -155,11 +155,11 @@ func (p *poolHarness) CreateCoinbaseTx(blockHeight int32, numOutputs uint32) (*u
|
|||||||
return util.NewTx(tx), nil
|
return util.NewTx(tx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSignedTx creates a new signed transaction that consumes the provided
|
// CreateSignedTxForSubnetwork creates a new signed transaction that consumes the provided
|
||||||
// inputs and generates the provided number of outputs by evenly splitting the
|
// inputs and generates the provided number of outputs by evenly splitting the
|
||||||
// total input amount. All outputs will be to the payment script associated
|
// total input amount. All outputs will be to the payment script associated
|
||||||
// with the harness and all inputs are assumed to do the same.
|
// with the harness and all inputs are assumed to do the same.
|
||||||
func (p *poolHarness) CreateSignedTx(inputs []spendableOutpoint, numOutputs uint32) (*util.Tx, error) {
|
func (p *poolHarness) CreateSignedTxForSubnetwork(inputs []spendableOutpoint, numOutputs uint32, subnetworkID uint64, gas uint64) (*util.Tx, error) {
|
||||||
// Calculate the total input amount and split it amongst the requested
|
// Calculate the total input amount and split it amongst the requested
|
||||||
// number of outputs.
|
// number of outputs.
|
||||||
var totalInput util.Amount
|
var totalInput util.Amount
|
||||||
@ -170,6 +170,8 @@ func (p *poolHarness) CreateSignedTx(inputs []spendableOutpoint, numOutputs uint
|
|||||||
remainder := uint64(totalInput) - amountPerOutput*uint64(numOutputs)
|
remainder := uint64(totalInput) - amountPerOutput*uint64(numOutputs)
|
||||||
|
|
||||||
tx := wire.NewMsgTx(wire.TxVersion)
|
tx := wire.NewMsgTx(wire.TxVersion)
|
||||||
|
tx.SubNetworkID = subnetworkID
|
||||||
|
tx.Gas = gas
|
||||||
for _, input := range inputs {
|
for _, input := range inputs {
|
||||||
tx.AddTxIn(&wire.TxIn{
|
tx.AddTxIn(&wire.TxIn{
|
||||||
PreviousOutPoint: input.outPoint,
|
PreviousOutPoint: input.outPoint,
|
||||||
@ -203,6 +205,14 @@ func (p *poolHarness) CreateSignedTx(inputs []spendableOutpoint, numOutputs uint
|
|||||||
return util.NewTx(tx), nil
|
return util.NewTx(tx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateSignedTx creates a new signed transaction that consumes the provided
|
||||||
|
// inputs and generates the provided number of outputs by evenly splitting the
|
||||||
|
// total input amount. All outputs will be to the payment script associated
|
||||||
|
// with the harness and all inputs are assumed to do the same.
|
||||||
|
func (p *poolHarness) CreateSignedTx(inputs []spendableOutpoint, numOutputs uint32) (*util.Tx, error) {
|
||||||
|
return p.CreateSignedTxForSubnetwork(inputs, numOutputs, wire.SubNetworkDAGCoin, 0)
|
||||||
|
}
|
||||||
|
|
||||||
// CreateTxChain creates a chain of zero-fee transactions (each subsequent
|
// CreateTxChain creates a chain of zero-fee transactions (each subsequent
|
||||||
// transaction spends the entire amount from the previous one) with the first
|
// transaction spends the entire amount from the previous one) with the first
|
||||||
// one spending the provided outpoint. Each transaction spends the entire
|
// one spending the provided outpoint. Each transaction spends the entire
|
||||||
@ -248,12 +258,12 @@ func (p *poolHarness) CreateTxChain(firstOutput spendableOutpoint, numTxns uint3
|
|||||||
// for testing. Also, the fake chain is populated with the returned spendable
|
// for testing. Also, the fake chain is populated with the returned spendable
|
||||||
// outputs so the caller can easily create new valid transactions which build
|
// outputs so the caller can easily create new valid transactions which build
|
||||||
// off of it.
|
// off of it.
|
||||||
func newPoolHarness(dagParams *dagconfig.Params, numOutputs uint32, dbName string) (*poolHarness, []spendableOutpoint, error) {
|
func newPoolHarness(dagParams *dagconfig.Params, numOutputs uint32, dbName string) (*poolHarness, []spendableOutpoint, func(), error) {
|
||||||
// Use a hard coded key pair for deterministic results.
|
// Use a hard coded key pair for deterministic results.
|
||||||
keyBytes, err := hex.DecodeString("700868df1838811ffbdf918fb482c1f7e" +
|
keyBytes, err := hex.DecodeString("700868df1838811ffbdf918fb482c1f7e" +
|
||||||
"ad62db4b97bd7012c23e726485e577d")
|
"ad62db4b97bd7012c23e726485e577d")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
signKey, signPub := btcec.PrivKeyFromBytes(btcec.S256(), keyBytes)
|
signKey, signPub := btcec.PrivKeyFromBytes(btcec.S256(), keyBytes)
|
||||||
|
|
||||||
@ -262,12 +272,12 @@ func newPoolHarness(dagParams *dagconfig.Params, numOutputs uint32, dbName strin
|
|||||||
pubKeyBytes := signPub.SerializeCompressed()
|
pubKeyBytes := signPub.SerializeCompressed()
|
||||||
payPubKeyAddr, err := util.NewAddressPubKey(pubKeyBytes, dagParams.Prefix)
|
payPubKeyAddr, err := util.NewAddressPubKey(pubKeyBytes, dagParams.Prefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
payAddr := payPubKeyAddr.AddressPubKeyHash()
|
payAddr := payPubKeyAddr.AddressPubKeyHash()
|
||||||
pkScript, err := txscript.PayToAddrScript(payAddr)
|
pkScript, err := txscript.PayToAddrScript(payAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new database and chain instance to run tests against.
|
// Create a new database and chain instance to run tests against.
|
||||||
@ -275,9 +285,13 @@ func newPoolHarness(dagParams *dagconfig.Params, numOutputs uint32, dbName strin
|
|||||||
DAGParams: &dagconfig.MainNetParams,
|
DAGParams: &dagconfig.MainNetParams,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("Failed to setup DAG instance: %v", err)
|
return nil, nil, nil, fmt.Errorf("Failed to setup DAG instance: %v", err)
|
||||||
}
|
}
|
||||||
defer teardownFunc()
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
teardownFunc()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Create a new fake chain and harness bound to it.
|
// Create a new fake chain and harness bound to it.
|
||||||
chain := &fakeChain{}
|
chain := &fakeChain{}
|
||||||
@ -317,7 +331,7 @@ func newPoolHarness(dagParams *dagconfig.Params, numOutputs uint32, dbName strin
|
|||||||
curHeight := harness.chain.BestHeight()
|
curHeight := harness.chain.BestHeight()
|
||||||
coinbase, err := harness.CreateCoinbaseTx(curHeight+1, numOutputs)
|
coinbase, err := harness.CreateCoinbaseTx(curHeight+1, numOutputs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
harness.txPool.mpUTXOSet.AddTx(coinbase.MsgTx(), curHeight+1)
|
harness.txPool.mpUTXOSet.AddTx(coinbase.MsgTx(), curHeight+1)
|
||||||
for i := uint32(0); i < numOutputs; i++ {
|
for i := uint32(0); i < numOutputs; i++ {
|
||||||
@ -326,7 +340,7 @@ func newPoolHarness(dagParams *dagconfig.Params, numOutputs uint32, dbName strin
|
|||||||
harness.chain.SetHeight(int32(dagParams.CoinbaseMaturity) + curHeight)
|
harness.chain.SetHeight(int32(dagParams.CoinbaseMaturity) + curHeight)
|
||||||
harness.chain.SetMedianTimePast(time.Now())
|
harness.chain.SetMedianTimePast(time.Now())
|
||||||
|
|
||||||
return &harness, outpoints, nil
|
return &harness, outpoints, teardownFunc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// testContext houses a test-related state that is useful to pass to helper
|
// testContext houses a test-related state that is useful to pass to helper
|
||||||
@ -434,10 +448,11 @@ func (p *poolHarness) createTx(outpoint spendableOutpoint, fee uint64, numOutput
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessTransaction(t *testing.T) {
|
func TestProcessTransaction(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 6, "TestProcessTransaction")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 6, "TestProcessTransaction")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
//Checks that a transaction cannot be added to the transaction pool if it's already there
|
//Checks that a transaction cannot be added to the transaction pool if it's already there
|
||||||
@ -593,7 +608,8 @@ func TestProcessTransaction(t *testing.T) {
|
|||||||
Value: 5000000000,
|
Value: 5000000000,
|
||||||
PkScript: p2shPKScript,
|
PkScript: p2shPKScript,
|
||||||
}},
|
}},
|
||||||
LockTime: 0,
|
LockTime: 0,
|
||||||
|
SubNetworkID: wire.SubNetworkDAGCoin,
|
||||||
})
|
})
|
||||||
harness.txPool.mpUTXOSet.AddTx(p2shTx.MsgTx(), curHeight+1)
|
harness.txPool.mpUTXOSet.AddTx(p2shTx.MsgTx(), curHeight+1)
|
||||||
|
|
||||||
@ -608,7 +624,8 @@ func TestProcessTransaction(t *testing.T) {
|
|||||||
Value: 5000000000,
|
Value: 5000000000,
|
||||||
PkScript: dummyPkScript,
|
PkScript: dummyPkScript,
|
||||||
}},
|
}},
|
||||||
LockTime: 0,
|
LockTime: 0,
|
||||||
|
SubNetworkID: wire.SubNetworkDAGCoin,
|
||||||
})
|
})
|
||||||
_, err = harness.txPool.ProcessTransaction(nonStdSigScriptTx, true, false, 0)
|
_, err = harness.txPool.ProcessTransaction(nonStdSigScriptTx, true, false, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -651,8 +668,9 @@ func TestProcessTransaction(t *testing.T) {
|
|||||||
SignatureScript: dummySigScript,
|
SignatureScript: dummySigScript,
|
||||||
Sequence: wire.MaxTxInSequenceNum,
|
Sequence: wire.MaxTxInSequenceNum,
|
||||||
}},
|
}},
|
||||||
TxOut: []*wire.TxOut{},
|
TxOut: []*wire.TxOut{},
|
||||||
LockTime: 0,
|
LockTime: 0,
|
||||||
|
SubNetworkID: wire.SubNetworkDAGCoin,
|
||||||
})
|
})
|
||||||
_, err = harness.txPool.ProcessTransaction(noOutsTx, true, false, 0)
|
_, err = harness.txPool.ProcessTransaction(noOutsTx, true, false, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -728,7 +746,8 @@ func TestProcessTransaction(t *testing.T) {
|
|||||||
Value: 1,
|
Value: 1,
|
||||||
PkScript: dummyPkScript,
|
PkScript: dummyPkScript,
|
||||||
}},
|
}},
|
||||||
LockTime: 0,
|
LockTime: 0,
|
||||||
|
SubNetworkID: wire.SubNetworkDAGCoin,
|
||||||
})
|
})
|
||||||
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
|
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -738,14 +757,14 @@ func TestProcessTransaction(t *testing.T) {
|
|||||||
if code, _ := extractRejectCode(err); code != wire.RejectNonstandard {
|
if code, _ := extractRejectCode(err); code != wire.RejectNonstandard {
|
||||||
t.Errorf("Unexpected error code. Expected %v but got %v", wire.RejectNonstandard, code)
|
t.Errorf("Unexpected error code. Expected %v but got %v", wire.RejectNonstandard, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddrIndex(t *testing.T) {
|
func TestAddrIndex(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestAddrIndex")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestAddrIndex")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
harness.txPool.cfg.AddrIndex = &indexers.AddrIndex{}
|
harness.txPool.cfg.AddrIndex = &indexers.AddrIndex{}
|
||||||
enteredAddUnconfirmedTx := false
|
enteredAddUnconfirmedTx := false
|
||||||
guard := monkey.Patch((*indexers.AddrIndex).AddUnconfirmedTx, func(idx *indexers.AddrIndex, tx *util.Tx, utxoSet blockdag.UTXOSet) {
|
guard := monkey.Patch((*indexers.AddrIndex).AddUnconfirmedTx, func(idx *indexers.AddrIndex, tx *util.Tx, utxoSet blockdag.UTXOSet) {
|
||||||
@ -782,10 +801,11 @@ func TestAddrIndex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFeeEstimatorCfg(t *testing.T) {
|
func TestFeeEstimatorCfg(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestFeeEstimatorCfg")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestFeeEstimatorCfg")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
harness.txPool.cfg.FeeEstimator = &FeeEstimator{}
|
harness.txPool.cfg.FeeEstimator = &FeeEstimator{}
|
||||||
enteredObserveTransaction := false
|
enteredObserveTransaction := false
|
||||||
guard := monkey.Patch((*FeeEstimator).ObserveTransaction, func(ef *FeeEstimator, t *TxDesc) {
|
guard := monkey.Patch((*FeeEstimator).ObserveTransaction, func(ef *FeeEstimator, t *TxDesc) {
|
||||||
@ -808,10 +828,11 @@ func TestFeeEstimatorCfg(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDoubleSpends(t *testing.T) {
|
func TestDoubleSpends(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestDoubleSpends")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestDoubleSpends")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
//Add two transactions to the mempool
|
//Add two transactions to the mempool
|
||||||
@ -857,7 +878,11 @@ func TestDoubleSpends(t *testing.T) {
|
|||||||
//TestFetchTransaction checks that FetchTransaction
|
//TestFetchTransaction checks that FetchTransaction
|
||||||
//returns only transaction from the main pool and not from the orphan pool
|
//returns only transaction from the main pool and not from the orphan pool
|
||||||
func TestFetchTransaction(t *testing.T) {
|
func TestFetchTransaction(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestFetchTransaction")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestFetchTransaction")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
orphanedTx, err := harness.CreateSignedTx([]spendableOutpoint{{
|
orphanedTx, err := harness.CreateSignedTx([]spendableOutpoint{{
|
||||||
@ -899,10 +924,11 @@ func TestFetchTransaction(t *testing.T) {
|
|||||||
// they are all orphans. Finally, it adds the linking transaction and ensures
|
// they are all orphans. Finally, it adds the linking transaction and ensures
|
||||||
// the entire orphan chain is moved to the transaction pool.
|
// the entire orphan chain is moved to the transaction pool.
|
||||||
func TestSimpleOrphanChain(t *testing.T) {
|
func TestSimpleOrphanChain(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestSimpleOrphanChain")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestSimpleOrphanChain")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
// Create a chain of transactions rooted with the first spendable output
|
// Create a chain of transactions rooted with the first spendable output
|
||||||
@ -960,10 +986,11 @@ func TestSimpleOrphanChain(t *testing.T) {
|
|||||||
// TestOrphanReject ensures that orphans are properly rejected when the allow
|
// TestOrphanReject ensures that orphans are properly rejected when the allow
|
||||||
// orphans flag is not set on ProcessTransaction.
|
// orphans flag is not set on ProcessTransaction.
|
||||||
func TestOrphanReject(t *testing.T) {
|
func TestOrphanReject(t *testing.T) {
|
||||||
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanReject")
|
harness, outputs, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanReject")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
// Create a chain of transactions rooted with the first spendable output
|
// Create a chain of transactions rooted with the first spendable output
|
||||||
@ -1014,10 +1041,11 @@ func TestOrphanReject(t *testing.T) {
|
|||||||
// it will check if we are beyond nextExpireScan, and if so, it will remove
|
// it will check if we are beyond nextExpireScan, and if so, it will remove
|
||||||
// all expired orphan transactions
|
// all expired orphan transactions
|
||||||
func TestOrphanExpiration(t *testing.T) {
|
func TestOrphanExpiration(t *testing.T) {
|
||||||
harness, _, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanExpiration")
|
harness, _, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanExpiration")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
expiredTx, err := harness.CreateSignedTx([]spendableOutpoint{{
|
expiredTx, err := harness.CreateSignedTx([]spendableOutpoint{{
|
||||||
@ -1058,10 +1086,11 @@ func TestOrphanExpiration(t *testing.T) {
|
|||||||
//TestMaxOrphanTxSize ensures that a transaction that is
|
//TestMaxOrphanTxSize ensures that a transaction that is
|
||||||
//bigger than MaxOrphanTxSize will get rejected
|
//bigger than MaxOrphanTxSize will get rejected
|
||||||
func TestMaxOrphanTxSize(t *testing.T) {
|
func TestMaxOrphanTxSize(t *testing.T) {
|
||||||
harness, _, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestMaxOrphanTxSize")
|
harness, _, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestMaxOrphanTxSize")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
harness.txPool.cfg.Policy.MaxOrphanTxSize = 1
|
harness.txPool.cfg.Policy.MaxOrphanTxSize = 1
|
||||||
|
|
||||||
@ -1085,10 +1114,11 @@ func TestMaxOrphanTxSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveTransaction(t *testing.T) {
|
func TestRemoveTransaction(t *testing.T) {
|
||||||
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestRemoveTransaction")
|
harness, outputs, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestRemoveTransaction")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
chainedTxns, err := harness.CreateTxChain(outputs[0], 5)
|
chainedTxns, err := harness.CreateTxChain(outputs[0], 5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1130,10 +1160,11 @@ func TestRemoveTransaction(t *testing.T) {
|
|||||||
// TestOrphanEviction ensures that exceeding the maximum number of orphans
|
// TestOrphanEviction ensures that exceeding the maximum number of orphans
|
||||||
// evicts entries to make room for the new ones.
|
// evicts entries to make room for the new ones.
|
||||||
func TestOrphanEviction(t *testing.T) {
|
func TestOrphanEviction(t *testing.T) {
|
||||||
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanEviction")
|
harness, outputs, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanEviction")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
// Create a chain of transactions rooted with the first spendable output
|
// Create a chain of transactions rooted with the first spendable output
|
||||||
@ -1191,10 +1222,11 @@ func TestOrphanEviction(t *testing.T) {
|
|||||||
// Attempt to remove orphans by tag,
|
// Attempt to remove orphans by tag,
|
||||||
// and ensure the state of all other orphans are unaffected.
|
// and ensure the state of all other orphans are unaffected.
|
||||||
func TestRemoveOrphansByTag(t *testing.T) {
|
func TestRemoveOrphansByTag(t *testing.T) {
|
||||||
harness, _, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestRemoveOrphansByTag")
|
harness, _, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestRemoveOrphansByTag")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
orphanedTx1, err := harness.CreateSignedTx([]spendableOutpoint{{
|
orphanedTx1, err := harness.CreateSignedTx([]spendableOutpoint{{
|
||||||
@ -1247,10 +1279,11 @@ func TestRemoveOrphansByTag(t *testing.T) {
|
|||||||
// redeems it and when there is not.
|
// redeems it and when there is not.
|
||||||
func TestBasicOrphanRemoval(t *testing.T) {
|
func TestBasicOrphanRemoval(t *testing.T) {
|
||||||
const maxOrphans = 4
|
const maxOrphans = 4
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestBasicOrphanRemoval")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestBasicOrphanRemoval")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
|
harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
@ -1320,10 +1353,11 @@ func TestBasicOrphanRemoval(t *testing.T) {
|
|||||||
// from other orphans) are removed as expected.
|
// from other orphans) are removed as expected.
|
||||||
func TestOrphanChainRemoval(t *testing.T) {
|
func TestOrphanChainRemoval(t *testing.T) {
|
||||||
const maxOrphans = 10
|
const maxOrphans = 10
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanChainRemoval")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestOrphanChainRemoval")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
|
harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
@ -1381,10 +1415,11 @@ func TestOrphanChainRemoval(t *testing.T) {
|
|||||||
// output that is spend by another transaction entering the pool are removed.
|
// output that is spend by another transaction entering the pool are removed.
|
||||||
func TestMultiInputOrphanDoubleSpend(t *testing.T) {
|
func TestMultiInputOrphanDoubleSpend(t *testing.T) {
|
||||||
const maxOrphans = 4
|
const maxOrphans = 4
|
||||||
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestMultiInputOrphanDoubleSpend")
|
harness, outputs, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestMultiInputOrphanDoubleSpend")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
|
harness.txPool.cfg.Policy.MaxOrphanTxs = maxOrphans
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
@ -1467,10 +1502,11 @@ func TestMultiInputOrphanDoubleSpend(t *testing.T) {
|
|||||||
// TestCheckSpend tests that CheckSpend returns the expected spends found in
|
// TestCheckSpend tests that CheckSpend returns the expected spends found in
|
||||||
// the mempool.
|
// the mempool.
|
||||||
func TestCheckSpend(t *testing.T) {
|
func TestCheckSpend(t *testing.T) {
|
||||||
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestCheckSpend")
|
harness, outputs, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestCheckSpend")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
|
|
||||||
// The mempool is empty, so none of the spendable outputs should have a
|
// The mempool is empty, so none of the spendable outputs should have a
|
||||||
// spend there.
|
// spend there.
|
||||||
@ -1532,10 +1568,11 @@ func TestCheckSpend(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCount(t *testing.T) {
|
func TestCount(t *testing.T) {
|
||||||
harness, outputs, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestCount")
|
harness, outputs, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 1, "TestCount")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
if harness.txPool.Count() != 0 {
|
if harness.txPool.Count() != 0 {
|
||||||
t.Errorf("TestCount: txPool should be initialized with 0 transactions")
|
t.Errorf("TestCount: txPool should be initialized with 0 transactions")
|
||||||
}
|
}
|
||||||
@ -1641,10 +1678,11 @@ func TestExtractRejectCode(t *testing.T) {
|
|||||||
|
|
||||||
// TestHandleNewBlock
|
// TestHandleNewBlock
|
||||||
func TestHandleNewBlock(t *testing.T) {
|
func TestHandleNewBlock(t *testing.T) {
|
||||||
harness, spendableOuts, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestHandleNewBlock")
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 2, "TestHandleNewBlock")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create test pool: %v", err)
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
}
|
}
|
||||||
|
defer teardownFunc()
|
||||||
tc := &testContext{t, harness}
|
tc := &testContext{t, harness}
|
||||||
|
|
||||||
// Create parent transaction for orphan transaction below
|
// Create parent transaction for orphan transaction below
|
||||||
@ -1790,7 +1828,43 @@ var dummyBlock = wire.MsgBlock{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
LockTime: 0,
|
LockTime: 0,
|
||||||
|
SubNetworkID: wire.SubNetworkDAGCoin,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransactionGas(t *testing.T) {
|
||||||
|
harness, spendableOuts, teardownFunc, err := newPoolHarness(&dagconfig.MainNetParams, 6, "TestTransactionGas")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create test pool: %v", err)
|
||||||
|
}
|
||||||
|
defer teardownFunc()
|
||||||
|
// tc := &testContext{t, harness}
|
||||||
|
|
||||||
|
const gasLimit = 10000
|
||||||
|
subnetworkID, err := blockdag.RegisterSubnetworkForTest(harness.txPool.cfg.DAG, gasLimit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to register network: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create valid transaction
|
||||||
|
tx, err := harness.CreateSignedTxForSubnetwork(spendableOuts[:1], 1, subnetworkID, gasLimit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create transaction: %v", err)
|
||||||
|
}
|
||||||
|
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ProcessTransaction: unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create invalid transaction
|
||||||
|
tx, err = harness.CreateSignedTxForSubnetwork(spendableOuts[1:], 1, subnetworkID, gasLimit+1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create transaction: %v", err)
|
||||||
|
}
|
||||||
|
_, err = harness.txPool.ProcessTransaction(tx, true, false, 0)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("ProcessTransaction did not return error, expecting ErrInvalidGas")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -482,7 +482,7 @@ func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress util.Address) (*BlockTe
|
|||||||
prioItem := heap.Pop(priorityQueue).(*txPrioItem)
|
prioItem := heap.Pop(priorityQueue).(*txPrioItem)
|
||||||
tx := prioItem.tx
|
tx := prioItem.tx
|
||||||
|
|
||||||
if tx.MsgTx().SubNetworkID > wire.SubNetworkDAGCoin {
|
if tx.MsgTx().SubNetworkID != wire.SubNetworkDAGCoin {
|
||||||
subnetwork := tx.MsgTx().SubNetworkID
|
subnetwork := tx.MsgTx().SubNetworkID
|
||||||
gasUsage, ok := gasUsageMap[subnetwork]
|
gasUsage, ok := gasUsageMap[subnetwork]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user