dkg

package
v0.31.14 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2023 License: AGPL-3.0 Imports: 25 Imported by: 3

Documentation

Overview

Package dkg implements a controller that manages the lifecycle of a Joint Feldman DKG node, as well as a broker that enables the controller to communicate with other nodes

Controller

A new controller must be instantiated for every epoch.

The state-machine can be represented as follows:

+-------+  /Run() +---------+  /EndPhase1() +---------+  /EndPhase2() +---------+  /End()   +-----+     +----------+
| Init  | ----->  | Phase 1 | ------------> | Phase 2 | ------------> | Phase 3 | --------> | End | --> | Shutdown |
+-------+         +---------+               +---------+               +---------+           +-----+     +----------+
|                   |                         |                         |                                 ^
v___________________v_________________________v_________________________v_________________________________|
                                         /Shutdown()

The controller is always in one of 6 states:

- Init: Default state before the instance is started - Phase 1: 1st phase of the JF DKG protocol while it's running - Phase 2: 2nd phase --- - Phase 3: 3rd phase --- - End: When the DKG protocol is finished - Shutdown: When the controller and all its routines are stopped

The controller exposes the following functions to trigger transitions:

Run(): Triggers transition from Init to Phase1. Starts the DKG protocol instance and background communication routines.

EndPhase1(): Triggers transition from Phase 1 to Phase 2.

EndPhase2(): Triggers transition from Phase 2 to Phase 3.

End(): Ends the DKG protocol and records the artifacts in controller. Triggers transition from Phase 3 to End.

Shutdown(): Can be called from any state to stop the DKG instance.

The End and Shutdown states differ in that the End state can only be arrived at from Phase 3 and after successfully computing the DKG artifacts. Whereas the Shutdown state can be reached from any other state.

Broker

The controller requires a broker to communicate with other nodes over the network and to read broadcast messages from the DKG smart-contract. A new broker must be instantiated for every epoch.

The Broker is responsible for:

  • converting to and from the message format used by the underlying crypto DKG package.
  • appending dkg instance id to messages to prevent replay attacks
  • checking the integrity of incoming messages
  • signing and verifying broadcast messages (broadcast messages are signed with the staking key of the sender)
  • forwarding incoming messages (private and broadcast) to the controller via a channel
  • forwarding outgoing messages (private and broadcast) to other nodes.

+------------+ +-------------+ | | | | <--------(tunnel)-----------> network engine <--> Other nodes | Controller |--| Broker | | | | | <--(smart-contract client)--> DKG smart-contract +------------+ +-------------+

To relay private messages, the broker uses a BrokerTunnel to communicate with a network engine.

To send and receive broadcast messages, the broker communicates with the DKG smart-contract via a smart-contract client. The broker's Poll method must be called regularly to read broadcast messages from the smart-contract.

Index

Constants

View Source
const (

	// DefaultBaseStartDelay is the default base delay to use when introducing
	// random delay to the DKG start process. See preStartDelay for details.
	DefaultBaseStartDelay = 500 * time.Microsecond

	// DefaultBaseHandleFirstBroadcastDelay is the default base to use when
	// introducing random delay to processing the first DKG broadcast message.
	// See preHandleFirstBroadcastDelay for details.
	//
	// For a 150-node DKG, we observe a cost of ~2.5s per message to process
	// broadcast messages during phase 1, for a total of ~6m of total CPU time.
	// We would like to target spreading this cost over a 30 minute period.
	// With the default value for DefaultHandleSubsequentBroadcastDelay, this
	// results in processing all phase 1 messages in 6m+6m=12m, so for a maximum
	// total processing time of 30m, we sample the initial delay from [0,18m].
	// We use 50ms as the default because 50ms*150^2 = 18.75m
	//
	DefaultBaseHandleFirstBroadcastDelay = 50 * time.Millisecond

	// DefaultHandleSubsequentBroadcastDelay is the default delay to use before
	// processing all DKG broadcasts after the first.
	DefaultHandleSubsequentBroadcastDelay = 2500 * time.Millisecond
)

Variables

This section is empty.

Functions

func CanonicalInstanceID

