Skip to content

Commit

Permalink
Reject very old votes from the memory pool (#168)
Browse files Browse the repository at this point in the history
Very old votes are now rejected from the memory pool by default.
The feature can be disabled with a runtime flag. A redundant
function that determined the transaction type was also removed
from mempool.go.
  • Loading branch information
cjepson authored and alexlyp committed May 16, 2016
1 parent 1da2845 commit ebade40
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 25 deletions.
3 changes: 3 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const (
defaultAddrIndex = false
defaultNonAggressive = false
defaultNoMiningStateSync = false
defaultAllowOldVotes = false
)

var (
Expand Down Expand Up @@ -124,6 +125,7 @@ type config struct {
DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up, and the exits."`
NonAggressive bool `long:"nonaggressive" description:"Disable mining off of the parent block of the blockchain if there aren't enough voters"`
NoMiningStateSync bool `long:"nominingstatesync" description:"Disable synchronizing the mining state with other nodes"`
AllowOldVotes bool `long:"allowoldvotes" description:"Enable the addition of very old votes to the mempool"`
onionlookup func(string) ([]net.IP, error)
lookup func(string) ([]net.IP, error)
oniondial func(string, string) (net.Conn, error)
Expand Down Expand Up @@ -334,6 +336,7 @@ func loadConfig() (*config, []string, error) {
Generate: defaultGenerate,
NoAddrIndex: defaultAddrIndex,
NoMiningStateSync: defaultNoMiningStateSync,
AllowOldVotes: defaultAllowOldVotes,
}

// Service options which are only added on Windows.
Expand Down
49 changes: 24 additions & 25 deletions mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ const (
// of height before SSGen relating to that block are pruned.
heightDiffToPruneVotes = 10

// If a vote is on a block whose height is before tip minus this
// amount, reject it from being added to the mempool.
maximumVoteAgeDelta = 1440

// maxNullDataOutputs is the maximum number of OP_RETURN null data
// pushes in a transaction, after which it is considered non-standard.
maxNullDataOutputs = 4
Expand Down Expand Up @@ -1142,29 +1146,6 @@ func (mp *txMemPool) FilterTransactionsByAddress(
return nil, fmt.Errorf("address does not have any transactions in the pool")
}

// This function detects whether or not a transaction is a stake transaction and,
// if it is, also returns the type of stake transaction.
func detectTxType(tx *dcrutil.Tx) stake.TxType {
// Check to see if it's an SStx
if pass, _ := stake.IsSStx(tx); pass {
return stake.TxTypeSStx
}

// Check to see if it's an SSGen
if pass, _ := stake.IsSSGen(tx); pass {
return stake.TxTypeSSGen
}

// Check to see if it's an SSGen
if pass, _ := stake.IsSSRtx(tx); pass {
return stake.TxTypeSSRtx
}

// If it's none of these things, it's a malformed or non-standard stake tx
// which will be rejected during other checks or a regular tx.
return stake.TxTypeRegular
}

// maybeAcceptTransaction is the internal function which implements the public
// MaybeAcceptTransaction. See the comment for MaybeAcceptTransaction for
// more details.
Expand Down Expand Up @@ -1229,7 +1210,7 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew,
// Determine what type of transaction we're dealing with (regular or stake).
// Then, be sure to set the tx tree correctly as it's possible a use submitted
// it to the network with TxTreeUnknown.
txType := detectTxType(tx)
txType := stake.DetermineTxType(tx)
if txType == stake.TxTypeRegular {
tx.SetTree(dcrutil.TxTreeRegular)
} else {
Expand Down Expand Up @@ -1317,6 +1298,24 @@ func (mp *txMemPool) maybeAcceptTransaction(tx *dcrutil.Tx, isNew,
return nil, err
}
}

// Votes that are on too old of blocks are rejected.
if txType == stake.TxTypeSSGen {
_, voteHeight, err := stake.GetSSGenBlockVotedOn(tx)
if err != nil {
return nil, err
}

if (int64(voteHeight) < curHeight-maximumVoteAgeDelta) &&
!cfg.AllowOldVotes {
str := fmt.Sprintf("transaction %v votes on old "+
"block height of %v which is before the "+
"current cutoff height of %v",
tx.Sha(), voteHeight, curHeight-maximumVoteAgeDelta)
return nil, txRuleError(wire.RejectNonstandard, str)
}
}

// Fetch all of the transactions referenced by the inputs to this
// transaction. This function also attempts to fetch the transaction
// itself to be used for detecting a duplicate transaction without
Expand Down Expand Up @@ -1693,7 +1692,7 @@ func (mp *txMemPool) PruneStakeTx(requiredStakeDifficulty, height int64) {

func (mp *txMemPool) pruneStakeTx(requiredStakeDifficulty, height int64) {
for _, tx := range mp.pool {
txType := detectTxType(tx.Tx)
txType := stake.DetermineTxType(tx.Tx)
if txType == stake.TxTypeSStx &&
tx.Height+int64(heightDiffToPruneTicket) < height {
mp.removeTransaction(tx.Tx, true)
Expand Down

0 comments on commit ebade40

Please sign in to comment.