dkg

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2024 License: MPL-2.0 Imports: 15 Imported by: 17

Documentation

Index

Constants

View Source
const (
	Success   = true
	Complaint = false
)
View Source
const NonceLength = 32

NonceLength is the length of the nonce

Variables

View Source
var ErrEvicted = errors.New("our node is evicted from list of qualified participants")

Functions

func GetNonce added in v1.1.0

func GetNonce() []byte

GetNonce returns a suitable nonce to feed in the DKG config.

func MinimumT

func MinimumT(n int) int

func VerifyPacketSignature added in v1.1.2

func VerifyPacketSignature(c *Config, p Packet) error

VerifyPacketSignature returns an error if the packet has an invalid signature. The signature is verified via the information contained in the config, namely the old and new nodes public keys.

Types

type BitSet

type BitSet map[uint32]bool

func (BitSet) LengthComplaints added in v1.1.1

func (b BitSet) LengthComplaints() int

type Board

type Board interface {
	PushDeals(*DealBundle)
	IncomingDeal() <-chan DealBundle
	PushResponses(*ResponseBundle)
	IncomingResponse() <-chan ResponseBundle
	PushJustifications(*JustificationBundle)
	IncomingJustification() <-chan JustificationBundle
}

Board is the interface between the dkg protocol and the external world. It consists in pushing packets out to other nodes and receiving in packets from the other nodes. A common board would use the network as the underlying communication mechanism but one can also use a smart contract based approach.

type Config

type Config struct {
	Suite Suite

	// Longterm is the longterm secret key.
	Longterm kyber.Scalar

	// Current group of share holders. It will be nil for new DKG. These nodes
	// will have invalid shares after the protocol has been run. To be able to issue
	// new shares to a new group, the group member's public key must be inside this
	// list and in the Share field. Keys can be disjoint or not with respect to the
	// NewNodes list.
	OldNodes []Node

	// PublicCoeffs are the coefficients of the distributed polynomial needed
	// during the resharing protocol. The first coefficient is the key. It is
	// required for new share holders.  It should be nil for a new DKG.
	PublicCoeffs []kyber.Point

	// Expected new group of share holders. These public-key designated nodes
	// will be in possession of new shares after the protocol has been run. To be a
	// receiver of a new share, one's public key must be inside this list. Keys
	// can be disjoint or not with respect to the OldNodes list.
	NewNodes []Node

	// Share to refresh. It must be nil for a new node wishing to
	// join or create a group. To be able to issue new fresh shares to a new group,
	// one's share must be specified here, along with the public key inside the
	// OldNodes field.
	Share *DistKeyShare

	// The threshold to use in order to reconstruct the secret with the produced
	// shares. This threshold is with respect to the number of nodes in the
	// NewNodes list. If unspecified, default is set to
	// `vss.MinimumT(len(NewNodes))`. This threshold indicates the degree of the
	// polynomials used to create the shares, and the minimum number of
	// verification required for each deal.
	Threshold int

	// OldThreshold holds the threshold value that was used in the previous
	// configuration. This field MUST be specified when doing resharing, but is
	// not needed when doing a fresh DKG. This value is required to gather a
	// correct number of valid deals before creating the distributed key share.
	// NOTE: this field is always required (instead of taking the default when
	// absent) when doing a resharing to avoid a downgrade attack, where a resharing
	// the number of deals required is less than what it is supposed to be.
	OldThreshold int

	// Reader is an optional field that can hold a user-specified entropy
	// source.  If it is set, Reader's data will be combined with random data
	// from crypto/rand to create a random stream which will pick the dkg's
	// secret coefficient. Otherwise, the random stream will only use
	// crypto/rand's entropy.
	Reader io.Reader

	// When UserReaderOnly it set to true, only the user-specified entropy
	// source Reader will be used. This should only be used in tests, allowing
	// reproducibility.
	UserReaderOnly bool

	// FastSync is a mode where nodes sends pre-emptively responses indicating
	// that the shares they received are good. If a share is invalid, a
	// complaint is still sent as usual. This has two consequences:
	//  - In the event all shares are good, nodes don't need to wait for the
	//  timeout; they can already finish the protocol at the point.
	//  - However, it requires nodes to send more messages on the network. We
	//  pass from a O(f) where f is the number of faults to a O(n^2). Note that
	//  the responses messages are small.
	FastSync bool

	// Nonce is required to avoid replay attacks from previous runs of a DKG /
	// resharing. The required property of the Nonce is that it must be unique
	// accross runs. A Nonce must be of length 32 bytes. User can get a secure
	// nonce by calling `GetNonce()`.
	Nonce []byte

	// Auth is the scheme to use to authentify the packets sent and received
	// during the protocol.
	Auth sign.Scheme

	// Log enables the DKG logic and protocol to log important events (mostly
	// errors).  from participants. Errors don't mean the protocol should be
	// stopped, so logging is the best way to communicate information to the
	// application layer. It can be nil.
	Log Logger
}

Config holds all required information to run a fresh DKG protocol or a resharing protocol. In the case of a new fresh DKG protocol, one must fill the following fields: Suite, Longterm, NewNodes, Threshold (opt). In the case of a resharing protocol, one must fill the following: Suite, Longterm, OldNodes, NewNodes. If the node using this config is creating new shares (i.e. it belongs to the current group), the Share field must be filled in with the current share of the node. If the node using this config is a new addition and thus has no current share, the PublicCoeffs field be must be filled in.

func (*Config) CheckForDuplicates added in v1.1.8

func (c *Config) CheckForDuplicates() error

CheckForDuplicates looks at the lits of node indices in the OldNodes and NewNodes list. It returns an error if there is a duplicate in either list. NOTE: It only looks at indices because it is plausible that one party may have multiple indices for the protocol, i.e. a higher "weight".

func (*Config) Error added in v1.1.9

func (c *Config) Error(keyvals ...interface{})

func (*Config) Info added in v1.1.9

func (c *Config) Info(keyvals ...interface{})

type Deal

type Deal struct {
	// Index of the share holder
	ShareIndex uint32
	// encrypted share issued to the share holder
	EncryptedShare []byte
}

Deal holds the Deal for one participant as well as the index of the issuing Dealer.

type DealBundle

type DealBundle struct {
	DealerIndex uint32
	Deals       []Deal
	// Public coefficients of the public polynomial used to create the shares
	Public []kyber.Point
	// SessionID of the current run
	SessionID []byte
	// Signature over the hash of the whole bundle
	Signature []byte
}

DealBundle is the struct sent out by dealers that contains all the deals and the public polynomial.

func (*DealBundle) Hash

func (d *DealBundle) Hash() []byte

Hash hashes the index, public coefficients and deals

func (*DealBundle) Index added in v1.1.0

func (d *DealBundle) Index() Index

func (*DealBundle) Sig added in v1.1.2

func (d *DealBundle) Sig() []byte

type DistKeyGenerator

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

DistKeyGenerator is the struct that runs the DKG protocol.

func NewDistKeyHandler

func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error)

NewDistKeyHandler takes a Config and returns a DistKeyGenerator that is able to drive the DKG or resharing protocol.

func (*DistKeyGenerator) Deals

func (d *DistKeyGenerator) Deals() (*DealBundle, error)

func (*DistKeyGenerator) Error added in v1.1.9

func (d *DistKeyGenerator) Error(keyvals ...interface{})

func (*DistKeyGenerator) ExpectedResponsesFastSync

func (d *DistKeyGenerator) ExpectedResponsesFastSync() int

func (*DistKeyGenerator) Info added in v1.1.9

func (d *DistKeyGenerator) Info(keyvals ...interface{})

func (*DistKeyGenerator) ProcessDeals

func (d *DistKeyGenerator) ProcessDeals(bundles []*DealBundle) (*ResponseBundle, error)

ProcessDeals process the deals from all the nodes. Each deal for this node is decrypted and stored. It returns a response bundle if there is any invalid or missing deals. It returns an error if the node is not in the right state, or if there is not enough valid shares, i.e. the dkg is failing already.

