Commit c0a88d2b authored by 张振华's avatar 张振华

update

parent 1e09c30a
......@@ -8,6 +8,7 @@ import (
"bytes"
"errors"
"fmt"
"github.com/33cn/chain33/types"
"reflect"
"runtime/debug"
"sync"
......@@ -16,6 +17,8 @@ import (
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"
"github.com/golang/protobuf/proto"
)
//-----------------------------------------------------------------------------
......@@ -96,6 +99,8 @@ type ConsensusState struct {
cachedVotes []*dpostype.DPosVote
cachedNotify *dpostype.DPosNotify
cycleBoundaryMap map[int64] *dty.DposCBInfo
}
// NewConsensusState returns a new ConsensusState.
......@@ -109,6 +114,7 @@ func NewConsensusState(client *Client, valMgr ValidatorMgr) *ConsensusState {
Quit: make(chan struct{}),
dposState: InitStateObj,
dposVotes: nil,
cycleBoundaryMap: make(map[int64] *dty.DposCBInfo),
}
cs.updateToValMgr(valMgr)
......@@ -531,3 +537,93 @@ func (cs *ConsensusState) VerifyNotify(notify *dpostype.DPosNotify) bool {
return true
}
// QueryCycleBoundaryInfo method
func (cs *ConsensusState) QueryCycleBoundaryInfo(cycle int64)(*dty.DposCBInfo, error){
req := &dty.DposCBQuery{Cycle: cycle, Ty: dty.QueryCBInfoByCycle}
param, err := proto.Marshal(req)
if err != nil {
dposlog.Error("Marshal DposCBQuery failed", "err", err)
return nil, err
}
msg := cs.client.GetQueueClient().NewMessage("execs", types.EventBlockChainQuery,
&types.ChainExecutor{
Driver: dty.DPosX,
FuncName: dty.FuncNameQueryCBInfoByCycle,
StateHash: zeroHash[:],
Param:param,
})
err = cs.client.GetQueueClient().Send(msg, true)
if err != nil {
dposlog.Error("send DposCBQuery to dpos exec failed", "err", err)
return nil, err
}
msg, err = cs.client.GetQueueClient().Wait(msg)
if err != nil {
dposlog.Error("send DposCBQuery wait failed", "err", err)
return nil, err
}
return msg.GetData().(types.Message).(*dty.DposCBInfo), nil
}
// InitCycleBoundaryInfo method
func (cs *ConsensusState) InitCycleBoundaryInfo(){
now := time.Now().Unix()
task := DecideTaskByTime(now)
info, err := cs.QueryCycleBoundaryInfo(task.cycle)
if err == nil && info != nil {
//cs.cycleBoundaryMap[task.cycle] = info
cs.UpdateCBInfo(info)
return
}
info, err = cs.QueryCycleBoundaryInfo(task.cycle - 1)
if err == nil && info != nil {
//cs.cycleBoundaryMap[task.cycle] = info
cs.UpdateCBInfo(info)
}
return
}
func (cs *ConsensusState) UpdateCBInfo(info *dty.DposCBInfo) {
valueNumber := len(cs.cycleBoundaryMap)
if valueNumber == 0 {
cs.cycleBoundaryMap[info.Cycle] = info
return
}
oldestCycle := int64(0)
for k, _ := range cs.cycleBoundaryMap {
if k == info.Cycle {
cs.cycleBoundaryMap[info.Cycle] = info
return
} else {
if oldestCycle == 0 {
oldestCycle = k
} else if oldestCycle > k {
oldestCycle = k
}
}
}
if valueNumber >= 5 {
delete(cs.cycleBoundaryMap, oldestCycle)
cs.cycleBoundaryMap[info.Cycle] = info
} else {
cs.cycleBoundaryMap[info.Cycle] = info
}
}
func (cs *ConsensusState) GetCBInfoByCircle(cycle int64) (info *dty.DposCBInfo) {
if v, ok := cs.cycleBoundaryMap[cycle];ok {
info = v
return info
}
return nil
}
\ No newline at end of file
......@@ -328,6 +328,7 @@ OuterLoop:
// 对于受托节点,才需要初始化区块,启动共识相关程序等,后续支持投票要做成动态切换的。
if client.isDelegator {
client.InitBlock()
client.csState.InitCycleBoundaryInfo()
node.Start()
}
......@@ -407,6 +408,52 @@ func (client *Client) CreateBlock() {
}
}
// CreateBlock a routine monitor whether some transactions available and tell client by available channel
func (client *Client) CreateBlockWithPriorTxs(priorTxs []*types.Transaction) {
lastBlock := client.GetCurrentBlock()
txs := client.RequestTx(int(types.GetP(lastBlock.Height + 1).MaxTxNumber), nil)
if len(priorTxs) > 0 {
txs = append(txs, priorTxs...)
}
if len(txs) == 0 {
block := client.GetCurrentBlock()
if createEmptyBlocks {
emptyBlock := &types.Block{}
emptyBlock.StateHash = block.StateHash
emptyBlock.ParentHash = block.Hash()
emptyBlock.Height = block.Height + 1
emptyBlock.Txs = nil
emptyBlock.TxHash = zeroHash[:]
emptyBlock.BlockTime = client.blockTime
err := client.WriteBlock(lastBlock.StateHash, emptyBlock)
//判断有没有交易是被删除的,这类交易要从mempool 中删除
if err != nil {
return
}
} else {
dposlog.Info("Ignore to create new Block for no tx in mempool", "Height", block.Height+1)
}
return
}
//check dup
txs = client.CheckTxDup(txs, client.GetCurrentHeight())
var newblock types.Block
newblock.ParentHash = lastBlock.Hash()
newblock.Height = lastBlock.Height + 1
client.AddTxsToBlock(&newblock, txs)
//
newblock.Difficulty = types.GetP(0).PowLimitBits
newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
newblock.BlockTime = client.blockTime
err := client.WriteBlock(lastBlock.StateHash, &newblock)
//判断有没有交易是被删除的,这类交易要从mempool 中删除
if err != nil {
return
}
}
// StopC stop client
func (client *Client) StopC() <-chan struct{} {
return client.stopC
......@@ -535,4 +582,42 @@ func (client *Client)isValidatorSetSame(v1, v2 *ttypes.ValidatorSet) bool {
}
return true
}
func (client *Client)QueryCycleBoundaryInfo(cycle int64)(*dty.DposCBInfo, error) {
var params rpctypes.Query4Jrpc
params.Execer = dty.DPosX
req := &dty.DposCBQuery{
Ty: dty.QueryCBInfoByCycle,
Cycle: cycle,
}
params.FuncName = dty.FuncNameQueryCBInfoByCycle
params.Payload = types.MustPBToJSON(req)
var res dty.DposCBReply
ctx := jsonrpc.NewRPCCtx(rpcAddr, "Chain33.Query", params, &res)
result, err := ctx.RunResult()
if err != nil {
fmt.Fprintln(os.Stderr, err)
return nil, err
}
res = *result.(*dty.DposCBReply)
return res.CbInfo, nil
}
func (client *Client)CreateRecordCBTx(info *dty.DposCBInfo)(tx*types.Transaction, err error) {
var action dty.DposVoteAction
action.Value = &dty.DposVoteAction_RecordCB{
RecordCB: info,
}
action.Ty = dty.DposVoteActionRecordCB
tx, err = types.CreateFormatTx("dpos", types.Encode(&action))
if err != nil {
return nil, err
}
return tx, nil
}
\ No newline at end of file
......@@ -6,12 +6,13 @@ package types;
message VoteItem {
int32 votedNodeIndex = 1; //被投票的节点索引
bytes votedNodeAddress = 2; //被投票的节点地址
int64 cycleStart = 3; //大周期起始时间
int64 cycleStop = 4; //大周期终止时间
int64 periodStart = 5; //新节点负责出块的起始时间
int64 periodStop = 6; //新节点负责出块的终止时间
int64 height = 7; //新节点负责出块的起始高度
bytes voteID = 8; //选票ID
int64 cycle = 3; //大周期序号
int64 cycleStart = 4; //大周期起始时间
int64 cycleStop = 5; //大周期终止时间
int64 periodStart = 6; //新节点负责出块的起始时间
int64 periodStop = 7; //新节点负责出块的终止时间
int64 height = 8; //新节点负责出块的起始高度
bytes voteID = 9; //选票ID
}
//DPosVote Dpos共识的节点投票,为达成共识用。
......
......@@ -6,6 +6,7 @@ package dpos
import (
"bytes"
"encoding/hex"
"encoding/json"
"math"
"time"
......@@ -13,6 +14,9 @@ import (
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto"
dpostype "github.com/33cn/plugin/plugin/consensus/dpos/types"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
"github.com/33cn/chain33/types"
)
var (
......@@ -49,6 +53,7 @@ var WaitNotifyStateObj = &WaitNofifyState{}
// Task 为计算当前时间所属周期的数据结构
type Task struct {
nodeID int64
cycle int64
cycleStart int64
cycleStop int64
periodStart int64
......@@ -60,7 +65,7 @@ type Task struct {
// DecideTaskByTime 根据时间戳计算所属的周期,包括cycle周期,负责出块周期,当前出块周期
func DecideTaskByTime(now int64) (task Task) {
task.nodeID = now % dposCycle / dposPeriod
task.cycle = now / dposCycle
task.cycleStart = now - now%dposCycle
task.cycleStop = task.cycleStart + dposCycle - 1
......@@ -120,6 +125,7 @@ func (init *InitState) timeOut(cs *ConsensusState) {
voteItem := &dpostype.VoteItem{
VotedNodeAddress: addr,
VotedNodeIndex: int32(task.nodeID),
Cycle: task.cycle,
CycleStart: task.cycleStart,
CycleStop: task.cycleStop,
PeriodStart: task.periodStart,
......@@ -311,6 +317,42 @@ func (voted *VotedState) timeOut(cs *ConsensusState) {
if now >= cs.currentVote.PeriodStop {
//当前时间超过了节点切换时间,需要进行重新投票
dposlog.Info("VotedState timeOut over periodStop.", "periodStop", cs.currentVote.PeriodStop)
//如果到了cycle结尾,需要再出一个块,把最终的CycleBoundary信息发布出去
if now >= cs.currentVote.CycleStop {
dposlog.Info("Create new tx for cycle change to record cycle boundary info.", "height", block.Height)
info := &dty.DposCBInfo{
Cycle: cs.currentVote.Cycle,
StopHeight: block.Height,
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.UpdateCBInfo(info)
}
//当前时间超过了节点切换时间,需要进行重新投票
notify := &dpostype.Notify{
DPosNotify: &dpostype.DPosNotify{
......@@ -543,6 +585,14 @@ func (wait *WaitNofifyState) recvNotify(cs *ConsensusState, notify *dpostype.DPo
hint.Stop()
}
info := &dty.DposCBInfo{
Cycle: notify.Vote.Cycle,
StopHeight: notify.HeightStop,
StopHash: hex.EncodeToString(notify.HashStop),
}
cs.UpdateCBInfo(info)
cs.ClearCachedNotify()
cs.SaveNotify()
cs.SetNotify(notify)
......
......@@ -33,12 +33,13 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
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"`
CycleStart int64 `protobuf:"varint,3,opt,name=cycleStart" json:"cycleStart,omitempty"`
CycleStop int64 `protobuf:"varint,4,opt,name=cycleStop" json:"cycleStop,omitempty"`
PeriodStart int64 `protobuf:"varint,5,opt,name=periodStart" json:"periodStart,omitempty"`
PeriodStop int64 `protobuf:"varint,6,opt,name=periodStop" json:"periodStop,omitempty"`
Height int64 `protobuf:"varint,7,opt,name=height" json:"height,omitempty"`
VoteID []byte `protobuf:"bytes,8,opt,name=voteID,proto3" json:"voteID,omitempty"`
Cycle int64 `protobuf:"varint,3,opt,name=cycle" json:"cycle,omitempty"`
CycleStart int64 `protobuf:"varint,4,opt,name=cycleStart" json:"cycleStart,omitempty"`
CycleStop int64 `protobuf:"varint,5,opt,name=cycleStop" json:"cycleStop,omitempty"`
PeriodStart int64 `protobuf:"varint,6,opt,name=periodStart" json:"periodStart,omitempty"`
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"`
}
func (m *VoteItem) Reset() { *m = VoteItem{} }
......@@ -60,6 +61,13 @@ func (m *VoteItem) GetVotedNodeAddress() []byte {
return nil
}
func (m *VoteItem) GetCycle() int64 {
if m != nil {
return m.Cycle
}
return 0
}
func (m *VoteItem) GetCycleStart() int64 {
if m != nil {
return m.CycleStart
......@@ -242,30 +250,30 @@ func init() {
func init() { proto.RegisterFile("dpos_msg.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 385 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x93, 0xcd, 0x4a, 0xeb, 0x40,
0x14, 0xc7, 0x49, 0xd3, 0xa4, 0xb9, 0xa7, 0x5f, 0xf7, 0xce, 0xe2, 0x12, 0x2e, 0x17, 0x09, 0x51,
0x24, 0xa8, 0x74, 0xa1, 0xbe, 0x80, 0xd0, 0x4d, 0x37, 0x45, 0xa2, 0xb8, 0x95, 0xd8, 0x8c, 0x4d,
0xa0, 0xe9, 0x0c, 0x33, 0x63, 0xb1, 0x0f, 0xa1, 0xaf, 0xe6, 0x2b, 0xc9, 0x9c, 0x7c, 0x4c, 0x9a,
0xe2, 0xae, 0xe7, 0xf7, 0x9f, 0x8f, 0x73, 0x7e, 0xd3, 0xc0, 0x24, 0xe5, 0x4c, 0x3e, 0x17, 0x72,
0x3d, 0xe3, 0x82, 0x29, 0x46, 0x1c, 0xb5, 0xe7, 0x54, 0x86, 0x9f, 0x3d, 0xf0, 0x9e, 0x98, 0xa2,
0x0b, 0x45, 0x0b, 0x72, 0x0e, 0x93, 0x1d, 0x53, 0x34, 0x5d, 0xb2, 0x94, 0x2e, 0xb6, 0x29, 0x7d,
0xf7, 0xad, 0xc0, 0x8a, 0x9c, 0xb8, 0x43, 0xc9, 0x05, 0xfc, 0x6e, 0xc8, 0x5d, 0x9a, 0x0a, 0x2a,
0xa5, 0xdf, 0x0b, 0xac, 0x68, 0x14, 0x1f, 0x71, 0x72, 0x02, 0xb0, 0xda, 0xaf, 0x36, 0xf4, 0x41,
0x25, 0x42, 0xf9, 0x76, 0x60, 0x45, 0x76, 0xdc, 0x22, 0xe4, 0x3f, 0xfc, 0xaa, 0x2a, 0xc6, 0xfd,
0x3e, 0xc6, 0x06, 0x90, 0x00, 0x86, 0x9c, 0x8a, 0x9c, 0xa5, 0xe5, 0x76, 0x07, 0xf3, 0x36, 0xd2,
0xe7, 0xd7, 0x25, 0xe3, 0xbe, 0x5b, 0x9e, 0x6f, 0x08, 0xf9, 0x0b, 0x6e, 0x46, 0xf3, 0x75, 0xa6,
0xfc, 0x01, 0x66, 0x55, 0xa5, 0xb9, 0xee, 0x75, 0x31, 0xf7, 0x3d, 0xec, 0xbc, 0xaa, 0xc2, 0x2f,
0x0b, 0xbc, 0xf9, 0x3d, 0x93, 0x5a, 0x0a, 0xb9, 0x04, 0x6f, 0x57, 0xc9, 0x41, 0x15, 0xc3, 0xeb,
0xe9, 0x0c, 0xbd, 0xcd, 0x6a, 0x67, 0x71, 0xb3, 0x80, 0x9c, 0xc1, 0x58, 0xff, 0x7e, 0xcc, 0x0b,
0x2a, 0x55, 0x52, 0x70, 0x54, 0x62, 0xc7, 0x87, 0xb0, 0x76, 0x2c, 0x8c, 0x63, 0xdb, 0x38, 0x16,
0x47, 0x8e, 0x45, 0xdb, 0x71, 0xdf, 0x38, 0x6e, 0x73, 0xed, 0x50, 0xe6, 0xeb, 0x6d, 0xa2, 0xde,
0x04, 0x45, 0x47, 0xa3, 0xd8, 0x80, 0xf0, 0x16, 0xc6, 0xf5, 0x40, 0x31, 0xe5, 0x9b, 0x3d, 0x39,
0x85, 0xbe, 0x3e, 0xa2, 0x33, 0x51, 0xb3, 0x06, 0xc3, 0xf0, 0xa3, 0x07, 0xa0, 0xd1, 0x92, 0xa9,
0xfc, 0xf5, 0xa7, 0x3d, 0x8d, 0x05, 0x0c, 0xf5, 0x5b, 0x94, 0x76, 0xf1, 0x2d, 0xca, 0xf1, 0x5b,
0x84, 0xfc, 0x03, 0x2f, 0x4b, 0x64, 0x86, 0xa9, 0x8d, 0x6d, 0x36, 0x35, 0x89, 0x60, 0xba, 0xc5,
0xab, 0x8c, 0xbf, 0xf2, 0xdf, 0xd0, 0xc5, 0x66, 0xa5, 0x51, 0xe8, 0xa0, 0xc2, 0x2e, 0x26, 0x57,
0xf0, 0xc7, 0xa0, 0x5a, 0xa2, 0x8b, 0x17, 0x1f, 0x07, 0x87, 0x16, 0x07, 0x1d, 0x8b, 0x2f, 0x2e,
0x7e, 0x36, 0x37, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x6e, 0xf4, 0x71, 0xcb, 0x48, 0x03, 0x00,
0x00,
// 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,
}
......@@ -14,6 +14,8 @@ import (
"sync"
"github.com/33cn/chain33/common/crypto"
dty "github.com/33cn/plugin/plugin/dapp/dposvote/types"
"github.com/33cn/chain33/types"
)
// KeyText ...
......@@ -30,6 +32,8 @@ type PrivValidator interface {
SignVote(chainID string, vote *Vote) error
SignNotify(chainID string, notify *Notify) error
SignCBInfo(info *dty.DposCBInfo) error
SignTx(tx *types.Transaction)
}
// PrivValidatorFS implements PrivValidator using data persisted to disk
......@@ -314,6 +318,41 @@ func (pv *PrivValidatorImp) SignNotify(chainID string, notify *Notify) error {
return nil
}
// SignCBInfo signs a canonical representation of the DposCBInfo, Implements PrivValidator.
func (pv *PrivValidatorImp) SignCBInfo(info *dty.DposCBInfo) 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)
if err != nil {
return errors.New(Fmt("Error write buffer: %v", err))
}
signature := pv.PrivKey.Sign(buf.Bytes())
info.Signature = hex.EncodeToString(signature.Bytes())
return nil
}
// SignTx signs a tx, Implements PrivValidator.
func (pv *PrivValidatorImp)SignTx(tx *types.Transaction){
tx.Sign(types.SECP256K1, pv.PrivKey)
}
// Persist height/round/step and signature
func (pv *PrivValidatorImp) saveSigned(signBytes []byte, sig crypto.Signature) {
......
......@@ -8,6 +8,7 @@ import (
"bytes"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/33cn/chain33/common/crypto"
"math/rand"
......@@ -780,3 +781,156 @@ func evaluate(cmd *cobra.Command, args []string) {
fmt.Println(fmt.Sprintf("hash:%x", vrfHash))
fmt.Println(fmt.Sprintf("proof:%x", vrfProof))
}
//CreateCmd to create keyfiles
func DPosCBRecordCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "cbRecord",
Short: "record cycle boundary info",
Run: recordCB,
}
addCBRecordCmdFlags(cmd)
return cmd
}
func addCBRecordCmdFlags(cmd *cobra.Command) {
cmd.Flags().Int64P("cycle", "c", 0, "cycle")
cmd.MarkFlagRequired("cycle")
cmd.Flags().Int64P("height", "h", 0, "height")
cmd.MarkFlagRequired("height")
cmd.Flags().StringP("hash", "m", "", "block hash")
cmd.MarkFlagRequired("hash")
cmd.Flags().StringP("privKey", "k", "", "private key")
cmd.MarkFlagRequired("privKey")
}
func recordCB(cmd *cobra.Command, args []string) {
// init crypto instance
err := initCryptoImpl()
if err != nil {
return
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
key, _ := cmd.Flags().GetString("privKey")
cycle, _ := cmd.Flags().GetInt64("cycle")
height, _ := cmd.Flags().GetInt64("height")
hash, _ := cmd.Flags().GetString("hash")
bKey, err := hex.DecodeString(key)
if err != nil {
fmt.Println("Error DecodeString bKey data failed: ", err)
return
}
privKey, err := ttypes.ConsensusCrypto.PrivKeyFromBytes(bKey)
if err != nil {
fmt.Println("Error PrivKeyFromBytes failed: ", err)
return
}
buf := new(bytes.Buffer)
canonical := dty.CanonicalOnceCBInfo{
Cycle: cycle,
StopHeight: height,
StopHash: hash,
Pubkey: hex.EncodeToString(privKey.PubKey().Bytes()),
}
byteCB, err := json.Marshal(&canonical)
if err != nil {
fmt.Println("Error Marshal failed: ", err)
return
}
_, err = buf.Write(byteCB)
if err != nil {
fmt.Println("Error buf.Write failed: ", err)
return
}
signature := privKey.Sign(buf.Bytes())
sig := hex.EncodeToString(signature.Bytes())
payload := fmt.Sprintf("{\"cycle\":\"%d\", \"stopHeight\":\"%d\", \"stopHash\":\"%s\", \"pubkey\":\"%s\", \"signature\":\"%s\"}",
cycle, height, hash, hex.EncodeToString(privKey.PubKey().Bytes()), sig)
params := &rpctypes.CreateTxIn{
Execer: types.ExecName(dty.DPosX),
ActionName: dty.CreateRecordCBTx,
Payload: []byte(payload),
}
var res string
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, &res)
ctx.RunWithoutMarshal()
}
//DPosVrfQueryCmd 构造VRF相关信息查询的命令行
func DPosCBQueryCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "cbQuery",
Short: "query cycle boundary info",
Run: cbQuery,
}
addCBQueryFlags(cmd)
return cmd
}
func addCBQueryFlags(cmd *cobra.Command) {
cmd.Flags().StringP("type", "t", "", "query type")
cmd.MarkFlagRequired("type")
cmd.Flags().Int64P("cycle", "c", 0, "cycle")
cmd.Flags().Int64P("height", "h", 0, "height")
cmd.Flags().StringP("hash", "m", "", "block hash")
}
func cbQuery(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ty, _ := cmd.Flags().GetString("type")
cycle, _ := cmd.Flags().GetInt64("cycle")
height, _ := cmd.Flags().GetInt64("height")
hash, _ := cmd.Flags().GetString("hash")
var params rpctypes.Query4Jrpc
params.Execer = dty.DPosX
switch ty {
case "cycle":
req := &dty.DposCBQuery{
Ty: dty.QueryCBInfoByCycle,
Cycle: cycle,
}
params.FuncName = dty.FuncNameQueryCBInfoByCycle
params.Payload = types.MustPBToJSON(req)
var res dty.DposCBReply
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
case "height":
req := &dty.DposCBQuery{
Ty: dty.QueryCBInfoByHeight,
StopHeight: height,
}
params.FuncName = dty.FuncNameQueryCBInfoByHeight
params.Payload = types.MustPBToJSON(req)
var res dty.DposCBReply
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
case "hash":
req := &dty.DposCBQuery{
Ty: dty.QueryCBInfoByHash,
StopHash: hash,
}
params.FuncName = dty.FuncNameQueryCBInfoByHash
params.Payload = types.MustPBToJSON(req)
var res dty.DposCBReply
ctx := jsonrpc.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
ctx.Run()
}
}
\ No newline at end of file
......@@ -554,6 +554,70 @@ func (action *Action) newCandicatorInfo(regist *dty.DposCandidatorRegist) *dty.C
return candInfo
}
//queryCBInfoByCycle 根据cycle查询stopHeight及stopHash等CBInfo信息,用于VRF计算
func queryCBInfoByCycle(kvdb db.KVDB, req *dty.DposCBQuery) (types.Message, error) {
cbTable := dty.NewDposCBTable(kvdb)
query := cbTable.GetQuery(kvdb)
rows, err := query.ListIndex("cycle", []byte(fmt.Sprintf("%018d", req.Cycle)), nil, 1, 0)
if err != nil {
return nil, err
}
cbInfo := rows[0].Data.(*dty.DposCycleBoundaryInfo)
info := &dty.DposCBInfo{
Cycle: cbInfo.Cycle,
StopHeight: cbInfo.StopHeight,
StopHash: hex.EncodeToString(cbInfo.StopHash),
Pubkey: strings.ToUpper(hex.EncodeToString(cbInfo.Pubkey)),
Signature: hex.EncodeToString(cbInfo.StopHash),
}
return &dty.DposCBReply{CbInfo: info}, nil
}
//queryCBInfoByHeight 根据stopHeight查询stopHash等CBInfo信息,用于VRF计算
func queryCBInfoByHeight(kvdb db.KVDB, req *dty.DposCBQuery) (types.Message, error) {
cbTable := dty.NewDposCBTable(kvdb)
query := cbTable.GetQuery(kvdb)
rows, err := query.ListIndex("height", []byte(fmt.Sprintf("%018d", req.StopHeight)), nil, 1, 0)
if err != nil {
return nil, err
}
cbInfo := rows[0].Data.(*dty.DposCycleBoundaryInfo)
info := &dty.DposCBInfo{
Cycle: cbInfo.Cycle,
StopHeight: cbInfo.StopHeight,
StopHash: hex.EncodeToString(cbInfo.StopHash),
Pubkey: strings.ToUpper(hex.EncodeToString(cbInfo.Pubkey)),
Signature: hex.EncodeToString(cbInfo.StopHash),
}
return &dty.DposCBReply{CbInfo: info}, nil
}
//queryCBInfoByHash 根据stopHash查询CBInfo信息,用于VRF计算
func queryCBInfoByHash(kvdb db.KVDB, req *dty.DposCBQuery) (types.Message, error) {
cbTable := dty.NewDposCBTable(kvdb)
query := cbTable.GetQuery(kvdb)
rows, err := query.ListIndex("hash", []byte(fmt.Sprintf("%X", req.StopHash)), nil, 1, 0)
if err != nil {
return nil, err
}
cbInfo := rows[0].Data.(*dty.DposCycleBoundaryInfo)
info := &dty.DposCBInfo{
Cycle: cbInfo.Cycle,
StopHeight: cbInfo.StopHeight,
StopHash: hex.EncodeToString(cbInfo.StopHash),
Pubkey: strings.ToUpper(hex.EncodeToString(cbInfo.Pubkey)),
Signature: hex.EncodeToString(cbInfo.StopHash),
}
return &dty.DposCBReply{CbInfo: info}, nil
}
//Regist 注册候选节点
func (action *Action) Regist(regist *dty.DposCandidatorRegist) (*types.Receipt, error) {
var logs []*types.ReceiptLog
......@@ -884,13 +948,6 @@ func (action *Action) RegistVrfM(vrfMReg *dty.DposVrfMRegist) (*types.Receipt, e
return nil, types.ErrInvalidParam
}
/*
bM, err := hex.DecodeString(vrfMReg.M)
if err != nil {
logger.Info("RegistVrfM", "addr", action.fromaddr, "execaddr", action.execaddr, "M is not correct",
vrfMReg.M)
return nil, types.ErrInvalidParam
}*/
bM := []byte(vrfMReg.M)
req := &dty.CandidatorQuery{}
......@@ -1048,3 +1105,71 @@ func (action *Action) RegistVrfRP(vrfRPReg *dty.DposVrfRPRegist) (*types.Receipt
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
}
//RegistVrfRP 注册受托节点的Vrf R/P信息
func (action *Action) RecordCB(cbInfo *dty.DposCBInfo) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
hash, err := hex.DecodeString(cbInfo.StopHash)
if err != nil {
logger.Info("RecordCB", "addr", action.fromaddr, "execaddr", action.execaddr, "StopHash is not correct", cbInfo.StopHash)
return nil, types.ErrInvalidParam
}
pubkey, err := hex.DecodeString(cbInfo.Pubkey)
if err != nil {
logger.Info("RecordCB", "addr", action.fromaddr, "execaddr", action.execaddr, "Pubkey is not correct", cbInfo.Pubkey)
return nil, types.ErrInvalidParam
}
sig, err := hex.DecodeString(cbInfo.Signature)
if err != nil {
logger.Info("RecordCB", "addr", action.fromaddr, "execaddr", action.execaddr, "Sig is not correct", cbInfo.Signature)
return nil, types.ErrInvalidParam
}
cb := &dty.DposCycleBoundaryInfo{
Cycle: cbInfo.Cycle,
StopHeight: cbInfo.StopHeight,
StopHash: hash,
Pubkey: pubkey,
Signature: sig,
}
cbTable := dty.NewDposCBTable(action.localDB)
query := cbTable.GetQuery(action.localDB)
rows, err := query.ListIndex("cycle", []byte(fmt.Sprintf("%018d", cbInfo.Cycle)), nil, 1, 0)
if err == nil && rows[0] != nil {
logger.Error("RecordCB failed", "addr", action.fromaddr, "execaddr", action.execaddr, "CB info is already recorded.", cbInfo.String())
return nil, dty.ErrCBRecordExist
}
cycleInfo := calcCycleByTime(action.blocktime)
if cbInfo.Cycle > cycleInfo.cycle + 1 || cbInfo.Cycle < cycleInfo.cycle - 2 {
logger.Error("RecordCB failed for cycle over range", "addr", action.fromaddr, "execaddr", action.execaddr, "CB info cycle", cbInfo.Cycle, "current cycle", cycleInfo.cycle)
return nil, dty.ErrCycleNotAllowed
}
middleTime := cycleInfo.cycleStart + (cycleInfo.cycleStop - cycleInfo.cycleStart) / 2
log := &types.ReceiptLog{}
r := &dty.ReceiptCB{}
r.Index = action.getIndex()
r.Pubkey = pubkey
r.Status = dty.CBStatusRecord
r.Cycle = cycleInfo.cycle
r.Height = action.mainHeight
r.Time = action.blocktime
r.CycleStart = cycleInfo.cycleStart
r.CycleStop = cycleInfo.cycleStop
r.CycleMiddle = middleTime
r.CbInfo = cb
log.Ty = dty.TyLogCBInfoRecord
log.Log = types.Encode(r)
logs = append(logs, log)
return &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}, nil
}
......@@ -39,7 +39,6 @@ func (d *DPos) Exec_CancelVote(payload *dty.DposCancelVote, tx *types.Transactio
return action.CancelVote(payload)
}
//Exec_RegistVrfM DPos执行器注册一个受托节点的Vrf M信息
func (d *DPos) Exec_RegistVrfM(payload *dty.DposVrfMRegist, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
......@@ -52,3 +51,8 @@ func (d *DPos) Exec_RegistVrfRP(payload *dty.DposVrfRPRegist, tx *types.Transact
return action.RegistVrfRP(payload)
}
//Exec_RecordCB DPos执行器记录CycleBoundary信息
func (d *DPos) Exec_RecordCB(payload *dty.DposCBInfo, tx *types.Transaction, index int) (*types.Receipt, error) {
action := NewAction(d, tx, index)
return action.RecordCB(payload)
}
......@@ -156,6 +156,22 @@ func (d *DPos) rollbackVrf(log *dty.ReceiptVrf) (kvs []*types.KeyValue, err erro
return nil, nil
}
func (d *DPos) rollbackCBInfo(log *dty.ReceiptCB) (kvs []*types.KeyValue, err error) {
if log.Status == dty.CBStatusRecord {
cbTable := dty.NewDposCBTable(d.GetLocalDB())
//注册回滚,cand表删除记录
err = cbTable.Del([]byte(fmt.Sprintf("%018d", log.Cycle)))
if err != nil {
return nil, err
}
kvs, err = cbTable.Save()
return kvs, err
}
return nil, nil
}
func (d *DPos) execDelLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
......@@ -175,7 +191,7 @@ func (d *DPos) execDelLocal(receipt *types.ReceiptData) (*types.LocalDBSet, erro
}
dbSet.KV = append(dbSet.KV, kv...)
case dty.VrfStatusMRegist, dty.VrfStatusRPRegist:
case dty.TyLogVrfMRegist, dty.TyLogVrfRPRegist:
receiptLog := &dty.ReceiptVrf{}
if err := types.Decode(log.Log, receiptLog); err != nil {
return nil, err
......@@ -185,6 +201,17 @@ func (d *DPos) execDelLocal(receipt *types.ReceiptData) (*types.LocalDBSet, erro
return nil, err
}
dbSet.KV = append(dbSet.KV, kv...)
case dty.TyLogCBInfoRecord:
receiptLog := &dty.ReceiptCB{}
if err := types.Decode(log.Log, receiptLog); err != nil {
return nil, err
}
kv, err := d.rollbackCBInfo(receiptLog)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kv...)
}
}
......@@ -224,4 +251,9 @@ func (d *DPos) ExecDelLocal_VrfMRegist(payload *dty.DposVrfMRegist, tx *types.Tr
//ExecDelLocal_VrfRPRegist method
func (d *DPos) ExecDelLocal_VrfRPRegist(payload *dty.DposVrfRPRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
//ExecDelLocal_RecordCB method
func (d *DPos) ExecDelLocal_RecordCB(payload *dty.DposCBInfo, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execDelLocal(receiptData)
}
\ No newline at end of file
......@@ -151,6 +151,24 @@ func (d *DPos) updateVrf(log *dty.ReceiptVrf) (kvs []*types.KeyValue, err error)
return kvs, nil
}
func (d *DPos) updateCB(log *dty.ReceiptCB) (kvs []*types.KeyValue, err error) {
if log.Status == dty.CBStatusRecord {
cbTable := dty.NewDposCBTable(d.GetLocalDB())
err = cbTable.Add(log.CbInfo)
if err != nil {
return nil, err
}
kvs, err = cbTable.Save()
if err != nil {
return nil, err
}
}
return kvs, nil
}
func (d *DPos) execLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
if receipt.GetTy() != types.ExecOk {
......@@ -180,6 +198,17 @@ func (d *DPos) execLocal(receipt *types.ReceiptData) (*types.LocalDBSet, error)
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
} else if item.Ty == dty.TyLogCBInfoRecord {
var cbLog dty.ReceiptCB
err := types.Decode(item.Log, &cbLog)
if err != nil {
return nil, err
}
kvs, err := d.updateCB(&cbLog)
if err != nil {
return nil, err
}
dbSet.KV = append(dbSet.KV, kvs...)
}
}
......@@ -219,4 +248,9 @@ func (d *DPos) ExecLocal_RegistVrfM(payload *dty.DposVrfMRegist, tx *types.Trans
//ExecLocal_VrfRPRegist method
func (d *DPos) ExecLocal_RegistVrfRP(payload *dty.DposVrfRPRegist, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
//ExecLocal_RecordCB method
func (d *DPos) ExecLocal_RecordCB(payload *dty.DposCBInfo, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return d.execLocal(receiptData)
}
\ No newline at end of file
......@@ -42,4 +42,19 @@ func (d *DPos) Query_QueryVrfByCycleForTopN(in *dty.DposVrfQuery) (types.Message
//Query_QueryVrfByCycleForPubkeys method
func (d *DPos) Query_QueryVrfByCycleForPubkeys(in *dty.DposVrfQuery) (types.Message, error) {
return queryVrfByCycleForPubkeys(d.GetLocalDB(), in)
}
\ No newline at end of file
}
//Query_QueryCBInfoByCycle method
func (d *DPos) Query_QueryCBInfoByCycle(in *dty.DposCBQuery) (types.Message, error) {
return queryCBInfoByCycle(d.GetLocalDB(), in)
}
//Query_QueryCBInfoByHeight method
func (d *DPos) Query_QueryCBInfoByHeight(in *dty.DposCBQuery) (types.Message, error) {
return queryCBInfoByHeight(d.GetLocalDB(), in)
}
//Query_QueryCBInfoByHash method
func (d *DPos) Query_QueryCBInfoByHash(in *dty.DposCBQuery) (types.Message, error) {
return queryCBInfoByHash(d.GetLocalDB(), in)
}
......@@ -75,14 +75,15 @@ message DposVoteAction {
DposVrfMRegist registVrfM = 8;
DposVrfRPRegist registVrfRP = 9;
DposVrfQuery vrfQuery = 10;
DposCBInfo recordCB = 11;
}
int32 ty = 11;
int32 ty = 12;
}
message CandidatorQuery{
repeated string pubkeys = 1; //候选节点公钥集合
int32 topN = 2; //topN
int32 ty = 3; //1:按公钥集合查询,2:按topN票数查询
int32 topN = 2; //topN
int32 ty = 3; //1:按公钥集合查询,2:按topN票数查询
}
......@@ -90,10 +91,10 @@ message CandidatorQuery{
//Candidator 候选节点信息
message JsonCandidator {
string pubkey = 1; //候选节点的公钥
string address = 2; //后续节点的地址
string ip = 3; //候选节点的运行IP
int64 votes = 4; //候选节点的投票数
int64 status = 5; //候选节点的状态,0:注册,1:当选,2:取消注册
string address = 2; //后续节点的地址
string ip = 3; //候选节点的运行IP
int64 votes = 4; //候选节点的投票数
int64 status = 5; //候选节点的状态,0:注册,1:当选,2:取消注册
}
message CandidatorReply{
repeated JsonCandidator candidators = 1; //候选节点
......@@ -101,7 +102,7 @@ message CandidatorReply{
message DposVoteQuery{
repeated string pubkeys = 1; //候选节点的公钥,如果为空,则查询所有,否则,查询该地址给具体候选节点的投票
string addr = 2; //要查询的地址
string addr = 2; //要查询的地址
}
message JsonDposVoter{
......@@ -118,7 +119,7 @@ message DposVoteReply{
//ReceiptCandicator 候选者收据信息
message ReceiptCandicator {
int64 Index = 1;
int64 Index = 1;
bytes pubkey = 2;
string address = 3;
int64 status = 4;
......@@ -219,4 +220,45 @@ message JsonVrfInfo {
message DposVrfReply{
repeated JsonVrfInfo vrf = 1;
}
message DposCycleBoundaryInfo {
int64 cycle = 1;
int64 stopHeight = 2;
bytes stopHash = 3;
bytes pubkey = 4;
bytes signature = 5;
}
message DposCBInfo {
int64 cycle = 1;
int64 stopHeight = 2;
string stopHash = 3;
string pubkey = 4;
string signature = 5;
}
message DposCBQuery {
int64 cycle = 1;
int64 stopHeight = 2;
string stopHash = 3;
int32 ty = 4;
}
message DposCBReply {
DposCBInfo cbInfo = 1;
}
//ReceiptCB CycleBoundary收据信息
message ReceiptCB {
int64 Index = 1;
bytes pubkey = 2;
int64 status = 3;
int64 cycle = 4;
int64 height = 5;
int64 time = 6;
int64 cycleStart = 7;
int64 cycleMiddle = 8;
int64 cycleStop = 9;
DposCycleBoundaryInfo cbInfo = 10;
}
\ No newline at end of file
......@@ -13,6 +13,7 @@ const (
DposVoteActionCancelVote
DposVoteActionRegistVrfM
DposVoteActionRegistVrfRP
DposVoteActionRecordCB
CandidatorStatusRegist = iota + 1
CandidatorStatusVoted
......@@ -22,17 +23,20 @@ const (
VrfStatusMRegist = iota + 1
VrfStatusRPRegist
CBStatusRecord = iota + 1
)
//log ty
const (
TyLogCandicatorRegist = 1001
TyLogCandicatorVoted = 1002
TyLogCandicatorCancelVoted = 1003
TyLogCandicatorRegist = 1001
TyLogCandicatorVoted = 1002
TyLogCandicatorCancelVoted = 1003
TyLogCandicatorCancelRegist = 1004
TyLogCandicatorReRegist = 1005
TyLogVrfMRegist = 1006
TyLogVrfRPRegist = 1007
TyLogCandicatorReRegist = 1005
TyLogVrfMRegist = 1006
TyLogVrfRPRegist = 1007
TyLogCBInfoRecord = 1008
)
const (
......@@ -95,15 +99,42 @@ const (
//CreateRegistVrfRPTx 创建注册Vrf的R/P信息的交易
CreateRegistVrfRPTx = "RegistVrfRP"
//QueryVrfByTime 创建根据time查询Vrf信息
//CreateRecordCBTx 创建记录CB信息的交易
CreateRecordCBTx = "RecordCB"
//QueryVrfByTime 根据time查询Vrf信息
QueryVrfByTime = 1
//QueryVrfByCycle 创建根据cycle查询Vrf信息
//QueryVrfByCycle 根据cycle查询Vrf信息
QueryVrfByCycle = 2
//QueryVrfByCycleForTopN 创建根据cycle查询当前topN的候选节点的Vrf信息
//QueryVrfByCycleForTopN 根据cycle查询当前topN的候选节点的Vrf信息
QueryVrfByCycleForTopN = 3
//QueryVrfByCycleForPubkeys 创建根据cycle查询指定pubkey的多个候选节点的Vrf信息
//QueryVrfByCycleForPubkeys 根据cycle查询指定pubkey的多个候选节点的Vrf信息
QueryVrfByCycleForPubkeys = 4
//FuncNameQueryCBInfoByCycle func name
FuncNameQueryCBInfoByCycle = "QueryCBInfoByCycle"
//FuncNameQueryCBInfoByHeight func name
FuncNameQueryCBInfoByHeight = "QueryCBInfoByHeight"
//FuncNameQueryCBInfoByHash func name
FuncNameQueryCBInfoByHash = "QueryCBInfoByHash"
//FuncNameQueryLatestCBInfoByHeight func name
FuncNameQueryLatestCBInfoByHeight = "QueryLatestCBInfoByHeight"
//QueryCBInfoByCycle 根据cycle查询cycle boundary信息
QueryCBInfoByCycle = 1
//QueryCBInfoByHeight 根据stopHeight查询cycle boundary信息
QueryCBInfoByHeight = 2
//QueryCBInfoByHash 根据stopHash查询cycle boundary信息
QueryCBInfoByHash = 3
//QueryCBInfoByHeight 根据stopHeight查询cycle boundary信息
QueryLatestCBInfoByHeight = 4
)
This diff is collapsed.
......@@ -22,4 +22,7 @@ var (
ErrParamStatusInvalid = errors.New("ErrParamStatusInvalid")
ErrParamAddressMustnotEmpty = errors.New("ErrParamAddressMustnotEmpty")
ErrSaveTable = errors.New("ErrSaveTable")
ErrCBRecordExist = errors.New("ErrCBRecordExist")
ErrCycleNotAllowed = errors.New("ErrCycleNotAllowed")
)
package types
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
ttypes "github.com/33cn/plugin/plugin/consensus/dpos/types"
)
// CanonicalOnceCBInfo ...
type CanonicalOnceCBInfo struct {
Cycle int64 `json:"cycle,omitempty"`
StopHeight int64 `json:"stopHeight,omitempty"`
StopHash string `json:"stopHash,omitempty"`
Pubkey string `json:"pubkey,omitempty"`
}
// CanonicalCBInfo ...
func CanonicalCBInfo(cb *DposCBInfo) CanonicalOnceCBInfo {
return CanonicalOnceCBInfo{
Cycle: cb.Cycle,
StopHeight: cb.StopHeight,
StopHash: cb.StopHash,
Pubkey: cb.Pubkey,
}
}
// CanonicalCBInfo ...
func (cb *DposCBInfo)Verify() error {
buf := new(bytes.Buffer)
canonical := CanonicalOnceCBInfo{
Cycle: cb.Cycle,
StopHeight: cb.StopHeight,
StopHash: cb.StopHash,
Pubkey: cb.Pubkey,
}
byteCB, err := json.Marshal(&canonical)
if err != nil {
return errors.New(fmt.Sprintf("Error marshal CanonicalOnceCBInfo: %v", err))
}
_, err = buf.Write(byteCB)
if err != nil {
return errors.New(fmt.Sprintf("Error write buffer: %v", err))
}
bPubkey, err := hex.DecodeString(cb.Pubkey)
if err != nil {
return errors.New(fmt.Sprintf("Error Decode pubkey: %v", err))
}
pubkey, err := ttypes.ConsensusCrypto.PubKeyFromBytes(bPubkey)
if err != nil {
return errors.New(fmt.Sprintf("Error PubKeyFromBytes: %v", err))
}
signature, err := hex.DecodeString(cb.Signature)
if err != nil {
return errors.New(fmt.Sprintf("Error Decode Signature: %v", err))
}
sig, err := ttypes.ConsensusCrypto.SignatureFromBytes(signature)
if err != nil {
return errors.New(fmt.Sprintf("Error SignatureFromBytes: %v", err))
}
if !pubkey.VerifyBytes(buf.Bytes(), sig) {
return errors.New(fmt.Sprintf("Error VerifyBytes: %v", err))
}
return nil
}
\ No newline at end of file
......@@ -230,3 +230,59 @@ func (tx *DposVrfRPRow) Get(key string) ([]byte, error) {
return nil, types.ErrNotFound
}
var opt_dpos_cb = &table.Option{
Prefix: "LODB-dpos",
Name: "cb",
Primary: "cycle",
Index: []string{"height", "hash"},
}
//NewDposVrfRPTable 新建表
func NewDposCBTable(kvdb db.KV) *table.Table {
rowmeta := NewDposCBRow()
table, err := table.NewTable(rowmeta, kvdb, opt_dpos_cb)
if err != nil {
panic(err)
}
return table
}
//DposCBRow table meta 结构
type DposCBRow struct {
*DposCycleBoundaryInfo
}
//NewDposVrfRPRow 新建一个meta 结构
func NewDposCBRow() *DposCBRow {
return &DposCBRow{DposCycleBoundaryInfo: &DposCycleBoundaryInfo{}}
}
//CreateRow 新建数据行
func (tx *DposCBRow) CreateRow() *table.Row {
return &table.Row{Data: &DposCycleBoundaryInfo{}}
}
//SetPayload 设置数据
func (tx *DposCBRow) SetPayload(data types.Message) error {
if txdata, ok := data.(*DposCycleBoundaryInfo); ok {
tx.DposCycleBoundaryInfo = txdata
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (tx *DposCBRow) Get(key string) ([]byte, error) {
if key == "cycle" {
return []byte(fmt.Sprintf("%018d", tx.Cycle)), nil
} else if key == "height" {
return []byte(fmt.Sprintf("%018d", tx.StopHeight)), nil
} else if key == "hash" {
return []byte(fmt.Sprintf("%X", tx.StopHash)), nil
}
return nil, types.ErrNotFound
}
......@@ -44,6 +44,7 @@ func (t *DPosType) GetTypeMap() map[string]int32 {
"CancelVote": DposVoteActionCancelVote,
"RegistVrfM": DposVoteActionRegistVrfM,
"RegistVrfRP": DposVoteActionRegistVrfRP,
"RecordCB": DposVoteActionRecordCB,
}
}
......@@ -57,5 +58,6 @@ func (t *DPosType) GetLogMap() map[int64]*types.LogInfo {
TyLogCandicatorReRegist: {Ty: reflect.TypeOf(ReceiptCandicator{}), Name: "TyLogCandicatorReRegist"},
TyLogVrfMRegist: {Ty: reflect.TypeOf(ReceiptVrf{}), Name: "TyLogVrfMRegist"},
TyLogVrfRPRegist: {Ty: reflect.TypeOf(ReceiptVrf{}), Name: "TyLogVrfRPRegist"},
TyLogCBInfoRecord: {Ty: reflect.TypeOf(ReceiptCB{}), Name: "TyLogCBInfoRecord"},
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment