Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chores grooming #11

Merged
merged 53 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
46a4190
change sever to operator and clint to initiator
pavelkrolevets Sep 13, 2023
8f83e7a
update readme about operator`s priv key
pavelkrolevets Sep 13, 2023
64ee75f
change plaintext password to file
pavelkrolevets Sep 13, 2023
a5b52c5
add logs about message signature verification
pavelkrolevets Sep 13, 2023
44e019f
change fork hex to name
pavelkrolevets Sep 13, 2023
a6d122f
add identity to initiator
pavelkrolevets Sep 14, 2023
9ddfa77
add security notes to readme
pavelkrolevets Sep 14, 2023
aa1c0a7
update flags + docker
pavelkrolevets Sep 14, 2023
ba097fb
rename project
pavelkrolevets Sep 14, 2023
8935dad
readme update
pavelkrolevets Sep 14, 2023
ecf4e91
fix tests + work on comments
pavelkrolevets Sep 15, 2023
4ad85a0
add test of initiator identity
pavelkrolevets Sep 15, 2023
ac06e54
update test operator
pavelkrolevets Sep 15, 2023
a71153e
add linter + fixes
pavelkrolevets Sep 19, 2023
18c0b58
comment fixes
pavelkrolevets Sep 19, 2023
79805c5
update configs and paths to store
pavelkrolevets Sep 19, 2023
1174c1f
readme update
pavelkrolevets Sep 19, 2023
aecffb6
add .dockerignore
pavelkrolevets Sep 19, 2023
211e779
add logging to file same as ssv
pavelkrolevets Sep 20, 2023
954e17f
update board logger
pavelkrolevets Sep 20, 2023
5d7d73b
readme update
pavelkrolevets Sep 20, 2023
859819e
- Break dkg function into smaller functions
y0sher Sep 20, 2023
e02bc02
update tests
pavelkrolevets Sep 21, 2023
1aec967
update tests
pavelkrolevets Sep 21, 2023
70432af
add unhappy flow
pavelkrolevets Sep 21, 2023
bf6ce6c
add threshold tests
pavelkrolevets Sep 26, 2023
114b3d8
clean up
pavelkrolevets Sep 26, 2023
c3748e6
Merge remote-tracking branch 'origin/chores_grooming' into refactor/l…
pavelkrolevets Sep 26, 2023
ff259b4
fix makefile
pavelkrolevets Sep 26, 2023
260398a
Merge pull request #13 from bloxapp/refactor/logging_and_codestyle
pavelkrolevets Sep 26, 2023
8808ccd
Merge branch 'main' into chores_grooming
pavelkrolevets Sep 26, 2023
c00be40
add more threshold checks for 4 ops
pavelkrolevets Sep 26, 2023
2495c75
groom log reports
pavelkrolevets Sep 27, 2023
9675a4d
minor fix
pavelkrolevets Sep 27, 2023
4ab3607
add test shares order ar ssv payload
pavelkrolevets Oct 2, 2023
d7a439c
move NewID to crypto
pavelkrolevets Oct 2, 2023
7949342
remove VerifyFunc
pavelkrolevets Oct 2, 2023
8765162
move VerifyInitiatorMessage to state
pavelkrolevets Oct 2, 2023
c3c1dcd
removed rsa priv from local owner
pavelkrolevets Oct 2, 2023
e1caae3
logs path
y0sher Oct 3, 2023
e6fd291
change payload strcuture
y0sher Oct 3, 2023
8c9050c
fix payload to v4
y0sher Oct 3, 2023
8704e08
correct help for flag
y0sher Oct 3, 2023
2fad7d7
set default nonce to 0
y0sher Oct 3, 2023
8a21497
fixed integration tests to new format
y0sher Oct 4, 2023
28c4c0a
added single operator/initiator to Makefile
y0sher Oct 4, 2023
e79c08b
change withdrawl address to be ETH1
y0sher Oct 4, 2023
b0a1ae6
fix test to look for the ETH1 addr
y0sher Oct 4, 2023
f09a35a
add hexToAddress function with error handling
pavelkrolevets Oct 5, 2023
62077ed
add error wrapper at state
pavelkrolevets Oct 5, 2023
b623cbc
fix operator test
pavelkrolevets Oct 5, 2023
a2b65cf
- change ssvpayload name to keyshares
y0sher Oct 5, 2023
695177e
change error to show bad sigs
y0sher Oct 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./bin/
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea/
bin/
bin/
.vscode/
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
FROM golang:1.20
FROM golang:1.20-alpine3.17
RUN apk add build-base

WORKDIR /

COPY go.mod go.sum ./
RUN go mod download
RUN go mod download && go mod verify

COPY ./ ./

# Build
RUN CGO_ENABLED=1 GOOS=linux go build -o /app /cmd/dkgcli/dkgcli.go
RUN CGO_ENABLED=1 GOOS=linux go build -o /app /cmd/ssv-dkg/ssv-dkg.go


EXPOSE 3030
43 changes: 29 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,60 @@
# with Go source code. If you know what GOPATH is then you probably
# don't need to bother with make.

.PHONY: dkgcli test clean build docker-build
.PHONY: install clean build test docker-build-image docker-operators docker-initiator mockgen-install lint-prepare lint

GOBIN = ./build/bin
GO ?= latest
GORUN = env GO111MODULE=on go run
GOINSTALL = env GO111MODULE=on go install -v
GOTEST = env GO111MODULE=on go test -v
# Name of the Go binary output
BINARY_NAME=./bin/dkgcli
BINARY_NAME=./bin/ssv-dkg
# Docker image name
DOCKER_IMAGE=ssv-dkg-tool
DOCKER_IMAGE=ssv-dkg

install:
$(GOINSTALL) cmd/dkgcli/dkgcli.go
$(GOINSTALL) cmd/ssv-dkg/ssv-dkg.go
@echo "Done building."
@echo "Run dkgcli to launch the tool."
@echo "Run ssv-dkg to launch the tool."

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove tool

Copy link
Contributor

@y0sher y0sher Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@echo "Run ssv-dkg to launch the tool."
@echo "ssv-dkg installed successfully."


clean:
env GO111MODULE=on go clean -cache

# Recipe to compile the Go program
build:
@echo "Building Go binary..."
go build -o $(BINARY_NAME) ./cmd/dkgcli/dkgcli.go
go build -o $(BINARY_NAME) ./cmd/ssv-dkg/ssv-dkg.go

# Recipe to run tests
test:
@echo "running tests"
go test -p 1 ./...
go test -v -p 1 ./...

# Recipe to build the Docker image
docker-build:
docker-build-image:
@echo "Building Docker image..."
docker build -t $(DOCKER_IMAGE) .

docker-servers:
@echo "Running servers in docker demo"
docker-compose up --build server1 server2 server3 server4
docker-operators:
@echo "Running operators in docker demo"
docker-compose up --build operator1 operator2 operator3 operator4

docker-client:
@echo "Running client in docker demo"
docker-compose up --build client
docker-initiator:
@echo "Running initiator in docker demo"
docker-compose up --build initiator

mockgen-install:
go install github.com/golang/mock/[email protected]
@which mockgen || echo "Error: ensure `go env GOPATH` is added to PATH"

lint-prepare:
@echo "Preparing Linter"
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s latest

lint:
./bin/golangci-lint run -v ./...
@if [ ! -z "${UNFORMATTED}" ]; then \
echo "Some files requires formatting, please run 'go fmt ./...'"; \
exit 1; \
fi
147 changes: 106 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,136 @@
# ssv-dkg-tool
# ssv-dkg

## Architecture
### Build

```sh
make install
```

### Operators data

The data of the operators (ID, IP, Pubkey) can be collected in any way, for example a central server that you can pull the data from, or a preset file where all operators data exist.

### Build

```sh
make install
Information about operators can be collected at `json` file and supplied to initiator to use for a key generation.

