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
b664bedc
Commit
b664bedc
authored
Jun 22, 2017
by
Péter Szilágyi
Committed by
GitHub
Jun 22, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14673 from holiman/txfix
core: add testcase for txpool
parents
c98d9b49
eebde1a2
Changes
3
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
200 additions
and
42 deletions
+200
-42
tx_pool.go
core/tx_pool.go
+78
-27
tx_pool_test.go
core/tx_pool_test.go
+121
-14
txpool.go
light/txpool.go
+1
-1
No files found.
core/tx_pool.go
View file @
b664bedc
...
@@ -35,16 +35,41 @@ import (
...
@@ -35,16 +35,41 @@ import (
)
)
var
(
var
(
// Transaction Pool Errors
// ErrInvalidSender is returned if the transaction contains an invalid signature.
ErrInvalidSender
=
errors
.
New
(
"invalid sender"
)
ErrInvalidSender
=
errors
.
New
(
"invalid sender"
)
ErrNonce
=
errors
.
New
(
"nonce too low"
)
ErrUnderpriced
=
errors
.
New
(
"transaction underpriced"
)
// ErrNonceTooLow is returned if the nonce of a transaction is lower than the
// one present in the local chain.
ErrNonceTooLow
=
errors
.
New
(
"nonce too low"
)
// ErrUnderpriced is returned if a transaction's gas price is below the minimum
// configured for the transaction pool.
ErrUnderpriced
=
errors
.
New
(
"transaction underpriced"
)
// ErrReplaceUnderpriced is returned if a transaction is attempted to be replaced
// with a different one without the required price bump.
ErrReplaceUnderpriced
=
errors
.
New
(
"replacement transaction underpriced"
)
ErrReplaceUnderpriced
=
errors
.
New
(
"replacement transaction underpriced"
)
ErrBalance
=
errors
.
New
(
"insufficient balance"
)
ErrInsufficientFunds
=
errors
.
New
(
"insufficient funds for gas * price + value"
)
// ErrInsufficientFunds is returned if the total cost of executing a transaction
ErrIntrinsicGas
=
errors
.
New
(
"intrinsic gas too low"
)
// is higher than the balance of the user's account.
ErrGasLimit
=
errors
.
New
(
"exceeds block gas limit"
)
ErrInsufficientFunds
=
errors
.
New
(
"insufficient funds for gas * price + value"
)
ErrNegativeValue
=
errors
.
New
(
"negative value"
)
// ErrIntrinsicGas is returned if the transaction is specified to use less gas
// than required to start the invocation.
ErrIntrinsicGas
=
errors
.
New
(
"intrinsic gas too low"
)
// ErrGasLimit is returned if a transaction's requested gas limit exceeds the
// maximum allowance of the current block.
ErrGasLimit
=
errors
.
New
(
"exceeds block gas limit"
)
// ErrNegativeValue is a sanity error to ensure noone is able to specify a
// transaction with a negative value.
ErrNegativeValue
=
errors
.
New
(
"negative value"
)
// ErrOversizedData is returned if the input data of a transaction is greater
// than some meaningful limit a user might use. This is not a consensus error
// making the transaction invalid, rather a DOS protection.
ErrOversizedData
=
errors
.
New
(
"oversized data"
)
)
)
var
(
var
(
...
@@ -54,16 +79,16 @@ var (
...
@@ -54,16 +79,16 @@ var (
var
(
var
(
// Metrics for the pending pool
// Metrics for the pending pool
pendingDiscardCounter
=
metrics
.
NewCounter
(
"txpool/pending/discard"
)
pendingDiscardCounter
=
metrics
.
NewCounter
(
"txpool/pending/discard"
)
pendingReplaceCounter
=
metrics
.
NewCounter
(
"txpool/pending/replace"
)
pendingReplaceCounter
=
metrics
.
NewCounter
(
"txpool/pending/replace"
)
pendingR
LCounter
=
metrics
.
NewCounter
(
"txpool/pending/ratelimit"
)
// Dropped due to rate limiting
pendingR
ateLimitCounter
=
metrics
.
NewCounter
(
"txpool/pending/ratelimit"
)
// Dropped due to rate limiting
pendingNofundsCounter
=
metrics
.
NewCounter
(
"txpool/pending/nofunds"
)
// Dropped due to out-of-funds
pendingNofundsCounter
=
metrics
.
NewCounter
(
"txpool/pending/nofunds"
)
// Dropped due to out-of-funds
// Metrics for the queued pool
// Metrics for the queued pool
queuedDiscardCounter
=
metrics
.
NewCounter
(
"txpool/queued/discard"
)
queuedDiscardCounter
=
metrics
.
NewCounter
(
"txpool/queued/discard"
)
queuedReplaceCounter
=
metrics
.
NewCounter
(
"txpool/queued/replace"
)
queuedReplaceCounter
=
metrics
.
NewCounter
(
"txpool/queued/replace"
)
queuedR
LCounter
=
metrics
.
NewCounter
(
"txpool/queued/ratelimit"
)
// Dropped due to rate limiting
queuedR
ateLimitCounter
=
metrics
.
NewCounter
(
"txpool/queued/ratelimit"
)
// Dropped due to rate limiting
queuedNofundsCounter
=
metrics
.
NewCounter
(
"txpool/queued/nofunds"
)
// Dropped due to out-of-funds
queuedNofundsCounter
=
metrics
.
NewCounter
(
"txpool/queued/nofunds"
)
// Dropped due to out-of-funds
// General tx metrics
// General tx metrics
invalidTxCounter
=
metrics
.
NewCounter
(
"txpool/invalid"
)
invalidTxCounter
=
metrics
.
NewCounter
(
"txpool/invalid"
)
...
@@ -374,7 +399,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
...
@@ -374,7 +399,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
}
}
// Last but not least check for nonce errors
// Last but not least check for nonce errors
if
currentState
.
GetNonce
(
from
)
>
tx
.
Nonce
()
{
if
currentState
.
GetNonce
(
from
)
>
tx
.
Nonce
()
{
return
ErrNonce
return
ErrNonce
TooLow
}
}
// Check the transaction doesn't exceed the current
// Check the transaction doesn't exceed the current
...
@@ -395,12 +420,15 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
...
@@ -395,12 +420,15 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
if
currentState
.
GetBalance
(
from
)
.
Cmp
(
tx
.
Cost
())
<
0
{
if
currentState
.
GetBalance
(
from
)
.
Cmp
(
tx
.
Cost
())
<
0
{
return
ErrInsufficientFunds
return
ErrInsufficientFunds
}
}
intrGas
:=
IntrinsicGas
(
tx
.
Data
(),
tx
.
To
()
==
nil
,
pool
.
homestead
)
intrGas
:=
IntrinsicGas
(
tx
.
Data
(),
tx
.
To
()
==
nil
,
pool
.
homestead
)
if
tx
.
Gas
()
.
Cmp
(
intrGas
)
<
0
{
if
tx
.
Gas
()
.
Cmp
(
intrGas
)
<
0
{
return
ErrIntrinsicGas
return
ErrIntrinsicGas
}
}
// Heuristic limit, reject transactions over 32KB to prevent DOS attacks
if
tx
.
Size
()
>
32
*
1024
{
return
ErrOversizedData
}
return
nil
return
nil
}
}
...
@@ -638,8 +666,9 @@ func (pool *TxPool) removeTx(hash common.Hash) {
...
@@ -638,8 +666,9 @@ func (pool *TxPool) removeTx(hash common.Hash) {
}
}
// Update the account nonce if needed
// Update the account nonce if needed
if
nonce
:=
tx
.
Nonce
();
pool
.
pendingState
.
GetNonce
(
addr
)
>
nonce
{
if
nonce
:=
tx
.
Nonce
();
pool
.
pendingState
.
GetNonce
(
addr
)
>
nonce
{
pool
.
pendingState
.
SetNonce
(
addr
,
tx
.
Nonce
()
)
pool
.
pendingState
.
SetNonce
(
addr
,
nonce
)
}
}
return
}
}
}
}
// Transaction is in the future queue
// Transaction is in the future queue
...
@@ -696,10 +725,10 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
...
@@ -696,10 +725,10 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
// Drop all transactions over the allowed limit
// Drop all transactions over the allowed limit
for
_
,
tx
:=
range
list
.
Cap
(
int
(
pool
.
config
.
AccountQueue
))
{
for
_
,
tx
:=
range
list
.
Cap
(
int
(
pool
.
config
.
AccountQueue
))
{
hash
:=
tx
.
Hash
()
hash
:=
tx
.
Hash
()
log
.
Trace
(
"Removed cap-exceeding queued transaction"
,
"hash"
,
hash
)
delete
(
pool
.
all
,
hash
)
delete
(
pool
.
all
,
hash
)
pool
.
priced
.
Removed
()
pool
.
priced
.
Removed
()
queuedRLCounter
.
Inc
(
1
)
queuedRateLimitCounter
.
Inc
(
1
)
log
.
Trace
(
"Removed cap-exceeding queued transaction"
,
"hash"
,
hash
)
}
}
queued
+=
uint64
(
list
.
Len
())
queued
+=
uint64
(
list
.
Len
())
...
@@ -745,7 +774,18 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
...
@@ -745,7 +774,18 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
for
pending
>
pool
.
config
.
GlobalSlots
&&
pool
.
pending
[
offenders
[
len
(
offenders
)
-
2
]]
.
Len
()
>
threshold
{
for
pending
>
pool
.
config
.
GlobalSlots
&&
pool
.
pending
[
offenders
[
len
(
offenders
)
-
2
]]
.
Len
()
>
threshold
{
for
i
:=
0
;
i
<
len
(
offenders
)
-
1
;
i
++
{
for
i
:=
0
;
i
<
len
(
offenders
)
-
1
;
i
++
{
list
:=
pool
.
pending
[
offenders
[
i
]]
list
:=
pool
.
pending
[
offenders
[
i
]]
list
.
Cap
(
list
.
Len
()
-
1
)
for
_
,
tx
:=
range
list
.
Cap
(
list
.
Len
()
-
1
)
{
// Drop the transaction from the global pools too
hash
:=
tx
.
Hash
()
delete
(
pool
.
all
,
hash
)
pool
.
priced
.
Removed
()
// Update the account nonce to the dropped transaction
if
nonce
:=
tx
.
Nonce
();
pool
.
pendingState
.
GetNonce
(
offenders
[
i
])
>
nonce
{
pool
.
pendingState
.
SetNonce
(
offenders
[
i
],
nonce
)
}
log
.
Trace
(
"Removed fairness-exceeding pending transaction"
,
"hash"
,
hash
)
}
pending
--
pending
--
}
}
}
}
...
@@ -756,12 +796,23 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
...
@@ -756,12 +796,23 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
for
pending
>
pool
.
config
.
GlobalSlots
&&
uint64
(
pool
.
pending
[
offenders
[
len
(
offenders
)
-
1
]]
.
Len
())
>
pool
.
config
.
AccountSlots
{
for
pending
>
pool
.
config
.
GlobalSlots
&&
uint64
(
pool
.
pending
[
offenders
[
len
(
offenders
)
-
1
]]
.
Len
())
>
pool
.
config
.
AccountSlots
{
for
_
,
addr
:=
range
offenders
{
for
_
,
addr
:=
range
offenders
{
list
:=
pool
.
pending
[
addr
]
list
:=
pool
.
pending
[
addr
]
list
.
Cap
(
list
.
Len
()
-
1
)
for
_
,
tx
:=
range
list
.
Cap
(
list
.
Len
()
-
1
)
{
// Drop the transaction from the global pools too
hash
:=
tx
.
Hash
()
delete
(
pool
.
all
,
hash
)
pool
.
priced
.
Removed
()
// Update the account nonce to the dropped transaction
if
nonce
:=
tx
.
Nonce
();
pool
.
pendingState
.
GetNonce
(
addr
)
>
nonce
{
pool
.
pendingState
.
SetNonce
(
addr
,
nonce
)
}
log
.
Trace
(
"Removed fairness-exceeding pending transaction"
,
"hash"
,
hash
)
}
pending
--
pending
--
}
}
}
}
}
}
pendingR
L
Counter
.
Inc
(
int64
(
pendingBeforeCap
-
pending
))
pendingR
ateLimit
Counter
.
Inc
(
int64
(
pendingBeforeCap
-
pending
))
}
}
// If we've queued more transactions than the hard limit, drop oldest ones
// If we've queued more transactions than the hard limit, drop oldest ones
if
queued
>
pool
.
config
.
GlobalQueue
{
if
queued
>
pool
.
config
.
GlobalQueue
{
...
@@ -785,7 +836,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
...
@@ -785,7 +836,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
pool
.
removeTx
(
tx
.
Hash
())
pool
.
removeTx
(
tx
.
Hash
())
}
}
drop
-=
size
drop
-=
size
queuedR
L
Counter
.
Inc
(
int64
(
size
))
queuedR
ateLimit
Counter
.
Inc
(
int64
(
size
))
continue
continue
}
}
// Otherwise drop only last few transactions
// Otherwise drop only last few transactions
...
@@ -793,7 +844,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
...
@@ -793,7 +844,7 @@ func (pool *TxPool) promoteExecutables(state *state.StateDB, accounts []common.A
for
i
:=
len
(
txs
)
-
1
;
i
>=
0
&&
drop
>
0
;
i
--
{
for
i
:=
len
(
txs
)
-
1
;
i
>=
0
&&
drop
>
0
;
i
--
{
pool
.
removeTx
(
txs
[
i
]
.
Hash
())
pool
.
removeTx
(
txs
[
i
]
.
Hash
())
drop
--
drop
--
queuedR
L
Counter
.
Inc
(
1
)
queuedR
ateLimit
Counter
.
Inc
(
1
)
}
}
}
}
}
}
...
...
core/tx_pool_test.go
View file @
b664bedc
This diff is collapsed.
Click to expand it.
light/txpool.go
View file @
b664bedc
...
@@ -360,7 +360,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
...
@@ -360,7 +360,7 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
currentState
:=
pool
.
currentState
()
currentState
:=
pool
.
currentState
()
if
n
,
err
:=
currentState
.
GetNonce
(
ctx
,
from
);
err
==
nil
{
if
n
,
err
:=
currentState
.
GetNonce
(
ctx
,
from
);
err
==
nil
{
if
n
>
tx
.
Nonce
()
{
if
n
>
tx
.
Nonce
()
{
return
core
.
ErrNonce
return
core
.
ErrNonce
TooLow
}
}
}
else
{
}
else
{
return
err
return
err
...
...
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