|
|
@ -37,10 +37,9 @@ var ( |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
type Transaction struct { |
|
|
|
type Transaction struct { |
|
|
|
data txdata |
|
|
|
data txdata // Consensus contents of a transaction
|
|
|
|
|
|
|
|
time time.Time // Time first seen locally (spam avoidance)
|
|
|
|
|
|
|
|
|
|
|
|
// Time when the transaction was added to the txPool
|
|
|
|
|
|
|
|
receivedTime *time.Time |
|
|
|
|
|
|
|
// caches
|
|
|
|
// caches
|
|
|
|
hash atomic.Value |
|
|
|
hash atomic.Value |
|
|
|
size atomic.Value |
|
|
|
size atomic.Value |
|
|
@ -104,8 +103,10 @@ func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit |
|
|
|
if gasPrice != nil { |
|
|
|
if gasPrice != nil { |
|
|
|
d.Price.Set(gasPrice) |
|
|
|
d.Price.Set(gasPrice) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return &Transaction{ |
|
|
|
return &Transaction{data: d} |
|
|
|
data: d, |
|
|
|
|
|
|
|
time: time.Now(), |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ChainId returns which chain id this transaction was signed for (if at all)
|
|
|
|
// ChainId returns which chain id this transaction was signed for (if at all)
|
|
|
@ -138,8 +139,8 @@ func (tx *Transaction) DecodeRLP(s *rlp.Stream) error { |
|
|
|
err := s.Decode(&tx.data) |
|
|
|
err := s.Decode(&tx.data) |
|
|
|
if err == nil { |
|
|
|
if err == nil { |
|
|
|
tx.size.Store(common.StorageSize(rlp.ListSize(size))) |
|
|
|
tx.size.Store(common.StorageSize(rlp.ListSize(size))) |
|
|
|
|
|
|
|
tx.time = time.Now() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -157,7 +158,6 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { |
|
|
|
if err := dec.UnmarshalJSON(input); err != nil { |
|
|
|
if err := dec.UnmarshalJSON(input); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
withSignature := dec.V.Sign() != 0 || dec.R.Sign() != 0 || dec.S.Sign() != 0 |
|
|
|
withSignature := dec.V.Sign() != 0 || dec.R.Sign() != 0 || dec.S.Sign() != 0 |
|
|
|
if withSignature { |
|
|
|
if withSignature { |
|
|
|
var V byte |
|
|
|
var V byte |
|
|
@ -171,8 +171,10 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { |
|
|
|
return ErrInvalidSig |
|
|
|
return ErrInvalidSig |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
*tx = Transaction{ |
|
|
|
*tx = Transaction{data: dec} |
|
|
|
data: dec, |
|
|
|
|
|
|
|
time: time.Now(), |
|
|
|
|
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -188,13 +190,6 @@ func (tx *Transaction) GasPriceIntCmp(other *big.Int) int { |
|
|
|
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) } |
|
|
|
func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) } |
|
|
|
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce } |
|
|
|
func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce } |
|
|
|
func (tx *Transaction) CheckNonce() bool { return true } |
|
|
|
func (tx *Transaction) CheckNonce() bool { return true } |
|
|
|
func (tx *Transaction) ReceivedTime() (time.Time, bool) { |
|
|
|
|
|
|
|
if tx.receivedTime == nil { |
|
|
|
|
|
|
|
return time.Time{}, false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return *tx.receivedTime, true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// To returns the recipient address of the transaction.
|
|
|
|
// To returns the recipient address of the transaction.
|
|
|
|
// It returns nil if the transaction is a contract creation.
|
|
|
|
// It returns nil if the transaction is a contract creation.
|
|
|
@ -257,7 +252,10 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
cpy := &Transaction{data: tx.data, receivedTime: tx.receivedTime} |
|
|
|
cpy := &Transaction{ |
|
|
|
|
|
|
|
data: tx.data, |
|
|
|
|
|
|
|
time: tx.time, |
|
|
|
|
|
|
|
} |
|
|
|
cpy.data.R, cpy.data.S, cpy.data.V = r, s, v |
|
|
|
cpy.data.R, cpy.data.S, cpy.data.V = r, s, v |
|
|
|
return cpy, nil |
|
|
|
return cpy, nil |
|
|
|
} |
|
|
|
} |
|
|
@ -275,11 +273,6 @@ func (tx *Transaction) RawSignatureValues() (v, r, s *big.Int) { |
|
|
|
return tx.data.V, tx.data.R, tx.data.S |
|
|
|
return tx.data.V, tx.data.R, tx.data.S |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// SetReceivedTime sets the time that this transaction was received at.
|
|
|
|
|
|
|
|
func (tx *Transaction) SetReceivedTime(time time.Time) { |
|
|
|
|
|
|
|
tx.receivedTime = &time |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Transactions is a Transaction slice type for basic sorting.
|
|
|
|
// Transactions is a Transaction slice type for basic sorting.
|
|
|
|
type Transactions []*Transaction |
|
|
|
type Transactions []*Transaction |
|
|
|
|
|
|
|
|
|
|
@ -322,35 +315,27 @@ func (s TxByNonce) Len() int { return len(s) } |
|
|
|
func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce } |
|
|
|
func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce } |
|
|
|
func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
|
|
|
func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
|
|
|
|
|
|
|
|
|
|
|
// TxByPriceAndReceiveTime implements both the sort and the heap interface, making it useful
|
|
|
|
// TxByPriceAndTime implements both the sort and the heap interface, making it useful
|
|
|
|
// for all at once sorting as well as individually adding and removing elements.
|
|
|
|
// for all at once sorting as well as individually adding and removing elements.
|
|
|
|
type TxByPriceAndReceiveTime Transactions |
|
|
|
type TxByPriceAndTime Transactions |
|
|
|
|
|
|
|
|
|
|
|
func (s TxByPriceAndReceiveTime) Len() int { return len(s) } |
|
|
|
func (s TxByPriceAndTime) Len() int { return len(s) } |
|
|
|
func (s TxByPriceAndReceiveTime) Less(i, j int) bool { |
|
|
|
func (s TxByPriceAndTime) Less(i, j int) bool { |
|
|
|
// If the price is equal, use the time the tx was received for deterministic sorting
|
|
|
|
// If the prices are equal, use the time the transaction was first seen for
|
|
|
|
if s[i].data.Price.Cmp(s[j].data.Price) == 0 { |
|
|
|
// deterministic sorting
|
|
|
|
recvI, ok := s[i].ReceivedTime() |
|
|
|
cmp := s[i].data.Price.Cmp(s[j].data.Price) |
|
|
|
if !ok { |
|
|
|
if cmp == 0 { |
|
|
|
return true |
|
|
|
return s[i].time.Before(s[j].time) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
recvJ, ok := s[j].ReceivedTime() |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return recvI.UnixNano() < recvJ.UnixNano() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return cmp > 0 |
|
|
|
return s[i].data.Price.Cmp(s[j].data.Price) > 0 |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
func (s TxByPriceAndReceiveTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
|
|
|
func (s TxByPriceAndTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
|
|
|
|
|
|
|
|
|
|
|
func (s *TxByPriceAndReceiveTime) Push(x interface{}) { |
|
|
|
func (s *TxByPriceAndTime) Push(x interface{}) { |
|
|
|
*s = append(*s, x.(*Transaction)) |
|
|
|
*s = append(*s, x.(*Transaction)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *TxByPriceAndReceiveTime) Pop() interface{} { |
|
|
|
func (s *TxByPriceAndTime) Pop() interface{} { |
|
|
|
old := *s |
|
|
|
old := *s |
|
|
|
n := len(old) |
|
|
|
n := len(old) |
|
|
|
x := old[n-1] |
|
|
|
x := old[n-1] |
|
|
@ -363,7 +348,7 @@ func (s *TxByPriceAndReceiveTime) Pop() interface{} { |
|
|
|
// entire batches of transactions for non-executable accounts.
|
|
|
|
// entire batches of transactions for non-executable accounts.
|
|
|
|
type TransactionsByPriceAndNonce struct { |
|
|
|
type TransactionsByPriceAndNonce struct { |
|
|
|
txs map[common.Address]Transactions // Per account nonce-sorted list of transactions
|
|
|
|
txs map[common.Address]Transactions // Per account nonce-sorted list of transactions
|
|
|
|
heads TxByPriceAndReceiveTime // Next transaction for each unique account (price heap)
|
|
|
|
heads TxByPriceAndTime // Next transaction for each unique account (price heap)
|
|
|
|
signer Signer // Signer for the set of transactions
|
|
|
|
signer Signer // Signer for the set of transactions
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -374,7 +359,7 @@ type TransactionsByPriceAndNonce struct { |
|
|
|
// if after providing it to the constructor.
|
|
|
|
// if after providing it to the constructor.
|
|
|
|
func NewTransactionsByPriceAndNonce(signer Signer, txs map[common.Address]Transactions) *TransactionsByPriceAndNonce { |
|
|
|
func NewTransactionsByPriceAndNonce(signer Signer, txs map[common.Address]Transactions) *TransactionsByPriceAndNonce { |
|
|
|
// Initialize a price and received time based heap with the head transactions
|
|
|
|
// Initialize a price and received time based heap with the head transactions
|
|
|
|
heads := make(TxByPriceAndReceiveTime, 0, len(txs)) |
|
|
|
heads := make(TxByPriceAndTime, 0, len(txs)) |
|
|
|
for from, accTxs := range txs { |
|
|
|
for from, accTxs := range txs { |
|
|
|
heads = append(heads, accTxs[0]) |
|
|
|
heads = append(heads, accTxs[0]) |
|
|
|
// Ensure the sender address is from the signer
|
|
|
|
// Ensure the sender address is from the signer
|
|
|
|