blockchain

package
v0.0.0-...-4c5418b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2020 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Put the fake implementations used by the production code for the integration test.

Index

Constants

View Source
const (
	TypeNil          = Type(0)
	TypeBlock        = Type(1)
	TypeProposal     = Type(2)
	TypeVote         = Type(3)
	TypeNotarization = Type(4)
	TypeClockMsg     = Type(5)
	TypeClockMsgNota = Type(6)
)

Variables

This section is empty.

Functions

func DumpFakeChain

func DumpFakeChain(bc BlockChain, b Block, showNota bool) string

func PrepareFakeChain

func PrepareFakeChain(
	req *require.Assertions, bc BlockChain, base BlockSn, epoch Epoch, k uint32,
	voters []string, newBlockBodies []string)

PrepareFakeChain adds blocks to the existing fake chain. Assume using the stability-favoring approach. k affects how to add the notarization in the block. For (e,s) * s=1 : contain the notarizations of the previous k blocks. * s in [2,k]: contain no notarization. * s>k : contain the notarization of (e,s-k).

func SetBootnodeIdsForTest

func SetBootnodeIdsForTest(ids []string)

Types

type Block

type Block interface {
	Message

	ImplementsBlock()

	GetParentBlockSn() BlockSn
	GetHash() Hash
	// GetNumber() returns the number (height) of this block.
	GetNumber() uint32
	GetNotarizations() []Notarization
	Compare(other Block) int

	// GetBodyString() returns a string to represent the block.
	// This is used for logging/testing/debugging.
	GetBodyString() string
}

NOTE: the function ImplementsX() is used to ensure no interface includes another interface's methods. For example, assume A and B are interfaces and A includes all methods of B. The object implemented A can be converted to B. Adding ImplementsX() to ensure these data-type interfaces are exclusive. Otherwise, we may get unexpected result after doing a type cast. ImplementsX() does nothing and shouldn't be called.

func GetParentBlock

func GetParentBlock(bc BlockChain, b Block) Block

func NewBlockFake

func NewBlockFake(sn BlockSn, parentSn BlockSn, nBlock uint32,
	notas []Notarization, body string) Block

type BlockAndEvent

type BlockAndEvent struct {
	Block Block
	Event *FinalizedChainExtendedEvent
}

type BlockChain

type BlockChain interface {
	// ContainsBlock returns true if the block(s) exists.
	// Expect this is more efficient compared to using GetBlock() == nil.
	ContainsBlock(s BlockSn) bool
	// GetBlock returns nil if there is no such value.
	GetBlock(s BlockSn) Block
	GetGenesisBlock() Block
	// GetNotarization returns nil if there is no such value.
	GetNotarization(s BlockSn) Notarization
	// GetFreshestNotarizedChain() returns the last block of the freshest notarized chain
	// decided by the all received notarizations.
	GetFreshestNotarizedChain() Block
	// GetFinalizedChain() returns the last block of the finalized chain.
	// Unlike the freshest notarized chain, we use notarizations in blocks to decide the finalized
	// chain. In other words, notarizations received from AddNotarization() are not used.
	// This constraint makes the finality stronger in practice.
	// When the freshest notarized chain contains 2K consecutive normal blocks,
	// the finalize chain is the one without the last 2k blocks. Note that it is possible
	// that the finalized chain doesn't grow while the freshest notarized chain keeps growing.
	// NOTE: To simplify the implementation, the notarizations in a timeout block doesn't finalize
	// any new block in current design. We can remove this constraint later.
	GetFinalizedChain() Block

	// InsertBlock returns error if:
	// * |b| already exists.
	// * |b|'s parent doesn't exist in the chain.
	// * notarizations in |b| doesn't follow the rules. See rules above BlockChain.
	// * Any other invalid block format based on the implementation definition.
	// The error may support IsTemporary().
	// If the error is temporary, the caller should catch up previous blocks and then insert
	// the block again. During the call, the finalized chain may be updated.
	InsertBlock(b Block) error

	// StartCreatingNewBlocks returns a channel with buffer size = |K|.
	// The first new block's BlockSn is {|epoch|,1} and its parent is the freshest notarized block.
	// BlockAndEvent.Event is set if the new block extends the finalized chain.
	// This fits the stability-favoring approach in PaLa.
	StartCreatingNewBlocks(epoch Epoch) (chan BlockAndEvent, error)
	// StopCreatingNewBlocks stops the creation. However, there may be some blocks in the channel returned
	// by StartCreatingNewBlocks(). The call returns after the worker goroutine ends.
	// It's safe to call this without calling StartCreatingNewBlocks().
	StopCreatingNewBlocks() error
	// IsCreatingBlock() returns true if the worker goroutine keeps trying to create new blocks.
	IsCreatingBlock() bool
	// AddNotarization may update the freshest notarized chain and/or continue creating a new block
	// if StartCreatingNewBlocks() is called before. Return error if:
	// * the corresponding block does not exist.
	// * the parent block's notarization does not exist.
	// Note that the notarization can be stored anywhere (even in memory) and may be lost
	// after we recreate the BlockChain object.
	AddNotarization(n Notarization) error

	// NewNotificationChannel creates a new channel used to notify events such as
	// FreshestNotarizedChainExtendedEvent and FinalizedChainExtendedEvent.
	NewNotificationChannel() <-chan interface{}
	// RemoveNotificationChannel removes the returned channel from NewNotificationChannel.
	RemoveNotificationChannel(target <-chan interface{})
}

