---
# System prepended metadata

title: '# DKG Sidecar Design for SSV'

---

*This is purely an idea for a sidecare design DKG for the SSV network, not a development proposal*
## Overview
Standardizing a sidecar design for a DKG subnetwork for SSV will open up the gates for implementors to develop different DKG implementations while removing a lot of the difficulties in integrating them with ssv.

A sidecar DKG implementation connects to the SSV node via RPC API, for: message authentication, message transport and access to the SSV registry.

A group of sidecars from same developer will create a sidecar subnetwork with a specific ID. 
Sidecars from the same network will work together to complete an entire DKG session.

Sidecars can be designed to have different DKG algorithms, processes and more just by developing them to be such. 

Some standardized messages are enforced to create unity and simplicity in designing sidecars: Init, Exchange and output messages.

![](https://hackmd.io/_uploads/Sy_os_Sun.png)

## Init DKG
Initiates a DKG by broadcasting the below message, via the SSV node, to other nodes.
Each node receiving the message and is part of the operators list will then send an Exchange message.

~~~go
type Init struct {
	// Operators involved in the DKG
	Operators []uint64 `ssz-max:"13"`
	// T is the threshold for signing
	T uint64
	// WithdrawalCredentials for deposit data
	WithdrawalCredentials []byte `ssz-max:"256"` // 2^23
	// Fork ethereum fork for signing
	Fork [4]byte `ssz-size:"4"`
    // Nonce for registering the validator in the SSV contracts
	Nonce uint64
}
~~~

## Exchange Message
Upon receiving the init message, the side car, via the SSV node, will broadcast an exchange message which contains a session encryption public key.

~~~go
type Exchange struct {
	PK []byte `ssz-max:"2048"`
}
~~~

## Key Generation Message
Each side car implements a specific key generation algorithm requiring different message structures. 
For that end a generic key generation message is used in which specific key generation messages can be carried over from sidecar to sidecar.
The below is a [Kyber](https://github.com/drand/kyber) - [specific](https://github.com/alonmuroch/rockx-dkg-cli/blob/drand/internal/node/messages.go) message and types

~~~go
const (
	KyberDealBundleMessageType TransportType = iota
	KyberResponseBundleMessageType
	KyberJustificationBundleMessageType
)

type KeyGenerationMessage struct {
	Type TransportType
	Data []byte `ssz-max:"2048"`
}
~~~

## Output Messag
After each sidecar finished with the key generation phase, it will produce a secret share for it self.
With the secret share it will partially sign:
1. deposit data
2. validator nonce

And encrypt:
1. secret share

It will then broadcast the below message to the network

~~~go
type Output struct {
	EncryptedShare                 []byte `ssz-max:"2048"`
	SharePK                        []byte `ssz-max:"2048"`
	ValidatorPK                    []byte `ssz-size:"48"`
	DepositDataPartialSignature    []byte `ssz-size:"96"`
	DepositValidatorNonceSignature []byte `ssz-size:"96"`
}
~~~

## Collecting outputs
The sidecar, via the SSV node API, will collect all signed outputs which must amount to 3f+1 for the DKG session to be valid.
With all outputs collected and validated the sidecar can reconstruct the necessary signatures, make a deposit and register the validator in the SSV contracts.

## Message Authentication
All messages are authenticated using the operator's RSA pubkey.

~~~go
func SignRSA(sk *rsa.PrivateKey, msg ssz.Marshaler) ([]byte, error) {
	byts, err := msg.MarshalSSZ()
	if err != nil {
		return nil, err
	}

	r := sha256.Sum256(byts)
	return sk.Sign(rand.Reader, r[:], &rsa.PSSOptions{
		SaltLength: rsa.PSSSaltLengthAuto,
		Hash:       crypto.SHA256,
	})
}

func VerifyRSA(pk *rsa.PublicKey, msg ssz.Marshaler, signature []byte) error {
	byts, err := msg.MarshalSSZ()
	if err != nil {
		return err
	}

	r := sha256.Sum256(byts)
	return rsa.VerifyPSS(pk, crypto.SHA256, r[:], signature, nil)
}
~~~