-
Notifications
You must be signed in to change notification settings - Fork 39
/
patch.go
86 lines (77 loc) · 2.07 KB
/
patch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package consensus
import (
"bytes"
"github.com/icon-project/goloop/common/codec"
"github.com/icon-project/goloop/common/errors"
"github.com/icon-project/goloop/module"
)
type skipPatch struct {
VoteList VoteList
}
func (s *skipPatch) Type() string {
return module.PatchTypeSkipTransaction
}
func (s *skipPatch) Data() []byte {
return codec.MustMarshalToBytes(s)
}
func (s *skipPatch) Height() int64 {
if s.VoteList.Len() == 0 {
return -1
}
return s.VoteList.Get(0).Height - 1
}
func (s *skipPatch) Verify(vl module.ValidatorList, roundLimit int64, nid int) error {
vset := make([]bool, vl.Len())
nidBytes := codec.MustMarshalToBytes(nid)
l := s.VoteList.Len()
if l == 0 {
return errors.Errorf("votes(%d) <= 2/3 of validators(%d)", l, vl.Len())
}
round := s.VoteList.Get(0).Round
if round < int32(roundLimit) {
return errors.Errorf("bad round %d roundLimit %d", round, roundLimit)
}
for i := 0; i < l; i++ {
msg := s.VoteList.Get(i)
index := vl.IndexOf(msg.address())
if index < 0 {
return errors.Errorf("bad voter %v at index %d in vote list", msg.address(), i)
}
if vset[index] {
return errors.Errorf("duplicated validator %v", msg.address())
}
if msg.BlockPartSetIDAndNTSVoteCount != nil {
return errors.Errorf("BPSID is not nil for validator %v", msg.address())
}
if !bytes.Equal(msg.BlockID, nidBytes) {
return errors.Errorf("bad nid %x for validator %v", msg.BlockID, msg.address())
}
if msg.Round != round {
return errors.Errorf("different round %d %d in vote list", round, msg.Round)
}
vset[index] = true
}
f := vl.Len() / 3
if l > f {
return nil
}
return errors.Errorf("votes(%d) <= 1/3 of validators(%d)", l, vl.Len())
}
func newSkipPatch(vl *VoteList) *skipPatch {
return &skipPatch{VoteList: *vl}
}
func DecodePatch(t string, bs []byte) (module.Patch, error) {
var err error
var patch module.Patch
switch t {
case module.PatchTypeSkipTransaction:
patch = &skipPatch{}
_, err = codec.UnmarshalFromBytes(bs, patch)
default:
err = errors.ErrUnsupported
}
if err != nil {
return nil, err
}
return patch, nil
}