mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-11-23 22:15:54 +00:00
Revalidate transactions before rebroadcast
This commit is contained in:
parent
4f4a8934e7
commit
903fa58957
@ -80,7 +80,11 @@ func (f *FlowContext) broadcastTransactionsAfterBlockAdded(
|
||||
|
||||
var txIDsToRebroadcast []*externalapi.DomainTransactionID
|
||||
if f.shouldRebroadcastTransactions() {
|
||||
txIDsToRebroadcast = f.txIDsToRebroadcast()
|
||||
var err error
|
||||
txIDsToRebroadcast, err = f.txIDsToRebroadcast()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
txIDsToBroadcast := make([]*externalapi.DomainTransactionID, len(transactionsAcceptedToMempool)+len(txIDsToRebroadcast))
|
||||
|
||||
@ -44,17 +44,25 @@ func (f *FlowContext) shouldRebroadcastTransactions() bool {
|
||||
return time.Since(f.lastRebroadcastTime) > rebroadcastInterval
|
||||
}
|
||||
|
||||
func (f *FlowContext) txIDsToRebroadcast() []*externalapi.DomainTransactionID {
|
||||
func (f *FlowContext) txIDsToRebroadcast() ([]*externalapi.DomainTransactionID, error) {
|
||||
f.transactionsToRebroadcastLock.Lock()
|
||||
defer f.transactionsToRebroadcastLock.Unlock()
|
||||
|
||||
txIDs := make([]*externalapi.DomainTransactionID, len(f.transactionsToRebroadcast))
|
||||
txIDs := make([]*externalapi.DomainTransactionID, 0, len(f.transactionsToRebroadcast))
|
||||
i := 0
|
||||
for _, tx := range f.transactionsToRebroadcast {
|
||||
txIDs[i] = consensushashing.TransactionID(tx)
|
||||
isValid, err := f.Domain().MiningManager().RevalidateTransaction(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !isValid {
|
||||
continue
|
||||
}
|
||||
|
||||
txIDs = append(txIDs, consensushashing.TransactionID(tx))
|
||||
i++
|
||||
}
|
||||
return txIDs
|
||||
return txIDs, nil
|
||||
}
|
||||
|
||||
// SharedRequestedTransactions returns a *transactionrelay.SharedRequestedTransactions for sharing
|
||||
|
||||
1
domain/miningmanager/mempool/expiration_heap.go
Normal file
1
domain/miningmanager/mempool/expiration_heap.go
Normal file
@ -0,0 +1 @@
|
||||
package mempool
|
||||
@ -7,22 +7,19 @@ package mempool
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
|
||||
|
||||
consensusexternalapi "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/estimatedsize"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
|
||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||
miningmanagermodel "github.com/kaspanet/kaspad/domain/miningmanager/model"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"github.com/pkg/errors"
|
||||
@ -164,6 +161,10 @@ type txDescriptor struct {
|
||||
// one that is accepted to pool, but cannot be mined in next block because it
|
||||
// depends on outputs of accepted, but still not mined transaction
|
||||
depCount int
|
||||
|
||||
// expirationDAAScore is the virtual DAA score at which this transaction is expired
|
||||
// if expirationDAAScore == 0 - the transaction never expires.
|
||||
expirationDAAScore uint64
|
||||
}
|
||||
|
||||
// orphanTx is normal transaction that references an ancestor transaction
|
||||
@ -411,6 +412,13 @@ type transactionAndOutpoint struct {
|
||||
outpoint *consensusexternalapi.DomainOutpoint
|
||||
}
|
||||
|
||||
func (mp *mempool) removeTransactionAndItsChainedTransactionsWithLock(transaction *consensusexternalapi.DomainTransaction) error {
|
||||
mp.mtx.Lock()
|
||||
defer mp.mtx.Unlock()
|
||||
|
||||
return mp.removeTransactionAndItsChainedTransactions(transaction)
|
||||
}
|
||||
|
||||
// removeTransactionAndItsChainedTransactions removes a transaction and all of its chained transaction from the mempool.
|
||||
// This function MUST be called with the mempool lock held (for writes).
|
||||
func (mp *mempool) removeTransactionAndItsChainedTransactions(transaction *consensusexternalapi.DomainTransaction) error {
|
||||
@ -899,7 +907,9 @@ func (mp *mempool) processOrphans(acceptedTx *consensusexternalapi.DomainTransac
|
||||
// the passed one being accepted.
|
||||
//
|
||||
// This function is safe for concurrent access.
|
||||
func (mp *mempool) ValidateAndInsertTransaction(tx *consensusexternalapi.DomainTransaction, allowOrphan bool) error {
|
||||
func (mp *mempool) ValidateAndInsertTransaction(
|
||||
tx *consensusexternalapi.DomainTransaction, expirationDAAScore uint64, allowOrphan bool) error {
|
||||
|
||||
log.Tracef("Processing transaction %s", consensushashing.TransactionID(tx))
|
||||
|
||||
// Protect concurrent access.
|
||||
@ -1042,3 +1052,25 @@ func (mp *mempool) RemoveTransactions(txs []*consensusexternalapi.DomainTransact
|
||||
|
||||
return mp.removeTransactionsFromPool(txs)
|
||||
}
|
||||
|
||||
// RevalidateTransaction revalidates given transaction, and removes from mempool if it isn't valid
|
||||
func (mp *mempool) RevalidateTransaction(tx *consensusexternalapi.DomainTransaction) (isValid bool, err error) {
|
||||
tx = tx.Clone()
|
||||
|
||||
_ = mp.mempoolUTXOSet.populateUTXOEntries(tx)
|
||||
|
||||
err = mp.consensus.ValidateTransactionAndPopulateWithConsensusData(tx)
|
||||
if err != nil {
|
||||
if errors.As(err, &ruleerrors.RuleError{}) {
|
||||
log.Debugf("Transaction %s was found invalid during revalidate and therefore is being removed from mempool",
|
||||
consensushashing.TransactionID(tx))
|
||||
err := mp.removeTransactionAndItsChainedTransactionsWithLock(tx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ type MiningManager interface {
|
||||
TransactionCount() int
|
||||
HandleNewBlockTransactions(txs []*consensusexternalapi.DomainTransaction) ([]*consensusexternalapi.DomainTransaction, error)
|
||||
ValidateAndInsertTransaction(transaction *consensusexternalapi.DomainTransaction, allowOrphan bool) error
|
||||
RevalidateTransaction(tx *consensusexternalapi.DomainTransaction) (isValid bool, err error)
|
||||
}
|
||||
|
||||
type miningManager struct {
|
||||
@ -51,3 +52,7 @@ func (mm *miningManager) AllTransactions() []*consensusexternalapi.DomainTransac
|
||||
func (mm *miningManager) TransactionCount() int {
|
||||
return mm.mempool.TransactionCount()
|
||||
}
|
||||
|
||||
func (mm *miningManager) RevalidateTransaction(tx *consensusexternalapi.DomainTransaction) (isValid bool, err error) {
|
||||
return mm.mempool.RevalidateTransaction(tx)
|
||||
}
|
||||
|
||||
@ -14,4 +14,5 @@ type Mempool interface {
|
||||
GetTransaction(transactionID *consensusexternalapi.DomainTransactionID) (*consensusexternalapi.DomainTransaction, bool)
|
||||
AllTransactions() []*consensusexternalapi.DomainTransaction
|
||||
TransactionCount() int
|
||||
RevalidateTransaction(tx *consensusexternalapi.DomainTransaction) (isValid bool, err error)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user