mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-22 11:39:15 +00:00
Compare commits
26 Commits
master
...
mempool-re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45ba3bec43 | ||
|
|
befc0172ee | ||
|
|
82e807cf5a | ||
|
|
bfa804b300 | ||
|
|
7115b54d3f | ||
|
|
25cc6184d6 | ||
|
|
4e46be67a4 | ||
|
|
35eb4b9d87 | ||
|
|
2402d48c3e | ||
|
|
9a1d548e7f | ||
|
|
65da2462b8 | ||
|
|
4335a8eaf8 | ||
|
|
d88fe305c5 | ||
|
|
099f023b5b | ||
|
|
2294559198 | ||
|
|
71875c99d6 | ||
|
|
c099fd2986 | ||
|
|
17357a0fca | ||
|
|
01edc43e36 | ||
|
|
b412cd9bbc | ||
|
|
e5e266ff0b | ||
|
|
b2da9a4a00 | ||
|
|
ff10ce145a | ||
|
|
619b7ab8cd | ||
|
|
04c98ac6df | ||
|
|
94ddf0aab0 |
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/kaspanet/kaspad/domain"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool_old"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
"github.com/pkg/errors"
|
||||
@@ -175,15 +175,15 @@ func (flow *handleRelayedTransactionsFlow) receiveTransactions(requestedTransact
|
||||
|
||||
err = flow.Domain().MiningManager().ValidateAndInsertTransaction(tx, true)
|
||||
if err != nil {
|
||||
ruleErr := &mempool.RuleError{}
|
||||
ruleErr := &mempool_old.RuleError{}
|
||||
if !errors.As(err, ruleErr) {
|
||||
return errors.Wrapf(err, "failed to process transaction %s", txID)
|
||||
}
|
||||
|
||||
shouldBan := true
|
||||
if txRuleErr := (&mempool.TxRuleError{}); errors.As(ruleErr.Err, txRuleErr) {
|
||||
if txRuleErr.RejectCode != mempool.RejectInvalid {
|
||||
shouldBan = false
|
||||
shouldBan := false
|
||||
if txRuleErr := (&mempool_old.TxRuleError{}); errors.As(ruleErr.Err, txRuleErr) {
|
||||
if txRuleErr.RejectCode == mempool_old.RejectInvalid {
|
||||
shouldBan = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool_old"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -23,7 +23,7 @@ func HandleSubmitTransaction(context *rpccontext.Context, _ *router.Router, requ
|
||||
transactionID := consensushashing.TransactionID(domainTransaction)
|
||||
err = context.ProtocolManager.AddTransaction(domainTransaction)
|
||||
if err != nil {
|
||||
if !errors.As(err, &mempool.RuleError{}) {
|
||||
if !errors.As(err, &mempool_old.RuleError{}) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/blocktemplatebuilder"
|
||||
mempoolpkg "github.com/kaspanet/kaspad/domain/miningmanager/mempool"
|
||||
mempoolpkg "github.com/kaspanet/kaspad/domain/miningmanager/mempool_old"
|
||||
)
|
||||
|
||||
// Factory instantiates new mining managers
|
||||
|
||||
39
domain/miningmanager/mempool/config.go
Normal file
39
domain/miningmanager/mempool/config.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTransactionExpireIntervalSeconds uint64 = 60
|
||||
defaultTransactionExpireScanIntervalSeconds uint64 = 10
|
||||
defaultOrphanExpireIntervalSeconds uint64 = 60
|
||||
defaultOrphanExpireScanIntervalSeconds uint64 = 10
|
||||
|
||||
defaultMaximumOrphanTransactionSize = 100000
|
||||
defaultMaximumOrphanTransactionCount = 50
|
||||
)
|
||||
|
||||
type config struct {
|
||||
transactionExpireIntervalDAAScore uint64
|
||||
transactionExpireScanIntervalDAAScore uint64
|
||||
orphanExpireIntervalDAAScore uint64
|
||||
orphanExpireScanIntervalDAAScore uint64
|
||||
maximumOrphanTransactionSize int
|
||||
maximumOrphanTransactionCount int
|
||||
}
|
||||
|
||||
func defaultConfig(dagParams *dagconfig.Params) *config {
|
||||
targetBlocksPerSecond := uint64(dagParams.TargetTimePerBlock / time.Second)
|
||||
|
||||
return &config{
|
||||
transactionExpireIntervalDAAScore: defaultTransactionExpireIntervalSeconds / targetBlocksPerSecond,
|
||||
transactionExpireScanIntervalDAAScore: defaultTransactionExpireScanIntervalSeconds / targetBlocksPerSecond,
|
||||
orphanExpireIntervalDAAScore: defaultOrphanExpireIntervalSeconds / targetBlocksPerSecond,
|
||||
orphanExpireScanIntervalDAAScore: defaultOrphanExpireScanIntervalSeconds / targetBlocksPerSecond,
|
||||
maximumOrphanTransactionSize: defaultMaximumOrphanTransactionSize,
|
||||
maximumOrphanTransactionCount: defaultMaximumOrphanTransactionCount,
|
||||
}
|
||||
}
|
||||
@@ -39,32 +39,34 @@ type RejectCode uint8
|
||||
|
||||
// These constants define the various supported reject codes.
|
||||
const (
|
||||
RejectMalformed RejectCode = 0x01
|
||||
RejectInvalid RejectCode = 0x10
|
||||
RejectObsolete RejectCode = 0x11
|
||||
RejectDuplicate RejectCode = 0x12
|
||||
RejectNotRequested RejectCode = 0x13
|
||||
RejectNonstandard RejectCode = 0x40
|
||||
RejectDust RejectCode = 0x41
|
||||
RejectInsufficientFee RejectCode = 0x42
|
||||
RejectFinality RejectCode = 0x43
|
||||
RejectDifficulty RejectCode = 0x44
|
||||
RejectImmatureSpend RejectCode = 0x45
|
||||
RejectMalformed RejectCode = 0x01
|
||||
RejectInvalid RejectCode = 0x10
|
||||
RejectObsolete RejectCode = 0x11
|
||||
RejectDuplicate RejectCode = 0x12
|
||||
RejectNotRequested RejectCode = 0x13
|
||||
RejectNonstandard RejectCode = 0x40
|
||||
RejectDust RejectCode = 0x41
|
||||
RejectInsufficientFee RejectCode = 0x42
|
||||
RejectFinality RejectCode = 0x43
|
||||
RejectDifficulty RejectCode = 0x44
|
||||
RejectImmatureSpend RejectCode = 0x45
|
||||
RejectIncompatibleOrphan RejectCode = 0x64
|
||||
)
|
||||
|
||||
// Map of reject codes back strings for pretty printing.
|
||||
var rejectCodeStrings = map[RejectCode]string{
|
||||
RejectMalformed: "REJECT_MALFORMED",
|
||||
RejectInvalid: "REJECT_INVALID",
|
||||
RejectObsolete: "REJECT_OBSOLETE",
|
||||
RejectDuplicate: "REJECT_DUPLICATE",
|
||||
RejectNonstandard: "REJECT_NONSTANDARD",
|
||||
RejectDust: "REJECT_DUST",
|
||||
RejectInsufficientFee: "REJECT_INSUFFICIENTFEE",
|
||||
RejectFinality: "REJECT_FINALITY",
|
||||
RejectDifficulty: "REJECT_DIFFICULTY",
|
||||
RejectNotRequested: "REJECT_NOTREQUESTED",
|
||||
RejectImmatureSpend: "REJECT_IMMATURESPEND",
|
||||
RejectMalformed: "REJECT_MALFORMED",
|
||||
RejectInvalid: "REJECT_INVALID",
|
||||
RejectObsolete: "REJECT_OBSOLETE",
|
||||
RejectDuplicate: "REJECT_DUPLICATE",
|
||||
RejectNonstandard: "REJECT_NON_STANDARD",
|
||||
RejectDust: "REJECT_DUST",
|
||||
RejectInsufficientFee: "REJECT_INSUFFICIENT_FEE",
|
||||
RejectFinality: "REJECT_FINALITY",
|
||||
RejectDifficulty: "REJECT_DIFFICULTY",
|
||||
RejectNotRequested: "REJECT_NOT_REQUESTED",
|
||||
RejectImmatureSpend: "REJECT_IMMATURE_SPEND",
|
||||
RejectIncompatibleOrphan: "REJECT_INCOMPATIBLE_ORPHAN",
|
||||
}
|
||||
|
||||
// String returns the RejectCode in human-readable form.
|
||||
|
||||
9
domain/miningmanager/mempool/helper_functions.go
Normal file
9
domain/miningmanager/mempool/helper_functions.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package mempool
|
||||
|
||||
func (mp *mempool) virtualDAAScore() (uint64, error) {
|
||||
virtualInfo, err := mp.consensus.GetVirtualInfo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return virtualInfo.DAAScore, nil
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
71
domain/miningmanager/mempool/mempool_utxo_set.go
Normal file
71
domain/miningmanager/mempool/mempool_utxo_set.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
|
||||
)
|
||||
|
||||
type mempoolUTXOSet struct {
|
||||
mempool *mempool
|
||||
poolUnspentOutputs model.OutpointToUTXOEntry
|
||||
transactionsByPreviousOutpoint model.OutpointToTransaction
|
||||
}
|
||||
|
||||
func newMempoolUTXOSet(mp *mempool) *mempoolUTXOSet {
|
||||
return &mempoolUTXOSet{
|
||||
mempool: mp,
|
||||
poolUnspentOutputs: model.OutpointToUTXOEntry{},
|
||||
transactionsByPreviousOutpoint: model.OutpointToTransaction{},
|
||||
}
|
||||
}
|
||||
|
||||
func (mpus *mempoolUTXOSet) addTransaction(transaction *model.MempoolTransaction) {
|
||||
outpoint := &externalapi.DomainOutpoint{TransactionID: *transaction.TransactionID()}
|
||||
|
||||
for i, input := range transaction.Transaction().Inputs {
|
||||
outpoint.Index = uint32(i)
|
||||
|
||||
delete(mpus.poolUnspentOutputs, *outpoint)
|
||||
mpus.transactionsByPreviousOutpoint[input.PreviousOutpoint] = transaction
|
||||
}
|
||||
|
||||
for i, output := range transaction.Transaction().Outputs {
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *transaction.TransactionID(), Index: uint32(i)}
|
||||
|
||||
mpus.poolUnspentOutputs[outpoint] =
|
||||
utxo.NewUTXOEntry(output.Value, output.ScriptPublicKey, false, model.UnacceptedDAAScore)
|
||||
}
|
||||
}
|
||||
|
||||
func (mpus *mempoolUTXOSet) removeTransaction(transaction *model.MempoolTransaction) {
|
||||
for _, input := range transaction.Transaction().Inputs {
|
||||
mpus.poolUnspentOutputs[input.PreviousOutpoint] = input.UTXOEntry
|
||||
delete(mpus.transactionsByPreviousOutpoint, input.PreviousOutpoint)
|
||||
}
|
||||
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *transaction.TransactionID()}
|
||||
for i := range transaction.Transaction().Outputs {
|
||||
outpoint.Index = uint32(i)
|
||||
|
||||
delete(mpus.poolUnspentOutputs, outpoint)
|
||||
}
|
||||
}
|
||||
|
||||
func (mpus *mempoolUTXOSet) checkDoubleSpends(transaction *model.MempoolTransaction) error {
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *transaction.TransactionID()}
|
||||
|
||||
for i, input := range transaction.Transaction().Inputs {
|
||||
outpoint.Index = uint32(i)
|
||||
|
||||
if existingTransaction, exists := mpus.transactionsByPreviousOutpoint[input.PreviousOutpoint]; exists {
|
||||
str := fmt.Sprintf("output %s already spent by transaction %s in the memory pool",
|
||||
input.PreviousOutpoint, existingTransaction.TransactionID())
|
||||
return txRuleError(RejectDuplicate, str)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
6
domain/miningmanager/mempool/model/constants.go
Normal file
6
domain/miningmanager/mempool/model/constants.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package model
|
||||
|
||||
import "math"
|
||||
|
||||
// UnacceptedDAAScore is used to for UTXOEntries that were created by transactions in the mempool.
|
||||
const UnacceptedDAAScore = math.MaxUint64
|
||||
14
domain/miningmanager/mempool/model/map_types.go
Normal file
14
domain/miningmanager/mempool/model/map_types.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// IDToTransaction maps transactionID to a MempoolTransaction
|
||||
type IDToTransaction map[externalapi.DomainTransactionID]*MempoolTransaction
|
||||
|
||||
// OutpointToUTXOEntry maps an outpoint to a UTXOEntry
|
||||
type OutpointToUTXOEntry map[externalapi.DomainOutpoint]externalapi.UTXOEntry
|
||||
|
||||
// OutpointToTransaction maps an outpoint to a MempoolTransaction
|
||||
type OutpointToTransaction map[externalapi.DomainOutpoint]*MempoolTransaction
|
||||
49
domain/miningmanager/mempool/model/mempool_transaction.go
Normal file
49
domain/miningmanager/mempool/model/mempool_transaction.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
)
|
||||
|
||||
// MempoolTransaction represents a transaction inside the main TransactionPool
|
||||
type MempoolTransaction struct {
|
||||
transaction *externalapi.DomainTransaction
|
||||
parentTransactionsInPool OutpointToTransaction
|
||||
isHighPriority bool
|
||||
addedAtDAAScore uint64
|
||||
}
|
||||
|
||||
func NewMempoolTransaction(
|
||||
transaction *externalapi.DomainTransaction,
|
||||
parentTransactionsInPool OutpointToTransaction,
|
||||
isHighPriority bool,
|
||||
addedAtDAAScore uint64,
|
||||
) *MempoolTransaction {
|
||||
return &MempoolTransaction{
|
||||
transaction: transaction,
|
||||
parentTransactionsInPool: parentTransactionsInPool,
|
||||
isHighPriority: isHighPriority,
|
||||
addedAtDAAScore: addedAtDAAScore,
|
||||
}
|
||||
}
|
||||
|
||||
// TransactionID returns the ID of this MempoolTransaction
|
||||
func (mt *MempoolTransaction) TransactionID() *externalapi.DomainTransactionID {
|
||||
return consensushashing.TransactionID(mt.transaction)
|
||||
}
|
||||
|
||||
func (mt *MempoolTransaction) Transaction() *externalapi.DomainTransaction {
|
||||
return mt.transaction
|
||||
}
|
||||
|
||||
func (mt *MempoolTransaction) ParentTransactionsInPool() OutpointToTransaction {
|
||||
return mt.parentTransactionsInPool
|
||||
}
|
||||
|
||||
func (mt *MempoolTransaction) IsHighPriority() bool {
|
||||
return mt.isHighPriority
|
||||
}
|
||||
|
||||
func (mt *MempoolTransaction) AddedAtDAAScore() uint64 {
|
||||
return mt.addedAtDAAScore
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// TransactionsOrderedByFeeRate represents a set of MempoolTransactions ordered by their fee / mass rate
|
||||
type TransactionsOrderedByFeeRate struct {
|
||||
slice []*MempoolTransaction
|
||||
}
|
||||
|
||||
// Push inserts a transaction into the set, placing it in the correct place to preserve order
|
||||
func (tobf *TransactionsOrderedByFeeRate) Push(transaction *MempoolTransaction) error {
|
||||
index, err := tobf.findTransactionIndex(transaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tobf.slice = append(tobf.slice[:index],
|
||||
append([]*MempoolTransaction{transaction}, tobf.slice[index:]...)...)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove removes the given transaction from the set.
|
||||
// Returns an error if transaction does not exist in the set, or if the given transaction does not have mass
|
||||
// and fee filled in.
|
||||
func (tobf *TransactionsOrderedByFeeRate) Remove(transaction *MempoolTransaction) error {
|
||||
index, err := tobf.findTransactionIndex(transaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txID := transaction.TransactionID()
|
||||
if !tobf.slice[index].TransactionID().Equal(txID) {
|
||||
return errors.Errorf("Couldn't find %s in mp.orderedTransactionsByFeeRate", txID)
|
||||
}
|
||||
|
||||
return tobf.RemoveAtIndex(index)
|
||||
}
|
||||
|
||||
// RemoveAtIndex removes the transaction at the given index.
|
||||
// Returns an error in case of out-of-bounds index.
|
||||
func (tobf *TransactionsOrderedByFeeRate) RemoveAtIndex(index int) error {
|
||||
if index < 0 || index > len(tobf.slice)-1 {
|
||||
return errors.Errorf("Index %d is out of bound of this TransactionsOrderedByFeeRate", index)
|
||||
}
|
||||
tobf.slice = append(tobf.slice[:index], tobf.slice[index+1:]...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tobf *TransactionsOrderedByFeeRate) findTransactionIndex(transaction *MempoolTransaction) (int, error) {
|
||||
if transaction.Transaction().Fee == 0 || transaction.Transaction().Mass == 0 {
|
||||
return 0, errors.Errorf("findTxIndexInOrderedTransactionsByFeeRate expects a transaction with " +
|
||||
"populated fee and mass")
|
||||
}
|
||||
txID := transaction.TransactionID()
|
||||
txFeeRate := float64(transaction.Transaction().Fee) / float64(transaction.Transaction().Mass)
|
||||
|
||||
return sort.Search(len(tobf.slice), func(i int) bool {
|
||||
iElement := tobf.slice[i]
|
||||
elementFeeRate := float64(iElement.Transaction().Fee) / float64(iElement.Transaction().Mass)
|
||||
if elementFeeRate > txFeeRate {
|
||||
return true
|
||||
}
|
||||
|
||||
if elementFeeRate == txFeeRate && txID.LessOrEqual(iElement.TransactionID()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}), nil
|
||||
}
|
||||
41
domain/miningmanager/mempool/model/orphan_transaction.go
Normal file
41
domain/miningmanager/mempool/model/orphan_transaction.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
)
|
||||
|
||||
// OrphanTransaction represents a transaction in the OrphanPool
|
||||
type OrphanTransaction struct {
|
||||
transaction *externalapi.DomainTransaction
|
||||
isHighPriority bool
|
||||
addedAtDAAScore uint64
|
||||
}
|
||||
|
||||
func NewOrphanTransaction(
|
||||
transaction *externalapi.DomainTransaction,
|
||||
isHighPriority bool,
|
||||
addedAtDAAScore uint64,
|
||||
) *OrphanTransaction {
|
||||
return &OrphanTransaction{
|
||||
transaction: transaction,
|
||||
isHighPriority: isHighPriority,
|
||||
addedAtDAAScore: addedAtDAAScore,
|
||||
}
|
||||
}
|
||||
|
||||
// TransactionID returns the ID of this OrphanTransaction
|
||||
func (ot *OrphanTransaction) TransactionID() *externalapi.DomainTransactionID {
|
||||
return consensushashing.TransactionID(ot.transaction)
|
||||
}
|
||||
|
||||
func (ot *OrphanTransaction) Transaction() *externalapi.DomainTransaction {
|
||||
return ot.transaction
|
||||
}
|
||||
func (ot *OrphanTransaction) IsHighPriority() bool {
|
||||
return ot.isHighPriority
|
||||
}
|
||||
|
||||
func (ot *OrphanTransaction) AddedAtDAAScore() uint64 {
|
||||
return ot.addedAtDAAScore
|
||||
}
|
||||
8
domain/miningmanager/mempool/model/transaction.go
Normal file
8
domain/miningmanager/mempool/model/transaction.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package model
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
type Transaction interface {
|
||||
TransactionID() *externalapi.DomainTransactionID
|
||||
Transaction() *externalapi.DomainTransaction
|
||||
}
|
||||
260
domain/miningmanager/mempool/orphan_pool.go
Normal file
260
domain/miningmanager/mempool/orphan_pool.go
Normal file
@@ -0,0 +1,260 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type idToOrphan map[externalapi.DomainTransactionID]*model.OrphanTransaction
|
||||
type previousOutpointToOrphans map[externalapi.DomainOutpoint]idToOrphan
|
||||
|
||||
type orphansPool struct {
|
||||
mempool *mempool
|
||||
allOrphans idToOrphan
|
||||
orphansByPreviousOutpoint previousOutpointToOrphans
|
||||
lastExpireScan uint64
|
||||
}
|
||||
|
||||
func newOrphansPool(mp *mempool) *orphansPool {
|
||||
return &orphansPool{
|
||||
mempool: mp,
|
||||
allOrphans: idToOrphan{},
|
||||
orphansByPreviousOutpoint: previousOutpointToOrphans{},
|
||||
lastExpireScan: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (op *orphansPool) maybeAddOrphan(transaction *externalapi.DomainTransaction, isHighPriority bool) error {
|
||||
serializedLength := estimatedsize.TransactionEstimatedSerializedSize(transaction)
|
||||
if serializedLength > uint64(op.mempool.config.maximumOrphanTransactionSize) {
|
||||
str := fmt.Sprintf("orphan transaction size of %d bytes is "+
|
||||
"larger than max allowed size of %d bytes",
|
||||
serializedLength, op.mempool.config.maximumOrphanTransactionSize)
|
||||
return txRuleError(RejectIncompatibleOrphan, str)
|
||||
}
|
||||
if op.mempool.config.maximumOrphanTransactionCount <= 0 {
|
||||
return nil
|
||||
}
|
||||
for len(op.allOrphans) >= op.mempool.config.maximumOrphanTransactionCount {
|
||||
// Don't remove redeemers in the case of a random eviction since
|
||||
// it is quite possible it might be needed again shortly.
|
||||
err := op.removeOrphan(op.randomOrphan().TransactionID(), false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return op.addOrphan(transaction, isHighPriority)
|
||||
}
|
||||
|
||||
func (op *orphansPool) addOrphan(transaction *externalapi.DomainTransaction, isHighPriority bool) error {
|
||||
virtualDAAScore, err := op.mempool.virtualDAAScore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
orphanTransaction := model.NewOrphanTransaction(transaction, isHighPriority, virtualDAAScore)
|
||||
|
||||
op.allOrphans[*orphanTransaction.TransactionID()] = orphanTransaction
|
||||
for _, input := range transaction.Inputs {
|
||||
if input.UTXOEntry == nil {
|
||||
if _, ok := op.orphansByPreviousOutpoint[input.PreviousOutpoint]; !ok {
|
||||
op.orphansByPreviousOutpoint[input.PreviousOutpoint] = idToOrphan{}
|
||||
}
|
||||
op.orphansByPreviousOutpoint[input.PreviousOutpoint][*orphanTransaction.TransactionID()] = orphanTransaction
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *orphansPool) processOrphansAfterAcceptedTransaction(acceptedTransaction *model.MempoolTransaction) (
|
||||
acceptedOrphans []*model.MempoolTransaction, err error) {
|
||||
|
||||
acceptedOrphans = []*model.MempoolTransaction{}
|
||||
queue := []*model.MempoolTransaction{acceptedTransaction}
|
||||
|
||||
for len(queue) > 0 {
|
||||
var current *model.MempoolTransaction
|
||||
current, queue = queue[0], queue[1:]
|
||||
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *current.TransactionID()}
|
||||
for i, output := range current.Transaction().Outputs {
|
||||
outpoint.Index = uint32(i)
|
||||
orphans, ok := op.orphansByPreviousOutpoint[outpoint]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, orphan := range orphans {
|
||||
for _, input := range orphan.Transaction().Inputs {
|
||||
if input.PreviousOutpoint.Equal(&outpoint) {
|
||||
input.UTXOEntry = utxo.NewUTXOEntry(output.Value, output.ScriptPublicKey, false,
|
||||
model.UnacceptedDAAScore)
|
||||
break
|
||||
}
|
||||
}
|
||||
if countUnfilledInputs(orphan) == 0 {
|
||||
unorphanedTransaction, err := op.unorphanTransaction(current)
|
||||
if err != nil {
|
||||
if errors.As(err, &RuleError{}) {
|
||||
log.Infof("Failed to unorphan transaction %s due to rule error: %s", err)
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
acceptedOrphans = append(acceptedOrphans, unorphanedTransaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return acceptedOrphans, nil
|
||||
}
|
||||
|
||||
func countUnfilledInputs(orphan *model.OrphanTransaction) int {
|
||||
unfilledInputs := 0
|
||||
for _, input := range orphan.Transaction().Inputs {
|
||||
if input.UTXOEntry == nil {
|
||||
unfilledInputs++
|
||||
}
|
||||
}
|
||||
return unfilledInputs
|
||||
}
|
||||
|
||||
func (op *orphansPool) unorphanTransaction(orphanTransaction *model.MempoolTransaction) (*model.MempoolTransaction, error) {
|
||||
err := op.removeOrphan(orphanTransaction.TransactionID(), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = op.mempool.validateTransactionInContext(orphanTransaction.Transaction())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
virtualDAAScore, err := op.mempool.virtualDAAScore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mempoolTransaction := model.NewMempoolTransaction(
|
||||
orphanTransaction.Transaction(),
|
||||
op.mempool.transactionsPool.getParentTransactionsInPool(orphanTransaction.Transaction()),
|
||||
false,
|
||||
virtualDAAScore,
|
||||
)
|
||||
err = op.mempool.transactionsPool.addMempoolTransaction(mempoolTransaction)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mempoolTransaction, nil
|
||||
}
|
||||
|
||||
func (op *orphansPool) removeOrphan(orphanTransactionID *externalapi.DomainTransactionID, removeRedeemers bool) error {
|
||||
orphanTransaction, ok := op.allOrphans[*orphanTransactionID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
delete(op.allOrphans, *orphanTransactionID)
|
||||
|
||||
for i, input := range orphanTransaction.Transaction().Inputs {
|
||||
orphans, ok := op.orphansByPreviousOutpoint[input.PreviousOutpoint]
|
||||
if !ok {
|
||||
return errors.Errorf("Input No. %d of %s (%s) doesn't exist in orphansByPreviousOutpoint",
|
||||
i, orphanTransactionID, input.PreviousOutpoint)
|
||||
}
|
||||
delete(orphans, *orphanTransactionID)
|
||||
if len(orphans) == 0 {
|
||||
delete(op.orphansByPreviousOutpoint, input.PreviousOutpoint)
|
||||
}
|
||||
}
|
||||
|
||||
if removeRedeemers {
|
||||
err := op.removeRedeemersOf(orphanTransaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *orphansPool) removeRedeemersOf(transaction model.Transaction) error {
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *transaction.TransactionID()}
|
||||
for i := range transaction.Transaction().Outputs {
|
||||
outpoint.Index = uint32(i)
|
||||
for _, orphan := range op.orphansByPreviousOutpoint[outpoint] {
|
||||
// Recursive call is bound by size of orphan pool (which is very small)
|
||||
err := op.removeOrphan(orphan.TransactionID(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *orphansPool) expireOrphanTransactions() error {
|
||||
virtualDAAScore, err := op.mempool.virtualDAAScore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if virtualDAAScore-op.lastExpireScan < op.mempool.config.orphanExpireScanIntervalDAAScore {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, orphanTransaction := range op.allOrphans {
|
||||
// Never expire high priority transactions
|
||||
if orphanTransaction.IsHighPriority() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Remove all transactions whose addedAtDAAScore is older then transactionExpireIntervalDAAScore
|
||||
if virtualDAAScore-orphanTransaction.AddedAtDAAScore() > op.mempool.config.orphanExpireIntervalDAAScore {
|
||||
err = op.removeOrphan(orphanTransaction.TransactionID(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
op.lastExpireScan = virtualDAAScore
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *orphansPool) updateOrphansAfterTransactionRemoved(
|
||||
removedTransaction *model.MempoolTransaction, removeRedeemers bool) error {
|
||||
|
||||
if removeRedeemers {
|
||||
return op.removeRedeemersOf(removedTransaction)
|
||||
}
|
||||
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *removedTransaction.TransactionID()}
|
||||
for i := range removedTransaction.Transaction().Outputs {
|
||||
outpoint.Index = uint32(i)
|
||||
for _, orphan := range op.orphansByPreviousOutpoint[outpoint] {
|
||||
for _, input := range orphan.Transaction().Inputs {
|
||||
if input.PreviousOutpoint.TransactionID.Equal(removedTransaction.TransactionID()) {
|
||||
input.UTXOEntry = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (op *orphansPool) randomOrphan() *model.OrphanTransaction {
|
||||
for _, orphan := range op.allOrphans {
|
||||
return orphan
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
151
domain/miningmanager/mempool/transactions_pool.go
Normal file
151
domain/miningmanager/mempool/transactions_pool.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
|
||||
)
|
||||
|
||||
type transactionsPool struct {
|
||||
mempool *mempool
|
||||
allTransactions model.IDToTransaction
|
||||
highPriorityTransactions model.IDToTransaction
|
||||
chainedTransactionsByPreviousOutpoint model.OutpointToTransaction
|
||||
transactionsOrderedByFeeRate model.TransactionsOrderedByFeeRate
|
||||
lastExpireScan uint64
|
||||
}
|
||||
|
||||
func newTransactionsPool(mp *mempool) *transactionsPool {
|
||||
return &transactionsPool{
|
||||
mempool: mp,
|
||||
allTransactions: model.IDToTransaction{},
|
||||
highPriorityTransactions: model.IDToTransaction{},
|
||||
chainedTransactionsByPreviousOutpoint: model.OutpointToTransaction{},
|
||||
transactionsOrderedByFeeRate: model.TransactionsOrderedByFeeRate{},
|
||||
lastExpireScan: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransaction,
|
||||
parentTransactionsInPool model.OutpointToTransaction, isHighPriority bool) error {
|
||||
|
||||
virtualDAAScore, err := tp.mempool.virtualDAAScore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mempoolTransaction := model.NewMempoolTransaction(
|
||||
transaction, parentTransactionsInPool, isHighPriority, virtualDAAScore)
|
||||
|
||||
return tp.addMempoolTransaction(mempoolTransaction)
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error {
|
||||
tp.allTransactions[*transaction.TransactionID()] = transaction
|
||||
|
||||
for outpoint, parentTransactionInPool := range transaction.ParentTransactionsInPool() {
|
||||
tp.chainedTransactionsByPreviousOutpoint[outpoint] = parentTransactionInPool
|
||||
}
|
||||
|
||||
tp.mempool.mempoolUTXOSet.addTransaction(transaction)
|
||||
|
||||
err := tp.transactionsOrderedByFeeRate.Push(transaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if transaction.IsHighPriority() {
|
||||
tp.highPriorityTransactions[*transaction.TransactionID()] = transaction
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) removeTransaction(transaction *model.MempoolTransaction) error {
|
||||
delete(tp.allTransactions, *transaction.TransactionID())
|
||||
|
||||
err := tp.transactionsOrderedByFeeRate.Remove(transaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delete(tp.highPriorityTransactions, *transaction.TransactionID())
|
||||
|
||||
for outpoint := range transaction.ParentTransactionsInPool() {
|
||||
delete(tp.chainedTransactionsByPreviousOutpoint, outpoint)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) expireOldTransactions() error {
|
||||
virtualDAAScore, err := tp.mempool.virtualDAAScore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if virtualDAAScore-tp.lastExpireScan < tp.mempool.config.transactionExpireScanIntervalDAAScore {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, mempoolTransaction := range tp.allTransactions {
|
||||
// Never expire high priority transactions
|
||||
if mempoolTransaction.IsHighPriority() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Remove all transactions whose addedAtDAAScore is older then transactionExpireIntervalDAAScore
|
||||
if virtualDAAScore-mempoolTransaction.AddedAtDAAScore() > tp.mempool.config.transactionExpireIntervalDAAScore {
|
||||
err = tp.mempool.RemoveTransaction(mempoolTransaction.TransactionID(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tp.lastExpireScan = virtualDAAScore
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransaction {
|
||||
result := []*externalapi.DomainTransaction{}
|
||||
|
||||
for _, mempoolTransaction := range tp.allTransactions {
|
||||
if len(mempoolTransaction.ParentTransactionsInPool()) == 0 {
|
||||
result = append(result, mempoolTransaction.Transaction())
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) getParentTransactionsInPool(
|
||||
transaction *externalapi.DomainTransaction) model.OutpointToTransaction {
|
||||
|
||||
parentsTransactionsInPool := model.OutpointToTransaction{}
|
||||
|
||||
for _, input := range transaction.Inputs {
|
||||
transaction := tp.allTransactions[input.PreviousOutpoint.TransactionID]
|
||||
parentsTransactionsInPool[input.PreviousOutpoint] = transaction
|
||||
}
|
||||
|
||||
return parentsTransactionsInPool
|
||||
}
|
||||
|
||||
func (tp *transactionsPool) getRedeemers(transaction *model.MempoolTransaction) []*model.MempoolTransaction {
|
||||
queue := []*model.MempoolTransaction{transaction}
|
||||
redeemers := []*model.MempoolTransaction{}
|
||||
for len(queue) > 0 {
|
||||
var current *model.MempoolTransaction
|
||||
current, queue = queue[0], queue[1:]
|
||||
|
||||
outpoint := externalapi.DomainOutpoint{TransactionID: *current.TransactionID()}
|
||||
for i := range current.Transaction().Outputs {
|
||||
outpoint.Index = uint32(i)
|
||||
if redeemerTransaction, ok := tp.chainedTransactionsByPreviousOutpoint[outpoint]; ok {
|
||||
queue = append(queue, redeemerTransaction)
|
||||
redeemers = append(redeemers, redeemerTransaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
return redeemers
|
||||
}
|
||||
@@ -59,10 +59,10 @@ be an exhaustive list.
|
||||
Errors
|
||||
|
||||
Errors returned by this package are either the raw errors provided by underlying
|
||||
calls or of type mempool.RuleError. Since there are two classes of rules
|
||||
calls or of type mempool_old.RuleError. Since there are two classes of rules
|
||||
(mempool acceptance rules and blockDAG (consensus) acceptance rules), the
|
||||
mempool.RuleError type contains a single Err field which will, in turn, either
|
||||
be a mempool.TxRuleError or a ruleerrors.RuleError. The first indicates a
|
||||
mempool_old.RuleError type contains a single Err field which will, in turn, either
|
||||
be a mempool_old.TxRuleError or a ruleerrors.RuleError. The first indicates a
|
||||
violation of mempool acceptance rules while the latter indicates a violation of
|
||||
consensus acceptance rules. This allows the caller to easily differentiate
|
||||
between unexpected errors, such as database errors, versus errors due to rule
|
||||
@@ -70,4 +70,4 @@ violations through type assertions. In addition, callers can programmatically
|
||||
determine the specific rule violation by type asserting the Err field to one of
|
||||
the aforementioned types and examining their underlying ErrorCode field.
|
||||
*/
|
||||
package mempool
|
||||
package mempool_old
|
||||
124
domain/miningmanager/mempool_old/error.go
Normal file
124
domain/miningmanager/mempool_old/error.go
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2014-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mempool_old
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// RuleError identifies a rule violation. It is used to indicate that
|
||||
// processing of a transaction failed due to one of the many validation
|
||||
// rules. The caller can use type assertions to determine if a failure was
|
||||
// specifically due to a rule violation and use the Err field to access the
|
||||
// underlying error, which will be either a TxRuleError or a
|
||||
// ruleerrors.RuleError.
|
||||
type RuleError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// Error satisfies the error interface and prints human-readable errors.
|
||||
func (e RuleError) Error() string {
|
||||
if e.Err == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
// Unwrap unwraps the wrapped error
|
||||
func (e RuleError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// RejectCode represents a numeric value by which a remote peer indicates
|
||||
// why a message was rejected.
|
||||
type RejectCode uint8
|
||||
|
||||
// These constants define the various supported reject codes.
|
||||
const (
|
||||
RejectMalformed RejectCode = 0x01
|
||||
RejectInvalid RejectCode = 0x10
|
||||
RejectObsolete RejectCode = 0x11
|
||||
RejectDuplicate RejectCode = 0x12
|
||||
RejectNotRequested RejectCode = 0x13
|
||||
RejectNonstandard RejectCode = 0x40
|
||||
RejectDust RejectCode = 0x41
|
||||
RejectInsufficientFee RejectCode = 0x42
|
||||
RejectFinality RejectCode = 0x43
|
||||
RejectDifficulty RejectCode = 0x44
|
||||
RejectImmatureSpend RejectCode = 0x45
|
||||
)
|
||||
|
||||
// Map of reject codes back strings for pretty printing.
|
||||
var rejectCodeStrings = map[RejectCode]string{
|
||||
RejectMalformed: "REJECT_MALFORMED",
|
||||
RejectInvalid: "REJECT_INVALID",
|
||||
RejectObsolete: "REJECT_OBSOLETE",
|
||||
RejectDuplicate: "REJECT_DUPLICATE",
|
||||
RejectNonstandard: "REJECT_NONSTANDARD",
|
||||
RejectDust: "REJECT_DUST",
|
||||
RejectInsufficientFee: "REJECT_INSUFFICIENTFEE",
|
||||
RejectFinality: "REJECT_FINALITY",
|
||||
RejectDifficulty: "REJECT_DIFFICULTY",
|
||||
RejectNotRequested: "REJECT_NOTREQUESTED",
|
||||
RejectImmatureSpend: "REJECT_IMMATURESPEND",
|
||||
}
|
||||
|
||||
// String returns the RejectCode in human-readable form.
|
||||
func (code RejectCode) String() string {
|
||||
if s, ok := rejectCodeStrings[code]; ok {
|
||||
return s
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Unknown RejectCode (%d)", uint8(code))
|
||||
}
|
||||
|
||||
// TxRuleError identifies a rule violation. It is used to indicate that
|
||||
// processing of a transaction failed due to one of the many validation
|
||||
// rules. The caller can use type assertions to determine if a failure was
|
||||
// specifically due to a rule violation and access the ErrorCode field to
|
||||
// ascertain the specific reason for the rule violation.
|
||||
type TxRuleError struct {
|
||||
RejectCode RejectCode // The code to send with reject messages
|
||||
Description string // Human readable description of the issue
|
||||
}
|
||||
|
||||
// Error satisfies the error interface and prints human-readable errors.
|
||||
func (e TxRuleError) Error() string {
|
||||
return e.Description
|
||||
}
|
||||
|
||||
// txRuleError creates an underlying TxRuleError with the given a set of
|
||||
// arguments and returns a RuleError that encapsulates it.
|
||||
func txRuleError(c RejectCode, desc string) RuleError {
|
||||
return RuleError{
|
||||
Err: TxRuleError{RejectCode: c, Description: desc},
|
||||
}
|
||||
}
|
||||
|
||||
func newRuleError(err error) RuleError {
|
||||
return RuleError{
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// extractRejectCode attempts to return a relevant reject code for a given error
|
||||
// by examining the error for known types. It will return true if a code
|
||||
// was successfully extracted.
|
||||
func extractRejectCode(err error) (RejectCode, bool) {
|
||||
// Pull the underlying error out of a RuleError.
|
||||
var ruleErr RuleError
|
||||
if ok := errors.As(err, &ruleErr); ok {
|
||||
err = ruleErr.Err
|
||||
}
|
||||
|
||||
var trErr TxRuleError
|
||||
if errors.As(err, &trErr) {
|
||||
return trErr.RejectCode, true
|
||||
}
|
||||
|
||||
return RejectInvalid, false
|
||||
}
|
||||
11
domain/miningmanager/mempool_old/log.go
Normal file
11
domain/miningmanager/mempool_old/log.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mempool_old
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
)
|
||||
|
||||
var log = logger.RegisterSubSystem("TXMP")
|
||||
1045
domain/miningmanager/mempool_old/mempool.go
Normal file
1045
domain/miningmanager/mempool_old/mempool.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
package mempool
|
||||
package mempool_old
|
||||
|
||||
import (
|
||||
"math"
|
||||
@@ -2,10 +2,11 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mempool
|
||||
package mempool_old
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
|
||||
consensusexternalapi "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mempool
|
||||
package mempool_old
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,10 +1,11 @@
|
||||
package miningmanager_test
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool_old"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
|
||||
@@ -84,8 +85,8 @@ func TestImmatureSpend(t *testing.T) {
|
||||
miningManager := miningFactory.NewMiningManager(tc, &consensusConfig.Params)
|
||||
tx := createTransactionWithUTXOEntry(t, 0)
|
||||
err = miningManager.ValidateAndInsertTransaction(tx, false)
|
||||
txRuleError := &mempool.TxRuleError{}
|
||||
if !errors.As(err, txRuleError) || txRuleError.RejectCode != mempool.RejectImmatureSpend {
|
||||
txRuleError := &mempool_old.TxRuleError{}
|
||||
if !errors.As(err, txRuleError) || txRuleError.RejectCode != mempool_old.RejectImmatureSpend {
|
||||
t.Fatalf("Unexpected error %+v", err)
|
||||
}
|
||||
transactionsFromMempool := miningManager.AllTransactions()
|
||||
|
||||
Reference in New Issue
Block a user