Operators info file example (`./examples/operators_integration.json`):

```json
[
{
"id": 1,
"public_key": "LS0tLS1CRUdJTiBSU0....",
"ip": "http://localhost:3030"
},
{
"id": 2,
"public_key": "LS0tLS1CRUdJTiB....",
"ip": "http://localhost:3031"
}
]
```

### Server
### Operator

The dkg server is ran by a SSV operator, an Operator RSA private key is a requirement.
The server is able to participate in multiple instances in parallel.
Whenever the server receives a message it directs it to the right instance by the identifier, and respond with an answer.
The dkg-operator is ran by a SSV operator, an Operator RSA private key is a requirement.
The operator is able to participate in multiple DKG ceremonies in parallel.

Start a DKG server
NOTE: ssv-dkg tool is using an ssv operator private key file. Encrypted and plintext versiaons are supported. If `password` parameter is provided then the ssv-dkg tool assumes that the operator`s RSA key is encrypted, if not then it assumes that the key is provided as plaintext.

#### Start a DKG-operator

```sh
dkgcli start-dkg-server --privKey ./examples/server1/encrypted_private_key.json --port 3030 --password 12345678 --storeShare true
ssv-dkg start-operator \
--privKey ./examples/operator1/encrypted_private_key.json \
--port 3030 \
--password ./password \
--storeShare true \
--logLevel info \
--logFormat json \
--logLevelFormat capitalColor \
--logFilePath ./operator1_logs/debug.log

