mirror of https://github.com/certusone/dc4bc.git
feat: airgapped state
This commit is contained in:
parent
f3684b0914
commit
eeb8e908fd
|
@ -8,6 +8,8 @@ import (
|
|||
"os"
|
||||
"sync"
|
||||
|
||||
bls12381 "github.com/depools/kyber-bls12381"
|
||||
|
||||
vss "github.com/corestario/kyber/share/vss/rabin"
|
||||
|
||||
"github.com/corestario/kyber"
|
||||
|
@ -20,7 +22,6 @@ import (
|
|||
"github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm"
|
||||
"github.com/depools/dc4bc/fsm/types/requests"
|
||||
"github.com/depools/dc4bc/qr"
|
||||
bls12381 "github.com/depools/kyber-bls12381"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
|
@ -28,6 +29,7 @@ const (
|
|||
resultQRFolder = "result_qr_codes"
|
||||
pubKeyDBKey = "public_key"
|
||||
privateKeyDBKey = "private_key"
|
||||
operationsLogDBKey = "operations_log"
|
||||
participantAddressKey = "participant_address"
|
||||
saltKey = "salt_key"
|
||||
)
|
||||
|
@ -44,6 +46,7 @@ type AirgappedMachine struct {
|
|||
pubKey kyber.Point
|
||||
secKey kyber.Scalar
|
||||
suite vss.Suite
|
||||
seed []byte
|
||||
|
||||
db *leveldb.DB
|
||||
}
|
||||
|
@ -64,19 +67,120 @@ func NewAirgappedMachine(dbPath string) (*AirgappedMachine, error) {
|
|||
qrProcessor: qr.NewCameraProcessor(),
|
||||
}
|
||||
|
||||
am.suite = bls12381.NewBLS12381Suite()
|
||||
|
||||
if am.db, err = leveldb.OpenFile(dbPath, nil); err != nil {
|
||||
return nil, fmt.Errorf("failed to open db file %s for keys: %w", dbPath, err)
|
||||
}
|
||||
|
||||
seed, err := am.getSeed()
|
||||
if err != nil {
|
||||
seed = make([]byte, 32)
|
||||
_, _ = rand.Read(seed)
|
||||
if err := am.storeSeed(seed); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
am.seed = seed
|
||||
am.suite = bls12381.NewBLS12381Suite(am.seed)
|
||||
|
||||
if err = am.loadAddressFromDB(dbPath); err != nil {
|
||||
return nil, fmt.Errorf("failed to load address from db")
|
||||
}
|
||||
|
||||
if _, err = am.db.Get([]byte(operationsLogDBKey), nil); err != nil {
|
||||
if err == leveldb.ErrNotFound {
|
||||
operationsLogBz, _ := json.Marshal([]client.Operation{})
|
||||
if err := am.db.Put([]byte(operationsLogDBKey), operationsLogBz, nil); err != nil {
|
||||
return nil, fmt.Errorf("failed to init Operation log: %w", err)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to init Operation log (fatal): %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return am, nil
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) storeSeed(seed []byte) error {
|
||||
if err := am.db.Put([]byte("seedKey"), seed, nil); err != nil {
|
||||
return fmt.Errorf("failed to put seed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) getSeed() ([]byte, error) {
|
||||
seed, err := am.db.Get([]byte("seedKey"), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get seed: %w", err)
|
||||
}
|
||||
|
||||
return seed, nil
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) storeOperation(o client.Operation) error {
|
||||
operationsLogBz, err := am.db.Get([]byte(operationsLogDBKey), nil)
|
||||
if err != nil {
|
||||
if err == leveldb.ErrNotFound {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("failed to get operationsLogBz from db: %w", err)
|
||||
}
|
||||
|
||||
var operationsLog []client.Operation
|
||||
if err := json.Unmarshal(operationsLogBz, &operationsLog); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal stored operationsLog: %w", err)
|
||||
}
|
||||
|
||||
operationsLog = append(operationsLog, o)
|
||||
|
||||
operationsLogBz, err = json.Marshal(operationsLog)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal operationsLog: %w", err)
|
||||
}
|
||||
|
||||
if err := am.db.Put([]byte(operationsLogDBKey), operationsLogBz, nil); err != nil {
|
||||
return fmt.Errorf("failed to put updated operationsLog: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) getOperationsLog() ([]client.Operation, error) {
|
||||
operationsLogBz, err := am.db.Get([]byte(operationsLogDBKey), nil)
|
||||
if err != nil {
|
||||
if err == leveldb.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get public key from db: %w", err)
|
||||
}
|
||||
|
||||
var operationsLog []client.Operation
|
||||
if err := json.Unmarshal(operationsLogBz, &operationsLog); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal stored operationsLog: %w", err)
|
||||
}
|
||||
|
||||
return operationsLog, nil
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) ReplayOperationsLog() error {
|
||||
operationsLog, err := am.getOperationsLog()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to getOperationsLog: %w", err)
|
||||
}
|
||||
|
||||
for _, operation := range operationsLog {
|
||||
if _, err := am.HandleOperation(operation); err != nil {
|
||||
return fmt.Errorf(
|
||||
"failed to HandleOperation %s (this error is fatal, the state can not be recovered): %w",
|
||||
operation.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Successfully replayed Operation log")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) InitKeys() error {
|
||||
err := am.LoadKeysFromDB()
|
||||
if err != nil && err != leveldb.ErrNotFound {
|
||||
|
@ -147,6 +251,7 @@ func (am *AirgappedMachine) LoadKeysFromDB() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
decryptedPrivateKey, err := decrypt(am.encryptionKey, salt, privateKeyBz)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -263,6 +368,14 @@ func (am *AirgappedMachine) decryptDataFromParticipant(data []byte) ([]byte, err
|
|||
}
|
||||
|
||||
func (am *AirgappedMachine) HandleOperation(operation client.Operation) (client.Operation, error) {
|
||||
if err := am.storeOperation(operation); err != nil {
|
||||
return client.Operation{}, fmt.Errorf("failed to storeOperation: %w", err)
|
||||
}
|
||||
|
||||
return am.handleOperation(operation)
|
||||
}
|
||||
|
||||
func (am *AirgappedMachine) handleOperation(operation client.Operation) (client.Operation, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
client "github.com/depools/dc4bc/client/types"
|
||||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
|
||||
|
@ -311,12 +313,261 @@ func TestAirgappedAllSteps(t *testing.T) {
|
|||
fmt.Println("DKG succeeded, signature recovered")
|
||||
}
|
||||
|
||||
func TestAirgappedMachine_Replay(t *testing.T) {
|
||||
testDir := "/tmp/airgapped_test"
|
||||
nodesCount := 2
|
||||
threshold := 2
|
||||
participants := make([]string, nodesCount)
|
||||
for i := 0; i < nodesCount; i++ {
|
||||
participants[i] = fmt.Sprintf("Participant#%d", i)
|
||||
}
|
||||
|
||||
tr := &Transport{}
|
||||
for i := 0; i < nodesCount; i++ {
|
||||
am, err := NewAirgappedMachine(fmt.Sprintf("%s/%s-%d", testDir, testDB, i))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create airgapped machine: %v", err)
|
||||
}
|
||||
am.SetAddress(participants[i])
|
||||
am.SetEncryptionKey([]byte(fmt.Sprintf(testDB+"%d", i)))
|
||||
if err = am.InitKeys(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
node := Node{
|
||||
ParticipantID: i,
|
||||
Participant: participants[i],
|
||||
Machine: am,
|
||||
}
|
||||
tr.nodes = append(tr.nodes, &node)
|
||||
}
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
var initReq responses.SignatureProposalParticipantInvitationsResponse
|
||||
for _, n := range tr.nodes {
|
||||
pubKey, err := n.Machine.pubKey.MarshalBinary()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal dkg pubkey: %v", err)
|
||||
}
|
||||
entry := &responses.SignatureProposalParticipantInvitationEntry{
|
||||
ParticipantId: n.ParticipantID,
|
||||
Addr: n.Participant,
|
||||
Threshold: threshold,
|
||||
DkgPubKey: pubKey,
|
||||
}
|
||||
initReq = append(initReq, entry)
|
||||
}
|
||||
op := createOperation(t, string(signature_proposal_fsm.StateAwaitParticipantsConfirmations), "", initReq)
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
_, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
})
|
||||
|
||||
// get commits
|
||||
var getCommitsRequest responses.DKGProposalPubKeysParticipantResponse
|
||||
for _, n := range tr.nodes {
|
||||
pubKey, err := n.Machine.pubKey.MarshalBinary()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to marshal pubkey: %v", n.Participant, err)
|
||||
}
|
||||
entry := &responses.DKGProposalPubKeysParticipantEntry{
|
||||
ParticipantId: n.ParticipantID,
|
||||
Addr: n.Participant,
|
||||
DkgPubKey: pubKey,
|
||||
}
|
||||
getCommitsRequest = append(getCommitsRequest, entry)
|
||||
}
|
||||
op = createOperation(t, string(dkg_proposal_fsm.StateDkgCommitsAwaitConfirmations), "", getCommitsRequest)
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
operation, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
for _, msg := range operation.ResultMsgs {
|
||||
tr.BroadcastMessage(t, msg)
|
||||
}
|
||||
})
|
||||
|
||||
//deals
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var payload responses.DKGProposalCommitParticipantResponse
|
||||
for _, req := range n.commits {
|
||||
p := responses.DKGProposalCommitParticipantEntry{
|
||||
ParticipantId: req.ParticipantId,
|
||||
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
|
||||
DkgCommit: req.Commit,
|
||||
}
|
||||
payload = append(payload, &p)
|
||||
}
|
||||
op := createOperation(t, string(dkg_proposal_fsm.StateDkgDealsAwaitConfirmations), "", payload)
|
||||
|
||||
operation, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
for _, msg := range operation.ResultMsgs {
|
||||
tr.BroadcastMessage(t, msg)
|
||||
}
|
||||
})
|
||||
|
||||
// At this point something goes wrong and we have to restart the machines.
|
||||
for _, node := range tr.nodes {
|
||||
_ = node.Machine.db.Close()
|
||||
}
|
||||
|
||||
participants = make([]string, nodesCount)
|
||||
for i := 0; i < nodesCount; i++ {
|
||||
participants[i] = fmt.Sprintf("Participant#%d", i)
|
||||
}
|
||||
|
||||
newTr := &Transport{}
|
||||
for i := 0; i < nodesCount; i++ {
|
||||
am, err := NewAirgappedMachine(fmt.Sprintf("%s/%s-%d", testDir, testDB, i))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create airgapped machine: %v", err)
|
||||
}
|
||||
_ = am.SetAddress(participants[i])
|
||||
am.SetEncryptionKey([]byte(fmt.Sprintf(testDB+"%d", i)))
|
||||
if err = am.InitKeys(); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
node := Node{
|
||||
ParticipantID: i,
|
||||
Participant: participants[i],
|
||||
Machine: am,
|
||||
deals: tr.nodes[i].deals,
|
||||
}
|
||||
newTr.nodes = append(newTr.nodes, &node)
|
||||
}
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
for _, node := range newTr.nodes {
|
||||
err := node.Machine.ReplayOperationsLog()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
//oldTr := tr
|
||||
tr = newTr
|
||||
|
||||
//responses
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var payload responses.DKGProposalDealParticipantResponse
|
||||
for _, req := range n.deals {
|
||||
p := responses.DKGProposalDealParticipantEntry{
|
||||
ParticipantId: req.ParticipantId,
|
||||
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
|
||||
DkgDeal: req.Deal,
|
||||
}
|
||||
payload = append(payload, &p)
|
||||
}
|
||||
op := createOperation(t, string(dkg_proposal_fsm.StateDkgResponsesAwaitConfirmations), "", payload)
|
||||
|
||||
operation, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
for _, msg := range operation.ResultMsgs {
|
||||
tr.BroadcastMessage(t, msg)
|
||||
}
|
||||
})
|
||||
|
||||
//master key
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var payload responses.DKGProposalResponseParticipantResponse
|
||||
for _, req := range n.responses {
|
||||
p := responses.DKGProposalResponseParticipantEntry{
|
||||
ParticipantId: req.ParticipantId,
|
||||
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
|
||||
DkgResponse: req.Response,
|
||||
}
|
||||
payload = append(payload, &p)
|
||||
}
|
||||
op := createOperation(t, string(dkg_proposal_fsm.StateDkgMasterKeyAwaitConfirmations), "", payload)
|
||||
|
||||
operation, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
for _, msg := range operation.ResultMsgs {
|
||||
tr.BroadcastMessage(t, msg)
|
||||
}
|
||||
})
|
||||
|
||||
// check that all master keys are equal
|
||||
for _, n := range tr.nodes {
|
||||
for i := 0; i < len(n.masterKeys); i++ {
|
||||
if !bytes.Equal(n.masterKeys[0].MasterKey, n.masterKeys[i].MasterKey) {
|
||||
t.Fatalf("master keys is not equal!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msgToSign := []byte("i am a message")
|
||||
|
||||
//partialSigns
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
payload := responses.SigningPartialSignsParticipantInvitationsResponse{
|
||||
SrcPayload: msgToSign,
|
||||
}
|
||||
|
||||
op := createOperation(t, string(signing_proposal_fsm.StateSigningAwaitPartialSigns), "", payload)
|
||||
|
||||
operation, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
for _, msg := range operation.ResultMsgs {
|
||||
tr.BroadcastMessage(t, msg)
|
||||
}
|
||||
})
|
||||
|
||||
//recover full signature
|
||||
runStep(tr, func(n *Node, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
|
||||
var payload responses.SigningProcessParticipantResponse
|
||||
for _, req := range n.partialSigns {
|
||||
p := responses.SigningProcessParticipantEntry{
|
||||
ParticipantId: req.ParticipantId,
|
||||
Addr: fmt.Sprintf("Participant#%d", req.ParticipantId),
|
||||
PartialSign: req.PartialSign,
|
||||
}
|
||||
payload.Participants = append(payload.Participants, &p)
|
||||
}
|
||||
payload.SrcPayload = msgToSign
|
||||
op := createOperation(t, string(signing_proposal_fsm.StateSigningPartialSignsCollected), "", payload)
|
||||
|
||||
operation, err := n.Machine.HandleOperation(op)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err)
|
||||
}
|
||||
for _, msg := range operation.ResultMsgs {
|
||||
tr.BroadcastMessage(t, msg)
|
||||
}
|
||||
})
|
||||
|
||||
fmt.Println("DKG succeeded, signature recovered")
|
||||
}
|
||||
|
||||
func runStep(transport *Transport, cb func(n *Node, wg *sync.WaitGroup)) {
|
||||
var wg = &sync.WaitGroup{}
|
||||
for _, node := range transport.nodes {
|
||||
wg.Add(1)
|
||||
n := node
|
||||
go cb(n, wg)
|
||||
cb(n, wg)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
"github.com/depools/dc4bc/fsm/types/requests"
|
||||
"github.com/depools/dc4bc/fsm/types/responses"
|
||||
"github.com/depools/dc4bc/storage"
|
||||
bls12381 "github.com/depools/kyber-bls12381"
|
||||
)
|
||||
|
||||
func createMessage(o client.Operation, data []byte) storage.Message {
|
||||
|
@ -97,14 +96,14 @@ func (am *AirgappedMachine) handleStateDkgCommitsAwaitConfirmations(o *client.Op
|
|||
}
|
||||
|
||||
for _, entry := range payload {
|
||||
pubKey := bls12381.NewBLS12381Suite().Point()
|
||||
pubKey := am.suite.Point()
|
||||
if err = pubKey.UnmarshalBinary(entry.DkgPubKey); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal pubkey: %w", err)
|
||||
}
|
||||
dkgInstance.StorePubKey(entry.Addr, entry.ParticipantId, pubKey)
|
||||
}
|
||||
|
||||
if err = dkgInstance.InitDKGInstance(); err != nil {
|
||||
if err = dkgInstance.InitDKGInstance(am.seed); err != nil {
|
||||
return fmt.Errorf("failed to init dkg instance: %w", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,10 @@ package airgapped
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/depools/dc4bc/dkg"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -57,7 +58,7 @@ func (am *AirgappedMachine) loadBLSKeyring(dkgID string) (*dkg.BLSKeyring, error
|
|||
return nil, fmt.Errorf("failed to decrypt BLS keyring: %w", err)
|
||||
}
|
||||
|
||||
if blsKeyring, err = dkg.LoadBLSKeyringFromBytes(decryptedKeyring); err != nil {
|
||||
if blsKeyring, err = dkg.LoadBLSKeyringFromBytes(am.suite, decryptedKeyring); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode bls keyring")
|
||||
}
|
||||
return blsKeyring, nil
|
||||
|
@ -85,7 +86,7 @@ func (am *AirgappedMachine) GetBLSKeyrings() (map[string]*dkg.BLSKeyring, error)
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decrypt BLS keyring: %w", err)
|
||||
}
|
||||
if blsKeyring, err = dkg.LoadBLSKeyringFromBytes(decryptedKeyring); err != nil {
|
||||
if blsKeyring, err = dkg.LoadBLSKeyringFromBytes(am.suite, decryptedKeyring); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode bls keyring: %w", err)
|
||||
}
|
||||
keyrings[strings.TrimLeft(string(key), blsKeyringPrefix)] = blsKeyring
|
||||
|
|
31
dkg/dkg.go
31
dkg/dkg.go
|
@ -7,11 +7,12 @@ import (
|
|||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/corestario/kyber/share"
|
||||
|
||||
"github.com/corestario/kyber"
|
||||
"github.com/corestario/kyber/share"
|
||||
dkg "github.com/corestario/kyber/share/dkg/pedersen"
|
||||
vss "github.com/corestario/kyber/share/vss/pedersen"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"lukechampine.com/frand"
|
||||
)
|
||||
|
||||
// TODO: dump necessary data on disk
|
||||
|
@ -46,6 +47,26 @@ func Init(suite vss.Suite, pubKey kyber.Point, secKey kyber.Scalar) *DKG {
|
|||
return &d
|
||||
}
|
||||
|
||||
func (d *DKG) Equals(other *DKG) error {
|
||||
for addr, commits := range d.commits {
|
||||
otherCommits := other.commits[addr]
|
||||
for idx := range commits {
|
||||
if !commits[idx].Equal(otherCommits[idx]) {
|
||||
return fmt.Errorf("commits from %s are not equal (idx %d): %v != %v", addr, idx, commits[idx], otherCommits[idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for addr, deal := range d.deals {
|
||||
otherDeal := other.deals[addr]
|
||||
if !cmp.Equal(deal.Deal, otherDeal.Deal) {
|
||||
return fmt.Errorf("deals from %s are not equal: %+v != %+v", addr, deal.Deal, otherDeal.Deal)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DKG) GetPubKey() kyber.Point {
|
||||
return d.pubKey
|
||||
}
|
||||
|
@ -90,7 +111,7 @@ func (d *DKG) calcParticipantID() int {
|
|||
return -1
|
||||
}
|
||||
|
||||
func (d *DKG) InitDKGInstance() (err error) {
|
||||
func (d *DKG) InitDKGInstance(seed []byte) (err error) {
|
||||
sort.Sort(d.pubkeys)
|
||||
|
||||
publicKeys := d.pubkeys.GetPKs()
|
||||
|
@ -107,7 +128,9 @@ func (d *DKG) InitDKGInstance() (err error) {
|
|||
|
||||
d.responses = newMessageStore(int(math.Pow(float64(participantsCount)-1, 2)))
|
||||
|
||||
d.instance, err = dkg.NewDistKeyGenerator(d.suite, d.secKey, publicKeys, d.Threshold)
|
||||
reader := frand.NewCustom(seed, 32, 20)
|
||||
|
||||
d.instance, err = dkg.NewDistKeyGenerator(d.suite, d.secKey, publicKeys, d.Threshold, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
10
dkg/types.go
10
dkg/types.go
|
@ -7,10 +7,10 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/corestario/kyber/pairing"
|
||||
vss "github.com/corestario/kyber/share/vss/pedersen"
|
||||
|
||||
"github.com/corestario/kyber"
|
||||
"github.com/corestario/kyber/share"
|
||||
bls12381 "github.com/depools/kyber-bls12381"
|
||||
)
|
||||
|
||||
type PK2Participant struct {
|
||||
|
@ -143,7 +143,7 @@ func (b *BLSKeyring) Bytes() ([]byte, error) {
|
|||
return json.Marshal(blsKeyringJSON)
|
||||
}
|
||||
|
||||
func LoadBLSKeyringFromBytes(data []byte) (*BLSKeyring, error) {
|
||||
func LoadBLSKeyringFromBytes(suite vss.Suite, data []byte) (*BLSKeyring, error) {
|
||||
var (
|
||||
err error
|
||||
blsKeyringJson blsKeyringJSON
|
||||
|
@ -154,20 +154,20 @@ func LoadBLSKeyringFromBytes(data []byte) (*BLSKeyring, error) {
|
|||
|
||||
commitments := make([]kyber.Point, 0, len(blsKeyringJson.Commitments))
|
||||
for _, commitmentBz := range blsKeyringJson.Commitments {
|
||||
commitment := bls12381.NewBLS12381Suite().Point()
|
||||
commitment := suite.Point()
|
||||
if err := commitment.UnmarshalBinary(commitmentBz); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal commitment: %w", err)
|
||||
}
|
||||
commitments = append(commitments, commitment)
|
||||
}
|
||||
|
||||
priShare, privDec := &share.PriShare{V: bls12381.NewBLS12381Suite().(pairing.Suite).G1().Scalar()}, gob.NewDecoder(bytes.NewBuffer(blsKeyringJson.Share))
|
||||
priShare, privDec := &share.PriShare{V: suite.(pairing.Suite).G1().Scalar()}, gob.NewDecoder(bytes.NewBuffer(blsKeyringJson.Share))
|
||||
if err := privDec.Decode(priShare); err != nil {
|
||||
return nil, fmt.Errorf("failed to share: %v", err)
|
||||
}
|
||||
|
||||
return &BLSKeyring{
|
||||
PubPoly: share.NewPubPoly(bls12381.NewBLS12381Suite(), nil, commitments),
|
||||
PubPoly: share.NewPubPoly(suite, nil, commitments),
|
||||
Share: priShare,
|
||||
}, nil
|
||||
}
|
||||
|
|
6
go.mod
6
go.mod
|
@ -6,6 +6,7 @@ require (
|
|||
github.com/corestario/kyber v1.3.0
|
||||
github.com/depools/kyber-bls12381 v0.0.0-20200831104422-978ac58f592e
|
||||
github.com/golang/mock v1.4.4
|
||||
github.com/google/go-cmp v0.2.0
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
|
||||
github.com/looplab/fsm v0.1.0
|
||||
|
@ -19,6 +20,11 @@ require (
|
|||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
|
||||
lukechampine.com/frand v1.3.0
|
||||
)
|
||||
|
||||
replace golang.org/x/crypto => github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5
|
||||
|
||||
replace github.com/corestario/kyber => ../kyber
|
||||
|
||||
replace github.com/depools/kyber-bls12381 => ../kyber-bls12381
|
||||
|
|
9
go.sum
9
go.sum
|
@ -1,6 +1,8 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
|
@ -13,8 +15,6 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
|||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/corestario/kyber v1.3.0 h1:SEWofdorUUeAJTsa9WJmrUYFyWHSWyXLgqDTFFEIzes=
|
||||
github.com/corestario/kyber v1.3.0/go.mod h1:kIWfWekm8kSJNti3Fo3DCV0GHEH050MWQrdvZdefbkk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -47,7 +47,9 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l
|
|||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
|
@ -180,6 +182,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -216,3 +219,5 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/frand v1.3.0 h1:HFLrwEHr78+EqAfyp8OChgEzdYCVZzzj6Y+cGDQRhaI=
|
||||
lukechampine.com/frand v1.3.0/go.mod h1:4S/TM2ZgrKejMcKMbeLjISpJMO+/eZ1zu3vYX9dtj3s=
|
||||
|
|
Loading…
Reference in New Issue