-
Notifications
You must be signed in to change notification settings - Fork 95
/
chain_rw.go
153 lines (132 loc) · 4.64 KB
/
chain_rw.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package consensus
import (
"math/big"
"time"
"sort"
"github.com/pkg/errors"
"github.com/vitelabs/go-vite/common/types"
"github.com/vitelabs/go-vite/consensus/core"
"github.com/vitelabs/go-vite/ledger"
)
type ch interface {
GetLatestSnapshotBlock() *ledger.SnapshotBlock
GetConsensusGroupList(snapshotHash types.Hash) ([]*types.ConsensusGroupInfo, error) // Get all consensus group
GetRegisterList(snapshotHash types.Hash, gid types.Gid) ([]*types.Registration, error) // Get register for consensus group
GetVoteMap(snapshotHash types.Hash, gid types.Gid) ([]*types.VoteInfo, error) // Get the candidate's vote
GetBalanceList(snapshotHash types.Hash, tokenTypeId types.TokenTypeId, addressList []types.Address) (map[types.Address]*big.Int, error) // Get balance for addressList
GetSnapshotBlockBeforeTime(timestamp *time.Time) (*ledger.SnapshotBlock, error)
GetContractGidByAccountBlock(block *ledger.AccountBlock) (*types.Gid, error)
GetSnapshotBlockByHeight(height uint64) (*ledger.SnapshotBlock, error)
GetSnapshotBlockByHash(hash *types.Hash) (*ledger.SnapshotBlock, error)
}
type chainRw struct {
rw ch
}
type VoteDetails struct {
core.Vote
CurrentAddr types.Address
RegisterList []types.Address
Addr map[types.Address]*big.Int
}
type ByBalance []*VoteDetails
func (a ByBalance) Len() int { return len(a) }
func (a ByBalance) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByBalance) Less(i, j int) bool {
r := a[j].Balance.Cmp(a[i].Balance)
if r == 0 {
return a[i].Name < a[j].Name
} else {
return r < 0
}
}
func (self *chainRw) GetSnapshotBeforeTime(t time.Time) (*ledger.SnapshotBlock, error) {
block, e := self.rw.GetSnapshotBlockBeforeTime(&t)
if e != nil {
return nil, e
}
if block == nil {
return nil, errors.New("before time[" + t.String() + "] block not exist")
}
return block, nil
}
func (self *chainRw) CalVotes(info *core.GroupInfo, block ledger.HashHeight) ([]*core.Vote, error) {
return core.CalVotes(info, block, self.rw)
}
func (self *chainRw) CalVoteDetails(gid types.Gid, info *core.GroupInfo, block ledger.HashHeight) ([]*VoteDetails, error) {
// query register info
registerList, _ := self.rw.GetRegisterList(block.Hash, gid)
// query vote info
votes, _ := self.rw.GetVoteMap(block.Hash, gid)
var registers []*VoteDetails
// cal candidate
for _, v := range registerList {
registers = append(registers, self.GenVoteDetails(block.Hash, v, votes, info.CountingTokenId))
}
sort.Sort(ByBalance(registers))
return registers, nil
}
func (self *chainRw) GenVoteDetails(snapshotHash types.Hash, registration *types.Registration, infos []*types.VoteInfo, id types.TokenTypeId) *VoteDetails {
var addrs []types.Address
for _, v := range infos {
if v.NodeName == registration.Name {
addrs = append(addrs, v.VoterAddr)
}
}
balanceMap, _ := self.rw.GetBalanceList(snapshotHash, id, addrs)
balanceTotal := big.NewInt(0)
for _, v := range balanceMap {
balanceTotal.Add(balanceTotal, v)
}
return &VoteDetails{
Vote: core.Vote{
Name: registration.Name,
Addr: registration.NodeAddr,
Balance: balanceTotal,
},
CurrentAddr: registration.NodeAddr,
RegisterList: registration.HisAddrList,
Addr: balanceMap,
}
}
func (self *chainRw) GetMemberInfo(gid types.Gid, genesis time.Time) *core.GroupInfo {
// todo consensus group maybe change ??
var result *core.GroupInfo
head := self.rw.GetLatestSnapshotBlock()
consensusGroupList, _ := self.rw.GetConsensusGroupList(head.Hash)
for _, v := range consensusGroupList {
if v.Gid == gid {
result = core.NewGroupInfo(genesis, *v)
}
}
return result
}
func (self *chainRw) getGid(block *ledger.AccountBlock) (types.Gid, error) {
gid, e := self.rw.GetContractGidByAccountBlock(block)
return *gid, e
}
func (self *chainRw) GetLatestSnapshotBlock() *ledger.SnapshotBlock {
return self.rw.GetLatestSnapshotBlock()
}
func (self *chainRw) checkSnapshotHashValid(startHeight uint64, startHash types.Hash, actual types.Hash) error {
if startHash == actual {
return nil
}
startB, e := self.rw.GetSnapshotBlockByHash(&startHash)
if e != nil {
return e
}
if startB == nil {
return errors.Errorf("start snapshot block is nil. hashH:%s-%d", startHash, startHeight)
}
actualB, e := self.rw.GetSnapshotBlockByHash(&actual)
if e != nil {
return e
}
if actualB == nil {
return errors.Errorf("refer snapshot block is nil. hashH:%s", actual)
}
if actualB.Height < startB.Height {
return errors.Errorf("refer snapshot block height must >= start snapshot block height")
}
return nil
}