Skip to content

Commit

Permalink
Refactor to allow roster changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Gilthoniel committed Apr 24, 2020
1 parent d5b839f commit 5aea26d
Show file tree
Hide file tree
Showing 42 changed files with 1,099 additions and 1,402 deletions.
3 changes: 0 additions & 3 deletions blockchain/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ type Block interface {
// GetHash returns the footprint of the block.
GetHash() []byte

// GetPlayers returns the participants involved in the block creation.
GetPlayers() mino.Players

// GetPayload returns the payload of the block.
GetPayload() proto.Message
}
Expand Down
149 changes: 32 additions & 117 deletions blockchain/skipchain/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"go.dedis.ch/fabric/consensus"
"go.dedis.ch/fabric/crypto"
"go.dedis.ch/fabric/encoding"
"go.dedis.ch/fabric/mino"
"golang.org/x/xerrors"
)

Expand Down Expand Up @@ -47,15 +46,11 @@ func (f sha256Factory) New() hash.Hash {
// - implements consensus.Proposal
// - implements fmt.Stringer
type SkipBlock struct {
hash Digest
verifier crypto.Verifier
hash Digest

// Index is the block index since the genesis block.
Index uint64

// Conodes is the list of conodes participating in the consensus.
Conodes Conodes

// GenesisID is the hash of the genesis block which represents the chain
// identifier.
GenesisID Digest
Expand All @@ -68,35 +63,6 @@ type SkipBlock struct {
Payload proto.Message
}

func newSkipBlock(
encoder encoding.ProtoMarshaler,
hashFactory crypto.HashFactory,
verifier crypto.Verifier,
index uint64,
conodes Conodes,
id Digest,
backLink Digest,
data proto.Message,
) (SkipBlock, error) {
block := SkipBlock{
verifier: verifier,
Index: index,
Conodes: conodes,
GenesisID: id,
BackLink: backLink,
Payload: data,
}

hash, err := block.computeHash(hashFactory, encoder)
if err != nil {
return SkipBlock{}, xerrors.Errorf("couldn't hash the block: %w", err)
}

block.hash = hash

return block, nil
}

// GetIndex returns the index of the block since the genesis block.
func (b SkipBlock) GetIndex() uint64 {
return b.Index
Expand All @@ -114,18 +80,6 @@ func (b SkipBlock) GetPreviousHash() []byte {
return b.BackLink.Bytes()
}

// GetPlayers implements blockchain.Block. It returns the list of players.
func (b SkipBlock) GetPlayers() mino.Players {
return b.Conodes
}

// GetVerifier implements consensus.Proposal. It returns the verifier for the
// block.
// TODO: it might have sense to remove this function.
func (b SkipBlock) GetVerifier() crypto.Verifier {
return b.verifier
}

// GetPayload implements blockchain.Block. It returns the block payload.
func (b SkipBlock) GetPayload() proto.Message {
return b.Payload
Expand All @@ -139,17 +93,11 @@ func (b SkipBlock) Pack(encoder encoding.ProtoMarshaler) (proto.Message, error)
return nil, xerrors.Errorf("couldn't marshal the payload: %v", err)
}

roster, err := encoder.Pack(b.Conodes)
if err != nil {
return nil, xerrors.Errorf("couldn't pack the conodes: %v", err)
}

blockproto := &BlockProto{
Index: b.Index,
GenesisID: b.GenesisID.Bytes(),
Backlink: b.BackLink.Bytes(),
Payload: payloadAny,
Roster: roster.(*Roster),
}

return blockproto, nil
Expand All @@ -173,13 +121,6 @@ func (b SkipBlock) computeHash(factory crypto.HashFactory,
return Digest{}, xerrors.Errorf("couldn't write index: %v", err)
}

if b.Conodes != nil {
_, err = b.Conodes.WriteTo(h)
if err != nil {
return Digest{}, xerrors.Errorf("couldn't write conodes: %v", err)
}
}

_, err = h.Write(b.GenesisID.Bytes())
if err != nil {
return Digest{}, xerrors.Errorf("couldn't write genesis hash: %v", err)
Expand Down Expand Up @@ -214,11 +155,6 @@ type VerifiableBlock struct {
// Verify implements blockchain.VerifiableBlock. It makes sure the integrity of
// the chain is valid.
func (vb VerifiableBlock) Verify(v crypto.Verifier) error {
err := vb.Chain.Verify(v)
if err != nil {
return xerrors.Errorf("couldn't verify the chain: %v", err)
}

if !bytes.Equal(vb.GetHash(), vb.Chain.GetLastHash()) {
return xerrors.Errorf("mismatch target %x != %x", vb.GetHash(), vb.Chain.GetLastHash())
}
Expand Down Expand Up @@ -256,6 +192,17 @@ type blockFactory struct {
hashFactory crypto.HashFactory
}

func (f blockFactory) prepareBlock(block *SkipBlock) error {
hash, err := block.computeHash(f.hashFactory, f.encoder)
if err != nil {
return xerrors.Errorf("couldn't hash the block: %w", err)
}

block.hash = hash

return nil
}

func (f blockFactory) fromPrevious(prev SkipBlock, data proto.Message) (SkipBlock, error) {
var genesisID Digest
if prev.Index == 0 {
Expand All @@ -264,43 +211,21 @@ func (f blockFactory) fromPrevious(prev SkipBlock, data proto.Message) (SkipBloc
genesisID = prev.GenesisID
}

block, err := newSkipBlock(
f.encoder,
f.hashFactory,
prev.verifier,
prev.Index+1,
prev.Conodes,
genesisID,
prev.hash,
data,
)
block := SkipBlock{
Index: prev.Index + 1,
GenesisID: genesisID,
BackLink: prev.hash,
Payload: data,
}

err := f.prepareBlock(&block)
if err != nil {
return block, xerrors.Errorf("couldn't make block: %w", err)
}

return block, nil
}

func (f blockFactory) decodeConodes(msgs []*ConodeProto) (Conodes, error) {
pubkeyFactory := f.cosi.GetPublicKeyFactory()
addrFactory := f.mino.GetAddressFactory()

conodes := make(Conodes, len(msgs))
for i, msg := range msgs {
publicKey, err := pubkeyFactory.FromProto(msg.GetPublicKey())
if err != nil {
return nil, xerrors.Errorf("couldn't decode public key: %v", err)
}

conodes[i] = Conode{
addr: addrFactory.FromText(msg.GetAddress()),
publicKey: publicKey,
}
}
return conodes, nil
}

func (f blockFactory) decodeBlock(src proto.Message) (SkipBlock, error) {
in, ok := src.(*BlockProto)
if !ok {
Expand All @@ -315,32 +240,19 @@ func (f blockFactory) decodeBlock(src proto.Message) (SkipBlock, error) {
backLink := Digest{}
copy(backLink[:], in.GetBacklink())

conodes, err := f.decodeConodes(in.GetRoster().GetConodes())
if err != nil {
return SkipBlock{}, err
}

verifier, err := f.cosi.GetVerifier(conodes)
if err != nil {
return SkipBlock{}, xerrors.Errorf("couldn't make verifier: %v", err)
}

genesisID := Digest{}
copy(genesisID[:], in.GetGenesisID())

block, err := newSkipBlock(
f.encoder,
f.hashFactory,
verifier,
in.GetIndex(),
conodes,
genesisID,
backLink,
payload,
)
block := SkipBlock{
Index: in.GetIndex(),
GenesisID: genesisID,
BackLink: backLink,
Payload: payload,
}

err = f.prepareBlock(&block)
if err != nil {
return block, xerrors.Errorf("couldn't make block: %v", err)
return block, xerrors.Errorf("couldn't prepare block: %v", err)
}

return block, nil
Expand All @@ -359,7 +271,10 @@ func (f blockFactory) FromVerifiable(src proto.Message) (blockchain.Block, error
return nil, xerrors.Errorf("couldn't decode the block: %v", err)
}

chainFactory := f.consensus.GetChainFactory()
chainFactory, err := f.consensus.GetChainFactory()
if err != nil {
return nil, err
}

chain, err := chainFactory.FromProto(in.GetChain())
if err != nil {
Expand All @@ -371,7 +286,7 @@ func (f blockFactory) FromVerifiable(src proto.Message) (blockchain.Block, error
Chain: chain,
}

err = vb.Verify(block.verifier)
err = vb.Verify(nil)
if err != nil {
return nil, xerrors.Errorf("couldn't verify: %v", err)
}
Expand Down
Loading

0 comments on commit 5aea26d

Please sign in to comment.