func CanonicalInstanceID(chainID flow.ChainID, epochCounter uint64) string

CanonicalInstanceID returns the canonical DKG instance ID for the given epoch on the given chain.

func IsInvalidStateTransitionError

func IsInvalidStateTransitionError(err error) bool

func NewDKGMessageHasher

func NewDKGMessageHasher() hash.Hasher

NewDKGMessageHasher returns a hasher for signing and verifying DKG broadcast messages.

Types

type Broker

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

Broker is an implementation of the DKGBroker interface which is intended to be used in conjunction with the DKG MessagingEngine for private messages, and with the DKG smart-contract for broadcast messages.

func NewBroker

func NewBroker(
	log zerolog.Logger,
	dkgInstanceID string,
	committee flow.IdentityList,
	me module.Local,
	myIndex int,
	dkgContractClients []module.DKGContractClient,
	tunnel *BrokerTunnel,
	opts ...BrokerOpt,
) *Broker

NewBroker instantiates a new epoch-specific broker capable of communicating with other nodes via a network engine and dkg smart-contract.

func (*Broker) Broadcast

func (b *Broker) Broadcast(data []byte)

Broadcast signs and broadcasts a message to all participants.

func (*Broker) Disqualify

func (b *Broker) Disqualify(node int, log string)

Disqualify flags that a node is misbehaving and got disqualified

func (*Broker) FlagMisbehavior

func (b *Broker) FlagMisbehavior(node int, log string)

FlagMisbehavior warns that a node is misbehaving.

func (*Broker) GetBroadcastMsgCh

func (b *Broker) GetBroadcastMsgCh() <-chan messages.BroadcastDKGMessage

GetBroadcastMsgCh returns the channel through which consumers can receive incoming broadcast DKG messages.

func (*Broker) GetIndex

func (b *Broker) GetIndex() int

GetIndex returns the index of this node in the committee list.

func (*Broker) GetPrivateMsgCh

func (b *Broker) GetPrivateMsgCh() <-chan messages.PrivDKGMessageIn

GetPrivateMsgCh returns the channel through which consumers can receive incoming private DKG messages.

func (*Broker) Poll

func (b *Broker) Poll(referenceBlock flow.Identifier) error

Poll calls the DKG smart contract to get missing DKG messages for the current epoch, and forwards them to the msgCh. It should be called with the ID of a block whose seal is finalized. The function doesn't return until the received messages are processed by the consumer because b.msgCh is not buffered.

func (*Broker) PrivateSend

func (b *Broker) PrivateSend(dest int, data []byte)

PrivateSend sends a DKGMessage to a destination over a private channel. It appends the current DKG instance ID to the message.

func (*Broker) Shutdown

func (b *Broker) Shutdown()

Shutdown stop the goroutine that listens to incoming private messages.

func (*Broker) SubmitResult

func (b *Broker) SubmitResult(groupKey crypto.PublicKey, pubKeys []crypto.PublicKey) error

SubmitResult publishes the result of the DKG protocol to the smart contract.

type BrokerConfig added in v0.25.0

type BrokerConfig struct {
	// PublishMaxRetries is the maximum number of times the broker will attempt
	// to broadcast a message or publish a result.
	PublishMaxRetries uint64
	// ReadMaxRetries is the max number of times the broker will attempt to
	// read messages before giving up.
	ReadMaxRetries uint64
	// RetryMaxConsecutiveFailures is the number of consecutive failures allowed
	// before we switch to a different Access client for subsequent attempts.
	RetryMaxConsecutiveFailures int
	// RetryInitialWait is the initial duration to wait between retries for all
	// retryable requests - increases exponentially for subsequent retries.
	RetryInitialWait time.Duration
	// RetryJitterPct is the percentage jitter to introduce to each retry interval
	// for all retryable requests.
	RetryJitterPct uint64
}

BrokerConfig is configuration for the DKG Broker component.

func DefaultBrokerConfig added in v0.25.0

func DefaultBrokerConfig() BrokerConfig

DefaultBrokerConfig returns the default config for the DKG Broker component.

type BrokerOpt added in v0.25.0

type BrokerOpt func(*BrokerConfig)

BrokerOpt is a functional option which modifies the DKG Broker config.

type BrokerTunnel

type BrokerTunnel struct {
	MsgChIn  chan messages.PrivDKGMessageIn  // from network engine to broker
	MsgChOut chan messages.PrivDKGMessageOut // from broker to network engine
}

BrokerTunnel allows the DKG MessagingEngine to relay messages to and from a loosely-coupled Broker and Controller. The same BrokerTunnel is intended to be reused across epochs (multiple DKG instances). The BrokerTunnel does not internally queue messages, so sends through the tunnel are blocking.

func NewBrokerTunnel

func NewBrokerTunnel() *BrokerTunnel

NewBrokerTunnel instantiates a new BrokerTunnel.

func (*BrokerTunnel) SendIn

func (t *BrokerTunnel) SendIn(msg messages.PrivDKGMessageIn)

SendIn pushes incoming messages in the MsgChIn channel to be received by the Broker. This is a blocking call (messages are not queued within the tunnel)

func (*BrokerTunnel) SendOut

func (t *BrokerTunnel) SendOut(msg messages.PrivDKGMessageOut)

SendOut pushes outbound messages in the MsgChOut channel to be received and forwarded by the network engine. This is a blocking call (messages are not queued within the tunnel)

type Client

type Client struct {
	epochs.BaseClient
	// contains filtered or unexported fields
}

Client is a client to the Flow DKG contract. Allows functionality to Broadcast, read a Broadcast and submit the final result of the DKG protocol

func NewClient

func NewClient(
	log zerolog.Logger,
	flowClient module.SDKClientWrapper,
	flowClientANID flow.Identifier,
	signer sdkcrypto.Signer,
	dkgContractAddress,
	accountAddress string,
	accountKeyIndex uint,
) *Client

NewClient initializes a new client to the Flow DKG contract

func (*Client) Broadcast

func (c *Client) Broadcast(msg model.BroadcastDKGMessage) error

Broadcast broadcasts a message to all other nodes participating in the DKG. The message is broadcast by submitting a transaction to the DKG smart contract. An error is returned if the transaction has failed.

func (*Client) ReadBroadcast

func (c *Client) ReadBroadcast(fromIndex uint, referenceBlock flow.Identifier) ([]model.BroadcastDKGMessage, error)

ReadBroadcast reads the broadcast messages from the smart contract. Messages are returned in the order in which they were received and stored in the smart contract

func (*Client) SubmitResult

func (c *Client) SubmitResult(groupPublicKey crypto.PublicKey, publicKeys []crypto.PublicKey) error

SubmitResult submits the final public result of the DKG protocol. This represents the group public key and the node's local computation of the public keys for each DKG participant. Serialized pub keys are encoded as hex.

type Controller

type Controller struct {
	// The embedded state Manager is used to manage the controller's underlying
	// state.
	Manager
	// contains filtered or unexported fields
}

Controller implements the DKGController interface. It controls the execution of a Joint Feldman DKG instance. A new Controller must be instantiated for every epoch.

func NewController

func NewController(
	log zerolog.Logger,
	dkgInstanceID string,
	dkg crypto.DKGState,
	seed []byte,
	broker module.DKGBroker,
	config ControllerConfig,
) *Controller

NewController instantiates a new Joint Feldman DKG controller.

func (*Controller) End

func (c *Controller) End() error

End terminates the DKG state machine and records the artifacts.

func (*Controller) EndPhase1

func (c *Controller) EndPhase1() error

EndPhase1 notifies the controller to end phase 1, and start phase 2

func (*Controller) EndPhase2

func (c *Controller) EndPhase2() error

EndPhase2 notifies the controller to end phase 2, and start phase 3

func (*Controller) GetArtifacts

func (c *Controller) GetArtifacts() (crypto.PrivateKey, crypto.PublicKey, []crypto.PublicKey)

GetArtifacts returns our node's private key share, the group public key, and the list of all nodes' public keys (including ours), as computed by the DKG.

func (*Controller) GetIndex

func (c *Controller) GetIndex() int

GetIndex returns the index of this node in the DKG committee list.

func (*Controller) Poll

func (c *Controller) Poll(blockReference flow.Identifier) error

