Skip to content

Commit 9c14f8f

Browse files
authored
Merge pull request #71 from getamis/feature/log-comments-and-errors-refactoring
consensus/pbft: log, comments and other slight refactoring
2 parents a6d4d69 + d932020 commit 9c14f8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+624
-915
lines changed

Makefile

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@
1111
GOBIN = build/bin
1212
GO ?= latest
1313

14-
pbft:
15-
build/env.sh go run build/ci.go install ./consensus/pbft/example/simplenode
16-
@echo "Done building."
17-
@echo "Run \"$(GOBIN)/simplenode\" to launch simplenode."
18-
1914
geth:
2015
build/env.sh go run build/ci.go install ./cmd/geth
2116
@echo "Done building."

consensus/pbft/backend.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,51 @@ import (
2121
"github.com/ethereum/go-ethereum/event"
2222
)
2323

24-
// Backend provides callbacks for PBFT consensus core
24+
// Backend provides application specific functions for PBFT core
2525
type Backend interface {
2626
// Address returns self address
2727
Address() common.Address
2828

29-
// Validators returns validator set
29+
// Validators returns the validator set
3030
Validators() ValidatorSet
3131

32-
// EventMux is defined to handle request event and pbft message event
32+
// EventMux returns the event mux in backend
3333
EventMux() *event.TypeMux
3434

35-
// Send is to send pbft message to specific peer
35+
// Send sends a message to specific peer
3636
Send(payload []byte, target common.Address) error
3737

38-
// Broadcast is to send pbft message to all peers
38+
// Broadcast sends a message to all peers
3939
Broadcast(payload []byte) error
4040

41-
// Commit is to deliver a final result to write into blockchain
41+
// Commit delivers a approved proposal to backend.
42+
// The delivered proposal will be put into blockchain.
4243
Commit(Proposal) error
4344

4445
// NextRound is called when we want to trigger next Seal()
4546
NextRound() error
4647

47-
// Verify is to verify the proposal request
48+
// Verify verifies the proposal.
4849
Verify(Proposal) error
4950

50-
// Sign is to sign the data
51+
// Sign signs input data with the backend's private key
5152
Sign([]byte) ([]byte, error)
5253

53-
// CheckSignature is to verify the signature is signed from given peer
54+
// CheckSignature verifies the signature by checking if it's signed by given peer
5455
CheckSignature(data []byte, addr common.Address, sig []byte) error
5556

5657
// CheckValidatorSignature verifies if the data is signed by one of the validators
58+
// If the verification succeeds, the signer's address is returned, otherwise
59+
// an empty address and an error are returned.
5760
CheckValidatorSignature(data []byte, sig []byte) (common.Address, error)
5861

59-
// FIXME: Hash, Encode, Decode and SetHandler are workaround functions for developing
60-
Hash(b interface{}) common.Hash
61-
6262
Persistence
6363
}
6464

65+
// Persistence provides persistence data storage for PBFT core
6566
type Persistence interface {
66-
// Save an object into db
67+
// Save an object into database
6768
Save(key string, val interface{}) error
68-
// Restore an object to val from db
69+
// Restore an object to val from database
6970
Restore(key string, val interface{}) error
7071
}

consensus/pbft/backends/simple/api.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
// Copyright 2017 AMIS Technologies
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
117
package simple
218

319
import (
@@ -19,8 +35,8 @@ func (api *API) Snapshot() {
1935
state, snapshot := api.backend.core.Snapshot()
2036
p := api.backend.valSet.GetProposer().Address()
2137
log.Info("Snapshot", "sequence", snapshot.Sequence, "Round", snapshot.Round,
22-
"state", state, "proposer", p.Hex(),
23-
"hash", snapshot.Preprepare.Proposal.Hash().Hex(),
38+
"state", state, "proposer", p,
39+
"hash", snapshot.Preprepare.Proposal.Hash(),
2440
"prepares", snapshot.Prepares, "commits", snapshot.Commits,
2541
"checkpoint", snapshot.Checkpoints)
2642
}
@@ -29,8 +45,8 @@ func (api *API) Snapshot() {
2945
func (api *API) Backlog() {
3046
backlog := api.backend.core.Backlog()
3147
logs := make([]string, 0, len(backlog))
32-
for address, q := range backlog {
33-
logs = append(logs, fmt.Sprintf("{%v, %v}", address.Address().Hex(), q.Size()))
48+
for validator, q := range backlog {
49+
logs = append(logs, fmt.Sprintf("{%v, %v}", validator, q.Size()))
3450
}
3551
log.Info("Backlog", "logs", fmt.Sprintf("[%v]", strings.Join(logs, ", ")))
3652
}

consensus/pbft/backends/simple/backend.go

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ import (
2727
"github.com/ethereum/go-ethereum/core"
2828
"github.com/ethereum/go-ethereum/core/types"
2929
"github.com/ethereum/go-ethereum/crypto"
30-
"github.com/ethereum/go-ethereum/crypto/sha3"
3130
"github.com/ethereum/go-ethereum/ethdb"
3231
"github.com/ethereum/go-ethereum/event"
3332
"github.com/ethereum/go-ethereum/log"
34-
"github.com/ethereum/go-ethereum/rlp"
3533
)
3634

35+
// New creates an Ethereum backend for PBFT core engine.
3736
func New(config *pbft.Config, eventMux *event.TypeMux, privateKey *ecdsa.PrivateKey, db ethdb.Database) consensus.PBFT {
3837
backend := &simpleBackend{
3938
config: config,
@@ -50,6 +49,7 @@ func New(config *pbft.Config, eventMux *event.TypeMux, privateKey *ecdsa.Private
5049
}
5150

5251
// ----------------------------------------------------------------------------
52+
5353
type simpleBackend struct {
5454
config *pbft.Config
5555
peerSet *peerSet
@@ -116,15 +116,15 @@ func (sb *simpleBackend) Broadcast(payload []byte) error {
116116

117117
// Commit implements pbft.Backend.Commit
118118
func (sb *simpleBackend) Commit(proposal pbft.Proposal) error {
119-
sb.logger.Info("Committed", "address", sb.Address().Hex(), "hash", proposal.Hash(), "number", proposal.Number().Uint64())
120-
// step1: update validator set from extra data of block
121-
// step2: insert chain
119+
// Check if the proposal is a valid block
122120
block := &types.Block{}
123121
block, ok := proposal.(*types.Block)
124122
if !ok {
125-
sb.logger.Error("Failed to commit proposal since RequestContext cannot cast to *types.Block")
126-
return errCastingRequest
123+
sb.logger.Error("Invalid proposal, %v", proposal)
124+
return errInvalidProposal
127125
}
126+
127+
sb.logger.Info("Committed", "address", sb.Address(), "hash", proposal.Hash(), "number", proposal.Number().Uint64())
128128
// - if the proposed and committed blocks are the same, send the proposed hash
129129
// to commit channel, which is being watched inside the engine.Seal() function.
130130
// - otherwise, we try to insert the block.
@@ -143,33 +143,24 @@ func (sb *simpleBackend) Commit(proposal pbft.Proposal) error {
143143
// NextRound will broadcast ChainHeadEvent to trigger next seal()
144144
func (sb *simpleBackend) NextRound() error {
145145
header := sb.chain.CurrentHeader()
146-
sb.logger.Debug("NextRound", "address", sb.Address().Hex(), "current_hash", header.Hash(), "current_number", header.Number)
146+
sb.logger.Debug("NextRound", "address", sb.Address(), "current_hash", header.Hash(), "current_number", header.Number)
147147
go sb.eventMux.Post(core.ChainHeadEvent{})
148148
return nil
149149
}
150150

151-
// Hash implements pbft.Backend.Hash
152-
func (sb *simpleBackend) Hash(x interface{}) (h common.Hash) {
153-
hw := sha3.NewKeccak256()
154-
rlp.Encode(hw, x)
155-
hw.Sum(h[:0])
156-
return h
157-
}
158-
159151
// EventMux implements pbft.Backend.EventMux
160152
func (sb *simpleBackend) EventMux() *event.TypeMux {
161-
// not implemented
162153
return sb.pbftEventMux
163154
}
164155

165156
// Verify implements pbft.Backend.Verify
166157
func (sb *simpleBackend) Verify(proposal pbft.Proposal) error {
167-
// decode the proposal to block
158+
// Check if the proposal is a valid block
168159
block := &types.Block{}
169160
block, ok := proposal.(*types.Block)
170161
if !ok {
171-
sb.logger.Error("Failed to commit proposal since RequestContext cannot cast to *types.Block")
172-
return errCastingRequest
162+
sb.logger.Error("Invalid proposal, %v", proposal)
163+
return errInvalidProposal
173164
}
174165
// verify the header of proposed block
175166
return sb.VerifyHeader(sb.chain, block.Header(), false)
@@ -185,12 +176,12 @@ func (sb *simpleBackend) Sign(data []byte) ([]byte, error) {
185176
func (sb *simpleBackend) CheckSignature(data []byte, address common.Address, sig []byte) error {
186177
signer, err := sb.getSignatureAddress(data, sig)
187178
if err != nil {
188-
log.Error("CheckSignature", "error", err)
179+
log.Error("Failed to get signer address", "err", err)
189180
return err
190181
}
191-
//Compare derived addresses
182+
// Compare derived addresses
192183
if signer != address {
193-
return pbft.ErrInvalidSignature
184+
return errInvalidSignature
194185
}
195186
return nil
196187
}
@@ -200,7 +191,7 @@ func (sb *simpleBackend) CheckValidatorSignature(data []byte, sig []byte) (commo
200191
// 1. Get signature address
201192
signer, err := sb.getSignatureAddress(data, sig)
202193
if err != nil {
203-
log.Error("CheckValidatorSignature", "error", err)
194+
log.Error("Failed to get signer address", "err", err)
204195
return common.Address{}, err
205196
}
206197

@@ -209,14 +200,14 @@ func (sb *simpleBackend) CheckValidatorSignature(data []byte, sig []byte) (commo
209200
return val.Address(), nil
210201
}
211202

212-
return common.Address{}, pbft.ErrNoMatchingValidator
203+
return common.Address{}, pbft.ErrUnauthorizedAddress
213204
}
214205

215206
// get the signer address from the signature
216207
func (sb *simpleBackend) getSignatureAddress(data []byte, sig []byte) (common.Address, error) {
217-
//1. Keccak data
208+
// 1. Keccak data
218209
hashData := crypto.Keccak256([]byte(data))
219-
//2. Recover public key
210+
// 2. Recover public key
220211
pubkey, err := crypto.SigToPub(hashData, sig)
221212
if err != nil {
222213
return common.Address{}, err

consensus/pbft/backends/simple/backend_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func TestCheckSignature(t *testing.T) {
5959
}
6060
a = getInvalidAddress()
6161
err = b.CheckSignature(data, a, sig)
62-
if err != pbft.ErrInvalidSignature {
62+
if err != errInvalidSignature {
6363
t.Error("Should fail with ErrInvalidSignature")
6464
}
6565
}
@@ -98,10 +98,10 @@ func TestCheckValidatorSignature(t *testing.T) {
9898
t.Errorf("Unable to sign data")
9999
}
100100

101-
// CheckValidatorSignature should return ErrNoMatchingValidator
101+
// CheckValidatorSignature should return ErrUnauthorizedAddress
102102
addr, err := b.CheckValidatorSignature(data, sig)
103-
if err != pbft.ErrNoMatchingValidator {
104-
t.Errorf("Expected error pbft.ErrNoMatchingValidator, but got: %v", err)
103+
if err != pbft.ErrUnauthorizedAddress {
104+
t.Errorf("Expected error pbft.ErrUnauthorizedAddress, but got: %v", err)
105105
}
106106
emptyAddr := common.Address{}
107107
if addr != emptyAddr {
@@ -151,7 +151,7 @@ func (slice Keys) Len() int {
151151
}
152152

153153
func (slice Keys) Less(i, j int) bool {
154-
return strings.Compare(crypto.PubkeyToAddress(slice[i].PublicKey).Hex(), crypto.PubkeyToAddress(slice[j].PublicKey).Hex()) < 0
154+
return strings.Compare(crypto.PubkeyToAddress(slice[i].PublicKey).String(), crypto.PubkeyToAddress(slice[j].PublicKey).String()) < 0
155155
}
156156

157157
func (slice Keys) Swap(i, j int) {

consensus/pbft/backends/simple/engine.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,16 @@ const (
4242
)
4343

4444
var (
45+
// errInvalidProposal is returned when a prposal is malformed.
46+
errInvalidProposal = errors.New("invalid proposal")
47+
// errInvalidSignature is returned when given signature is not signed by given
48+
// address.
49+
errInvalidSignature = errors.New("invalid signature")
4550
// errUnknownBlock is returned when the list of signers is requested for a block
4651
// that is not part of the local blockchain.
4752
errUnknownBlock = errors.New("unknown block")
4853
// errUnauthorized is returned if a header is signed by a non authorized entity.
4954
errUnauthorized = errors.New("unauthorized")
50-
// errNotInValidatorSet is returned if I'm not in validator set but try to start engine
51-
errNotInValidatorSet = errors.New("not in validator set")
5255
// errInvalidDifficulty is returned if the difficulty of a block is not 1
5356
errInvalidDifficulty = errors.New("invalid difficulty")
5457
// errInvalidPeer is returned when a message from invalid peer comes
@@ -63,8 +66,6 @@ var (
6366
errInvalidUncleHash = errors.New("non empty uncle hash")
6467
// errInconsistentValidatorSet is returned if the validator set is inconsistent
6568
errInconsistentValidatorSet = errors.New("non empty uncle hash")
66-
// errCastingRequest is returned if request cannot cast specific type
67-
errCastingRequest = errors.New("failed to cast the request")
6869
// errInvalidTimestamp is returned if the timestamp of a block is lower than the previous block's timestamp + the minimum block period.
6970
errInvalidTimestamp = errors.New("invalid timestamp")
7071
)
@@ -365,10 +366,6 @@ func (sb *simpleBackend) AddPeer(peerID string, publicKey *ecdsa.PublicKey) erro
365366
if _, val := sb.valSet.GetByAddress(peer.Address()); val != nil {
366367
// add to peer set
367368
sb.peerSet.Add(peer)
368-
// post connection event to pbft core
369-
go sb.pbftEventMux.Post(pbft.ConnectionEvent{
370-
Address: val.Address(),
371-
})
372369
}
373370
return nil
374371
}
@@ -388,7 +385,7 @@ func (sb *simpleBackend) HandleMsg(peerID string, data []byte) error {
388385
}
389386

390387
if _, val := sb.valSet.GetByAddress(peer.Address()); val == nil {
391-
sb.logger.Error("Not in validator set", "peerAddr", peer.Address().Hex())
388+
sb.logger.Error("Not in validator set", "peerAddr", peer.Address())
392389
return errInvalidPeer
393390
}
394391

@@ -402,7 +399,7 @@ func (sb *simpleBackend) HandleMsg(peerID string, data []byte) error {
402399
func (sb *simpleBackend) NewChainHead(block *types.Block) {
403400
p, err := sb.Author(block.Header())
404401
if err != nil {
405-
sb.logger.Error("Failed to get block proposer", "error", err)
402+
sb.logger.Error("Failed to get block proposer", "err", err)
406403
return
407404
}
408405
go sb.pbftEventMux.Post(pbft.FinalCommittedEvent{
@@ -417,7 +414,7 @@ func (sb *simpleBackend) Start(chain consensus.ChainReader, inserter func(block
417414
return err
418415
}
419416
if _, v := sb.valSet.GetByAddress(sb.address); v == nil {
420-
return errNotInValidatorSet
417+
return pbft.ErrUnauthorizedAddress
421418
}
422419
sb.chain = chain
423420
sb.inserter = inserter

consensus/pbft/backends/simple/engine_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ func TestSealCommitted(t *testing.T) {
229229
if err != nil {
230230
t.Errorf("error should be nil, but got: %v", err)
231231
}
232-
if finalBlock.Hash().Hex() != expectedBlock.Hash().Hex() {
233-
t.Errorf("block should be equal, got: %v, expected: %v", finalBlock.Hash().Hex(), expectedBlock.Hash().Hex())
232+
if finalBlock.Hash() != expectedBlock.Hash() {
233+
t.Errorf("block should be equal, got: %v, expected: %v", finalBlock.Hash(), expectedBlock.Hash())
234234
}
235235
}
236236

consensus/pbft/backends/simple/persistence.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package simple
1818

1919
import (
2020
"github.com/ethereum/go-ethereum/common"
21+
"github.com/ethereum/go-ethereum/consensus/pbft"
2122
"github.com/ethereum/go-ethereum/rlp"
2223
)
2324

@@ -30,11 +31,11 @@ func (sb *simpleBackend) Save(key string, val interface{}) error {
3031
if err != nil {
3132
return err
3233
}
33-
return sb.db.Put(toDatabaseKey(sb.Hash, key), blob)
34+
return sb.db.Put(toDatabaseKey(pbft.RLPHash, key), blob)
3435
}
3536

3637
func (sb *simpleBackend) Restore(key string, val interface{}) error {
37-
blob, err := sb.db.Get(toDatabaseKey(sb.Hash, key))
38+
blob, err := sb.db.Get(toDatabaseKey(pbft.RLPHash, key))
3839
if err != nil {
3940
return err
4041
}

0 commit comments

Comments
 (0)