mirror of https://github.com/certusone/dc4bc.git
Merge branch 'fsm-draft' into feat/airgapped-client-tests
This commit is contained in:
commit
826da7a0a6
|
@ -134,6 +134,8 @@ func (s DKGParticipantStatus) String() string {
|
|||
// Signing proposal
|
||||
|
||||
type SigningConfirmation struct {
|
||||
SigningId string
|
||||
InitiatorId int
|
||||
Quorum SigningProposalQuorum
|
||||
RecoveredKey []byte
|
||||
SrcPayload []byte
|
||||
|
@ -152,8 +154,7 @@ type SigningProposalQuorum map[int]*SigningProposalParticipant
|
|||
type SigningParticipantStatus uint8
|
||||
|
||||
const (
|
||||
SigningIdle SigningParticipantStatus = iota
|
||||
SigningAwaitConfirmation
|
||||
SigningAwaitConfirmation SigningParticipantStatus = iota
|
||||
SigningConfirmed
|
||||
SigningDeclined
|
||||
SigningAwaitPartialKeys
|
||||
|
@ -165,8 +166,6 @@ const (
|
|||
func (s SigningParticipantStatus) String() string {
|
||||
var str = "undefined"
|
||||
switch s {
|
||||
case SigningIdle:
|
||||
str = "SigningIdle"
|
||||
case SigningAwaitConfirmation:
|
||||
str = "SigningAwaitConfirmation"
|
||||
case SigningConfirmed:
|
||||
|
|
|
@ -2,10 +2,9 @@ package state_machines
|
|||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm"
|
||||
"strings"
|
||||
|
||||
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
|
||||
|
@ -16,10 +15,6 @@ import (
|
|||
"github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm"
|
||||
)
|
||||
|
||||
const (
|
||||
dkgTransactionIdLength = 128
|
||||
)
|
||||
|
||||
// Is machine state scope dump will be locked?
|
||||
type FSMDump struct {
|
||||
TransactionId string
|
||||
|
@ -32,17 +27,6 @@ type FSMInstance struct {
|
|||
dump *FSMDump
|
||||
}
|
||||
|
||||
var (
|
||||
fsmPoolProvider *fsm_pool.FSMPool
|
||||
)
|
||||
|
||||
func init() {
|
||||
fsmPoolProvider = fsm_pool.Init(
|
||||
signature_proposal_fsm.New(),
|
||||
dkg_proposal_fsm.New(),
|
||||
)
|
||||
}
|
||||
|
||||
// Create new fsm with unique id
|
||||
// transactionId required for unique identify dump
|
||||
func Create(dkgID string) (*FSMInstance, error) {
|
||||
|
@ -56,6 +40,12 @@ func Create(dkgID string) (*FSMInstance, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fsmPoolProvider := fsm_pool.Init(
|
||||
signature_proposal_fsm.New(),
|
||||
dkg_proposal_fsm.New(),
|
||||
signing_proposal_fsm.New(),
|
||||
)
|
||||
|
||||
machine, err := fsmPoolProvider.EntryPointMachine()
|
||||
i.machine = machine.(internal.DumpedMachineProvider)
|
||||
i.machine.SetUpPayload(i.dump.Payload)
|
||||
|
@ -80,7 +70,16 @@ func FromDump(data []byte) (*FSMInstance, error) {
|
|||
return nil, errors.New("cannot read machine dump")
|
||||
}
|
||||
|
||||
fsmPoolProvider := fsm_pool.Init(
|
||||
signature_proposal_fsm.New(),
|
||||
dkg_proposal_fsm.New(),
|
||||
signing_proposal_fsm.New(),
|
||||
)
|
||||
|
||||
machine, err := fsmPoolProvider.MachineByState(i.dump.State)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.machine = machine.(internal.DumpedMachineProvider)
|
||||
i.machine.SetUpPayload(i.dump.Payload)
|
||||
return i, err
|
||||
|
@ -173,13 +172,3 @@ func (d *FSMDump) Unmarshal(data []byte) error {
|
|||
|
||||
return json.Unmarshal(data, d)
|
||||
}
|
||||
|
||||
func generateDkgTransactionId() (string, error) {
|
||||
b := make([]byte, dkgTransactionIdLength)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.URLEncoding.EncodeToString(b), err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
sif "github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm"
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -379,6 +380,63 @@ func Test_SignatureProposal_Positive(t *testing.T) {
|
|||
}
|
||||
|
||||
compareState(t, dpf.StateDkgMasterKeyCollected, fsmResponse.State)
|
||||
|
||||
// Signing
|
||||
|
||||
testFSMInstance, err = FromDump(dump)
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
||||
compareFSMInstanceNotNil(t, testFSMInstance)
|
||||
|
||||
fsmResponse, dump, err = testFSMInstance.Do(sif.EventSigningInit, requests.DefaultRequest{
|
||||
CreatedAt: time.Now(),
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
||||
compareDumpNotZero(t, dump)
|
||||
|
||||
compareFSMResponseNotNil(t, fsmResponse)
|
||||
|
||||
compareState(t, sif.StateSigningIdle, fsmResponse.State)
|
||||
|
||||
// Start
|
||||
|
||||
testFSMInstance, err = FromDump(dump)
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
||||
compareFSMInstanceNotNil(t, testFSMInstance)
|
||||
|
||||
fsmResponse, dump, err = testFSMInstance.Do(sif.EventSigningStart, requests.SigningProposalStartRequest{
|
||||
ParticipantId: 1,
|
||||
SrcPayload: []byte("message to sign"),
|
||||
CreatedAt: time.Now(),
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
||||
compareDumpNotZero(t, dump)
|
||||
|
||||
compareFSMResponseNotNil(t, fsmResponse)
|
||||
|
||||
compareState(t, sif.StateSigningAwaitConfirmations, fsmResponse.State)
|
||||
|
||||
testSigningParticipantsListResponse, ok := fsmResponse.Data.(responses.SigningProposalParticipantInvitationsResponse)
|
||||
|
||||
if !ok {
|
||||
t.Fatalf("expected response {SigningProposalParticipantInvitationsResponse}")
|
||||
}
|
||||
|
||||
if len(testSigningParticipantsListResponse.Participants) != len(testParticipantsListRequest.Participants) {
|
||||
t.Fatalf("expected response len {%d}, got {%d}", len(testParticipantsListRequest.Participants), len(testSigningParticipantsListResponse.Participants))
|
||||
}
|
||||
|
||||
if testSigningParticipantsListResponse.SigningId == "" {
|
||||
t.Fatalf("expected field {SigningId}")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_DKGProposal_Positive(t *testing.T) {
|
||||
|
|
|
@ -116,11 +116,12 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
|
|||
case EventDeclineProposal:
|
||||
signatureProposalParticipant.Status = internal.SigConfirmationDeclined
|
||||
default:
|
||||
err = errors.New("undefined {Event} for action")
|
||||
err = errors.New(fmt.Sprintf("unsupported event for action {inEvent} = {\"%s\"}", inEvent))
|
||||
return
|
||||
}
|
||||
|
||||
signatureProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
m.payload.SignatureProposalPayload.UpdatedAt = request.CreatedAt
|
||||
|
||||
m.payload.SigQuorumUpdate(request.ParticipantId, signatureProposalParticipant)
|
||||
|
||||
|
@ -129,7 +130,7 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
|
|||
|
||||
func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
var (
|
||||
isContainsDeclined bool
|
||||
isContainsDecline bool
|
||||
)
|
||||
|
||||
m.payloadMu.Lock()
|
||||
|
@ -146,11 +147,11 @@ func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event
|
|||
if participant.Status == internal.SigConfirmationConfirmed {
|
||||
unconfirmedParticipants--
|
||||
} else if participant.Status == internal.SigConfirmationDeclined {
|
||||
isContainsDeclined = true
|
||||
isContainsDecline = true
|
||||
}
|
||||
}
|
||||
|
||||
if isContainsDeclined {
|
||||
if isContainsDecline {
|
||||
outEvent = eventSetValidationCanceledByParticipant
|
||||
return
|
||||
}
|
||||
|
@ -166,6 +167,7 @@ func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event
|
|||
responseEntry := &responses.SignatureProposalParticipantStatusEntry{
|
||||
ParticipantId: participantId,
|
||||
Addr: participant.Addr,
|
||||
DkgPubKey: participant.DkgPubKey,
|
||||
Status: uint8(participant.Status),
|
||||
}
|
||||
responseData = append(responseData, responseEntry)
|
||||
|
@ -184,6 +186,7 @@ func (m *SignatureProposalFSM) actionSignatureProposalCanceledByTimeout(inEvent
|
|||
responseEntry := &responses.SignatureProposalParticipantStatusEntry{
|
||||
ParticipantId: participantId,
|
||||
Addr: participant.Addr,
|
||||
DkgPubKey: participant.DkgPubKey,
|
||||
Status: uint8(participant.Status),
|
||||
}
|
||||
responseData = append(responseData, responseEntry)
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/internal"
|
||||
"github.com/depools/dc4bc/fsm/types/requests"
|
||||
"time"
|
||||
"github.com/depools/dc4bc/fsm/types/responses"
|
||||
)
|
||||
|
||||
func (m *SigningProposalFSM) actionInitSigningProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
|
@ -36,14 +36,6 @@ func (m *SigningProposalFSM) actionInitSigningProposal(inEvent fsm.Event, args .
|
|||
ExpiresAt: request.CreatedAt.Add(config.SigningConfirmationDeadline),
|
||||
}
|
||||
|
||||
for participantId, participant := range m.payload.SignatureProposalPayload.Quorum {
|
||||
m.payload.SigningProposalPayload.Quorum[participantId] = &internal.SigningProposalParticipant{
|
||||
Addr: participant.Addr,
|
||||
Status: internal.SigningIdle,
|
||||
UpdatedAt: participant.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -67,9 +59,47 @@ func (m *SigningProposalFSM) actionStartSigningProposal(inEvent fsm.Event, args
|
|||
return
|
||||
}
|
||||
|
||||
m.payload.SigningProposalPayload.SigningId, err = generateSigningId()
|
||||
|
||||
if err != nil {
|
||||
err = errors.New("cannot generate {SigningId}")
|
||||
return
|
||||
}
|
||||
|
||||
m.payload.SigningProposalPayload.InitiatorId = request.ParticipantId
|
||||
m.payload.SigningProposalPayload.SrcPayload = request.SrcPayload
|
||||
|
||||
m.payload.SigningProposalPayload.Quorum = make(internal.SigningProposalQuorum)
|
||||
|
||||
// Initialize new quorum
|
||||
for id, dkgEntry := range m.payload.DKGProposalPayload.Quorum {
|
||||
m.payload.SigningProposalPayload.Quorum[id] = &internal.SigningProposalParticipant{
|
||||
Addr: dkgEntry.Addr,
|
||||
Status: internal.SigningAwaitConfirmation,
|
||||
UpdatedAt: request.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
m.payload.SigningProposalPayload.Quorum[request.ParticipantId].Status = internal.SigningConfirmed
|
||||
m.payload.SigningProposalPayload.CreatedAt = request.CreatedAt
|
||||
|
||||
return
|
||||
// Make response
|
||||
|
||||
responseData := responses.SigningProposalParticipantInvitationsResponse{
|
||||
SigningId: m.payload.SigningProposalPayload.SigningId,
|
||||
InitiatorId: m.payload.SigningProposalPayload.InitiatorId,
|
||||
Participants: make([]*responses.SigningProposalParticipantInvitationEntry, 0),
|
||||
}
|
||||
|
||||
for participantId, proposal := range m.payload.SigningProposalPayload.Quorum {
|
||||
responseEntry := &responses.SigningProposalParticipantInvitationEntry{
|
||||
ParticipantId: participantId,
|
||||
Addr: proposal.Addr,
|
||||
}
|
||||
responseData.Participants = append(responseData.Participants, responseEntry)
|
||||
}
|
||||
|
||||
return inEvent, responseData, nil
|
||||
}
|
||||
|
||||
func (m *SigningProposalFSM) actionProposalResponseByParticipant(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
|
@ -105,9 +135,20 @@ func (m *SigningProposalFSM) actionProposalResponseByParticipant(inEvent fsm.Eve
|
|||
}
|
||||
|
||||
// copy(signingProposalParticipant.Commit, request.Commit)
|
||||
signingProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
switch inEvent {
|
||||
case EventConfirmSigningConfirmation:
|
||||
signingProposalParticipant.Status = internal.SigningConfirmed
|
||||
case EventDeclineSigningConfirmation:
|
||||
signingProposalParticipant.Status = internal.SigningDeclined
|
||||
default:
|
||||
err = errors.New(fmt.Sprintf("unsupported event for action {inEvent} = {\"%s\"}", inEvent))
|
||||
return
|
||||
}
|
||||
signingProposalParticipant.Status = internal.SigningConfirmed
|
||||
|
||||
signingProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
m.payload.SigningProposalPayload.UpdatedAt = request.CreatedAt
|
||||
|
||||
m.payload.SigningQuorumUpdate(request.ParticipantId, signingProposalParticipant)
|
||||
|
||||
return
|
||||
|
@ -115,35 +156,27 @@ func (m *SigningProposalFSM) actionProposalResponseByParticipant(inEvent fsm.Eve
|
|||
|
||||
func (m *SigningProposalFSM) actionValidateSigningProposalConfirmations(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
var (
|
||||
isContainsError, isContainsExpired bool
|
||||
isContainsDecline bool
|
||||
)
|
||||
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
tm := time.Now()
|
||||
|
||||
unconfirmedParticipants := m.payload.SigningQuorumCount()
|
||||
for _, participant := range m.payload.SigningProposalPayload.Quorum {
|
||||
if participant.Status == internal.SigningAwaitConfirmation {
|
||||
if participant.UpdatedAt.Add(config.SigningConfirmationDeadline).Before(tm) {
|
||||
isContainsExpired = true
|
||||
}
|
||||
} else {
|
||||
if participant.Status == internal.SigningDeclined {
|
||||
isContainsError = true
|
||||
} else if participant.Status == internal.SigningConfirmed {
|
||||
unconfirmedParticipants--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isContainsError {
|
||||
outEvent = eventSetSigningConfirmCanceledByTimeoutInternal
|
||||
if m.payload.SigningProposalPayload.IsExpired() {
|
||||
outEvent = eventSetSigningConfirmCanceledByParticipantInternal
|
||||
return
|
||||
}
|
||||
|
||||
if isContainsExpired {
|
||||
unconfirmedParticipants := m.payload.SigningQuorumCount()
|
||||
for _, participant := range m.payload.SigningProposalPayload.Quorum {
|
||||
if participant.Status == internal.SigningDeclined {
|
||||
isContainsDecline = true
|
||||
} else if participant.Status == internal.SigningConfirmed {
|
||||
unconfirmedParticipants--
|
||||
}
|
||||
}
|
||||
|
||||
if isContainsDecline {
|
||||
outEvent = eventSetSigningConfirmCanceledByParticipantInternal
|
||||
return
|
||||
}
|
||||
|
@ -161,3 +194,150 @@ func (m *SigningProposalFSM) actionValidateSigningProposalConfirmations(inEvent
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
func (m *SigningProposalFSM) actionPartialKeyConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
if len(args) != 1 {
|
||||
err = errors.New("{arg0} required {SigningProposalPartialKeyRequest}")
|
||||
return
|
||||
}
|
||||
|
||||
request, ok := args[0].(requests.SigningProposalPartialKeyRequest)
|
||||
|
||||
if !ok {
|
||||
err = errors.New("cannot cast {arg0} to type {SigningProposalPartialKeyRequest}")
|
||||
return
|
||||
}
|
||||
|
||||
if err = request.Validate(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !m.payload.SigningQuorumExists(request.ParticipantId) {
|
||||
err = errors.New("{ParticipantId} not exist in quorum")
|
||||
return
|
||||
}
|
||||
|
||||
signingProposalParticipant := m.payload.SigningQuorumGet(request.ParticipantId)
|
||||
|
||||
if signingProposalParticipant.Status != internal.SigningAwaitPartialKeys {
|
||||
err = errors.New(fmt.Sprintf("cannot confirm response with {Status} = {\"%s\"}", signingProposalParticipant.Status))
|
||||
return
|
||||
}
|
||||
|
||||
copy(signingProposalParticipant.PartialKey, request.PartialKey)
|
||||
signingProposalParticipant.Status = internal.SigningPartialKeysConfirmed
|
||||
|
||||
signingProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
m.payload.SignatureProposalPayload.UpdatedAt = request.CreatedAt
|
||||
|
||||
m.payload.SigningQuorumUpdate(request.ParticipantId, signingProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (m *SigningProposalFSM) actionValidateSigningPartialKeyAwaitConfirmations(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
var (
|
||||
isContainsError bool
|
||||
)
|
||||
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
if m.payload.SigningProposalPayload.IsExpired() {
|
||||
outEvent = eventSigningPartialKeyCancelByTimeoutInternal
|
||||
return
|
||||
}
|
||||
|
||||
unconfirmedParticipants := m.payload.SigningQuorumCount()
|
||||
for _, participant := range m.payload.SigningProposalPayload.Quorum {
|
||||
if participant.Status == internal.SigningError {
|
||||
isContainsError = true
|
||||
} else if participant.Status == internal.SigningPartialKeysConfirmed {
|
||||
unconfirmedParticipants--
|
||||
}
|
||||
}
|
||||
|
||||
if isContainsError {
|
||||
outEvent = eventSigningPartialKeyCancelByErrorInternal
|
||||
return
|
||||
}
|
||||
|
||||
// The are no declined and timed out participants, check for all confirmations
|
||||
if unconfirmedParticipants > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
outEvent = eventSigningPartialKeysConfirmedInternal
|
||||
|
||||
for _, participant := range m.payload.SigningProposalPayload.Quorum {
|
||||
participant.Status = internal.SigningProcess
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Errors
|
||||
func (m *SigningProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
if len(args) != 1 {
|
||||
err = errors.New("{arg0} required {SignatureProposalConfirmationErrorRequest}")
|
||||
return
|
||||
}
|
||||
|
||||
request, ok := args[0].(requests.SignatureProposalConfirmationErrorRequest)
|
||||
|
||||
if !ok {
|
||||
err = errors.New("cannot cast {arg0} to type {SignatureProposalConfirmationErrorRequest}")
|
||||
return
|
||||
}
|
||||
|
||||
if err = request.Validate(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !m.payload.SigningQuorumExists(request.ParticipantId) {
|
||||
err = errors.New("{ParticipantId} not exist in quorum")
|
||||
return
|
||||
}
|
||||
|
||||
signingProposalParticipant := m.payload.SigningQuorumGet(request.ParticipantId)
|
||||
|
||||
// TODO: Move to methods
|
||||
switch inEvent {
|
||||
case EventSigningPartialKeyError:
|
||||
switch signingProposalParticipant.Status {
|
||||
case internal.SigningAwaitPartialKeys:
|
||||
signingProposalParticipant.Status = internal.SigningError
|
||||
case internal.SigningPartialKeysConfirmed:
|
||||
err = errors.New("{Status} already confirmed")
|
||||
case internal.SigningError:
|
||||
err = errors.New(fmt.Sprintf("{Status} already has {\"%s\"}", internal.SigningError))
|
||||
default:
|
||||
err = errors.New(fmt.Sprintf(
|
||||
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
||||
signingProposalParticipant.Status,
|
||||
internal.SigningError,
|
||||
))
|
||||
}
|
||||
default:
|
||||
err = errors.New(fmt.Sprintf("{%s} event cannot be used for action {actionConfirmationError}", inEvent))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
signingProposalParticipant.Error = request.Error
|
||||
|
||||
signingProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
m.payload.SignatureProposalPayload.UpdatedAt = request.CreatedAt
|
||||
|
||||
m.payload.SigningQuorumUpdate(request.ParticipantId, signingProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package signing_proposal_fsm
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
const (
|
||||
dkgTransactionIdLength = 128
|
||||
)
|
||||
|
||||
func generateSigningId() (string, error) {
|
||||
b := make([]byte, dkgTransactionIdLength)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base64.URLEncoding.EncodeToString(b), err
|
||||
}
|
|
@ -28,10 +28,6 @@ const (
|
|||
|
||||
StateSigningPartialKeysCollected = fsm.State("state_signing_partial_signatures_collected")
|
||||
|
||||
// await full
|
||||
|
||||
//
|
||||
|
||||
// Events
|
||||
|
||||
EventSigningInit = fsm.Event("event_signing_init")
|
||||
|
@ -49,7 +45,7 @@ const (
|
|||
eventSigningPartialKeyCancelByTimeoutInternal = fsm.Event("event_signing_partial_key_canceled_by_timeout_internal")
|
||||
eventSigningPartialKeyCancelByErrorInternal = fsm.Event("event_signing_partial_key_canceled_by_error_internal")
|
||||
eventSigningPartialKeysConfirmedInternal = fsm.Event("event_signing_partial_keys_confirmed_internal")
|
||||
EventSigningFinish = fsm.Event("event_signing_finish")
|
||||
EventSigningRestart = fsm.Event("event_signing_restart")
|
||||
)
|
||||
|
||||
type SigningProposalFSM struct {
|
||||
|
@ -82,7 +78,7 @@ func New() internal.DumpedMachineProvider {
|
|||
// Validate
|
||||
{Name: eventAutoValidateProposalInternal, SrcState: []fsm.State{StateSigningAwaitConfirmations}, DstState: StateSigningAwaitConfirmations, IsInternal: true, IsAuto: true},
|
||||
|
||||
{Name: eventSetProposalValidatedInternal, SrcState: []fsm.State{StateSigningAwaitConfirmations}, DstState: StateSigningAwaitConfirmations, IsInternal: true, IsAuto: true},
|
||||
{Name: eventSetProposalValidatedInternal, SrcState: []fsm.State{StateSigningAwaitConfirmations}, DstState: StateSigningAwaitPartialKeys, IsInternal: true},
|
||||
|
||||
// Canceled
|
||||
{Name: EventSigningPartialKeyReceived, SrcState: []fsm.State{StateSigningAwaitPartialKeys}, DstState: StateSigningAwaitPartialKeys},
|
||||
|
@ -92,10 +88,17 @@ func New() internal.DumpedMachineProvider {
|
|||
|
||||
{Name: eventSigningPartialKeysConfirmedInternal, SrcState: []fsm.State{StateSigningAwaitPartialKeys}, DstState: StateSigningPartialKeysCollected, IsInternal: true},
|
||||
|
||||
{Name: EventSigningFinish, SrcState: []fsm.State{StateSigningPartialKeysCollected}, DstState: StateSigningIdle, IsInternal: true},
|
||||
{Name: EventSigningRestart, SrcState: []fsm.State{StateSigningPartialKeysCollected}, DstState: StateSigningIdle, IsInternal: true},
|
||||
},
|
||||
fsm.Callbacks{
|
||||
EventSigningInit: machine.actionInitSigningProposal,
|
||||
EventSigningInit: machine.actionInitSigningProposal,
|
||||
EventSigningStart: machine.actionStartSigningProposal,
|
||||
EventConfirmSigningConfirmation: machine.actionProposalResponseByParticipant,
|
||||
EventDeclineSigningConfirmation: machine.actionProposalResponseByParticipant,
|
||||
eventAutoValidateProposalInternal: machine.actionValidateSigningProposalConfirmations,
|
||||
EventSigningPartialKeyReceived: machine.actionPartialKeyConfirmationReceived,
|
||||
EventSigningPartialKeyError: machine.actionValidateSigningPartialKeyAwaitConfirmations,
|
||||
// actionConfirmationError
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -23,7 +23,12 @@ type SignatureProposalParticipantsEntry struct {
|
|||
// Events: "event_sig_proposal_confirm_by_participant"
|
||||
// "event_sig_proposal_decline_by_participant"
|
||||
type SignatureProposalParticipantRequest struct {
|
||||
// Key for link invitations to participants
|
||||
ParticipantId int
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type SignatureProposalConfirmationErrorRequest struct {
|
||||
ParticipantId int
|
||||
Error error
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
|
|
@ -55,3 +55,19 @@ func (r *SignatureProposalParticipantRequest) Validate() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SignatureProposalConfirmationErrorRequest) Validate() error {
|
||||
if r.ParticipantId < 0 {
|
||||
return errors.New("{ParticipantId} cannot be a negative number")
|
||||
}
|
||||
|
||||
if r.Error == nil {
|
||||
return errors.New("{Error} cannot be a nil")
|
||||
}
|
||||
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ type SigningProposalStartRequest struct {
|
|||
// Events: "event_signing_proposal_confirm_by_participant"
|
||||
// "event_signing_proposal_decline_by_participant"
|
||||
type SigningProposalParticipantRequest struct {
|
||||
SigningId string
|
||||
ParticipantId int
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
@ -21,6 +22,7 @@ type SigningProposalParticipantRequest struct {
|
|||
// States: "state_signing_await_partial_keys"
|
||||
// Events: "event_signing_partial_key_received"
|
||||
type SigningProposalPartialKeyRequest struct {
|
||||
SigningId string
|
||||
ParticipantId int
|
||||
PartialKey []byte
|
||||
CreatedAt time.Time
|
||||
|
|
|
@ -19,6 +19,10 @@ func (r *SigningProposalStartRequest) Validate() error {
|
|||
}
|
||||
|
||||
func (r *SigningProposalParticipantRequest) Validate() error {
|
||||
if r.SigningId == "" {
|
||||
return errors.New("{SigningId} cannot be empty")
|
||||
}
|
||||
|
||||
if r.ParticipantId < 0 {
|
||||
return errors.New("{ParticipantId} cannot be a negative number")
|
||||
}
|
||||
|
@ -31,6 +35,10 @@ func (r *SigningProposalParticipantRequest) Validate() error {
|
|||
}
|
||||
|
||||
func (r *SigningProposalPartialKeyRequest) Validate() error {
|
||||
if r.SigningId == "" {
|
||||
return errors.New("{SigningId} cannot be empty")
|
||||
}
|
||||
|
||||
if r.ParticipantId < 0 {
|
||||
return errors.New("{ParticipantId} cannot be a negative number")
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ type SignatureProposalParticipantStatusResponse []*SignatureProposalParticipantS
|
|||
type SignatureProposalParticipantStatusEntry struct {
|
||||
ParticipantId int
|
||||
Addr string
|
||||
DkgPubKey []byte
|
||||
Status uint8
|
||||
DkgPubKey []byte
|
||||
}
|
||||
|
|
|
@ -1 +1,20 @@
|
|||
package responses
|
||||
|
||||
type SigningProposalParticipantInvitationsResponse struct {
|
||||
InitiatorId int
|
||||
Participants []*SigningProposalParticipantInvitationEntry
|
||||
SigningId string
|
||||
}
|
||||
|
||||
type SigningProposalParticipantInvitationEntry struct {
|
||||
ParticipantId int
|
||||
Addr string
|
||||
}
|
||||
|
||||
type SigningProposalParticipantStatusResponse []*SignatureProposalParticipantStatusEntry
|
||||
|
||||
type SigningProposalParticipantStatusEntry struct {
|
||||
ParticipantId int
|
||||
Addr string
|
||||
Status uint8
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue