diff --git a/cluster/cluster_test.go b/cluster/cluster_test.go index 5071201df..a2cc8d376 100644 --- a/cluster/cluster_test.go +++ b/cluster/cluster_test.go @@ -99,16 +99,8 @@ func TestEncode(t *testing.T) { Validators: []cluster.DistValidator{ { PubKey: testutil.RandomETHAddress(), - Verifiers: [][]byte{ - testutil.RandomBytes32(), - testutil.RandomBytes32(), - }, }, { PubKey: testutil.RandomETHAddress(), - Verifiers: [][]byte{ - testutil.RandomBytes32(), - testutil.RandomBytes32(), - }, }, }, } diff --git a/cluster/distvalidator.go b/cluster/distvalidator.go index b38db99ee..d70ad4805 100644 --- a/cluster/distvalidator.go +++ b/cluster/distvalidator.go @@ -32,10 +32,6 @@ type DistValidator struct { // It can be used to verify a partial signature created by any node in the cluster. PubShares [][]byte `json:"public_shares,omitempty"` - // Verifiers are the threshold verifier commitments. - // Deprecated: Use PubShares. - Verifiers [][]byte `json:"threshold_verifiers,omitempty"` - // FeeRecipientAddress Ethereum address override for this validator, defaults to definition withdrawal address. FeeRecipientAddress string `json:"fee_recipient_address,omitempty"` } @@ -52,9 +48,9 @@ func (v DistValidator) HashTreeRootWith(hh *ssz.Hasher) error { // Field (0) 'PubKey' hh.PutBytes([]byte(v.PubKey)) - for _, verifier := range v.Verifiers { - // Field (1+i) 'Verifier' - hh.PutBytes(verifier) + for _, pubshare := range v.PubShares { + // Field (1+i) 'Pubshare' + hh.PutBytes(pubshare) } // Field (N) 'FeeRecipientAddress' diff --git a/cluster/test_cluster.go b/cluster/test_cluster.go index 34588f17d..d216fccca 100644 --- a/cluster/test_cluster.go +++ b/cluster/test_cluster.go @@ -65,15 +65,9 @@ func NewForT(t *testing.T, dv, k, n, seed int) (Lock, []*ecdsa.PrivateKey, [][]* pk, err := tss.PublicKey().MarshalBinary() require.NoError(t, err) - var verifiers [][]byte - for _, commitment := range tss.Verifier().Commitments { - verifiers = append(verifiers, commitment.ToAffineCompressed()) - } - var pubshares [][]byte for i := 0; i < n; i++ { - share, err := tss.PublicShare(i + 1) // Share indexes are 1-indexed. - require.NoError(t, err) + share := tss.PublicShare(i + 1) // Share indexes are 1-indexed. b, err := share.MarshalBinary() require.NoError(t, err) @@ -84,7 +78,6 @@ func NewForT(t *testing.T, dv, k, n, seed int) (Lock, []*ecdsa.PrivateKey, [][]* vals = append(vals, DistValidator{ PubKey: fmt.Sprintf("%#x", pk), PubShares: pubshares, - Verifiers: verifiers, }) dvShares = append(dvShares, shares) } diff --git a/cluster/testdata/TestEncode_lock_json.golden b/cluster/testdata/TestEncode_lock_json.golden index 0effdf90d..def76b571 100644 --- a/cluster/testdata/TestEncode_lock_json.golden +++ b/cluster/testdata/TestEncode_lock_json.golden @@ -31,20 +31,12 @@ }, "distributed_validators": [ { - "distributed_public_key": "0x7b182e046410f44bc4b0f3f03a0d06820a30f257", - "threshold_verifiers": [ - "NCyLgFXEZtiGRB0lmQbWms2JS5aK6fDrnZZc5qRpPE4=", - "vogVAbfZhGtm6wK1flzae2y6aJHWFr1obDe4NGE6yLo=" - ] + "distributed_public_key": "0x7b182e046410f44bc4b0f3f03a0d06820a30f257" }, { - "distributed_public_key": "0xa22c008ffe688352734ae4e3f1217acd5f832708", - "threshold_verifiers": [ - "eVeydxnOPzGI3+V97r9vgllaEPe7ViygTVw9J5QpWMY=", - "2zJiZwZJ87yX2aIxZzXt5oKl3+bxoBH7yYrQ++eQADw=" - ] + "distributed_public_key": "0x342c8b8055c466d886441d259906d69acd894b96" } ], "signature_aggregate": "bbXBREw6NNMqXEp/++jRgfftO4z+kE+T+PBtKbzZ7YQ=", - "lock_hash": "wcS2qPDhSo0jvYr6tM+7pk4H+nsglA/cf8+baqBnuK0=" + "lock_hash": "c1GjLXPvkrYyXHyyATXvQ64yEjCcc/YmXl4PrK5MeDQ=" } \ No newline at end of file diff --git a/cluster/testdata/TestEncode_lock_yaml.golden b/cluster/testdata/TestEncode_lock_yaml.golden index 2a52807bc..21b41887b 100644 --- a/cluster/testdata/TestEncode_lock_yaml.golden +++ b/cluster/testdata/TestEncode_lock_yaml.golden @@ -23,12 +23,6 @@ cluster_definition: - otcjnEC0WsOVDZQfxP4cDLlq0yLWIoIpX7/hHiakMwc= distributed_validators: - distributed_public_key: "0x7b182e046410f44bc4b0f3f03a0d06820a30f257" - threshold_verifiers: - - NCyLgFXEZtiGRB0lmQbWms2JS5aK6fDrnZZc5qRpPE4= - - vogVAbfZhGtm6wK1flzae2y6aJHWFr1obDe4NGE6yLo= -- distributed_public_key: "0xa22c008ffe688352734ae4e3f1217acd5f832708" - threshold_verifiers: - - eVeydxnOPzGI3+V97r9vgllaEPe7ViygTVw9J5QpWMY= - - 2zJiZwZJ87yX2aIxZzXt5oKl3+bxoBH7yYrQ++eQADw= +- distributed_public_key: "0x342c8b8055c466d886441d259906d69acd894b96" signature_aggregate: bbXBREw6NNMqXEp/++jRgfftO4z+kE+T+PBtKbzZ7YQ= -lock_hash: wcS2qPDhSo0jvYr6tM+7pk4H+nsglA/cf8+baqBnuK0= +lock_hash: c1GjLXPvkrYyXHyyATXvQ64yEjCcc/YmXl4PrK5MeDQ= diff --git a/cmd/createcluster.go b/cmd/createcluster.go index ddae4e5f3..7a6aa62f7 100644 --- a/cmd/createcluster.go +++ b/cmd/createcluster.go @@ -337,10 +337,7 @@ func newLock(conf clusterConfig, dvs []tbls.TSS, peers []p2p.Peer) (cluster.Lock var pubshares [][]byte for i := 0; i < dv.NumShares(); i++ { - share, err := dv.PublicShare(i + 1) // Shares are 1-indexed. - if err != nil { - return cluster.Lock{}, err - } + share := dv.PublicShare(i + 1) // Shares are 1-indexed. b, err := share.MarshalBinary() if err != nil { return cluster.Lock{}, errors.Wrap(err, "marshal pubshare") diff --git a/core/validatorapi/validatorapi_test.go b/core/validatorapi/validatorapi_test.go index 4fd2e1584..178a221b7 100644 --- a/core/validatorapi/validatorapi_test.go +++ b/core/validatorapi/validatorapi_test.go @@ -626,8 +626,7 @@ func TestComponent_ProposerDuties(t *testing.T) { // Create keys (just use normal keys, not split tbls) pubkey := tss.PublicKey() - pubshare, err := tss.PublicShare(vIdx) - require.NoError(t, err) + pubshare := tss.PublicShare(vIdx) eth2Share, err := tblsconv.KeyToETH2(pubshare) require.NoError(t, err) diff --git a/dkg/dkg.go b/dkg/dkg.go index 0eef3ced2..fb4dad958 100644 --- a/dkg/dkg.go +++ b/dkg/dkg.go @@ -328,12 +328,9 @@ func aggLockHashSig(data map[core.PubKey][]core.ParSignedData, shares map[core.P var pubshare *bls_sig.PublicKey switch dkgAlgo { case "keycast": - pubshare, err = tbls.GetPubShare(s.ShareIdx, shares[pk].Verifier) - if err != nil { - return nil, nil, errors.Wrap(err, "get pubshare from verifier") - } + pubshare = shares[pk].PublicShares[s.ShareIdx] case "frost": - pubshare = shares[pk].PublicShares[uint32(s.ShareIdx)] + pubshare = shares[pk].PublicShares[s.ShareIdx] default: return nil, nil, errors.New("invalid dkg algo") } @@ -493,7 +490,6 @@ func dvsFromShares(shares []share) ([]cluster.DistValidator, error) { dvs = append(dvs, cluster.DistValidator{ PubKey: fmt.Sprintf("%#x", msg.PubKey), - Verifiers: msg.Verifiers, PubShares: msg.PubShares, }) } diff --git a/dkg/frost.go b/dkg/frost.go index 2917b9a24..9ddaeb78d 100644 --- a/dkg/frost.go +++ b/dkg/frost.go @@ -219,7 +219,7 @@ func makeShares( targetID uint32, ) ([]share, error) { // Get set of public shares for each validator. - pubShares := make(map[uint32]map[uint32]*bls_sig.PublicKey) // map[ValIdx]map[SourceID]*bls_sig.PublicKey + pubShares := make(map[uint32]map[int]*bls_sig.PublicKey) // map[ValIdx]map[SourceID]*bls_sig.PublicKey for key, result := range r2Result { if key.TargetID != targetID { // Not for us. @@ -232,10 +232,10 @@ func makeShares( m, ok := pubShares[key.ValIdx] if !ok { - m = make(map[uint32]*bls_sig.PublicKey) + m = make(map[int]*bls_sig.PublicKey) pubShares[key.ValIdx] = m } - m[key.SourceID] = pubShare + m[int(key.SourceID)] = pubShare } // Sort shares by vIdx diff --git a/dkg/keycast.go b/dkg/keycast.go index bf149c4fb..54458d7ab 100644 --- a/dkg/keycast.go +++ b/dkg/keycast.go @@ -21,8 +21,6 @@ import ( "io" "sort" - "github.com/coinbase/kryptology/pkg/core/curves" - "github.com/coinbase/kryptology/pkg/sharing" "github.com/coinbase/kryptology/pkg/signatures/bls/bls_sig" "github.com/obolnetwork/charon/app/errors" @@ -46,16 +44,13 @@ type share struct { PubKey *bls_sig.PublicKey SecretShare *bls_sig.SecretKeyShare - // One of the two below will be populated, - Verifier *sharing.FeldmanVerifier - PublicShares map[uint32]*bls_sig.PublicKey // map[shareIdx]*bls_sig.PublicKey + PublicShares map[int]*bls_sig.PublicKey // map[shareIdx]*bls_sig.PublicKey } // shareMsg is the share message wire format sent by the dealer. type shareMsg struct { PubKey []byte PubShares [][]byte - Verifiers [][]byte SecretShare []byte } @@ -169,12 +164,7 @@ func leadKeyCast(ctx context.Context, tp kcTransport, def cluster.Definition, ra func createShares(numValidators, numNodes, threshold int, random io.Reader) ([][]share, error) { resp := make([][]share, numNodes) for i := 0; i < numValidators; i++ { - pubkey, secret, err := tbls.Keygen() - if err != nil { - return nil, err - } - - shares, verifier, err := tbls.SplitSecret(secret, threshold, numNodes, random) + tss, shares, err := tbls.GenerateTSS(threshold, numNodes, random) if err != nil { return nil, err } @@ -185,9 +175,9 @@ func createShares(numValidators, numNodes, threshold int, random io.Reader) ([][ for ni := 0; ni < numNodes; ni++ { resp[ni] = append(resp[ni], share{ - PubKey: pubkey, - Verifier: verifier, - SecretShare: shares[ni], + PubKey: tss.PublicKey(), + PublicShares: tss.PublicShares(), + SecretShare: shares[ni], }) } } @@ -202,13 +192,6 @@ func msgFromShare(s share) (shareMsg, error) { return shareMsg{}, errors.Wrap(err, "marshal pubkey") } - var verifiers [][]byte - if s.Verifier != nil { - for _, commitment := range s.Verifier.Commitments { - verifiers = append(verifiers, commitment.ToAffineCompressed()) - } - } - // Sort pub shares by id/index. var pubSharesIDs []int for id := range s.PublicShares { @@ -218,7 +201,7 @@ func msgFromShare(s share) (shareMsg, error) { var pubShares [][]byte for _, id := range pubSharesIDs { - b, err := s.PublicShares[uint32(id)].MarshalBinary() + b, err := s.PublicShares[id].MarshalBinary() if err != nil { return shareMsg{}, errors.Wrap(err, "marshal public share") } @@ -232,7 +215,6 @@ func msgFromShare(s share) (shareMsg, error) { return shareMsg{ PubKey: pubkey, - Verifiers: verifiers, SecretShare: secretShare, PubShares: pubShares, }, nil @@ -245,24 +227,14 @@ func shareFromMsg(msg shareMsg) (share, error) { return share{}, errors.Wrap(err, "unmarshal pubkey") } - var commitments []curves.Point - for _, v := range msg.Verifiers { - c, err := curves.BLS12381G1().Point.FromAffineCompressed(v) - if err != nil { - return share{}, errors.Wrap(err, "verifier hex") - } - - commitments = append(commitments, c) - } - - pubShares := make(map[uint32]*bls_sig.PublicKey) + pubShares := make(map[int]*bls_sig.PublicKey) for id, bytes := range msg.PubShares { pubShare := new(bls_sig.PublicKey) if err := pubShare.UnmarshalBinary(bytes); err != nil { return share{}, errors.Wrap(err, "unmarshal public share") } - pubShares[uint32(id+1)] = pubShare // Public shares IDs are 1-indexed. + pubShares[id+1] = pubShare // Public shares IDs are 1-indexed. } secretShare := new(bls_sig.SecretKeyShare) @@ -272,7 +244,6 @@ func shareFromMsg(msg shareMsg) (share, error) { return share{ PubKey: pubKey, - Verifier: &sharing.FeldmanVerifier{Commitments: commitments}, SecretShare: secretShare, PublicShares: pubShares, }, nil diff --git a/tbls/tss.go b/tbls/tss.go index 6c089528f..5bd14c8be 100644 --- a/tbls/tss.go +++ b/tbls/tss.go @@ -60,18 +60,14 @@ func KeygenWithSeed(reader io.Reader) (*bls_sig.PublicKey, *bls_sig.SecretKey, e // TSS (threshold signing scheme) wraps PubKey (PublicKey), Verifiers (the coefficients of the public polynomial) // and threshold (number of shares). type TSS struct { - verifier *share.FeldmanVerifier + pubshares map[int]*bls_sig.PublicKey numShares int + threshold int // publicKey inferred from verifier commitments in NewTSS. publicKey *bls_sig.PublicKey } -// Verifier returns the feldman verifier containing the public shares of the threshold signature scheme. -func (t TSS) Verifier() *share.FeldmanVerifier { - return t.verifier -} - // NumShares returns the number of shares in the threshold signature scheme. func (t TSS) NumShares() int { return t.numShares @@ -84,12 +80,16 @@ func (t TSS) PublicKey() *bls_sig.PublicKey { // Threshold returns the minimum number of partial signatures required to aggregate the threshold signature. func (t TSS) Threshold() int { - return len(t.verifier.Commitments) + return t.threshold } // PublicShare returns a share's public key by share index (identifier). -func (t TSS) PublicShare(shareIdx int) (*bls_sig.PublicKey, error) { - return GetPubShare(shareIdx, t.verifier) +func (t TSS) PublicShare(shareIdx int) *bls_sig.PublicKey { + return t.pubshares[shareIdx] +} + +func (t TSS) PublicShares() map[int]*bls_sig.PublicKey { + return t.pubshares } func NewTSS(verifier *share.FeldmanVerifier, numShares int) (TSS, error) { @@ -99,10 +99,19 @@ func NewTSS(verifier *share.FeldmanVerifier, numShares int) (TSS, error) { return TSS{}, errors.Wrap(err, "unmarshal pubkey") } + pubshares := make(map[int]*bls_sig.PublicKey) + for i := 1; i <= numShares; i++ { + pubshares[i], err = getPubShare(i, verifier) + if err != nil { + return TSS{}, err + } + } + return TSS{ - verifier: verifier, + pubshares: pubshares, publicKey: pk, numShares: numShares, + threshold: len(verifier.Commitments), }, nil } @@ -153,10 +162,7 @@ func VerifyAndAggregate(tss TSS, partialSigs []*bls_sig.PartialSignature, msg [] for _, psig := range partialSigs { // TODO(dhruv): add break condition if valid shares >= threshold - pubShare, err := tss.PublicShare(int(psig.Identifier)) - if err != nil { - return nil, nil, errors.Wrap(err, "get Public Share") - } + pubShare := tss.PublicShare(int(psig.Identifier)) sig := &bls_sig.Signature{Value: psig.Signature} ok, err := blsScheme.Verify(pubShare, msg, sig) @@ -247,8 +253,8 @@ func SplitSecret(secret *bls_sig.SecretKey, t, n int, reader io.Reader) ([]*bls_ return sks, verifier, nil } -// GetPubShare returns the public key share for the i'th/identifier/shareIdx share from the verifier commitments. -func GetPubShare(identifier int, verifier *share.FeldmanVerifier) (*bls_sig.PublicKey, error) { +// getPubShare returns the public key share for the i'th/identifier/shareIdx share from the verifier commitments. +func getPubShare(identifier int, verifier *share.FeldmanVerifier) (*bls_sig.PublicKey, error) { curve := curves.GetCurveByName(verifier.Commitments[0].CurveName()) if curve != curves.BLS12381G1() { return nil, errors.New("curve mismatch") diff --git a/tbls/tss_test.go b/tbls/tss_test.go index 56aaea1b9..a90ba9e78 100644 --- a/tbls/tss_test.go +++ b/tbls/tss_test.go @@ -53,8 +53,7 @@ func TestAggregateSignatures(t *testing.T) { partialSigs[i] = psig - pubshare, err := tss.PublicShare(int(psig.Identifier)) - require.NoError(t, err) + pubshare := tss.PublicShare(int(psig.Identifier)) ok, err := tbls.Verify(pubshare, msg, &bls_sig.Signature{Value: psig.Signature}) require.NoError(t, err)