Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
71814bf6
Commit
71814bf6
authored
May 30, 2017
by
Péter Szilágyi
Committed by
GitHub
May 30, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14547 from karalabe/txpool-gas-decrease
core: check for gas limit exceeding txs too on new block
parents
b0f30b0b
280609c9
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
72 additions
and
31 deletions
+72
-31
tx_list.go
core/tx_list.go
+24
-16
tx_pool.go
core/tx_pool.go
+8
-4
tx_pool_test.go
core/tx_pool_test.go
+40
-11
No files found.
core/tx_list.go
View file @
71814bf6
...
...
@@ -220,9 +220,11 @@ func (m *txSortedMap) Flatten() types.Transactions {
// the executable/pending queue; and for storing gapped transactions for the non-
// executable/future queue, with minor behavioral changes.
type
txList
struct
{
strict
bool
// Whether nonces are strictly continuous or not
txs
*
txSortedMap
// Heap indexed sorted hash map of the transactions
costcap
*
big
.
Int
// Price of the highest costing transaction (reset only if exceeds balance)
strict
bool
// Whether nonces are strictly continuous or not
txs
*
txSortedMap
// Heap indexed sorted hash map of the transactions
costcap
*
big
.
Int
// Price of the highest costing transaction (reset only if exceeds balance)
gascap
*
big
.
Int
// Gas limit of the highest spending transaction (reset only if exceeds block limit)
}
// newTxList create a new transaction list for maintaining nonce-indexable fast,
...
...
@@ -232,6 +234,7 @@ func newTxList(strict bool) *txList {
strict
:
strict
,
txs
:
newTxSortedMap
(),
costcap
:
new
(
big
.
Int
),
gascap
:
new
(
big
.
Int
),
}
}
...
...
@@ -244,8 +247,8 @@ func (l *txList) Overlaps(tx *types.Transaction) bool {
// Add tries to insert a new transaction into the list, returning whether the
// transaction was accepted, and if yes, any previous transaction it replaced.
//
// If the new transaction is accepted into the list, the lists' cost
threshold
//
is
also potentially updated.
// If the new transaction is accepted into the list, the lists' cost
and gas
//
thresholds are
also potentially updated.
func
(
l
*
txList
)
Add
(
tx
*
types
.
Transaction
,
priceBump
uint64
)
(
bool
,
*
types
.
Transaction
)
{
// If there's an older better transaction, abort
old
:=
l
.
txs
.
Get
(
tx
.
Nonce
())
...
...
@@ -260,6 +263,9 @@ func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Tran
if
cost
:=
tx
.
Cost
();
l
.
costcap
.
Cmp
(
cost
)
<
0
{
l
.
costcap
=
cost
}
if
gas
:=
tx
.
Gas
();
l
.
gascap
.
Cmp
(
gas
)
<
0
{
l
.
gascap
=
gas
}
return
true
,
old
}
...
...
@@ -270,23 +276,25 @@ func (l *txList) Forward(threshold uint64) types.Transactions {
return
l
.
txs
.
Forward
(
threshold
)
}
// Filter removes all transactions from the list with a cost higher than the
// provided threshold. Every removed transaction is returned for any post-removal
// maintenance. Strict-mode invalidated transactions are also returned.
// Filter removes all transactions from the list with a cost or gas limit higher
// than the provided thresholds. Every removed transaction is returned for any
// post-removal maintenance. Strict-mode invalidated transactions are also
// returned.
//
// This method uses the cached costcap
to quickly decide if there's even a point
//
in calculating all the costs or if the balance covers all. If the threshold is
//
lower than the costcap, the costcap
will be reset to a new high after removing
//
expensive the too
transactions.
func
(
l
*
txList
)
Filter
(
threshold
*
big
.
Int
)
(
types
.
Transactions
,
types
.
Transactions
)
{
// This method uses the cached costcap
and gascap to quickly decide if there's even
//
a point in calculating all the costs or if the balance covers all. If the threshold
//
is lower than the costgas cap, the caps
will be reset to a new high after removing
//
the newly invalidated
transactions.
func
(
l
*
txList
)
Filter
(
costLimit
,
gasLimit
*
big
.
Int
)
(
types
.
Transactions
,
types
.
Transactions
)
{
// If all transactions are below the threshold, short circuit
if
l
.
costcap
.
Cmp
(
threshold
)
<=
0
{
if
l
.
costcap
.
Cmp
(
costLimit
)
<=
0
&&
l
.
gascap
.
Cmp
(
gasLimit
)
<=
0
{
return
nil
,
nil
}
l
.
costcap
=
new
(
big
.
Int
)
.
Set
(
threshold
)
// Lower the cap to the threshold
l
.
costcap
=
new
(
big
.
Int
)
.
Set
(
costLimit
)
// Lower the caps to the thresholds
l
.
gascap
=
new
(
big
.
Int
)
.
Set
(
gasLimit
)
// Filter out all the transactions above the account's funds
removed
:=
l
.
txs
.
Filter
(
func
(
tx
*
types
.
Transaction
)
bool
{
return
tx
.
Cost
()
.
Cmp
(
threshold
)
>
0
})
removed
:=
l
.
txs
.
Filter
(
func
(
tx
*
types
.
Transaction
)
bool
{
return
tx
.
Cost
()
.
Cmp
(
costLimit
)
>
0
||
tx
.
Gas
()
.
Cmp
(
gasLimit
)
>
0
})
// If the list was strict, filter anything above the lowest nonce
var
invalids
types
.
Transactions
...
...
core/tx_pool.go
View file @
71814bf6
...
...
@@ -663,6 +663,8 @@ func (pool *TxPool) removeTx(hash common.Hash) {
// future queue to the set of pending transactions. During this process, all
// invalidated transactions (low nonce, low balance) are deleted.
func
(
pool
*
TxPool
)
promoteExecutables
(
state
*
state
.
StateDB
)
{
gaslimit
:=
pool
.
gasLimit
()
// Iterate over all accounts and promote any executable transactions
queued
:=
uint64
(
0
)
for
addr
,
list
:=
range
pool
.
queue
{
...
...
@@ -673,8 +675,8 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB) {
delete
(
pool
.
all
,
hash
)
pool
.
priced
.
Removed
()
}
// Drop all transactions that are too costly (low balance)
drops
,
_
:=
list
.
Filter
(
state
.
GetBalance
(
addr
))
// Drop all transactions that are too costly (low balance
or out of gas
)
drops
,
_
:=
list
.
Filter
(
state
.
GetBalance
(
addr
)
,
gaslimit
)
for
_
,
tx
:=
range
drops
{
hash
:=
tx
.
Hash
()
log
.
Trace
(
"Removed unpayable queued transaction"
,
"hash"
,
hash
)
...
...
@@ -798,6 +800,8 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB) {
// executable/pending queue and any subsequent transactions that become unexecutable
// are moved back into the future queue.
func
(
pool
*
TxPool
)
demoteUnexecutables
(
state
*
state
.
StateDB
)
{
gaslimit
:=
pool
.
gasLimit
()
// Iterate over all accounts and demote any non-executable transactions
for
addr
,
list
:=
range
pool
.
pending
{
nonce
:=
state
.
GetNonce
(
addr
)
...
...
@@ -809,8 +813,8 @@ func (pool *TxPool) demoteUnexecutables(state *state.StateDB) {
delete
(
pool
.
all
,
hash
)
pool
.
priced
.
Removed
()
}
// Drop all transactions that are too costly (low balance), and queue any invalids back for later
drops
,
invalids
:=
list
.
Filter
(
state
.
GetBalance
(
addr
))
// Drop all transactions that are too costly (low balance
or out of gas
), and queue any invalids back for later
drops
,
invalids
:=
list
.
Filter
(
state
.
GetBalance
(
addr
)
,
gaslimit
)
for
_
,
tx
:=
range
drops
{
hash
:=
tx
.
Hash
()
log
.
Trace
(
"Removed unpayable pending transaction"
,
"hash"
,
hash
)
...
...
core/tx_pool_test.go
View file @
71814bf6
...
...
@@ -397,50 +397,79 @@ func TestTransactionDropping(t *testing.T) {
var
(
tx0
=
transaction
(
0
,
big
.
NewInt
(
100
),
key
)
tx1
=
transaction
(
1
,
big
.
NewInt
(
200
),
key
)
tx2
=
transaction
(
2
,
big
.
NewInt
(
300
),
key
)
tx10
=
transaction
(
10
,
big
.
NewInt
(
100
),
key
)
tx11
=
transaction
(
11
,
big
.
NewInt
(
200
),
key
)
tx12
=
transaction
(
12
,
big
.
NewInt
(
300
),
key
)
)
pool
.
promoteTx
(
account
,
tx0
.
Hash
(),
tx0
)
pool
.
promoteTx
(
account
,
tx1
.
Hash
(),
tx1
)
pool
.
promoteTx
(
account
,
tx1
.
Hash
(),
tx2
)
pool
.
enqueueTx
(
tx10
.
Hash
(),
tx10
)
pool
.
enqueueTx
(
tx11
.
Hash
(),
tx11
)
pool
.
enqueueTx
(
tx11
.
Hash
(),
tx12
)
// Check that pre and post validations leave the pool as is
if
pool
.
pending
[
account
]
.
Len
()
!=
2
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
pool
.
pending
[
account
]
.
Len
(),
2
)
if
pool
.
pending
[
account
]
.
Len
()
!=
3
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
pool
.
pending
[
account
]
.
Len
(),
3
)
}
if
pool
.
queue
[
account
]
.
Len
()
!=
2
{
t
.
Errorf
(
"queued transaction mismatch: have %d, want %d"
,
pool
.
queue
[
account
]
.
Len
(),
2
)
if
pool
.
queue
[
account
]
.
Len
()
!=
3
{
t
.
Errorf
(
"queued transaction mismatch: have %d, want %d"
,
pool
.
queue
[
account
]
.
Len
(),
3
)
}
if
len
(
pool
.
all
)
!=
4
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
4
)
}
pool
.
resetState
()
if
pool
.
pending
[
account
]
.
Len
()
!=
2
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
pool
.
pending
[
account
]
.
Len
(),
2
)
if
pool
.
pending
[
account
]
.
Len
()
!=
3
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
pool
.
pending
[
account
]
.
Len
(),
3
)
}
if
pool
.
queue
[
account
]
.
Len
()
!=
2
{
t
.
Errorf
(
"queued transaction mismatch: have %d, want %d"
,
pool
.
queue
[
account
]
.
Len
(),
2
)
if
pool
.
queue
[
account
]
.
Len
()
!=
3
{
t
.
Errorf
(
"queued transaction mismatch: have %d, want %d"
,
pool
.
queue
[
account
]
.
Len
(),
3
)
}
if
len
(
pool
.
all
)
!=
4
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
4
)
}
// Reduce the balance of the account, and check that invalidated transactions are dropped
state
.
AddBalance
(
account
,
big
.
NewInt
(
-
7
50
))
state
.
AddBalance
(
account
,
big
.
NewInt
(
-
6
50
))
pool
.
resetState
()
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
tx0
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"funded pending transaction missing: %v"
,
tx0
)
}
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
tx1
.
Nonce
()];
ok
{
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
tx1
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"funded pending transaction missing: %v"
,
tx0
)
}
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
tx2
.
Nonce
()];
ok
{
t
.
Errorf
(
"out-of-fund pending transaction present: %v"
,
tx1
)
}
if
_
,
ok
:=
pool
.
queue
[
account
]
.
txs
.
items
[
tx10
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"funded queued transaction missing: %v"
,
tx10
)
}
if
_
,
ok
:=
pool
.
queue
[
account
]
.
txs
.
items
[
tx11
.
Nonce
()];
ok
{
if
_
,
ok
:=
pool
.
queue
[
account
]
.
txs
.
items
[
tx11
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"funded queued transaction missing: %v"
,
tx10
)
}
if
_
,
ok
:=
pool
.
queue
[
account
]
.
txs
.
items
[
tx12
.
Nonce
()];
ok
{
t
.
Errorf
(
"out-of-fund queued transaction present: %v"
,
tx11
)
}
if
len
(
pool
.
all
)
!=
4
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
4
)
}
// Reduce the block gas limit, check that invalidated transactions are dropped
pool
.
gasLimit
=
func
()
*
big
.
Int
{
return
big
.
NewInt
(
100
)
}
pool
.
resetState
()
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
tx0
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"funded pending transaction missing: %v"
,
tx0
)
}
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
tx1
.
Nonce
()];
ok
{
t
.
Errorf
(
"over-gased pending transaction present: %v"
,
tx1
)
}
if
_
,
ok
:=
pool
.
queue
[
account
]
.
txs
.
items
[
tx10
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"funded queued transaction missing: %v"
,
tx10
)
}
if
_
,
ok
:=
pool
.
queue
[
account
]
.
txs
.
items
[
tx11
.
Nonce
()];
ok
{
t
.
Errorf
(
"over-gased queued transaction present: %v"
,
tx11
)
}
if
len
(
pool
.
all
)
!=
2
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
2
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment