diff --git a/.gitmodules b/.gitmodules index c0c2c61d8..118ee2656 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,6 +5,3 @@ [submodule "vendor/github.com/golang/protobuf"] path = vendor/github.com/golang/protobuf url = https://github.com/golang/protobuf -[submodule "vendor/github.com/dedis/kyber"] - path = vendor/github.com/dedis/kyber - url = https://github.com/dedis/kyber diff --git a/api/proto/bcconn/bcconn_test.go b/api/proto/bcconn/bcconn_test.go index 3f3379c22..af15d7fb4 100644 --- a/api/proto/bcconn/bcconn_test.go +++ b/api/proto/bcconn/bcconn_test.go @@ -13,7 +13,7 @@ func TestSerializeDeserializeNodeInfo(t *testing.T) { var ip, port string ip = "127.0.0.1" port = "8080" - _, pk := utils.GenKeyBLS(ip, port) + _, pk := utils.GenKey(ip, port) pkb := pk.Serialize() nodeInfo := &node.Info{IP: ip, Port: port, PubKey: pkb} serializedNI := SerializeNodeInfo(nodeInfo) @@ -29,13 +29,13 @@ func TestSerializeDeserializeRandomInfo(t *testing.T) { ip = "127.0.0.1" port = "8080" - _, pk := utils.GenKeyBLS(ip, port) + _, pk := utils.GenKey(ip, port) pkb := pk.Serialize() nodeInfo1 := &node.Info{IP: ip, Port: port, PubKey: pkb} ip = "127.0.0.1" port = "9080" - _, pk2 := utils.GenKeyBLS(ip, port) + _, pk2 := utils.GenKey(ip, port) pkb2 := pk2.Serialize() nodeInfo2 := &node.Info{IP: ip, Port: port, PubKey: pkb2} diff --git a/consensus/README.md b/consensus/README.md index 3b30f27ea..82d509dce 100644 --- a/consensus/README.md +++ b/consensus/README.md @@ -1,5 +1 @@ -Consensus package includes the Harmony BFT consensus protocol code. - -For now, the current implementation is still in experimental phase because it's coded using the two-round Schnorr-based multi-signature similar to [Byzcoin's design](https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_kokoris-kogias.pdf). - -We will migrate to BLS-based multi-signature following Harmony's new [consensus protocol design](https://talk.harmony.one/t/bls-based-practical-bft-consensus/131). +Consensus package includes the Harmony BFT consensus protocol code, which uses BLS-based multi-signature to cosign the new block. The details are in Harmony's new [consensus protocol design](https://talk.harmony.one/t/bls-based-practical-bft-consensus/131). diff --git a/consensus/consensus.go b/consensus/consensus.go index 0d36401c0..743911f6e 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -449,7 +449,6 @@ func (consensus *Consensus) DebugPrintValidators() { // UpdatePublicKeys updates the PublicKeys variable, protected by a mutex func (consensus *Consensus) UpdatePublicKeys(pubKeys []*bls.PublicKey) int { consensus.pubKeyLock.Lock() - // consensus.PublicKeys = make([]kyber.Point, len(pubKeys)) consensus.PublicKeys = append(pubKeys[:0:0], pubKeys...) consensus.pubKeyLock.Unlock() diff --git a/consensus/consensus_leader_msg_test.go b/consensus/consensus_leader_msg_test.go index a5a732dd8..fa9f700c7 100644 --- a/consensus/consensus_leader_msg_test.go +++ b/consensus/consensus_leader_msg_test.go @@ -29,10 +29,10 @@ func TestConstructAnnounceMessage(test *testing.T) { func TestConstructPreparedMessage(test *testing.T) { - leaderPriKey, leaderPubKey := utils.GenKeyBLS("127.0.0.1", "6000") + leaderPriKey, leaderPubKey := utils.GenKey("127.0.0.1", "6000") leader := p2p.Peer{IP: "127.0.0.1", Port: "6000", PubKey: leaderPubKey} - validatorPriKey, validatorPubKey := utils.GenKeyBLS("127.0.0.1", "5555") + validatorPriKey, validatorPubKey := utils.GenKey("127.0.0.1", "5555") validator := p2p.Peer{IP: "127.0.0.1", Port: "5555", PubKey: validatorPubKey} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") host, err := p2pimpl.NewHost(&leader, priKey) diff --git a/consensus/consensus_leader_test.go b/consensus/consensus_leader_test.go index 4f5337e6b..ae53dc3dc 100644 --- a/consensus/consensus_leader_test.go +++ b/consensus/consensus_leader_test.go @@ -33,7 +33,7 @@ func TestProcessMessageLeaderPrepare(test *testing.T) { defer ctrl.Finish() leader := p2p.Peer{IP: ip, Port: "7777"} - _, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) + _, leader.PubKey = utils.GenKey(leader.IP, leader.Port) validators := make([]p2p.Peer, 3) hosts := make([]p2p.Host, 3) @@ -41,7 +41,7 @@ func TestProcessMessageLeaderPrepare(test *testing.T) { for i := 0; i < 3; i++ { port := fmt.Sprintf("%d", 7788+i) validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1} - _, validators[i].PubKey = utils.GenKeyBLS(validators[i].IP, validators[i].Port) + _, validators[i].PubKey = utils.GenKey(validators[i].IP, validators[i].Port) } m := mock_host.NewMockHost(ctrl) @@ -78,7 +78,7 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) { defer ctrl.Finish() leader := p2p.Peer{IP: ip, Port: "7777"} - _, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) + _, leader.PubKey = utils.GenKey(leader.IP, leader.Port) validators := make([]p2p.Peer, 3) hosts := make([]p2p.Host, 3) @@ -86,7 +86,7 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) { for i := 0; i < 3; i++ { port := fmt.Sprintf("%d", 7788+i) validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1} - _, validators[i].PubKey = utils.GenKeyBLS(validators[i].IP, validators[i].Port) + _, validators[i].PubKey = utils.GenKey(validators[i].IP, validators[i].Port) } m := mock_host.NewMockHost(ctrl) @@ -129,7 +129,7 @@ func TestProcessMessageLeaderCommit(test *testing.T) { defer ctrl.Finish() leader := p2p.Peer{IP: ip, Port: "8889"} - _, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) + _, leader.PubKey = utils.GenKey(leader.IP, leader.Port) validators := make([]p2p.Peer, 3) hosts := make([]p2p.Host, 3) @@ -137,7 +137,7 @@ func TestProcessMessageLeaderCommit(test *testing.T) { for i := 0; i < 3; i++ { port := fmt.Sprintf("%d", 8788+i) validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1} - _, validators[i].PubKey = utils.GenKeyBLS(validators[i].IP, validators[i].Port) + _, validators[i].PubKey = utils.GenKey(validators[i].IP, validators[i].Port) } m := mock_host.NewMockHost(ctrl) diff --git a/consensus/consensus_test.go b/consensus/consensus_test.go index 662cf134e..567de9897 100644 --- a/consensus/consensus_test.go +++ b/consensus/consensus_test.go @@ -37,11 +37,11 @@ func TestNew(test *testing.T) { } func TestRemovePeers(t *testing.T) { - _, pk1 := utils.GenKeyBLS("1", "1") - _, pk2 := utils.GenKeyBLS("2", "2") - _, pk3 := utils.GenKeyBLS("3", "3") - _, pk4 := utils.GenKeyBLS("4", "4") - _, pk5 := utils.GenKeyBLS("5", "5") + _, pk1 := utils.GenKey("1", "1") + _, pk2 := utils.GenKey("2", "2") + _, pk3 := utils.GenKey("3", "3") + _, pk4 := utils.GenKey("4", "4") + _, pk5 := utils.GenKey("5", "5") p1 := p2p.Peer{IP: "127.0.0.1", Port: "19901", PubKey: pk1} p2 := p2p.Peer{IP: "127.0.0.1", Port: "19902", PubKey: pk2} diff --git a/consensus/consensus_validator_test.go b/consensus/consensus_validator_test.go index f3b42f95f..38cab8097 100644 --- a/consensus/consensus_validator_test.go +++ b/consensus/consensus_validator_test.go @@ -23,14 +23,14 @@ func TestProcessMessageValidatorAnnounce(test *testing.T) { defer ctrl.Finish() leader := p2p.Peer{IP: "127.0.0.1", Port: "9982"} - _, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) + _, leader.PubKey = utils.GenKey(leader.IP, leader.Port) validator1 := p2p.Peer{IP: "127.0.0.1", Port: "9984", ValidatorID: 1} - _, validator1.PubKey = utils.GenKeyBLS(validator1.IP, validator1.Port) + _, validator1.PubKey = utils.GenKey(validator1.IP, validator1.Port) validator2 := p2p.Peer{IP: "127.0.0.1", Port: "9986", ValidatorID: 2} - _, validator2.PubKey = utils.GenKeyBLS(validator2.IP, validator2.Port) + _, validator2.PubKey = utils.GenKey(validator2.IP, validator2.Port) validator3 := p2p.Peer{IP: "127.0.0.1", Port: "9988", ValidatorID: 3} - _, validator3.PubKey = utils.GenKeyBLS(validator3.IP, validator3.Port) + _, validator3.PubKey = utils.GenKey(validator3.IP, validator3.Port) m := mock_host.NewMockHost(ctrl) // Asserts that the first and only call to Bar() is passed 99. @@ -77,14 +77,14 @@ func TestProcessMessageValidatorPrepared(test *testing.T) { defer ctrl.Finish() leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"} - _, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) + _, leader.PubKey = utils.GenKey(leader.IP, leader.Port) validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1} - _, validator1.PubKey = utils.GenKeyBLS(validator1.IP, validator1.Port) + _, validator1.PubKey = utils.GenKey(validator1.IP, validator1.Port) validator2 := p2p.Peer{IP: "127.0.0.1", Port: "7786", ValidatorID: 2} - _, validator2.PubKey = utils.GenKeyBLS(validator2.IP, validator2.Port) + _, validator2.PubKey = utils.GenKey(validator2.IP, validator2.Port) validator3 := p2p.Peer{IP: "127.0.0.1", Port: "7788", ValidatorID: 3} - _, validator3.PubKey = utils.GenKeyBLS(validator3.IP, validator3.Port) + _, validator3.PubKey = utils.GenKey(validator3.IP, validator3.Port) m := mock_host.NewMockHost(ctrl) // Asserts that the first and only call to Bar() is passed 99. @@ -137,14 +137,14 @@ func TestProcessMessageValidatorCommitted(test *testing.T) { defer ctrl.Finish() leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"} - _, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) + _, leader.PubKey = utils.GenKey(leader.IP, leader.Port) validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1} - _, validator1.PubKey = utils.GenKeyBLS(validator1.IP, validator1.Port) + _, validator1.PubKey = utils.GenKey(validator1.IP, validator1.Port) validator2 := p2p.Peer{IP: "127.0.0.1", Port: "7786", ValidatorID: 2} - _, validator2.PubKey = utils.GenKeyBLS(validator2.IP, validator2.Port) + _, validator2.PubKey = utils.GenKey(validator2.IP, validator2.Port) validator3 := p2p.Peer{IP: "127.0.0.1", Port: "7788", ValidatorID: 3} - _, validator3.PubKey = utils.GenKeyBLS(validator3.IP, validator3.Port) + _, validator3.PubKey = utils.GenKey(validator3.IP, validator3.Port) m := mock_host.NewMockHost(ctrl) // Asserts that the first and only call to Bar() is passed 99. diff --git a/crypto/bls/bls_test.go b/crypto/bls/bls_test.go index 76db0e705..b08552715 100644 --- a/crypto/bls/bls_test.go +++ b/crypto/bls/bls_test.go @@ -9,9 +9,9 @@ import ( // Test the basic functionality of a BLS multi-sig mask. func TestNewMask(test *testing.T) { - _, pubKey1 := utils.GenKeyBLS("127.0.0.1", "5555") - _, pubKey2 := utils.GenKeyBLS("127.0.0.1", "6666") - _, pubKey3 := utils.GenKeyBLS("127.0.0.1", "7777") + _, pubKey1 := utils.GenKey("127.0.0.1", "5555") + _, pubKey2 := utils.GenKey("127.0.0.1", "6666") + _, pubKey3 := utils.GenKey("127.0.0.1", "7777") mask, err := NewMask([]*bls.PublicKey{pubKey1, pubKey2, pubKey3}, pubKey1) diff --git a/crypto/cosi.go b/crypto/cosi.go deleted file mode 100644 index 5751864a1..000000000 --- a/crypto/cosi.go +++ /dev/null @@ -1,440 +0,0 @@ -/* -Package crypto implements the collective signing (CoSi) algorithm as presented in -the paper "Keeping Authorities 'Honest or Bust' with Decentralized Witness -Cosigning" by Ewa Syta et al. See https://arxiv.org/abs/1503.08768. This -package only provides the functionality for the cryptographic operations of -CoSi. All network-related operations have to be handled elsewhere. Below we -describe a high-level overview of the CoSi protocol (using a star communication -topology). We refer to the research paper for further details on communication -over trees, exception mechanisms and signature verification policies. - -The CoSi protocol has four phases executed between a list of participants P -having a protocol leader (index i = 0) and a list of other nodes (index i > 0). -The secret key of node i is denoted by a_i and the public key by A_i = [a_i]G -(where G is the base point of the underlying group and [...] denotes scalar -multiplication). The aggregate public key is given as A = \sum{i ∈ P}(A_i). - -1. Announcement: The leader broadcasts an announcement to the other nodes -optionally including the message M to be signed. Upon receiving an announcement -message, a node starts its commitment phase. - -2. Commitment: Each node i (including the leader) picks a random scalar v_i, -computes its commitment V_i = [v_i]G and sends V_i back to the leader. The -leader waits until it has received enough commitments (according to some -policy) from the other nodes or a timer has run out. Let P' be the nodes that -have sent their commitments. The leader computes an aggregate commitment V from -all commitments he has received, i.e., V = \sum{j ∈ P'}(V_j) and creates a -participation bitmask Z. The leader then broadcasts V and Z to the other -participations together with the message M if it was not sent in phase 1. Upon -receiving a commitment message, a node starts the challenge phase. - -3. Challenge: Each node i computes the collective challenge c = H(V || A || M) -using a cryptographic hash function H (here: SHA512), computes its -response r_i = v_i + c*a_i and sends it back to the leader. - -4. Response: The leader waits until he has received replies from all nodes in -P' or a timer has run out. If he has not enough replies he aborts. Finally, -the leader computes the aggregate response r = \sum{j ∈ P'}(r_j) and publishes -(V,r,Z) as the signature for the message M. -*/ -package crypto - -import ( - "errors" - "fmt" - - "github.com/dedis/kyber" -) - -// Commit returns a random scalar v, generated from the given suite, -// and a corresponding commitment V = [v]G. If the given cipher stream is nil, -// a random stream is used. -func Commit(suite Suite) (v kyber.Scalar, V kyber.Point) { - random := suite.Scalar().Pick(suite.RandomStream()) - commitment := suite.Point().Mul(random, nil) - return random, commitment -} - -// AggregateCommitments returns the sum of the given commitments and the -// bitwise OR of the corresponding masks. -func AggregateCommitments(suite Suite, commitments []kyber.Point, masks [][]byte) (sum kyber.Point, commits []byte, err error) { - if len(commitments) != len(masks) { - return nil, nil, errors.New("mismatching lengths of commitment and mask slices") - } - aggCom := suite.Point().Null() - aggMask := make([]byte, len(masks[0])) - - for i := range commitments { - aggCom = suite.Point().Add(aggCom, commitments[i]) - aggMask, err = AggregateMasks(aggMask, masks[i]) - if err != nil { - return nil, nil, err - } - } - return aggCom, aggMask, nil -} - -// AggregateCommitmentsOnly returns the sum of the given commitments. -func AggregateCommitmentsOnly(suite Suite, commitments []kyber.Point) kyber.Point { - aggCom := suite.Point().Null() - - for i := range commitments { - aggCom = suite.Point().Add(aggCom, commitments[i]) - } - return aggCom -} - -// Challenge creates the collective challenge from the given aggregate -// commitment V, aggregate public key A, and message M, i.e., it returns -// c = H(V || A || M). -func Challenge(suite Suite, commitment, public kyber.Point, message []byte) (kyber.Scalar, error) { - if commitment == nil { - return nil, errors.New("no commitment provided") - } - if message == nil { - return nil, errors.New("no message provided") - } - hash := suite.Hash() - if _, err := commitment.MarshalTo(hash); err != nil { - return nil, err - } - if _, err := public.MarshalTo(hash); err != nil { - return nil, err - } - hash.Write(message) - return suite.Scalar().SetBytes(hash.Sum(nil)), nil -} - -// Response creates the response from the given random scalar v, (collective) -// challenge c, and private key a, i.e., it returns r = v + c*a. -func Response(suite Suite, private, random, challenge kyber.Scalar) (kyber.Scalar, error) { - if private == nil { - return nil, errors.New("no private key provided") - } - if random == nil { - return nil, errors.New("no random scalar provided") - } - if challenge == nil { - return nil, errors.New("no challenge provided") - } - // TODO: figure out why in the paper it says r = v - cx - ca := suite.Scalar().Mul(private, challenge) - return ca.Add(random, ca), nil -} - -// AggregateResponses returns the sum of given responses. -func AggregateResponses(suite Suite, responses []kyber.Scalar) (kyber.Scalar, error) { - if responses == nil { - return nil, errors.New("no responses provided") - } - r := suite.Scalar().Zero() - for i := range responses { - r = r.Add(r, responses[i]) - } - return r, nil -} - -// Sign returns the collective signature from the given (aggregate) commitment -// V, (aggregate) response r, and participation bitmask Z using the EdDSA -// format, i.e., the signature is V || r || Z. -func Sign(suite Suite, commitment kyber.Point, response kyber.Scalar, mask *Mask) ([]byte, error) { - if commitment == nil { - return nil, errors.New("no commitment provided") - } - if response == nil { - return nil, errors.New("no response provided") - } - if mask == nil { - return nil, errors.New("no mask provided") - } - lenV := suite.PointLen() - lenSig := lenV + suite.ScalarLen() - VB, err := commitment.MarshalBinary() - if err != nil { - return nil, errors.New("marshalling of commitment failed") - } - RB, err := response.MarshalBinary() - if err != nil { - return nil, errors.New("marshalling of signature failed") - } - sig := make([]byte, lenSig+mask.Len()) - copy(sig[:], VB) - copy(sig[lenV:lenSig], RB) - copy(sig[lenSig:], mask.mask) - return sig, nil -} - -// Verify checks the given cosignature on the provided message using the list -// of public keys and cosigning policy. -func Verify(suite Suite, publics []kyber.Point, message, sig []byte, policy Policy) error { - if publics == nil { - return errors.New("no public keys provided") - } - if message == nil { - return errors.New("no message provided") - } - if sig == nil { - return errors.New("no signature provided") - } - if policy == nil { - policy = CompletePolicy{} - } - - lenCom := suite.PointLen() - VBuff := sig[:lenCom] - V := suite.Point() - if err := V.UnmarshalBinary(VBuff); err != nil { - return errors.New("unmarshalling of commitment failed") - } - - // Unpack the aggregate response - lenRes := lenCom + suite.ScalarLen() - rBuff := sig[lenCom:lenRes] - r := suite.Scalar().SetBytes(rBuff) - - // Unpack the participation mask and get the aggregate public key - mask, err := NewMask(suite, publics, nil) - if err != nil { - return err - } - mask.SetMask(sig[lenRes:]) - A := mask.AggregatePublic - ABuff, err := A.MarshalBinary() - if err != nil { - return errors.New("marshalling of aggregate public key failed") - } - - // Recompute the challenge - hash := suite.Hash() - hash.Write(VBuff) - hash.Write(ABuff) - hash.Write(message) - buff := hash.Sum(nil) - k := suite.Scalar().SetBytes(buff) - - // k * -aggPublic + s * B = k*-A + s*B - // from s = k * a + r => s * B = k * a * B + r * B <=> s*B = k*A + r*B - // <=> s*B + k*-A = r*B - minusPublic := suite.Point().Neg(A) - kA := suite.Point().Mul(k, minusPublic) - sB := suite.Point().Mul(r, nil) - left := suite.Point().Add(kA, sB) - - if !left.Equal(V) { - return errors.New("recreated response is different from signature") - } - if !policy.Check(mask) { - return errors.New("the policy is not fulfilled") - } - - return nil -} - -// Mask represents a cosigning participation bitmask. -type Mask struct { - mask []byte - publics []kyber.Point - AggregatePublic kyber.Point -} - -// NewMask returns a new participation bitmask for cosigning where all -// cosigners are disabled by default. If a public key is given it verifies that -// it is present in the list of keys and sets the corresponding index in the -// bitmask to 1 (enabled). -func NewMask(suite Suite, publics []kyber.Point, myKey kyber.Point) (*Mask, error) { - m := &Mask{ - publics: publics, - } - m.mask = make([]byte, m.Len()) - m.AggregatePublic = suite.Point().Null() - if myKey != nil { - found := false - for i, key := range publics { - if key.Equal(myKey) { - m.SetBit(i, true) - found = true - break - } - } - if !found { - return nil, errors.New("key not found") - } - } - return m, nil -} - -// Mask returns a copy of the participation bitmask. -func (m *Mask) Mask() []byte { - clone := make([]byte, len(m.mask)) - copy(clone[:], m.mask) - return clone -} - -// Len returns the mask length in bytes. -func (m *Mask) Len() int { - return (len(m.publics) + 7) >> 3 -} - -// SetMask sets the participation bitmask according to the given byte slice -// interpreted in little-endian order, i.e., bits 0-7 of byte 0 correspond to -// cosigners 0-7, bits 0-7 of byte 1 correspond to cosigners 8-15, etc. -func (m *Mask) SetMask(mask []byte) error { - if m.Len() != len(mask) { - return fmt.Errorf("mismatching mask lengths") - } - for i := range m.publics { - byt := i >> 3 - msk := byte(1) << uint(i&7) - if ((m.mask[byt] & msk) == 0) && ((mask[byt] & msk) != 0) { - m.mask[byt] ^= msk // flip bit in mask from 0 to 1 - m.AggregatePublic.Add(m.AggregatePublic, m.publics[i]) - } - if ((m.mask[byt] & msk) != 0) && ((mask[byt] & msk) == 0) { - m.mask[byt] ^= msk // flip bit in mask from 1 to 0 - m.AggregatePublic.Sub(m.AggregatePublic, m.publics[i]) - } - } - return nil -} - -// SetBit enables (enable: true) or disables (enable: false) the bit -// in the participation mask of the given cosigner. -func (m *Mask) SetBit(i int, enable bool) error { - if i >= len(m.publics) { - return errors.New("index out of range") - } - byt := i >> 3 - msk := byte(1) << uint(i&7) - if ((m.mask[byt] & msk) == 0) && enable { - m.mask[byt] ^= msk // flip bit in mask from 0 to 1 - m.AggregatePublic.Add(m.AggregatePublic, m.publics[i]) - } - if ((m.mask[byt] & msk) != 0) && !enable { - m.mask[byt] ^= msk // flip bit in mask from 1 to 0 - m.AggregatePublic.Sub(m.AggregatePublic, m.publics[i]) - } - return nil -} - -// GetPubKeyFromMask will return pubkeys which masked either zero or one depending on the flag -// it is used to show which signers are signed or not in the cosign message -func (m *Mask) GetPubKeyFromMask(flag bool) []kyber.Point { - pubKeys := []kyber.Point{} - for i := range m.publics { - byt := i >> 3 - msk := byte(1) << uint(i&7) - if flag == true { - if (m.mask[byt] & msk) != 0 { - pubKeys = append(pubKeys, m.publics[i]) - } - } else { - if (m.mask[byt] & msk) == 0 { - pubKeys = append(pubKeys, m.publics[i]) - } - } - } - return pubKeys -} - -// IndexEnabled checks whether the given index is enabled in the mask or not. -func (m *Mask) IndexEnabled(i int) (bool, error) { - if i >= len(m.publics) { - return false, errors.New("index out of range") - } - byt := i >> 3 - msk := byte(1) << uint(i&7) - return ((m.mask[byt] & msk) != 0), nil -} - -// KeyEnabled checks whether the index, corresponding to the given key, is -// enabled in the mask or not. -func (m *Mask) KeyEnabled(public kyber.Point) (bool, error) { - for i, key := range m.publics { - if key.Equal(public) { - return m.IndexEnabled(i) - } - } - return false, errors.New("key not found") -} - -// SetKey set the bit in the mask for the given cosigner -func (m *Mask) SetKey(public kyber.Point, enable bool) error { - for i, key := range m.publics { - if key.Equal(public) { - return m.SetBit(i, enable) - } - } - return errors.New("key not found") -} - -// CountEnabled returns the number of enabled nodes in the CoSi participation -// mask. -func (m *Mask) CountEnabled() int { - // hw is hamming weight - hw := 0 - for i := range m.publics { - byt := i >> 3 - msk := byte(1) << uint(i&7) - if (m.mask[byt] & msk) != 0 { - hw++ - } - } - return hw -} - -// CountTotal returns the total number of nodes this CoSi instance knows. -func (m *Mask) CountTotal() int { - return len(m.publics) -} - -// AggregateMasks computes the bitwise OR of the two given participation masks. -func AggregateMasks(a, b []byte) ([]byte, error) { - if len(a) != len(b) { - return nil, errors.New("mismatching mask lengths") - } - m := make([]byte, len(a)) - for i := range m { - m[i] = a[i] | b[i] - } - return m, nil -} - -// Policy represents a fully customizable cosigning policy deciding what -// cosigner sets are and aren't sufficient for a collective signature to be -// considered acceptable to a verifier. The Check method may inspect the set of -// participants that cosigned by invoking cosi.Mask and/or cosi.MaskBit, and may -// use any other relevant contextual information (e.g., how security-critical -// the operation relying on the collective signature is) in determining whether -// the collective signature was produced by an acceptable set of cosigners. -type Policy interface { - Check(m *Mask) bool -} - -// CompletePolicy is the default policy requiring that all participants have -// cosigned to make a collective signature valid. -type CompletePolicy struct { -} - -// Check verifies that all participants have contributed to a collective -// signature. -func (p CompletePolicy) Check(m *Mask) bool { - return m.CountEnabled() == m.CountTotal() -} - -// ThresholdPolicy allows to specify a simple t-of-n policy requring that at -// least the given threshold number of participants t have cosigned to make a -// collective signature valid. -type ThresholdPolicy struct { - thold int -} - -// NewThresholdPolicy returns a new ThresholdPolicy with the given threshold. -func NewThresholdPolicy(thold int) *ThresholdPolicy { - return &ThresholdPolicy{thold: thold} -} - -// Check verifies that at least a threshold number of participants have -// contributed to a collective signature. -func (p ThresholdPolicy) Check(m *Mask) bool { - return m.CountEnabled() >= p.thold -} diff --git a/crypto/curve.go b/crypto/curve.go deleted file mode 100644 index fb5b21845..000000000 --- a/crypto/curve.go +++ /dev/null @@ -1,6 +0,0 @@ -package crypto - -import "github.com/dedis/kyber/group/edwards25519" - -// Ed25519Curve value gets initialized. -var Ed25519Curve = edwards25519.NewBlakeSHA256Ed25519() diff --git a/crypto/pki/utils.go b/crypto/pki/utils.go index c7edba76b..68aa0db46 100644 --- a/crypto/pki/utils.go +++ b/crypto/pki/utils.go @@ -4,9 +4,7 @@ import ( "crypto/sha256" "encoding/binary" - "github.com/dedis/kyber" "github.com/harmony-one/bls/ffi/go/bls" - "github.com/harmony-one/harmony/crypto" ) func init() { @@ -42,11 +40,6 @@ func GetAddressFromInt(value int) [20]byte { return GetAddressFromPrivateKeyBytes(priKey) } -// GetPrivateKeyScalarFromInt return private key scalar. -func GetPrivateKeyScalarFromInt(value int) kyber.Scalar { - return crypto.Ed25519Curve.Scalar().SetInt64(int64(value)) -} - // GetBLSPrivateKeyFromInt returns bls private key func GetBLSPrivateKeyFromInt(value int) *bls.SecretKey { priKey := [32]byte{} @@ -55,36 +48,3 @@ func GetBLSPrivateKeyFromInt(value int) *bls.SecretKey { privateKey.SetLittleEndian(priKey[:]) return &privateKey } - -// GetPrivateKeyFromInt returns private key in bytes given an interger. -func GetPrivateKeyFromInt(value int) [32]byte { - priKey, err := crypto.Ed25519Curve.Scalar().SetInt64(int64(value)).MarshalBinary() - priKeyBytes := [32]byte{} - if err == nil { - copy(priKeyBytes[:], priKey[:]) - } - return priKeyBytes -} - -// GetPublicKeyFromPrivateKey return public key from private key. -func GetPublicKeyFromPrivateKey(priKey [32]byte) kyber.Point { - suite := crypto.Ed25519Curve - scalar := suite.Scalar() - scalar.UnmarshalBinary(priKey[:]) - return suite.Point().Mul(scalar, nil) -} - -// GetPublicKeyFromScalar is the same as GetPublicKeyFromPrivateKey, but it directly works on kyber.Scalar object. -func GetPublicKeyFromScalar(priKey kyber.Scalar) kyber.Point { - return crypto.Ed25519Curve.Point().Mul(priKey, nil) -} - -// GetBytesFromPublicKey converts public key point to bytes -func GetBytesFromPublicKey(pubKey kyber.Point) [32]byte { - bytes, err := pubKey.MarshalBinary() - result := [32]byte{} - if err == nil { - copy(result[:], bytes) - } - return result -} diff --git a/crypto/pki/utils_test.go b/crypto/pki/utils_test.go index 831fc485f..9b534d88e 100644 --- a/crypto/pki/utils_test.go +++ b/crypto/pki/utils_test.go @@ -7,7 +7,6 @@ import ( "time" "github.com/harmony-one/bls/ffi/go/bls" - "github.com/harmony-one/harmony/crypto" ) func TestGetAddressFromPublicKey(test *testing.T) { @@ -22,37 +21,3 @@ func TestGetAddressFromPublicKey(test *testing.T) { test.Error("two public address should be equal") } } - -func TestGetPublicKeyFromPrivateKey(test *testing.T) { - suite := crypto.Ed25519Curve - t := time.Now().UnixNano() - scalar := suite.Scalar().SetInt64(t) - pubKey1 := GetPublicKeyFromScalar(scalar) - bytes := [32]byte{} - tmp, err := scalar.MarshalBinary() - copy(bytes[:], tmp) - if err != nil { - test.Error("unable to marshal private key to binary") - } - pubKey2 := GetPublicKeyFromPrivateKey(bytes) - if !reflect.DeepEqual(pubKey1, pubKey2) { - test.Error("two public keys should be equal") - } -} - -func TestGetPrivateKeyFromInt(test *testing.T) { - t := int(time.Now().UnixNano()) - priKey1 := GetPrivateKeyFromInt(t) - priKeyScalar := GetPrivateKeyScalarFromInt(t) - tmp, err := priKeyScalar.MarshalBinary() - priKey2 := [32]byte{} - copy(priKey2[:], tmp) - - if err != nil { - test.Error("unable to marshal private key to binary") - } - if !reflect.DeepEqual(priKey1, priKey2) { - test.Error("two private keys should be equal") - } - -} diff --git a/crypto/suite.go b/crypto/suite.go deleted file mode 100644 index 69f9b0a4c..000000000 --- a/crypto/suite.go +++ /dev/null @@ -1,10 +0,0 @@ -package crypto - -import "github.com/dedis/kyber" - -// Suite specifies the cryptographic building blocks required for the cosi package. -type Suite interface { - kyber.Group - kyber.HashFactory - kyber.Random -} diff --git a/internal/newnode/newnode.go b/internal/newnode/newnode.go index ba4850efc..f07b6f9d5 100644 --- a/internal/newnode/newnode.go +++ b/internal/newnode/newnode.go @@ -39,7 +39,7 @@ type NewNode struct { // New candidatenode initialization func New(ip string, port string, nodePk p2p_crypto.PrivKey) *NewNode { - priKey, pubKey := utils.GenKeyBLS(ip, port) + priKey, pubKey := utils.GenKey(ip, port) var node NewNode var err error node.PubK = pubKey @@ -131,7 +131,7 @@ func (node *NewNode) processShardInfo(msgPayload []byte) bool { leaderPeer.PubKey = &bls.PublicKey{} err = leaderPeer.PubKey.Deserialize(v.PubKey[:]) if err != nil { - node.log.Error("Could not unmarshall leaders public key from binary to kyber.point") + node.log.Error("Could not unmarshall leaders public key from binary") } node.Leaders[uint32(n)] = leaderPeer } diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 1084bdcba..bc103a694 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -13,10 +13,7 @@ import ( "strconv" "sync" - "github.com/dedis/kyber" "github.com/harmony-one/bls/ffi/go/bls" - "github.com/harmony-one/harmony/crypto" - "github.com/harmony-one/harmony/crypto/pki" "github.com/harmony-one/harmony/p2p" p2p_crypto "github.com/libp2p/go-libp2p-crypto" ) @@ -75,16 +72,8 @@ func GetUniqueIDFromIPPort(ip, port string) uint32 { return uint32(value) } -// GenKey generates a key given ip and port. -func GenKey(ip, port string) (kyber.Scalar, kyber.Point) { - priKey := crypto.Ed25519Curve.Scalar().SetInt64(int64(GetUniqueIDFromIPPort(ip, port))) // TODO: figure out why using a random hash value doesn't work for private key (schnorr) - pubKey := pki.GetPublicKeyFromScalar(priKey) - - return priKey, pubKey -} - -// GenKeyBLS generates a bls key pair given ip and port. -func GenKeyBLS(ip, port string) (*bls.SecretKey, *bls.PublicKey) { +// GenKey generates a bls key pair given ip and port. +func GenKey(ip, port string) (*bls.SecretKey, *bls.PublicKey) { nodeIDBytes := make([]byte, 32) binary.LittleEndian.PutUint32(nodeIDBytes, GetUniqueIDFromIPPort(ip, port)) privateKey := bls.SecretKey{} diff --git a/internal/utils/utils_test.go b/internal/utils/utils_test.go index ad0838126..4a813a2ef 100644 --- a/internal/utils/utils_test.go +++ b/internal/utils/utils_test.go @@ -48,12 +48,7 @@ func TestAllocateShard(t *testing.T) { // Test for GenKey func TestGenKey(t *testing.T) { - GenKey("3.3.3.3", "3456") -} - -// Test for GenKeyBLS -func TestGenKeyBLS(t *testing.T) { - priKey, pubKey := GenKeyBLS("3.3.3.3", "3456") + priKey, pubKey := GenKey("3.3.3.3", "3456") if priKey == nil || pubKey == nil { t.Error("Failed to create keys for BLS sig") } diff --git a/node/node_handler_test.go b/node/node_handler_test.go index 9b347bf8f..f24a0e6cb 100644 --- a/node/node_handler_test.go +++ b/node/node_handler_test.go @@ -11,7 +11,7 @@ import ( ) func TestNodeStreamHandler(t *testing.T) { - _, pubKey := utils.GenKeyBLS("1", "2") + _, pubKey := utils.GenKey("1", "2") leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") @@ -35,7 +35,7 @@ func TestNodeStreamHandler(t *testing.T) { } func TestAddNewBlock(t *testing.T) { - _, pubKey := utils.GenKeyBLS("1", "2") + _, pubKey := utils.GenKey("1", "2") leader := p2p.Peer{IP: "127.0.0.1", Port: "9882", PubKey: pubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "9885"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") @@ -58,7 +58,7 @@ func TestAddNewBlock(t *testing.T) { } func TestVerifyNewBlock(t *testing.T) { - _, pubKey := utils.GenKeyBLS("1", "2") + _, pubKey := utils.GenKey("1", "2") leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") diff --git a/node/node_test.go b/node/node_test.go index 26a08cb3d..3e51c9040 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -15,7 +15,7 @@ import ( ) func TestNewNode(t *testing.T) { - _, pubKey := utils.GenKeyBLS("1", "2") + _, pubKey := utils.GenKey("1", "2") leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") @@ -39,7 +39,7 @@ func TestNewNode(t *testing.T) { } func TestGetSyncingPeers(t *testing.T) { - _, pubKey := utils.GenKeyBLS("1", "2") + _, pubKey := utils.GenKey("1", "2") leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") @@ -82,7 +82,7 @@ func TestAddPeers(t *testing.T) { ValidatorID: 2, }, } - _, pubKey := utils.GenKeyBLS("1", "2") + _, pubKey := utils.GenKey("1", "2") leader := p2p.Peer{IP: "127.0.0.1", Port: "8982", PubKey: pubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "8985"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") @@ -156,7 +156,7 @@ func exitServer() { } func TestPingPongHandler(t *testing.T) { - _, pubKey := utils.GenKeyBLS("127.0.0.1", "8881") + _, pubKey := utils.GenKey("127.0.0.1", "8881") leader := p2p.Peer{IP: "127.0.0.1", Port: "8881", PubKey: pubKey} // validator := p2p.Peer{IP: "127.0.0.1", Port: "9991"} priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") diff --git a/vendor/github.com/dedis/kyber b/vendor/github.com/dedis/kyber deleted file mode 160000 index 5cc646019..000000000 --- a/vendor/github.com/dedis/kyber +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5cc64601919b0945d10aba014129cdfef5fdda46