Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
040aa2bb
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,体验更适合开发者的 AI 搜索 >>
提交
040aa2bb
编写于
8月 15, 2018
作者:
G
gary rong
提交者:
Péter Szilágyi
8月 15, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
miner: streaming uncle blocks (#17320)
* miner: stream uncle block * miner: polish
上级
e598ae5c
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
125 addition
and
50 deletion
+125
-50
miner/worker.go
miner/worker.go
+57
-42
miner/worker_test.go
miner/worker_test.go
+68
-8
未找到文件。
miner/worker.go
浏览文件 @
040aa2bb
...
...
@@ -213,8 +213,9 @@ type worker struct {
running
int32
// The indicator whether the consensus engine is running or not.
// Test hooks
newTaskHook
func
(
*
task
)
// Method to call upon receiving a new sealing task
fullTaskInterval
func
()
// Method to call before pushing the full sealing task
newTaskHook
func
(
*
task
)
// Method to call upon receiving a new sealing task
skipSealHook
func
(
*
task
)
bool
// Method to decide whether skipping the sealing.
fullTaskHook
func
()
// Method to call before pushing the full sealing task
}
func
newWorker
(
config
*
params
.
ChainConfig
,
engine
consensus
.
Engine
,
eth
Backend
,
mux
*
event
.
TypeMux
)
*
worker
{
...
...
@@ -329,8 +330,32 @@ func (w *worker) mainLoop() {
w
.
commitNewWork
()
case
ev
:=
<-
w
.
chainSideCh
:
if
_
,
exist
:=
w
.
possibleUncles
[
ev
.
Block
.
Hash
()];
exist
{
continue
}
// Add side block to possible uncle block set.
w
.
possibleUncles
[
ev
.
Block
.
Hash
()]
=
ev
.
Block
// If our mining block contains less than 2 uncle blocks,
// add the new uncle block if valid and regenerate a mining block.
if
w
.
isRunning
()
&&
w
.
current
!=
nil
&&
w
.
current
.
uncles
.
Cardinality
()
<
2
{
start
:=
time
.
Now
()
if
err
:=
w
.
commitUncle
(
w
.
current
,
ev
.
Block
.
Header
());
err
==
nil
{
var
uncles
[]
*
types
.
Header
w
.
current
.
uncles
.
Each
(
func
(
item
interface
{})
bool
{
hash
,
ok
:=
item
.
(
common
.
Hash
)
if
!
ok
{
return
false
}
uncle
,
exist
:=
w
.
possibleUncles
[
hash
]
if
!
exist
{
return
false
}
uncles
=
append
(
uncles
,
uncle
.
Header
())
return
true
})
w
.
commit
(
uncles
,
nil
,
true
,
start
)
}
}
case
ev
:=
<-
w
.
txsCh
:
// Apply transactions to the pending state if we're not mining.
...
...
@@ -378,6 +403,10 @@ func (w *worker) seal(t *task, stop <-chan struct{}) {
res
*
task
)
if
w
.
skipSealHook
!=
nil
&&
w
.
skipSealHook
(
t
)
{
return
}
if
t
.
block
,
err
=
w
.
engine
.
Seal
(
w
.
chain
,
t
.
block
,
stop
);
t
.
block
!=
nil
{
log
.
Info
(
"Successfully sealed new block"
,
"number"
,
t
.
block
.
Number
(),
"hash"
,
t
.
block
.
Hash
(),
"elapsed"
,
common
.
PrettyDuration
(
time
.
Since
(
t
.
createdAt
)))
...
...
@@ -637,30 +666,9 @@ func (w *worker) commitNewWork() {
delete
(
w
.
possibleUncles
,
hash
)
}
var
(
emptyBlock
,
fullBlock
*
types
.
Block
emptyState
,
fullState
*
state
.
StateDB
)
// Create an empty block based on temporary copied state for sealing in advance without waiting block
// execution finished.
emptyState
=
env
.
state
.
Copy
()
if
emptyBlock
,
err
=
w
.
engine
.
Finalize
(
w
.
chain
,
header
,
emptyState
,
nil
,
uncles
,
nil
);
err
!=
nil
{
log
.
Error
(
"Failed to finalize block for temporary sealing"
,
"err"
,
err
)
}
else
{
// Push empty work in advance without applying pending transaction.
// The reason is transactions execution can cost a lot and sealer need to
// take advantage of this part time.
if
w
.
isRunning
()
{
select
{
case
w
.
taskCh
<-
&
task
{
receipts
:
nil
,
state
:
emptyState
,
block
:
emptyBlock
,
createdAt
:
time
.
Now
()}
:
log
.
Info
(
"Commit new empty mining work"
,
"number"
,
emptyBlock
.
Number
(),
"uncles"
,
len
(
uncles
))
case
<-
w
.
exitCh
:
log
.
Info
(
"Worker has exited"
)
return
}
}
}
w
.
commit
(
uncles
,
nil
,
false
,
tstart
)
// Fill the block with all available pending transactions.
pending
,
err
:=
w
.
eth
.
TxPool
()
.
Pending
()
...
...
@@ -676,31 +684,38 @@ func (w *worker) commitNewWork() {
txs
:=
types
.
NewTransactionsByPriceAndNonce
(
w
.
current
.
signer
,
pending
)
env
.
commitTransactions
(
w
.
mux
,
txs
,
w
.
chain
,
w
.
coinbase
)
// Create the full block to seal with the consensus engine
fullState
=
env
.
state
.
Copy
()
if
fullBlock
,
err
=
w
.
engine
.
Finalize
(
w
.
chain
,
header
,
fullState
,
env
.
txs
,
uncles
,
env
.
receipts
);
err
!=
nil
{
log
.
Error
(
"Failed to finalize block for sealing"
,
"err"
,
err
)
return
}
w
.
commit
(
uncles
,
w
.
fullTaskHook
,
true
,
tstart
)
}
// commit runs any post-transaction state modifications, assembles the final block
// and commits new work if consensus engine is running.
func
(
w
*
worker
)
commit
(
uncles
[]
*
types
.
Header
,
interval
func
(),
update
bool
,
start
time
.
Time
)
error
{
// Deep copy receipts here to avoid interaction between different tasks.
cpy
:=
make
([]
*
types
.
Receipt
,
len
(
env
.
receipts
))
for
i
,
l
:=
range
env
.
receipts
{
cpy
[
i
]
=
new
(
types
.
Receipt
)
*
cpy
[
i
]
=
*
l
receipts
:=
make
([]
*
types
.
Receipt
,
len
(
w
.
current
.
receipts
))
for
i
,
l
:=
range
w
.
current
.
receipts
{
receipts
[
i
]
=
new
(
types
.
Receipt
)
*
receipts
[
i
]
=
*
l
}
s
:=
w
.
current
.
state
.
Copy
()
block
,
err
:=
w
.
engine
.
Finalize
(
w
.
chain
,
w
.
current
.
header
,
s
,
w
.
current
.
txs
,
uncles
,
w
.
current
.
receipts
)
if
err
!=
nil
{
return
err
}
// We only care about logging if we're actually mining.
if
w
.
isRunning
()
{
if
w
.
fullTaskI
nterval
!=
nil
{
w
.
fullTaskI
nterval
()
if
i
nterval
!=
nil
{
i
nterval
()
}
select
{
case
w
.
taskCh
<-
&
task
{
receipts
:
cpy
,
state
:
fullState
,
block
:
fullBlock
,
createdAt
:
time
.
Now
()}
:
w
.
unconfirmed
.
Shift
(
fullBlock
.
NumberU64
()
-
1
)
log
.
Info
(
"Commit new full mining work"
,
"number"
,
fullBlock
.
Number
(),
"txs"
,
env
.
tcount
,
"uncles"
,
len
(
uncles
),
"elapsed"
,
common
.
PrettyDuration
(
time
.
Since
(
tstart
)))
case
w
.
taskCh
<-
&
task
{
receipts
:
receipts
,
state
:
s
,
block
:
block
,
createdAt
:
time
.
Now
()}
:
w
.
unconfirmed
.
Shift
(
block
.
NumberU64
()
-
1
)
log
.
Info
(
"Commit new mining work"
,
"number"
,
block
.
Number
(),
"txs"
,
w
.
current
.
tcount
,
"uncles"
,
len
(
uncles
),
"elapsed"
,
common
.
PrettyDuration
(
time
.
Since
(
start
)))
case
<-
w
.
exitCh
:
log
.
Info
(
"Worker has exited"
)
}
}
w
.
updateSnapshot
()
if
update
{
w
.
updateSnapshot
()
}
return
nil
}
miner/worker_test.go
浏览文件 @
040aa2bb
...
...
@@ -59,7 +59,7 @@ func init() {
ethashChainConfig
=
params
.
TestChainConfig
cliqueChainConfig
=
params
.
TestChainConfig
cliqueChainConfig
.
Clique
=
&
params
.
CliqueConfig
{
Period
:
1
,
Period
:
1
0
,
Epoch
:
30000
,
}
tx1
,
_
:=
types
.
SignTx
(
types
.
NewTransaction
(
0
,
acc1Addr
,
big
.
NewInt
(
1000
),
params
.
TxGas
,
nil
,
nil
),
types
.
HomesteadSigner
{},
testBankKey
)
...
...
@@ -74,6 +74,7 @@ type testWorkerBackend struct {
txPool
*
core
.
TxPool
chain
*
core
.
BlockChain
testTxFeed
event
.
Feed
uncleBlock
*
types
.
Block
}
func
newTestWorkerBackend
(
t
*
testing
.
T
,
chainConfig
*
params
.
ChainConfig
,
engine
consensus
.
Engine
)
*
testWorkerBackend
{
...
...
@@ -93,15 +94,19 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
default
:
t
.
Fatal
(
"unexpect consensus engine type"
)
}
gspec
.
MustCommit
(
db
)
g
enesis
:=
g
spec
.
MustCommit
(
db
)
chain
,
_
:=
core
.
NewBlockChain
(
db
,
nil
,
gspec
.
Config
,
engine
,
vm
.
Config
{})
txpool
:=
core
.
NewTxPool
(
testTxPoolConfig
,
chainConfig
,
chain
)
blocks
,
_
:=
core
.
GenerateChain
(
chainConfig
,
genesis
,
engine
,
db
,
1
,
func
(
i
int
,
gen
*
core
.
BlockGen
)
{
gen
.
SetCoinbase
(
acc1Addr
)
})
return
&
testWorkerBackend
{
db
:
db
,
chain
:
chain
,
txPool
:
txpool
,
db
:
db
,
chain
:
chain
,
txPool
:
txpool
,
uncleBlock
:
blocks
[
0
],
}
}
...
...
@@ -188,7 +193,7 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
taskCh
<-
struct
{}{}
}
}
w
.
fullTask
Interval
=
func
()
{
w
.
fullTask
Hook
=
func
()
{
time
.
Sleep
(
100
*
time
.
Millisecond
)
}
...
...
@@ -202,11 +207,66 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
w
.
start
()
for
i
:=
0
;
i
<
2
;
i
+=
1
{
to
:=
time
.
NewTimer
(
time
.
Second
)
select
{
case
<-
taskCh
:
case
<-
t
o
.
C
:
case
<-
t
ime
.
NewTimer
(
time
.
Second
)
.
C
:
t
.
Error
(
"new task timeout"
)
}
}
}
func
TestStreamUncleBlock
(
t
*
testing
.
T
)
{
ethash
:=
ethash
.
NewFaker
()
defer
ethash
.
Close
()
w
,
b
:=
newTestWorker
(
t
,
ethashChainConfig
,
ethash
)
defer
w
.
close
()
var
taskCh
=
make
(
chan
struct
{})
taskIndex
:=
0
w
.
newTaskHook
=
func
(
task
*
task
)
{
if
task
.
block
.
NumberU64
()
==
1
{
if
taskIndex
==
2
{
has
:=
task
.
block
.
Header
()
.
UncleHash
want
:=
types
.
CalcUncleHash
([]
*
types
.
Header
{
b
.
uncleBlock
.
Header
()})
if
has
!=
want
{
t
.
Errorf
(
"uncle hash mismatch, has %s, want %s"
,
has
.
Hex
(),
want
.
Hex
())
}
}
taskCh
<-
struct
{}{}
taskIndex
+=
1
}
}
w
.
skipSealHook
=
func
(
task
*
task
)
bool
{
return
true
}
w
.
fullTaskHook
=
func
()
{
time
.
Sleep
(
100
*
time
.
Millisecond
)
}
// Ensure worker has finished initialization
for
{
b
:=
w
.
pendingBlock
()
if
b
!=
nil
&&
b
.
NumberU64
()
==
1
{
break
}
}
w
.
start
()
// Ignore the first two works
for
i
:=
0
;
i
<
2
;
i
+=
1
{
select
{
case
<-
taskCh
:
case
<-
time
.
NewTimer
(
time
.
Second
)
.
C
:
t
.
Error
(
"new task timeout"
)
}
}
b
.
PostChainEvents
([]
interface
{}{
core
.
ChainSideEvent
{
Block
:
b
.
uncleBlock
}})
select
{
case
<-
taskCh
:
case
<-
time
.
NewTimer
(
time
.
Second
)
.
C
:
t
.
Error
(
"new task timeout"
)
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录