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
- func CanonicalInstanceID(chainID flow.ChainID, epochCounter uint64) string
- func IsInvalidStateTransitionError(err error) bool
- func NewDKGMessageHasher() hash.Hasher
- type Broker
- func (b *Broker) Broadcast(data []byte)
- func (b *Broker) Disqualify(node int, log string)
- func (b *Broker) FlagMisbehavior(node int, log string)
- func (b *Broker) GetBroadcastMsgCh() <-chan messages.DKGMessage
- func (b *Broker) GetIndex() int
- func (b *Broker) GetPrivateMsgCh() <-chan messages.DKGMessage
- func (b *Broker) Poll(referenceBlock flow.Identifier) error
- func (b *Broker) PrivateSend(dest int, data []byte)
- func (b *Broker) Shutdown()
- func (b *Broker) SubmitResult(pubKey crypto.PublicKey, groupKeys []crypto.PublicKey) error
- type BrokerTunnel
- type Client
- type Controller
- func (c *Controller) End() error
- func (c *Controller) EndPhase1() error
- func (c *Controller) EndPhase2() error
- func (c *Controller) GetArtifacts() (crypto.PrivateKey, crypto.PublicKey, []crypto.PublicKey)
- func (c *Controller) GetIndex() int
- func (c *Controller) Poll(blockReference flow.Identifier) error
- func (c *Controller) Run() error
- func (c *Controller) Shutdown()
- func (c *Controller) SubmitResult() error
- type ControllerConfig
- type ControllerFactory
- type InvalidStateTransitionError
- type Manager
- type MockClient
- type State
Constants ¶
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 ¶
CanonicalInstanceID returns the canonical DKG instance ID for the given epoch on the given chain.
func NewDKGMessageHasher ¶
NewDKGMessageHasher returns a hasher for signing and verifying DKG broadcast messages.
Types ¶
type Broker ¶
Broker is an implementation of the DKGBroker interface which is intended to be used in conjuction 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, dkgContractClient module.DKGContractClient, tunnel *BrokerTunnel) *Broker
NewBroker instantiates a new epoch-specific broker capable of communicating with other nodes via a network engine and dkg smart-contract.
func (*Broker) Disqualify ¶
Disqualify flags that a node is misbehaving and got disqualified
func (*Broker) FlagMisbehavior ¶
FlagMisbehavior warns that a node is misbehaving.
func (*Broker) GetBroadcastMsgCh ¶
func (b *Broker) GetBroadcastMsgCh() <-chan messages.DKGMessage
GetBroadcastMsgCh returns the channel through which consumers can receive incoming broadcast DKG messages.
func (*Broker) GetPrivateMsgCh ¶
func (b *Broker) GetPrivateMsgCh() <-chan messages.DKGMessage
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 ¶
PrivateSend sends a DKGMessage to a destination over a private channel. It appends the current DKG instance ID to the message.
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.
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.
func (*BrokerTunnel) SendOut ¶
func (t *BrokerTunnel) SendOut(msg messages.PrivDKGMessageOut)
SendOut pushes outcoing messages in the MsgChOut channel to be received and forwarded by the network engine.
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, 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 broadcast (received and stored in the smart contract)
func (*Client) SubmitResult ¶
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, dkgContractClient 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 ¶
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 ¶
func (e InvalidStateTransitionError) Error() string
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)