@@ -130,6 +130,8 @@ struct TransactionOrder {
130
130
/// (e.g. Tx(nonce:5), State(nonce:0) -> height: 5)
131
131
/// High nonce_height = Low priority (processed later)
132
132
nonce_height : U256 ,
133
+ /// Gas specified in the transaction.
134
+ gas : U256 ,
133
135
/// Gas Price of the transaction.
134
136
/// Low gas price = Low priority (processed later)
135
137
gas_price : U256 ,
@@ -146,6 +148,7 @@ impl TransactionOrder {
146
148
fn for_transaction ( tx : & VerifiedTransaction , base_nonce : U256 ) -> Self {
147
149
TransactionOrder {
148
150
nonce_height : tx. nonce ( ) - base_nonce,
151
+ gas : tx. transaction . gas . clone ( ) ,
149
152
gas_price : tx. transaction . gas_price ,
150
153
hash : tx. hash ( ) ,
151
154
origin : tx. origin ,
@@ -287,6 +290,7 @@ struct TransactionSet {
287
290
by_address : Table < Address , U256 , TransactionOrder > ,
288
291
by_gas_price : GasPriceQueue ,
289
292
limit : usize ,
293
+ gas_limit : U256 ,
290
294
}
291
295
292
296
impl TransactionSet {
@@ -317,15 +321,18 @@ impl TransactionSet {
317
321
/// It drops transactions from this set but also removes associated `VerifiedTransaction`.
318
322
/// Returns addresses and lowest nonces of transactions removed because of limit.
319
323
fn enforce_limit ( & mut self , by_hash : & mut HashMap < H256 , VerifiedTransaction > ) -> Option < HashMap < Address , U256 > > {
320
- let len = self . by_priority . len ( ) ;
321
- if len <= self . limit {
322
- return None ;
323
- }
324
-
324
+ let mut count = 0 ;
325
+ let mut gas: U256 = 0 . into ( ) ;
325
326
let to_drop : Vec < ( Address , U256 ) > = {
326
327
self . by_priority
327
328
. iter ( )
328
- . skip ( self . limit )
329
+ . skip_while ( |order| {
330
+ count = count + 1 ;
331
+ let r = gas. overflowing_add ( order. gas ) ;
332
+ if r. 1 { return false }
333
+ gas = r. 0 ;
334
+ count <= self . limit && gas <= self . gas_limit
335
+ } )
329
336
. map ( |order| by_hash. get ( & order. hash )
330
337
. expect ( "All transactions in `self.by_priority` and `self.by_address` are kept in sync with `by_hash`." ) )
331
338
. map ( |tx| ( tx. sender ( ) , tx. nonce ( ) ) )
@@ -432,23 +439,25 @@ impl Default for TransactionQueue {
432
439
impl TransactionQueue {
433
440
/// Creates new instance of this Queue
434
441
pub fn new ( ) -> Self {
435
- Self :: with_limits ( 1024 , !U256 :: zero ( ) )
442
+ Self :: with_limits ( 1024 , !U256 :: zero ( ) , ! U256 :: zero ( ) )
436
443
}
437
444
438
445
/// Create new instance of this Queue with specified limits
439
- pub fn with_limits ( limit : usize , tx_gas_limit : U256 ) -> Self {
446
+ pub fn with_limits ( limit : usize , gas_limit : U256 , tx_gas_limit : U256 ) -> Self {
440
447
let current = TransactionSet {
441
448
by_priority : BTreeSet :: new ( ) ,
442
449
by_address : Table :: new ( ) ,
443
450
by_gas_price : Default :: default ( ) ,
444
451
limit : limit,
452
+ gas_limit : gas_limit,
445
453
} ;
446
454
447
455
let future = TransactionSet {
448
456
by_priority : BTreeSet :: new ( ) ,
449
457
by_address : Table :: new ( ) ,
450
458
by_gas_price : Default :: default ( ) ,
451
459
limit : limit,
460
+ gas_limit : gas_limit,
452
461
} ;
453
462
454
463
TransactionQueue {
@@ -504,6 +513,13 @@ impl TransactionQueue {
504
513
} ;
505
514
}
506
515
516
+ /// Sets new total gas limit.
517
+ pub fn set_total_gas_limit ( & mut self , gas_limit : U256 ) {
518
+ self . future . gas_limit = gas_limit;
519
+ self . current . gas_limit = gas_limit;
520
+ self . future . enforce_limit ( & mut self . by_hash ) ;
521
+ }
522
+
507
523
/// Set the new limit for the amount of gas any individual transaction may have.
508
524
/// Any transaction already imported to the queue is not affected.
509
525
pub fn set_tx_gas_limit ( & mut self , limit : U256 ) {
@@ -827,6 +843,16 @@ impl TransactionQueue {
827
843
let nonce = tx. nonce ( ) ;
828
844
let hash = tx. hash ( ) ;
829
845
846
+ {
847
+ // Rough size sanity check
848
+ let gas = & tx. transaction . gas ;
849
+ if U256 :: from ( tx. transaction . data . len ( ) ) > * gas {
850
+ // Droping transaction
851
+ trace ! ( target: "txqueue" , "Dropping oversized transaction: {:?} (gas: {} < size {})" , hash, gas, tx. transaction. data. len( ) ) ;
852
+ return Err ( TransactionError :: LimitReached ) ;
853
+ }
854
+ }
855
+
830
856
// The transaction might be old, let's check that.
831
857
// This has to be the first test, otherwise calculating
832
858
// nonce height would result in overflow.
@@ -979,14 +1005,15 @@ mod test {
979
1005
}
980
1006
981
1007
fn default_nonce ( ) -> U256 { 123 . into ( ) }
1008
+ fn default_gas_val ( ) -> U256 { 100_000 . into ( ) }
982
1009
fn default_gas_price ( ) -> U256 { 1 . into ( ) }
983
1010
984
1011
fn new_unsigned_tx ( nonce : U256 , gas_price : U256 ) -> Transaction {
985
1012
Transaction {
986
1013
action : Action :: Create ,
987
1014
value : U256 :: from ( 100 ) ,
988
1015
data : "3331600055" . from_hex ( ) . unwrap ( ) ,
989
- gas : U256 :: from ( 100_000 ) ,
1016
+ gas : default_gas_val ( ) ,
990
1017
gas_price : gas_price,
991
1018
nonce : nonce
992
1019
}
@@ -1051,7 +1078,7 @@ mod test {
1051
1078
#[ test]
1052
1079
fn should_return_correct_nonces_when_dropped_because_of_limit ( ) {
1053
1080
// given
1054
- let mut txq = TransactionQueue :: with_limits ( 2 , !U256 :: zero ( ) ) ;
1081
+ let mut txq = TransactionQueue :: with_limits ( 2 , !U256 :: zero ( ) , ! U256 :: zero ( ) ) ;
1055
1082
let ( tx1, tx2) = new_tx_pair ( 123 . into ( ) , 1 . into ( ) , 1 . into ( ) , 0 . into ( ) ) ;
1056
1083
let sender = tx1. sender ( ) . unwrap ( ) ;
1057
1084
let nonce = tx1. nonce ;
@@ -1089,7 +1116,8 @@ mod test {
1089
1116
by_priority : BTreeSet :: new ( ) ,
1090
1117
by_address : Table :: new ( ) ,
1091
1118
by_gas_price : Default :: default ( ) ,
1092
- limit : 1
1119
+ limit : 1 ,
1120
+ gas_limit : !U256 :: zero ( ) ,
1093
1121
} ;
1094
1122
let ( tx1, tx2) = new_tx_pair_default ( 1 . into ( ) , 0 . into ( ) ) ;
1095
1123
let tx1 = VerifiedTransaction :: new ( tx1, TransactionOrigin :: External ) . unwrap ( ) ;
@@ -1129,7 +1157,8 @@ mod test {
1129
1157
by_priority : BTreeSet :: new ( ) ,
1130
1158
by_address : Table :: new ( ) ,
1131
1159
by_gas_price : Default :: default ( ) ,
1132
- limit : 1
1160
+ limit : 1 ,
1161
+ gas_limit : !U256 :: zero ( ) ,
1133
1162
} ;
1134
1163
// Create two transactions with same nonce
1135
1164
// (same hash)
@@ -1177,7 +1206,8 @@ mod test {
1177
1206
by_priority : BTreeSet :: new ( ) ,
1178
1207
by_address : Table :: new ( ) ,
1179
1208
by_gas_price : Default :: default ( ) ,
1180
- limit : 2
1209
+ limit : 2 ,
1210
+ gas_limit : !U256 :: zero ( ) ,
1181
1211
} ;
1182
1212
let tx = new_tx_default ( ) ;
1183
1213
let tx1 = VerifiedTransaction :: new ( tx. clone ( ) , TransactionOrigin :: External ) . unwrap ( ) ;
@@ -1194,7 +1224,8 @@ mod test {
1194
1224
by_priority : BTreeSet :: new ( ) ,
1195
1225
by_address : Table :: new ( ) ,
1196
1226
by_gas_price : Default :: default ( ) ,
1197
- limit : 1
1227
+ limit : 1 ,
1228
+ gas_limit : !U256 :: zero ( ) ,
1198
1229
} ;
1199
1230
1200
1231
assert_eq ! ( set. gas_price_entry_limit( ) , 0 . into( ) ) ;
@@ -1690,7 +1721,7 @@ mod test {
1690
1721
#[ test]
1691
1722
fn should_drop_old_transactions_when_hitting_the_limit ( ) {
1692
1723
// given
1693
- let mut txq = TransactionQueue :: with_limits ( 1 , !U256 :: zero ( ) ) ;
1724
+ let mut txq = TransactionQueue :: with_limits ( 1 , !U256 :: zero ( ) , ! U256 :: zero ( ) ) ;
1694
1725
let ( tx, tx2) = new_tx_pair_default ( 1 . into ( ) , 0 . into ( ) ) ;
1695
1726
let sender = tx. sender ( ) . unwrap ( ) ;
1696
1727
let nonce = tx. nonce ;
@@ -1711,7 +1742,7 @@ mod test {
1711
1742
1712
1743
#[ test]
1713
1744
fn should_limit_future_transactions ( ) {
1714
- let mut txq = TransactionQueue :: with_limits ( 1 , !U256 :: zero ( ) ) ;
1745
+ let mut txq = TransactionQueue :: with_limits ( 1 , !U256 :: zero ( ) , ! U256 :: zero ( ) ) ;
1715
1746
txq. current . set_limit ( 10 ) ;
1716
1747
let ( tx1, tx2) = new_tx_pair_default ( 4 . into ( ) , 1 . into ( ) ) ;
1717
1748
let ( tx3, tx4) = new_tx_pair_default ( 4 . into ( ) , 2 . into ( ) ) ;
@@ -1728,6 +1759,16 @@ mod test {
1728
1759
assert_eq ! ( txq. status( ) . future, 1 ) ;
1729
1760
}
1730
1761
1762
+ #[ test]
1763
+ fn should_limit_by_gas ( ) {
1764
+ let mut txq = TransactionQueue :: with_limits ( 100 , default_gas_val ( ) * U256 :: from ( 2 ) , !U256 :: zero ( ) ) ;
1765
+ let ( tx1, _) = new_tx_pair_default ( U256 :: from ( 4 ) , U256 :: from ( 1 ) ) ;
1766
+ let ( tx3, _) = new_tx_pair_default ( U256 :: from ( 4 ) , U256 :: from ( 2 ) ) ;
1767
+ txq. add ( tx1. clone ( ) , & default_account_details, TransactionOrigin :: External ) . unwrap ( ) ;
1768
+ txq. add ( tx3. clone ( ) , & default_account_details, TransactionOrigin :: External ) . unwrap ( ) ;
1769
+ assert_eq ! ( txq. status( ) . pending, 2 ) ;
1770
+ }
1771
+
1731
1772
#[ test]
1732
1773
fn should_drop_transactions_with_old_nonces ( ) {
1733
1774
let mut txq = TransactionQueue :: new ( ) ;
@@ -1971,7 +2012,7 @@ mod test {
1971
2012
#[ test]
1972
2013
fn should_keep_right_order_in_future ( ) {
1973
2014
// given
1974
- let mut txq = TransactionQueue :: with_limits ( 1 , !U256 :: zero ( ) ) ;
2015
+ let mut txq = TransactionQueue :: with_limits ( 1 , !U256 :: zero ( ) , ! U256 :: zero ( ) ) ;
1975
2016
let ( tx1, tx2) = new_tx_pair_default ( 1 . into ( ) , 0 . into ( ) ) ;
1976
2017
let prev_nonce = |a : & Address | AccountDetails { nonce : default_account_details ( a) . nonce - U256 :: one ( ) , balance :
1977
2018
default_account_details ( a) . balance } ;
0 commit comments