Skip to content

Commit

Permalink
Merge pull request #61 from relab/reorganize
Browse files Browse the repository at this point in the history
Package reorganization
  • Loading branch information
johningve authored Aug 12, 2022
2 parents 67c7f8b + 5debbb0 commit eb133bb
Show file tree
Hide file tree
Showing 73 changed files with 1,227 additions and 1,233 deletions.
35 changes: 18 additions & 17 deletions backend/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
"testing"
"time"

"github.com/relab/hotstuff/modules"

"github.com/golang/mock/gomock"
"github.com/relab/gorums"
"github.com/relab/hotstuff"
"github.com/relab/hotstuff/consensus"
"github.com/relab/hotstuff/crypto/keygen"
"github.com/relab/hotstuff/eventloop"
"github.com/relab/hotstuff/internal/testutil"
Expand All @@ -26,7 +27,7 @@ func TestConnect(t *testing.T) {
const n = 4
ctrl := gomock.NewController(t)
td := setup(t, ctrl, n)
builder := consensus.NewBuilder(1, td.keys[0])
builder := modules.NewConsensusBuilder(1, td.keys[0])
testutil.TestModules(t, ctrl, 1, td.keys[0], &builder)
teardown := createServers(t, td, ctrl)
defer teardown()
Expand All @@ -47,7 +48,7 @@ func TestConnect(t *testing.T) {
}

// testBase is a generic test for a unicast/multicast call
func testBase(t *testing.T, typ interface{}, send func(consensus.Configuration), handle eventloop.EventHandler) {
func testBase(t *testing.T, typ any, send func(modules.Configuration), handle eventloop.EventHandler) {
run := func(t *testing.T, setup setupFunc) {
const n = 4
ctrl := gomock.NewController(t)
Expand Down Expand Up @@ -79,20 +80,20 @@ func testBase(t *testing.T, typ interface{}, send func(consensus.Configuration),

func TestPropose(t *testing.T) {
var wg sync.WaitGroup
want := consensus.ProposeMsg{
want := hotstuff.ProposeMsg{
ID: 1,
Block: consensus.NewBlock(
consensus.GetGenesis().Hash(),
consensus.NewQuorumCert(nil, 0, consensus.GetGenesis().Hash()),
Block: hotstuff.NewBlock(
hotstuff.GetGenesis().Hash(),
hotstuff.NewQuorumCert(nil, 0, hotstuff.GetGenesis().Hash()),
"foo", 1, 1,
),
}
testBase(t, want, func(cfg consensus.Configuration) {
testBase(t, want, func(cfg modules.Configuration) {
wg.Add(3)
cfg.Propose(want)
wg.Wait()
}, func(event interface{}) {
got := event.(consensus.ProposeMsg)
}, func(event any) {
got := event.(hotstuff.ProposeMsg)
if got.ID != want.ID {
t.Errorf("wrong id in proposal: got: %d, want: %d", got.ID, want.ID)
}
Expand All @@ -105,18 +106,18 @@ func TestPropose(t *testing.T) {

func TestTimeout(t *testing.T) {
var wg sync.WaitGroup
want := consensus.TimeoutMsg{
want := hotstuff.TimeoutMsg{
ID: 1,
View: 1,
ViewSignature: nil,
SyncInfo: consensus.NewSyncInfo(),
SyncInfo: hotstuff.NewSyncInfo(),
}
testBase(t, want, func(cfg consensus.Configuration) {
testBase(t, want, func(cfg modules.Configuration) {
wg.Add(3)
cfg.Timeout(want)
wg.Wait()
}, func(event interface{}) {
got := event.(consensus.TimeoutMsg)
}, func(event any) {
got := event.(hotstuff.TimeoutMsg)
if got.ID != want.ID {
t.Errorf("wrong id in proposal: got: %d, want: %d", got.ID, want.ID)
}
Expand All @@ -133,7 +134,7 @@ type testData struct {
creds credentials.TransportCredentials
replicas []ReplicaInfo
listeners []net.Listener
keys []consensus.PrivateKey
keys []hotstuff.PrivateKey
builders testutil.BuilderList
}

Expand All @@ -143,7 +144,7 @@ func setupReplicas(t *testing.T, ctrl *gomock.Controller, n int) testData {
t.Helper()

listeners := make([]net.Listener, n)
keys := make([]consensus.PrivateKey, 0, n)
keys := make([]hotstuff.PrivateKey, 0, n)
replicas := make([]ReplicaInfo, 0, n)

// generate keys and replicaInfo
Expand Down
47 changes: 24 additions & 23 deletions backend/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"fmt"
"strings"

"github.com/relab/hotstuff/modules"

"github.com/relab/gorums"
"github.com/relab/hotstuff"
"github.com/relab/hotstuff/consensus"
"github.com/relab/hotstuff/internal/proto/hotstuffpb"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
Expand All @@ -22,7 +23,7 @@ import (
type Replica struct {
node *hotstuffpb.Node
id hotstuff.ID
pubKey consensus.PublicKey
pubKey hotstuff.PublicKey
voteCancel context.CancelFunc
newViewCancel context.CancelFunc
md map[string]string
Expand All @@ -34,12 +35,12 @@ func (r *Replica) ID() hotstuff.ID {
}

// PublicKey returns the replica's public key.
func (r *Replica) PublicKey() consensus.PublicKey {
func (r *Replica) PublicKey() hotstuff.PublicKey {
return r.pubKey
}

// Vote sends the partial certificate to the other replica.
func (r *Replica) Vote(cert consensus.PartialCert) {
func (r *Replica) Vote(cert hotstuff.PartialCert) {
if r.node == nil {
return
}
Expand All @@ -51,7 +52,7 @@ func (r *Replica) Vote(cert consensus.PartialCert) {
}

// NewView sends the quorum certificate to the other replica.
func (r *Replica) NewView(msg consensus.SyncInfo) {
func (r *Replica) NewView(msg hotstuff.SyncInfo) {
if r.node == nil {
return
}
Expand All @@ -77,18 +78,18 @@ type Config struct {
}

type subConfig struct {
mods *consensus.Modules
mods *modules.ConsensusCore
cfg *hotstuffpb.Configuration
replicas map[hotstuff.ID]consensus.Replica
replicas map[hotstuff.ID]modules.Replica
}

// InitConsensusModule gives the module a reference to the Modules object.
// InitModule gives the module a reference to the ConsensusCore object.
// It also allows the module to set module options using the OptionsBuilder.
func (cfg *Config) InitConsensusModule(mods *consensus.Modules, _ *consensus.OptionsBuilder) {
func (cfg *Config) InitModule(mods *modules.ConsensusCore, _ *modules.OptionsBuilder) {
cfg.mods = mods

// We delay processing `replicaConnected` events until after the configurations `connected` event has occurred.
cfg.mods.EventLoop().RegisterHandler(replicaConnected{}, func(event interface{}) {
cfg.mods.EventLoop().RegisterHandler(replicaConnected{}, func(event any) {
if !cfg.connected {
cfg.mods.EventLoop().DelayUntil(connected{}, event)
return
Expand All @@ -109,10 +110,10 @@ func NewConfig(creds credentials.TransportCredentials, opts ...gorums.ManagerOpt
}
opts = append(opts, gorums.WithGrpcDialOptions(grpcOpts...))

// initialization will be finished by InitConsensusModule
// initialization will be finished by InitModule
cfg := &Config{
subConfig: subConfig{
replicas: make(map[hotstuff.ID]consensus.Replica),
replicas: make(map[hotstuff.ID]modules.Replica),
},
opts: opts,
}
Expand Down Expand Up @@ -172,7 +173,7 @@ func (cfg *Config) GetRawConfiguration() gorums.RawConfiguration {
type ReplicaInfo struct {
ID hotstuff.ID
Address string
PubKey consensus.PublicKey
PubKey hotstuff.PublicKey
}

// Connect opens connections to the replicas in the configuration.
Expand Down Expand Up @@ -230,19 +231,19 @@ func (cfg *Config) Connect(replicas []ReplicaInfo) (err error) {
}

// Replicas returns all of the replicas in the configuration.
func (cfg *subConfig) Replicas() map[hotstuff.ID]consensus.Replica {
func (cfg *subConfig) Replicas() map[hotstuff.ID]modules.Replica {
return cfg.replicas
}

// Replica returns a replica if it is present in the configuration.
func (cfg *subConfig) Replica(id hotstuff.ID) (replica consensus.Replica, ok bool) {
func (cfg *subConfig) Replica(id hotstuff.ID) (replica modules.Replica, ok bool) {
replica, ok = cfg.replicas[id]
return
}

// SubConfig returns a subconfiguration containing the replicas specified in the ids slice.
func (cfg *Config) SubConfig(ids []hotstuff.ID) (sub consensus.Configuration, err error) {
replicas := make(map[hotstuff.ID]consensus.Replica)
func (cfg *Config) SubConfig(ids []hotstuff.ID) (sub modules.Configuration, err error) {
replicas := make(map[hotstuff.ID]modules.Replica)
nids := make([]uint32, len(ids))
for i, id := range ids {
nids[i] = uint32(id)
Expand All @@ -259,7 +260,7 @@ func (cfg *Config) SubConfig(ids []hotstuff.ID) (sub consensus.Configuration, er
}, nil
}

func (cfg *subConfig) SubConfig(_ []hotstuff.ID) (_ consensus.Configuration, err error) {
func (cfg *subConfig) SubConfig(_ []hotstuff.ID) (_ modules.Configuration, err error) {
return nil, errors.New("not supported")
}

Expand All @@ -274,7 +275,7 @@ func (cfg *subConfig) QuorumSize() int {
}

// Propose sends the block to all replicas in the configuration
func (cfg *subConfig) Propose(proposal consensus.ProposeMsg) {
func (cfg *subConfig) Propose(proposal hotstuff.ProposeMsg) {
if cfg.cfg == nil {
return
}
Expand All @@ -286,7 +287,7 @@ func (cfg *subConfig) Propose(proposal consensus.ProposeMsg) {
}

// Timeout sends the timeout message to all replicas.
func (cfg *subConfig) Timeout(msg consensus.TimeoutMsg) {
func (cfg *subConfig) Timeout(msg hotstuff.TimeoutMsg) {
if cfg.cfg == nil {
return
}
Expand All @@ -298,7 +299,7 @@ func (cfg *subConfig) Timeout(msg consensus.TimeoutMsg) {
}

// Fetch requests a block from all the replicas in the configuration
func (cfg *subConfig) Fetch(ctx context.Context, hash consensus.Hash) (*consensus.Block, bool) {
func (cfg *subConfig) Fetch(ctx context.Context, hash hotstuff.Hash) (*hotstuff.Block, bool) {
protoBlock, err := cfg.cfg.Fetch(ctx, &hotstuffpb.BlockHash{Hash: hash[:]})
if err != nil {
qcErr, ok := err.(gorums.QuorumCallError)
Expand All @@ -316,14 +317,14 @@ func (cfg *Config) Close() {
cfg.mgr.Close()
}

var _ consensus.Configuration = (*Config)(nil)
var _ modules.Configuration = (*Config)(nil)

type qspec struct{}

// FetchQF is the quorum function for the Fetch quorum call method.
// It simply returns true if one of the replies matches the requested block.
func (q qspec) FetchQF(in *hotstuffpb.BlockHash, replies map[uint32]*hotstuffpb.Block) (*hotstuffpb.Block, bool) {
var h consensus.Hash
var h hotstuff.Hash
copy(h[:], in.GetHash())
for _, b := range replies {
block := hotstuffpb.BlockFromProto(b)
Expand Down
16 changes: 8 additions & 8 deletions backend/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package backend
import (
"context"
"fmt"
"github.com/relab/hotstuff/modules"
"net"
"strconv"

"github.com/relab/gorums"
"github.com/relab/hotstuff"
"github.com/relab/hotstuff/consensus"
"github.com/relab/hotstuff/internal/proto/hotstuffpb"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
Expand All @@ -20,13 +20,13 @@ import (
// Server is the Server-side of the gorums backend.
// It is responsible for calling handler methods on the consensus instance.
type Server struct {
mods *consensus.Modules
mods *modules.ConsensusCore
gorumsSrv *gorums.Server
}

// InitConsensusModule gives the module a reference to the Modules object.
// InitModule gives the module a reference to the ConsensusCore object.
// It also allows the module to set module options using the OptionsBuilder.
func (srv *Server) InitConsensusModule(mods *consensus.Modules, _ *consensus.OptionsBuilder) {
func (srv *Server) InitModule(mods *modules.ConsensusCore, _ *modules.OptionsBuilder) {
srv.mods = mods
}

Expand Down Expand Up @@ -70,7 +70,7 @@ func (srv *Server) StartOnListener(listener net.Listener) {
}

// GetPeerIDFromContext extracts the ID of the peer from the context.
func GetPeerIDFromContext(ctx context.Context, cfg consensus.Configuration) (hotstuff.ID, error) {
func GetPeerIDFromContext(ctx context.Context, cfg modules.Configuration) (hotstuff.ID, error) {
peerInfo, ok := peer.FromContext(ctx)
if !ok {
return 0, fmt.Errorf("peerInfo not available")
Expand Down Expand Up @@ -144,7 +144,7 @@ func (impl *serviceImpl) Vote(ctx gorums.ServerCtx, cert *hotstuffpb.PartialCert
return
}

impl.srv.mods.EventLoop().AddEvent(consensus.VoteMsg{
impl.srv.mods.EventLoop().AddEvent(hotstuff.VoteMsg{
ID: id,
PartialCert: hotstuffpb.PartialCertFromProto(cert),
})
Expand All @@ -158,15 +158,15 @@ func (impl *serviceImpl) NewView(ctx gorums.ServerCtx, msg *hotstuffpb.SyncInfo)
return
}

impl.srv.mods.EventLoop().AddEvent(consensus.NewViewMsg{
impl.srv.mods.EventLoop().AddEvent(hotstuff.NewViewMsg{
ID: id,
SyncInfo: hotstuffpb.SyncInfoFromProto(msg),
})
}

// Fetch handles an incoming fetch request.
func (impl *serviceImpl) Fetch(ctx gorums.ServerCtx, pb *hotstuffpb.BlockHash) (*hotstuffpb.Block, error) {
var hash consensus.Hash
var hash hotstuff.Hash
copy(hash[:], pb.GetHash())

block, ok := impl.srv.mods.BlockChain().LocalGet(hash)
Expand Down
10 changes: 4 additions & 6 deletions consensus/block.go → block.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
package consensus
package hotstuff

import (
"crypto/sha256"
"encoding/binary"
"fmt"

"github.com/relab/hotstuff"
)

// Block contains a propsed "command", metadata for the protocol, and a link to the "parent" block.
type Block struct {
// keep a copy of the hash to avoid hashing multiple times
hash Hash
parent Hash
proposer hotstuff.ID
proposer ID
cmd Command
cert QuorumCert
view View
}

// NewBlock creates a new Block
func NewBlock(parent Hash, cert QuorumCert, cmd Command, view View, proposer hotstuff.ID) *Block {
func NewBlock(parent Hash, cert QuorumCert, cmd Command, view View, proposer ID) *Block {
b := &Block{
parent: parent,
cert: cert,
Expand Down Expand Up @@ -50,7 +48,7 @@ func (b *Block) Hash() Hash {
}

// Proposer returns the id of the replica who proposed the block.
func (b *Block) Proposer() hotstuff.ID {
func (b *Block) Proposer() ID {
return b.proposer
}

Expand Down
Loading

0 comments on commit eb133bb

Please sign in to comment.