pbft

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Dec 21, 2022 License: Apache-2.0 Imports: 13 Imported by: 0

README

myl7/pbft

PBFT (Practical Byzantine Fault Tolerance) implementation focused on composability

The project is aimed for academic use currently. It may consider production use as a long-term goal, but not now.

Getting Started

All required interfaces are in the traits.go file. All you need to do is to implement all (public) interfaces, then pass them to NewNode function to initialize a Node, and finally pass received PBFT messages from the network to Node respective Handle* methods.

Features

  • Basic PBFT (request, preprepare, prepare, commit, reply)
  • Custom KV storage backend
  • Custom network communication
  • Custom state machine, to fit whatever you want to do

Caveats

  • No checkpoint
  • No view change
  • Some ignored (so) edge cases. Search TODO comments in the code for details.
  • NO READY FOR PRODUCTION USE, yet. Please only use it for academic purposes currently.

License

Copyright (C) 2022 myl7

SPDX-License-Identifier: Apache-2.0

Documentation

Overview

All traits do not need inner locking, because in the node they are accessed in handlers, and handlers all have a mutex lock so that only one handler is running at a time

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidSig = errors.New("sig error: invalid signature")
View Source
var ErrInvalidStorage = errors.New("invalid storage error: value is invalid and not put by the app")
View Source
var ErrNoRequestAfterCommittedLocal = errors.New("request error: no request even after committed-local")
View Source
var ErrTimestampNotNew = errors.New("request timestamp error: not newer than the latest handled one")
View Source
var ErrUnknownNodeID = errors.New("id error: can not use the ID to get the required information of the node")
View Source
var ErrUnknownUser = errors.New("user error: can not get the public key of the user due to unknown user")
View Source
var ErrUnmatchedDigest = errors.New("digest error: the digest of the request is not matched with the digest in the preprepare")
View Source
var ErrUnmatchedPP = errors.New("preprepare error: accepted 2 preprepares and the 2 do not match")
View Source
var ErrUnmatchedView = errors.New("view error: the view is not matched with the current node state")

Functions

func SerPK

func SerPK(pk ed25519.PublicKey) []byte

SerPK See [dePK]

func SerSK

func SerSK(sk ed25519.PrivateKey) []byte

SerSK See [dePK]

Types

type Commit

type Commit struct {
	Sig    []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"`
	View   int32  `protobuf:"varint,2,opt,name=view,proto3" json:"view,omitempty"`
	Seq    int64  `protobuf:"varint,3,opt,name=seq,proto3" json:"seq,omitempty"`
	Digest []byte `protobuf:"bytes,4,opt,name=digest,proto3" json:"digest,omitempty"`
	Node   string `protobuf:"bytes,5,opt,name=node,proto3" json:"node,omitempty"`
	// contains filtered or unexported fields
}

func (*Commit) Descriptor deprecated

func (*Commit) Descriptor() ([]byte, []int)

Deprecated: Use Commit.ProtoReflect.Descriptor instead.

func (*Commit) GetDigest

func (x *Commit) GetDigest() []byte

func (*Commit) GetNode

func (x *Commit) GetNode() string

func (*Commit) GetSeq

func (x *Commit) GetSeq() int64

func (*Commit) GetSig

func (x *Commit) GetSig() []byte

func (*Commit) GetView

func (x *Commit) GetView() int32

func (*Commit) ProtoMessage

func (*Commit) ProtoMessage()

func (*Commit) ProtoReflect

func (x *Commit) ProtoReflect() protoreflect.Message

func (*Commit) Reset

func (x *Commit) Reset()

func (*Commit) String

func (x *Commit) String() string

type Node

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

func (*Node) HandleCommit

func (nd *Node) HandleCommit(msgB []byte) error

func (*Node) HandlePrePrepare

func (nd *Node) HandlePrePrepare(msgPPB []byte, msgReqB []byte) error

func (*Node) HandlePrepare

func (nd *Node) HandlePrepare(msgB []byte) error

func (*Node) HandleRequest

func (nd *Node) HandleRequest(msgB []byte) error

type NodeAPI

type NodeAPI interface {
	HandleRequest(msgB []byte) error
	// HandlePrePrepare parses msgPPB as preprepare & msgReqB as request
	HandlePrePrepare(msgPPB []byte, msgReqB []byte) error
	HandlePrepare(msgB []byte) error
	HandleCommit(msgB []byte) error
}

type NodeCommunicator

type NodeCommunicator interface {
	Unicast(msgB []byte, toNode string, msgType msgType) error
	// Broadcast should not sends the msg to itself, as that has been done in this library.
	Broadcast(msgB []byte, fromNode string, msgType msgType) error
	// BroadcastWithLarge is similar to [Broadcast], but it sends a small msg msgB together with a large msg msgLB, e.g., a preprepare with a request.
	// If you do not need the optimization, you can combine the two msgs and send them in one time.
	BroadcastWithLarge(msgB []byte, msgLB []byte, fromNode string, msgType msgType) error
	// Return can only send reply msg so no msgType is required
	Return(msgB []byte, toUser string) error
}

NodeCommunicator needs to handle stable transmission, e.g., retrying / timeouts

type NodeParams

type NodeParams struct {
	ID string
	// N is total node num
	// TODO: Allow not 3f + 1
	N int
	// PKs should include the node's own pubkey
	PKs map[string][]byte
	SK  []byte
}

type NodePrimaryGetter

type NodePrimaryGetter interface {
	Get(view int) (primary string, err error)
}

type NodeStateMachine

type NodeStateMachine interface {
	// Transform does computation, so it may be slow
	Transform(op []byte) (result []byte)
}

type NodeStorage

type NodeStorage interface {
	Put(key string, val []byte) error
	// Get returns nil if not found
	Get(key string) (val []byte, err error)
}

NodeStorage key of it use / to separate namespaces

type NodeUserPKGetter

type NodeUserPKGetter interface {
	Get(user string) (pk []byte, err error)
}

type PrePrepare

type PrePrepare struct {
	Sig    []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"`
	View   int32  `protobuf:"varint,2,opt,name=view,proto3" json:"view,omitempty"`
	Seq    int64  `protobuf:"varint,3,opt,name=seq,proto3" json:"seq,omitempty"`
	Digest []byte `protobuf:"bytes,4,opt,name=digest,proto3" json:"digest,omitempty"`
	// contains filtered or unexported fields
}

func (*PrePrepare) Descriptor deprecated

func (*PrePrepare) Descriptor() ([]byte, []int)

Deprecated: Use PrePrepare.ProtoReflect.Descriptor instead.

func (*PrePrepare) GetDigest

func (x *PrePrepare) GetDigest() []byte

func (*PrePrepare) GetSeq

func (x *PrePrepare) GetSeq() int64

func (*PrePrepare) GetSig

func (x *PrePrepare) GetSig() []byte

func (*PrePrepare) GetView

func (x *PrePrepare) GetView() int32

func (*PrePrepare) ProtoMessage

func (*PrePrepare) ProtoMessage()

func (*PrePrepare) ProtoReflect

func (x *PrePrepare) ProtoReflect() protoreflect.Message

func (*PrePrepare) Reset

func (x *PrePrepare) Reset()

func (*PrePrepare) String

func (x *PrePrepare) String() string

type Prepare

type Prepare struct {
	Sig    []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"`
	View   int32  `protobuf:"varint,2,opt,name=view,proto3" json:"view,omitempty"`
	Seq    int64  `protobuf:"varint,3,opt,name=seq,proto3" json:"seq,omitempty"`
	Digest []byte `protobuf:"bytes,4,opt,name=digest,proto3" json:"digest,omitempty"`
	Node   string `protobuf:"bytes,5,opt,name=node,proto3" json:"node,omitempty"`
	// contains filtered or unexported fields
}

func (*Prepare) Descriptor deprecated

func (*Prepare) Descriptor() ([]byte, []int)

Deprecated: Use Prepare.ProtoReflect.Descriptor instead.

func (*Prepare) GetDigest

func (x *Prepare) GetDigest() []byte

func (*Prepare) GetNode

func (x *Prepare) GetNode() string

func (*Prepare) GetSeq

func (x *Prepare) GetSeq() int64

func (*Prepare) GetSig

func (x *Prepare) GetSig() []byte

func (*Prepare) GetView

func (x *Prepare) GetView() int32

func (*Prepare) ProtoMessage

func (*Prepare) ProtoMessage()

func (*Prepare) ProtoReflect

func (x *Prepare) ProtoReflect() protoreflect.Message

func (*Prepare) Reset

func (x *Prepare) Reset()

func (*Prepare) String

func (x *Prepare) String() string

type Reply

type Reply struct {
	Sig       []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"`
	View      int32  `protobuf:"varint,2,opt,name=view,proto3" json:"view,omitempty"`
	Timestamp int64  `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	User      string `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"`
	Node      string `protobuf:"bytes,5,opt,name=node,proto3" json:"node,omitempty"`
	// result may be large, so Reply may be large too
	Result []byte `protobuf:"bytes,6,opt,name=result,proto3" json:"result,omitempty"`
	// contains filtered or unexported fields
}

func (*Reply) Descriptor deprecated

func (*Reply) Descriptor() ([]byte, []int)

Deprecated: Use Reply.ProtoReflect.Descriptor instead.

func (*Reply) GetNode

func (x *Reply) GetNode() string

func (*Reply) GetResult

func (x *Reply) GetResult() []byte

func (*Reply) GetSig

func (x *Reply) GetSig() []byte

func (*Reply) GetTimestamp

func (x *Reply) GetTimestamp() int64

func (*Reply) GetUser

func (x *Reply) GetUser() string

func (*Reply) GetView

func (x *Reply) GetView() int32

func (*Reply) ProtoMessage

func (*Reply) ProtoMessage()

func (*Reply) ProtoReflect

func (x *Reply) ProtoReflect() protoreflect.Message

func (*Reply) Reset

func (x *Reply) Reset()

func (*Reply) String

func (x *Reply) String() string

type Request

type Request struct {
	Sig []byte `protobuf:"bytes,1,opt,name=sig,proto3" json:"sig,omitempty"`
	// op may be large, so Request may be large too
	Op        []byte `protobuf:"bytes,2,opt,name=op,proto3" json:"op,omitempty"`
	Timestamp int64  `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	User      string `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"`
	// contains filtered or unexported fields
}

func (*Request) Descriptor deprecated

func (*Request) Descriptor() ([]byte, []int)

Deprecated: Use Request.ProtoReflect.Descriptor instead.

func (*Request) GetOp

func (x *Request) GetOp() []byte

func (*Request) GetSig

func (x *Request) GetSig() []byte

func (*Request) GetTimestamp

func (x *Request) GetTimestamp() int64

func (*Request) GetUser

func (x *Request) GetUser() string

func (*Request) ProtoMessage

func (*Request) ProtoMessage()

func (*Request) ProtoReflect

func (x *Request) ProtoReflect() protoreflect.Message

func (*Request) Reset

func (x *Request) Reset()

func (*Request) String

func (x *Request) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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