Requirement: * All operations are goroutine-safe. * Follow the rule to store notarizations on chain. For block (e,s):

  • s=1 : contain the notarizations of the previous k blocks.
  • s in [2,k]: contain no notarization.
  • s>k : contain the notarization of (e,s-k).
  • The implementation must receive an argument K (outstanding unnotarized proposals) which affect GetFinalizedChain() and StartCreatingNewBlocks().
  • InsertBlock()/AddNotarization() must guarantee the blocks/notarizations are added in order. This constraint simplifies the implementation of managing freshest notarized chain.

func New

func New(cfg Config) (BlockChain, error)

New returns a BlockChain whose genesis block is always created.

TODO(thunder): support a real BlockChain

func NewBlockChainFake

func NewBlockChainFake(k uint32) (BlockChain, error)

func NewBlockChainFakeWithDelay

func NewBlockChainFakeWithDelay(k uint32, delay time.Duration) (BlockChain, error)

type BlockChainFake

type BlockChainFake struct {
	// contains filtered or unexported fields
}

About goroutine-safety: * All public methods hold mutex by themselves. * Most private methods assume the caller holds the mutex.

func (*BlockChainFake) AddNotarization

func (bc *BlockChainFake) AddNotarization(n Notarization) error

func (*BlockChainFake) ComputeFinalizedChain

func (bc *BlockChainFake) ComputeFinalizedChain() Block

ComputeFinalizedChain is the baseline for correctness. The time complexity is O(N).

func (*BlockChainFake) ComputeFreshestNotarizedChain

func (bc *BlockChainFake) ComputeFreshestNotarizedChain() Block

ComputeFreshestNotarizedChain is the baseline for correctness. The time complexity is O(N).

func (*BlockChainFake) ContainsBlock

func (bc *BlockChainFake) ContainsBlock(s BlockSn) bool

func (*BlockChainFake) GetBlock

func (bc *BlockChainFake) GetBlock(s BlockSn) Block

func (*BlockChainFake) GetFinalizedChain

func (bc *BlockChainFake) GetFinalizedChain() Block

func (*BlockChainFake) GetFreshestNotarizedChain

func (bc *BlockChainFake) GetFreshestNotarizedChain() Block

func (*BlockChainFake) GetGenesisBlock

func (bc *BlockChainFake) GetGenesisBlock() Block

func (*BlockChainFake) GetLongestChain

func (bc *BlockChainFake) GetLongestChain() Block

func (*BlockChainFake) GetNotarization

func (bc *BlockChainFake) GetNotarization(s BlockSn) Notarization

func (*BlockChainFake) InsertBlock

func (bc *BlockChainFake) InsertBlock(b Block) error

TODO: in production system, we should reject b if it is not extended from b.finalizedChain. Exception: b is the first block of this session, and its parent is the stop block in the last session.

