Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
d43ffdbf
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
d43ffdbf
编写于
3月 07, 2018
作者:
P
Péter Szilágyi
提交者:
GitHub
3月 07, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #16240 from cuiweixie/txpool
core: should enqueue the invalids tx anyway
上级
f6bef558
2b5d1a4a
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
115 addition
and
55 deletion
+115
-55
core/tx_pool.go
core/tx_pool.go
+5
-6
core/tx_pool_test.go
core/tx_pool_test.go
+110
-49
未找到文件。
core/tx_pool.go
浏览文件 @
d43ffdbf
...
...
@@ -877,16 +877,15 @@ func (pool *TxPool) removeTx(hash common.Hash) {
// Remove the transaction from the pending lists and reset the account nonce
if
pending
:=
pool
.
pending
[
addr
];
pending
!=
nil
{
if
removed
,
invalids
:=
pending
.
Remove
(
tx
);
removed
{
// If no more transactions are left, remove the list
// If no more
pending
transactions are left, remove the list
if
pending
.
Empty
()
{
delete
(
pool
.
pending
,
addr
)
delete
(
pool
.
beats
,
addr
)
}
else
{
// Otherwise p
ostpone any invalidated transactions
}
// P
ostpone any invalidated transactions
for
_
,
tx
:=
range
invalids
{
pool
.
enqueueTx
(
tx
.
Hash
(),
tx
)
}
}
// Update the account nonce if needed
if
nonce
:=
tx
.
Nonce
();
pool
.
pendingState
.
GetNonce
(
addr
)
>
nonce
{
pool
.
pendingState
.
SetNonce
(
addr
,
nonce
)
...
...
core/tx_pool_test.go
浏览文件 @
d43ffdbf
...
...
@@ -557,74 +557,112 @@ func TestTransactionDropping(t *testing.T) {
func
TestTransactionPostponing
(
t
*
testing
.
T
)
{
t
.
Parallel
()
// Create a test account and fund it
pool
,
key
:=
setupTxPool
()
// Create the pool to test the postponing with
db
,
_
:=
ethdb
.
NewMemDatabase
()
statedb
,
_
:=
state
.
New
(
common
.
Hash
{},
state
.
NewDatabase
(
db
))
blockchain
:=
&
testBlockChain
{
statedb
,
1000000
,
new
(
event
.
Feed
)}
pool
:=
NewTxPool
(
testTxPoolConfig
,
params
.
TestChainConfig
,
blockchain
)
defer
pool
.
Stop
()
account
,
_
:=
deriveSender
(
transaction
(
0
,
0
,
key
))
pool
.
currentState
.
AddBalance
(
account
,
big
.
NewInt
(
1000
))
// Create two test accounts to produce different gap profiles with
keys
:=
make
([]
*
ecdsa
.
PrivateKey
,
2
)
accs
:=
make
([]
common
.
Address
,
len
(
keys
))
for
i
:=
0
;
i
<
len
(
keys
);
i
++
{
keys
[
i
],
_
=
crypto
.
GenerateKey
()
accs
[
i
]
=
crypto
.
PubkeyToAddress
(
keys
[
i
]
.
PublicKey
)
pool
.
currentState
.
AddBalance
(
crypto
.
PubkeyToAddress
(
keys
[
i
]
.
PublicKey
),
big
.
NewInt
(
50100
))
}
// Add a batch consecutive pending transactions for validation
txns
:=
[]
*
types
.
Transaction
{}
for
i
:=
0
;
i
<
100
;
i
++
{
txs
:=
[]
*
types
.
Transaction
{}
for
i
,
key
:=
range
keys
{
for
j
:=
0
;
j
<
100
;
j
++
{
var
tx
*
types
.
Transaction
if
i
%
2
==
0
{
tx
=
transaction
(
uint64
(
i
),
1
00
,
key
)
if
(
i
+
j
)
%
2
==
0
{
tx
=
transaction
(
uint64
(
j
),
250
00
,
key
)
}
else
{
tx
=
transaction
(
uint64
(
i
),
500
,
key
)
tx
=
transaction
(
uint64
(
j
),
50000
,
key
)
}
txs
=
append
(
txs
,
tx
)
}
}
for
i
,
err
:=
range
pool
.
AddRemotes
(
txs
)
{
if
err
!=
nil
{
t
.
Fatalf
(
"tx %d: failed to add transactions: %v"
,
i
,
err
)
}
pool
.
promoteTx
(
account
,
tx
.
Hash
(),
tx
)
txns
=
append
(
txns
,
tx
)
}
// Check that pre and post validations leave the pool as is
if
p
ool
.
pending
[
account
]
.
Len
()
!=
len
(
txn
s
)
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
p
ool
.
pending
[
account
]
.
Len
(),
len
(
txn
s
))
if
p
ending
:=
pool
.
pending
[
accs
[
0
]]
.
Len
()
+
pool
.
pending
[
accs
[
1
]]
.
Len
();
pending
!=
len
(
tx
s
)
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
p
ending
,
len
(
tx
s
))
}
if
len
(
pool
.
queue
)
!=
0
{
t
.
Errorf
(
"queued
transaction mismatch: have %d, want %d"
,
pool
.
queue
[
account
]
.
Len
(
),
0
)
t
.
Errorf
(
"queued
accounts mismatch: have %d, want %d"
,
len
(
pool
.
queue
),
0
)
}
if
len
(
pool
.
all
)
!=
len
(
tx
n
s
)
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
len
(
tx
n
s
))
if
len
(
pool
.
all
)
!=
len
(
txs
)
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
len
(
txs
))
}
pool
.
lockedReset
(
nil
,
nil
)
if
p
ool
.
pending
[
account
]
.
Len
()
!=
len
(
txn
s
)
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
p
ool
.
pending
[
account
]
.
Len
(),
len
(
txn
s
))
if
p
ending
:=
pool
.
pending
[
accs
[
0
]]
.
Len
()
+
pool
.
pending
[
accs
[
1
]]
.
Len
();
pending
!=
len
(
tx
s
)
{
t
.
Errorf
(
"pending transaction mismatch: have %d, want %d"
,
p
ending
,
len
(
tx
s
))
}
if
len
(
pool
.
queue
)
!=
0
{
t
.
Errorf
(
"queued
transaction mismatch: have %d, want %d"
,
pool
.
queue
[
account
]
.
Len
(
),
0
)
t
.
Errorf
(
"queued
accounts mismatch: have %d, want %d"
,
len
(
pool
.
queue
),
0
)
}
if
len
(
pool
.
all
)
!=
len
(
tx
n
s
)
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
len
(
tx
n
s
))
if
len
(
pool
.
all
)
!=
len
(
txs
)
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
len
(
txs
))
}
// Reduce the balance of the account, and check that transactions are reorganised
pool
.
currentState
.
AddBalance
(
account
,
big
.
NewInt
(
-
750
))
for
_
,
addr
:=
range
accs
{
pool
.
currentState
.
AddBalance
(
addr
,
big
.
NewInt
(
-
1
))
}
pool
.
lockedReset
(
nil
,
nil
)
if
_
,
ok
:=
pool
.
pending
[
account
]
.
txs
.
items
[
txns
[
0
]
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"tx %d: valid and funded transaction missing from pending pool: %v"
,
0
,
txns
[
0
])
// The first account's first transaction remains valid, check that subsequent
// ones are either filtered out, or queued up for later.
if
_
,
ok
:=
pool
.
pending
[
accs
[
0
]]
.
txs
.
items
[
txs
[
0
]
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"tx %d: valid and funded transaction missing from pending pool: %v"
,
0
,
txs
[
0
])
}
if
_
,
ok
:=
pool
.
queue
[
acc
ount
]
.
txs
.
items
[
txn
s
[
0
]
.
Nonce
()];
ok
{
t
.
Errorf
(
"tx %d: valid and funded transaction present in future queue: %v"
,
0
,
tx
n
s
[
0
])
if
_
,
ok
:=
pool
.
queue
[
acc
s
[
0
]]
.
txs
.
items
[
tx
s
[
0
]
.
Nonce
()];
ok
{
t
.
Errorf
(
"tx %d: valid and funded transaction present in future queue: %v"
,
0
,
txs
[
0
])
}
for
i
,
tx
:=
range
tx
ns
[
1
:
]
{
for
i
,
tx
:=
range
tx
s
[
1
:
100
]
{
if
i
%
2
==
1
{
if
_
,
ok
:=
pool
.
pending
[
acc
ount
]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
if
_
,
ok
:=
pool
.
pending
[
acc
s
[
0
]
]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
t
.
Errorf
(
"tx %d: valid but future transaction present in pending pool: %v"
,
i
+
1
,
tx
)
}
if
_
,
ok
:=
pool
.
queue
[
acc
ount
]
.
txs
.
items
[
tx
.
Nonce
()];
!
ok
{
if
_
,
ok
:=
pool
.
queue
[
acc
s
[
0
]
]
.
txs
.
items
[
tx
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"tx %d: valid but future transaction missing from future queue: %v"
,
i
+
1
,
tx
)
}
}
else
{
if
_
,
ok
:=
pool
.
pending
[
acc
ount
]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
if
_
,
ok
:=
pool
.
pending
[
acc
s
[
0
]
]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
t
.
Errorf
(
"tx %d: out-of-fund transaction present in pending pool: %v"
,
i
+
1
,
tx
)
}
if
_
,
ok
:=
pool
.
queue
[
acc
ount
]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
if
_
,
ok
:=
pool
.
queue
[
acc
s
[
0
]
]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
t
.
Errorf
(
"tx %d: out-of-fund transaction present in future queue: %v"
,
i
+
1
,
tx
)
}
}
}
if
len
(
pool
.
all
)
!=
len
(
txns
)
/
2
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
len
(
txns
)
/
2
)
// The second account's first transaction got invalid, check that all transactions
// are either filtered out, or queued up for later.
if
pool
.
pending
[
accs
[
1
]]
!=
nil
{
t
.
Errorf
(
"invalidated account still has pending transactions"
)
}
for
i
,
tx
:=
range
txs
[
100
:
]
{
if
i
%
2
==
1
{
if
_
,
ok
:=
pool
.
queue
[
accs
[
1
]]
.
txs
.
items
[
tx
.
Nonce
()];
!
ok
{
t
.
Errorf
(
"tx %d: valid but future transaction missing from future queue: %v"
,
100
+
i
,
tx
)
}
}
else
{
if
_
,
ok
:=
pool
.
queue
[
accs
[
1
]]
.
txs
.
items
[
tx
.
Nonce
()];
ok
{
t
.
Errorf
(
"tx %d: out-of-fund transaction present in future queue: %v"
,
100
+
i
,
tx
)
}
}
}
if
len
(
pool
.
all
)
!=
len
(
txs
)
/
2
{
t
.
Errorf
(
"total transaction mismatch: have %d, want %d"
,
len
(
pool
.
all
),
len
(
txs
)
/
2
)
}
}
...
...
@@ -949,11 +987,11 @@ func testTransactionLimitingEquivalency(t *testing.T, origin uint64) {
account2
,
_
:=
deriveSender
(
transaction
(
0
,
0
,
key2
))
pool2
.
currentState
.
AddBalance
(
account2
,
big
.
NewInt
(
1000000
))
tx
n
s
:=
[]
*
types
.
Transaction
{}
txs
:=
[]
*
types
.
Transaction
{}
for
i
:=
uint64
(
0
);
i
<
testTxPoolConfig
.
AccountQueue
+
5
;
i
++
{
tx
ns
=
append
(
txn
s
,
transaction
(
origin
+
i
,
100000
,
key2
))
tx
s
=
append
(
tx
s
,
transaction
(
origin
+
i
,
100000
,
key2
))
}
pool2
.
AddRemotes
(
tx
n
s
)
pool2
.
AddRemotes
(
txs
)
// Ensure the batch optimization honors the same pool mechanics
if
len
(
pool1
.
pending
)
!=
len
(
pool2
.
pending
)
{
...
...
@@ -1124,7 +1162,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
defer
sub
.
Unsubscribe
()
// Create a number of test accounts and fund them
keys
:=
make
([]
*
ecdsa
.
PrivateKey
,
3
)
keys
:=
make
([]
*
ecdsa
.
PrivateKey
,
4
)
for
i
:=
0
;
i
<
len
(
keys
);
i
++
{
keys
[
i
],
_
=
crypto
.
GenerateKey
()
pool
.
currentState
.
AddBalance
(
crypto
.
PubkeyToAddress
(
keys
[
i
]
.
PublicKey
),
big
.
NewInt
(
1000000
))
...
...
@@ -1136,24 +1174,28 @@ func TestTransactionPoolRepricing(t *testing.T) {
txs
=
append
(
txs
,
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
1
),
keys
[
0
]))
txs
=
append
(
txs
,
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
2
),
keys
[
0
]))
txs
=
append
(
txs
,
pricedTransaction
(
0
,
100000
,
big
.
NewInt
(
1
),
keys
[
1
]))
txs
=
append
(
txs
,
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
2
),
keys
[
1
]))
txs
=
append
(
txs
,
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
1
),
keys
[
1
]))
txs
=
append
(
txs
,
pricedTransaction
(
3
,
100000
,
big
.
NewInt
(
2
),
keys
[
1
]))
txs
=
append
(
txs
,
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
2
),
keys
[
1
]))
ltx
:=
pricedTransaction
(
0
,
100000
,
big
.
NewInt
(
1
),
keys
[
2
])
txs
=
append
(
txs
,
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
2
),
keys
[
2
]))
txs
=
append
(
txs
,
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
1
),
keys
[
2
]))
txs
=
append
(
txs
,
pricedTransaction
(
3
,
100000
,
big
.
NewInt
(
2
),
keys
[
2
]))
ltx
:=
pricedTransaction
(
0
,
100000
,
big
.
NewInt
(
1
),
keys
[
3
])
// Import the batch and that both pending and queued transactions match up
pool
.
AddRemotes
(
txs
)
pool
.
AddLocal
(
ltx
)
pending
,
queued
:=
pool
.
Stats
()
if
pending
!=
4
{
t
.
Fatalf
(
"pending transactions mismatched: have %d, want %d"
,
pending
,
4
)
if
pending
!=
7
{
t
.
Fatalf
(
"pending transactions mismatched: have %d, want %d"
,
pending
,
7
)
}
if
queued
!=
3
{
t
.
Fatalf
(
"queued transactions mismatched: have %d, want %d"
,
queued
,
3
)
}
if
err
:=
validateEvents
(
events
,
4
);
err
!=
nil
{
if
err
:=
validateEvents
(
events
,
7
);
err
!=
nil
{
t
.
Fatalf
(
"original event firing failed: %v"
,
err
)
}
if
err
:=
validateTxPoolInternals
(
pool
);
err
!=
nil
{
...
...
@@ -1166,8 +1208,8 @@ func TestTransactionPoolRepricing(t *testing.T) {
if
pending
!=
2
{
t
.
Fatalf
(
"pending transactions mismatched: have %d, want %d"
,
pending
,
2
)
}
if
queued
!=
3
{
t
.
Fatalf
(
"queued transactions mismatched: have %d, want %d"
,
queued
,
3
)
if
queued
!=
5
{
t
.
Fatalf
(
"queued transactions mismatched: have %d, want %d"
,
queued
,
5
)
}
if
err
:=
validateEvents
(
events
,
0
);
err
!=
nil
{
t
.
Fatalf
(
"reprice event firing failed: %v"
,
err
)
...
...
@@ -1179,7 +1221,10 @@ func TestTransactionPoolRepricing(t *testing.T) {
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
1
),
keys
[
0
]));
err
!=
ErrUnderpriced
{
t
.
Fatalf
(
"adding underpriced pending transaction error mismatch: have %v, want %v"
,
err
,
ErrUnderpriced
)
}
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
1
),
keys
[
1
]));
err
!=
ErrUnderpriced
{
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
0
,
100000
,
big
.
NewInt
(
1
),
keys
[
1
]));
err
!=
ErrUnderpriced
{
t
.
Fatalf
(
"adding underpriced pending transaction error mismatch: have %v, want %v"
,
err
,
ErrUnderpriced
)
}
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
1
),
keys
[
2
]));
err
!=
ErrUnderpriced
{
t
.
Fatalf
(
"adding underpriced queued transaction error mismatch: have %v, want %v"
,
err
,
ErrUnderpriced
)
}
if
err
:=
validateEvents
(
events
,
0
);
err
!=
nil
{
...
...
@@ -1189,7 +1234,7 @@ func TestTransactionPoolRepricing(t *testing.T) {
t
.
Fatalf
(
"pool internal state corrupted: %v"
,
err
)
}
// However we can add local underpriced transactions
tx
:=
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
1
),
keys
[
2
])
tx
:=
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
1
),
keys
[
3
])
if
err
:=
pool
.
AddLocal
(
tx
);
err
!=
nil
{
t
.
Fatalf
(
"failed to add underpriced local transaction: %v"
,
err
)
}
...
...
@@ -1202,6 +1247,22 @@ func TestTransactionPoolRepricing(t *testing.T) {
if
err
:=
validateTxPoolInternals
(
pool
);
err
!=
nil
{
t
.
Fatalf
(
"pool internal state corrupted: %v"
,
err
)
}
// And we can fill gaps with properly priced transactions
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
1
,
100000
,
big
.
NewInt
(
2
),
keys
[
0
]));
err
!=
nil
{
t
.
Fatalf
(
"failed to add pending transaction: %v"
,
err
)
}
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
0
,
100000
,
big
.
NewInt
(
2
),
keys
[
1
]));
err
!=
nil
{
t
.
Fatalf
(
"failed to add pending transaction: %v"
,
err
)
}
if
err
:=
pool
.
AddRemote
(
pricedTransaction
(
2
,
100000
,
big
.
NewInt
(
2
),
keys
[
2
]));
err
!=
nil
{
t
.
Fatalf
(
"failed to add queued transaction: %v"
,
err
)
}
if
err
:=
validateEvents
(
events
,
5
);
err
!=
nil
{
t
.
Fatalf
(
"post-reprice event firing failed: %v"
,
err
)
}
if
err
:=
validateTxPoolInternals
(
pool
);
err
!=
nil
{
t
.
Fatalf
(
"pool internal state corrupted: %v"
,
err
)
}
}
// Tests that setting the transaction pool gas price to a higher value does not
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录