2020-08-18 11:52:04 -07:00
|
|
|
package airgapped
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2020-08-20 08:08:11 -07:00
|
|
|
client "github.com/depools/dc4bc/client/types"
|
2020-08-18 11:52:04 -07:00
|
|
|
"github.com/depools/dc4bc/dkg"
|
|
|
|
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
|
2020-08-20 09:50:18 -07:00
|
|
|
"github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm"
|
2020-08-18 11:52:04 -07:00
|
|
|
"github.com/depools/dc4bc/fsm/types/requests"
|
|
|
|
"github.com/depools/dc4bc/fsm/types/responses"
|
2020-08-25 05:56:27 -07:00
|
|
|
"github.com/depools/dc4bc/storage"
|
2020-08-18 11:52:04 -07:00
|
|
|
"go.dedis.ch/kyber/v3"
|
|
|
|
"go.dedis.ch/kyber/v3/pairing/bn256"
|
|
|
|
dkgPedersen "go.dedis.ch/kyber/v3/share/dkg/pedersen"
|
|
|
|
)
|
|
|
|
|
2020-08-25 05:56:27 -07:00
|
|
|
func createMessage(o client.Operation, data []byte) storage.Message {
|
|
|
|
return storage.Message{
|
|
|
|
Event: string(o.Event),
|
|
|
|
Data: data,
|
|
|
|
DkgRoundID: o.DKGIdentifier,
|
|
|
|
RecipientAddr: o.To,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-18 11:52:04 -07:00
|
|
|
func (am *AirgappedMachine) handleStateAwaitParticipantsConfirmations(o *client.Operation) error {
|
|
|
|
var (
|
|
|
|
payload responses.SignatureProposalParticipantInvitationsResponse
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
if _, ok := am.dkgInstances[o.DKGIdentifier]; ok {
|
|
|
|
return fmt.Errorf("dkg instance %s already exists", o.DKGIdentifier)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = json.Unmarshal(o.Payload, &payload); err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal payload: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := am.dkgInstances[o.DKGIdentifier]; ok {
|
|
|
|
return fmt.Errorf("dkg instance %s already exists", o.DKGIdentifier)
|
|
|
|
}
|
|
|
|
|
|
|
|
dkgInstance := dkg.Init(am.suite, am.pubKey, am.secKey)
|
|
|
|
dkgInstance.Threshold = len(payload)
|
|
|
|
|
|
|
|
am.dkgInstances[o.DKGIdentifier] = dkgInstance
|
|
|
|
|
2020-08-25 06:19:44 -07:00
|
|
|
pid := -1
|
2020-08-21 09:25:09 -07:00
|
|
|
for _, r := range payload {
|
|
|
|
if r.Addr == am.ParticipantAddress {
|
|
|
|
pid = r.ParticipantId
|
|
|
|
}
|
|
|
|
}
|
2020-08-25 06:19:44 -07:00
|
|
|
if pid < 0 {
|
|
|
|
return fmt.Errorf("failed to determine participant id for DKG with participant address %s", am.ParticipantAddress)
|
|
|
|
}
|
2020-08-21 09:25:09 -07:00
|
|
|
|
2020-08-20 09:50:18 -07:00
|
|
|
req := requests.SignatureProposalParticipantRequest{
|
2020-08-21 09:25:09 -07:00
|
|
|
ParticipantId: pid,
|
2020-08-20 09:50:18 -07:00
|
|
|
CreatedAt: o.CreatedAt,
|
|
|
|
}
|
|
|
|
reqBz, err := json.Marshal(req)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to generate fsm request: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-08-25 05:56:27 -07:00
|
|
|
o.Event = signature_proposal_fsm.EventConfirmSignatureProposal
|
|
|
|
o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz))
|
2020-08-18 11:52:04 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (am *AirgappedMachine) GetPubKey() kyber.Point {
|
|
|
|
return am.pubKey
|
|
|
|
}
|
|
|
|
|
|
|
|
func (am *AirgappedMachine) handleStateDkgCommitsAwaitConfirmations(o *client.Operation) error {
|
|
|
|
var (
|
2020-08-21 09:50:30 -07:00
|
|
|
payload responses.DKGProposalPubKeysParticipantResponse
|
2020-08-18 11:52:04 -07:00
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
dkgInstance, ok := am.dkgInstances[o.DKGIdentifier]
|
|
|
|
if !ok {
|
2020-08-19 06:47:37 -07:00
|
|
|
dkgInstance = dkg.Init(am.suite, am.pubKey, am.secKey)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
2020-08-19 06:47:37 -07:00
|
|
|
dkgInstance.Threshold = len(payload)
|
|
|
|
|
2020-08-18 11:52:04 -07:00
|
|
|
if err = json.Unmarshal(o.Payload, &payload); err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal payload: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, entry := range payload {
|
|
|
|
pubKey := bn256.NewSuiteG2().Point()
|
|
|
|
if err = pubKey.UnmarshalBinary(entry.DkgPubKey); err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal pubkey: %w", err)
|
|
|
|
}
|
2020-08-19 09:26:18 -07:00
|
|
|
dkgInstance.StorePubKey(entry.Addr, entry.ParticipantId, pubKey)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if err = dkgInstance.InitDKGInstance(); err != nil {
|
|
|
|
return fmt.Errorf("failed to init dkg instance: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dkgCommits := dkgInstance.GetCommits()
|
2020-08-19 04:48:42 -07:00
|
|
|
marshaledCommits := make([][]byte, 0, len(dkgCommits))
|
2020-08-18 11:52:04 -07:00
|
|
|
for _, commit := range dkgCommits {
|
|
|
|
commitBz, err := commit.MarshalBinary()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to marshal commits: %w", err)
|
|
|
|
}
|
2020-08-19 04:48:42 -07:00
|
|
|
marshaledCommits = append(marshaledCommits, commitBz)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
2020-08-19 04:48:42 -07:00
|
|
|
commitsBz, err := json.Marshal(marshaledCommits)
|
2020-08-18 11:52:04 -07:00
|
|
|
|
|
|
|
am.dkgInstances[o.DKGIdentifier] = dkgInstance
|
|
|
|
|
|
|
|
req := requests.DKGProposalCommitConfirmationRequest{
|
|
|
|
ParticipantId: dkgInstance.ParticipantID,
|
|
|
|
Commit: commitsBz,
|
|
|
|
CreatedAt: o.CreatedAt,
|
|
|
|
}
|
|
|
|
reqBz, err := json.Marshal(req)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to generate fsm request: %w", err)
|
|
|
|
}
|
2020-08-25 05:56:27 -07:00
|
|
|
|
2020-08-18 11:52:04 -07:00
|
|
|
o.Event = dkg_proposal_fsm.EventDKGCommitConfirmationReceived
|
2020-08-25 05:56:27 -07:00
|
|
|
o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz))
|
2020-08-18 11:52:04 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-08-25 05:56:27 -07:00
|
|
|
func (am *AirgappedMachine) handleStateDkgDealsAwaitConfirmations(o *client.Operation) error {
|
2020-08-18 11:52:04 -07:00
|
|
|
var (
|
|
|
|
payload responses.DKGProposalCommitParticipantResponse
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
dkgInstance, ok := am.dkgInstances[o.DKGIdentifier]
|
|
|
|
if !ok {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("dkg instance with identifier %s does not exist", o.DKGIdentifier)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if err = json.Unmarshal(o.Payload, &payload); err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to unmarshal payload: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, entry := range payload {
|
2020-08-19 04:48:42 -07:00
|
|
|
var commitsBz [][]byte
|
2020-08-21 09:50:30 -07:00
|
|
|
if err = json.Unmarshal(entry.DkgCommit, &commitsBz); err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to unmarshal commits: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
2020-08-19 04:48:42 -07:00
|
|
|
dkgCommits := make([]kyber.Point, 0, len(commitsBz))
|
|
|
|
for _, commitBz := range commitsBz {
|
2020-08-18 11:52:04 -07:00
|
|
|
commit := am.suite.Point()
|
2020-08-19 04:48:42 -07:00
|
|
|
if err = commit.UnmarshalBinary(commitBz); err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to unmarshal commit: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
dkgCommits = append(dkgCommits, commit)
|
|
|
|
}
|
2020-08-21 09:50:30 -07:00
|
|
|
dkgInstance.StoreCommits(entry.Addr, dkgCommits)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
deals, err := dkgInstance.GetDeals()
|
|
|
|
if err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to get deals: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
am.dkgInstances[o.DKGIdentifier] = dkgInstance
|
|
|
|
|
|
|
|
// deals variable is a map, so every key is an index of participant we should send a deal
|
|
|
|
for index, deal := range deals {
|
|
|
|
dealBz, err := json.Marshal(deal)
|
|
|
|
if err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to marshal deal: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
toParticipant := dkgInstance.GetParticipantByIndex(index)
|
|
|
|
encryptedDeal, err := am.encryptData(o.DKGIdentifier, toParticipant, dealBz)
|
|
|
|
if err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to encrypt deal: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
req := requests.DKGProposalDealConfirmationRequest{
|
|
|
|
ParticipantId: dkgInstance.ParticipantID,
|
|
|
|
Deal: encryptedDeal,
|
|
|
|
CreatedAt: o.CreatedAt,
|
|
|
|
}
|
|
|
|
o.To = toParticipant
|
|
|
|
reqBz, err := json.Marshal(req)
|
|
|
|
if err != nil {
|
2020-08-25 05:56:27 -07:00
|
|
|
return fmt.Errorf("failed to generate fsm request: %w", err)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
o.Event = dkg_proposal_fsm.EventDKGDealConfirmationReceived
|
2020-08-25 05:56:27 -07:00
|
|
|
o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz))
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
2020-08-25 05:56:27 -07:00
|
|
|
return nil
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (am *AirgappedMachine) handleStateDkgResponsesAwaitConfirmations(o *client.Operation) error {
|
|
|
|
var (
|
|
|
|
payload responses.DKGProposalDealParticipantResponse
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
dkgInstance, ok := am.dkgInstances[o.DKGIdentifier]
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("dkg instance with identifier %s does not exist", o.DKGIdentifier)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = json.Unmarshal(o.Payload, &payload); err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal payload: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, entry := range payload {
|
2020-08-21 09:50:30 -07:00
|
|
|
decryptedDealBz, err := am.decryptData(entry.DkgDeal)
|
2020-08-18 11:52:04 -07:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to decrypt deal: %w", err)
|
|
|
|
}
|
|
|
|
var deal dkgPedersen.Deal
|
|
|
|
if err = json.Unmarshal(decryptedDealBz, &deal); err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal deal")
|
|
|
|
}
|
2020-08-21 09:50:30 -07:00
|
|
|
dkgInstance.StoreDeal(entry.Addr, &deal)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
processedResponses, err := dkgInstance.ProcessDeals()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to process deals: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
am.dkgInstances[o.DKGIdentifier] = dkgInstance
|
|
|
|
|
|
|
|
responsesBz, err := json.Marshal(processedResponses)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to marshal deals")
|
|
|
|
}
|
|
|
|
|
|
|
|
req := requests.DKGProposalResponseConfirmationRequest{
|
|
|
|
ParticipantId: dkgInstance.ParticipantID,
|
|
|
|
Response: responsesBz,
|
|
|
|
CreatedAt: o.CreatedAt,
|
|
|
|
}
|
|
|
|
|
|
|
|
reqBz, err := json.Marshal(req)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to generate fsm request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
o.Event = dkg_proposal_fsm.EventDKGResponseConfirmationReceived
|
2020-08-25 05:56:27 -07:00
|
|
|
o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz))
|
2020-08-18 11:52:04 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (am *AirgappedMachine) handleStateDkgMasterKeyAwaitConfirmations(o *client.Operation) error {
|
|
|
|
var (
|
2020-08-21 09:50:30 -07:00
|
|
|
payload responses.DKGProposalResponseParticipantResponse
|
2020-08-18 11:52:04 -07:00
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
dkgInstance, ok := am.dkgInstances[o.DKGIdentifier]
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("dkg instance with identifier %s does not exist", o.DKGIdentifier)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = json.Unmarshal(o.Payload, &payload); err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal payload: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, entry := range payload {
|
|
|
|
var entryResponses []*dkgPedersen.Response
|
2020-08-21 09:50:30 -07:00
|
|
|
if err = json.Unmarshal(entry.DkgResponse, &entryResponses); err != nil {
|
2020-08-18 11:52:04 -07:00
|
|
|
return fmt.Errorf("failed to unmarshal responses: %w", err)
|
|
|
|
}
|
2020-08-21 09:50:30 -07:00
|
|
|
dkgInstance.StoreResponses(entry.Addr, entryResponses)
|
2020-08-18 11:52:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if err = dkgInstance.ProcessResponses(); err != nil {
|
|
|
|
return fmt.Errorf("failed to process responses: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
pubKey, err := dkgInstance.GetDistributedPublicKey()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get master pub key: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
masterPubKeyBz, err := pubKey.MarshalBinary()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to marshal master pub key: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
am.dkgInstances[o.DKGIdentifier] = dkgInstance
|
|
|
|
|
|
|
|
blsKeyring, err := dkgInstance.GetBLSKeyring()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get BLSKeyring: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = am.saveBLSKeyring(o.DKGIdentifier, blsKeyring); err != nil {
|
|
|
|
return fmt.Errorf("failed to save BLSKeyring: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
req := requests.DKGProposalMasterKeyConfirmationRequest{
|
|
|
|
ParticipantId: dkgInstance.ParticipantID,
|
|
|
|
MasterKey: masterPubKeyBz,
|
|
|
|
CreatedAt: o.CreatedAt,
|
|
|
|
}
|
|
|
|
reqBz, err := json.Marshal(req)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to generate fsm request: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
o.Event = dkg_proposal_fsm.EventDKGMasterKeyConfirmationReceived
|
2020-08-25 05:56:27 -07:00
|
|
|
o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz))
|
2020-08-24 07:41:15 -07:00
|
|
|
|
|
|
|
fmt.Println(dkgInstance.ParticipantID, pubKey.String())
|
|
|
|
|
2020-08-18 11:52:04 -07:00
|
|
|
return nil
|
|
|
|
}
|