func (*DistKeyGenerator) ProcessJustifications

func (d *DistKeyGenerator) ProcessJustifications(bundles []*JustificationBundle) (*Result, error)

ProcessJustifications takes the justifications of the nodes and returns the results if there is enough QUALified nodes, or an error otherwise. Note that this method returns "nil,nil" if this node is a node only present in the old group of the dkg: indeed a node leaving the group don't need to process justifications, and can simply leave the protocol.

func (*DistKeyGenerator) ProcessResponses

func (d *DistKeyGenerator) ProcessResponses(bundles []*ResponseBundle) (res *Result, jb *JustificationBundle, err error)

ProcessResponses takes the response from all nodes if any and returns a triplet: - the result if there is no complaint. If not nil, the DKG is finished. - the justification bundle if this node must produce at least one. If nil, this node must still wait on the justification phase. - error if the dkg must stop now, an unrecoverable failure.

type DistKeyShare

type DistKeyShare struct {
	// Coefficients of the public polynomial holding the public key.
	Commits []kyber.Point
	// Share of the distributed secret which is private information.
	Share *share.PriShare
}

DistKeyShare holds the share of a distributed key for a participant.

func (*DistKeyShare) Commitments

func (d *DistKeyShare) Commitments() []kyber.Point

Commitments implements the dss.DistKeyShare interface so either pedersen or rabin dkg can be used with dss.

func (*DistKeyShare) PriShare

func (d *DistKeyShare) PriShare() *share.PriShare

PriShare implements the dss.DistKeyShare interface so either pedersen or rabin dkg can be used with dss.

func (*DistKeyShare) Public

func (d *DistKeyShare) Public() kyber.Point

Public returns the public key associated with the distributed private key.

type Index

type Index = uint32

Index is an alias to designate the index of a node. The index is used to evaluate the share of a node, and is thereafter fixed. A node will use the same index for generating a partial signature afterwards for example.

type Justification

type Justification struct {
	ShareIndex uint32
	Share      kyber.Scalar
}

type JustificationBundle

type JustificationBundle struct {
	DealerIndex    uint32
	Justifications []Justification
	// SessionID of the current run
	SessionID []byte
	// Signature over the hash of the whole bundle
	Signature []byte
}

JustificationBundle is the struct that contains all justifications for each complaint in the precedent phase.

func (*JustificationBundle) Hash

func (j *JustificationBundle) Hash() []byte

func (*JustificationBundle) Index added in v1.1.0

func (j *JustificationBundle) Index() Index

func (*JustificationBundle) Sig added in v1.1.2

func (j *JustificationBundle) Sig() []byte

type Logger added in v1.1.8

type Logger interface {
	Info(keyvals ...interface{})
	Error(keyvals ...interface{})
}

Logger is a simpler key value logger interface

type Node

type Node struct {
	Index  Index
	Public kyber.Point
}

Node represents the public key and its index amongt the list of participants. For a fresh DKG, the index can be anything but we usually take the index that corresponds to the position in the list of participants. For a resharing, if that node is a node that has already ran the DKG, we need to use the same index as it was given in the previous DKG in the list of OldNodes, in the DKG config.

func (*Node) Equal

func (n *Node) Equal(n2 *Node) bool

type OptionResult

type OptionResult struct {
	Result *Result
	Error  error
}

type Packet added in v1.1.2

type Packet interface {
	Hash() []byte
	Index() Index
	Sig() []byte
}

Packet is the interface that implements the three messages that this implementation uses during the different phases. This interface allows to verify a DKG packet without knowing its specific type.

type Phase

type Phase int

Phase is a type that represents the different stages of the DKG protocol.

const (
	InitPhase Phase = iota
	DealPhase
	ResponsePhase
	JustifPhase
	FinishPhase
)

func (Phase) String

func (p Phase) String() string

type Phaser

type Phaser interface {
	NextPhase() chan Phase
}

