core: documented changes in tx pool
This commit is contained in:
parent
cf5ad266f6
commit
dcdb4554d7
@ -62,19 +62,32 @@ func NewTxPool(eventMux *event.TypeMux, currentStateFn stateFn, gasLimitFn func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pool *TxPool) Start() {
|
func (pool *TxPool) Start() {
|
||||||
|
// 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
|
||||||
|
// the nonces in the managed state
|
||||||
pool.events = pool.eventMux.Subscribe(ChainEvent{})
|
pool.events = pool.eventMux.Subscribe(ChainEvent{})
|
||||||
for _ = range pool.events.Chan() {
|
for _ = range pool.events.Chan() {
|
||||||
pool.mu.Lock()
|
pool.mu.Lock()
|
||||||
pool.state = state.ManageState(pool.currentState())
|
pool.state = state.ManageState(pool.currentState())
|
||||||
|
|
||||||
|
// validate the pool of pending transactions, this will remove
|
||||||
|
// any transactions that have been included in the block or
|
||||||
|
// have been invalidated because of another transaction (e.g.
|
||||||
|
// higher gas price)
|
||||||
|
pool.validatePool()
|
||||||
|
|
||||||
|
// Loop over the pending transactions and base the nonce of the new
|
||||||
|
// pending transaction set.
|
||||||
for _, tx := range pool.pending {
|
for _, tx := range pool.pending {
|
||||||
if addr, err := tx.From(); err == nil {
|
if addr, err := tx.From(); err == nil {
|
||||||
if pool.state.GetNonce(addr) < tx.Nonce() {
|
// Set the nonce. Transaction nonce can never be lower
|
||||||
pool.state.SetNonce(addr, tx.Nonce())
|
// than the state nonce; validatePool took care of that.
|
||||||
}
|
pool.state.SetNonce(addr, tx.Nonce())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the queue and move transactions over to the pending if possible
|
||||||
|
// or remove those that have become invalid
|
||||||
pool.checkQueue()
|
pool.checkQueue()
|
||||||
pool.mu.Unlock()
|
pool.mu.Unlock()
|
||||||
}
|
}
|
||||||
@ -103,32 +116,46 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Validate the transaction sender and it's sig. Throw
|
||||||
|
// if the from fields is invalid.
|
||||||
if from, err = tx.From(); err != nil {
|
if from, err = tx.From(); err != nil {
|
||||||
return ErrInvalidSender
|
return ErrInvalidSender
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the account exist. Non existant accounts
|
||||||
|
// haven't got funds and well therefor never pass.
|
||||||
if !pool.currentState().HasAccount(from) {
|
if !pool.currentState().HasAccount(from) {
|
||||||
return ErrNonExistentAccount
|
return ErrNonExistentAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the transaction doesn't exceed the current
|
||||||
|
// block limit gas.
|
||||||
if pool.gasLimit().Cmp(tx.GasLimit) < 0 {
|
if pool.gasLimit().Cmp(tx.GasLimit) < 0 {
|
||||||
return ErrGasLimit
|
return ErrGasLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transactions can't be negative. This may never happen
|
||||||
|
// using RLP decoded transactions but may occur if you create
|
||||||
|
// a transaction using the RPC for example.
|
||||||
if tx.Amount.Cmp(common.Big0) < 0 {
|
if tx.Amount.Cmp(common.Big0) < 0 {
|
||||||
return ErrNegativeValue
|
return ErrNegativeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transactor should have enough funds to cover the costs
|
||||||
|
// cost == V + GP * GL
|
||||||
total := new(big.Int).Mul(tx.Price, tx.GasLimit)
|
total := new(big.Int).Mul(tx.Price, tx.GasLimit)
|
||||||
total.Add(total, tx.Value())
|
total.Add(total, tx.Value())
|
||||||
if pool.currentState().GetBalance(from).Cmp(total) < 0 {
|
if pool.currentState().GetBalance(from).Cmp(total) < 0 {
|
||||||
return ErrInsufficientFunds
|
return ErrInsufficientFunds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should supply enough intrinsic gas
|
||||||
if tx.GasLimit.Cmp(IntrinsicGas(tx)) < 0 {
|
if tx.GasLimit.Cmp(IntrinsicGas(tx)) < 0 {
|
||||||
return ErrIntrinsicGas
|
return ErrIntrinsicGas
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last but not least check for nonce errors (intensive
|
||||||
|
// operation, saved for last)
|
||||||
if pool.currentState().GetNonce(from) > tx.Nonce() {
|
if pool.currentState().GetNonce(from) > tx.Nonce() {
|
||||||
return ErrNonce
|
return ErrNonce
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user