-
Notifications
You must be signed in to change notification settings - Fork 0
/
consensus.go
87 lines (73 loc) · 2.14 KB
/
consensus.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 (
"github.com/msaldanha/realChain/address"
"github.com/msaldanha/realChain/errors"
"github.com/msaldanha/realChain/ledger"
)
//go:generate mockgen -destination=../tests/mock_consensusclient.go -package=tests github.com/msaldanha/realChain/consensus ConsensusClient
//go:generate mockgen -destination=../tests/mock_consensus.go -package=tests github.com/msaldanha/realChain/consensus Consensus
//go:generate protoc -I.. consensus/consensus.proto --go_out=plugins=grpc:../
const (
ErrInvalidVotingResult = errors.Error("invalid voting result")
)
type Consensus interface {
Vote(*VoteRequest) (*VoteResult, error)
Accept(*AcceptRequest) (*AcceptResult, error)
}
type consensus struct {
ledger ledger.Ledger
addr *address.Address
}
func NewConsensus(ledger ledger.Ledger, addr *address.Address) *consensus {
return &consensus{
ledger: ledger,
addr: addr,
}
}
func (c *consensus) Vote(request *VoteRequest) (*VoteResult, error) {
err := c.ledger.VerifyTransaction(request.ReceiveTx, true)
if err != nil {
return c.createVoteResult(false, err.Error())
}
err = c.ledger.VerifyTransaction(request.SendTx, true)
if err != nil {
return c.createVoteResult(false, err.Error())
}
err = c.ledger.Verify(request.SendTx, request.ReceiveTx)
if err != nil {
return c.createVoteResult(false, err.Error())
}
return c.createVoteResult(true, "")
}
func (c *consensus) Accept(request *AcceptRequest) (*AcceptResult, error) {
oks := 0
for _, vote := range request.Votes {
err := c.validateVote(vote)
if err != nil {
return nil, err
}
if vote.Ok {
oks++
}
}
if oks == 0 || oks != len(request.Votes) {
return nil, ErrInvalidVotingResult
}
err := c.ledger.Register(request.SendTx, request.ReceiveTx)
if err != nil {
return nil, err
}
return &AcceptResult{}, nil
}
func (c *consensus) createVoteResult(ok bool, reason string) (*VoteResult, error) {
vote := &Vote{Ok: ok, Reason: reason}
err := vote.Sign(c.addr.Keys.ToEcdsaPrivateKey())
if err != nil {
return nil, err
}
vote.PubKey = c.addr.Keys.PublicKey
return &VoteResult{Vote: vote}, nil
}
func (c *consensus) validateVote(vote *Vote) error {
return nil
}