Phaser must signal on its channel when the protocol should move to a next phase. Phase must be sequential: DealPhase (start), ResponsePhase, JustifPhase and then FinishPhase. Note that if the dkg protocol finishes before the phaser sends the FinishPhase, the protocol will not listen on the channel anymore. This can happen if there is no complaints, or if using the "FastSync" mode. Most of the times, user should use the TimePhaser when using the network, but if one wants to use a smart contract as a board, then the phaser can tick at certain blocks, or when the smart contract tells it.

type Protocol

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

Protocol contains the logic to run a DKG protocol over a generic broadcast channel, called Board. It handles the receival of packets, ordering of the phases and the termination. A protocol can be ran over a network, a smart contract, or anything else that is implemented via the Board interface.

func NewProtocol

func NewProtocol(c *Config, b Board, phaser Phaser, skipVerification bool) (*Protocol, error)

func (*Protocol) Error added in v1.1.9

func (p *Protocol) Error(keyvals ...interface{})

func (*Protocol) Info added in v1.1.9

func (p *Protocol) Info(keyvals ...interface{})

func (*Protocol) Start

func (p *Protocol) Start()

func (*Protocol) WaitEnd

func (p *Protocol) WaitEnd() <-chan OptionResult

type Response

type Response struct {
	// Index of the Dealer for which this response is for
	DealerIndex uint32
	Status      bool
}

Response holds the Response from another participant as well as the index of the target Dealer.

type ResponseBundle

type ResponseBundle struct {
	// Index of the share holder for which these reponses are for
	ShareIndex uint32
	Responses  []Response
	// SessionID of the current run
	SessionID []byte
	// Signature over the hash of the whole bundle
	Signature []byte
}

ResponseBundle is the struct sent out by share holder containing the status for the deals received in the first phase.

func (*ResponseBundle) Hash

func (r *ResponseBundle) Hash() []byte

Hash hashes the share index and responses

func (*ResponseBundle) Index added in v1.1.0

func (b *ResponseBundle) Index() Index

func (*ResponseBundle) Sig added in v1.1.2

func (b *ResponseBundle) Sig() []byte

func (*ResponseBundle) String

func (b *ResponseBundle) String() string

type Result

type Result struct {
	QUAL []Node
	Key  *DistKeyShare
}

Result is the struct that is outputted by the DKG protocol after it finishes. It contains both the list of nodes that successfully ran the protocol and the share of the node.

func (*Result) PublicEqual

func (r *Result) PublicEqual(r2 *Result) bool

type StatusMatrix

type StatusMatrix map[uint32]BitSet

func NewStatusMatrix

func NewStatusMatrix(dealers []Node, shareHolders []Node, status bool) *StatusMatrix

func (*StatusMatrix) AllTrue

func (s *StatusMatrix) AllTrue(dealer uint32) bool

func (*StatusMatrix) CompleteSuccess

func (s *StatusMatrix) CompleteSuccess() bool

func (*StatusMatrix) Get

func (s *StatusMatrix) Get(dealer, share uint32) bool

can panic if indexes are not from the original list of nodes

func (*StatusMatrix) Set

func (s *StatusMatrix) Set(dealer, share uint32, status bool)

can panic if indexes are not from the original list of nodes

func (*StatusMatrix) SetAll

func (s *StatusMatrix) SetAll(dealer uint32, status bool)

func (*StatusMatrix) StatusesForShare

func (s *StatusMatrix) StatusesForShare(shareIndex uint32) BitSet

func (*StatusMatrix) StatusesOfDealer

func (s *StatusMatrix) StatusesOfDealer(dealerIndex uint32) BitSet

func (*StatusMatrix) String

func (s *StatusMatrix) String() string

type Suite

type TimePhaser

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

TimePhaser is a phaser that sleeps between the different phases and send the signal over its channel.

func NewTimePhaser

func NewTimePhaser(p time.Duration) *TimePhaser

func NewTimePhaserFunc

func NewTimePhaserFunc(sleepPeriod func(Phase)) *TimePhaser

func (*TimePhaser) NextPhase

func (t *TimePhaser) NextPhase() chan Phase

func (*TimePhaser) Start

func (t *TimePhaser) Start()

Jump to

Keyboard shortcuts

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