@ -19,6 +19,7 @@ var (
// Transaction Pool Errors
// Transaction Pool Errors
ErrInvalidSender = errors . New ( "Invalid sender" )
ErrInvalidSender = errors . New ( "Invalid sender" )
ErrNonce = errors . New ( "Nonce too low" )
ErrNonce = errors . New ( "Nonce too low" )
ErrCheap = errors . New ( "Gas price too low for acceptance" )
ErrBalance = errors . New ( "Insufficient balance" )
ErrBalance = errors . New ( "Insufficient balance" )
ErrNonExistentAccount = errors . New ( "Account does not exist or account balance too low" )
ErrNonExistentAccount = errors . New ( "Account does not exist or account balance too low" )
ErrInsufficientFunds = errors . New ( "Insufficient funds for gas * price + value" )
ErrInsufficientFunds = errors . New ( "Insufficient funds for gas * price + value" )
@ -27,6 +28,10 @@ var (
ErrNegativeValue = errors . New ( "Negative value" )
ErrNegativeValue = errors . New ( "Negative value" )
)
)
const (
maxQueued = 200 // max limit of queued txs per address
)
type stateFn func ( ) * state . StateDB
type stateFn func ( ) * state . StateDB
// TxPool contains all currently known transactions. Transactions
// TxPool contains all currently known transactions. Transactions
@ -41,6 +46,7 @@ type TxPool struct {
currentState stateFn // The state function which will allow us to do some pre checkes
currentState stateFn // The state function which will allow us to do some pre checkes
pendingState * state . ManagedState
pendingState * state . ManagedState
gasLimit func ( ) * big . Int // The current gas limit function callback
gasLimit func ( ) * big . Int // The current gas limit function callback
minGasPrice * big . Int
eventMux * event . TypeMux
eventMux * event . TypeMux
events event . Subscription
events event . Subscription
@ -57,8 +63,9 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
eventMux : eventMux ,
eventMux : eventMux ,
currentState : currentStateFn ,
currentState : currentStateFn ,
gasLimit : gasLimitFn ,
gasLimit : gasLimitFn ,
minGasPrice : new ( big . Int ) ,
pendingState : state . ManageState ( currentStateFn ( ) ) ,
pendingState : state . ManageState ( currentStateFn ( ) ) ,
events : eventMux . Subscribe ( ChainEvent { } ) ,
events : eventMux . Subscribe ( ChainEvent { } , GasPriceChanged { } ) ,
}
}
go pool . eventLoop ( )
go pool . eventLoop ( )
@ -69,10 +76,15 @@ func (pool *TxPool) eventLoop() {
// Track chain events. When a chain events occurs (new chain canon block)
// Track chain events. When a chain events occurs (new chain canon block)
// we need to know the new state. The new state will help us determine
// we need to know the new state. The new state will help us determine
// the nonces in the managed state
// the nonces in the managed state
for _ = range pool . events . Chan ( ) {
for ev : = range pool . events . Chan ( ) {
pool . mu . Lock ( )
pool . mu . Lock ( )
switch ev := ev . ( type ) {
case ChainEvent :
pool . resetState ( )
pool . resetState ( )
case GasPriceChanged :
pool . minGasPrice = ev . Price
}
pool . mu . Unlock ( )
pool . mu . Unlock ( )
}
}
@ -124,6 +136,11 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
err error
err error
)
)
// Drop transactions under our own minimal accepted gas price
if pool . minGasPrice . Cmp ( tx . GasPrice ( ) ) > 0 {
return ErrCheap
}
// Validate the transaction sender and it's sig. Throw
// Validate the transaction sender and it's sig. Throw
// if the from fields is invalid.
// if the from fields is invalid.
if from , err = tx . From ( ) ; err != nil {
if from , err = tx . From ( ) ; err != nil {
@ -335,7 +352,16 @@ func (pool *TxPool) checkQueue() {
// Find the next consecutive nonce range starting at the
// Find the next consecutive nonce range starting at the
// current account nonce.
// current account nonce.
sort . Sort ( addq )
sort . Sort ( addq )
for _ , e := range addq {
for i , e := range addq {
// start deleting the transactions from the queue if they exceed the limit
if i > maxQueued {
if glog . V ( logger . Debug ) {
glog . Infof ( "Queued tx limit exceeded for %s. Tx %s removed\n" , common . PP ( address [ : ] ) , common . PP ( e . hash [ : ] ) )
}
delete ( pool . queue [ address ] , e . hash )
continue
}
if e . AccountNonce > guessedNonce {
if e . AccountNonce > guessedNonce {
break
break
}
}