func (*BlockChainFake) IsCreatingBlock

func (bc *BlockChainFake) IsCreatingBlock() bool

func (*BlockChainFake) NewNotificationChannel

func (bc *BlockChainFake) NewNotificationChannel() <-chan interface{}

func (*BlockChainFake) RemoveNotificationChannel

func (bc *BlockChainFake) RemoveNotificationChannel(target <-chan interface{})

func (*BlockChainFake) Reset

func (bc *BlockChainFake) Reset() error

Reset wipes out all data.

func (*BlockChainFake) SetStopBlockNumber

func (bc *BlockChainFake) SetStopBlockNumber(stopBlockNumber uint32)

func (*BlockChainFake) StartCreatingNewBlocks

func (bc *BlockChainFake) StartCreatingNewBlocks(epoch Epoch) (chan BlockAndEvent, error)

func (*BlockChainFake) StopCreatingNewBlocks

func (bc *BlockChainFake) StopCreatingNewBlocks() error

Stop the creation. However, there may be some blocks in the returned channel by StartCreatingNewBlocks().

type BlockFake

type BlockFake struct {
	// contains filtered or unexported fields
}

func (*BlockFake) Compare

func (b *BlockFake) Compare(other Block) int

func (*BlockFake) GetBlockSn

func (b *BlockFake) GetBlockSn() BlockSn

func (*BlockFake) GetBody

func (b *BlockFake) GetBody() []byte

func (*BlockFake) GetBodyString

func (b *BlockFake) GetBodyString() string

func (*BlockFake) GetDebugString

func (b *BlockFake) GetDebugString() string

func (*BlockFake) GetHash

func (b *BlockFake) GetHash() Hash

func (*BlockFake) GetNotarizations

func (b *BlockFake) GetNotarizations() []Notarization

func (*BlockFake) GetNumber

func (b *BlockFake) GetNumber() uint32

func (*BlockFake) GetParentBlockSn

func (b *BlockFake) GetParentBlockSn() BlockSn

func (*BlockFake) GetType

func (b *BlockFake) GetType() Type

func (*BlockFake) ImplementsBlock

func (b *BlockFake) ImplementsBlock()

type BlockSn

type BlockSn struct {
	Epoch Epoch
	S     uint32
}

Estimate a rough lower bound: (2**32-1) / (86400*365) == 136.19 (years) uint32 is large enough. TODO(thunder): add Session and refine the reconfiguration.

func GetGenesisBlockSn

func GetGenesisBlockSn() BlockSn

func NewBlockSnFromBytes

func NewBlockSnFromBytes(bytes []byte) (BlockSn, []byte, error)

NewBlockSnFromBytes unmarshal the serialzed block (in byte array), extract the block seq #, the rest of the bytes and errors if any.

func (BlockSn) Compare

func (s BlockSn) Compare(s2 BlockSn) int

func (BlockSn) GetBlockSn

func (s BlockSn) GetBlockSn() BlockSn

func (BlockSn) IsGenesis

func (s BlockSn) IsGenesis() bool

func (BlockSn) IsNil

func (s BlockSn) IsNil() bool

func (BlockSn) Less

func (s BlockSn) Less(s2 llrb.Item) bool

func (BlockSn) String

func (s BlockSn) String() string

func (BlockSn) ToBytes

func (s BlockSn) ToBytes() []byte

type BlockSnGetter

type BlockSnGetter interface {
	GetBlockSn() BlockSn
}

type ByBlockSn

type ByBlockSn []Message

func (ByBlockSn) Len

func (s ByBlockSn) Len() int

func (ByBlockSn) Less

func (s ByBlockSn) Less(i, j int) bool

func (ByBlockSn) Swap

func (s ByBlockSn) Swap(i, j int)

type ClockMsg

type ClockMsg interface {
	Message

	ImplementsClockMsg()

	GetEpoch() Epoch
	GetVoterId() string
}

type ClockMsgFake

type ClockMsgFake struct {
	// contains filtered or unexported fields
}

func (*ClockMsgFake) GetBlockSn

func (c *ClockMsgFake) GetBlockSn() BlockSn