Poll instructs the broker to read new broadcast messages, which will be relayed through the message channel. The function does not return until the received messages are processed.

func (*Controller) Run

func (c *Controller) Run() error

Run starts the DKG controller and executes the DKG state-machine. It blocks until the controller is shutdown or until an error is encountered in one of the protocol phases.

func (*Controller) Shutdown

func (c *Controller) Shutdown()

Shutdown stops the controller regardless of the current state.

func (*Controller) SubmitResult

func (c *Controller) SubmitResult() error

SubmitResult instructs the broker to submit DKG results. It is up to the caller to ensure that this method is called after a succesfull run of the protocol.

type ControllerConfig added in v0.22.4

type ControllerConfig struct {
	// BaseStartDelay determines the maximum delay before starting the DKG.
	BaseStartDelay time.Duration
	// BaseHandleFirstBroadcastDelay determines the maximum delay before handling
	// the first broadcast message.
	BaseHandleFirstBroadcastDelay time.Duration
	// HandleSubsequentBroadcastDelay determines the constant delay before handling
	// all broadcast messages following the first.
	HandleSubsequentBroadcastDelay time.Duration
}

ControllerConfig defines configuration for the DKG Controller. These define how the DKG controller introduces delays to expensive DKG computations.

We introduce delays for two reasons: 1. Avoid running long-running expensive DKG computations consecutively. 2. Avoid synchronizing expensive DKG computations across the DKG committee.

Delays introduced prior to DKG start and prior to processing the FIRST broadcast message are sampled uniformly from [0,m), where m=b*n^2

b = base delay (from config)
n = size of DKG committee

Delays introduced prior to processing subsequent broadcast messages are constant.

type ControllerFactory

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

ControllerFactory is a factory object that creates new Controllers for new epochs. Each Controller produced by a factory shares the same underlying Local object to sign broadcast messages, the same tunnel tying it to the MessagingEngine, and the same client to communicate with the DKG smart-contract.

func NewControllerFactory

func NewControllerFactory(
	log zerolog.Logger,
	me module.Local,
	dkgContractClients []module.DKGContractClient,
	tunnel *BrokerTunnel,
	config ControllerConfig) *ControllerFactory

NewControllerFactory creates a new factory that generates Controllers with the same underlying Local object, tunnel and dkg smart-contract client.

func (*ControllerFactory) Create

func (f *ControllerFactory) Create(
	dkgInstanceID string,
	participants flow.IdentityList,
	seed []byte) (module.DKGController, error)

Create creates a new epoch-specific Controller equipped with a broker which is capable of communicating with other nodes.

type InvalidStateTransitionError

type InvalidStateTransitionError struct {
	From State
	To   State
}

InvalidStateTransitionError happens when an invalid DKG state transition is attempted.

func NewInvalidStateTransitionError

func NewInvalidStateTransitionError(from State, to State) InvalidStateTransitionError

NewInvalidStateTransitionError creates a new InvalidStateTransitionError between the specified states.

func (InvalidStateTransitionError) Error

type Manager

type Manager struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Manager wraps a State with get and set methods

func (*Manager) GetState

func (m *Manager) GetState() State

GetState returns the current state.

func (*Manager) SetState

func (m *Manager) SetState(s State)

SetState sets the state.

type MockClient

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

func NewMockClient

func NewMockClient(log zerolog.Logger) *MockClient

func (*MockClient) Broadcast

func (c *MockClient) Broadcast(msg model.BroadcastDKGMessage) error

func (*MockClient) ReadBroadcast

func (c *MockClient) ReadBroadcast(fromIndex uint, referenceBlock flow.Identifier) ([]model.BroadcastDKGMessage, error)

func (*MockClient) SubmitResult

func (c *MockClient) SubmitResult(groupPublicKey crypto.PublicKey, publicKeys []crypto.PublicKey) error

type State

type State uint32

State captures the state of an in-progress DKG.

const (
	Init State = iota
	Phase1
	Phase2
	Phase3
	End
	Shutdown
)

func (State) String

func (s State) String() string

String returns the string representation of a State

Jump to

Keyboard shortcuts

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