mirror of https://github.com/certusone/dc4bc.git
Merge branch 'master' into feat/save-offset-cli
This commit is contained in:
commit
8a4c61fe98
4
HowTo.md
4
HowTo.md
|
@ -9,7 +9,7 @@ git clone git@github.com:depools/dc4bc.git
|
||||||
|
|
||||||
First install the Go toolchain:
|
First install the Go toolchain:
|
||||||
```
|
```
|
||||||
wget https://golang.org/dl/go1.15.2.linux-amd64.tar.gz
|
curl -O https://golang.org/dl/go1.15.2.linux-amd64.tar.gz
|
||||||
tar -C /usr/local -xzf 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
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
```
|
```
|
||||||
|
@ -229,4 +229,4 @@ You can verify any signature by executing `verify_signature` command inside the
|
||||||
> Enter the BLS signature: tK+3CV2CI0flgwWLuhrZA5eaFfuJIvpLAc6CbAy5XBuRpzuCkjOZLCU6z1SvlwQIBJp5dAVa2rtbSy1jl98YtidujVWeUDNUz+kRl2C1C1BeLG5JvzQxhgr2dDxq0thu
|
> Enter the BLS signature: tK+3CV2CI0flgwWLuhrZA5eaFfuJIvpLAc6CbAy5XBuRpzuCkjOZLCU6z1SvlwQIBJp5dAVa2rtbSy1jl98YtidujVWeUDNUz+kRl2C1C1BeLG5JvzQxhgr2dDxq0thu
|
||||||
> Enter the message which was signed (base64): dGhlIG1lc3NhZ2UgdG8gc2lnbgo=
|
> Enter the message which was signed (base64): dGhlIG1lc3NhZ2UgdG8gc2lnbgo=
|
||||||
Signature is correct!
|
Signature is correct!
|
||||||
```
|
```
|
||||||
|
|
|
@ -411,3 +411,11 @@ func (c *BaseClient) verifyMessage(fsmInstance *state_machines.FSMInstance, mess
|
||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -82,10 +82,48 @@ func (c *BaseClient) StartHTTPServer(listenAddr string) error {
|
||||||
mux.HandleFunc("/saveOffset", c.saveOffsetHandler)
|
mux.HandleFunc("/saveOffset", c.saveOffsetHandler)
|
||||||
mux.HandleFunc("/getOffset", c.getOffsetHandler)
|
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)
|
c.Logger.Log("Starting HTTP server on address: %s", listenAddr)
|
||||||
return http.ListenAndServe(listenAddr, mux)
|
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) {
|
func (c *BaseClient) getUsernameHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodGet {
|
if r.Method != http.MethodGet {
|
||||||
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
|
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
|
||||||
|
|
|
@ -31,6 +31,7 @@ type State interface {
|
||||||
|
|
||||||
SaveFSM(dkgRoundID string, dump []byte) error
|
SaveFSM(dkgRoundID string, dump []byte) error
|
||||||
LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, bool, error)
|
LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, bool, error)
|
||||||
|
GetAllFSM() (map[string]*state_machines.FSMInstance, error)
|
||||||
|
|
||||||
PutOperation(operation *types.Operation) error
|
PutOperation(operation *types.Operation) error
|
||||||
DeleteOperation(operationID string) error
|
DeleteOperation(operationID string) error
|
||||||
|
@ -146,6 +147,27 @@ func (s *LevelDBState) SaveFSM(dkgRoundID string, dump []byte) error {
|
||||||
return nil
|
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) {
|
func (s *LevelDBState) LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, bool, error) {
|
||||||
bz, err := s.stateDb.Get([]byte(fsmStateKey), nil)
|
bz, err := s.stateDb.Get([]byte(fsmStateKey), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,12 +7,14 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/depools/dc4bc/fsm/state_machines"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/depools/dc4bc/fsm/fsm"
|
"github.com/depools/dc4bc/fsm/fsm"
|
||||||
|
@ -59,6 +61,8 @@ func main() {
|
||||||
getSignatureCommand(),
|
getSignatureCommand(),
|
||||||
saveOffsetCommand(),
|
saveOffsetCommand(),
|
||||||
getOffsetCommand(),
|
getOffsetCommand(),
|
||||||
|
getFSMStatusCommand(),
|
||||||
|
getFSMListCommand(),
|
||||||
)
|
)
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
log.Fatalf("Failed to execute root command: %v", err)
|
log.Fatalf("Failed to execute root command: %v", err)
|
||||||
|
@ -577,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.GetAddr())
|
||||||
|
}
|
||||||
|
if strings.Contains(p.GetStatus().String(), "Error") {
|
||||||
|
failed = append(failed, p.GetAddr())
|
||||||
|
}
|
||||||
|
if strings.Contains(p.GetStatus().String(), "Confirmed") {
|
||||||
|
confirmed = append(confirmed, p.GetAddr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/depools/dc4bc/client/types"
|
"github.com/depools/dc4bc/client/types"
|
||||||
"github.com/depools/dc4bc/fsm/fsm"
|
"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/dkg_proposal_fsm"
|
||||||
"github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm"
|
"github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm"
|
||||||
"github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm"
|
"github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm"
|
||||||
|
@ -32,6 +33,11 @@ type OperationsResponse struct {
|
||||||
Result map[string]*types.Operation `json:"result"`
|
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 {
|
type SignaturesResponse struct {
|
||||||
ErrorMessage string `json:"error_message,omitempty"`
|
ErrorMessage string `json:"error_message,omitempty"`
|
||||||
Result map[string][]types.ReconstructedSignature `json:"result"`
|
Result map[string][]types.ReconstructedSignature `json:"result"`
|
||||||
|
|
|
@ -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,10 +2,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"reflect"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/depools/dc4bc/client"
|
"github.com/depools/dc4bc/client"
|
||||||
|
@ -24,6 +27,7 @@ const (
|
||||||
flagStoreDBDSN = "key_store_dbdsn"
|
flagStoreDBDSN = "key_store_dbdsn"
|
||||||
flagFramesDelay = "frames_delay"
|
flagFramesDelay = "frames_delay"
|
||||||
flagChunkSize = "chunk_size"
|
flagChunkSize = "chunk_size"
|
||||||
|
flagConfigPath = "config_path"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -35,31 +39,127 @@ func init() {
|
||||||
rootCmd.PersistentFlags().String(flagStoreDBDSN, "./dc4bc_key_store", "Key Store DBDSN")
|
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(flagFramesDelay, 10, "Delay times between frames in 100ths of a second")
|
||||||
rootCmd.PersistentFlags().Int(flagChunkSize, 256, "QR-code's chunk size")
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = checkConfig(&cfg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func genKeyPairCommand() *cobra.Command {
|
func genKeyPairCommand() *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "gen_keys",
|
Use: "gen_keys",
|
||||||
Short: "generates a keypair to sign and verify messages",
|
Short: "generates a keypair to sign and verify messages",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
userName, err := cmd.Flags().GetString(flagUserName)
|
cfg, err := loadConfig(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read configuration: %v", err)
|
log.Fatalf("failed to load config: %v", err)
|
||||||
}
|
|
||||||
keyStoreDBDSN, err := cmd.Flags().GetString(flagStoreDBDSN)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to read configuration: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPair := client.NewKeyPair()
|
keyPair := client.NewKeyPair()
|
||||||
keyStore, err := client.NewLevelDBKeyStore(userName, keyStoreDBDSN)
|
keyStore, err := client.NewLevelDBKeyStore(cfg.Username, cfg.KeyStoreDBDSN)
|
||||||
if err != nil {
|
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 {
|
if err = keyStore.PutKeys(cfg.Username, keyPair); err != nil {
|
||||||
return fmt.Errorf("failed to save keypair: %w", err)
|
log.Fatalf("failed to save keypair: %v", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("keypair generated for user %s and saved to %s\n", userName, keyStoreDBDSN)
|
fmt.Printf("keypair generated for user %s and saved to %s\n", cfg.Username, cfg.KeyStoreDBDSN)
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,69 +169,34 @@ func startClientCommand() *cobra.Command {
|
||||||
Use: "start",
|
Use: "start",
|
||||||
Short: "starts dc4bc client",
|
Short: "starts dc4bc client",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
userName, err := cmd.Flags().GetString(flagUserName)
|
cfg, err := loadConfig(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to read configuration: %v", err)
|
log.Fatalf("failed to load config: %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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
state, err := client.NewLevelDBState(stateDBDSN)
|
state, err := client.NewLevelDBState(cfg.StateDBDSN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to init state client: %v", err)
|
log.Fatalf("Failed to init state client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stg, err := storage.NewKafkaStorage(ctx, storageDBDSN, storageTopic)
|
stg, err := storage.NewKafkaStorage(ctx, cfg.StorageDBDSN, cfg.StorageTopic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to init storage client: %v", err)
|
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 {
|
if err != nil {
|
||||||
log.Fatalf("Failed to init key store: %v", err)
|
log.Fatalf("Failed to init key store: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
processor := qr.NewCameraProcessor()
|
processor := qr.NewCameraProcessor()
|
||||||
processor.SetDelay(framesDelay)
|
processor.SetDelay(cfg.FramesDelay)
|
||||||
processor.SetChunkSize(chunkSize)
|
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 {
|
if err != nil {
|
||||||
log.Fatalf("Failed to init client: %v", err)
|
log.Fatalf("Failed to init client: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -149,7 +214,7 @@ func startClientCommand() *cobra.Command {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := cli.StartHTTPServer(listenAddr); err != nil {
|
if err := cli.StartHTTPServer(cfg.ListenAddress); err != nil {
|
||||||
log.Fatalf("HTTP server error: %v", err)
|
log.Fatalf("HTTP server error: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -5,6 +5,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ParticipantStatus interface {
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
type ConfirmationParticipantStatus uint8
|
type ConfirmationParticipantStatus uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -47,6 +51,14 @@ type SignatureProposalParticipant struct {
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sigP SignatureProposalParticipant) GetStatus() ParticipantStatus {
|
||||||
|
return sigP.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sigP SignatureProposalParticipant) GetAddr() string {
|
||||||
|
return sigP.Addr
|
||||||
|
}
|
||||||
|
|
||||||
func (c *SignatureConfirmation) IsExpired() bool {
|
func (c *SignatureConfirmation) IsExpired() bool {
|
||||||
return c.ExpiresAt.Before(c.UpdatedAt)
|
return c.ExpiresAt.Before(c.UpdatedAt)
|
||||||
}
|
}
|
||||||
|
@ -86,6 +98,14 @@ type DKGProposalParticipant struct {
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dkgP DKGProposalParticipant) GetStatus() ParticipantStatus {
|
||||||
|
return dkgP.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dkgP DKGProposalParticipant) GetAddr() string {
|
||||||
|
return dkgP.Addr
|
||||||
|
}
|
||||||
|
|
||||||
type DKGProposalQuorum map[int]*DKGProposalParticipant
|
type DKGProposalQuorum map[int]*DKGProposalParticipant
|
||||||
|
|
||||||
type DKGConfirmation struct {
|
type DKGConfirmation struct {
|
||||||
|
@ -190,3 +210,11 @@ type SigningProposalParticipant struct {
|
||||||
Error error
|
Error error
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (signingP SigningProposalParticipant) GetStatus() ParticipantStatus {
|
||||||
|
return signingP.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
func (signingP SigningProposalParticipant) GetAddr() string {
|
||||||
|
return signingP.Addr
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,11 @@ type FSMInstance struct {
|
||||||
dump *FSMDump
|
dump *FSMDump
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Participant interface {
|
||||||
|
GetStatus() internal.ParticipantStatus
|
||||||
|
GetAddr() string
|
||||||
|
}
|
||||||
|
|
||||||
// Create new fsm with unique id
|
// Create new fsm with unique id
|
||||||
// transactionId required for unique identify dump
|
// transactionId required for unique identify dump
|
||||||
func Create(dkgID string) (*FSMInstance, error) {
|
func Create(dkgID string) (*FSMInstance, error) {
|
||||||
|
@ -176,6 +181,10 @@ func (i *FSMInstance) Dump() ([]byte, error) {
|
||||||
return i.dump.Marshal()
|
return i.dump.Marshal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *FSMInstance) FSMDump() *FSMDump {
|
||||||
|
return i.dump
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Add encryption
|
// TODO: Add encryption
|
||||||
func (d *FSMDump) Marshal() ([]byte, error) {
|
func (d *FSMDump) Marshal() ([]byte, error) {
|
||||||
return json.Marshal(d)
|
return json.Marshal(d)
|
||||||
|
|
|
@ -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)
|
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
|
// PutOperation mocks base method
|
||||||
func (m *MockState) PutOperation(operation *types.Operation) error {
|
func (m *MockState) PutOperation(operation *types.Operation) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
Loading…
Reference in New Issue