A helper function for logging.

func (*ClockMsgFake) GetBody

func (c *ClockMsgFake) GetBody() []byte

func (*ClockMsgFake) GetDebugString

func (c *ClockMsgFake) GetDebugString() string

func (*ClockMsgFake) GetEpoch

func (c *ClockMsgFake) GetEpoch() Epoch

func (*ClockMsgFake) GetType

func (c *ClockMsgFake) GetType() Type

func (*ClockMsgFake) GetVoterId

func (c *ClockMsgFake) GetVoterId() string

func (*ClockMsgFake) ImplementsClockMsg

func (c *ClockMsgFake) ImplementsClockMsg()

type ClockMsgNota

type ClockMsgNota interface {
	Message

	ImplementsClockMsgNota()

	GetEpoch() Epoch
	GetNVote() uint16
}

func NewClockMsgNotaFake

func NewClockMsgNotaFake(epoch Epoch, voterIds []string) ClockMsgNota

type ClockMsgNotaFake

type ClockMsgNotaFake struct {
	// contains filtered or unexported fields
}

func (*ClockMsgNotaFake) GetBlockSn

func (n *ClockMsgNotaFake) GetBlockSn() BlockSn

func (*ClockMsgNotaFake) GetBody

func (n *ClockMsgNotaFake) GetBody() []byte

func (*ClockMsgNotaFake) GetDebugString

func (n *ClockMsgNotaFake) GetDebugString() string

func (*ClockMsgNotaFake) GetEpoch

func (n *ClockMsgNotaFake) GetEpoch() Epoch

func (*ClockMsgNotaFake) GetNVote

func (n *ClockMsgNotaFake) GetNVote() uint16

func (*ClockMsgNotaFake) GetType

func (n *ClockMsgNotaFake) GetType() Type

func (*ClockMsgNotaFake) GetVoterIds

func (n *ClockMsgNotaFake) GetVoterIds() []string

func (*ClockMsgNotaFake) ImplementsClockMsgNota

func (n *ClockMsgNotaFake) ImplementsClockMsgNota()

func (*ClockMsgNotaFake) Verify

func (n *ClockMsgNotaFake) Verify() bool

type Config

type Config struct {
}

type DataUnmarshaller

type DataUnmarshaller interface {
	// UnmarshalBlock receives Block.GetBody() and returns Block and the rest of the bytes.
	UnmarshalBlock([]byte) (Block, []byte, error)
	// UnmarshalProposal receives Proposal.GetBody() and returns Proposal and the rest of the bytes.
	UnmarshalProposal([]byte) (Proposal, []byte, error)
	// UnmarshalVote receives Vote.GetBody() and returns Vote and the rest of the bytes.
	UnmarshalVote([]byte) (Vote, []byte, error)
	// UnmarshalNotarization receives Notarization.GetBody() and returns Notarization and
	// the rest of the bytes.
	UnmarshalNotarization([]byte) (Notarization, []byte, error)
	// UnmarshalClockMsg receives ClockMsg.GetBody() and returns ClockMsg and the rest of the bytes.
	UnmarshalClockMsg([]byte) (ClockMsg, []byte, error)
	// UnmarshalClockMsgNota receives ClockMsgNota.GetBody()
	// and returns ClockMsgNota and the rest of the bytes.
	UnmarshalClockMsgNota([]byte) (ClockMsgNota, []byte, error)
}

type DataUnmarshallerFake

type DataUnmarshallerFake struct {
}

func (*DataUnmarshallerFake) UnmarshalBlock

func (du *DataUnmarshallerFake) UnmarshalBlock(bytes []byte) (Block, []byte, error)

UnmarshalBlock unmarshal the output of BlockFake.GetBody().

func (*DataUnmarshallerFake) UnmarshalClockMsg

func (du *DataUnmarshallerFake) UnmarshalClockMsg(bytes []byte) (ClockMsg, []byte, error)

UnmarshalClockMsg unmarshal the output of ClockMsgFake.GetBody().

func (*DataUnmarshallerFake) UnmarshalClockMsgNota

func (du *DataUnmarshallerFake) UnmarshalClockMsgNota(
	bytes []byte) (ClockMsgNota, []byte, error)

