diff --git a/dkg/pedersen/dkg.go b/dkg/pedersen/dkg.go index 31803ae87..d8f44c42c 100644 --- a/dkg/pedersen/dkg.go +++ b/dkg/pedersen/dkg.go @@ -51,14 +51,8 @@ func RunDKG(ctx context.Context, config *Config, board *Board, numVals int) ([]s return int(a.Index) - int(b.Index) }) - nonce, err := generateNonce(nodes) - if err != nil { - return nil, err - } - dkgConfig := &kdkg.Config{ Longterm: nodePrivateKey, - Nonce: nonce, Suite: config.Suite, NewNodes: nodes, Threshold: config.Threshold, @@ -71,7 +65,14 @@ func RunDKG(ctx context.Context, config *Config, board *Board, numVals int) ([]s shares := make([]share.Share, 0, numVals) - for range numVals { + for i := 0; i < numVals; i++ { + nonce, err := generateNonce(nodes, i) + if err != nil { + return nil, err + } + + dkgConfig.Nonce = nonce + phaser := kdkg.NewTimePhaser(config.PhaseDuration) protocol, err := kdkg.NewProtocol( diff --git a/dkg/pedersen/reshare.go b/dkg/pedersen/reshare.go index d1b3d66c9..6e67bb5f1 100644 --- a/dkg/pedersen/reshare.go +++ b/dkg/pedersen/reshare.go @@ -5,7 +5,6 @@ package pedersen import ( "bytes" "context" - "crypto/sha256" "slices" "github.com/drand/kyber" @@ -13,6 +12,7 @@ import ( kshare "github.com/drand/kyber/share" kdkg "github.com/drand/kyber/share/dkg" drandbls "github.com/drand/kyber/sign/bdn" + ssz "github.com/ferranbt/fastssz" "github.com/obolnetwork/charon/app/errors" "github.com/obolnetwork/charon/app/log" @@ -173,14 +173,8 @@ func RunReshareDKG(ctx context.Context, config *Config, board *Board, shares []s return nil, errors.New("existing node in add operation must have shares to contribute") } - nonce, err := generateNonce(nodes) - if err != nil { - return nil, err - } - reshareConfig := &kdkg.Config{ Longterm: nodePrivateKey, - Nonce: nonce, Suite: config.Suite, NewNodes: newNodes, OldNodes: oldNodes, @@ -199,6 +193,13 @@ func RunReshareDKG(ctx context.Context, config *Config, board *Board, shares []s newShares := make([]share.Share, 0, config.Reshare.TotalShares) for shareNum := range config.Reshare.TotalShares { + nonce, err := generateNonce(nodes, shareNum) + if err != nil { + return nil, err + } + + reshareConfig.Nonce = nonce + phaser := kdkg.NewTimePhaser(config.PhaseDuration) // Nodes with existing shares provide their share to the reshare protocol. @@ -355,22 +356,42 @@ func restoreCommits(publicShares map[int][][]byte, shareNum, threshold int) ([]k return restoreCommitsFromPubShares(pubSharesBytes, threshold) } -func generateNonce(nodes []kdkg.Node) ([]byte, error) { - var buf bytes.Buffer +func generateNonce(nodes []kdkg.Node, iteration int) ([]byte, error) { + hh := ssz.DefaultHasherPool.Get() + defer ssz.DefaultHasherPool.Put(hh) - for _, node := range nodes { - pkBytes, err := node.Public.MarshalBinary() - if err != nil { - return nil, errors.Wrap(err, "marshal node public key") - } + indx := hh.Index() - _, err = buf.Write(pkBytes) - if err != nil { - return nil, errors.Wrap(err, "hash node public key") + // Field (0) 'iteration' + hh.PutUint32(uint32(iteration)) + + // Field (1) 'nodes' - list of (index, pubkey) pairs + { + subIndx := hh.Index() + + for _, node := range nodes { + elemIndx := hh.Index() + + hh.PutUint32(node.Index) + + pkBytes, err := node.Public.MarshalBinary() + if err != nil { + return nil, errors.Wrap(err, "marshal node public key") + } + + hh.PutBytes(pkBytes) + hh.Merkleize(elemIndx) } + + hh.MerkleizeWithMixin(subIndx, uint64(len(nodes)), uint64(len(nodes))) } - hash := sha256.Sum256(buf.Bytes()) + hh.Merkleize(indx) + + hash, err := hh.HashRoot() + if err != nil { + return nil, errors.Wrap(err, "hash root") + } return hash[:], nil } diff --git a/dkg/pedersen/reshare_internal_test.go b/dkg/pedersen/reshare_internal_test.go index 57fafad54..e98e4b735 100644 --- a/dkg/pedersen/reshare_internal_test.go +++ b/dkg/pedersen/reshare_internal_test.go @@ -5,6 +5,8 @@ package pedersen import ( "testing" + kbls "github.com/drand/kyber-bls12381" + kdkg "github.com/drand/kyber/share/dkg" "github.com/stretchr/testify/require" "github.com/obolnetwork/charon/dkg/share" @@ -54,3 +56,34 @@ func TestRestoreDistKeyShare(t *testing.T) { require.Error(t, err) }) } + +func TestGenerateNonce(t *testing.T) { + suite := kbls.NewBLS12381Suite().G1().(kdkg.Suite) + _, pub1 := randomKeyPair(suite) + _, pub2 := randomKeyPair(suite) + _, pub3 := randomKeyPair(suite) + + nodes := []kdkg.Node{ + {Index: 1, Public: pub1}, + {Index: 2, Public: pub2}, + {Index: 3, Public: pub3}, + } + + nonce1, err := generateNonce(nodes, 0) + require.NoError(t, err) + + nonce2, err := generateNonce(nodes, 1) + require.NoError(t, err) + + require.NotEqual(t, nonce1, nonce2) + + nodes = []kdkg.Node{ + {Index: 1, Public: pub1}, + {Index: 2, Public: pub2}, + } + + nonce3, err := generateNonce(nodes, 1) + require.NoError(t, err) + + require.NotEqual(t, nonce2, nonce3) +}