### where
--privKey ./encrypted_private_key.json # path to base 64 encoded RSA private key in PKCS #1, ASN.1 DER form.
--privKey ./encrypted_private_key.json # path to ssv operator`s private key
--port 3030 # port for listening messages
--password: 12345678 # password for encrypted keys
--storeShare # store created bls key share to a file for later reuse
--password: ./password # path to password file to decrypt the key
--storeShare: true # store created bls key share to a file for later reuse if needed
--logLevel: info # logger's log level (info/debug/
--logFormat: json # logger's encoding, valid values are 'json' (default) and 'console'
--logLevelFormat: capitalColor # logger's level format, valid values are 'capitalColor' (default), 'capital' or 'lowercase''
--logFilePath: ./operator1_logs/debug.log # a file path to write logs into
```

Its also possible to use yaml configuration file `./config/operator.yaml` for parameters. `dkgcli` will be looking for this file at `./config/` folder.
Its also possible to use yaml configuration file `./config/operator.yaml` for parameters. `ssv-dkg` will be looking for the config file at `./config/` folder.

Example:

```yaml
privKey: ./encrypted_private_key.json
password: 12345678
password: ./password
port: 3030
storeShare: true
logLevel: info
logFormat: json
logLevelFormat: capitalColor
logFilePath: ./operator1_logs/debug.log
```

When using configuration file, run:

```sh
dkgcli start-dkg-server
ssv-dkg start-operator --configPath "/examples/config/operator4.example.yaml"
```

### Initiator of DKG key generation
### Initiator

The initiator uses `init` to create the initial details needed to run DKG between all operators.

The initiator uses `init-dkg` to create the initial details needed to run DKG between all operators.
Generate initiator identity RSA key pair:

```sh
dkgcli init-dkg \
ssv-dkg generate-initiator-keys --password 12345678
```

This will create `encrypted_private_key.json` with encrypted by password RSA key pair
Write down `password` in any text file, for example to `./password`

Run:

```sh
ssv-dkg init \
--operatorIDs 1,2,3,4 \
--operatorsInfoPath ./examples/operators_integration.json \
--operatorsInfoPath ./operators_integration.json \
--owner 0x81592c3de184a3e2c0dcb5a261bc107bfa91f494 \
--nonce 4 \
--withdrawAddress 0000000000000000000000000000000000000009 \
--fork 00000000
--depositResultsPath deposit.json
--ssvPayloadResultsPath payload.json
--fork "mainnet" \
--depositResultsPath deposit.json \
--ssvPayloadResultsPath payload.json \
--initiatorPrivKey ./encrypted_private_key.json \
--initiatorPrivKeyPassword ./password \
--logLevel info \
--logFormat json \
--logLevelFormat capitalColor \
--logFilePath ./initiator_logs/debug.log

#### where
--operatorIDs 1,2,3,4 # operator IDs which will be used for a DKG ceremony
--operatorsInfoPath ./examples/operators_integration.json # path to info about operators - ID,base64(RSA pub key),
--operatorsInfoPath ./operators_integration.json # path to operators info ID,base64(RSA pub key),
--owner 0x81592c3de184a3e2c0dcb5a261bc107bfa91f494 # owner address for the SSV contract
--nonce 4 # owner nonce for the SSV contract
--fork "00000000" # fork id bytes in HEX
--depositResultsPath # path to store the result file
--ssvPayloadResultsPath # path to store ssv contract payload file
--withdrawAddress # Reward payments of excess balance over 32 ETH will automatically and regularly be sent to a withdrawal address linked to each validator, once provided by the user. Users can also exit staking entirely, unlocking their full validator balance.
--fork "mainnet" # fork name: mainnet, prater, or now_test_network
--depositResultsPath: ./output/ # path and filename to store the staking deposit file
--ssvPayloadResultsPath: ./output/ # path and filename to store ssv contract payload file
--initiatorPrivKey ./encrypted_private_key.json # path to ssv initiators`s private key
--initiatorPrivKeyPassword: ./password # path to password file to decrypt the key
--logLevel: info # logger's log level (info/debug/
--logFormat: json # logger's encoding, valid values are 'json' (default) and 'console'
--logLevelFormat: capitalColor # logger's level format, valid values are 'capitalColor' (default), 'capital' or 'lowercase''
--logFilePath: ./initiator_logs/debug.log # a file path to write logs into
```

Its also possible to use yaml configuration file `./config/initiator.yaml` for parameters. `dkgcli` will be looking for this file at `./config/` folder.
Its also possible to use yaml configuration file `./config/initiator.yaml` for parameters. `ssv-dkg` will be looking for this file at `./config/` folder at the same root as the binary.

Example:

Expand All @@ -82,29 +141,35 @@ owner: "0x81592c3de184a3e2c0dcb5a261bc107bfa91f494"
nonce: 4
fork: "00000000"
operatorsInfoPath: ./examples/operators_integration.json
depositResultsPath: ./deposit.json
ssvPayloadResultsPath: ./payload.json
depositResultsPath: ./output/
ssvPayloadResultsPath: ./output/
privKey: ./encrypted_private_key.json
password: ./password
```

When using configuration file, run:

```sh
dkgcli init-dkg
ssv-dkg init --configPath /examples/config/initiator.example.yaml
```

**_NOTE: Threshold is computed automatically using 3f+1 tolerance._**

### Generate RSA operator key
---

```sh
./dkgcli generate-operator-keys --password 12345678
```
### Security notes

---
Here we explain how we secure the communication between DKG ceremony initiator and operators

1. Initiator is using RSA key (2048 bits) to sign init message sent to operators. Upon receiving operators verify the sig using pub key at init message. If the sig is valid, operators store this pub key for further verification of messages coming from the initiator(s).
2. Operators are using RSA key (ssv operator key - 2048 bits) to sign every message sent back to initiator.
3. Initiator verifies every message incoming from any operator using ID and Public Key provided by operators info file, then initiator creates a combined message and signs it.
4. Operators verify each of the messages of other operators participating in the ceremony and verifies initiator`s signature of the combined message.
5. During the DKG protocol execution, the BLS auth scheme is used - G2 for its signature space and G1 for its public keys

### Schema
## Architecture

![flow](./imgs/DKGinit.drawio.png)
![flow](./docs/imgs/DKGinit.drawio.png)

#### Basic Flow Description:

Expand Down Expand Up @@ -210,7 +275,7 @@ Initial message fields:

### `Switch` instance management

The DKG server can handle multiple DKG instances, it saves up to MaxInstances(1024) up to `MaxInstanceTime` (5 minutes). If a new Init arrives we try to clean our list from instances older than `MaxInstanceTime` if we find any, we remove them and add the incoming, otherwise we respond with error that the maximum number of instances is already running.
The DKG-operator can handle multiple DKG instances, it saves up to MaxInstances(1024) up to `MaxInstanceTime` (5 minutes). If a new Init arrives we try to clean our list from instances older than `MaxInstanceTime` if we find any, we remove them and add the incoming, otherwise we respond with error that the maximum number of instances is already running.

### TODO:

Expand Down
11 changes: 5 additions & 6 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ package cli
import (
"log"

"github.com/bloxapp/ssv-dkg-tool/cli/initiator"
"github.com/bloxapp/ssv-dkg-tool/cli/operator"
"github.com/bloxapp/ssv-dkg/cli/initiator"
"github.com/bloxapp/ssv-dkg/cli/operator"
"github.com/spf13/cobra"
"go.uber.org/zap"
)

func init() {
RootCmd.AddCommand(initiator.StartDKG)
RootCmd.AddCommand(operator.StartDKGServer)
RootCmd.AddCommand(operator.GenerateOperatorKeysCmd)
RootCmd.AddCommand(operator.ExportKeysCmd)
RootCmd.AddCommand(initiator.GenerateInitiatorKeysCmd)
RootCmd.AddCommand(operator.StartDKGOperator)
}

// RootCmd represents the root command of DKG-tool CLI
var RootCmd = &cobra.Command{
Use: "dkgcli",
Use: "ssv-dkg",
Short: "CLI for running Distributed Key Generation protocol",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
},
Expand Down
Loading