UnmarshalClockMsgNota unmarshal the output of ClockMsgNotaFake.GetBody().

func (*DataUnmarshallerFake) UnmarshalNotarization

func (du *DataUnmarshallerFake) UnmarshalNotarization(bytes []byte) (Notarization, []byte, error)

UnmarshalNotarization unmarshal the output of NotarizationFake.GetBody().

func (*DataUnmarshallerFake) UnmarshalProposal

func (du *DataUnmarshallerFake) UnmarshalProposal(bytes []byte) (Proposal, []byte, error)

UnmarshalProposal unmarshal the output of ProposalFake.GetBody().

func (*DataUnmarshallerFake) UnmarshalVote

func (du *DataUnmarshallerFake) UnmarshalVote(bytes []byte) (Vote, []byte, error)

UnmarshalVote unmarshal the output of VoteFake.GetBody().

type ElectionResult

type ElectionResult struct {
	// contains filtered or unexported fields
}

NOTE: Maybe we can move ElectionResult to blockchain.go if it's easy to use for the real implementation.

All data are immutable after being set.

func NewElectionResult

func NewElectionResult(consensusId []string, begin Epoch, end Epoch) ElectionResult

func (ElectionResult) Contain

func (t ElectionResult) Contain(targetId string, epoch Epoch) bool

func (ElectionResult) GetConsensusIds

func (t ElectionResult) GetConsensusIds() []string

func (ElectionResult) IsNil

func (t ElectionResult) IsNil() bool

func (ElectionResult) String

func (t ElectionResult) String() string

type Epoch

type Epoch uint32

type FinalizedChainExtendedEvent

type FinalizedChainExtendedEvent struct {
	Sn BlockSn
	// This field is set when there is a reconfiguration.
	ReconfFinalizedByBlockSn BlockSn
}

type FreshestNotarizedChainExtendedEvent

type FreshestNotarizedChainExtendedEvent struct {
	Sn BlockSn
}

type Hash

type Hash []byte

func (Hash) Equal

func (h Hash) Equal(other Hash) bool

type Message

type Message interface {
	GetType() Type
	GetBody() []byte
	GetBlockSn() BlockSn
	GetDebugString() string
}

Message is a marshal/unmarshal helper.

type Notarization

type Notarization interface {
	Message

	ImplementsNotarization()

	GetNVote() uint16
	GetBlockHash() Hash
}

func NewNotarizationFake

func NewNotarizationFake(sn BlockSn, voterIds []string) Notarization

type NotarizationFake

type NotarizationFake struct {
	// contains filtered or unexported fields
}

func (*NotarizationFake) GetBlockHash

func (n *NotarizationFake) GetBlockHash() Hash

func (*NotarizationFake) GetBlockSn

func (n *NotarizationFake) GetBlockSn() BlockSn

func (*NotarizationFake) GetBody

func (n *NotarizationFake) GetBody() []byte

func (*NotarizationFake) GetDebugString

func (n *NotarizationFake) GetDebugString() string

func (*NotarizationFake) GetNVote

func (n *NotarizationFake) GetNVote() uint16

func (*NotarizationFake) GetType

func (n *NotarizationFake) GetType() Type

func (*NotarizationFake) GetVoterIds

func (n *NotarizationFake) GetVoterIds() []string

func (*NotarizationFake) ImplementsNotarization

func (n *NotarizationFake) ImplementsNotarization()

func (*NotarizationFake) Verify

func (n *NotarizationFake) Verify() bool

type Proposal

type Proposal interface {
	Message

	ImplementsProposal()

	GetBlock() Block
	GetProposerId() string
}

func NewProposalFake

func NewProposalFake(id string, b Block) Proposal

type ProposalFake

type ProposalFake struct {
	// contains filtered or unexported fields
}

func (*ProposalFake) GetBlock

func (p *ProposalFake) GetBlock() Block

func (*ProposalFake) GetBlockSn

func (p *ProposalFake) GetBlockSn() BlockSn

func (*ProposalFake) GetBody

func (p *ProposalFake) GetBody() []byte

func (*ProposalFake) GetDebugString

