18 "github.com/vapor/chain"
19 "github.com/vapor/common"
20 "github.com/vapor/config"
21 "github.com/vapor/consensus"
22 engine "github.com/vapor/consensus/consensus"
23 "github.com/vapor/crypto"
24 "github.com/vapor/protocol/bc"
25 "github.com/vapor/protocol/bc/types"
26 "github.com/vapor/protocol/vm"
29 type Delegate struct {
30 DelegateAddress string `json:"delegate_address"`
31 Votes uint64 `json:"votes"`
34 type DelegateWrapper struct {
36 by func(p, q *Delegate) bool
39 func (dw DelegateWrapper) Len() int {
40 return len(dw.delegate)
42 func (dw DelegateWrapper) Swap(i, j int) {
43 dw.delegate[i], dw.delegate[j] = dw.delegate[j], dw.delegate[i]
45 func (dw DelegateWrapper) Less(i, j int) bool {
46 return dw.by(&dw.delegate[i], &dw.delegate[j])
49 type DelegateInfo struct {
50 Delegates []Delegate `json:"delegates"`
53 func (d *DelegateInfo) ConsensusName() string {
57 const maxConfirmBlockCount = 2
59 type IrreversibleBlockInfo struct {
62 HeightHash map[int64]bc.Hash
65 func newIrreversibleBlockInfo() *IrreversibleBlockInfo {
66 o := &IrreversibleBlockInfo{}
67 for i := 0; i < maxConfirmBlockCount; i++ {
68 o.heights = append(o.heights, -1)
69 o.hashs = append(o.hashs, bc.Hash{})
71 o.HeightHash = make(map[int64]bc.Hash)
75 type DposType struct {
78 MaxDelegateNumber uint64
79 BlockIntervalTime uint64
80 DposStartHeight uint64
82 superForgerAddress common.Address
83 irreversibleBlockFileName string
84 irreversibleBlockInfo IrreversibleBlockInfo
85 lockIrreversibleBlockInfo sync.Mutex
86 maxIrreversibleCount int
87 firstIrreversibleThreshold uint64
88 secondIrreversibleThreshold uint64
91 var GDpos = &DposType{
92 maxIrreversibleCount: 10000,
93 firstIrreversibleThreshold: 90,
94 secondIrreversibleThreshold: 67,
97 func (d *DposType) Init(c chain.Chain, delegateNumber, intervalTime, blockHeight uint64, blockHash bc.Hash) error {
99 vote, err := newVote(blockHeight, blockHash)
101 d.MaxDelegateNumber = delegateNumber
102 d.BlockIntervalTime = intervalTime
103 d.DposStartHeight = 0
104 address, _ := common.DecodeAddress("vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep", &consensus.ActiveNetParams)
105 d.superForgerAddress = address
107 GDpos.irreversibleBlockFileName = filepath.Join(config.CommonConfig.RootDir, "dpos", "irreversible_block.dat")
108 GDpos.irreversibleBlockInfo = *newIrreversibleBlockInfo()
109 GDpos.ReadIrreversibleBlockInfo(&GDpos.irreversibleBlockInfo)
110 header, _ := c.GetHeaderByHeight(d.DposStartHeight)
111 d.setStartTime(header.Timestamp)
115 func (d *DposType) setStartTime(t uint64) {
119 func (d *DposType) IsMining(address common.Address, t uint64) (interface{}, error) {
121 header := d.c.BestBlockHeader()
122 currentLoopIndex := d.GetLoopIndex(t)
123 currentDelegateIndex := d.GetDelegateIndex(t)
124 prevLoopIndex := d.GetLoopIndex(header.Timestamp)
125 prevDelegateIndex := d.GetDelegateIndex(header.Timestamp)
126 if currentLoopIndex > prevLoopIndex {
127 delegateInfo := d.GetNextDelegates(t)
128 cDelegateInfo := delegateInfo.(*DelegateInfo)
129 if uint64(len(cDelegateInfo.Delegates)) < currentDelegateIndex+1 {
130 return nil, errors.New("Out of the block node list")
132 if cDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
133 return delegateInfo, nil
135 return nil, errors.New("Is not the current mining node")
136 } else if currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex {
137 currentDelegateInfo, err := d.GetBlockDelegates(header)
141 if currentDelegateIndex+1 > uint64(len(currentDelegateInfo.Delegates)) {
142 return nil, errors.New("Out of the block node list")
143 } else if currentDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
146 return nil, errors.New("Is not the current mining node")
149 return nil, errors.New("Time anomaly")
153 func (d *DposType) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
154 return d.vote.ProcessRegister(delegateAddress, delegateName, hash, height)
157 func (d *DposType) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
158 return d.vote.ProcessVote(voterAddress, delegates, hash, height)
161 func (d *DposType) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
162 return d.vote.ProcessCancelVote(voterAddress, delegates, hash, height)
165 func (d *DposType) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
166 d.vote.UpdateAddressBalance(addressBalance)
169 func (d *DposType) GetLoopIndex(time uint64) uint64 {
170 if time < d.DposStartTime {
173 return (time - d.DposStartTime) / (d.MaxDelegateNumber * d.BlockIntervalTime)
176 func (d *DposType) GetDelegateIndex(time uint64) uint64 {
177 if time < d.DposStartTime {
180 return (time - d.DposStartTime) % (d.MaxDelegateNumber * d.BlockIntervalTime) / d.BlockIntervalTime
183 func (d *DposType) GetNextDelegates(t uint64) interface{} {
184 delegates := d.vote.GetTopDelegateInfo(config.CommonConfig.Consensus.MinVoterBalance, d.MaxDelegateNumber-1)
185 delegate := Delegate{
186 DelegateAddress: d.superForgerAddress.EncodeAddress(),
189 delegates = append(delegates, delegate)
190 delegateInfo := DelegateInfo{}
191 delegateInfo.Delegates = delegates //SortDelegate(delegates, t)
195 func (d *DposType) GetBlockDelegates(header *types.BlockHeader) (*DelegateInfo, error) {
196 loopIndex := d.GetLoopIndex(header.Timestamp)
198 preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
202 if header.Height == d.DposStartHeight || d.GetLoopIndex(preHeader.Timestamp) < loopIndex {
203 block, err := d.c.GetBlockByHeight(header.Height)
207 delegateInfo, err := d.GetBlockDelegate(block)
211 return delegateInfo, nil
217 func (d *DposType) GetBlockDelegate(block *types.Block) (*DelegateInfo, error) {
218 tx := block.Transactions[0]
219 if len(tx.TxData.Inputs) == 1 && tx.TxData.Inputs[0].InputType() == types.CoinbaseInputType {
221 if err := json.Unmarshal(tx.TxData.ReferenceData, msg); err != nil {
224 if msg.Type == vm.OP_DELEGATE {
225 delegateInfo := &DelegateInfoList{}
226 if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
229 return &delegateInfo.Delegate, nil
233 return nil, errors.New("The first transaction is not a coinbase transaction")
236 func (d *DposType) CheckCoinbase(tx types.TxData, t uint64, Height uint64) error {
238 if err := json.Unmarshal(tx.ReferenceData, msg); err != nil {
241 if msg.Type == vm.OP_DELEGATE {
242 delegateInfo := &DelegateInfoList{}
243 if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
247 binary.LittleEndian.PutUint64(buf[:], t)
249 if !delegateInfo.Xpub.Verify(buf[:], delegateInfo.SigTime) {
250 return errors.New("CheckBlock CheckCoinbase: Verification signature error")
253 address common.Address
256 address, err = common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
260 derivedPK := delegateInfo.Xpub.PublicKey()
261 pubHash := crypto.Ripemd160(derivedPK)
263 addressDet, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
268 if addressDet.EncodeAddress() == address.EncodeAddress() {
272 return errors.New("CheckBlock CheckCoinbase error")
275 func (d *DposType) CheckBlockHeader(header types.BlockHeader) error {
276 blockT := time.Unix(int64(header.Timestamp), 0)
278 if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
279 return errors.New("block time is error")
282 if header.Height > d.DposStartHeight {
283 header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
284 d.setStartTime(header.Timestamp)
287 preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
292 currentLoopIndex := d.GetLoopIndex(header.Timestamp)
293 currentDelegateIndex := d.GetDelegateIndex(header.Timestamp)
294 prevLoopIndex := d.GetLoopIndex(preHeader.Timestamp)
295 prevDelegateIndex := d.GetDelegateIndex(preHeader.Timestamp)
296 if currentLoopIndex > prevLoopIndex ||
297 (currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex) {
301 return errors.New("DPoS CheckBlockHeader error")
304 func (d *DposType) CheckBlock(block types.Block, fIsCheckDelegateInfo bool) error {
305 if block.Height > d.DposStartHeight {
306 header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
307 d.setStartTime(header.Timestamp)
310 blockT := time.Unix(int64(block.Timestamp), 0)
311 if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
312 return errors.New("block time is error")
314 if err := d.CheckCoinbase(block.Transactions[0].TxData, block.Timestamp, block.Height); err != nil {
318 preBlock, err := d.c.GetBlockByHash(&block.PreviousBlockHash)
323 currentLoopIndex := d.GetLoopIndex(block.Timestamp)
324 currentDelegateIndex := d.GetDelegateIndex(block.Timestamp)
325 prevLoopIndex := d.GetLoopIndex(preBlock.Timestamp)
326 prevDelegateIndex := d.GetDelegateIndex(preBlock.Timestamp)
328 delegateInfo := &DelegateInfo{}
330 if currentLoopIndex < prevLoopIndex {
331 return errors.New("Block time exception")
332 } else if currentLoopIndex > prevLoopIndex {
333 if fIsCheckDelegateInfo {
334 if err := d.CheckBlockDelegate(block); err != nil {
337 d.ProcessIrreversibleBlock(block.Height, block.Hash())
339 delegateInfo, err = d.GetBlockDelegate(&block)
344 if currentDelegateIndex < prevDelegateIndex {
345 return errors.New("Block time exception")
348 delegateInfo, err = d.GetBlockDelegates(&preBlock.BlockHeader)
354 delegateAddress := d.getBlockForgerAddress(block)
355 if currentDelegateIndex < uint64(len(delegateInfo.Delegates)) &&
356 delegateInfo.Delegates[currentDelegateIndex].DelegateAddress == delegateAddress.EncodeAddress() {
360 return fmt.Errorf("CheckBlock GetDelegateID blockhash:%s error", h.String())
363 func (d *DposType) CheckBlockDelegate(block types.Block) error {
364 delegateInfo, err := d.GetBlockDelegate(&block)
368 nextDelegateInfoInterface := d.GetNextDelegates(block.Timestamp)
369 nextDelegateInfo := nextDelegateInfoInterface.(*DelegateInfo)
370 if len(delegateInfo.Delegates) != len(nextDelegateInfo.Delegates) {
371 return errors.New("The delegates num is not correct in block")
374 for index, v := range delegateInfo.Delegates {
375 if v.DelegateAddress != nextDelegateInfo.Delegates[index].DelegateAddress {
376 return errors.New("The delegates address is not correct in block")
383 func (d *DposType) ProcessIrreversibleBlock(height uint64, hash bc.Hash) {
384 d.lockIrreversibleBlockInfo.Lock()
385 defer d.lockIrreversibleBlockInfo.Unlock()
387 for i = maxConfirmBlockCount - 1; i >= 0; i-- {
388 if d.irreversibleBlockInfo.heights[i] < 0 || int64(height) < d.irreversibleBlockInfo.heights[i] {
389 d.irreversibleBlockInfo.heights[i] = -1
391 level := (height - uint64(d.irreversibleBlockInfo.heights[i])) * 100
392 if level >= d.MaxDelegateNumber*d.firstIrreversibleThreshold {
393 d.AddIrreversibleBlock(int64(height), hash)
394 } else if level >= d.MaxDelegateNumber*d.secondIrreversibleThreshold {
395 if i == maxConfirmBlockCount-1 {
396 d.AddIrreversibleBlock(int64(height), hash)
397 for k := 0; k < maxConfirmBlockCount-1; k++ {
398 d.irreversibleBlockInfo.heights[k] = d.irreversibleBlockInfo.heights[k+1]
399 d.irreversibleBlockInfo.hashs[k] = d.irreversibleBlockInfo.hashs[k+1]
401 d.irreversibleBlockInfo.heights[i] = int64(height)
402 d.irreversibleBlockInfo.hashs[i] = hash
405 d.irreversibleBlockInfo.heights[i+1] = int64(height)
406 d.irreversibleBlockInfo.hashs[i+1] = hash
411 for k := 0; k < maxConfirmBlockCount; k++ {
412 d.irreversibleBlockInfo.heights[k] = -1
414 d.irreversibleBlockInfo.heights[0] = int64(height)
415 d.irreversibleBlockInfo.hashs[0] = hash
421 d.irreversibleBlockInfo.heights[0] = int64(height)
422 d.irreversibleBlockInfo.hashs[0] = hash
426 func (d *DposType) getBlockForgerAddress(block types.Block) common.Address {
427 tx := block.Transactions[0].TxData
429 if len(tx.Inputs) == 1 && tx.Inputs[0].InputType() == types.CoinbaseInputType {
430 address, err := common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
432 address, err := common.NewAddressWitnessScriptHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
444 func (d *DposType) IsValidBlockCheckIrreversibleBlock(height uint64, hash bc.Hash) error {
445 d.lockIrreversibleBlockInfo.Lock()
446 defer d.lockIrreversibleBlockInfo.Unlock()
448 if h, ok := d.irreversibleBlockInfo.HeightHash[int64(height)]; ok {
450 return fmt.Errorf("invalid block[%d:%s]", height, hash.String())
457 func (d *DposType) ReadIrreversibleBlockInfo(info *IrreversibleBlockInfo) error {
458 f, err := os.Open(d.irreversibleBlockFileName)
463 buf := bufio.NewReader(f)
465 line, err := buf.ReadString('\n')
472 line = strings.TrimSpace(line)
474 var hashString string
475 n, err := fmt.Sscanf(line, "%d;%s\n", &height, &hashString)
476 if err != nil || n != 2 {
477 return errors.New("parse error for ReadIrreversibleBlockInfo ")
480 if err := hash.UnmarshalText([]byte(hashString)); err != nil {
483 d.AddIrreversibleBlock(height, hash)
487 type Int64Slice []int64
489 func (a Int64Slice) Len() int {
492 func (a Int64Slice) Swap(i, j int) {
493 a[i], a[j] = a[j], a[i]
495 func (a Int64Slice) Less(i, j int) bool {
499 func (d *DposType) WriteIrreversibleBlockInfo() error {
500 if len(d.irreversibleBlockInfo.HeightHash) == 0 {
504 f, err := os.Create(d.irreversibleBlockFileName)
509 w := bufio.NewWriter(f)
511 for k := range d.irreversibleBlockInfo.HeightHash {
512 keys = append(keys, k)
515 sort.Sort(Int64Slice(keys))
517 for _, k := range keys {
518 data, _ := d.irreversibleBlockInfo.HeightHash[k].MarshalText()
519 line := fmt.Sprintf("%d;%s\n", k, string(data))
523 if err := w.Flush(); err != nil {
530 func (d *DposType) AddIrreversibleBlock(height int64, hash bc.Hash) {
531 for k, _ := range d.irreversibleBlockInfo.HeightHash {
532 if len(d.irreversibleBlockInfo.HeightHash) > d.maxIrreversibleCount {
533 delete(d.irreversibleBlockInfo.HeightHash, k)
538 d.irreversibleBlockInfo.HeightHash[height] = hash
539 d.vote.DeleteInvalidVote(uint64(height))
542 func (d *DposType) GetSuperForgerAddress() common.Address {
543 return d.superForgerAddress
546 func (d *DposType) GetIrreversibleBlock() {
550 func (d *DposType) GetOldBlockHeight() uint64 {
551 return d.vote.GetOldBlockHeight()
554 func (d *DposType) GetOldBlockHash() bc.Hash {
555 return d.vote.GetOldBlockHash()
558 func (d *DposType) ListDelegates() map[string]string {
559 return d.vote.ListDelegates()
562 func (d *DposType) GetDelegateVotes(delegate string) uint64 {
563 return d.vote.GetDelegateVotes(delegate)
566 func (d *DposType) GetDelegateVoters(delegate string) []string {
567 return d.vote.GetDelegateVoters(delegate)
570 func (d *DposType) GetDelegate(name string) string {
571 return d.vote.GetDelegate(name)
575 func (d *DposType) GetDelegateName(address string) string {
576 return d.vote.GetDelegateName(address)
579 func (d *DposType) GetAddressBalance(address string) uint64 {
580 return d.vote.GetAddressBalance(address)
583 func (d *DposType) GetVotedDelegates(voter string) []string {
584 return d.vote.GetVotedDelegates(voter)
587 func (d *DposType) HaveVote(voter, delegate string) bool {
588 return d.vote.HaveVote(voter, delegate)
591 func (d *DposType) HaveDelegate(name, delegate string) bool {
592 return d.vote.HaveDelegate(name, delegate)
595 func (d *DposType) Finish() error {
596 header := d.c.BestBlockHeader()
597 if err := d.vote.Store(header.Height, header.Hash()); err != nil {
601 if err := d.WriteIrreversibleBlockInfo(); err != nil {
608 func SortDelegate(delegates []Delegate, t uint64) []Delegate {
609 var result []Delegate
610 r := getRand(uint64(len(delegates)), int64(t))
611 for _, i := range r {
612 result = append(result, delegates[i])
617 func getRand(num uint64, seed int64) []uint64 {
620 s := make(map[uint64]bool)
624 if _, ok := s[v]; ok {
629 if uint64(len(r)) >= num {