Merge branch 'master' into feat/kafka-auth-tls

This commit is contained in:
programmer10110 2020-11-05 16:04:27 +03:00
commit 461f5d48ee
31 changed files with 1885 additions and 213 deletions

View File

@ -9,7 +9,7 @@ git clone git@github.com:depools/dc4bc.git
First install the Go toolchain:
```
wget https://golang.org/dl/go1.15.2.linux-amd64.tar.gz
curl -OL https://golang.org/dl/go1.15.2.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.15.2.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
```
@ -92,7 +92,7 @@ Print your communication public key and encryption public key and save it somewh
$ ./dc4bc_cli get_pubkey --listen_addr localhost:8080
EcVs+nTi4iFERVeBHUPePDmvknBx95co7csKj0sZNuo=
# Inside the airgapped shell:
>>> show_dkg_pub_key
>>> show_dkg_pubkey
sN7XbnvZCRtg650dVCCpPK/hQ/rMTSlxrdnvzJ75zV4W/Uzk9suvjNPtyRt7PDXLDTGNimn+4X/FcJj2K6vDdgqOrr9BHwMqJXnQykcv3IV0ggIUjpMMgdbQ+0iSseyq
```
@ -106,12 +106,12 @@ Example of start_dkg_propose.json file structure:
"SigningThreshold": 2,
"Participants": [
{
"Addr": "e0d8083f8a2d18f310bfbdc9649a83664470f46053ab53c105a054b08f9eff85",
"Username": "john_doe",
"PubKey": "EcVs+nTi4iFERVeBHUPePDmvknBx95co7csKj0sZNuo=",
"DkgPubKey": "sN7XbnvZCRtg650dVCCpPK/hQ/rMTSlxrdnvzJ75zV4W/Uzk9suvjNPtyRt7PDXLDTGNimn+4X/FcJj2K6vDdgqOrr9BHwMqJXnQykcv3IV0ggIUjpMMgdbQ+0iSseyq"
},
{
"Addr": "addr2",
"Username": "jane_doe",
"PubKey": "cHVia2V5Mg==",
"DkgPubKey": "ZGtnX3B1YmtleV8y"
}
@ -124,7 +124,7 @@ The message will be consumed by your node:
[john_doe] starting to poll messages from append-only log...
[john_doe] Starting HTTP server on address: localhost:8080
[john_doe] Handling message with offset 0, type event_sig_proposal_init
[john_doe] message event_sig_proposal_init done successfully from e0d8083f8a2d18f310bfbdc9649a83664470f46053ab53c105a054b08f9eff85
[john_doe] message event_sig_proposal_init done successfully from john_doe
[john_doe] Successfully processed message with offset 0, type event_sig_proposal_init
```
@ -181,7 +181,7 @@ Operation successfully scanned
After scanning the response, a message is send to the message board. When all participants perform the necessary operations, the node will proceed to the next step:
```
[john_doe] message event_sig_proposal_confirm_by_participant done successfully from b8c083cd717b9958e141be5956bab1e463a7a0d85e4fe8924833601d43d671c4
[john_doe] message event_sig_proposal_confirm_by_participant done successfully from john_doe
```
Further actions are repetitive. Check for new pending operations:
```
@ -202,9 +202,8 @@ Now we have to collectively sign a message. Some participant will run the comman
# Inside dc4bc_airgapped prompt:
$ >>> show_finished_dkg
AABB10CABB10
$ echo "the message to sign" | base64
dGhlIG1lc3NhZ2UgdG8gc2lnbgo=
$ ./dc4bc_cli sign_data AABB10CABB10 dGhlIG1lc3NhZ2UgdG8gc2lnbgo= --listen_addr localhost:8080
$ echo "the message to sign" > data.txt
$ ./dc4bc_cli sign_data AABB10CABB10 data.txt --listen_addr localhost:8080
```
Further actions are repetitive and are similar to the DKG procedure. Check for new pending operations, feed them to `dc4bc_airgapped`, pass the responses to the client, then wait for new operations, etc. After some back and forth you'll see the node tell you that the signature is ready:
```
@ -229,4 +228,4 @@ You can verify any signature by executing `verify_signature` command inside the
> Enter the BLS signature: tK+3CV2CI0flgwWLuhrZA5eaFfuJIvpLAc6CbAy5XBuRpzuCkjOZLCU6z1SvlwQIBJp5dAVa2rtbSy1jl98YtidujVWeUDNUz+kRl2C1C1BeLG5JvzQxhgr2dDxq0thu
> Enter the message which was signed (base64): dGhlIG1lc3NhZ2UgdG8gc2lnbgo=
Signature is correct!
```
```

87
Makefile Normal file → Executable file
View File

@ -1,3 +1,55 @@
.ONESHELL:
TMP_DIR?=/tmp/
OPENCV_VERSION?=4.4.0
PROJECT_DIR=$(shell pwd)
RPMS=cmake curl wget git gtk2-devel libpng-devel libjpeg-devel libtiff-devel tbb tbb-devel libdc1394-devel unzip
DEBS=unzip wget build-essential cmake curl git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
explain:
@echo "For quick install with typical defaults of both OpenCV and GoCV, run 'make install'"
# Detect Linux distribution
distro_deps=
ifneq ($(shell which dnf 2>/dev/null),)
distro_deps=deps_fedora
else
ifneq ($(shell which apt-get 2>/dev/null),)
distro_deps=deps_debian
else
ifneq ($(shell which yum 2>/dev/null),)
distro_deps=deps_rh_centos
endif
endif
endif
# Install all necessary dependencies.
deps: $(distro_deps)
deps_rh_centos:
sudo yum -y install pkgconfig $(RPMS)
deps_fedora:
sudo dnf -y install pkgconf-pkg-config $(RPMS)
deps_debian:
sudo apt-get -y update
sudo apt-get -y install $(DEBS)
download:
rm -rf $(TMP_DIR)opencv
mkdir $(TMP_DIR)opencv
cd $(TMP_DIR)opencv
curl -Lo opencv.zip https://github.com/opencv/opencv/archive/$(OPENCV_VERSION).zip
unzip -q opencv.zip
curl -Lo opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/$(OPENCV_VERSION).zip
unzip -q opencv_contrib.zip
rm opencv.zip opencv_contrib.zip
cd -
test:
@echo "Testing Go packages..."
@go test ./... -cover
@ -17,6 +69,8 @@ build-darwin:
GOOS=darwin GOARCH=amd64 go build -o dc4bc_cli_darwin ./cmd/dc4bc_cli/
@echo "Building dc4bc_airgapped..."
GOOS=darwin GOARCH=amd64 go build -o dc4bc_airgapped_darwin ./cmd/airgapped/
@echo "Building dc4bc_prysm_compatibility_checker..."
GOOS=darwin GOARCH=amd64 go build -o dc4bc_prysm_compatibility_checker_darwin ./cmd/prysm_compatibility_checker/
build-linux:
@echo "Building dc4bc_d..."
@ -25,5 +79,38 @@ build-linux:
GOOS=linux GOARCH=amd64 go build -o dc4bc_cli_linux ./cmd/dc4bc_cli/
@echo "Building dc4bc_airgapped..."
GOOS=linux GOARCH=amd64 go build -o dc4bc_airgapped_linux ./cmd/airgapped/
@echo "Building dc4bc_prysm_compatibility_checker..."
GOOS=linux GOARCH=amd64 go build -o dc4bc_prysm_compatibility_checker_linux ./cmd/prysm_compatibility_checker/
clean:
go clean --cache
rm -rf $(TMP_DIR)opencv
sudo_pre_install_clean:
sudo rm -rf /usr/local/lib/cmake/opencv4/
sudo rm -rf /usr/local/lib/libopencv*
sudo rm -rf /usr/local/lib/pkgconfig/opencv*
sudo rm -rf /usr/local/include/opencv*
build-linux-static: deps sudo_pre_install_clean download
cd $(TMP_DIR)opencv/opencv-$(OPENCV_VERSION)
mkdir build
cd build
rm -rf *
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_SHARED_LIBS=OFF -D OPENCV_EXTRA_MODULES_PATH=$(TMP_DIR)opencv/opencv_contrib-$(OPENCV_VERSION)/modules -D BUILD_DOCS=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_opencv_java=NO -D WITH_FFMPEG=OFF -D WITH_QT=OFF -D WITH_GTK=OFF -D WITH_CUDA=OFF -D WITH_TIFF=OFF -D WITH_WEBP=OFF -D WITH_QT=OFF -D WITH_PNG=OFF -D WITH_1394=OFF -D HAVE_OPENEXR=OFF -D BUILD_opencv_python=NO -D BUILD_opencv_python2=NO -D BUILD_opencv_python3=NO -D WITH_JASPER=OFF -D OPENCV_GENERATE_PKGCONFIG=YES ..
$(MAKE) -j $(shell nproc --all)
$(MAKE) preinstall
cd $(PROJECT_DIR)
export CGO_CPPFLAGS="-I/usr/local/include/opencv4"
export CGO_LDFLAGS="-L/usr/local/lib -L/usr/local/lib/opencv4/3rdparty -L/tmp/opencv/opencv-4.4.0/build/lib -lopencv_gapi -lopencv_stitching -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_dpm -lopencv_highgui -lopencv_face -lopencv_freetype -lopencv_fuzzy -lopencv_hfs -lopencv_img_hash -lopencv_intensity_transform -lopencv_line_descriptor -lopencv_quality -lopencv_rapid -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_superres -lopencv_optflow -lopencv_surface_matching -lopencv_tracking -lopencv_datasets -lopencv_text -lopencv_dnn -lopencv_plot -lopencv_videostab -lopencv_videoio -lopencv_xfeatures2d -lopencv_shape -lopencv_ml -lopencv_ximgproc -lopencv_video -lopencv_xobjdetect -lopencv_objdetect -lopencv_calib3d -lopencv_imgcodecs -lopencv_features2d -lopencv_flann -lopencv_xphoto -lopencv_photo -lopencv_imgproc -lopencv_core -littnotify -llibprotobuf -lIlmImf -lquirc -lippiw -lippicv -lade -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -lcairo -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lgthread-2.0 -lz -ljpeg -lfreetype -lharfbuzz -ldl -lm -lpthread -lrt"
@echo "Building dc4bc_d..."
go build -ldflags "-linkmode 'external' -extldflags '-static'" -o dc4bc_d_linux ./cmd/dc4bc_d/*.go
@echo "Building dc4bc_cli..."
go build -ldflags "-linkmode 'external' -extldflags '-static'" -o dc4bc_cli_linux ./cmd/dc4bc_cli/*.go
@echo "Building dc4bc_airgapped..."
go build -ldflags "-linkmode 'external' -extldflags '-static'" -o dc4bc_airgapped_linux ./cmd/airgapped/*.go
.PHONY: mocks

View File

@ -260,8 +260,7 @@ func (am *Machine) HandleQR() (string, error) {
return "", fmt.Errorf("failed to marshal operation: %w", err)
}
qrPath := filepath.Join(am.resultQRFolder, fmt.Sprintf("%s_%s_%s.gif", resultOperation.Type, resultOperation.ID,
resultOperation.To))
qrPath := filepath.Join(am.resultQRFolder, fmt.Sprintf("dc4bc_qr_%s-response.gif", resultOperation.ID))
if err = am.qrProcessor.WriteQR(qrPath, operationBz); err != nil {
return "", fmt.Errorf("failed to write QR: %w", err)
}

View File

@ -147,7 +147,7 @@ func TestAirgappedAllSteps(t *testing.T) {
}
entry := &responses.SignatureProposalParticipantInvitationEntry{
ParticipantId: n.ParticipantID,
Addr: n.Participant,
Username: n.Participant,
Threshold: threshold,
DkgPubKey: pubKey,
}
@ -172,7 +172,7 @@ func TestAirgappedAllSteps(t *testing.T) {
}
entry := &responses.DKGProposalPubKeysParticipantEntry{
ParticipantId: n.ParticipantID,
Addr: n.Participant,
Username: n.Participant,
DkgPubKey: pubKey,
}
getCommitsRequest = append(getCommitsRequest, entry)
@ -198,7 +198,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.commits {
p := responses.DKGProposalCommitParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgCommit: req.Commit,
}
payload = append(payload, &p)
@ -222,7 +222,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.deals {
p := responses.DKGProposalDealParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgDeal: req.Deal,
}
payload = append(payload, &p)
@ -246,7 +246,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.responses {
p := responses.DKGProposalResponseParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgResponse: req.Response,
}
payload = append(payload, &p)
@ -300,7 +300,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.partialSigns {
p := responses.SigningProcessParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
PartialSign: req.PartialSign,
}
payload.Participants = append(payload.Participants, &p)
@ -371,7 +371,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
}
entry := &responses.SignatureProposalParticipantInvitationEntry{
ParticipantId: n.ParticipantID,
Addr: n.Participant,
Username: n.Participant,
Threshold: threshold,
DkgPubKey: pubKey,
}
@ -396,7 +396,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
}
entry := &responses.DKGProposalPubKeysParticipantEntry{
ParticipantId: n.ParticipantID,
Addr: n.Participant,
Username: n.Participant,
DkgPubKey: pubKey,
}
getCommitsRequest = append(getCommitsRequest, entry)
@ -422,7 +422,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.commits {
p := responses.DKGProposalCommitParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgCommit: req.Commit,
}
payload = append(payload, &p)
@ -484,7 +484,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.deals {
p := responses.DKGProposalDealParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgDeal: req.Deal,
}
payload = append(payload, &p)
@ -508,7 +508,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.responses {
p := responses.DKGProposalResponseParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgResponse: req.Response,
}
payload = append(payload, &p)
@ -562,7 +562,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.partialSigns {
p := responses.SigningProcessParticipantEntry{
ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
PartialSign: req.PartialSign,
}
payload.Participants = append(payload.Participants, &p)

View File

@ -113,7 +113,7 @@ func (am *Machine) handleStateDkgCommitsAwaitConfirmations(o *client.Operation)
if err = pubKey.UnmarshalBinary(entry.DkgPubKey); err != nil {
return fmt.Errorf("failed to unmarshal pubkey: %w", err)
}
dkgInstance.StorePubKey(entry.Addr, entry.ParticipantId, pubKey)
dkgInstance.StorePubKey(entry.Username, entry.ParticipantId, pubKey)
}
if err = dkgInstance.InitDKGInstance(am.baseSeed); err != nil {
@ -182,7 +182,7 @@ func (am *Machine) handleStateDkgDealsAwaitConfirmations(o *client.Operation) er
}
dkgCommits = append(dkgCommits, commit)
}
dkgInstance.StoreCommits(entry.Addr, dkgCommits)
dkgInstance.StoreCommits(entry.Username, dkgCommits)
}
deals, err := dkgInstance.GetDeals()
@ -245,7 +245,7 @@ func (am *Machine) handleStateDkgResponsesAwaitConfirmations(o *client.Operation
if err = json.Unmarshal(decryptedDealBz, &deal); err != nil {
return fmt.Errorf("failed to unmarshal deal")
}
dkgInstance.StoreDeal(entry.Addr, &deal)
dkgInstance.StoreDeal(entry.Username, &deal)
}
processedResponses, err := dkgInstance.ProcessDeals()
@ -298,7 +298,7 @@ func (am *Machine) handleStateDkgMasterKeyAwaitConfirmations(o *client.Operation
if err = json.Unmarshal(entry.DkgResponse, &entryResponses); err != nil {
return fmt.Errorf("failed to unmarshal responses: %w", err)
}
dkgInstance.StoreResponses(entry.Addr, entryResponses)
dkgInstance.StoreResponses(entry.Username, entryResponses)
}
if err = dkgInstance.ProcessResponses(); err != nil {

View File

@ -230,7 +230,7 @@ func (c *BaseClient) ProcessMessage(message storage.Message) error {
if err != nil {
return fmt.Errorf("failed to get SigningQuorumParticipant: %w", err)
}
if initiator.Addr == c.GetUsername() {
if initiator.Username == c.GetUsername() {
break
}
}
@ -400,9 +400,9 @@ func (c *BaseClient) signMessage(message []byte) ([]byte, error) {
}
func (c *BaseClient) verifyMessage(fsmInstance *state_machines.FSMInstance, message storage.Message) error {
senderPubKey, err := fsmInstance.GetPubKeyByAddr(message.SenderAddr)
senderPubKey, err := fsmInstance.GetPubKeyByUsername(message.SenderAddr)
if err != nil {
return fmt.Errorf("failed to GetPubKeyByAddr: %w", err)
return fmt.Errorf("failed to GetPubKeyByUsername: %w", err)
}
if !ed25519.Verify(senderPubKey, message.Bytes(), message.Signature) {
@ -411,3 +411,11 @@ func (c *BaseClient) verifyMessage(fsmInstance *state_machines.FSMInstance, mess
return nil
}
func (c *BaseClient) GetFSMDump(dkgID string) (*state_machines.FSMDump, error) {
fsmInstance, err := c.getFSMInstance(dkgID)
if err != nil {
return nil, fmt.Errorf("failed to get FSM instance for DKG round ID %s: %w", dkgID, err)
}
return fsmInstance.FSMDump(), nil
}

View File

@ -63,22 +63,22 @@ func TestClient_ProcessMessage(t *testing.T) {
messageData := requests.SignatureProposalParticipantsListRequest{
Participants: []*requests.SignatureProposalParticipantsEntry{
{
Addr: senderAddr,
Username: senderAddr,
PubKey: senderKeyPair.Pub,
DkgPubKey: make([]byte, 128),
},
{
Addr: "111",
Username: "111",
PubKey: client.NewKeyPair().Pub,
DkgPubKey: make([]byte, 128),
},
{
Addr: "222",
Username: "222",
PubKey: client.NewKeyPair().Pub,
DkgPubKey: make([]byte, 128),
},
{
Addr: "333",
Username: "333",
PubKey: client.NewKeyPair().Pub,
DkgPubKey: make([]byte, 128),
},

View File

@ -4,7 +4,7 @@ import (
"bytes"
"context"
"crypto/md5"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
@ -15,7 +15,6 @@ import (
"testing"
"time"
bls12381 "github.com/corestario/kyber/pairing/bls12381"
"github.com/depools/dc4bc/airgapped"
"github.com/depools/dc4bc/client/types"
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
@ -111,14 +110,8 @@ func (n *node) run(t *testing.T) {
if err = json.Unmarshal(msg.Data, &pubKeyReq); err != nil {
t.Fatalf("failed to unmarshal pubKey request: %v", err)
}
seed := make([]byte, 32)
_, _ = rand.Read(seed)
pubKey := bls12381.NewBLS12381Suite(seed).Point()
if err = pubKey.UnmarshalBinary(pubKeyReq.MasterKey); err != nil {
t.Fatalf("failed to unmarshal pubkey: %v", err)
}
if err = ioutil.WriteFile(fmt.Sprintf("/tmp/participant_%d.pubkey",
pubKeyReq.ParticipantId), []byte(pubKey.String()), 0666); err != nil {
pubKeyReq.ParticipantId), []byte(hex.EncodeToString(pubKeyReq.MasterKey)), 0666); err != nil {
t.Fatalf("failed to write pubkey to temp file: %v", err)
}
}
@ -237,7 +230,7 @@ func TestFullFlow(t *testing.T) {
log.Fatalln("failed to get DKG pubKey:", err.Error())
}
participants = append(participants, &requests.SignatureProposalParticipantsEntry{
Addr: node.client.GetUsername(),
Username: node.client.GetUsername(),
PubKey: node.client.GetPubKey(),
DkgPubKey: dkgPubKey,
})

View File

@ -8,7 +8,6 @@ import (
"io/ioutil"
"log"
"net/http"
"time"
"github.com/depools/dc4bc/client/types"
@ -80,10 +79,51 @@ func (c *BaseClient) StartHTTPServer(listenAddr string) error {
mux.HandleFunc("/startDKG", c.startDKGHandler)
mux.HandleFunc("/proposeSignMessage", c.proposeSignDataHandler)
mux.HandleFunc("/saveOffset", c.saveOffsetHandler)
mux.HandleFunc("/getOffset", c.getOffsetHandler)
mux.HandleFunc("/getFSMDump", c.getFSMDumpHandler)
mux.HandleFunc("/getFSMList", c.getFSMList)
c.Logger.Log("Starting HTTP server on address: %s", listenAddr)
return http.ListenAndServe(listenAddr, mux)
}
func (c *BaseClient) getFSMDumpHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
return
}
dump, err := c.GetFSMDump(r.URL.Query().Get("dkgID"))
if err != nil {
errorResponse(w, http.StatusInternalServerError, err.Error())
return
}
successResponse(w, dump)
}
func (c *BaseClient) getFSMList(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
return
}
fsmInstances, err := c.state.GetAllFSM()
if err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get all FSM instances: %v", err))
return
}
fsmInstancesStates := make(map[string]string, len(fsmInstances))
for k, v := range fsmInstances {
state, err := v.State()
if err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get FSM state: %v", err))
return
}
fsmInstancesStates[k] = state.String()
}
successResponse(w, fsmInstancesStates)
}
func (c *BaseClient) getUsernameHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
@ -100,6 +140,47 @@ func (c *BaseClient) getPubkeyHandler(w http.ResponseWriter, r *http.Request) {
successResponse(w, c.GetPubKey())
}
func (c *BaseClient) getOffsetHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
return
}
offset, err := c.state.LoadOffset()
if err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to load offset: %v", err))
return
}
successResponse(w, offset)
}
func (c *BaseClient) saveOffsetHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
return
}
reqBytes, err := ioutil.ReadAll(r.Body)
if err != nil {
errorResponse(w, http.StatusBadRequest, fmt.Sprintf("failed to read request body: %v", err))
return
}
defer r.Body.Close()
var req map[string]uint64
if err = json.Unmarshal(reqBytes, &req); err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to unmarshal request: %v", err))
return
}
if _, ok := req["offset"]; !ok {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("offset cannot be null: %v", err))
return
}
if err = c.state.SaveOffset(req["offset"]); err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to save offset: %v", err))
return
}
successResponse(w, "ok")
}
func (c *BaseClient) sendMessageHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
@ -275,7 +356,7 @@ func (c *BaseClient) proposeSignDataHandler(w http.ResponseWriter, r *http.Reque
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get FSM instance: %v", err))
return
}
participantID, err := fsmInstance.GetIDByAddr(c.GetUsername())
participantID, err := fsmInstance.GetIDByUsername(c.GetUsername())
if err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get participantID: %v", err))
return

View File

@ -31,6 +31,7 @@ type State interface {
SaveFSM(dkgRoundID string, dump []byte) error
LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, bool, error)
GetAllFSM() (map[string]*state_machines.FSMInstance, error)
PutOperation(operation *types.Operation) error
DeleteOperation(operationID string) error
@ -146,6 +147,27 @@ func (s *LevelDBState) SaveFSM(dkgRoundID string, dump []byte) error {
return nil
}
func (s *LevelDBState) GetAllFSM() (map[string]*state_machines.FSMInstance, error) {
bz, err := s.stateDb.Get([]byte(fsmStateKey), nil)
if err != nil {
return nil, fmt.Errorf("failed to get FSM instances: %w", err)
}
var fsmInstancesBz = map[string][]byte{}
if len(bz) > 0 {
if err := json.Unmarshal(bz, &fsmInstancesBz); err != nil {
return nil, fmt.Errorf("failed to unmarshal FSM instances: %w", err)
}
}
fsmInstances := make(map[string]*state_machines.FSMInstance, len(fsmInstancesBz))
for k, v := range fsmInstancesBz {
fsmInstances[k], err = state_machines.FromDump(v)
if err != nil {
return nil, fmt.Errorf("failed to restore FSM instance from dump: %w", err)
}
}
return fsmInstances, nil
}
func (s *LevelDBState) LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, bool, error) {
bz, err := s.stateDb.Get([]byte(fsmStateKey), nil)
if err != nil {

View File

@ -9,6 +9,7 @@ import (
"os"
"os/signal"
"runtime"
"strconv"
"strings"
"syscall"
"time"
@ -33,10 +34,17 @@ type terminal struct {
reader *bufio.Reader
airgapped *airgapped.Machine
commands map[string]*terminalCommand
stopDroppingSensitiveData chan bool
}
func NewTerminal(machine *airgapped.Machine) *terminal {
t := terminal{bufio.NewReader(os.Stdin), machine, make(map[string]*terminalCommand)}
t := terminal{
bufio.NewReader(os.Stdin),
machine,
make(map[string]*terminalCommand),
make(chan bool),
}
t.addCommand("read_qr", &terminalCommand{
commandHandler: t.readQRCommand,
description: "Reads QR chunks from camera, handle a decoded operation and returns paths to qr chunks of operation's result",
@ -45,7 +53,7 @@ func NewTerminal(machine *airgapped.Machine) *terminal {
commandHandler: t.helpCommand,
description: "shows available commands",
})
t.addCommand("show_dkg_pub_key", &terminalCommand{
t.addCommand("show_dkg_pubkey", &terminalCommand{
commandHandler: t.showDKGPubKeyCommand,
description: "shows a dkg pub key",
})
@ -72,6 +80,10 @@ func NewTerminal(machine *airgapped.Machine) *terminal {
commandHandler: t.verifySignCommand,
description: "verifies a BLS signature of a message",
})
t.addCommand("change_configuration", &terminalCommand{
commandHandler: t.changeConfigurationCommand,
description: "changes a configuration variables (frames delay, chunk size, etc...)",
})
return &t
}
@ -116,7 +128,12 @@ func (t *terminal) showFinishedDKGCommand() error {
}
for dkgID, keyring := range keyrings {
fmt.Printf("DKG identifier: %s\n", dkgID)
fmt.Printf("PubKey: %s\n", keyring.PubPoly.Commit().String())
pubkeyBz, err := keyring.PubPoly.Commit().MarshalBinary()
if err != nil {
fmt.Println("failed to marshal pubkey: %w", err)
continue
}
fmt.Printf("PubKey: %s\n", base64.StdEncoding.EncodeToString(pubkeyBz))
fmt.Println("-----------------------------------------------------")
}
return nil
@ -135,6 +152,62 @@ func (t *terminal) replayOperationLogCommand() error {
return nil
}
func (t *terminal) changeConfigurationCommand() error {
fmt.Print("> Enter a new path to save QR codes (leave empty to avoid changes): ")
newQRCodesfolder, _, err := t.reader.ReadLine()
if err != nil {
return fmt.Errorf("failed to read input: %w", err)
}
if len(newQRCodesfolder) > 0 {
t.airgapped.SetResultQRFolder(string(newQRCodesfolder))
fmt.Printf("Folder to save QR codes was changed to: %s\n", string(newQRCodesfolder))
}
fmt.Print("> Enter a new frames delay in 100ths of second (leave empty to avoid changes): ")
framesDelayInput, _, err := t.reader.ReadLine()
if err != nil {
return fmt.Errorf("failed to read input: %w", err)
}
if len(framesDelayInput) > 0 {
framesDelay, err := strconv.Atoi(string(framesDelayInput))
if err != nil {
return fmt.Errorf("failed to parse new frames delay: %w", err)
}
t.airgapped.SetQRProcessorFramesDelay(framesDelay)
fmt.Printf("Frames delay was changed to: %d\n", framesDelay)
}
fmt.Print("> Enter a new QR chunk size (leave empty to avoid changes): ")
chunkSizeInput, _, err := t.reader.ReadLine()
if err != nil {
return fmt.Errorf("failed to read input: %w", err)
}
if len(chunkSizeInput) > 0 {
chunkSize, err := strconv.Atoi(string(chunkSizeInput))
if err != nil {
return fmt.Errorf("failed to parse new chunk size: %w", err)
}
t.airgapped.SetQRProcessorChunkSize(chunkSize)
fmt.Printf("Chunk size was changed to: %d\n", chunkSize)
}
fmt.Print("> Enter a password expiration duration (leave empty to avoid changes): ")
durationInput, _, err := t.reader.ReadLine()
if err != nil {
return fmt.Errorf("failed to read input: %w", err)
}
if len(durationInput) > 0 {
duration, err := time.ParseDuration(string(durationInput))
if err != nil {
return fmt.Errorf("failed to parse new duration: %w", err)
}
t.stopDroppingSensitiveData <- true
go t.dropSensitiveDataByTicker(duration)
fmt.Printf("Password expiration was changed to: %s\n", duration.String())
}
return nil
}
func (t *terminal) dropOperationLogCommand() error {
fmt.Print("> Enter the DKGRoundIdentifier: ")
dkgRoundIdentifier, err := t.reader.ReadString('\n')
@ -242,10 +315,16 @@ func (t *terminal) run() error {
}
}
func (t *terminal) dropSensitiveData(passExpiration time.Duration) {
func (t *terminal) dropSensitiveDataByTicker(passExpiration time.Duration) {
ticker := time.NewTicker(passExpiration)
for range ticker.C {
t.airgapped.DropSensitiveData()
defer ticker.Stop()
for {
select {
case <-ticker.C:
t.airgapped.DropSensitiveData()
case <-t.stopDroppingSensitiveData:
return
}
}
}
@ -290,7 +369,7 @@ func main() {
}()
t := NewTerminal(air)
go t.dropSensitiveData(passwordLifeDuration)
go t.dropSensitiveDataByTicker(passwordLifeDuration)
if err = t.run(); err != nil {
log.Fatalf(err.Error())
}

View File

@ -7,11 +7,14 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/depools/dc4bc/fsm/state_machines"
"io/ioutil"
"log"
"net/http"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
"github.com/depools/dc4bc/fsm/fsm"
@ -56,6 +59,10 @@ func main() {
getHashOfStartDKGCommand(),
getSignaturesCommand(),
getSignatureCommand(),
saveOffsetCommand(),
getOffsetCommand(),
getFSMStatusCommand(),
getFSMListCommand(),
)
if err := rootCmd.Execute(); err != nil {
log.Fatalf("Failed to execute root command: %v", err)
@ -266,7 +273,7 @@ func getOperationQRPathCommand() *cobra.Command {
return fmt.Errorf("failed to get operations: %s", operation.ErrorMessage)
}
operationQRPath := filepath.Join(qrCodeFolder, fmt.Sprintf("dc4bc_qr_%s", operationID))
operationQRPath := filepath.Join(qrCodeFolder, fmt.Sprintf("dc4bc_qr_%s-request", operationID))
qrPath := fmt.Sprintf("%s.gif", operationQRPath)
@ -325,6 +332,62 @@ func getPubKeyCommand() *cobra.Command {
}
}
func saveOffsetCommand() *cobra.Command {
return &cobra.Command{
Use: "save_offset [offset]",
Short: "saves a new offset for a storage",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
listenAddr, err := cmd.Flags().GetString(flagListenAddr)
if err != nil {
return fmt.Errorf("failed to read configuration: %v", err)
}
offset, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return fmt.Errorf("failed to parse uint: %w", err)
}
req := map[string]uint64{"offset": offset}
data, err := json.Marshal(req)
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
resp, err := rawPostRequest(fmt.Sprintf("http://%s/saveOffset", listenAddr), "application/json", data)
if err != nil {
return fmt.Errorf("failed to save offset: %w", err)
}
if resp.ErrorMessage != "" {
return fmt.Errorf("failed to save offset: %v", resp.ErrorMessage)
}
fmt.Println(resp.Result.(string))
return nil
},
}
}
func getOffsetCommand() *cobra.Command {
return &cobra.Command{
Use: "get_offset",
Short: "returns a current offset for the storage",
RunE: func(cmd *cobra.Command, args []string) error {
listenAddr, err := cmd.Flags().GetString(flagListenAddr)
if err != nil {
return fmt.Errorf("failed to read configuration: %v", err)
}
resp, err := rawGetRequest(fmt.Sprintf("http://%s//getOffset", listenAddr))
if err != nil {
return fmt.Errorf("failed to get offset: %w", err)
}
if resp.ErrorMessage != "" {
return fmt.Errorf("failed to get offset: %v", resp.ErrorMessage)
}
fmt.Println(uint64(resp.Result.(float64)))
return nil
},
}
}
func getUsernameCommand() *cobra.Command {
return &cobra.Command{
Use: "get_username",
@ -369,7 +432,7 @@ func rawPostRequest(url string, contentType string, data []byte) (*client.Respon
func readOperationFromCameraCommand() *cobra.Command {
return &cobra.Command{
Use: "read_from_camera",
Use: "read_qr",
Short: "opens the camera and reads QR codes which should contain a processed operation",
RunE: func(cmd *cobra.Command, args []string) error {
listenAddr, err := cmd.Flags().GetString(flagListenAddr)
@ -468,7 +531,7 @@ func getHashOfStartDKGCommand() *cobra.Command {
if _, err := hashPayload.Write(p.DkgPubKey); err != nil {
return err
}
if _, err := hashPayload.Write([]byte(p.Addr)); err != nil {
if _, err := hashPayload.Write([]byte(p.Username)); err != nil {
return err
}
}
@ -518,3 +581,117 @@ func proposeSignMessageCommand() *cobra.Command {
},
}
}
func getFSMDumpRequest(host string, dkgID string) (*FSMDumpResponse, error) {
resp, err := http.Get(fmt.Sprintf("http://%s/getFSMDump?dkgID=%s", host, dkgID))
if err != nil {
return nil, fmt.Errorf("failed to get FSM dump: %w", err)
}
defer resp.Body.Close()
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read body: %w", err)
}
var response FSMDumpResponse
if err = json.Unmarshal(responseBody, &response); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %v", err)
}
return &response, nil
}
func getFSMStatusCommand() *cobra.Command {
return &cobra.Command{
Use: "show_fsm_status [dkg_id]",
Args: cobra.ExactArgs(1),
Short: "shows the current status of FSM",
RunE: func(cmd *cobra.Command, args []string) error {
listenAddr, err := cmd.Flags().GetString(flagListenAddr)
if err != nil {
return fmt.Errorf("failed to read configuration: %v", err)
}
fsmDumpResponse, err := getFSMDumpRequest(listenAddr, args[0])
if err != nil {
return fmt.Errorf("failed to get FSM dump: %w", err)
}
if fsmDumpResponse.ErrorMessage != "" {
return fmt.Errorf("failed to get FSM dump: %v", fsmDumpResponse.ErrorMessage)
}
dump := fsmDumpResponse.Result
fmt.Printf("FSM current status is %s\n", dump.State)
quorum := make(map[int]state_machines.Participant)
if strings.HasPrefix(string(dump.State), "state_signing") {
for k, v := range dump.Payload.SigningProposalPayload.Quorum {
quorum[k] = v
}
}
if strings.HasPrefix(string(dump.State), "state_dkg") {
for k, v := range dump.Payload.DKGProposalPayload.Quorum {
quorum[k] = v
}
}
if strings.HasPrefix(string(dump.State), "state_sig_") {
for k, v := range dump.Payload.SignatureProposalPayload.Quorum {
quorum[k] = v
}
}
waiting := make([]string, 0)
confirmed := make([]string, 0)
failed := make([]string, 0)
for _, p := range quorum {
if strings.Contains(p.GetStatus().String(), "Await") {
waiting = append(waiting, p.GetUsername())
}
if strings.Contains(p.GetStatus().String(), "Error") {
failed = append(failed, p.GetUsername())
}
if strings.Contains(p.GetStatus().String(), "Confirmed") {
confirmed = append(confirmed, p.GetUsername())
}
}
if len(waiting) > 0 {
fmt.Printf("Waiting for a data from: %s\n", strings.Join(waiting, ", "))
}
if len(confirmed) > 0 {
fmt.Printf("Received a data from: %s\n", strings.Join(confirmed, ", "))
}
if len(failed) > 0 {
fmt.Printf("Participants who got some error during a process: %s\n", strings.Join(waiting, ", "))
}
return nil
},
}
}
func getFSMListCommand() *cobra.Command {
return &cobra.Command{
Use: "get_fsm_list",
Short: "returns a list of all FSMs served by the client",
RunE: func(cmd *cobra.Command, args []string) error {
listenAddr, err := cmd.Flags().GetString(flagListenAddr)
if err != nil {
return fmt.Errorf("failed to read configuration: %v", err)
}
resp, err := rawGetRequest(fmt.Sprintf("http://%s/getFSMList", listenAddr))
if err != nil {
return fmt.Errorf("failed to make HTTP request to get FSM list: %w", err)
}
if resp.ErrorMessage != "" {
return fmt.Errorf("failed to make HTTP request to get FSM list: %v", resp.ErrorMessage)
}
fsms := resp.Result.(map[string]interface{})
for dkgID, state := range fsms {
fmt.Printf("DKG ID: %s - FSM state: %s\n", dkgID, state.(string))
}
return nil
},
}
}

View File

@ -2,22 +2,22 @@
"SigningThreshold": 3,
"Participants": [
{
"Addr": "addr1",
"Username": "addr1",
"PubKey": "Otwt+xeI7Po3aNIcLWugnMIHxWcoTPnI3kylUkIFq80=",
"DkgPubKey": "icmEgjz+F/W6qC347pIvu317GOZA7vj4cthe/+6+GtTvh4hng0C6yx40f7RTKcNuCe+xUATI2dNEciyx7ntUaAzBOuuzRuYmOIYjBTFmt8Zms/9K1EVMhXm0zGFb5rfP"
},
{
"Addr": "addr2",
"Username": "addr2",
"PubKey": "PTX6ck8mBg+n8fRJC2MdTJGq7i9PrvfxWALgZ/B7YJo=",
"DkgPubKey": "r7GSpa+roaukv8B+ulGWKNNjquY/B5rLPvyrjD5u36nrT69p8yQtSHHM7yp59gDuA8CIrb1ph0JsaTXYCsyjVuSzChCJVMxTNPqr/vB911DTkhkO1M2HcKYkyj2fzHHL"
},
{
"Addr": "addr3",
"Username": "addr3",
"PubKey": "PTX6ck8mBg+n8fRJC2MdTJGq7i9PrvfxWALgZ/B7YJo=",
"DkgPubKey": "r7GSpa+roaukv8B+ulGWKNNjquY/B5rLPvyrjD5u36nrT69p8yQtSHHM7yp59gDuA8CIrb1ph0JsaTXYCsyjVuSzChCJVMxTNPqr/vB911DTkhkO1M2HcKYkyj2fzHHL"
},
{
"Addr": "addr4",
"Username": "addr4",
"PubKey": "PTX6ck8mBg+n8fRJC2MdTJGq7i9PrvfxWALgZ/B7YJo=",
"DkgPubKey": "r7GSpa+roaukv8B+ulGWKNNjquY/B5rLPvyrjD5u36nrT69p8yQtSHHM7yp59gDuA8CIrb1ph0JsaTXYCsyjVuSzChCJVMxTNPqr/vB911DTkhkO1M2HcKYkyj2fzHHL"
}

View File

@ -7,6 +7,7 @@ import (
"fmt"
"github.com/depools/dc4bc/client/types"
"github.com/depools/dc4bc/fsm/fsm"
"github.com/depools/dc4bc/fsm/state_machines"
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
"github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm"
"github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm"
@ -19,19 +20,24 @@ type DKGInvitationResponse responses.SignatureProposalParticipantInvitationsResp
func (d DKGInvitationResponse) Len() int { return len(d) }
func (d DKGInvitationResponse) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d DKGInvitationResponse) Less(i, j int) bool { return d[i].Addr < d[j].Addr }
func (d DKGInvitationResponse) Less(i, j int) bool { return d[i].Username < d[j].Username }
type DKGParticipants []*requests.SignatureProposalParticipantsEntry
func (d DKGParticipants) Len() int { return len(d) }
func (d DKGParticipants) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d DKGParticipants) Less(i, j int) bool { return d[i].Addr < d[j].Addr }
func (d DKGParticipants) Less(i, j int) bool { return d[i].Username < d[j].Username }
type OperationsResponse struct {
ErrorMessage string `json:"error_message,omitempty"`
Result map[string]*types.Operation `json:"result"`
}
type FSMDumpResponse struct {
ErrorMessage string `json:"error_message,omitempty"`
Result *state_machines.FSMDump `json:"result"`
}
type SignaturesResponse struct {
ErrorMessage string `json:"error_message,omitempty"`
Result map[string][]types.ReconstructedSignature `json:"result"`
@ -68,7 +74,7 @@ func calcStartDKGMessageHash(payload []byte) ([]byte, error) {
if _, err := hashPayload.Write(p.DkgPubKey); err != nil {
return nil, err
}
if _, err := hashPayload.Write([]byte(p.Addr)); err != nil {
if _, err := hashPayload.Write([]byte(p.Username)); err != nil {
return nil, err
}
}

10
cmd/dc4bc_d/config.json Normal file
View File

@ -0,0 +1,10 @@
{
"username": "node_0",
"listen_address": "localhost:8080",
"state_dbdsn": "/tmp/dc4bc_node_0_state/",
"storage_dbdsn": "94.130.57.249:9092",
"storage_topic": "test_topic",
"keystore_dbdsn": "/tmp/dc4bc_node_0_key_store",
"frames_delay": 10,
"chunk_size": 512
}

View File

@ -2,11 +2,14 @@ package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"os/signal"
"strings"
"reflect"
"syscall"
"github.com/depools/dc4bc/client"
@ -28,6 +31,7 @@ const (
flagStoreDBDSN = "key_store_dbdsn"
flagFramesDelay = "frames_delay"
flagChunkSize = "chunk_size"
flagConfigPath = "config_path"
)
func init() {
@ -42,31 +46,143 @@ func init() {
rootCmd.PersistentFlags().String(flagStoreDBDSN, "./dc4bc_key_store", "Key Store DBDSN")
rootCmd.PersistentFlags().Int(flagFramesDelay, 10, "Delay times between frames in 100ths of a second")
rootCmd.PersistentFlags().Int(flagChunkSize, 256, "QR-code's chunk size")
rootCmd.PersistentFlags().String(flagConfigPath, "", "Path to a config file")
}
type config struct {
Username string `json:"username"`
ListenAddress string `json:"listen_address"`
StateDBDSN string `json:"state_dbdsn"`
StorageDBDSN string `json:"storage_dbdsn"`
StorageTopic string `json:"storage_topic"`
KeyStoreDBDSN string `json:"keystore_dbdsn"`
FramesDelay int `json:"frames_delay"`
ChunkSize int `json:"chunk_size"`
ProducerCredentials string `json:"producer_credentials"`
ConsumerCredentials string `json:"consumer_credentials"`
KafkaTrustStorePath string `json:"kafka_trust_store_path"`
}
func readConfig(path string) (config, error) {
var cfg config
configBz, err := ioutil.ReadFile(path)
if err != nil {
return cfg, fmt.Errorf("failed to read config file: %w", err)
}
if err = json.Unmarshal(configBz, &cfg); err != nil {
return cfg, fmt.Errorf("failed to unmarshal config: %w", err)
}
return cfg, nil
}
func checkConfig(cfg *config) error {
v := reflect.ValueOf(cfg)
v = v.Elem()
t := reflect.TypeOf(*cfg)
for i := 0; i < v.NumField(); i++ {
if v.Field(i).IsZero() {
return fmt.Errorf("%s cannot be empty", t.Field(i).Tag.Get("json"))
}
}
if cfg.FramesDelay < 0 {
return fmt.Errorf("frames_delay cannot be less than zero")
}
if cfg.ChunkSize < 0 {
return fmt.Errorf("chunk_size cannot be less than zero")
}
return nil
}
func loadConfig(cmd *cobra.Command) (*config, error) {
var cfg config
cfgPath, err := cmd.Flags().GetString(flagConfigPath)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
if cfgPath != "" {
cfg, err = readConfig(cfgPath)
if err != nil {
return nil, err
}
} else {
cfg.Username, err = cmd.Flags().GetString(flagUserName)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.KeyStoreDBDSN, err = cmd.Flags().GetString(flagStoreDBDSN)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.ListenAddress, err = cmd.Flags().GetString(flagListenAddr)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.StateDBDSN, err = cmd.Flags().GetString(flagStateDBDSN)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.FramesDelay, err = cmd.Flags().GetInt(flagFramesDelay)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.ChunkSize, err = cmd.Flags().GetInt(flagChunkSize)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.StorageDBDSN, err = cmd.Flags().GetString(flagStorageDBDSN)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.StorageTopic, err = cmd.Flags().GetString(flagStorageTopic)
if err != nil {
return nil, fmt.Errorf("failed to read configuration: %v", err)
}
cfg.KafkaTrustStorePath, err = cmd.Flags().GetString(flagKafkaTrustStorePath)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
cfg.ProducerCredentials, err = cmd.Flags().GetString(flagKafkaProducerCredentials)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
cfg.ConsumerCredentials, err = cmd.Flags().GetString(flagKafkaConsumerCredentials)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
}
if err = checkConfig(&cfg); err != nil {
return nil, err
}
return &cfg, nil
}
func genKeyPairCommand() *cobra.Command {
return &cobra.Command{
Use: "gen_keys",
Short: "generates a keypair to sign and verify messages",
RunE: func(cmd *cobra.Command, args []string) error {
userName, err := cmd.Flags().GetString(flagUserName)
Run: func(cmd *cobra.Command, args []string) {
cfg, err := loadConfig(cmd)
if err != nil {
return fmt.Errorf("failed to read configuration: %v", err)
}
keyStoreDBDSN, err := cmd.Flags().GetString(flagStoreDBDSN)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
log.Fatalf("failed to load config: %v", err)
}
keyPair := client.NewKeyPair()
keyStore, err := client.NewLevelDBKeyStore(userName, keyStoreDBDSN)
keyStore, err := client.NewLevelDBKeyStore(cfg.Username, cfg.KeyStoreDBDSN)
if err != nil {
return fmt.Errorf("failed to init key store: %w", err)
log.Fatalf("failed to init key store: %v", err)
}
if err = keyStore.PutKeys(userName, keyPair); err != nil {
return fmt.Errorf("failed to save keypair: %w", err)
if err = keyStore.PutKeys(cfg.Username, keyPair); err != nil {
log.Fatalf("failed to save keypair: %v", err)
}
fmt.Printf("keypair generated for user %s and saved to %s\n", userName, keyStoreDBDSN)
return nil
fmt.Printf("keypair generated for user %s and saved to %s\n", cfg.Username, cfg.KeyStoreDBDSN)
},
}
}
@ -87,94 +203,47 @@ func startClientCommand() *cobra.Command {
Use: "start",
Short: "starts dc4bc client",
Run: func(cmd *cobra.Command, args []string) {
userName, err := cmd.Flags().GetString(flagUserName)
cfg, err := loadConfig(cmd)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
listenAddr, err := cmd.Flags().GetString(flagListenAddr)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
stateDBDSN, err := cmd.Flags().GetString(flagStateDBDSN)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
framesDelay, err := cmd.Flags().GetInt(flagFramesDelay)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
chunkSize, err := cmd.Flags().GetInt(flagChunkSize)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
storageDBDSN, err := cmd.Flags().GetString(flagStorageDBDSN)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
storageTopic, err := cmd.Flags().GetString(flagStorageTopic)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
keyStoreDBDSN, err := cmd.Flags().GetString(flagStoreDBDSN)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
log.Fatalf("failed to load config: %v", err)
}
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
state, err := client.NewLevelDBState(stateDBDSN)
state, err := client.NewLevelDBState(cfg.StateDBDSN)
if err != nil {
log.Fatalf("Failed to init state client: %v", err)
}
kafkaTrustStorePath, err := cmd.Flags().GetString(flagKafkaTrustStorePath)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
tlsConfig, err := storage.GetTLSConfig(kafkaTrustStorePath)
tlsConfig, err := storage.GetTLSConfig(cfg.KafkaTrustStorePath)
if err != nil {
log.Fatalf("faile to create tls config: %v", err)
}
producerCredentialsString, err := cmd.Flags().GetString(flagKafkaProducerCredentials)
producerCreds, err := parseKafkaAuthCredentials(cfg.ProducerCredentials)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
log.Fatal(err.Error())
}
producerCreds, err := parseKafkaAuthCredentials(producerCredentialsString)
consumerCreds, err := parseKafkaAuthCredentials(cfg.ProducerCredentials)
if err != nil {
log.Fatal(err.Error())
}
consumerCredentialsString, err := cmd.Flags().GetString(flagKafkaConsumerCredentials)
if err != nil {
log.Fatalf("failed to read configuration: %v", err)
}
consumerCreds, err := parseKafkaAuthCredentials(consumerCredentialsString)
if err != nil {
log.Fatal(err.Error())
}
stg, err := storage.NewKafkaStorage(ctx, storageDBDSN, storageTopic, tlsConfig, producerCreds, consumerCreds)
stg, err := storage.NewKafkaStorage(ctx, cfg.StorageDBDSN, cfg.StorageTopic, tlsConfig, producerCreds, consumerCreds)
if err != nil {
log.Fatalf("Failed to init storage client: %v", err)
}
keyStore, err := client.NewLevelDBKeyStore(userName, keyStoreDBDSN)
keyStore, err := client.NewLevelDBKeyStore(cfg.Username, cfg.KeyStoreDBDSN)
if err != nil {
log.Fatalf("Failed to init key store: %v", err)
}
processor := qr.NewCameraProcessor()
processor.SetDelay(framesDelay)
processor.SetChunkSize(chunkSize)
processor.SetDelay(cfg.FramesDelay)
processor.SetChunkSize(cfg.ChunkSize)
cli, err := client.NewClient(ctx, userName, state, stg, keyStore, processor)
cli, err := client.NewClient(ctx, cfg.Username, state, stg, keyStore, processor)
if err != nil {
log.Fatalf("Failed to init client: %v", err)
}
@ -192,7 +261,7 @@ func startClientCommand() *cobra.Command {
}()
go func() {
if err := cli.StartHTTPServer(listenAddr); err != nil {
if err := cli.StartHTTPServer(cfg.ListenAddress); err != nil {
log.Fatalf("HTTP server error: %v", err)
}
}()

View File

@ -0,0 +1,96 @@
package main
import (
"encoding/base64"
"fmt"
prysmBLS "github.com/prysmaticlabs/prysm/shared/bls"
"github.com/spf13/cobra"
"io/ioutil"
"log"
)
func checkSignature() *cobra.Command {
return &cobra.Command{
Use: "check_signature [signature]",
Short: "checks a signature on prysm compatibility",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
sig, err := base64.StdEncoding.DecodeString(args[0])
if err != nil {
log.Fatalf("failed to decode signature bytes from string: %v", err)
}
if _, err = prysmBLS.SignatureFromBytes(sig); err != nil {
log.Fatalf("failed to get prysm sig from bytes: %v", err)
}
fmt.Println("Signature is correct")
},
}
}
func checkPubKey() *cobra.Command {
return &cobra.Command{
Use: "check_pubkey [pubkey]",
Short: "checks a pubkey on prysm compatibility",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
pubkey, err := base64.StdEncoding.DecodeString(args[0])
if err != nil {
log.Fatalf("failed to decode pubkey bytes from string: %v", err)
}
if _, err = prysmBLS.PublicKeyFromBytes(pubkey); err != nil {
log.Fatalf("failed to get prysm pubkey from bytes: %v", err)
}
fmt.Println("Public key is correct")
},
}
}
func verify() *cobra.Command {
return &cobra.Command{
Use: "verify [signature] [pubkey] [file]",
Short: "verify signature with Prysm",
Args: cobra.ExactArgs(3),
Run: func(cmd *cobra.Command, args []string) {
sig, err := base64.StdEncoding.DecodeString(args[0])
if err != nil {
log.Fatalf("failed to decode signature bytes from string: %v", err)
}
prysmSig, err := prysmBLS.SignatureFromBytes(sig)
if err != nil {
log.Fatalf("failed to get prysm sig from bytes: %v", err)
}
pubkey, err := base64.StdEncoding.DecodeString(args[1])
if err != nil {
log.Fatalf("failed to decode pubkey bytes from string: %v", err)
}
prysmPubKey, err := prysmBLS.PublicKeyFromBytes(pubkey)
if err != nil {
log.Fatalf("failed to get prysm pubkey from bytes: %v", err)
}
msg, err := ioutil.ReadFile(args[2])
if err != nil {
log.Fatalf("failed to read file: %v", err)
}
if !prysmSig.Verify(prysmPubKey, msg) {
log.Fatalf("failed to verify prysm signature")
}
fmt.Println("Signature is correct")
},
}
}
var rootCmd = &cobra.Command{
Use: "./prysmCompatibilityChecker",
Short: "util to check signatures and pubkeys compatibility with Prysm",
}
func main() {
rootCmd.AddCommand(
checkPubKey(),
checkSignature(),
verify(),
)
if err := rootCmd.Execute(); err != nil {
log.Fatalf("Failed to execute root command: %v", err)
}
}

View File

@ -42,7 +42,7 @@ func (m *DKGProposalFSM) actionInitDKGProposal(inEvent fsm.Event, args ...interf
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
m.payload.DKGProposalPayload.Quorum[participantId] = &internal.DKGProposalParticipant{
Addr: participant.Addr,
Username: participant.Username,
DkgPubKey: make([]byte, len(participant.DkgPubKey)),
Status: internal.CommitAwaitConfirmation,
UpdatedAt: participant.UpdatedAt,
@ -59,7 +59,7 @@ func (m *DKGProposalFSM) actionInitDKGProposal(inEvent fsm.Event, args ...interf
for participantId, participant := range m.payload.DKGProposalPayload.Quorum {
responseEntry := &responses.DKGProposalPubKeysParticipantEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
DkgPubKey: participant.DkgPubKey,
}
responseData = append(responseData, responseEntry)
@ -158,7 +158,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event
for participantId, participant := range m.payload.DKGProposalPayload.Quorum {
responseEntry := &responses.DKGProposalCommitParticipantEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
DkgCommit: participant.DkgCommit,
}
responseData = append(responseData, responseEntry)
@ -263,7 +263,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event,
}
responseEntry := &responses.DKGProposalDealParticipantEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
DkgDeal: participant.DkgDeal,
}
responseData = append(responseData, responseEntry)
@ -365,7 +365,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Eve
for participantId, participant := range m.payload.DKGProposalPayload.Quorum {
responseEntry := &responses.DKGProposalResponseParticipantEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
DkgResponse: participant.DkgResponse,
}
responseData = append(responseData, responseEntry)

View File

@ -117,45 +117,45 @@ func (p *DumpedMachineStatePayload) SigningQuorumUpdate(id int, participant *Sig
}
}
func (p *DumpedMachineStatePayload) SetPubKeyAddr(addr string, pubKey ed25519.PublicKey) {
func (p *DumpedMachineStatePayload) SetPubKeyUsername(username string, pubKey ed25519.PublicKey) {
if p.PubKeys == nil {
p.PubKeys = make(map[string]ed25519.PublicKey)
}
p.PubKeys[addr] = pubKey
p.PubKeys[username] = pubKey
}
func (p *DumpedMachineStatePayload) SetIDAddr(addr string, id int) {
func (p *DumpedMachineStatePayload) SetIDUsername(username string, id int) {
if p.IDs == nil {
p.IDs = make(map[string]int)
}
p.IDs[addr] = id
p.IDs[username] = id
}
func (p *DumpedMachineStatePayload) GetPubKeyByAddr(addr string) (ed25519.PublicKey, error) {
func (p *DumpedMachineStatePayload) GetPubKeyByUsername(username string) (ed25519.PublicKey, error) {
if p.PubKeys == nil {
return nil, errors.New("{PubKeys} not initialized")
}
if addr == "" {
return nil, errors.New("{addr} cannot be empty")
if username == "" {
return nil, errors.New("{username} cannot be empty")
}
pubKey, ok := p.PubKeys[addr]
pubKey, ok := p.PubKeys[username]
if !ok {
return nil, errors.New("cannot find public key by {addr}")
return nil, errors.New("cannot find public key by {username}")
}
return pubKey, nil
}
func (p *DumpedMachineStatePayload) GetIDByAddr(addr string) (int, error) {
func (p *DumpedMachineStatePayload) GetIDByUsername(username string) (int, error) {
if p.IDs == nil {
return -1, errors.New("{IDs} not initialized")
}
if addr == "" {
return -1, errors.New("{addr} cannot be empty")
if username == "" {
return -1, errors.New("{username} cannot be empty")
}
id, ok := p.IDs[addr]
id, ok := p.IDs[username]
if !ok {
return -1, errors.New("cannot find id by {addr}")
return -1, errors.New("cannot find id by {username}")
}
return id, nil
}

View File

@ -5,6 +5,10 @@ import (
"time"
)
type ParticipantStatus interface {
String() string
}
type ConfirmationParticipantStatus uint8
const (
@ -37,7 +41,7 @@ type SignatureConfirmation struct {
}
type SignatureProposalParticipant struct {
Addr string
Username string
PubKey ed25519.PublicKey
DkgPubKey []byte
// For validation user confirmation: sign(InvitationSecret, PubKey) => user
@ -47,6 +51,14 @@ type SignatureProposalParticipant struct {
UpdatedAt time.Time
}
func (sigP SignatureProposalParticipant) GetStatus() ParticipantStatus {
return sigP.Status
}
func (sigP SignatureProposalParticipant) GetUsername() string {
return sigP.Username
}
func (c *SignatureConfirmation) IsExpired() bool {
return c.ExpiresAt.Before(c.UpdatedAt)
}
@ -75,7 +87,7 @@ const (
)
type DKGProposalParticipant struct {
Addr string
Username string
DkgPubKey []byte
DkgCommit []byte
DkgDeal []byte
@ -86,6 +98,14 @@ type DKGProposalParticipant struct {
UpdatedAt time.Time
}
func (dkgP DKGProposalParticipant) GetStatus() ParticipantStatus {
return dkgP.Status
}
func (dkgP DKGProposalParticipant) GetUsername() string {
return dkgP.Username
}
type DKGProposalQuorum map[int]*DKGProposalParticipant
type DKGConfirmation struct {
@ -184,9 +204,17 @@ func (s SigningParticipantStatus) String() string {
}
type SigningProposalParticipant struct {
Addr string
Username string
Status SigningParticipantStatus
PartialSign []byte
Error error
UpdatedAt time.Time
}
func (signingP SigningProposalParticipant) GetStatus() ParticipantStatus {
return signingP.Status
}
func (signingP SigningProposalParticipant) GetUsername() string {
return signingP.Username
}

View File

@ -27,6 +27,11 @@ type FSMInstance struct {
dump *FSMDump
}
type Participant interface {
GetStatus() internal.ParticipantStatus
GetUsername() string
}
// Create new fsm with unique id
// transactionId required for unique identify dump
func Create(dkgID string) (*FSMInstance, error) {
@ -86,12 +91,12 @@ func FromDump(data []byte) (*FSMInstance, error) {
return i, err
}
func (i *FSMInstance) GetPubKeyByAddr(addr string) (ed25519.PublicKey, error) {
func (i *FSMInstance) GetPubKeyByUsername(username string) (ed25519.PublicKey, error) {
if i.dump == nil {
return nil, errors.New("dump not initialized")
}
return i.dump.Payload.GetPubKeyByAddr(addr)
return i.dump.Payload.GetPubKeyByUsername(username)
}
func (i *FSMInstance) SigningQuorumGetParticipant(id int) (*internal.SigningProposalParticipant, error) {
@ -102,12 +107,12 @@ func (i *FSMInstance) SigningQuorumGetParticipant(id int) (*internal.SigningProp
return i.dump.Payload.SigningQuorumGet(id), nil
}
func (i *FSMInstance) GetIDByAddr(addr string) (int, error) {
func (i *FSMInstance) GetIDByUsername(username string) (int, error) {
if i.dump == nil {
return -1, errors.New("dump not initialized")
}
return i.dump.Payload.GetIDByAddr(addr)
return i.dump.Payload.GetIDByUsername(username)
}
func (i *FSMInstance) Do(event fsm.Event, args ...interface{}) (result *fsm.Response, dump []byte, err error) {
@ -176,6 +181,10 @@ func (i *FSMInstance) Dump() ([]byte, error) {
return i.dump.Marshal()
}
func (i *FSMInstance) FSMDump() *FSMDump {
return i.dump
}
// TODO: Add encryption
func (d *FSMDump) Marshal() ([]byte, error) {
return json.Marshal(d)

View File

@ -21,12 +21,12 @@ import (
)
const (
addrMockLen = 32
keysMockLen = 128
usernameMockLen = 32
keysMockLen = 128
)
type testParticipantsPayload struct {
Addr string
Username string
HotPrivKey ed25519.PrivateKey
HotPubKey ed25519.PublicKey
DkgPubKey []byte
@ -41,8 +41,8 @@ var (
dkgId = "1b7a6382afe0fbe2ff127a5779f5e9b042e685cabefeadcf4ef27c6089a56bfb"
// map {addr} -> {participant}
testAddrMapParticipants = map[string]*testParticipantsPayload{}
// map {username} -> {participant}
testUsernameMapParticipants = map[string]*testParticipantsPayload{}
// map {dkg_queue_id} -> {participant}
testIdMapParticipants = map[int]*testParticipantsPayload{}
@ -62,7 +62,7 @@ func init() {
for i := 0; i < 3; i++ {
participant := &testParticipantsPayload{
Addr: base64.StdEncoding.EncodeToString(genDataMock(addrMockLen)),
Username: base64.StdEncoding.EncodeToString(genDataMock(usernameMockLen)),
HotPrivKey: genDataMock(keysMockLen),
HotPubKey: genDataMock(keysMockLen),
DkgPubKey: genDataMock(keysMockLen),
@ -71,7 +71,7 @@ func init() {
DkgResponse: genDataMock(keysMockLen),
DkgPartialKey: genDataMock(keysMockLen),
}
testAddrMapParticipants[participant.Addr] = participant
testUsernameMapParticipants[participant.Username] = participant
}
}
@ -162,10 +162,10 @@ func Test_SignatureProposal_EventInitProposal_Positive(t *testing.T) {
// Make request
request := make([]*requests.SignatureProposalParticipantsEntry, 0)
for _, participant := range testAddrMapParticipants {
for _, participant := range testUsernameMapParticipants {
request = append(request, &requests.SignatureProposalParticipantsEntry{
Addr: participant.Addr,
Username: participant.Username,
PubKey: participant.HotPubKey,
DkgPubKey: participant.DkgPubKey,
})
@ -196,14 +196,14 @@ func Test_SignatureProposal_EventInitProposal_Positive(t *testing.T) {
t.Fatalf("expected unique {ParticipantId}")
}
if participant.Addr == "" {
t.Fatalf("expected not empty {Addr}")
if participant.Username == "" {
t.Fatalf("expected not empty {Username}")
}
participantEntry, ok := testAddrMapParticipants[participant.Addr]
participantEntry, ok := testUsernameMapParticipants[participant.Username]
if !ok {
t.Fatalf("expected exist {Addr}")
t.Fatalf("expected exist {Username}")
}
testIdMapParticipants[participant.ParticipantId] = participantEntry
@ -409,8 +409,8 @@ func Test_DkgProposal_EventDKGCommitConfirmationReceived(t *testing.T) {
t.Fatalf("expected exist {ParticipantId}")
}
if responseEntry.Addr == "" {
t.Fatalf("expected {Addr} non zero length")
if responseEntry.Username == "" {
t.Fatalf("expected {Username} non zero length")
}
if len(responseEntry.DkgCommit) == 0 {
@ -534,8 +534,8 @@ func Test_DkgProposal_EventDKGDealConfirmationReceived(t *testing.T) {
t.Fatalf("expected exist {ParticipantId}")
}
if responseEntry.Addr == "" {
t.Fatalf("expected {Addr} non zero length")
if responseEntry.Username == "" {
t.Fatalf("expected {Username} non zero length")
}
if len(responseEntry.DkgDeal) == 0 {
@ -653,8 +653,8 @@ func Test_DkgProposal_EventDKGResponseConfirmationReceived_Positive(t *testing.T
t.Fatalf("expected exist {ParticipantId}")
}
if responseEntry.Addr == "" {
t.Fatalf("expected {Addr} non zero length")
if responseEntry.Username == "" {
t.Fatalf("expected {Username} non zero length")
}
if len(responseEntry.DkgResponse) == 0 {

View File

@ -40,9 +40,8 @@ func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, ar
}
for index, participant := range request.Participants {
//participantId := createFingerprint(&participant.DkgPubKey)
m.payload.SignatureProposalPayload.Quorum[index] = &internal.SignatureProposalParticipant{
Addr: participant.Addr,
Username: participant.Username,
PubKey: participant.PubKey,
DkgPubKey: participant.DkgPubKey,
Status: internal.SigConfirmationAwaitConfirmation,
@ -50,8 +49,8 @@ func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, ar
UpdatedAt: request.CreatedAt,
}
m.payload.SetPubKeyAddr(participant.Addr, participant.PubKey)
m.payload.SetIDAddr(participant.Addr, index)
m.payload.SetPubKeyUsername(participant.Username, participant.PubKey)
m.payload.SetIDUsername(participant.Username, index)
}
// Checking fo quorum length
@ -67,7 +66,7 @@ func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, ar
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
responseEntry := &responses.SignatureProposalParticipantInvitationEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
Threshold: participant.Threshold,
DkgPubKey: participant.DkgPubKey,
PubKey: participant.PubKey,
@ -171,7 +170,7 @@ func (m *SignatureProposalFSM) actionValidateSignatureProposal(fsm.Event, ...int
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
responseEntry := &responses.SignatureProposalParticipantStatusEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
Status: uint8(participant.Status),
}
responseData = append(responseData, responseEntry)

View File

@ -75,7 +75,7 @@ func (m *SigningProposalFSM) actionStartSigningProposal(inEvent fsm.Event, args
// Initialize new quorum
for id, dkgEntry := range m.payload.DKGProposalPayload.Quorum {
m.payload.SigningProposalPayload.Quorum[id] = &internal.SigningProposalParticipant{
Addr: dkgEntry.Addr,
Username: dkgEntry.Username,
Status: internal.SigningAwaitConfirmation,
UpdatedAt: request.CreatedAt,
}
@ -95,7 +95,7 @@ func (m *SigningProposalFSM) actionStartSigningProposal(inEvent fsm.Event, args
for participantId, participant := range m.payload.SigningProposalPayload.Quorum {
responseEntry := &responses.SigningProposalParticipantInvitationEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
Status: uint8(participant.Status),
}
responseData.Participants = append(responseData.Participants, responseEntry)
@ -296,7 +296,7 @@ func (m *SigningProposalFSM) actionValidateSigningPartialSignsAwaitConfirmations
for participantId, participant := range m.payload.SigningProposalPayload.Quorum {
responseEntry := &responses.SigningProcessParticipantEntry{
ParticipantId: participantId,
Addr: participant.Addr,
Username: participant.Username,
PartialSign: participant.PartialSign,
}
responseData.Participants = append(responseData.Participants, responseEntry)

View File

@ -13,7 +13,7 @@ type SignatureProposalParticipantsListRequest struct {
}
type SignatureProposalParticipantsEntry struct {
Addr string
Username string
PubKey []byte
DkgPubKey []byte
}

View File

@ -20,21 +20,21 @@ func (r *SignatureProposalParticipantsListRequest) Validate() error {
return errors.New("{SigningThreshold} cannot be higher than {ParticipantsCount}")
}
uniqueAddresses := make(map[string]bool)
uniqueUsernames := make(map[string]bool)
for _, participant := range r.Participants {
if _, ok := uniqueAddresses[participant.Addr]; ok {
return errors.New("{Addr} must be unique")
if _, ok := uniqueUsernames[participant.Username]; ok {
return errors.New("{Username} must be unique")
}
uniqueAddresses[participant.Addr] = true
uniqueUsernames[participant.Username] = true
}
for _, participant := range r.Participants {
if len(participant.Addr) < 3 {
return errors.New("{Addr} minimum length is {3}")
if len(participant.Username) < 3 {
return errors.New("{Username} minimum length is {3}")
}
if len(participant.Addr) > 150 {
return errors.New("{Addr} maximum length is {150}")
if len(participant.Username) > 150 {
return errors.New("{Username} maximum length is {150}")
}
if len(participant.PubKey) < 10 {

View File

@ -4,7 +4,7 @@ type DKGProposalPubKeysParticipantResponse []*DKGProposalPubKeysParticipantEntry
type DKGProposalPubKeysParticipantEntry struct {
ParticipantId int
Addr string
Username string
DkgPubKey []byte
}
@ -12,7 +12,7 @@ type DKGProposalCommitParticipantResponse []*DKGProposalCommitParticipantEntry
type DKGProposalCommitParticipantEntry struct {
ParticipantId int
Addr string
Username string
DkgCommit []byte
}
@ -20,7 +20,7 @@ type DKGProposalDealParticipantResponse []*DKGProposalDealParticipantEntry
type DKGProposalDealParticipantEntry struct {
ParticipantId int
Addr string
Username string
DkgDeal []byte
}
@ -28,6 +28,6 @@ type DKGProposalResponseParticipantResponse []*DKGProposalResponseParticipantEnt
type DKGProposalResponseParticipantEntry struct {
ParticipantId int
Addr string
Username string
DkgResponse []byte
}

View File

@ -8,11 +8,10 @@ type SignatureProposalParticipantInvitationsResponse []*SignatureProposalPartici
type SignatureProposalParticipantInvitationEntry struct {
ParticipantId int
// Public title for address, such as name, nickname, organization
Addr string
Threshold int
DkgPubKey []byte
PubKey []byte
Username string
Threshold int
DkgPubKey []byte
PubKey []byte
}
// Public lists for proposal confirmation process
@ -21,7 +20,7 @@ type SignatureProposalParticipantStatusResponse []*SignatureProposalParticipantS
type SignatureProposalParticipantStatusEntry struct {
ParticipantId int
Addr string
Username string
Status uint8
DkgPubKey []byte
}

View File

@ -12,7 +12,7 @@ type SigningProposalParticipantInvitationsResponse struct {
type SigningProposalParticipantInvitationEntry struct {
ParticipantId int
Addr string
Username string
Status uint8
}
@ -33,7 +33,7 @@ type SigningProposalParticipantStatusResponse struct {
type SigningProposalParticipantStatusEntry struct {
ParticipantId int
Addr string
Username string
Status uint8
}
@ -47,6 +47,6 @@ type SigningProcessParticipantResponse struct {
type SigningProcessParticipantEntry struct {
ParticipantId int
Addr string
Username string
PartialSign []byte
}

996
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -93,6 +93,21 @@ func (mr *MockStateMockRecorder) LoadFSM(dkgRoundID interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LoadFSM", reflect.TypeOf((*MockState)(nil).LoadFSM), dkgRoundID)
}
// GetAllFSM mocks base method
func (m *MockState) GetAllFSM() (map[string]*state_machines.FSMInstance, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAllFSM")
ret0, _ := ret[0].(map[string]*state_machines.FSMInstance)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetAllFSM indicates an expected call of GetAllFSM
func (mr *MockStateMockRecorder) GetAllFSM() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllFSM", reflect.TypeOf((*MockState)(nil).GetAllFSM))
}
// PutOperation mocks base method
func (m *MockState) PutOperation(operation *types.Operation) error {
m.ctrl.T.Helper()