Skip to content
Go implementation of the Lean Helix Byzantine fault tolerant consensus algorithm
Go Shell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci New Threading Model (#67) Aug 19, 2019
.idea/runConfigurations New Threading Model (#67) Aug 19, 2019
instrumentation/metrics Added license files Mar 24, 2019
services New Threading Model (#67) Aug 19, 2019
spec Rename lean-helix-readme.md to README.md May 15, 2019
state New Threading Model (#67) Aug 19, 2019
test New Threading Model (#67) Aug 19, 2019
test_poc New Threading Model (#67) Aug 19, 2019
vendor/github.com New Threading Model (#67) Aug 19, 2019
.gitignore Adding test harness (WIP) Aug 21, 2018
.gitmodules New Threading Model (#67) Aug 19, 2019
DEV-GUIDE.md
LICENSE Initial commit Aug 12, 2018
LICENSE-HEADER
NETWORK-TOU.md
README.md Update README.md Mar 5, 2019
git-submodule-checkout.sh Typo in git submodules script Aug 30, 2018
go.mod adding support for go modules Jul 28, 2019
go.sum
mainloop.go New Threading Model (#67) Aug 19, 2019
mainloop_test.go New Threading Model (#67) Aug 19, 2019
test.sh New Threading Model (#67) Aug 19, 2019
workerloop.go
workerloop_test.go New Threading Model (#67) Aug 19, 2019

README.md

lean-helix-go

CircleCI

Lean Helix consensus algorithm implementation in Go.

TODO

Installation

  • Download from Github
  • Run ./git-submodule-checkout.sh - this will install all git submodules under vendor folder

Terminology

  • Library - this repo

  • Consumer - the user of this library

  • API - methods in the library that the consumer can execute (e.g. NewLeanHelix())

  • SPI - Service Programming Interface - interfaces defined in the library, for which the consumer provides the implementation

    • For example - Communication is responsible for transferring messages between nodes in the network. The library cannot assume anything about the consumer's network, therefore it is up to the consumer to provide the actual implementation of message transfer.
  • membuffers - the 3rd party dependency that the library uses for serializing its messages into and from byte arrays

  • protos - the *.proto files (in Google's Protobuf language) which define the structure of messages passing between Lean Helix and its consumer.

    • The membuffers library takes *.proto files and compiles them to *.mb.go files
    • Any change to *.proto files requires running cd types; ./build.sh to regenerate the respective *.mb.go !
  • Lean Helix (object) - runs the infinite loop that with every iteration requests a new block, reaches consensus, and broadcasts the commit message. There is only a single instance of this type, it is aware of all blocks pending consensus (of all heights). It holds one or more LeanHelixTerm instances.

  • Committee - the ordered list of nodes participating in a single Term. The first node in the committee is the first leader. If that leader is unable to reach consensus on its block proposal, the next node in the committee becomes the new leader and the process repeats.

  • Term - a.k.a. consensus round - the process of reaching consensus for a specific block height - the algo is trying to reach consensus on a block of some height during a term. A Term handles only a specific height, but the algo can locally store blocks for several heights. It will associate each block height with its term. See struct LeanHelixTerm.

  • View - part of the Term, during which a specific leader node proposes a block and tries to reach consensus with its validators (the other, non-leader nodes). If that leader is unable to reach consensus for any reason (usually timeout), the view is incremented and a new leader is set. The next leader is the next node in the committee So - each view (modulo the number of nodes in a committee) has a different leader.

Design

Formal spec for this library can be found under the /spec folder.

API

  • NewLeanHelix()
  • ValidateConsensusOnBlock
  • tbd

SPI

Interfaces provided by the library, implemented by the consumer

  • KeyManager (to be renamed to SignerVerifier - tbd)
  • BlockUtils (to be split into BlockProvider and BlockValidator)
  • NetworkCommunication

Internal structs

tbd These are internal, not to be used directly by the consumer of the library

  • LeanHelixTerm handles a specific term - that is it handles reaching consensus on a single block of some height. It has no knowledge of blocks of other heights. There may be multiple LeanHelixTerm instances active at the same time.

TBD

Messages

The library creates and serializes its own messages into and from byte arrays. The library does not actually transfer messages over the wire as it does not assume anything about the consumer's network.

Message handling

tbd go over make sure still relevant Message creation

type MessageFactory interface {
	// Message creation methods

	CreatePreprepareMessage(blockRef BlockRef, sender SenderSignature, block Block) PreprepareMessage
	CreatePrepareMessage(blockRef BlockRef, sender SenderSignature) PrepareMessage
	CreateCommitMessage(blockRef BlockRef, sender SenderSignature) CommitMessage
	CreateViewChangeMessage(vcHeader ViewChangeHeader, sender SenderSignature, block Block) ViewChangeMessage
	CreateNewViewMessage(preprepareMessage PreprepareMessage, nvHeader NewViewHeader, sender SenderSignature) NewViewMessage

	// Auxiliary methods

	CreateSenderSignature(sender []byte, signature []byte) SenderSignature
	CreateBlockRef(messageType int, blockHeight int, view int, blockHash []byte) BlockRef
	CreateNewViewHeader(messageType int, blockHeight int, view int, confirmations []ViewChangeConfirmation) NewViewHeader
	CreateViewChangeConfirmation(vcHeader ViewChangeHeader, sender SenderSignature) ViewChangeConfirmation
	CreateViewChangeHeader(blockHeight int, view int, proof PreparedProof) ViewChangeHeader
	CreatePreparedProof(ppBlockRef BlockRef, pBlockRef BlockRef, ppSender SenderSignature, pSenders []SenderSignature) PreparedProof
}

Message primitives

type PreprepareMessage interface {
	Serializable
	SignedHeader() BlockRef
	Sender() SenderSignature
	Block() Block
}

type PrepareMessage interface {
	Serializable
	SignedHeader() BlockRef
	Sender() SenderSignature
}

type CommitMessage interface {
	Serializable
	SignedHeader() BlockRef
	Sender() SenderSignature
}

type ViewChangeMessage interface {
	Serializable
	SignedHeader() ViewChangeHeader
	Sender() SenderSignature
	Block() Block
}

type NewViewMessage interface {
	Serializable
	SignedHeader() NewViewHeader
	PreprepareMessage() PreprepareMessage
	Sender() SenderSignature
}

Message parts

type BlockRef interface {
	Serializable
	HasMessageType
	BlockHeight() BlockHeight
	View() View
	BlockHash() BlockHash
}

type ViewChangeHeader interface {
	Serializable
	HasMessageType
	BlockHeight() BlockHeight
	View() View
	PreparedProof() PreparedProof
}

type SenderSignature interface {
	Serializable
	SenderMemberId() MemberId
	Signature() Signature
}

type HasMessageType interface {
	MessageType() MessageType
}

type Serializable interface {
	Serialize() []byte
}

// TODO this is different from definition of LeanHelixPreparedProof in lean_helix.mb.go:448 in orbs-spec
type PreparedProof interface {
	Serializable
	PPBlockRef() BlockRef
	PBlockRef() BlockRef
	PPSender() SenderSignature
	PSenders() []SenderSignature
}

type NewViewHeader interface {
	Serializable
	HasMessageType
	BlockHeight() BlockHeight
	View() View
	ViewChangeConfirmations() []ViewChangeConfirmation
}

type ViewChangeConfirmation interface {
	Serializable
	SignedHeader() ViewChangeHeader
	Sender() SenderSignature
}

Block Proof

type BlockProof interface {
  BlockHeight() BlockHeight
  View() View // this is only for display in a future block viewer - it is of no use to Orbs as it is lh-internal
  BlockHash() BlockHash
  Signers() []MemberId
  ConsensusSpecificData() []byte
}

NetworkCommunication

type NetworkCommunication interface {
	SendToMembers(publicKeys []MemberId, messageType string, message []MessageTransporter)
	RequestCommittee(seed uint64) []MemberId
	IsMember(pk MemberId) bool
	SendPreprepare(publicKeys []MemberId, message PreprepareMessage)
	SendPrepare(publicKeys []MemberId, message PrepareMessage)
	SendCommit(publicKeys []MemberId, message CommitMessage)
	SendViewChange(publicKey MemberId, message ViewChangeMessage)
	SendNewView(publicKeys []MemberId, message NewViewMessage)

KeyManager

type KeyManager interface {
	Sign(content []byte) []byte
	Verify(content []byte, sender SenderSignature) bool
	MyMemberId() MemberId
}

BlockUtils

type BlockUtils interface {
	CalculateBlockHash(block Block) BlockHash
	RequestNewBlock(blockHeight BlockHeight) Block
	ValidateBlock(block Block) bool
	RequestCommittee()
}

TODO add this:

  • MessageReceiver
    • HandleLeanHelixPrePrepare, HandleLeanHelixPrepare, HandleLeanHelixCommit, HandleLeanHelixViewChange, HandleLeanHelixNewView

On creation of the lib instance (of type LeanHelixLib) by Orbs, Orbs will pass a service parameter to the lib instance. That service will contain implementations of the above interfaces

Installation

Prerequisites

  1. Make sure Go is installed (version 1.10 or later).

    Verify with go version

  2. Make sure Go workspace bin is in your path.

    Install with export PATH=$PATH:`go env GOPATH`/bin

    Verify with echo $PATH

Get and build

  1. Get the library into your Go workspace:

    go get github.com/orbs-network/lean-helix-go/go/...

Test

  1. Test the library (unit tests and end to end tests):

    ./test.sh

Terminology

Logging

JSON-based format to make it easily on log capturing tools.

DEBUG

INFO

By design, there is no WARN log level. We believe such messages are no more actionable than regular INFO messages. For example, a view timeout could easily be classified as WARN as it is "exceptional" though it is recoverable, it is a normal part of the algo so it is expected to happen occasionally. If there are too many timeouts, it is the job of a log monitoring tool to trigger some alert over this.

ERRORs are reserved for unrecoverable situations, either due to bugs, assertions (again bugs), panics and OS errors - all of which require either node restart or bug fixing.

You can’t perform that action at this time.