Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
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
link33
plugin
Commits
2cb03695
Commit
2cb03695
authored
Aug 08, 2019
by
张振华
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
0ef31ffb
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
787 additions
and
133 deletions
+787
-133
consensus_state.go
plugin/consensus/dpos/consensus_state.go
+320
-7
dpos.go
plugin/consensus/dpos/dpos.go
+1
-1
dpos_msg.proto
plugin/consensus/dpos/proto/dpos_msg.proto
+15
-0
state_machine.go
plugin/consensus/dpos/state_machine.go
+102
-72
dpos_msg.pb.go
plugin/consensus/dpos/types/dpos_msg.pb.go
+140
-30
priv_validator.go
plugin/consensus/dpos/types/priv_validator.go
+42
-20
validator_manager.go
plugin/consensus/dpos/validator_manager.go
+167
-3
No files found.
plugin/consensus/dpos/consensus_state.go
View file @
2cb03695
...
...
@@ -17,6 +17,7 @@ import (
"sync/atomic"
"time"
"github.com/33cn/chain33/common/crypto"
dpostype
"github.com/33cn/plugin/plugin/consensus/dpos/types"
ttypes
"github.com/33cn/plugin/plugin/consensus/dpos/types"
dty
"github.com/33cn/plugin/plugin/dapp/dposvote/types"
...
...
@@ -30,6 +31,9 @@ const (
continueToVote
=
0
voteSuccess
=
1
voteFail
=
2
VrfQueryTypeM
=
0
VrfQueryTypeRP
=
1
)
// Errors define
...
...
@@ -55,11 +59,15 @@ func (ti *timeoutInfo) String() string {
return
fmt
.
Sprintf
(
"%v"
,
ti
.
Duration
)
}
/*
type vrfStatusInfo struct {
Cycle int64
VrfStatus int64 //0:初始状态,1:未注册M状态,2:已发起M注册状态,3:已注册M状态,4:已发起RP注册状态,5:已注册RP状态,6:已过cycle一半但未发起M注册,7.cycle周期已过,未注册RP状态
M []byte
R []byte
P []byte
}
*/
// ConsensusState handles execution of the consensus algorithm.
// It processes votes and proposals, and upon reaching agreement,
// commits blocks to the chain and executes them against the application.
...
...
@@ -108,6 +116,9 @@ type ConsensusState struct {
cachedNotify
*
dpostype
.
DPosNotify
cycleBoundaryMap
map
[
int64
]
*
dty
.
DposCBInfo
vrfInfoMap
map
[
int64
]
*
dty
.
VrfInfo
vrfInfosMap
map
[
int64
]
[]
*
dty
.
VrfInfo
}
// NewConsensusState returns a new ConsensusState.
...
...
@@ -122,6 +133,8 @@ func NewConsensusState(client *Client, valMgr ValidatorMgr) *ConsensusState {
dposState
:
InitStateObj
,
dposVotes
:
nil
,
cycleBoundaryMap
:
make
(
map
[
int64
]
*
dty
.
DposCBInfo
),
vrfInfoMap
:
make
(
map
[
int64
]
*
dty
.
VrfInfo
),
vrfInfosMap
:
make
(
map
[
int64
]
[]
*
dty
.
VrfInfo
),
}
cs
.
updateToValMgr
(
valMgr
)
...
...
@@ -578,11 +591,17 @@ func (cs *ConsensusState) QueryCycleBoundaryInfo(cycle int64)(*dty.DposCBInfo, e
return
msg
.
GetData
()
.
(
types
.
Message
)
.
(
*
dty
.
DposCBInfo
),
nil
}
// Init
CycleBoundaryInfo
method
func
(
cs
*
ConsensusState
)
Init
CycleBoundaryInfo
()
{
// Init method
func
(
cs
*
ConsensusState
)
Init
()
{
now
:=
time
.
Now
()
.
Unix
()
task
:=
DecideTaskByTime
(
now
)
cs
.
InitCycleBoundaryInfo
(
task
)
cs
.
InitCycleVrfInfo
(
task
)
cs
.
InitCycleVrfInfos
(
task
)
}
// InitCycleBoundaryInfo method
func
(
cs
*
ConsensusState
)
InitCycleBoundaryInfo
(
task
Task
){
info
,
err
:=
cs
.
QueryCycleBoundaryInfo
(
task
.
cycle
)
if
err
==
nil
&&
info
!=
nil
{
//cs.cycleBoundaryMap[task.cycle] = info
...
...
@@ -599,6 +618,7 @@ func (cs *ConsensusState) InitCycleBoundaryInfo(){
return
}
// UpdateCBInfo method
func
(
cs
*
ConsensusState
)
UpdateCBInfo
(
info
*
dty
.
DposCBInfo
)
{
valueNumber
:=
len
(
cs
.
cycleBoundaryMap
)
if
valueNumber
==
0
{
...
...
@@ -627,16 +647,23 @@ func (cs *ConsensusState) UpdateCBInfo(info *dty.DposCBInfo) {
cs
.
cycleBoundaryMap
[
info
.
Cycle
]
=
info
}
// GetCBInfoByCircle method
func
(
cs
*
ConsensusState
)
GetCBInfoByCircle
(
cycle
int64
)
(
info
*
dty
.
DposCBInfo
)
{
if
v
,
ok
:=
cs
.
cycleBoundaryMap
[
cycle
];
ok
{
info
=
v
return
info
}
info
,
err
:=
cs
.
QueryCycleBoundaryInfo
(
cycle
)
if
err
==
nil
&&
info
!=
nil
{
cs
.
UpdateCBInfo
(
info
)
return
info
}
return
nil
}
// Verify
Notify
method
// Verify
CBInfo
method
func
(
cs
*
ConsensusState
)
VerifyCBInfo
(
info
*
dty
.
DposCBInfo
)
bool
{
// Verify signature
bPubkey
,
err
:=
hex
.
DecodeString
(
info
.
Pubkey
)
...
...
@@ -690,12 +717,27 @@ func (cs *ConsensusState) VerifyCBInfo(info *dty.DposCBInfo) bool {
return
true
}
// SendCBTx method
func
(
cs
*
ConsensusState
)
SendCBTx
(
info
*
dty
.
DposCBInfo
)
bool
{
err
:=
cs
.
privValidator
.
SignCBInfo
(
info
)
info
.
Pubkey
=
hex
.
EncodeToString
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
())
canonical
:=
dty
.
CanonicalOnceCBInfo
{
Cycle
:
info
.
Cycle
,
StopHeight
:
info
.
StopHeight
,
StopHash
:
info
.
StopHash
,
Pubkey
:
info
.
Pubkey
,
}
byteCB
,
err
:=
json
.
Marshal
(
&
canonical
)
if
err
!=
nil
{
dposlog
.
Error
(
"marshal CanonicalOnceCBInfo failed"
,
"err"
,
err
)
}
sig
,
err
:=
cs
.
privValidator
.
SignMsg
(
byteCB
)
if
err
!=
nil
{
dposlog
.
Error
(
"SignCBInfo failed."
,
"err"
,
err
)
return
false
}
else
{
info
.
Signature
=
sig
tx
,
err
:=
cs
.
client
.
CreateRecordCBTx
(
info
)
if
err
!=
nil
{
dposlog
.
Error
(
"CreateRecordCBTx failed."
,
"err"
,
err
)
...
...
@@ -718,6 +760,7 @@ func (cs *ConsensusState) SendCBTx(info *dty.DposCBInfo) bool {
return
true
}
// SendRegistVrfMTx method
func
(
cs
*
ConsensusState
)
SendRegistVrfMTx
(
info
*
dty
.
DposVrfMRegist
)
bool
{
tx
,
err
:=
cs
.
client
.
CreateRegVrfMTx
(
info
)
if
err
!=
nil
{
...
...
@@ -740,6 +783,7 @@ func (cs *ConsensusState) SendRegistVrfMTx(info *dty.DposVrfMRegist) bool {
return
true
}
// SendRegistVrfRPTx method
func
(
cs
*
ConsensusState
)
SendRegistVrfRPTx
(
info
*
dty
.
DposVrfRPRegist
)
bool
{
tx
,
err
:=
cs
.
client
.
CreateRegVrfRPTx
(
info
)
if
err
!=
nil
{
...
...
@@ -762,4 +806,272 @@ func (cs *ConsensusState) SendRegistVrfRPTx(info *dty.DposVrfRPRegist) bool {
return
true
}
func
(
cs
*
ConsensusState
)
QueryVrf
(
info
*
dty
.
DposCBInfo
)
bool
{
// QueryVrf method
func
(
cs
*
ConsensusState
)
QueryVrf
(
pubkey
[]
byte
,
cycle
int64
)
(
info
*
dty
.
VrfInfo
,
err
error
)
{
var
pubkeys
[][]
byte
pubkeys
=
append
(
pubkeys
,
pubkey
)
infos
,
err
:=
cs
.
client
.
QueryVrfInfos
(
pubkeys
,
cycle
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
infos
)
>
0
{
info
=
infos
[
0
]
}
return
info
,
nil
}
// InitCycleVrfInfo method
func
(
cs
*
ConsensusState
)
InitCycleVrfInfo
(
task
Task
){
info
,
err
:=
cs
.
QueryVrf
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
(),
task
.
cycle
)
if
err
==
nil
&&
info
!=
nil
{
//cs.cycleBoundaryMap[task.cycle] = info
cs
.
UpdateVrfInfo
(
info
)
return
}
info
,
err
=
cs
.
QueryVrf
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
(),
task
.
cycle
-
1
)
if
err
==
nil
&&
info
!=
nil
{
//cs.cycleBoundaryMap[task.cycle] = info
cs
.
UpdateVrfInfo
(
info
)
}
return
}
// UpdateCBInfo method
func
(
cs
*
ConsensusState
)
UpdateVrfInfo
(
info
*
dty
.
VrfInfo
)
{
valueNumber
:=
len
(
cs
.
vrfInfoMap
)
if
valueNumber
==
0
{
cs
.
vrfInfoMap
[
info
.
Cycle
]
=
info
return
}
oldestCycle
:=
int64
(
0
)
for
k
,
_
:=
range
cs
.
vrfInfoMap
{
if
k
==
info
.
Cycle
{
cs
.
vrfInfoMap
[
info
.
Cycle
]
=
info
return
}
else
{
if
oldestCycle
==
0
{
oldestCycle
=
k
}
else
if
oldestCycle
>
k
{
oldestCycle
=
k
}
}
}
if
valueNumber
>=
5
{
delete
(
cs
.
vrfInfoMap
,
oldestCycle
)
}
cs
.
vrfInfoMap
[
info
.
Cycle
]
=
info
}
// GetCBInfoByCircle method
func
(
cs
*
ConsensusState
)
GetVrfInfoByCircle
(
cycle
int64
,
ty
int
)
(
info
*
dty
.
VrfInfo
)
{
if
v
,
ok
:=
cs
.
vrfInfoMap
[
cycle
];
ok
{
info
=
v
if
VrfQueryTypeM
==
ty
&&
len
(
info
.
M
)
>
0
{
return
info
}
else
if
VrfQueryTypeRP
==
ty
&&
len
(
info
.
M
)
>
0
&&
len
(
info
.
R
)
>
0
&&
len
(
info
.
P
)
>
0
{
return
info
}
}
info
,
err
:=
cs
.
QueryVrf
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
(),
cycle
)
if
err
==
nil
&&
info
!=
nil
{
cs
.
UpdateVrfInfo
(
info
)
return
info
}
return
nil
}
// QueryVrfs method
func
(
cs
*
ConsensusState
)
QueryVrfs
(
set
*
ttypes
.
ValidatorSet
,
cycle
int64
)
(
infos
[]
*
dty
.
VrfInfo
,
err
error
)
{
var
pubkeys
[][]
byte
for
i
:=
0
;
i
<
set
.
Size
();
i
++
{
pubkeys
=
append
(
pubkeys
,
set
.
Validators
[
i
]
.
PubKey
)
}
infos
,
err
=
cs
.
client
.
QueryVrfInfos
(
pubkeys
,
cycle
)
if
err
!=
nil
{
return
nil
,
err
}
return
infos
,
nil
}
// InitCycleVrfInfo method
func
(
cs
*
ConsensusState
)
InitCycleVrfInfos
(
task
Task
){
infos
,
err
:=
cs
.
QueryVrfs
(
cs
.
validatorMgr
.
Validators
,
task
.
cycle
-
1
)
if
err
==
nil
&&
infos
!=
nil
{
//cs.cycleBoundaryMap[task.cycle] = info
cs
.
UpdateVrfInfos
(
task
.
cycle
,
infos
)
}
return
}
// UpdateCBInfo method
func
(
cs
*
ConsensusState
)
UpdateVrfInfos
(
cycle
int64
,
infos
[]
*
dty
.
VrfInfo
)
{
if
len
(
cs
.
validatorMgr
.
Validators
.
Validators
)
!=
len
(
infos
)
{
return
}
for
i
:=
0
;
i
<
len
(
infos
);
i
++
{
if
len
(
infos
[
i
]
.
M
)
==
0
||
len
(
infos
[
i
]
.
R
)
==
0
||
len
(
infos
[
i
]
.
P
)
==
0
{
return
}
}
valueNumber
:=
len
(
cs
.
vrfInfosMap
)
if
valueNumber
==
0
{
cs
.
vrfInfosMap
[
cycle
]
=
infos
return
}
oldestCycle
:=
int64
(
0
)
for
k
,
_
:=
range
cs
.
vrfInfosMap
{
if
k
==
cycle
{
cs
.
vrfInfosMap
[
cycle
]
=
infos
return
}
else
{
if
oldestCycle
==
0
{
oldestCycle
=
k
}
else
if
oldestCycle
>
k
{
oldestCycle
=
k
}
}
}
if
valueNumber
>=
5
{
delete
(
cs
.
vrfInfosMap
,
oldestCycle
)
}
cs
.
vrfInfosMap
[
cycle
]
=
infos
}
// GetVrfInfosByCircle method
func
(
cs
*
ConsensusState
)
GetVrfInfosByCircle
(
cycle
int64
)
(
info
[]
*
dty
.
VrfInfo
)
{
if
v
,
ok
:=
cs
.
vrfInfosMap
[
cycle
];
ok
{
info
=
v
return
info
}
infos
,
err
:=
cs
.
QueryVrfs
(
cs
.
validatorMgr
.
Validators
,
cycle
)
if
err
==
nil
&&
infos
!=
nil
{
cs
.
UpdateVrfInfos
(
cycle
,
infos
)
return
info
}
return
nil
}
// ShuffleValidators method
func
(
cs
*
ConsensusState
)
ShuffleValidators
(
cycle
int64
){
if
cycle
==
cs
.
validatorMgr
.
ShuffleCycle
{
//如果已经洗过牌,则直接返回,不重复洗牌
return
}
infos
:=
cs
.
GetVrfInfosByCircle
(
cycle
-
1
)
if
infos
==
nil
{
cs
.
validatorMgr
.
VrfValidators
=
nil
cs
.
validatorMgr
.
NoVrfValidators
=
nil
cs
.
validatorMgr
.
ShuffleCycle
=
cycle
cs
.
validatorMgr
.
ShuffleType
=
ShuffleTypeNoVrf
return
}
cbInfo
:=
cs
.
GetCBInfoByCircle
(
cycle
-
1
)
if
cbInfo
==
nil
{
cs
.
validatorMgr
.
VrfValidators
=
nil
cs
.
validatorMgr
.
NoVrfValidators
=
nil
cs
.
validatorMgr
.
ShuffleCycle
=
cycle
cs
.
validatorMgr
.
ShuffleType
=
ShuffleTypeNoVrf
return
}
cs
.
validatorMgr
.
LastCycleBoundaryInfo
=
cbInfo
var
vrfValidators
[]
*
ttypes
.
Validator
var
noVrfValidators
[]
*
ttypes
.
Validator
for
i
:=
0
;
i
<
len
(
infos
);
i
++
{
if
isValidVrfInfo
(
infos
[
i
])
{
var
vrfBytes
[]
byte
vrfBytes
=
append
(
vrfBytes
,
[]
byte
(
cbInfo
.
StopHash
)
...
)
vrfBytes
=
append
(
vrfBytes
,
infos
[
i
]
.
R
...
)
item
:=
&
ttypes
.
Validator
{
PubKey
:
infos
[
i
]
.
Pubkey
,
}
item
.
Address
=
crypto
.
Ripemd160
(
vrfBytes
)
vrfValidators
=
append
(
vrfValidators
,
item
)
}
}
set
:=
cs
.
validatorMgr
.
Validators
.
Validators
if
len
(
vrfValidators
)
==
0
{
cs
.
validatorMgr
.
ShuffleCycle
=
cycle
cs
.
validatorMgr
.
ShuffleType
=
ShuffleTypeNoVrf
return
}
else
if
len
(
vrfValidators
)
==
len
(
set
)
{
cs
.
validatorMgr
.
ShuffleCycle
=
cycle
cs
.
validatorMgr
.
ShuffleType
=
ShuffleTypeVrf
cs
.
validatorMgr
.
VrfValidators
=
ttypes
.
NewValidatorSet
(
vrfValidators
)
return
}
cs
.
validatorMgr
.
ShuffleCycle
=
cycle
cs
.
validatorMgr
.
ShuffleType
=
ShuffleTypePartVrf
for
i
:=
0
;
i
<
len
(
set
);
i
++
{
//如果节点信息不在VrfValidators,则说明没有完整的VRF信息,将被放入NoVrfValidators中
if
!
isValidatorExist
(
set
[
i
]
.
PubKey
,
vrfValidators
)
{
item
:=
&
ttypes
.
Validator
{
PubKey
:
set
[
i
]
.
PubKey
,
Address
:
set
[
i
]
.
Address
,
}
noVrfValidators
=
append
(
noVrfValidators
,
item
)
}
}
cs
.
validatorMgr
.
VrfValidators
=
ttypes
.
NewValidatorSet
(
vrfValidators
)
cs
.
validatorMgr
.
NoVrfValidators
=
ttypes
.
NewValidatorSet
(
noVrfValidators
)
}
func
isValidVrfInfo
(
info
*
dty
.
VrfInfo
)
bool
{
if
info
!=
nil
&&
len
(
info
.
M
)
>
0
||
len
(
info
.
R
)
>
0
||
len
(
info
.
P
)
>
0
{
return
true
}
return
false
}
func
isValidatorExist
(
pubkey
[]
byte
,
set
[]
*
ttypes
.
Validator
)
bool
{
for
i
:=
0
;
i
<
len
(
set
);
i
++
{
if
bytes
.
Equal
(
pubkey
,
set
[
i
]
.
PubKey
)
{
return
true
}
}
return
false
}
// VrfEvaluate method
func
(
cs
*
ConsensusState
)
VrfEvaluate
(
input
[]
byte
)(
hash
[
32
]
byte
,
proof
[]
byte
)
{
return
cs
.
privValidator
.
VrfEvaluate
(
input
)
}
// VrfEvaluate method
func
(
cs
*
ConsensusState
)
VrfProof
(
pubkey
[]
byte
,
input
[]
byte
,
hash
[
32
]
byte
,
proof
[]
byte
)
bool
{
return
cs
.
privValidator
.
VrfProof
(
pubkey
,
input
,
hash
,
proof
)
}
\ No newline at end of file
plugin/consensus/dpos/dpos.go
View file @
2cb03695
...
...
@@ -325,7 +325,7 @@ OuterLoop:
// 对于受托节点,才需要初始化区块,启动共识相关程序等,后续支持投票要做成动态切换的。
if
client
.
isDelegator
{
client
.
InitBlock
()
client
.
csState
.
Init
CycleBoundaryInfo
()
client
.
csState
.
Init
()
node
.
Start
()
}
...
...
plugin/consensus/dpos/proto/dpos_msg.proto
View file @
2cb03695
...
...
@@ -3,6 +3,16 @@ syntax = "proto3";
package
types
;
message
CycleBoundaryInfo
{
int64
cycle
=
1
;
int64
stopHeight
=
2
;
string
stopHash
=
3
;
}
message
SuperNode
{
bytes
address
=
1
;
bytes
pubKey
=
2
;
}
message
VoteItem
{
int32
votedNodeIndex
=
1
;
//被投票的节点索引
bytes
votedNodeAddress
=
2
;
//被投票的节点地址
...
...
@@ -13,6 +23,11 @@ message VoteItem {
int64
periodStop
=
7
;
//新节点负责出块的终止时间
int64
height
=
8
;
//新节点负责出块的起始高度
bytes
voteID
=
9
;
//选票ID
CycleBoundaryInfo
lastCBInfo
=
10
;
int64
shuffleType
=
11
;
repeated
SuperNode
validators
=
12
;
repeated
SuperNode
vrfValidators
=
13
;
repeated
SuperNode
noVrfValidators
=
14
;
}
//DPosVote Dpos共识的节点投票,为达成共识用。
...
...
plugin/consensus/dpos/state_machine.go
View file @
2cb03695
...
...
@@ -76,49 +76,23 @@ func DecideTaskByTime(now int64) (task Task) {
return
task
}
// State is the base class of dpos state machine, it defines some interfaces.
type
State
interface
{
timeOut
(
cs
*
ConsensusState
)
sendVote
(
cs
*
ConsensusState
,
vote
*
dpostype
.
DPosVote
)
recvVote
(
cs
*
ConsensusState
,
vote
*
dpostype
.
DPosVote
)
sendVoteReply
(
cs
*
ConsensusState
,
reply
*
dpostype
.
DPosVoteReply
)
recvVoteReply
(
cs
*
ConsensusState
,
reply
*
dpostype
.
DPosVoteReply
)
sendNotify
(
cs
*
ConsensusState
,
notify
*
dpostype
.
DPosNotify
)
recvNotify
(
cs
*
ConsensusState
,
notify
*
dpostype
.
DPosNotify
)
//sendCBInfo(cs *ConsensusState, info *dty.DposCBInfo)
recvCBInfo
(
cs
*
ConsensusState
,
info
*
dty
.
DposCBInfo
)
}
// InitState is the initial state of dpos state machine
type
InitState
struct
{
}
func
(
init
*
InitState
)
timeOut
(
cs
*
ConsensusState
)
{
//if available noes < 2/3, don't change the state to voting.
connections
:=
cs
.
client
.
node
.
peerSet
.
Size
()
validators
:=
cs
.
validatorMgr
.
Validators
.
Size
()
if
connections
==
0
||
connections
<
(
validators
*
2
/
3
-
1
)
{
dposlog
.
Error
(
"InitState timeout but available nodes less than 2/3,waiting for more connections"
,
"connections"
,
connections
,
"validators"
,
validators
)
cs
.
ClearVotes
()
//设定超时时间,超时后再检查链接数量
cs
.
scheduleDPosTimeout
(
time
.
Duration
(
timeoutCheckConnections
)
*
time
.
Millisecond
,
InitStateType
)
}
else
{
func
generateVote
(
cs
*
ConsensusState
)
*
dpostype
.
Vote
{
//获得当前高度
height
:=
cs
.
client
.
GetCurrentHeight
()
now
:=
time
.
Now
()
.
Unix
()
if
cs
.
lastMyVote
!=
nil
&&
math
.
Abs
(
float64
(
now
-
cs
.
lastMyVote
.
VoteItem
.
PeriodStop
))
<=
1
{
if
cs
.
lastMyVote
!=
nil
&&
math
.
Abs
(
float64
(
now
-
cs
.
lastMyVote
.
VoteItem
.
PeriodStop
))
<=
1
{
now
+=
2
}
//计算当前时间,属于哪一个周期,应该哪一个节点出块,应该出块的高度
task
:=
DecideTaskByTime
(
now
)
addr
,
validator
:=
cs
.
validatorMgr
.
Validators
.
GetByIndex
(
int
(
task
.
nodeID
))
cs
.
ShuffleValidators
(
task
.
cycle
)
addr
,
validator
:=
cs
.
validatorMgr
.
GetValidatorByIndex
(
int
(
task
.
nodeID
))
if
addr
==
nil
&&
validator
==
nil
{
dposlog
.
Error
(
"Address and Validator is nil"
,
"node index"
,
task
.
nodeID
,
"now"
,
now
,
"cycle"
,
dposCycle
,
"period"
,
dposPeriod
)
//cs.SetState(InitStateObj)
cs
.
scheduleDPosTimeout
(
time
.
Duration
(
timeoutCheckConnections
)
*
time
.
Millisecond
,
InitStateType
)
return
//cs.scheduleDPosTimeout(time.Duration(timeoutCheckConnections)*time.Millisecond, InitStateType)
return
nil
}
//生成vote, 对于vote进行签名
...
...
@@ -132,29 +106,23 @@ func (init *InitState) timeOut(cs *ConsensusState) {
PeriodStop
:
task
.
periodStop
,
Height
:
height
+
1
,
}
cs
.
validatorMgr
.
FillVoteItem
(
voteItem
)
encode
,
err
:=
json
.
Marshal
(
voteItem
)
if
err
!=
nil
{
panic
(
"Marshal vote failed."
)
//cs.scheduleDPosTimeout(time.Duration(timeoutCheckConnections)*time.Millisecond, InitStateType)
//return
}
voteItem
.
VoteID
=
crypto
.
Ripemd160
(
encode
)
index
:=
-
1
for
i
:=
0
;
i
<
cs
.
validatorMgr
.
Validators
.
Size
();
i
++
{
if
bytes
.
Equal
(
cs
.
validatorMgr
.
Validators
.
Validators
[
i
]
.
Address
,
cs
.
privValidator
.
GetAddress
())
{
index
=
i
break
}
}
index
:=
cs
.
validatorMgr
.
GetIndexByPubKey
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
())
if
index
==
-
1
{
panic
(
"This node's address is not exist in Validators."
)
}
vote
:=
&
dpostype
.
Vote
{
DPosVote
:
&
dpostype
.
DPosVote
{
vote
:=
&
dpostype
.
Vote
{
DPosVote
:
&
dpostype
.
DPosVote
{
VoteItem
:
voteItem
,
VoteTimestamp
:
now
,
VoterNodeAddress
:
cs
.
privValidator
.
GetAddress
(),
...
...
@@ -162,9 +130,79 @@ func (init *InitState) timeOut(cs *ConsensusState) {
},
}
return
vote
}
func
checkVrf
(
cs
*
ConsensusState
)
{
now
:=
time
.
Now
()
.
Unix
()
task
:=
DecideTaskByTime
(
now
)
middleTime
:=
task
.
cycleStart
+
(
task
.
cycleStop
-
task
.
cycleStart
)
/
2
if
now
<
middleTime
{
info
:=
cs
.
GetVrfInfoByCircle
(
task
.
cycle
,
VrfQueryTypeM
)
if
info
==
nil
{
vrfM
:=
&
dty
.
DposVrfMRegist
{
Pubkey
:
hex
.
EncodeToString
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
()),
Cycle
:
task
.
cycle
,
M
:
cs
.
currentVote
.
LastCBInfo
.
StopHash
,
}
cs
.
SendRegistVrfMTx
(
vrfM
)
}
}
else
{
info
:=
cs
.
GetVrfInfoByCircle
(
task
.
cycle
,
VrfQueryTypeRP
)
if
info
!=
nil
&&
len
(
info
.
M
)
>
0
&&
(
len
(
info
.
R
)
==
0
||
len
(
info
.
P
)
==
0
){
hash
,
proof
:=
cs
.
VrfEvaluate
(
info
.
M
)
vrfRP
:=
&
dty
.
DposVrfRPRegist
{
Pubkey
:
hex
.
EncodeToString
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
()),
Cycle
:
task
.
cycle
,
R
:
hex
.
EncodeToString
(
hash
[
:
]),
P
:
hex
.
EncodeToString
(
proof
),
}
cs
.
SendRegistVrfRPTx
(
vrfRP
)
}
}
}
// State is the base class of dpos state machine, it defines some interfaces.
type
State
interface
{
timeOut
(
cs
*
ConsensusState
)
sendVote
(
cs
*
ConsensusState
,
vote
*
dpostype
.
DPosVote
)
recvVote
(
cs
*
ConsensusState
,
vote
*
dpostype
.
DPosVote
)
sendVoteReply
(
cs
*
ConsensusState
,
reply
*
dpostype
.
DPosVoteReply
)
recvVoteReply
(
cs
*
ConsensusState
,
reply
*
dpostype
.
DPosVoteReply
)
sendNotify
(
cs
*
ConsensusState
,
notify
*
dpostype
.
DPosNotify
)
recvNotify
(
cs
*
ConsensusState
,
notify
*
dpostype
.
DPosNotify
)
//sendCBInfo(cs *ConsensusState, info *dty.DposCBInfo)
recvCBInfo
(
cs
*
ConsensusState
,
info
*
dty
.
DposCBInfo
)
}
// InitState is the initial state of dpos state machine
type
InitState
struct
{
}
func
(
init
*
InitState
)
timeOut
(
cs
*
ConsensusState
)
{
//if available noes < 2/3, don't change the state to voting.
connections
:=
cs
.
client
.
node
.
peerSet
.
Size
()
validators
:=
cs
.
validatorMgr
.
Validators
.
Size
()
if
connections
==
0
||
connections
<
(
validators
*
2
/
3
-
1
)
{
dposlog
.
Error
(
"InitState timeout but available nodes less than 2/3,waiting for more connections"
,
"connections"
,
connections
,
"validators"
,
validators
)
cs
.
ClearVotes
()
//设定超时时间,超时后再检查链接数量
cs
.
scheduleDPosTimeout
(
time
.
Duration
(
timeoutCheckConnections
)
*
time
.
Millisecond
,
InitStateType
)
}
else
{
vote
:=
generateVote
(
cs
)
if
nil
==
vote
{
cs
.
scheduleDPosTimeout
(
time
.
Duration
(
timeoutCheckConnections
)
*
time
.
Millisecond
,
InitStateType
)
return
}
if
err
:=
cs
.
privValidator
.
SignVote
(
cs
.
validatorMgr
.
ChainID
,
vote
);
err
!=
nil
{
dposlog
.
Error
(
"SignVote failed"
,
"vote"
,
vote
.
String
())
//cs.SetState(InitStateObj)
cs
.
scheduleDPosTimeout
(
time
.
Duration
(
timeoutCheckConnections
)
*
time
.
Millisecond
,
InitStateType
)
return
}
...
...
@@ -279,6 +317,14 @@ func (voting *VotingState) recvVote(cs *ConsensusState, vote *dpostype.DPosVote)
cs
.
SetCurrentVote
(
voteItem
)
//检查最终投票是否与自己的投票一致,如果不一致,需要更新本地的信息,保证各节点共识结果执行一致。
if
!
bytes
.
Equal
(
cs
.
myVote
.
VoteItem
.
VoteID
,
voteItem
.
VoteID
)
{
if
!
cs
.
validatorMgr
.
UpdateFromVoteItem
(
voteItem
)
{
panic
(
"This node's validators are not the same with final vote, please check"
)
}
}
//进行VRF相关处理
checkVrf
(
cs
)
//1s后检查是否出块,是否需要重新投票
cs
.
scheduleDPosTimeout
(
time
.
Millisecond
*
500
,
VotedStateType
)
}
else
if
result
==
continueToVote
{
...
...
@@ -330,6 +376,15 @@ func (voted *VotedState) timeOut(cs *ConsensusState) {
if
bytes
.
Equal
(
cs
.
privValidator
.
GetAddress
(),
cs
.
currentVote
.
VotedNodeAddress
)
{
//当前节点为出块节点
//如果区块未同步,则等待;如果区块已同步,则进行后续正常出块的判断和处理。
if
block
.
Height
+
1
<
cs
.
currentVote
.
Height
{
dposlog
.
Info
(
"VotedState timeOut but block is not sync,wait..."
,
"localHeight"
,
block
.
Height
,
"vote height"
,
cs
.
currentVote
.
Height
)
cs
.
scheduleDPosTimeout
(
time
.
Second
*
1
,
VotedStateType
)
return
}
//时间到了节点切换时刻
if
now
>=
cs
.
currentVote
.
PeriodStop
{
//当前时间超过了节点切换时间,需要进行重新投票
dposlog
.
Info
(
"VotedState timeOut over periodStop."
,
"periodStop"
,
cs
.
currentVote
.
PeriodStop
)
...
...
@@ -344,28 +399,7 @@ func (voted *VotedState) timeOut(cs *ConsensusState) {
StopHash
:
hex
.
EncodeToString
(
block
.
Hash
()),
Pubkey
:
hex
.
EncodeToString
(
cs
.
privValidator
.
GetPubKey
()
.
Bytes
()),
}
/*
err := cs.privValidator.SignCBInfo(info)
if err != nil {
dposlog.Error("SignCBInfo failed.", "err", err)
} else {
tx, err := cs.client.CreateRecordCBTx(info)
if err != nil {
dposlog.Error("CreateRecordCBTx failed.", "err", err)
}else {
cs.privValidator.SignTx(tx)
dposlog.Info("Sign RecordCBTx.")
//将交易发往交易池中,方便后续重启或者新加入的超级节点查询
msg := cs.client.GetQueueClient().NewMessage("mempool", types.EventTx, tx)
err = cs.client.GetQueueClient().Send(msg, false)
if err != nil {
dposlog.Error("Send RecordCBTx to mempool failed.", "err", err)
} else {
dposlog.Error("Send RecordCBTx to mempool ok.", "err", err)
}
}
}
*/
cs
.
SendCBTx
(
info
)
info2
:=
&
dty
.
DposCBInfo
{
Cycle
:
info
.
Cycle
,
...
...
@@ -417,12 +451,6 @@ func (voted *VotedState) timeOut(cs *ConsensusState) {
cs
.
scheduleDPosTimeout
(
time
.
Duration
(
timeoutCheckConnections
)
*
time
.
Millisecond
,
InitStateType
)
return
}
//如果区块未同步,则等待;如果区块已同步,则进行后续正常出块的判断和处理。
if
block
.
Height
+
1
<
cs
.
currentVote
.
Height
{
dposlog
.
Info
(
"VotedState timeOut but block is not sync,wait..."
,
"localHeight"
,
block
.
Height
,
"vote height"
,
cs
.
currentVote
.
Height
)
cs
.
scheduleDPosTimeout
(
time
.
Second
*
1
,
VotedStateType
)
return
}
//当前时间未到节点切换时间,则继续进行出块判断
if
block
.
BlockTime
>=
task
.
blockStop
{
...
...
@@ -457,6 +485,8 @@ func (voted *VotedState) timeOut(cs *ConsensusState) {
}
else
{
dposlog
.
Info
(
"This node is not current owner."
,
"current owner index"
,
cs
.
currentVote
.
VotedNodeIndex
,
"this node index"
,
cs
.
client
.
ValidatorIndex
())
//根据时间进行vrf相关处理,如果在(cyclestart,middle)之间,发布M,如果在(middle,cyclestop)之间,发布R、P
checkVrf
(
cs
)
//非当前出块节点,如果到了切换出块节点的时间,则进行状态切换,进行投票
if
now
>=
cs
.
currentVote
.
PeriodStop
{
//当前时间超过了节点切换时间,需要进行重新投票
...
...
plugin/consensus/dpos/types/dpos_msg.pb.go
View file @
2cb03695
...
...
@@ -8,6 +8,8 @@ It is generated from these files:
dpos_msg.proto
It has these top-level messages:
CycleBoundaryInfo
SuperNode
VoteItem
DPosVote
DPosVoteReply
...
...
@@ -30,6 +32,62 @@ var _ = math.Inf
// proto package needs to be updated.
const
_
=
proto
.
ProtoPackageIsVersion2
// please upgrade the proto package
type
CycleBoundaryInfo
struct
{
Cycle
int64
`protobuf:"varint,1,opt,name=cycle" json:"cycle,omitempty"`
StopHeight
int64
`protobuf:"varint,2,opt,name=stopHeight" json:"stopHeight,omitempty"`
StopHash
string
`protobuf:"bytes,3,opt,name=stopHash" json:"stopHash,omitempty"`
}
func
(
m
*
CycleBoundaryInfo
)
Reset
()
{
*
m
=
CycleBoundaryInfo
{}
}
func
(
m
*
CycleBoundaryInfo
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
CycleBoundaryInfo
)
ProtoMessage
()
{}
func
(
*
CycleBoundaryInfo
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
0
}
}
func
(
m
*
CycleBoundaryInfo
)
GetCycle
()
int64
{
if
m
!=
nil
{
return
m
.
Cycle
}
return
0
}
func
(
m
*
CycleBoundaryInfo
)
GetStopHeight
()
int64
{
if
m
!=
nil
{
return
m
.
StopHeight
}
return
0
}
func
(
m
*
CycleBoundaryInfo
)
GetStopHash
()
string
{
if
m
!=
nil
{
return
m
.
StopHash
}
return
""
}
type
SuperNode
struct
{
Address
[]
byte
`protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
PubKey
[]
byte
`protobuf:"bytes,2,opt,name=pubKey,proto3" json:"pubKey,omitempty"`
}
func
(
m
*
SuperNode
)
Reset
()
{
*
m
=
SuperNode
{}
}
func
(
m
*
SuperNode
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
SuperNode
)
ProtoMessage
()
{}
func
(
*
SuperNode
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
1
}
}
func
(
m
*
SuperNode
)
GetAddress
()
[]
byte
{
if
m
!=
nil
{
return
m
.
Address
}
return
nil
}
func
(
m
*
SuperNode
)
GetPubKey
()
[]
byte
{
if
m
!=
nil
{
return
m
.
PubKey
}
return
nil
}
type
VoteItem
struct
{
VotedNodeIndex
int32
`protobuf:"varint,1,opt,name=votedNodeIndex" json:"votedNodeIndex,omitempty"`
VotedNodeAddress
[]
byte
`protobuf:"bytes,2,opt,name=votedNodeAddress,proto3" json:"votedNodeAddress,omitempty"`
...
...
@@ -40,12 +98,17 @@ type VoteItem struct {
PeriodStop
int64
`protobuf:"varint,7,opt,name=periodStop" json:"periodStop,omitempty"`
Height
int64
`protobuf:"varint,8,opt,name=height" json:"height,omitempty"`
VoteID
[]
byte
`protobuf:"bytes,9,opt,name=voteID,proto3" json:"voteID,omitempty"`
LastCBInfo
*
CycleBoundaryInfo
`protobuf:"bytes,10,opt,name=lastCBInfo" json:"lastCBInfo,omitempty"`
ShuffleType
int64
`protobuf:"varint,11,opt,name=shuffleType" json:"shuffleType,omitempty"`
Validators
[]
*
SuperNode
`protobuf:"bytes,12,rep,name=validators" json:"validators,omitempty"`
VrfValidators
[]
*
SuperNode
`protobuf:"bytes,13,rep,name=vrfValidators" json:"vrfValidators,omitempty"`
NoVrfValidators
[]
*
SuperNode
`protobuf:"bytes,14,rep,name=noVrfValidators" json:"noVrfValidators,omitempty"`
}
func
(
m
*
VoteItem
)
Reset
()
{
*
m
=
VoteItem
{}
}
func
(
m
*
VoteItem
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
VoteItem
)
ProtoMessage
()
{}
func
(
*
VoteItem
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
0
}
}
func
(
*
VoteItem
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
2
}
}
func
(
m
*
VoteItem
)
GetVotedNodeIndex
()
int32
{
if
m
!=
nil
{
...
...
@@ -110,6 +173,41 @@ func (m *VoteItem) GetVoteID() []byte {
return
nil
}
func
(
m
*
VoteItem
)
GetLastCBInfo
()
*
CycleBoundaryInfo
{
if
m
!=
nil
{
return
m
.
LastCBInfo
}
return
nil
}
func
(
m
*
VoteItem
)
GetShuffleType
()
int64
{
if
m
!=
nil
{
return
m
.
ShuffleType
}
return
0
}
func
(
m
*
VoteItem
)
GetValidators
()
[]
*
SuperNode
{
if
m
!=
nil
{
return
m
.
Validators
}
return
nil
}
func
(
m
*
VoteItem
)
GetVrfValidators
()
[]
*
SuperNode
{
if
m
!=
nil
{
return
m
.
VrfValidators
}
return
nil
}
func
(
m
*
VoteItem
)
GetNoVrfValidators
()
[]
*
SuperNode
{
if
m
!=
nil
{
return
m
.
NoVrfValidators
}
return
nil
}
// DPosVote Dpos共识的节点投票,为达成共识用。
type
DPosVote
struct
{
VoteItem
*
VoteItem
`protobuf:"bytes,1,opt,name=voteItem" json:"voteItem,omitempty"`
...
...
@@ -122,7 +220,7 @@ type DPosVote struct {
func
(
m
*
DPosVote
)
Reset
()
{
*
m
=
DPosVote
{}
}
func
(
m
*
DPosVote
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
DPosVote
)
ProtoMessage
()
{}
func
(
*
DPosVote
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
1
}
}
func
(
*
DPosVote
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
3
}
}
func
(
m
*
DPosVote
)
GetVoteItem
()
*
VoteItem
{
if
m
!=
nil
{
...
...
@@ -166,7 +264,7 @@ type DPosVoteReply struct {
func
(
m
*
DPosVoteReply
)
Reset
()
{
*
m
=
DPosVoteReply
{}
}
func
(
m
*
DPosVoteReply
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
DPosVoteReply
)
ProtoMessage
()
{}
func
(
*
DPosVoteReply
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
2
}
}
func
(
*
DPosVoteReply
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
4
}
}
func
(
m
*
DPosVoteReply
)
GetVote
()
*
DPosVote
{
if
m
!=
nil
{
...
...
@@ -189,7 +287,7 @@ type DPosNotify struct {
func
(
m
*
DPosNotify
)
Reset
()
{
*
m
=
DPosNotify
{}
}
func
(
m
*
DPosNotify
)
String
()
string
{
return
proto
.
CompactTextString
(
m
)
}
func
(
*
DPosNotify
)
ProtoMessage
()
{}
func
(
*
DPosNotify
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
3
}
}
func
(
*
DPosNotify
)
Descriptor
()
([]
byte
,
[]
int
)
{
return
fileDescriptor0
,
[]
int
{
5
}
}
func
(
m
*
DPosNotify
)
GetVote
()
*
VoteItem
{
if
m
!=
nil
{
...
...
@@ -241,6 +339,8 @@ func (m *DPosNotify) GetSignature() []byte {
}
func
init
()
{
proto
.
RegisterType
((
*
CycleBoundaryInfo
)(
nil
),
"types.CycleBoundaryInfo"
)
proto
.
RegisterType
((
*
SuperNode
)(
nil
),
"types.SuperNode"
)
proto
.
RegisterType
((
*
VoteItem
)(
nil
),
"types.VoteItem"
)
proto
.
RegisterType
((
*
DPosVote
)(
nil
),
"types.DPosVote"
)
proto
.
RegisterType
((
*
DPosVoteReply
)(
nil
),
"types.DPosVoteReply"
)
...
...
@@ -250,30 +350,40 @@ func init() {
func
init
()
{
proto
.
RegisterFile
(
"dpos_msg.proto"
,
fileDescriptor0
)
}
var
fileDescriptor0
=
[]
byte
{
// 396 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0x74
,
0x93
,
0xdd
,
0x6a
,
0xdb
,
0x30
,
0x14
,
0xc7
,
0x71
,
0x1c
,
0x3b
,
0xce
,
0xc9
,
0xd7
,
0x26
,
0xc6
,
0x10
,
0x63
,
0x0c
,
0xe3
,
0x8d
,
0x61
,
0xb6
,
0x91
,
0x8b
,
0x6d
,
0x2f
,
0x30
,
0xc8
,
0x4d
,
0x6e
,
0xc2
,
0x70
,
0x4b
,
0x6f
,
0x8b
,
0x1b
,
0xab
,
0xb1
,
0x21
,
0x8e
,
0x84
,
0xa4
,
0x86
,
0xe6
,
0x21
,
0xfa
,
0x16
,
0x7d
,
0x9f
,
0xbe
,
0x52
,
0xd1
,
0xf1
,
0x87
,
0x1c
,
0x87
,
0xde
,
0xe9
,
0xfc
,
0xfe
,
0xd2
,
0x51
,
0xce
,
0x4f
,
0x31
,
0xcc
,
0x33
,
0xc1
,
0xd5
,
0x6d
,
0xa9
,
0x76
,
0x4b
,
0x21
,
0xb9
,
0xe6
,
0xc4
,
0xd3
,
0x27
,
0xc1
,
0x54
,
0xf4
,
0x3c
,
0x80
,
0xe0
,
0x86
,
0x6b
,
0xb6
,
0xd6
,
0xac
,
0x24
,
0xdf
,
0x61
,
0x7e
,
0xe4
,
0x9a
,
0x65
,
0x1b
,
0x9e
,
0xb1
,
0xf5
,
0x21
,
0x63
,
0x8f
,
0xd4
,
0x09
,
0x9d
,
0xd8
,
0x4b
,
0x7a
,
0x94
,
0xfc
,
0x80
,
0x77
,
0x2d
,
0xf9
,
0x97
,
0x65
,
0x92
,
0x29
,
0x45
,
0x07
,
0xa1
,
0x13
,
0x4f
,
0x93
,
0x0b
,
0x4e
,
0x3e
,
0x80
,
0xb7
,
0x3d
,
0x6d
,
0xf7
,
0x8c
,
0xba
,
0xa1
,
0x13
,
0xbb
,
0x49
,
0x55
,
0x90
,
0x2f
,
0x00
,
0xb8
,
0xb8
,
0xd2
,
0xa9
,
0xd4
,
0x74
,
0x88
,
0x51
,
0x87
,
0x90
,
0xcf
,
0x30
,
0xae
,
0x2b
,
0x2e
,
0xa8
,
0x87
,
0xb1
,
0x05
,
0x24
,
0x84
,
0x89
,
0x60
,
0xb2
,
0xe0
,
0x59
,
0x75
,
0xdc
,
0xc7
,
0xbc
,
0x8b
,
0x4c
,
0xff
,
0xa6
,
0xe4
,
0x82
,
0x8e
,
0xaa
,
0xfe
,
0x96
,
0x90
,
0x8f
,
0xe0
,
0xe7
,
0xac
,
0xd8
,
0xe5
,
0x9a
,
0x06
,
0x98
,
0xd5
,
0x95
,
0xe1
,
0x66
,
0x82
,
0xf5
,
0x8a
,
0x8e
,
0x71
,
0x9e
,
0xba
,
0x8a
,
0x5e
,
0x1c
,
0x08
,
0x56
,
0xff
,
0xb9
,
0x32
,
0xaa
,
0xc8
,
0x4f
,
0x08
,
0x8e
,
0xb5
,
0x32
,
0x14
,
0x34
,
0xf9
,
0xbd
,
0x58
,
0xa2
,
0xcd
,
0x65
,
0x63
,
0x32
,
0x69
,
0x37
,
0x90
,
0x6f
,
0x30
,
0x33
,
0xeb
,
0xeb
,
0xa2
,
0x64
,
0x4a
,
0xa7
,
0xa5
,
0x40
,
0x51
,
0x6e
,
0x72
,
0x0e
,
0x1b
,
0xf3
,
0xd2
,
0x9a
,
0x77
,
0xad
,
0x79
,
0x79
,
0x61
,
0x5e
,
0x76
,
0xcd
,
0x0f
,
0xad
,
0xf9
,
0x2e
,
0x37
,
0x0e
,
0x55
,
0xb1
,
0x3b
,
0xa4
,
0xfa
,
0x41
,
0x32
,
0x74
,
0x38
,
0x4d
,
0x2c
,
0x88
,
0xfe
,
0xc2
,
0xac
,
0x19
,
0x28
,
0x61
,
0x62
,
0x7f
,
0x22
,
0x5f
,
0x61
,
0x68
,
0x5a
,
0xf4
,
0x26
,
0x6a
,
0xf7
,
0x60
,
0x18
,
0x3d
,
0x0d
,
0x00
,
0x0c
,
0xda
,
0x70
,
0x5d
,
0xdc
,
0xbf
,
0x75
,
0xa6
,
0xb5
,
0x80
,
0xa1
,
0x79
,
0x8b
,
0xca
,
0x2e
,
0xbe
,
0x45
,
0x35
,
0x7e
,
0x87
,
0x90
,
0x4f
,
0x10
,
0xe4
,
0xa9
,
0xca
,
0x31
,
0x75
,
0xf1
,
0x67
,
0xb6
,
0x35
,
0x89
,
0x61
,
0x71
,
0xc0
,
0xab
,
0xac
,
0xbf
,
0xea
,
0xcf
,
0xd2
,
0xc7
,
0x76
,
0xa7
,
0x55
,
0xe8
,
0xa1
,
0xc2
,
0x3e
,
0x26
,
0xbf
,
0xe0
,
0xbd
,
0x45
,
0x8d
,
0x44
,
0x1f
,
0x2f
,
0xbe
,
0x0c
,
0xce
,
0x2d
,
0x8e
,
0x7a
,
0x16
,
0xef
,
0x7c
,
0xfc
,
0x98
,
0xfe
,
0xbc
,
0x06
,
0x00
,
0x00
,
0xff
,
0xff
,
0x98
,
0x0c
,
0x28
,
0xf0
,
0x5e
,
0x03
,
0x00
,
0x00
,
// 558 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0x74
,
0x54
,
0xdd
,
0x8a
,
0x13
,
0x31
,
0x14
,
0xa6
,
0x3b
,
0xfd
,
0x3d
,
0xfd
,
0xd9
,
0xdd
,
0x20
,
0x12
,
0x44
,
0xa4
,
0x8c
,
0x22
,
0x45
,
0xa5
,
0x48
,
0x15
,
0x11
,
0xc1
,
0x0b
,
0x77
,
0xf7
,
0xc2
,
0x22
,
0x2c
,
0x32
,
0xbb
,
0xf4
,
0x56
,
0xb2
,
0x3b
,
0x69
,
0x67
,
0xa0
,
0x6d
,
0x42
,
0x92
,
0x16
,
0xe7
,
0x21
,
0x7c
,
0x0d
,
0x5f
,
0xc7
,
0x57
,
0x92
,
0x9c
,
0xcc
,
0x4c
,
0xa6
,
0x53
,
0x7a
,
0x37
,
0xdf
,
0x77
,
0x7e
,
0x92
,
0xf3
,
0x9d
,
0x2f
,
0x03
,
0xa3
,
0x58
,
0x0a
,
0xfd
,
0x6b
,
0xa3
,
0x57
,
0x53
,
0xa9
,
0x84
,
0x11
,
0xa4
,
0x65
,
0x32
,
0xc9
,
0x75
,
0xc8
,
0xe1
,
0xf2
,
0x3a
,
0x7b
,
0x5c
,
0xf3
,
0x2b
,
0xb1
,
0xdb
,
0xc6
,
0x4c
,
0x65
,
0xf3
,
0xed
,
0x52
,
0x90
,
0x27
,
0xd0
,
0x7a
,
0xb4
,
0x24
,
0x6d
,
0x8c
,
0x1b
,
0x93
,
0x20
,
0x72
,
0x80
,
0xbc
,
0x00
,
0xd0
,
0x46
,
0xc8
,
0xef
,
0x3c
,
0x5d
,
0x25
,
0x86
,
0x9e
,
0x61
,
0xa8
,
0xc2
,
0x90
,
0x67
,
0xd0
,
0x45
,
0xc4
,
0x74
,
0x42
,
0x83
,
0x71
,
0x63
,
0xd2
,
0x8b
,
0x4a
,
0x1c
,
0x7e
,
0x85
,
0xde
,
0xdd
,
0x4e
,
0x72
,
0x75
,
0x2b
,
0x62
,
0x4e
,
0x28
,
0x74
,
0x58
,
0x1c
,
0x2b
,
0xae
,
0x35
,
0x1e
,
0x30
,
0x88
,
0x0a
,
0x48
,
0x9e
,
0x42
,
0x5b
,
0xee
,
0x1e
,
0x7e
,
0xf0
,
0x0c
,
0xdb
,
0x0f
,
0xa2
,
0x1c
,
0x85
,
0x7f
,
0x9b
,
0xd0
,
0x5d
,
0x08
,
0xc3
,
0xe7
,
0x86
,
0x6f
,
0xc8
,
0x6b
,
0x18
,
0xed
,
0x85
,
0xe1
,
0xb1
,
0xed
,
0x35
,
0xdf
,
0xc6
,
0xfc
,
0x37
,
0x76
,
0x69
,
0x45
,
0x35
,
0x96
,
0xbc
,
0x81
,
0x8b
,
0x92
,
0xf9
,
0x96
,
0x9f
,
0xe7
,
0xda
,
0x1e
,
0xf1
,
0x7e
,
0xe2
,
0xa0
,
0x36
,
0x31
,
0x7e
,
0xdc
,
0x19
,
0xa6
,
0x0c
,
0x6d
,
0xba
,
0x89
,
0x3d
,
0x43
,
0x9e
,
0x43
,
0x2f
,
0x47
,
0x42
,
0xd2
,
0x16
,
0x86
,
0x3d
,
0x41
,
0xc6
,
0xd0
,
0x97
,
0x5c
,
0xa5
,
0x22
,
0x76
,
0xe5
,
0x6d
,
0x8c
,
0x57
,
0x29
,
0xdb
,
0xbf
,
0x80
,
0x42
,
0xd2
,
0x8e
,
0xeb
,
0xef
,
0x19
,
0x2b
,
0x47
,
0xe2
,
0xd4
,
0xee
,
0x62
,
0x2c
,
0x47
,
0x96
,
0xb7
,
0x13
,
0xcc
,
0x6f
,
0x68
,
0xcf
,
0xc9
,
0xe4
,
0x10
,
0xf9
,
0x0c
,
0xb0
,
0x66
,
0xda
,
0x5c
,
0x5f
,
0xd9
,
0x2d
,
0x52
,
0x18
,
0x37
,
0x26
,
0xfd
,
0x19
,
0x9d
,
0xe2
,
0xa2
,
0xa7
,
0x47
,
0x5b
,
0x8e
,
0x2a
,
0xb9
,
0xf6
,
0xae
,
0x3a
,
0xd9
,
0x2d
,
0x97
,
0x6b
,
0x7e
,
0x9f
,
0x49
,
0x4e
,
0xfb
,
0xee
,
0xae
,
0x15
,
0x8a
,
0xbc
,
0x07
,
0xd8
,
0xb3
,
0x75
,
0x1a
,
0x33
,
0x23
,
0x94
,
0xa6
,
0x83
,
0x71
,
0x30
,
0xe9
,
0xcf
,
0x2e
,
0xf2
,
0xde
,
0xe5
,
0x6a
,
0xa3
,
0x4a
,
0x0e
,
0xf9
,
0x04
,
0xc3
,
0xbd
,
0x5a
,
0x2e
,
0x7c
,
0xd1
,
0xf0
,
0x44
,
0xd1
,
0x61
,
0x1a
,
0xf9
,
0x02
,
0xe7
,
0x5b
,
0xb1
,
0x38
,
0xa8
,
0x1c
,
0x9d
,
0xa8
,
0xac
,
0x27
,
0x86
,
0xff
,
0x1a
,
0xd0
,
0xbd
,
0xf9
,
0x29
,
0xb4
,
0x35
,
0x0b
,
0x79
,
0x0b
,
0xdd
,
0x7d
,
0x6e
,
0x1a
,
0xb4
,
0x48
,
0x7f
,
0x76
,
0x9e
,
0x77
,
0x28
,
0xbc
,
0x14
,
0x95
,
0x09
,
0xe4
,
0x15
,
0x0c
,
0xed
,
0xf7
,
0x7d
,
0xba
,
0xe1
,
0xda
,
0xb0
,
0x8d
,
0xcc
,
0x0d
,
0x7e
,
0x48
,
0x16
,
0xde
,
0x53
,
0xde
,
0x7b
,
0x81
,
0xf7
,
0x9e
,
0x3a
,
0xf2
,
0x9e
,
0xaa
,
0x7a
,
0xaf
,
0xe9
,
0xbd
,
0x57
,
0xe5
,
0xad
,
0x8b
,
0x74
,
0xba
,
0xda
,
0x32
,
0xb3
,
0x53
,
0x1c
,
0x5d
,
0x34
,
0x88
,
0x3c
,
0x11
,
0x7e
,
0x84
,
0x61
,
0x31
,
0x50
,
0xc4
,
0xe5
,
0x3a
,
0x23
,
0x2f
,
0xa1
,
0x69
,
0x5b
,
0xd4
,
0x26
,
0x2a
,
0x73
,
0x30
,
0x18
,
0xfe
,
0x39
,
0x03
,
0xb0
,
0xd4
,
0xad
,
0x30
,
0xe9
,
0xf2
,
0x54
,
0x4d
,
0xa9
,
0x02
,
0x06
,
0xad
,
0x1b
,
0x9d
,
0xbf
,
0xd0
,
0x8d
,
0xf9
,
0xfb
,
0xf6
,
0x8c
,
0x7d
,
0xdf
,
0x09
,
0xd3
,
0x09
,
0x46
,
0x03
,
0xbc
,
0x66
,
0x89
,
0xc9
,
0xc4
,
0xee
,
0xcc
,
0x1e
,
0xe5
,
0xf5
,
0x73
,
0xcf
,
0xa5
,
0x4e
,
0xfb
,
0x4c
,
0x2f
,
0x61
,
0x0b
,
0x25
,
0xac
,
0xd3
,
0xe4
,
0x1d
,
0x5c
,
0x7a
,
0xaa
,
0x10
,
0xb1
,
0x8d
,
0x07
,
0x1f
,
0x07
,
0x0e
,
0x55
,
0xec
,
0xd4
,
0x54
,
0x7c
,
0x68
,
0xe3
,
0x4f
,
0xef
,
0xc3
,
0xff
,
0x00
,
0x00
,
0x00
,
0xff
,
0xff
,
0x1d
,
0x49
,
0x1a
,
0xb6
,
0x06
,
0x05
,
0x00
,
0x00
,
}
plugin/consensus/dpos/types/priv_validator.go
View file @
2cb03695
...
...
@@ -6,6 +6,7 @@ package types
import
(
"bytes"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"errors"
...
...
@@ -14,8 +15,9 @@ import (
"sync"
"github.com/33cn/chain33/common/crypto"
dty
"github.com/33cn/plugin/plugin/dapp/dposvote/types
"
vrf
"github.com/33cn/chain33/common/vrf/secp256k1
"
"github.com/33cn/chain33/types"
secp256k1
"github.com/btcsuite/btcd/btcec"
)
// KeyText ...
...
...
@@ -32,8 +34,10 @@ type PrivValidator interface {
SignVote
(
chainID
string
,
vote
*
Vote
)
error
SignNotify
(
chainID
string
,
notify
*
Notify
)
error
Sign
CBInfo
(
info
*
dty
.
DposCBInfo
)
error
Sign
Msg
(
msg
[]
byte
)
(
sig
string
,
err
error
)
SignTx
(
tx
*
types
.
Transaction
)
VrfEvaluate
(
input
[]
byte
)
(
hash
[
32
]
byte
,
proof
[]
byte
)
VrfProof
(
pubkey
[]
byte
,
input
[]
byte
,
hash
[
32
]
byte
,
proof
[]
byte
)
bool
}
// PrivValidatorFS implements PrivValidator using data persisted to disk
...
...
@@ -319,40 +323,58 @@ func (pv *PrivValidatorImp) SignNotify(chainID string, notify *Notify) error {
}
// SignCBInfo signs a canonical representation of the DposCBInfo, Implements PrivValidator.
func
(
pv
*
PrivValidatorImp
)
Sign
CBInfo
(
info
*
dty
.
DposCBInfo
)
error
{
func
(
pv
*
PrivValidatorImp
)
Sign
Msg
(
msg
[]
byte
)
(
sig
string
,
err
error
)
{
pv
.
mtx
.
Lock
()
defer
pv
.
mtx
.
Unlock
()
buf
:=
new
(
bytes
.
Buffer
)
info
.
Pubkey
=
hex
.
EncodeToString
(
pv
.
PubKey
.
Bytes
())
canonical
:=
dty
.
CanonicalOnceCBInfo
{
Cycle
:
info
.
Cycle
,
StopHeight
:
info
.
StopHeight
,
StopHash
:
info
.
StopHash
,
Pubkey
:
info
.
Pubkey
,
}
byteCB
,
err
:=
json
.
Marshal
(
&
canonical
)
if
err
!=
nil
{
return
errors
.
New
(
Fmt
(
"Error marshal CanonicalOnceCBInfo: %v"
,
err
))
}
_
,
err
=
buf
.
Write
(
byteCB
)
_
,
err
=
buf
.
Write
(
msg
)
if
err
!=
nil
{
return
errors
.
New
(
Fmt
(
"Error write buffer: %v"
,
err
))
return
""
,
errors
.
New
(
Fmt
(
"Error write buffer: %v"
,
err
))
}
signature
:=
pv
.
PrivKey
.
Sign
(
buf
.
Bytes
())
info
.
Signature
=
hex
.
EncodeToString
(
signature
.
Bytes
())
return
nil
sig
=
hex
.
EncodeToString
(
signature
.
Bytes
())
return
sig
,
nil
}
// SignTx signs a tx, Implements PrivValidator.
func
(
pv
*
PrivValidatorImp
)
SignTx
(
tx
*
types
.
Transaction
){
tx
.
Sign
(
types
.
SECP256K1
,
pv
.
PrivKey
)
}
// VrfEvaluate use input to generate hash & proof.
func
(
pv
*
PrivValidatorImp
)
VrfEvaluate
(
input
[]
byte
)
(
hash
[
32
]
byte
,
proof
[]
byte
)
{
pv
.
mtx
.
Lock
()
defer
pv
.
mtx
.
Unlock
()
privKey
,
_
:=
secp256k1
.
PrivKeyFromBytes
(
secp256k1
.
S256
(),
pv
.
PrivKey
.
Bytes
())
vrfPriv
:=
&
vrf
.
PrivateKey
{
PrivateKey
:
(
*
ecdsa
.
PrivateKey
)(
privKey
)}
hash
,
proof
=
vrfPriv
.
Evaluate
(
input
)
return
hash
,
proof
}
func
(
pv
*
PrivValidatorImp
)
VrfProof
(
pubkey
[]
byte
,
input
[]
byte
,
hash
[
32
]
byte
,
proof
[]
byte
)
bool
{
pv
.
mtx
.
Lock
()
defer
pv
.
mtx
.
Unlock
()
pubKey
,
err
:=
secp256k1
.
ParsePubKey
(
pubkey
,
secp256k1
.
S256
())
if
err
!=
nil
{
return
false
}
vrfPub
:=
&
vrf
.
PublicKey
{
PublicKey
:
(
*
ecdsa
.
PublicKey
)(
pubKey
)}
vrfHash
,
err
:=
vrfPub
.
ProofToHash
(
input
,
proof
)
if
err
!=
nil
{
return
false
}
if
bytes
.
Equal
(
hash
[
:
],
vrfHash
[
:
]){
return
true
}
return
false
}
// Persist height/round/step and signature
func
(
pv
*
PrivValidatorImp
)
saveSigned
(
signBytes
[]
byte
,
sig
crypto
.
Signature
)
{
...
...
plugin/consensus/dpos/validator_manager.go
View file @
2cb03695
...
...
@@ -12,12 +12,19 @@ import (
"math/rand"
ttypes
"github.com/33cn/plugin/plugin/consensus/dpos/types"
dty
"github.com/33cn/plugin/plugin/dapp/dposvote/types"
)
var
(
r
*
rand
.
Rand
)
const
(
ShuffleTypeNoVrf
=
iota
ShuffleTypeVrf
ShuffleTypePartVrf
)
// ValidatorMgr ...
type
ValidatorMgr
struct
{
// Immutable
...
...
@@ -28,7 +35,11 @@ type ValidatorMgr struct {
// Note that if s.LastBlockHeight causes a valset change,
// we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1
Validators
*
ttypes
.
ValidatorSet
VrfValidators
*
ttypes
.
ValidatorSet
NoVrfValidators
*
ttypes
.
ValidatorSet
LastCycleBoundaryInfo
*
dty
.
DposCBInfo
ShuffleCycle
int64
ShuffleType
int64
//0-no vrf 1-vrf 2-part vrf
// The latest AppHash we've received from calling abci.Commit()
AppHash
[]
byte
}
...
...
@@ -37,10 +48,19 @@ type ValidatorMgr struct {
func
(
s
ValidatorMgr
)
Copy
()
ValidatorMgr
{
return
ValidatorMgr
{
ChainID
:
s
.
ChainID
,
Validators
:
s
.
Validators
.
Copy
(),
AppHash
:
s
.
AppHash
,
ShuffleCycle
:
s
.
ShuffleCycle
,
ShuffleType
:
s
.
ShuffleType
,
VrfValidators
:
s
.
VrfValidators
.
Copy
(),
NoVrfValidators
:
s
.
NoVrfValidators
.
Copy
(),
LastCycleBoundaryInfo
:
&
dty
.
DposCBInfo
{
Cycle
:
s
.
LastCycleBoundaryInfo
.
Cycle
,
StopHeight
:
s
.
LastCycleBoundaryInfo
.
StopHeight
,
StopHash
:
s
.
LastCycleBoundaryInfo
.
StopHash
,
Pubkey
:
s
.
LastCycleBoundaryInfo
.
Pubkey
,
Signature
:
s
.
LastCycleBoundaryInfo
.
Signature
,
},
}
}
...
...
@@ -97,3 +117,146 @@ func MakeGenesisValidatorMgr(genDoc *ttypes.GenesisDoc) (ValidatorMgr, error) {
AppHash
:
genDoc
.
AppHash
,
},
nil
}
func
(
s
*
ValidatorMgr
)
GetValidatorByIndex
(
index
int
)
(
addres
[]
byte
,
val
*
ttypes
.
Validator
)
{
if
index
<
0
||
index
>=
len
(
s
.
Validators
.
Validators
)
{
return
nil
,
nil
}
if
s
.
ShuffleType
==
ShuffleTypeNoVrf
{
val
=
s
.
Validators
.
Validators
[
index
]
return
val
.
Address
,
val
.
Copy
()
}
else
if
s
.
ShuffleType
==
ShuffleTypeVrf
{
val
=
s
.
VrfValidators
.
Validators
[
index
]
return
address
.
PubKeyToAddress
(
val
.
PubKey
)
.
Hash160
[
:
],
val
.
Copy
()
}
else
if
s
.
ShuffleType
==
ShuffleTypePartVrf
{
if
index
<
len
(
s
.
VrfValidators
.
Validators
)
{
val
=
s
.
VrfValidators
.
Validators
[
index
]
return
address
.
PubKeyToAddress
(
val
.
PubKey
)
.
Hash160
[
:
],
val
.
Copy
()
}
else
{
val
=
s
.
NoVrfValidators
.
Validators
[
index
-
len
(
s
.
VrfValidators
.
Validators
)]
return
address
.
PubKeyToAddress
(
val
.
PubKey
)
.
Hash160
[
:
],
val
.
Copy
()
}
}
return
nil
,
nil
}
func
(
s
*
ValidatorMgr
)
GetIndexByPubKey
(
pubkey
[]
byte
)
(
index
int
)
{
if
nil
==
pubkey
{
return
-
1
}
index
=
-
1
if
s
.
ShuffleType
==
ShuffleTypeNoVrf
{
for
i
:=
0
;
i
<
s
.
Validators
.
Size
();
i
++
{
if
bytes
.
Equal
(
s
.
Validators
.
Validators
[
i
]
.
PubKey
,
pubkey
)
{
index
=
i
return
index
}
}
}
else
if
s
.
ShuffleType
==
ShuffleTypeVrf
{
for
i
:=
0
;
i
<
s
.
VrfValidators
.
Size
();
i
++
{
if
bytes
.
Equal
(
s
.
VrfValidators
.
Validators
[
i
]
.
PubKey
,
pubkey
)
{
index
=
i
return
index
}
}
}
else
if
s
.
ShuffleType
==
ShuffleTypePartVrf
{
for
i
:=
0
;
i
<
s
.
VrfValidators
.
Size
();
i
++
{
if
bytes
.
Equal
(
s
.
VrfValidators
.
Validators
[
i
]
.
PubKey
,
pubkey
)
{
index
=
i
return
index
}
}
for
j
:=
0
;
j
<
s
.
NoVrfValidators
.
Size
();
j
++
{
if
bytes
.
Equal
(
s
.
NoVrfValidators
.
Validators
[
j
]
.
PubKey
,
pubkey
)
{
index
=
j
+
s
.
VrfValidators
.
Size
()
return
index
}
}
}
return
index
}
func
(
s
*
ValidatorMgr
)
FillVoteItem
(
voteItem
*
ttypes
.
VoteItem
)
{
voteItem
.
LastCBInfo
=
&
ttypes
.
CycleBoundaryInfo
{
Cycle
:
s
.
LastCycleBoundaryInfo
.
Cycle
,
StopHeight
:
s
.
LastCycleBoundaryInfo
.
StopHeight
,
StopHash
:
s
.
LastCycleBoundaryInfo
.
StopHash
,
}
voteItem
.
ShuffleType
=
s
.
ShuffleType
for
i
:=
0
;
i
<
s
.
Validators
.
Size
();
i
++
{
node
:=
&
ttypes
.
SuperNode
{
PubKey
:
s
.
Validators
.
Validators
[
i
]
.
PubKey
,
Address
:
s
.
Validators
.
Validators
[
i
]
.
Address
,
}
voteItem
.
Validators
=
append
(
voteItem
.
Validators
,
node
)
}
for
i
:=
0
;
i
<
s
.
VrfValidators
.
Size
();
i
++
{
node
:=
&
ttypes
.
SuperNode
{
PubKey
:
s
.
VrfValidators
.
Validators
[
i
]
.
PubKey
,
Address
:
s
.
VrfValidators
.
Validators
[
i
]
.
Address
,
}
voteItem
.
VrfValidators
=
append
(
voteItem
.
VrfValidators
,
node
)
}
for
i
:=
0
;
i
<
s
.
NoVrfValidators
.
Size
();
i
++
{
node
:=
&
ttypes
.
SuperNode
{
PubKey
:
s
.
NoVrfValidators
.
Validators
[
i
]
.
PubKey
,
Address
:
s
.
NoVrfValidators
.
Validators
[
i
]
.
Address
,
}
voteItem
.
NoVrfValidators
=
append
(
voteItem
.
NoVrfValidators
,
node
)
}
}
func
(
s
*
ValidatorMgr
)
UpdateFromVoteItem
(
voteItem
*
ttypes
.
VoteItem
)
bool
{
validators
:=
voteItem
.
Validators
for
i
:=
0
;
i
<
s
.
Validators
.
Size
();
i
++
{
if
!
bytes
.
Equal
(
validators
[
i
]
.
PubKey
,
s
.
Validators
.
Validators
[
i
]
.
PubKey
)
{
return
false
}
}
if
s
.
LastCycleBoundaryInfo
==
nil
||
voteItem
.
LastCBInfo
.
Cycle
!=
s
.
LastCycleBoundaryInfo
.
Cycle
||
voteItem
.
LastCBInfo
.
StopHeight
!=
s
.
LastCycleBoundaryInfo
.
StopHeight
||
voteItem
.
LastCBInfo
.
StopHash
!=
s
.
LastCycleBoundaryInfo
.
StopHash
{
s
.
LastCycleBoundaryInfo
=
&
dty
.
DposCBInfo
{
Cycle
:
voteItem
.
LastCBInfo
.
Cycle
,
StopHeight
:
voteItem
.
LastCBInfo
.
StopHeight
,
StopHash
:
voteItem
.
LastCBInfo
.
StopHash
,
}
}
var
vrfVals
[]
*
ttypes
.
Validator
for
i
:=
0
;
i
<
len
(
voteItem
.
VrfValidators
);
i
++
{
val
:=
&
ttypes
.
Validator
{
Address
:
voteItem
.
VrfValidators
[
i
]
.
Address
,
PubKey
:
voteItem
.
VrfValidators
[
i
]
.
PubKey
,
}
vrfVals
=
append
(
vrfVals
,
val
)
}
s
.
VrfValidators
=
ttypes
.
NewValidatorSet
(
vrfVals
)
var
noVrfVals
[]
*
ttypes
.
Validator
for
i
:=
0
;
i
<
len
(
voteItem
.
NoVrfValidators
);
i
++
{
val
:=
&
ttypes
.
Validator
{
Address
:
voteItem
.
NoVrfValidators
[
i
]
.
Address
,
PubKey
:
voteItem
.
NoVrfValidators
[
i
]
.
PubKey
,
}
noVrfVals
=
append
(
noVrfVals
,
val
)
}
s
.
NoVrfValidators
=
ttypes
.
NewValidatorSet
(
noVrfVals
)
return
true
}
\ No newline at end of file
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