|
|
@ -390,81 +390,81 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error |
|
|
|
|
|
|
|
|
|
|
|
// add validates a new transaction and sets its state pending if processable.
|
|
|
|
// add validates a new transaction and sets its state pending if processable.
|
|
|
|
// It also updates the locally stored nonce if necessary.
|
|
|
|
// It also updates the locally stored nonce if necessary.
|
|
|
|
func (self *TxPool) add(ctx context.Context, tx *types.Transaction) error { |
|
|
|
func (pool *TxPool) add(ctx context.Context, tx *types.Transaction) error { |
|
|
|
hash := tx.Hash() |
|
|
|
hash := tx.Hash() |
|
|
|
|
|
|
|
|
|
|
|
if self.pending[hash] != nil { |
|
|
|
if pool.pending[hash] != nil { |
|
|
|
return fmt.Errorf("Known transaction (%x)", hash[:4]) |
|
|
|
return fmt.Errorf("Known transaction (%x)", hash[:4]) |
|
|
|
} |
|
|
|
} |
|
|
|
err := self.validateTx(ctx, tx) |
|
|
|
err := pool.validateTx(ctx, tx) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if _, ok := self.pending[hash]; !ok { |
|
|
|
if _, ok := pool.pending[hash]; !ok { |
|
|
|
self.pending[hash] = tx |
|
|
|
pool.pending[hash] = tx |
|
|
|
|
|
|
|
|
|
|
|
nonce := tx.Nonce() + 1 |
|
|
|
nonce := tx.Nonce() + 1 |
|
|
|
|
|
|
|
|
|
|
|
addr, _ := types.Sender(self.signer, tx) |
|
|
|
addr, _ := types.Sender(pool.signer, tx) |
|
|
|
if nonce > self.nonce[addr] { |
|
|
|
if nonce > pool.nonce[addr] { |
|
|
|
self.nonce[addr] = nonce |
|
|
|
pool.nonce[addr] = nonce |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Notify the subscribers. This event is posted in a goroutine
|
|
|
|
// Notify the subscribers. This event is posted in a goroutine
|
|
|
|
// because it's possible that somewhere during the post "Remove transaction"
|
|
|
|
// because it's possible that somewhere during the post "Remove transaction"
|
|
|
|
// gets called which will then wait for the global tx pool lock and deadlock.
|
|
|
|
// gets called which will then wait for the global tx pool lock and deadlock.
|
|
|
|
go self.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}}) |
|
|
|
go pool.txFeed.Send(core.NewTxsEvent{Txs: types.Transactions{tx}}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Print a log message if low enough level is set
|
|
|
|
// Print a log message if low enough level is set
|
|
|
|
log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(self.signer, tx); return from }}, "to", tx.To()) |
|
|
|
log.Debug("Pooled new transaction", "hash", hash, "from", log.Lazy{Fn: func() common.Address { from, _ := types.Sender(pool.signer, tx); return from }}, "to", tx.To()) |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Add adds a transaction to the pool if valid and passes it to the tx relay
|
|
|
|
// Add adds a transaction to the pool if valid and passes it to the tx relay
|
|
|
|
// backend
|
|
|
|
// backend
|
|
|
|
func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error { |
|
|
|
func (pool *TxPool) Add(ctx context.Context, tx *types.Transaction) error { |
|
|
|
self.mu.Lock() |
|
|
|
pool.mu.Lock() |
|
|
|
defer self.mu.Unlock() |
|
|
|
defer pool.mu.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
data, err := rlp.EncodeToBytes(tx) |
|
|
|
data, err := rlp.EncodeToBytes(tx) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if err := self.add(ctx, tx); err != nil { |
|
|
|
if err := pool.add(ctx, tx); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
//fmt.Println("Send", tx.Hash())
|
|
|
|
//fmt.Println("Send", tx.Hash())
|
|
|
|
self.relay.Send(types.Transactions{tx}) |
|
|
|
pool.relay.Send(types.Transactions{tx}) |
|
|
|
|
|
|
|
|
|
|
|
self.chainDb.Put(tx.Hash().Bytes(), data) |
|
|
|
pool.chainDb.Put(tx.Hash().Bytes(), data) |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// AddTransactions adds all valid transactions to the pool and passes them to
|
|
|
|
// AddTransactions adds all valid transactions to the pool and passes them to
|
|
|
|
// the tx relay backend
|
|
|
|
// the tx relay backend
|
|
|
|
func (self *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) { |
|
|
|
func (pool *TxPool) AddBatch(ctx context.Context, txs []*types.Transaction) { |
|
|
|
self.mu.Lock() |
|
|
|
pool.mu.Lock() |
|
|
|
defer self.mu.Unlock() |
|
|
|
defer pool.mu.Unlock() |
|
|
|
var sendTx types.Transactions |
|
|
|
var sendTx types.Transactions |
|
|
|
|
|
|
|
|
|
|
|
for _, tx := range txs { |
|
|
|
for _, tx := range txs { |
|
|
|
if err := self.add(ctx, tx); err == nil { |
|
|
|
if err := pool.add(ctx, tx); err == nil { |
|
|
|
sendTx = append(sendTx, tx) |
|
|
|
sendTx = append(sendTx, tx) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if len(sendTx) > 0 { |
|
|
|
if len(sendTx) > 0 { |
|
|
|
self.relay.Send(sendTx) |
|
|
|
pool.relay.Send(sendTx) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// GetTransaction returns a transaction if it is contained in the pool
|
|
|
|
// GetTransaction returns a transaction if it is contained in the pool
|
|
|
|
// and nil otherwise.
|
|
|
|
// and nil otherwise.
|
|
|
|
func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { |
|
|
|
func (pool *TxPool) GetTransaction(hash common.Hash) *types.Transaction { |
|
|
|
// check the txs first
|
|
|
|
// check the txs first
|
|
|
|
if tx, ok := tp.pending[hash]; ok { |
|
|
|
if tx, ok := pool.pending[hash]; ok { |
|
|
|
return tx |
|
|
|
return tx |
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
@ -472,13 +472,13 @@ func (tp *TxPool) GetTransaction(hash common.Hash) *types.Transaction { |
|
|
|
|
|
|
|
|
|
|
|
// GetTransactions returns all currently processable transactions.
|
|
|
|
// GetTransactions returns all currently processable transactions.
|
|
|
|
// The returned slice may be modified by the caller.
|
|
|
|
// The returned slice may be modified by the caller.
|
|
|
|
func (self *TxPool) GetTransactions() (txs types.Transactions, err error) { |
|
|
|
func (pool *TxPool) GetTransactions() (txs types.Transactions, err error) { |
|
|
|
self.mu.RLock() |
|
|
|
pool.mu.RLock() |
|
|
|
defer self.mu.RUnlock() |
|
|
|
defer pool.mu.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
txs = make(types.Transactions, len(self.pending)) |
|
|
|
txs = make(types.Transactions, len(pool.pending)) |
|
|
|
i := 0 |
|
|
|
i := 0 |
|
|
|
for _, tx := range self.pending { |
|
|
|
for _, tx := range pool.pending { |
|
|
|
txs[i] = tx |
|
|
|
txs[i] = tx |
|
|
|
i++ |
|
|
|
i++ |
|
|
|
} |
|
|
|
} |
|
|
@ -487,14 +487,14 @@ func (self *TxPool) GetTransactions() (txs types.Transactions, err error) { |
|
|
|
|
|
|
|
|
|
|
|
// Content retrieves the data content of the transaction pool, returning all the
|
|
|
|
// Content retrieves the data content of the transaction pool, returning all the
|
|
|
|
// pending as well as queued transactions, grouped by account and nonce.
|
|
|
|
// pending as well as queued transactions, grouped by account and nonce.
|
|
|
|
func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { |
|
|
|
func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { |
|
|
|
self.mu.RLock() |
|
|
|
pool.mu.RLock() |
|
|
|
defer self.mu.RUnlock() |
|
|
|
defer pool.mu.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
// Retrieve all the pending transactions and sort by account and by nonce
|
|
|
|
// Retrieve all the pending transactions and sort by account and by nonce
|
|
|
|
pending := make(map[common.Address]types.Transactions) |
|
|
|
pending := make(map[common.Address]types.Transactions) |
|
|
|
for _, tx := range self.pending { |
|
|
|
for _, tx := range pool.pending { |
|
|
|
account, _ := types.Sender(self.signer, tx) |
|
|
|
account, _ := types.Sender(pool.signer, tx) |
|
|
|
pending[account] = append(pending[account], tx) |
|
|
|
pending[account] = append(pending[account], tx) |
|
|
|
} |
|
|
|
} |
|
|
|
// There are no queued transactions in a light pool, just return an empty map
|
|
|
|
// There are no queued transactions in a light pool, just return an empty map
|
|
|
@ -503,20 +503,20 @@ func (self *TxPool) Content() (map[common.Address]types.Transactions, map[common |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// RemoveTransactions removes all given transactions from the pool.
|
|
|
|
// RemoveTransactions removes all given transactions from the pool.
|
|
|
|
func (self *TxPool) RemoveTransactions(txs types.Transactions) { |
|
|
|
func (pool *TxPool) RemoveTransactions(txs types.Transactions) { |
|
|
|
self.mu.Lock() |
|
|
|
pool.mu.Lock() |
|
|
|
defer self.mu.Unlock() |
|
|
|
defer pool.mu.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
var hashes []common.Hash |
|
|
|
var hashes []common.Hash |
|
|
|
batch := self.chainDb.NewBatch() |
|
|
|
batch := pool.chainDb.NewBatch() |
|
|
|
for _, tx := range txs { |
|
|
|
for _, tx := range txs { |
|
|
|
hash := tx.Hash() |
|
|
|
hash := tx.Hash() |
|
|
|
delete(self.pending, hash) |
|
|
|
delete(pool.pending, hash) |
|
|
|
batch.Delete(hash.Bytes()) |
|
|
|
batch.Delete(hash.Bytes()) |
|
|
|
hashes = append(hashes, hash) |
|
|
|
hashes = append(hashes, hash) |
|
|
|
} |
|
|
|
} |
|
|
|
batch.Write() |
|
|
|
batch.Write() |
|
|
|
self.relay.Discard(hashes) |
|
|
|
pool.relay.Discard(hashes) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// RemoveTx removes the transaction with the given hash from the pool.
|
|
|
|
// RemoveTx removes the transaction with the given hash from the pool.
|
|
|
|