Merge branch 'master' into fix/airgapped-camera-lock

This commit is contained in:
programmer10110 2020-11-03 18:41:45 +03:00
commit b3cec9b3be
24 changed files with 311 additions and 140 deletions

View File

@ -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 $ ./dc4bc_cli get_pubkey --listen_addr localhost:8080
EcVs+nTi4iFERVeBHUPePDmvknBx95co7csKj0sZNuo= EcVs+nTi4iFERVeBHUPePDmvknBx95co7csKj0sZNuo=
# Inside the airgapped shell: # Inside the airgapped shell:
>>> show_dkg_pub_key >>> show_dkg_pubkey
sN7XbnvZCRtg650dVCCpPK/hQ/rMTSlxrdnvzJ75zV4W/Uzk9suvjNPtyRt7PDXLDTGNimn+4X/FcJj2K6vDdgqOrr9BHwMqJXnQykcv3IV0ggIUjpMMgdbQ+0iSseyq sN7XbnvZCRtg650dVCCpPK/hQ/rMTSlxrdnvzJ75zV4W/Uzk9suvjNPtyRt7PDXLDTGNimn+4X/FcJj2K6vDdgqOrr9BHwMqJXnQykcv3IV0ggIUjpMMgdbQ+0iSseyq
``` ```
@ -106,12 +106,12 @@ Example of start_dkg_propose.json file structure:
"SigningThreshold": 2, "SigningThreshold": 2,
"Participants": [ "Participants": [
{ {
"Addr": "e0d8083f8a2d18f310bfbdc9649a83664470f46053ab53c105a054b08f9eff85", "Username": "john_doe",
"PubKey": "EcVs+nTi4iFERVeBHUPePDmvknBx95co7csKj0sZNuo=", "PubKey": "EcVs+nTi4iFERVeBHUPePDmvknBx95co7csKj0sZNuo=",
"DkgPubKey": "sN7XbnvZCRtg650dVCCpPK/hQ/rMTSlxrdnvzJ75zV4W/Uzk9suvjNPtyRt7PDXLDTGNimn+4X/FcJj2K6vDdgqOrr9BHwMqJXnQykcv3IV0ggIUjpMMgdbQ+0iSseyq" "DkgPubKey": "sN7XbnvZCRtg650dVCCpPK/hQ/rMTSlxrdnvzJ75zV4W/Uzk9suvjNPtyRt7PDXLDTGNimn+4X/FcJj2K6vDdgqOrr9BHwMqJXnQykcv3IV0ggIUjpMMgdbQ+0iSseyq"
}, },
{ {
"Addr": "addr2", "Username": "jane_doe",
"PubKey": "cHVia2V5Mg==", "PubKey": "cHVia2V5Mg==",
"DkgPubKey": "ZGtnX3B1YmtleV8y" "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 to poll messages from append-only log...
[john_doe] Starting HTTP server on address: localhost:8080 [john_doe] Starting HTTP server on address: localhost:8080
[john_doe] Handling message with offset 0, type event_sig_proposal_init [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 [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: 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: 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: # Inside dc4bc_airgapped prompt:
$ >>> show_finished_dkg $ >>> show_finished_dkg
AABB10CABB10 AABB10CABB10
$ echo "the message to sign" | base64 $ echo "the message to sign" > data.txt
dGhlIG1lc3NhZ2UgdG8gc2lnbgo= $ ./dc4bc_cli sign_data AABB10CABB10 data.txt --listen_addr localhost:8080
$ ./dc4bc_cli sign_data AABB10CABB10 dGhlIG1lc3NhZ2UgdG8gc2lnbgo= --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: 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:
``` ```

View File

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

View File

@ -147,7 +147,7 @@ func TestAirgappedAllSteps(t *testing.T) {
} }
entry := &responses.SignatureProposalParticipantInvitationEntry{ entry := &responses.SignatureProposalParticipantInvitationEntry{
ParticipantId: n.ParticipantID, ParticipantId: n.ParticipantID,
Addr: n.Participant, Username: n.Participant,
Threshold: threshold, Threshold: threshold,
DkgPubKey: pubKey, DkgPubKey: pubKey,
} }
@ -172,7 +172,7 @@ func TestAirgappedAllSteps(t *testing.T) {
} }
entry := &responses.DKGProposalPubKeysParticipantEntry{ entry := &responses.DKGProposalPubKeysParticipantEntry{
ParticipantId: n.ParticipantID, ParticipantId: n.ParticipantID,
Addr: n.Participant, Username: n.Participant,
DkgPubKey: pubKey, DkgPubKey: pubKey,
} }
getCommitsRequest = append(getCommitsRequest, entry) getCommitsRequest = append(getCommitsRequest, entry)
@ -198,7 +198,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.commits { for _, req := range n.commits {
p := responses.DKGProposalCommitParticipantEntry{ p := responses.DKGProposalCommitParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgCommit: req.Commit, DkgCommit: req.Commit,
} }
payload = append(payload, &p) payload = append(payload, &p)
@ -222,7 +222,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.deals { for _, req := range n.deals {
p := responses.DKGProposalDealParticipantEntry{ p := responses.DKGProposalDealParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgDeal: req.Deal, DkgDeal: req.Deal,
} }
payload = append(payload, &p) payload = append(payload, &p)
@ -246,7 +246,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.responses { for _, req := range n.responses {
p := responses.DKGProposalResponseParticipantEntry{ p := responses.DKGProposalResponseParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgResponse: req.Response, DkgResponse: req.Response,
} }
payload = append(payload, &p) payload = append(payload, &p)
@ -300,7 +300,7 @@ func TestAirgappedAllSteps(t *testing.T) {
for _, req := range n.partialSigns { for _, req := range n.partialSigns {
p := responses.SigningProcessParticipantEntry{ p := responses.SigningProcessParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
PartialSign: req.PartialSign, PartialSign: req.PartialSign,
} }
payload.Participants = append(payload.Participants, &p) payload.Participants = append(payload.Participants, &p)
@ -371,7 +371,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
} }
entry := &responses.SignatureProposalParticipantInvitationEntry{ entry := &responses.SignatureProposalParticipantInvitationEntry{
ParticipantId: n.ParticipantID, ParticipantId: n.ParticipantID,
Addr: n.Participant, Username: n.Participant,
Threshold: threshold, Threshold: threshold,
DkgPubKey: pubKey, DkgPubKey: pubKey,
} }
@ -396,7 +396,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
} }
entry := &responses.DKGProposalPubKeysParticipantEntry{ entry := &responses.DKGProposalPubKeysParticipantEntry{
ParticipantId: n.ParticipantID, ParticipantId: n.ParticipantID,
Addr: n.Participant, Username: n.Participant,
DkgPubKey: pubKey, DkgPubKey: pubKey,
} }
getCommitsRequest = append(getCommitsRequest, entry) getCommitsRequest = append(getCommitsRequest, entry)
@ -422,7 +422,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.commits { for _, req := range n.commits {
p := responses.DKGProposalCommitParticipantEntry{ p := responses.DKGProposalCommitParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgCommit: req.Commit, DkgCommit: req.Commit,
} }
payload = append(payload, &p) payload = append(payload, &p)
@ -484,7 +484,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.deals { for _, req := range n.deals {
p := responses.DKGProposalDealParticipantEntry{ p := responses.DKGProposalDealParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgDeal: req.Deal, DkgDeal: req.Deal,
} }
payload = append(payload, &p) payload = append(payload, &p)
@ -508,7 +508,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.responses { for _, req := range n.responses {
p := responses.DKGProposalResponseParticipantEntry{ p := responses.DKGProposalResponseParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
DkgResponse: req.Response, DkgResponse: req.Response,
} }
payload = append(payload, &p) payload = append(payload, &p)
@ -562,7 +562,7 @@ func TestAirgappedMachine_Replay(t *testing.T) {
for _, req := range n.partialSigns { for _, req := range n.partialSigns {
p := responses.SigningProcessParticipantEntry{ p := responses.SigningProcessParticipantEntry{
ParticipantId: req.ParticipantId, ParticipantId: req.ParticipantId,
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId), Username: fmt.Sprintf("Participant#%d", req.ParticipantId),
PartialSign: req.PartialSign, PartialSign: req.PartialSign,
} }
payload.Participants = append(payload.Participants, &p) 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 { if err = pubKey.UnmarshalBinary(entry.DkgPubKey); err != nil {
return fmt.Errorf("failed to unmarshal pubkey: %w", err) 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 { if err = dkgInstance.InitDKGInstance(am.baseSeed); err != nil {
@ -182,7 +182,7 @@ func (am *Machine) handleStateDkgDealsAwaitConfirmations(o *client.Operation) er
} }
dkgCommits = append(dkgCommits, commit) dkgCommits = append(dkgCommits, commit)
} }
dkgInstance.StoreCommits(entry.Addr, dkgCommits) dkgInstance.StoreCommits(entry.Username, dkgCommits)
} }
deals, err := dkgInstance.GetDeals() deals, err := dkgInstance.GetDeals()
@ -245,7 +245,7 @@ func (am *Machine) handleStateDkgResponsesAwaitConfirmations(o *client.Operation
if err = json.Unmarshal(decryptedDealBz, &deal); err != nil { if err = json.Unmarshal(decryptedDealBz, &deal); err != nil {
return fmt.Errorf("failed to unmarshal deal") return fmt.Errorf("failed to unmarshal deal")
} }
dkgInstance.StoreDeal(entry.Addr, &deal) dkgInstance.StoreDeal(entry.Username, &deal)
} }
processedResponses, err := dkgInstance.ProcessDeals() processedResponses, err := dkgInstance.ProcessDeals()
@ -298,7 +298,7 @@ func (am *Machine) handleStateDkgMasterKeyAwaitConfirmations(o *client.Operation
if err = json.Unmarshal(entry.DkgResponse, &entryResponses); err != nil { if err = json.Unmarshal(entry.DkgResponse, &entryResponses); err != nil {
return fmt.Errorf("failed to unmarshal responses: %w", err) 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 { if err = dkgInstance.ProcessResponses(); err != nil {

View File

@ -230,7 +230,7 @@ func (c *BaseClient) ProcessMessage(message storage.Message) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to get SigningQuorumParticipant: %w", err) return fmt.Errorf("failed to get SigningQuorumParticipant: %w", err)
} }
if initiator.Addr == c.GetUsername() { if initiator.Username == c.GetUsername() {
break 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 { 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 { 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) { if !ed25519.Verify(senderPubKey, message.Bytes(), message.Signature) {

View File

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

View File

@ -230,7 +230,7 @@ func TestFullFlow(t *testing.T) {
log.Fatalln("failed to get DKG pubKey:", err.Error()) log.Fatalln("failed to get DKG pubKey:", err.Error())
} }
participants = append(participants, &requests.SignatureProposalParticipantsEntry{ participants = append(participants, &requests.SignatureProposalParticipantsEntry{
Addr: node.client.GetUsername(), Username: node.client.GetUsername(),
PubKey: node.client.GetPubKey(), PubKey: node.client.GetPubKey(),
DkgPubKey: dkgPubKey, DkgPubKey: dkgPubKey,
}) })

View File

@ -8,7 +8,6 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"net/http" "net/http"
"time" "time"
"github.com/depools/dc4bc/client/types" "github.com/depools/dc4bc/client/types"
@ -80,6 +79,9 @@ func (c *BaseClient) StartHTTPServer(listenAddr string) error {
mux.HandleFunc("/startDKG", c.startDKGHandler) mux.HandleFunc("/startDKG", c.startDKGHandler)
mux.HandleFunc("/proposeSignMessage", c.proposeSignDataHandler) mux.HandleFunc("/proposeSignMessage", c.proposeSignDataHandler)
mux.HandleFunc("/saveOffset", c.saveOffsetHandler)
mux.HandleFunc("/getOffset", c.getOffsetHandler)
mux.HandleFunc("/getFSMDump", c.getFSMDumpHandler) mux.HandleFunc("/getFSMDump", c.getFSMDumpHandler)
mux.HandleFunc("/getFSMList", c.getFSMList) mux.HandleFunc("/getFSMList", c.getFSMList)
@ -138,6 +140,47 @@ func (c *BaseClient) getPubkeyHandler(w http.ResponseWriter, r *http.Request) {
successResponse(w, c.GetPubKey()) 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) { func (c *BaseClient) sendMessageHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost { if r.Method != http.MethodPost {
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method") errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
@ -313,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)) errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get FSM instance: %v", err))
return return
} }
participantID, err := fsmInstance.GetIDByAddr(c.GetUsername()) participantID, err := fsmInstance.GetIDByUsername(c.GetUsername())
if err != nil { if err != nil {
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get participantID: %v", err)) errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get participantID: %v", err))
return return

View File

@ -9,6 +9,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"runtime" "runtime"
"strconv"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@ -35,10 +36,17 @@ type terminal struct {
commands map[string]*terminalCommand commands map[string]*terminalCommand
currentCommand string currentCommand string
stopDroppingSensitiveData chan bool
} }
func NewTerminal(machine *airgapped.Machine) *terminal { 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{ t.addCommand("read_qr", &terminalCommand{
commandHandler: t.readQRCommand, commandHandler: t.readQRCommand,
description: "Reads QR chunks from camera, handle a decoded operation and returns paths to qr chunks of operation's result", description: "Reads QR chunks from camera, handle a decoded operation and returns paths to qr chunks of operation's result",
@ -47,7 +55,7 @@ func NewTerminal(machine *airgapped.Machine) *terminal {
commandHandler: t.helpCommand, commandHandler: t.helpCommand,
description: "shows available commands", description: "shows available commands",
}) })
t.addCommand("show_dkg_pub_key", &terminalCommand{ t.addCommand("show_dkg_pubkey", &terminalCommand{
commandHandler: t.showDKGPubKeyCommand, commandHandler: t.showDKGPubKeyCommand,
description: "shows a dkg pub key", description: "shows a dkg pub key",
}) })
@ -74,6 +82,10 @@ func NewTerminal(machine *airgapped.Machine) *terminal {
commandHandler: t.verifySignCommand, commandHandler: t.verifySignCommand,
description: "verifies a BLS signature of a message", 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 return &t
} }
@ -142,6 +154,62 @@ func (t *terminal) replayOperationLogCommand() error {
return nil 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 { func (t *terminal) dropOperationLogCommand() error {
fmt.Print("> Enter the DKGRoundIdentifier: ") fmt.Print("> Enter the DKGRoundIdentifier: ")
dkgRoundIdentifier, err := t.reader.ReadString('\n') dkgRoundIdentifier, err := t.reader.ReadString('\n')
@ -252,10 +320,16 @@ func (t *terminal) run() error {
} }
} }
func (t *terminal) dropSensitiveData(passExpiration time.Duration) { func (t *terminal) dropSensitiveDataByTicker(passExpiration time.Duration) {
ticker := time.NewTicker(passExpiration) ticker := time.NewTicker(passExpiration)
for range ticker.C { defer ticker.Stop()
for {
select {
case <-ticker.C:
t.airgapped.DropSensitiveData() t.airgapped.DropSensitiveData()
case <-t.stopDroppingSensitiveData:
return
}
} }
} }
@ -295,7 +369,6 @@ func main() {
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt)
t := NewTerminal(air) t := NewTerminal(air)
go t.dropSensitiveData(passwordLifeDuration)
go func() { go func() {
for range c { for range c {
if t.currentCommand == "read_qr" { if t.currentCommand == "read_qr" {
@ -305,7 +378,7 @@ func main() {
fmt.Printf("Intercepting SIGINT, please type `exit` to stop the machine\n>>> ") fmt.Printf("Intercepting SIGINT, please type `exit` to stop the machine\n>>> ")
} }
}() }()
go t.dropSensitiveDataByTicker(passwordLifeDuration)
if err = t.run(); err != nil { if err = t.run(); err != nil {
log.Fatalf(err.Error()) log.Fatalf(err.Error())
} }

View File

@ -13,6 +13,7 @@ import (
"net/http" "net/http"
"path/filepath" "path/filepath"
"sort" "sort"
"strconv"
"strings" "strings"
"time" "time"
@ -58,6 +59,8 @@ func main() {
getHashOfStartDKGCommand(), getHashOfStartDKGCommand(),
getSignaturesCommand(), getSignaturesCommand(),
getSignatureCommand(), getSignatureCommand(),
saveOffsetCommand(),
getOffsetCommand(),
getFSMStatusCommand(), getFSMStatusCommand(),
getFSMListCommand(), getFSMListCommand(),
) )
@ -270,7 +273,7 @@ func getOperationQRPathCommand() *cobra.Command {
return fmt.Errorf("failed to get operations: %s", operation.ErrorMessage) 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) qrPath := fmt.Sprintf("%s.gif", operationQRPath)
@ -329,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 { func getUsernameCommand() *cobra.Command {
return &cobra.Command{ return &cobra.Command{
Use: "get_username", Use: "get_username",
@ -373,7 +432,7 @@ func rawPostRequest(url string, contentType string, data []byte) (*client.Respon
func readOperationFromCameraCommand() *cobra.Command { func readOperationFromCameraCommand() *cobra.Command {
return &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", Short: "opens the camera and reads QR codes which should contain a processed operation",
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
listenAddr, err := cmd.Flags().GetString(flagListenAddr) listenAddr, err := cmd.Flags().GetString(flagListenAddr)
@ -472,7 +531,7 @@ func getHashOfStartDKGCommand() *cobra.Command {
if _, err := hashPayload.Write(p.DkgPubKey); err != nil { if _, err := hashPayload.Write(p.DkgPubKey); err != nil {
return err return err
} }
if _, err := hashPayload.Write([]byte(p.Addr)); err != nil { if _, err := hashPayload.Write([]byte(p.Username)); err != nil {
return err return err
} }
} }
@ -574,7 +633,7 @@ func getFSMStatusCommand() *cobra.Command {
quorum[k] = v quorum[k] = v
} }
} }
if strings.HasPrefix(string(dump.State), "state_sig") { if strings.HasPrefix(string(dump.State), "state_sig_") {
for k, v := range dump.Payload.SignatureProposalPayload.Quorum { for k, v := range dump.Payload.SignatureProposalPayload.Quorum {
quorum[k] = v quorum[k] = v
} }
@ -586,13 +645,13 @@ func getFSMStatusCommand() *cobra.Command {
for _, p := range quorum { for _, p := range quorum {
if strings.Contains(p.GetStatus().String(), "Await") { if strings.Contains(p.GetStatus().String(), "Await") {
waiting = append(waiting, p.GetAddr()) waiting = append(waiting, p.GetUsername())
} }
if strings.Contains(p.GetStatus().String(), "Error") { if strings.Contains(p.GetStatus().String(), "Error") {
failed = append(failed, p.GetAddr()) failed = append(failed, p.GetUsername())
} }
if strings.Contains(p.GetStatus().String(), "Confirmed") { if strings.Contains(p.GetStatus().String(), "Confirmed") {
confirmed = append(confirmed, p.GetAddr()) confirmed = append(confirmed, p.GetUsername())
} }
} }

View File

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

View File

@ -20,13 +20,13 @@ type DKGInvitationResponse responses.SignatureProposalParticipantInvitationsResp
func (d DKGInvitationResponse) Len() int { return len(d) } 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) 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 type DKGParticipants []*requests.SignatureProposalParticipantsEntry
func (d DKGParticipants) Len() int { return len(d) } 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) 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 { type OperationsResponse struct {
ErrorMessage string `json:"error_message,omitempty"` ErrorMessage string `json:"error_message,omitempty"`
@ -74,7 +74,7 @@ func calcStartDKGMessageHash(payload []byte) ([]byte, error) {
if _, err := hashPayload.Write(p.DkgPubKey); err != nil { if _, err := hashPayload.Write(p.DkgPubKey); err != nil {
return nil, err return nil, err
} }
if _, err := hashPayload.Write([]byte(p.Addr)); err != nil { if _, err := hashPayload.Write([]byte(p.Username)); err != nil {
return nil, err return nil, err
} }
} }

View File

@ -42,7 +42,7 @@ func (m *DKGProposalFSM) actionInitDKGProposal(inEvent fsm.Event, args ...interf
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum { for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
m.payload.DKGProposalPayload.Quorum[participantId] = &internal.DKGProposalParticipant{ m.payload.DKGProposalPayload.Quorum[participantId] = &internal.DKGProposalParticipant{
Addr: participant.Addr, Username: participant.Username,
DkgPubKey: make([]byte, len(participant.DkgPubKey)), DkgPubKey: make([]byte, len(participant.DkgPubKey)),
Status: internal.CommitAwaitConfirmation, Status: internal.CommitAwaitConfirmation,
UpdatedAt: participant.UpdatedAt, UpdatedAt: participant.UpdatedAt,
@ -59,7 +59,7 @@ func (m *DKGProposalFSM) actionInitDKGProposal(inEvent fsm.Event, args ...interf
for participantId, participant := range m.payload.DKGProposalPayload.Quorum { for participantId, participant := range m.payload.DKGProposalPayload.Quorum {
responseEntry := &responses.DKGProposalPubKeysParticipantEntry{ responseEntry := &responses.DKGProposalPubKeysParticipantEntry{
ParticipantId: participantId, ParticipantId: participantId,
Addr: participant.Addr, Username: participant.Username,
DkgPubKey: participant.DkgPubKey, DkgPubKey: participant.DkgPubKey,
} }
responseData = append(responseData, responseEntry) responseData = append(responseData, responseEntry)
@ -158,7 +158,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event
for participantId, participant := range m.payload.DKGProposalPayload.Quorum { for participantId, participant := range m.payload.DKGProposalPayload.Quorum {
responseEntry := &responses.DKGProposalCommitParticipantEntry{ responseEntry := &responses.DKGProposalCommitParticipantEntry{
ParticipantId: participantId, ParticipantId: participantId,
Addr: participant.Addr, Username: participant.Username,
DkgCommit: participant.DkgCommit, DkgCommit: participant.DkgCommit,
} }
responseData = append(responseData, responseEntry) responseData = append(responseData, responseEntry)
@ -263,7 +263,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event,
} }
responseEntry := &responses.DKGProposalDealParticipantEntry{ responseEntry := &responses.DKGProposalDealParticipantEntry{
ParticipantId: participantId, ParticipantId: participantId,
Addr: participant.Addr, Username: participant.Username,
DkgDeal: participant.DkgDeal, DkgDeal: participant.DkgDeal,
} }
responseData = append(responseData, responseEntry) responseData = append(responseData, responseEntry)
@ -365,7 +365,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Eve
for participantId, participant := range m.payload.DKGProposalPayload.Quorum { for participantId, participant := range m.payload.DKGProposalPayload.Quorum {
responseEntry := &responses.DKGProposalResponseParticipantEntry{ responseEntry := &responses.DKGProposalResponseParticipantEntry{
ParticipantId: participantId, ParticipantId: participantId,
Addr: participant.Addr, Username: participant.Username,
DkgResponse: participant.DkgResponse, DkgResponse: participant.DkgResponse,
} }
responseData = append(responseData, responseEntry) 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 { if p.PubKeys == nil {
p.PubKeys = make(map[string]ed25519.PublicKey) 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 { if p.IDs == nil {
p.IDs = make(map[string]int) 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 { if p.PubKeys == nil {
return nil, errors.New("{PubKeys} not initialized") return nil, errors.New("{PubKeys} not initialized")
} }
if addr == "" { if username == "" {
return nil, errors.New("{addr} cannot be empty") return nil, errors.New("{username} cannot be empty")
} }
pubKey, ok := p.PubKeys[addr] pubKey, ok := p.PubKeys[username]
if !ok { 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 return pubKey, nil
} }
func (p *DumpedMachineStatePayload) GetIDByAddr(addr string) (int, error) { func (p *DumpedMachineStatePayload) GetIDByUsername(username string) (int, error) {
if p.IDs == nil { if p.IDs == nil {
return -1, errors.New("{IDs} not initialized") return -1, errors.New("{IDs} not initialized")
} }
if addr == "" { if username == "" {
return -1, errors.New("{addr} cannot be empty") return -1, errors.New("{username} cannot be empty")
} }
id, ok := p.IDs[addr] id, ok := p.IDs[username]
if !ok { if !ok {
return -1, errors.New("cannot find id by {addr}") return -1, errors.New("cannot find id by {username}")
} }
return id, nil return id, nil
} }

View File

@ -41,7 +41,7 @@ type SignatureConfirmation struct {
} }
type SignatureProposalParticipant struct { type SignatureProposalParticipant struct {
Addr string Username string
PubKey ed25519.PublicKey PubKey ed25519.PublicKey
DkgPubKey []byte DkgPubKey []byte
// For validation user confirmation: sign(InvitationSecret, PubKey) => user // For validation user confirmation: sign(InvitationSecret, PubKey) => user
@ -55,8 +55,8 @@ func (sigP SignatureProposalParticipant) GetStatus() ParticipantStatus {
return sigP.Status return sigP.Status
} }
func (sigP SignatureProposalParticipant) GetAddr() string { func (sigP SignatureProposalParticipant) GetUsername() string {
return sigP.Addr return sigP.Username
} }
func (c *SignatureConfirmation) IsExpired() bool { func (c *SignatureConfirmation) IsExpired() bool {
@ -87,7 +87,7 @@ const (
) )
type DKGProposalParticipant struct { type DKGProposalParticipant struct {
Addr string Username string
DkgPubKey []byte DkgPubKey []byte
DkgCommit []byte DkgCommit []byte
DkgDeal []byte DkgDeal []byte
@ -102,8 +102,8 @@ func (dkgP DKGProposalParticipant) GetStatus() ParticipantStatus {
return dkgP.Status return dkgP.Status
} }
func (dkgP DKGProposalParticipant) GetAddr() string { func (dkgP DKGProposalParticipant) GetUsername() string {
return dkgP.Addr return dkgP.Username
} }
type DKGProposalQuorum map[int]*DKGProposalParticipant type DKGProposalQuorum map[int]*DKGProposalParticipant
@ -204,7 +204,7 @@ func (s SigningParticipantStatus) String() string {
} }
type SigningProposalParticipant struct { type SigningProposalParticipant struct {
Addr string Username string
Status SigningParticipantStatus Status SigningParticipantStatus
PartialSign []byte PartialSign []byte
Error error Error error
@ -215,6 +215,6 @@ func (signingP SigningProposalParticipant) GetStatus() ParticipantStatus {
return signingP.Status return signingP.Status
} }
func (signingP SigningProposalParticipant) GetAddr() string { func (signingP SigningProposalParticipant) GetUsername() string {
return signingP.Addr return signingP.Username
} }

View File

@ -29,7 +29,7 @@ type FSMInstance struct {
type Participant interface { type Participant interface {
GetStatus() internal.ParticipantStatus GetStatus() internal.ParticipantStatus
GetAddr() string GetUsername() string
} }
// Create new fsm with unique id // Create new fsm with unique id
@ -91,12 +91,12 @@ func FromDump(data []byte) (*FSMInstance, error) {
return i, err 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 { if i.dump == nil {
return nil, errors.New("dump not initialized") 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) { func (i *FSMInstance) SigningQuorumGetParticipant(id int) (*internal.SigningProposalParticipant, error) {
@ -107,12 +107,12 @@ func (i *FSMInstance) SigningQuorumGetParticipant(id int) (*internal.SigningProp
return i.dump.Payload.SigningQuorumGet(id), nil 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 { if i.dump == nil {
return -1, errors.New("dump not initialized") 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) { func (i *FSMInstance) Do(event fsm.Event, args ...interface{}) (result *fsm.Response, dump []byte, err error) {

View File

@ -21,12 +21,12 @@ import (
) )
const ( const (
addrMockLen = 32 usernameMockLen = 32
keysMockLen = 128 keysMockLen = 128
) )
type testParticipantsPayload struct { type testParticipantsPayload struct {
Addr string Username string
HotPrivKey ed25519.PrivateKey HotPrivKey ed25519.PrivateKey
HotPubKey ed25519.PublicKey HotPubKey ed25519.PublicKey
DkgPubKey []byte DkgPubKey []byte
@ -41,8 +41,8 @@ var (
dkgId = "1b7a6382afe0fbe2ff127a5779f5e9b042e685cabefeadcf4ef27c6089a56bfb" dkgId = "1b7a6382afe0fbe2ff127a5779f5e9b042e685cabefeadcf4ef27c6089a56bfb"
// map {addr} -> {participant} // map {username} -> {participant}
testAddrMapParticipants = map[string]*testParticipantsPayload{} testUsernameMapParticipants = map[string]*testParticipantsPayload{}
// map {dkg_queue_id} -> {participant} // map {dkg_queue_id} -> {participant}
testIdMapParticipants = map[int]*testParticipantsPayload{} testIdMapParticipants = map[int]*testParticipantsPayload{}
@ -62,7 +62,7 @@ func init() {
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
participant := &testParticipantsPayload{ participant := &testParticipantsPayload{
Addr: base64.StdEncoding.EncodeToString(genDataMock(addrMockLen)), Username: base64.StdEncoding.EncodeToString(genDataMock(usernameMockLen)),
HotPrivKey: genDataMock(keysMockLen), HotPrivKey: genDataMock(keysMockLen),
HotPubKey: genDataMock(keysMockLen), HotPubKey: genDataMock(keysMockLen),
DkgPubKey: genDataMock(keysMockLen), DkgPubKey: genDataMock(keysMockLen),
@ -71,7 +71,7 @@ func init() {
DkgResponse: genDataMock(keysMockLen), DkgResponse: genDataMock(keysMockLen),
DkgPartialKey: 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 // Make request
request := make([]*requests.SignatureProposalParticipantsEntry, 0) request := make([]*requests.SignatureProposalParticipantsEntry, 0)
for _, participant := range testAddrMapParticipants { for _, participant := range testUsernameMapParticipants {
request = append(request, &requests.SignatureProposalParticipantsEntry{ request = append(request, &requests.SignatureProposalParticipantsEntry{
Addr: participant.Addr, Username: participant.Username,
PubKey: participant.HotPubKey, PubKey: participant.HotPubKey,
DkgPubKey: participant.DkgPubKey, DkgPubKey: participant.DkgPubKey,
}) })
@ -196,14 +196,14 @@ func Test_SignatureProposal_EventInitProposal_Positive(t *testing.T) {
t.Fatalf("expected unique {ParticipantId}") t.Fatalf("expected unique {ParticipantId}")
} }
if participant.Addr == "" { if participant.Username == "" {
t.Fatalf("expected not empty {Addr}") t.Fatalf("expected not empty {Username}")
} }
participantEntry, ok := testAddrMapParticipants[participant.Addr] participantEntry, ok := testUsernameMapParticipants[participant.Username]
if !ok { if !ok {
t.Fatalf("expected exist {Addr}") t.Fatalf("expected exist {Username}")
} }
testIdMapParticipants[participant.ParticipantId] = participantEntry testIdMapParticipants[participant.ParticipantId] = participantEntry
@ -409,8 +409,8 @@ func Test_DkgProposal_EventDKGCommitConfirmationReceived(t *testing.T) {
t.Fatalf("expected exist {ParticipantId}") t.Fatalf("expected exist {ParticipantId}")
} }
if responseEntry.Addr == "" { if responseEntry.Username == "" {
t.Fatalf("expected {Addr} non zero length") t.Fatalf("expected {Username} non zero length")
} }
if len(responseEntry.DkgCommit) == 0 { if len(responseEntry.DkgCommit) == 0 {
@ -534,8 +534,8 @@ func Test_DkgProposal_EventDKGDealConfirmationReceived(t *testing.T) {
t.Fatalf("expected exist {ParticipantId}") t.Fatalf("expected exist {ParticipantId}")
} }
if responseEntry.Addr == "" { if responseEntry.Username == "" {
t.Fatalf("expected {Addr} non zero length") t.Fatalf("expected {Username} non zero length")
} }
if len(responseEntry.DkgDeal) == 0 { if len(responseEntry.DkgDeal) == 0 {
@ -653,8 +653,8 @@ func Test_DkgProposal_EventDKGResponseConfirmationReceived_Positive(t *testing.T
t.Fatalf("expected exist {ParticipantId}") t.Fatalf("expected exist {ParticipantId}")
} }
if responseEntry.Addr == "" { if responseEntry.Username == "" {
t.Fatalf("expected {Addr} non zero length") t.Fatalf("expected {Username} non zero length")
} }
if len(responseEntry.DkgResponse) == 0 { 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 { for index, participant := range request.Participants {
//participantId := createFingerprint(&participant.DkgPubKey)
m.payload.SignatureProposalPayload.Quorum[index] = &internal.SignatureProposalParticipant{ m.payload.SignatureProposalPayload.Quorum[index] = &internal.SignatureProposalParticipant{
Addr: participant.Addr, Username: participant.Username,
PubKey: participant.PubKey, PubKey: participant.PubKey,
DkgPubKey: participant.DkgPubKey, DkgPubKey: participant.DkgPubKey,
Status: internal.SigConfirmationAwaitConfirmation, Status: internal.SigConfirmationAwaitConfirmation,
@ -50,8 +49,8 @@ func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, ar
UpdatedAt: request.CreatedAt, UpdatedAt: request.CreatedAt,
} }
m.payload.SetPubKeyAddr(participant.Addr, participant.PubKey) m.payload.SetPubKeyUsername(participant.Username, participant.PubKey)
m.payload.SetIDAddr(participant.Addr, index) m.payload.SetIDUsername(participant.Username, index)
} }
// Checking fo quorum length // Checking fo quorum length
@ -67,7 +66,7 @@ func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, ar
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum { for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
responseEntry := &responses.SignatureProposalParticipantInvitationEntry{ responseEntry := &responses.SignatureProposalParticipantInvitationEntry{
ParticipantId: participantId, ParticipantId: participantId,
Addr: participant.Addr, Username: participant.Username,
Threshold: participant.Threshold, Threshold: participant.Threshold,
DkgPubKey: participant.DkgPubKey, DkgPubKey: participant.DkgPubKey,
PubKey: participant.PubKey, PubKey: participant.PubKey,
@ -171,7 +170,7 @@ func (m *SignatureProposalFSM) actionValidateSignatureProposal(fsm.Event, ...int
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum { for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
responseEntry := &responses.SignatureProposalParticipantStatusEntry{ responseEntry := &responses.SignatureProposalParticipantStatusEntry{
ParticipantId: participantId, ParticipantId: participantId,
Addr: participant.Addr, Username: participant.Username,
Status: uint8(participant.Status), Status: uint8(participant.Status),
} }
responseData = append(responseData, responseEntry) responseData = append(responseData, responseEntry)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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