mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-20 13:56:45 +00:00

* BlockCandidateTransactions patch * Fix condition * Fix fee * Fix bug * Reject from mempool * Fix hasCoinbaseInput * Fix position * Bump version to v0.12.14
80 lines
2.6 KiB
Go
80 lines
2.6 KiB
Go
package mempool
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
|
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
|
)
|
|
|
|
func (mp *mempool) validateTransactionPreUTXOEntry(transaction *externalapi.DomainTransaction) error {
|
|
err := mp.validateTransactionInIsolation(transaction)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := mp.mempoolUTXOSet.checkDoubleSpends(transaction); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (mp *mempool) validateTransactionInIsolation(transaction *externalapi.DomainTransaction) error {
|
|
transactionID := consensushashing.TransactionID(transaction)
|
|
if _, ok := mp.transactionsPool.allTransactions[*transactionID]; ok {
|
|
return transactionRuleError(RejectDuplicate,
|
|
fmt.Sprintf("transaction %s is already in the mempool", transactionID))
|
|
}
|
|
|
|
if !mp.config.AcceptNonStandard {
|
|
if err := mp.checkTransactionStandardInIsolation(transaction); err != nil {
|
|
// Attempt to extract a reject code from the error so
|
|
// it can be retained. When not possible, fall back to
|
|
// a non standard error.
|
|
rejectCode, found := extractRejectCode(err)
|
|
if !found {
|
|
rejectCode = RejectNonstandard
|
|
}
|
|
str := fmt.Sprintf("transaction %s is not standard: %s", transactionID, err)
|
|
return transactionRuleError(rejectCode, str)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (mp *mempool) validateTransactionInContext(transaction *externalapi.DomainTransaction) error {
|
|
hasCoinbaseInput := false
|
|
for _, input := range transaction.Inputs {
|
|
if input.UTXOEntry.IsCoinbase() {
|
|
hasCoinbaseInput = true
|
|
break
|
|
}
|
|
}
|
|
|
|
numExtraOuts := len(transaction.Outputs) - len(transaction.Inputs)
|
|
if !hasCoinbaseInput && numExtraOuts > 2 && transaction.Fee < uint64(numExtraOuts)*constants.SompiPerKaspa {
|
|
log.Warnf("Rejected spam tx %s from mempool (%d outputs)", consensushashing.TransactionID(transaction), len(transaction.Outputs))
|
|
return transactionRuleError(RejectSpamTx, fmt.Sprintf("Rejected spam tx %s from mempool", consensushashing.TransactionID(transaction)))
|
|
}
|
|
|
|
if !mp.config.AcceptNonStandard {
|
|
err := mp.checkTransactionStandardInContext(transaction)
|
|
if err != nil {
|
|
// Attempt to extract a reject code from the error so
|
|
// it can be retained. When not possible, fall back to
|
|
// a non standard error.
|
|
rejectCode, found := extractRejectCode(err)
|
|
if !found {
|
|
rejectCode = RejectNonstandard
|
|
}
|
|
str := fmt.Sprintf("transaction inputs %s are not standard: %s",
|
|
consensushashing.TransactionID(transaction), err)
|
|
return transactionRuleError(rejectCode, str)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|