mirror of https://github.com/certusone/dc4bc.git
Merge branch 'master' into feat/kafka-auth-tls
This commit is contained in:
commit
461f5d48ee
19
HowTo.md
19
HowTo.md
|
@ -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!
|
||||
```
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -13,7 +13,7 @@ type SignatureProposalParticipantsListRequest struct {
|
|||
}
|
||||
|
||||
type SignatureProposalParticipantsEntry struct {
|
||||
Addr string
|
||||
Username string
|
||||
PubKey []byte
|
||||
DkgPubKey []byte
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue