-
Notifications
You must be signed in to change notification settings - Fork 4
/
deputy_node.go
115 lines (101 loc) · 3.06 KB
/
deputy_node.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
package deputynode
import (
"encoding/hex"
"encoding/json"
"errors"
"github.com/LemoFoundationLtd/lemochain-core/common"
"github.com/LemoFoundationLtd/lemochain-core/common/crypto/sha3"
"github.com/LemoFoundationLtd/lemochain-core/common/hexutil"
"github.com/LemoFoundationLtd/lemochain-core/common/log"
"github.com/LemoFoundationLtd/lemochain-core/common/merkle"
"github.com/LemoFoundationLtd/lemochain-core/common/rlp"
"math/big"
)
//go:generate gencodec -type DeputyNode --field-override deputyNodeMarshaling -out gen_deputy_node_json.go
var (
ErrMinerAddressInvalid = errors.New("incorrect field: 'MinerAddress'")
ErrNodeIDInvalid = errors.New("incorrect field: 'NodeID'")
ErrRankInvalid = errors.New("max deputy node's rank is 65535")
ErrVotesInvalid = errors.New("min deputy node's votes are 0")
)
// DeputyNode
type DeputyNode struct {
MinerAddress common.Address `json:"minerAddress" gencodec:"required"` // candidate account address
NodeID []byte `json:"nodeID" gencodec:"required"`
Rank uint32 `json:"rank" gencodec:"required"` // start from 0
Votes *big.Int `json:"votes" gencodec:"required"`
}
type deputyNodeMarshaling struct {
NodeID hexutil.Bytes
Rank hexutil.Uint32
Votes *hexutil.Big10
}
func NewDeputyNode(votes *big.Int, rank uint32, minerAddr common.Address, nodeIDStr string) (*DeputyNode, error) {
// nodeID
nodeID, err := hex.DecodeString(nodeIDStr)
if err != nil {
log.Errorf("NewDeputyNode fail", "NodeID", nodeIDStr)
return nil, err
}
return &DeputyNode{
MinerAddress: minerAddr,
Votes: votes,
Rank: rank,
NodeID: nodeID,
}, nil
}
func (d *DeputyNode) Hash() (h common.Hash) {
data := []interface{}{
d.MinerAddress,
d.NodeID,
d.Rank,
d.Votes,
}
hw := sha3.NewKeccak256()
rlp.Encode(hw, data)
hw.Sum(h[:0])
return h
}
func (d *DeputyNode) Check() error {
if d.MinerAddress == (common.Address{}) {
log.Errorf("Incorrect field: 'MinerAddress'. value: %s", d.MinerAddress.String())
return ErrMinerAddressInvalid
}
if len(d.NodeID) != 64 {
log.Errorf("Incorrect field: 'NodeID'. value: %s", common.ToHex(d.NodeID))
return ErrNodeIDInvalid
}
if d.Rank > 65535 {
log.Errorf("Incorrect field: 'rank'. value: %d", d.Rank)
return ErrRankInvalid
}
if d.Votes.Cmp(new(big.Int)) < 0 {
log.Errorf("Incorrect field: 'votes'. value: %d", d.Votes)
return ErrVotesInvalid
}
return nil
}
func (d *DeputyNode) Copy() *DeputyNode {
result := &DeputyNode{
MinerAddress: d.MinerAddress,
NodeID: d.NodeID,
Rank: d.Rank,
Votes: new(big.Int).Set(d.Votes),
}
return result
}
type DeputyNodes []*DeputyNode
func (nodes DeputyNodes) String() string {
if buf, err := json.Marshal(nodes); err == nil {
return string(buf)
}
return ""
}
// MerkleRootSha compute the root hash of deputy nodes merkle trie
func (nodes DeputyNodes) MerkleRootSha() common.Hash {
leaves := make([]common.Hash, len(nodes))
for i, item := range nodes {
leaves[i] = item.Hash()
}
return merkle.New(leaves).Root()
}