func (p *ProposalFake) GetDebugString() string

func (*ProposalFake) GetProposerId

func (p *ProposalFake) GetProposerId() string

func (*ProposalFake) GetType

func (p *ProposalFake) GetType() Type

func (*ProposalFake) ImplementsProposal

func (p *ProposalFake) ImplementsProposal()

type Type

type Type uint8

func (Type) String

func (typ Type) String() string

type Verifier

type Verifier interface {
	Propose(b Block) (Proposal, error)
	// VerifyProposal verifies |p| is signed by the eligible proposer
	// and |p|'s block should contain valid notarizations of ancestor blocks.
	// See the rule above BlockChain for details.
	VerifyProposal(p Proposal) error
	Vote(p Proposal) (Vote, error)
	VerifyVote(v Vote) error
	Notarize(votes []Vote) (Notarization, error)
	VerifyNotarization(n Notarization) error
	NewClockMsg(e Epoch) (ClockMsg, error)
	VerifyClockMsg(c ClockMsg) error
	NewClockMsgNota(clocks []ClockMsg) (ClockMsgNota, error)
	VerifyClockMsgNota(cn ClockMsgNota) error

	// Used for verifying the other end's role (challenge-response)
	Sign(id string, bytes []byte) ([]byte, error)
	VerifySignature(id string, signature []byte, expected []byte) error
}

type VerifierFake

type VerifierFake struct {
	// contains filtered or unexported fields
}

myProposerIds/myVoterIds are slices to make it possible to simulate key rotations during reconfiguration.

func NewVerifierFake

func NewVerifierFake(
	myProposerIds, myVoterIds []string, proposers ElectionResult, voters ElectionResult,
) *VerifierFake

func (*VerifierFake) AddElectionResult

func (v *VerifierFake) AddElectionResult(proposers ElectionResult, voters ElectionResult)

func (*VerifierFake) NewClockMsg

func (v *VerifierFake) NewClockMsg(e Epoch) (ClockMsg, error)

func (*VerifierFake) NewClockMsgNota

func (v *VerifierFake) NewClockMsgNota(clocks []ClockMsg) (ClockMsgNota, error)

func (*VerifierFake) Notarize

func (v *VerifierFake) Notarize(votes []Vote) (Notarization, error)

func (*VerifierFake) Propose

func (v *VerifierFake) Propose(b Block) (Proposal, error)

func (*VerifierFake) Sign

func (v *VerifierFake) Sign(id string, bytes []byte) ([]byte, error)

func (*VerifierFake) VerifyClockMsg

func (v *VerifierFake) VerifyClockMsg(c ClockMsg) error

func (*VerifierFake) VerifyClockMsgNota

func (v *VerifierFake) VerifyClockMsgNota(cn ClockMsgNota) error

func (*VerifierFake) VerifyNotarization

func (v *VerifierFake) VerifyNotarization(n Notarization) error

func (*VerifierFake) VerifyProposal

func (v *VerifierFake) VerifyProposal(p Proposal) error

func (*VerifierFake) VerifySignature

func (v *VerifierFake) VerifySignature(targetId string, signature []byte, expected []byte) error

func (*VerifierFake) VerifyVote

func (v *VerifierFake) VerifyVote(vote Vote) error

func (*VerifierFake) Vote

func (v *VerifierFake) Vote(p Proposal) (Vote, error)

type Vote

type Vote interface {
	Message

	ImplementsVote()

	GetVoterId() string
}

func NewVoteFake

func NewVoteFake(sn BlockSn, id string) Vote

type VoteFake

type VoteFake struct {
	// contains filtered or unexported fields
}

func (*VoteFake) GetBlockSn

func (v *VoteFake) GetBlockSn() BlockSn

func (*VoteFake) GetBody

func (v *VoteFake) GetBody() []byte

func (*VoteFake) GetDebugString

func (v *VoteFake) GetDebugString() string

func (*VoteFake) GetType

func (v *VoteFake) GetType() Type

func (*VoteFake) GetVoterId

func (v *VoteFake) GetVoterId() string

func (*VoteFake) ImplementsVote

func (v *VoteFake) ImplementsVote()

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL