dc4bc/main.go

246 lines
7.1 KiB
Go
Raw Normal View History

2020-07-22 04:53:06 -07:00
package main
import (
2020-09-04 08:35:22 -07:00
"bytes"
2020-08-09 14:37:53 -07:00
"context"
2020-08-19 09:04:41 -07:00
"crypto/md5"
"encoding/json"
2020-07-23 06:29:20 -07:00
"fmt"
2020-09-04 09:40:15 -07:00
"github.com/depools/dc4bc/client/types"
2020-07-22 04:53:06 -07:00
_ "image/jpeg"
2020-09-04 09:40:15 -07:00
"io/ioutil"
2020-07-22 04:53:06 -07:00
"log"
2020-09-04 08:35:22 -07:00
"net/http"
2020-07-23 06:29:20 -07:00
"sync"
2020-08-19 09:04:41 -07:00
"time"
2020-08-21 13:37:49 -07:00
"github.com/depools/dc4bc/airgapped"
2020-08-30 09:23:48 -07:00
"github.com/depools/dc4bc/client"
2020-08-19 09:04:41 -07:00
"github.com/depools/dc4bc/fsm/types/requests"
2020-08-09 14:37:53 -07:00
"github.com/depools/dc4bc/qr"
"github.com/depools/dc4bc/storage"
2020-07-22 04:53:06 -07:00
)
2020-08-19 09:04:41 -07:00
type node struct {
2020-09-07 01:07:49 -07:00
client client.Poller
2020-09-04 09:40:15 -07:00
keyPair *client.KeyPair
air *airgapped.AirgappedMachine
listenAddr string
}
type OperationsResponse struct {
Result map[string]*types.Operation `json:"result"`
}
func getOperations(url string) (*OperationsResponse, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("failed to get operations for node %w", err)
}
defer resp.Body.Close()
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("failed to read body %v", err)
}
var response OperationsResponse
if err = json.Unmarshal(responseBody, &response); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %v", err)
}
return &response, nil
}
func handleProcessedOperation(url string, operation types.Operation) error {
operationBz, err := json.Marshal(operation)
if err != nil {
return fmt.Errorf("failed to marshal operation: %w", err)
}
resp, err := http.Post(url, "application/json", bytes.NewReader(operationBz))
if err != nil {
return fmt.Errorf("failed to handle processed operation %w", err)
}
defer resp.Body.Close()
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("failed to read body %v", err)
}
var response client.Response
if err = json.Unmarshal(responseBody, &response); err != nil {
return fmt.Errorf("failed to unmarshal response: %w", err)
}
if response.ErrorMessage != "" {
return fmt.Errorf("failed to handle processed operation: %s", response.ErrorMessage)
}
return nil
2020-09-04 08:35:22 -07:00
}
func (n *node) run() {
for {
2020-09-04 09:40:15 -07:00
operationsResponse, err := getOperations(fmt.Sprintf("http://%s/getOperations", n.listenAddr))
2020-09-04 08:35:22 -07:00
if err != nil {
2020-09-04 09:40:15 -07:00
log.Fatalf("failed to get operations: %v", err)
2020-09-04 08:35:22 -07:00
}
2020-09-04 09:40:15 -07:00
operations := operationsResponse.Result
2020-09-04 08:35:22 -07:00
if len(operations) == 0 {
time.Sleep(1 * time.Second)
continue
}
2020-09-07 01:07:49 -07:00
n.client.GetLogger().Log("Got %d Operations from pool", len(operations))
2020-09-04 08:35:22 -07:00
for _, operation := range operations {
2020-09-07 01:07:49 -07:00
n.client.GetLogger().Log("Handling operation %s in airgapped", operation.Type)
2020-09-04 08:35:22 -07:00
processedOperation, err := n.air.HandleOperation(*operation)
if err != nil {
2020-09-07 01:07:49 -07:00
n.client.GetLogger().Log("Failed to handle operation: %v", err)
2020-09-04 08:35:22 -07:00
}
2020-09-07 01:07:49 -07:00
n.client.GetLogger().Log("Got %d Processed Operations from Airgapped", len(operations))
n.client.GetLogger().Log("Operation %s handled in airgapped, result event is %s",
2020-09-04 08:35:22 -07:00
operation.Event, processedOperation.Event)
2020-09-04 09:40:15 -07:00
if err = handleProcessedOperation(fmt.Sprintf("http://%s/handleProcessedOperationJSON", n.listenAddr),
processedOperation); err != nil {
2020-09-07 01:07:49 -07:00
n.client.GetLogger().Log("Failed to handle processed operation: %v", err)
2020-09-04 08:35:22 -07:00
} else {
2020-09-07 01:07:49 -07:00
n.client.GetLogger().Log("Successfully handled processed operation %s", processedOperation.Event)
2020-09-04 08:35:22 -07:00
}
2020-09-04 09:40:15 -07:00
2020-09-04 08:35:22 -07:00
}
}
2020-08-19 09:04:41 -07:00
}
2020-07-22 04:53:06 -07:00
func main() {
2020-07-23 06:29:20 -07:00
var numNodes = 4
2020-08-19 09:04:41 -07:00
var threshold = 3
var storagePath = "/tmp/dc4bc_storage"
2020-09-04 08:35:22 -07:00
var nodes = make([]*node, numNodes)
startingPort := 8080
2020-08-09 14:37:53 -07:00
for nodeID := 0; nodeID < numNodes; nodeID++ {
var ctx = context.Background()
2020-08-14 05:34:15 -07:00
var userName = fmt.Sprintf("node_%d", nodeID)
2020-08-09 14:37:53 -07:00
var state, err = client.NewLevelDBState(fmt.Sprintf("/tmp/dc4bc_node_%d_state", nodeID))
if err != nil {
log.Fatalf("node %d failed to init state: %v\n", nodeID, err)
2020-07-22 04:53:06 -07:00
}
2020-08-19 09:04:41 -07:00
stg, err := storage.NewFileStorage(storagePath)
2020-07-23 08:39:56 -07:00
if err != nil {
2020-08-09 14:37:53 -07:00
log.Fatalf("node %d failed to init storage: %v\n", nodeID, err)
2020-07-23 08:39:56 -07:00
}
2020-08-14 05:34:15 -07:00
keyStore, err := client.NewLevelDBKeyStore(userName, fmt.Sprintf("/tmp/dc4bc_node_%d_key_store", nodeID))
if err != nil {
log.Fatalf("Failed to init key store: %v", err)
}
2020-08-19 09:04:41 -07:00
keyPair := client.NewKeyPair()
if err := keyStore.PutKeys(userName, keyPair); err != nil {
log.Fatalf("Failed to PutKeys: %v\n", err)
}
airgappedMachine, err := airgapped.NewAirgappedMachine(fmt.Sprintf("/tmp/dc4bc_node_%d_airgapped_db", nodeID))
if err != nil {
log.Fatalf("Failed to create airgapped machine: %v", err)
}
2020-08-09 14:37:53 -07:00
clt, err := client.NewClient(
ctx,
2020-08-14 05:34:15 -07:00
userName,
2020-08-09 14:37:53 -07:00
state,
stg,
2020-08-14 05:34:15 -07:00
keyStore,
2020-08-09 14:37:53 -07:00
qr.NewCameraProcessor(),
)
2020-07-23 08:39:56 -07:00
if err != nil {
2020-08-09 14:37:53 -07:00
log.Fatalf("node %d failed to init client: %v\n", nodeID, err)
2020-07-23 08:39:56 -07:00
}
2020-09-04 08:35:22 -07:00
airgappedMachine.SetAddress(clt.GetAddr())
2020-07-23 08:39:56 -07:00
2020-08-19 09:04:41 -07:00
nodes[nodeID] = &node{
2020-09-04 09:40:15 -07:00
client: clt,
keyPair: keyPair,
air: airgappedMachine,
listenAddr: fmt.Sprintf("localhost:%d", startingPort),
2020-08-19 09:04:41 -07:00
}
2020-09-04 09:40:15 -07:00
startingPort++
2020-08-19 09:04:41 -07:00
}
2020-07-23 08:39:56 -07:00
2020-08-19 09:04:41 -07:00
// Each node starts to Poll().
2020-09-04 08:35:22 -07:00
for nodeID, n := range nodes {
2020-09-04 09:40:15 -07:00
go func(nodeID int, node *node) {
if err := node.client.StartHTTPServer(node.listenAddr); err != nil {
2020-09-04 08:35:22 -07:00
log.Fatalf("failed to start HTTP server for nodeID #%d: %v\n", nodeID, err)
}
2020-09-04 09:40:15 -07:00
}(nodeID, n)
2020-09-04 08:35:22 -07:00
go nodes[nodeID].run()
2020-09-07 01:07:49 -07:00
go func(nodeID int, node client.Poller) {
2020-08-09 14:37:53 -07:00
if err := node.Poll(); err != nil {
log.Fatalf("client %d poller failed: %v\n", nodeID, err)
}
2020-09-04 08:35:22 -07:00
}(nodeID, n.client)
2020-07-22 04:53:06 -07:00
2020-08-09 14:37:53 -07:00
log.Printf("client %d started...\n", nodeID)
2020-07-23 06:29:20 -07:00
}
2020-08-09 14:37:53 -07:00
2020-08-19 09:04:41 -07:00
// Node1 tells other participants to start DKG.
var participants []*requests.SignatureProposalParticipantsEntry
for _, node := range nodes {
2020-09-04 08:35:22 -07:00
dkgPubKey, err := node.air.GetPubKey().MarshalBinary()
2020-08-21 09:25:09 -07:00
if err != nil {
log.Fatalln("failed to get DKG pubKey:", err.Error())
}
2020-08-19 09:04:41 -07:00
participants = append(participants, &requests.SignatureProposalParticipantsEntry{
Addr: node.client.GetAddr(),
PubKey: node.client.GetPubKey(),
2020-08-26 08:15:38 -07:00
DkgPubKey: dkgPubKey,
2020-08-19 09:04:41 -07:00
})
}
messageData := requests.SignatureProposalParticipantsListRequest{
Participants: participants,
SigningThreshold: threshold,
CreatedAt: time.Now(),
}
messageDataBz, err := json.Marshal(messageData)
if err != nil {
log.Fatalf("failed to marshal SignatureProposalParticipantsListRequest: %v\n", err)
}
2020-09-04 08:35:22 -07:00
if _, err := http.Post(fmt.Sprintf("http://localhost:%d/startDKG", startingPort-1),
"application/json", bytes.NewReader(messageDataBz)); err != nil {
log.Fatalf("failed to send HTTP request to start DKG: %v\n", err)
2020-08-19 09:04:41 -07:00
}
2020-08-27 02:45:05 -07:00
// i haven't a better idea to test signing without big changes in the client code
2020-08-26 08:15:38 -07:00
time.Sleep(10 * time.Second)
log.Println("Propose message to sign")
2020-09-04 08:35:22 -07:00
dkgRoundID := md5.Sum(messageDataBz)
2020-08-26 08:15:38 -07:00
messageDataSign := requests.SigningProposalStartRequest{
2020-09-04 08:35:22 -07:00
ParticipantId: len(nodes) - 1,
2020-08-26 08:15:38 -07:00
SrcPayload: []byte("message to sign"),
CreatedAt: time.Now(),
}
2020-09-04 08:35:22 -07:00
messageDataSignBz, err := json.Marshal(messageDataSign)
2020-08-26 08:15:38 -07:00
if err != nil {
2020-09-04 08:35:22 -07:00
log.Fatalf("failed to marshal SigningProposalStartRequest: %v\n", err)
2020-08-26 08:15:38 -07:00
}
2020-09-04 08:35:22 -07:00
messageDataBz, err = json.Marshal(map[string][]byte{"data": messageDataSignBz,
"dkgID": dkgRoundID[:]})
if err != nil {
log.Fatalf("failed to marshal SignatureProposalParticipantsListRequest: %v\n", err)
2020-08-26 08:15:38 -07:00
}
2020-09-04 08:35:22 -07:00
if _, err := http.Post(fmt.Sprintf("http://localhost:%d/proposeSignMessage", startingPort-1),
"application/json", bytes.NewReader(messageDataBz)); err != nil {
log.Fatalf("failed to send HTTP request to sign message: %v\n", err)
2020-08-26 08:15:38 -07:00
}
2020-08-09 14:37:53 -07:00
var wg = sync.WaitGroup{}
wg.Add(1)
2020-07-23 06:29:20 -07:00
wg.Wait()
2020-07-22 04:53:06 -07:00
}