Merge pull request #582 from harmony-one/rj_branch

Use genesis BLS key for beacon chain nodes; Check resharding effect
pull/590/head
Rongjian Lan 6 years ago committed by GitHub
commit 25e3303b67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      cmd/client/txgen/main.go
  2. 21
      cmd/harmony/main.go
  3. 22
      consensus/consensus.go
  4. 2
      consensus/consensus_leader.go
  5. 6
      consensus/consensus_leader_msg_test.go
  6. 32
      consensus/consensus_leader_test.go
  7. 12
      consensus/consensus_test.go
  8. 2
      consensus/consensus_validator.go
  9. 6
      consensus/consensus_validator_msg_test.go
  10. 23
      consensus/consensus_validator_test.go
  11. 17
      core/blockchain.go
  12. 15
      core/resharding.go
  13. 7
      crypto/bls/bls.go
  14. 13
      drand/drand.go
  15. 6
      drand/drand_leader_msg_test.go
  16. 20
      drand/drand_test.go
  17. 6
      drand/drand_validator_msg_test.go
  18. 2
      node/contract_test.go
  19. 44
      node/node_handler.go
  20. 4
      node/node_handler_test.go
  21. 14
      node/node_test.go
  22. 2
      node/staking_test.go
  23. 5
      test/deploy_newnode.sh

@ -118,7 +118,7 @@ func main() {
}
// Client/txgenerator server node setup
consensusObj := consensus.New(host, "0", nil, p2p.Peer{})
consensusObj := consensus.New(host, "0", nil, p2p.Peer{}, nil)
clientNode := node.New(host, consensusObj, nil)
clientNode.Client = client.NewClient(clientNode.GetHost(), shardIDs)

@ -7,8 +7,11 @@ import (
"os"
"path"
"runtime"
"strconv"
"time"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/internal/utils/contract"
"github.com/ethereum/go-ethereum/ethdb"
@ -124,10 +127,20 @@ func createGlobalConfig() *nodeconfig.ConfigType {
// Key Setup ================= [Start]
// Staking private key is the ecdsa key used for token related transaction signing (especially the staking txs).
stakingPriKey := ""
consensusPriKey := &bls.SecretKey{}
if *isBeacon {
stakingPriKey = contract.InitialBeaconChainAccounts[*accountIndex].Private
// TODO: use a better way to get the index for accounts.
portNum, _ := strconv.Atoi(*port)
index := portNum % 10
stakingPriKey = contract.InitialBeaconChainAccounts[index].Private
err := consensusPriKey.SetHexString(contract.InitialBeaconChainBLSAccounts[index].Private)
if err != nil {
panic(fmt.Errorf("generate key error"))
}
} else {
stakingPriKey = contract.NewNodeAccounts[*accountIndex].Private
// TODO: use user supplied key
consensusPriKey, _ = utils.GenKey(*ip, *port)
}
nodeConfig.StakingPriKey = node.StoreStakingKeyFromFile(*stakingKeyFile, stakingPriKey)
@ -138,7 +151,7 @@ func createGlobalConfig() *nodeconfig.ConfigType {
}
// Consensus keys are the BLS12-381 keys used to sign consensus messages
nodeConfig.ConsensusPriKey, nodeConfig.ConsensusPubKey = utils.GenKey(*ip, *port)
nodeConfig.ConsensusPriKey, nodeConfig.ConsensusPubKey = consensusPriKey, consensusPriKey.GetPublicKey()
if nodeConfig.ConsensusPriKey == nil || nodeConfig.ConsensusPubKey == nil {
panic(fmt.Errorf("generate key error"))
}
@ -179,7 +192,7 @@ func setUpConsensusAndNode(nodeConfig *nodeconfig.ConfigType) (*consensus.Consen
// Consensus object.
// TODO: consensus object shouldn't start here
// TODO(minhdoan): During refactoring, found out that the peers list is actually empty. Need to clean up the logic of consensus later.
consensus := consensus.New(nodeConfig.Host, nodeConfig.ShardIDString, []p2p.Peer{}, nodeConfig.Leader)
consensus := consensus.New(nodeConfig.Host, nodeConfig.ShardIDString, []p2p.Peer{}, nodeConfig.Leader, nodeConfig.ConsensusPriKey)
consensus.MinPeers = *minPeers
// Current node.
@ -215,7 +228,7 @@ func setUpConsensusAndNode(nodeConfig *nodeconfig.ConfigType) (*consensus.Consen
// TODO: enable drand only for beacon chain
// TODO: put this in a better place other than main.
// TODO(minhdoan): During refactoring, found out that the peers list is actually empty. Need to clean up the logic of drand later.
dRand := drand.New(nodeConfig.Host, nodeConfig.ShardIDString, []p2p.Peer{}, nodeConfig.Leader, currentNode.ConfirmedBlockChannel, *isLeader)
dRand := drand.New(nodeConfig.Host, nodeConfig.ShardIDString, []p2p.Peer{}, nodeConfig.Leader, currentNode.ConfirmedBlockChannel, *isLeader, nodeConfig.ConsensusPriKey)
currentNode.Consensus.RegisterPRndChannel(dRand.PRndChannel)
currentNode.Consensus.RegisterRndChannel(dRand.RndChannel)
currentNode.DRand = dRand

@ -4,7 +4,6 @@ package consensus // consensus
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
@ -62,7 +61,7 @@ type Consensus struct {
// private/public keys of current node
priKey *bls.SecretKey
pubKey *bls.PublicKey
PubKey *bls.PublicKey
// Whether I am leader. False means I am validator
IsLeader bool
@ -170,7 +169,7 @@ func (consensus *Consensus) GetNextRnd() ([32]byte, [32]byte, error) {
// New creates a new Consensus object
// TODO: put shardId into chain reader's chain config
func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer) *Consensus {
func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer, blsPriKey *bls.SecretKey) *Consensus {
consensus := Consensus{}
consensus.host = host
@ -210,13 +209,10 @@ func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer) *Cons
// TODO: populate Id derived from address
consensus.nodeID = utils.GetUniqueIDFromPeer(selfPeer)
// Set private key for myself so that I can sign messages.
nodeIDBytes := make([]byte, 32)
binary.LittleEndian.PutUint32(nodeIDBytes, consensus.nodeID)
privateKey := bls.SecretKey{}
err := privateKey.SetLittleEndian(nodeIDBytes)
consensus.priKey = &privateKey
consensus.pubKey = privateKey.GetPublicKey()
if blsPriKey != nil {
consensus.priKey = blsPriKey
consensus.PubKey = blsPriKey.GetPublicKey()
}
consensus.consensusID = 0 // or view Id in the original pbft paper
@ -242,7 +238,7 @@ func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer) *Cons
consensus.uniqueIDInstance = utils.GetUniqueValidatorIDInstance()
consensus.OfflinePeerList = make([]p2p.Peer, 0)
// consensus.Log.Info("New Consensus", "IP", ip, "Port", port, "NodeID", consensus.nodeID, "priKey", consensus.priKey, "pubKey", consensus.pubKey)
// consensus.Log.Info("New Consensus", "IP", ip, "Port", port, "NodeID", consensus.nodeID, "priKey", consensus.priKey, "PubKey", consensus.PubKey)
return &consensus
}
@ -404,8 +400,8 @@ func (consensus *Consensus) String() string {
} else {
duty = "VLD" // validator
}
return fmt.Sprintf("[duty:%s, pubKey:%s, ShardID:%v, nodeID:%v, state:%s]",
duty, hex.EncodeToString(consensus.pubKey.Serialize()), consensus.ShardID, consensus.nodeID, consensus.state)
return fmt.Sprintf("[duty:%s, PubKey:%s, ShardID:%v, nodeID:%v, state:%s]",
duty, hex.EncodeToString(consensus.PubKey.Serialize()), consensus.ShardID, consensus.nodeID, consensus.state)
}
// AddPeers adds new peers into the validator map of the consensus

@ -350,7 +350,7 @@ func (consensus *Consensus) reportMetrics(block types.Block) {
txHashes = append(txHashes, hex.EncodeToString(txHash[:]))
}
metrics := map[string]interface{}{
"key": hex.EncodeToString(consensus.pubKey.Serialize()),
"key": hex.EncodeToString(consensus.PubKey.Serialize()),
"tps": tps,
"txCount": numOfTxs,
"nodeCount": len(consensus.PublicKeys) + 1,

@ -3,6 +3,8 @@ package consensus
import (
"testing"
"github.com/harmony-one/harmony/crypto/bls"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -19,7 +21,7 @@ func TestConstructAnnounceMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
consensus.blockHash = [32]byte{}
message := &msg_pb.Message{}
@ -45,7 +47,7 @@ func TestConstructPreparedMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
consensus.blockHash = [32]byte{}
message := "test string"

@ -6,6 +6,8 @@ import (
"testing"
"time"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/ethereum/go-ethereum/rlp"
"github.com/golang/mock/gomock"
protobuf "github.com/golang/protobuf/proto"
@ -30,15 +32,17 @@ func TestProcessMessageLeaderPrepare(test *testing.T) {
defer ctrl.Finish()
leader := p2p.Peer{IP: ip, Port: "7777"}
_, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
var priKey *bls.SecretKey
priKey, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
validators := make([]p2p.Peer, 3)
hosts := make([]p2p.Host, 3)
validatorsPriKeys := [3]*bls.SecretKey{}
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].ConsensusPubKey = utils.GenKey(validators[i].IP, validators[i].Port)
validatorsPriKeys[i], validators[i].ConsensusPubKey = utils.GenKey(validators[i].IP, validators[i].Port)
}
m := mock_host.NewMockHost(ctrl)
@ -47,7 +51,7 @@ func TestProcessMessageLeaderPrepare(test *testing.T) {
m.EXPECT().GetSelfPeer().Return(leader)
m.EXPECT().SendMessageToGroups([]p2p.GroupID{p2p.GroupIDBeacon}, gomock.Any())
consensusLeader := New(m, "0", validators, leader)
consensusLeader := New(m, "0", validators, leader, priKey)
consensusLeader.blockHash = blockHash
consensusValidators := make([]*Consensus, 3)
@ -59,7 +63,7 @@ func TestProcessMessageLeaderPrepare(test *testing.T) {
}
hosts[i] = host
consensusValidators[i] = New(hosts[i], "0", validators, leader)
consensusValidators[i] = New(hosts[i], "0", validators, leader, validatorsPriKeys[i])
consensusValidators[i].blockHash = blockHash
msg := consensusValidators[i].constructPrepareMessage()
msgPayload, _ := proto.GetConsensusMessagePayload(msg)
@ -76,15 +80,17 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) {
defer ctrl.Finish()
leader := p2p.Peer{IP: ip, Port: "7777"}
_, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
var priKey *bls.SecretKey
priKey, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
validators := make([]p2p.Peer, 3)
hosts := make([]p2p.Host, 3)
validatorKeys := [3]*bls.SecretKey{}
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].ConsensusPubKey = utils.GenKey(validators[i].IP, validators[i].Port)
validatorKeys[i], validators[i].ConsensusPubKey = utils.GenKey(validators[i].IP, validators[i].Port)
}
m := mock_host.NewMockHost(ctrl)
@ -92,7 +98,7 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) {
// Anything else will fail.
m.EXPECT().GetSelfPeer().Return(leader)
consensusLeader := New(m, "0", validators, leader)
consensusLeader := New(m, "0", validators, leader, priKey)
consensusLeader.blockHash = blockHash
consensusValidators := make([]*Consensus, 3)
@ -104,7 +110,7 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) {
}
hosts[i] = host
consensusValidators[i] = New(hosts[i], "0", validators, leader)
consensusValidators[i] = New(hosts[i], "0", validators, leader, validatorKeys[i])
consensusValidators[i].blockHash = blockHash
msgBytes := consensusValidators[i].constructPrepareMessage()
msgPayload, _ := proto.GetConsensusMessagePayload(msgBytes)
@ -130,15 +136,17 @@ func TestProcessMessageLeaderCommit(test *testing.T) {
defer ctrl.Finish()
leader := p2p.Peer{IP: ip, Port: "8889"}
_, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
var priKey *bls.SecretKey
priKey, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
validators := make([]p2p.Peer, 3)
hosts := make([]p2p.Host, 3)
validatorKeys := [3]*bls.SecretKey{}
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].ConsensusPubKey = utils.GenKey(validators[i].IP, validators[i].Port)
validatorKeys[i], validators[i].ConsensusPubKey = utils.GenKey(validators[i].IP, validators[i].Port)
}
m := mock_host.NewMockHost(ctrl)
@ -156,7 +164,7 @@ func TestProcessMessageLeaderCommit(test *testing.T) {
hosts[i] = host
}
consensusLeader := New(m, "0", validators, leader)
consensusLeader := New(m, "0", validators, leader, priKey)
consensusLeader.state = PreparedDone
consensusLeader.blockHash = blockHash
consensusLeader.OnConsensusDone = func(newBlock *types.Block) {}
@ -174,7 +182,7 @@ func TestProcessMessageLeaderCommit(test *testing.T) {
<-consensusLeader.ReadySignal
}()
for i := 0; i < 3; i++ {
consensusValidators[i] = New(hosts[i], "0", validators, leader)
consensusValidators[i] = New(hosts[i], "0", validators, leader, validatorKeys[i])
consensusValidators[i].blockHash = blockHash
payload := consensusValidators[i].constructCommitMessage(multiSigAndBitmap)
msg, err := proto.GetConsensusMessagePayload(payload)

@ -4,6 +4,8 @@ import (
"bytes"
"testing"
"github.com/harmony-one/harmony/crypto/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/p2p"
@ -18,7 +20,7 @@ func TestNew(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
if consensus.consensusID != 0 {
test.Errorf("Consensus Id is initialized to the wrong value: %d", consensus.consensusID)
}
@ -54,7 +56,7 @@ func TestRemovePeers(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", peers, leader)
consensus := New(host, "0", peers, leader, nil)
// consensus.DebugPrintPublicKeys()
f := consensus.RemovePeers(peerRemove)
@ -72,7 +74,7 @@ func TestGetPeerFromID(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
leaderID := utils.GetUniqueIDFromIPPort(leader.IP, leader.Port)
validatorID := utils.GetUniqueIDFromIPPort(validator.IP, validator.Port)
l, _ := consensus.GetPeerFromID(leaderID)
@ -93,7 +95,7 @@ func TestPopulateMessageFields(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
consensus.consensusID = 2
consensus.blockHash = blockHash
consensus.nodeID = 3
@ -125,7 +127,7 @@ func TestSignAndMarshalConsensusMessage(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
consensus.consensusID = 2
consensus.blockHash = blockHash
consensus.nodeID = 3

@ -176,7 +176,7 @@ func (consensus *Consensus) processPreparedMessage(message *msg_pb.Message) {
mask, err := bls_cosi.NewMask(consensus.PublicKeys, nil)
mask.SetMask(bitmap)
if !deserializedMultiSig.VerifyHash(mask.AggregatePublic, blockHash) || err != nil {
utils.GetLogInstance().Warn("Failed to verify the multi signature for prepare phase", "Error", err, "leader ID", leaderID)
utils.GetLogInstance().Warn("Failed to verify the multi signature for prepare phase", "Error", err, "leader ID", leaderID, "PubKeys", len(consensus.PublicKeys))
return
}
consensus.aggregatedPrepareSig = &deserializedMultiSig

@ -3,6 +3,8 @@ package consensus
import (
"testing"
"github.com/harmony-one/harmony/crypto/bls"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -19,7 +21,7 @@ func TestConstructPrepareMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
consensus.blockHash = [32]byte{}
msgBytes := consensus.constructPrepareMessage()
msgBytes, err = proto.GetConsensusMessagePayload(msgBytes)
@ -45,7 +47,7 @@ func TestConstructCommitMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := New(host, "0", []p2p.Peer{leader, validator}, leader, bls.RandPrivateKey())
consensus.blockHash = [32]byte{}
msg := consensus.constructCommitMessage([]byte("random string"))
msg, err = proto.GetConsensusMessagePayload(msg)

@ -5,6 +5,8 @@ import (
"testing"
"time"
"github.com/harmony-one/bls/ffi/go/bls"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
@ -53,7 +55,8 @@ func TestProcessMessageValidatorAnnounce(test *testing.T) {
defer ctrl.Finish()
leader := p2p.Peer{IP: "127.0.0.1", Port: "9982"}
_, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
var leaderPriKey *bls.SecretKey
leaderPriKey, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
validator1 := p2p.Peer{IP: "127.0.0.1", Port: "9984", ValidatorID: 1}
_, validator1.ConsensusPubKey = utils.GenKey(validator1.IP, validator1.Port)
@ -73,7 +76,7 @@ func TestProcessMessageValidatorAnnounce(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensusLeader := New(host, "0", []p2p.Peer{validator1, validator2, validator3}, leader)
consensusLeader := New(host, "0", []p2p.Peer{validator1, validator2, validator3}, leader, leaderPriKey)
blockBytes, err := hex.DecodeString("f902a5f902a0a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a02b418211410ee3e75b32abd925bbeba215172afa509d65c1953d4b4e505a4a2aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808502540be400808080a000000000000000000000000000000000000000000000000000000000000000008800000000000000008400000001b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000c0c0")
consensusLeader.block = blockBytes
hashBytes, err := hex.DecodeString("bdd66a8211ffcbf0ad431b506c854b49264951fd9f690928e9cf44910c381053")
@ -91,7 +94,7 @@ func TestProcessMessageValidatorAnnounce(test *testing.T) {
test.Errorf("Failed to unmarshal message payload")
}
consensusValidator1 := New(m, "0", []p2p.Peer{validator1, validator2, validator3}, leader)
consensusValidator1 := New(m, "0", []p2p.Peer{validator1, validator2, validator3}, leader, bls_cosi.RandPrivateKey())
consensusValidator1.ChainReader = MockChainReader{}
copy(consensusValidator1.blockHash[:], hashBytes[:])
@ -107,7 +110,8 @@ func TestProcessMessageValidatorPrepared(test *testing.T) {
defer ctrl.Finish()
leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"}
_, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
var leaderPriKey *bls.SecretKey
leaderPriKey, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1}
_, validator1.ConsensusPubKey = utils.GenKey(validator1.IP, validator1.Port)
@ -127,7 +131,7 @@ func TestProcessMessageValidatorPrepared(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
consensusLeader := New(host, "0", []p2p.Peer{validator1, validator2, validator3}, leader)
consensusLeader := New(host, "0", []p2p.Peer{validator1, validator2, validator3}, leader, leaderPriKey)
blockBytes, err := hex.DecodeString("f902a5f902a0a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a02b418211410ee3e75b32abd925bbeba215172afa509d65c1953d4b4e505a4a2aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808502540be400808080a000000000000000000000000000000000000000000000000000000000000000008800000000000000008400000001b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000c0c0")
consensusLeader.block = blockBytes
hashBytes, err := hex.DecodeString("bdd66a8211ffcbf0ad431b506c854b49264951fd9f690928e9cf44910c381053")
@ -139,7 +143,7 @@ func TestProcessMessageValidatorPrepared(test *testing.T) {
preparedMsg, _ := consensusLeader.constructPreparedMessage()
consensusValidator1 := New(m, "0", []p2p.Peer{validator1, validator2, validator3}, leader)
consensusValidator1 := New(m, "0", []p2p.Peer{validator1, validator2, validator3}, leader, bls_cosi.RandPrivateKey())
consensusValidator1.ChainReader = MockChainReader{}
// Get actual consensus messages.
@ -175,7 +179,8 @@ func TestProcessMessageValidatorCommitted(test *testing.T) {
defer ctrl.Finish()
leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"}
_, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
var leaderPriKey *bls.SecretKey
leaderPriKey, leader.ConsensusPubKey = utils.GenKey(leader.IP, leader.Port)
validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1}
_, validator1.ConsensusPubKey = utils.GenKey(validator1.IP, validator1.Port)
@ -196,7 +201,7 @@ func TestProcessMessageValidatorCommitted(test *testing.T) {
test.Fatalf("newhost failure: %v", err)
}
message := &msg_pb.Message{}
consensusLeader := New(host, "0", []p2p.Peer{validator1, validator2, validator3}, leader)
consensusLeader := New(host, "0", []p2p.Peer{validator1, validator2, validator3}, leader, leaderPriKey)
blockBytes, err := hex.DecodeString("f902a5f902a0a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a02b418211410ee3e75b32abd925bbeba215172afa509d65c1953d4b4e505a4a2aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808502540be400808080a000000000000000000000000000000000000000000000000000000000000000008800000000000000008400000001b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000c0c0")
consensusLeader.block = blockBytes
hashBytes, err := hex.DecodeString("bdd66a8211ffcbf0ad431b506c854b49264951fd9f690928e9cf44910c381053")
@ -227,7 +232,7 @@ func TestProcessMessageValidatorCommitted(test *testing.T) {
test.Errorf("Failed to get consensus message")
}
consensusValidator1 := New(m, "0", []p2p.Peer{validator1, validator2, validator3}, leader)
consensusValidator1 := New(m, "0", []p2p.Peer{validator1, validator2, validator3}, leader, bls_cosi.RandPrivateKey())
consensusValidator1.ChainReader = MockChainReader{}
consensusValidator1.OnConsensusDone = func(newBlock *types.Block) {}

@ -1733,17 +1733,14 @@ func (bc *BlockChain) ValidateNewShardState(block *types.Block, stakeInfo *map[c
}
// StoreNewShardState insert new shard state into epoch block
func (bc *BlockChain) StoreNewShardState(block *types.Block, stakeInfo *map[common.Address]*structs.StakeInfo) {
func (bc *BlockChain) StoreNewShardState(block *types.Block, stakeInfo *map[common.Address]*structs.StakeInfo) types.ShardState {
// write state into db.
shardState := bc.GetNewShardState(block, stakeInfo)
if shardState == nil {
return
}
hash := block.Hash()
number := block.NumberU64()
rawdb.WriteShardState(bc.db, hash, number, shardState)
utils.GetLogInstance().Debug("[Resharding] Saved new shard state success", "shardStateHash", shardState.Hash())
for _, c := range shardState {
utils.GetLogInstance().Debug("[Resharding] Shard Info", "shardID", c.ShardID, "NodeList", c.NodeList)
if shardState != nil {
hash := block.Hash()
number := block.NumberU64()
rawdb.WriteShardState(bc.db, hash, number, shardState)
utils.GetLogInstance().Debug("[Resharding] Saved new shard state success", "state", shardState)
}
return shardState
}

@ -2,7 +2,6 @@ package core
import (
"encoding/binary"
"encoding/hex"
"math/rand"
"sort"
@ -151,8 +150,10 @@ func CalculateNewShardState(bc *BlockChain, epoch uint64, stakeInfo *map[common.
ss := GetShardingStateFromBlockChain(bc, epoch-1)
if epoch == FirstEpoch {
newNodes := []types.NodeID{}
for addr, stakeInfo := range *stakeInfo {
newNodes = append(newNodes, types.NodeID{addr.Hex(), hex.EncodeToString(stakeInfo.BlsAddress[:])})
blsAddr := common.BytesToAddress(stakeInfo.BlsAddress[:])
newNodes = append(newNodes, types.NodeID{addr.Hex(), blsAddr.Hex()})
}
rand.Seed(int64(ss.rnd))
Shuffle(newNodes)
@ -191,7 +192,7 @@ func (ss *ShardingState) UpdateShardingState(stakeInfo *map[common.Address]*stru
for addr, info := range *stakeInfo {
_, ok := oldAddresses[addr.Hex()]
if !ok {
newAddresses = append(newAddresses, types.NodeID{hex.EncodeToString(info.BlsAddress[:]), addr.Hex()})
newAddresses = append(newAddresses, types.NodeID{addr.Hex(), common.BytesToAddress(info.BlsAddress[:]).Hex()})
}
}
return newAddresses
@ -208,9 +209,13 @@ func GetInitShardState() types.ShardState {
priKey := bls.SecretKey{}
priKey.SetHexString(contract.InitialBeaconChainBLSAccounts[j].Private)
addrBytes := priKey.GetPublicKey().GetAddress()
blsAddr := hex.EncodeToString(addrBytes[:])
blsAddr := common.BytesToAddress(addrBytes[:]).Hex()
// TODO: directly read address for bls too
com.NodeList = append(com.NodeList, types.NodeID{blsAddr, contract.InitialBeaconChainAccounts[j].Address})
curNodeID := types.NodeID{contract.InitialBeaconChainAccounts[j].Address, blsAddr}
if j == 0 {
com.Leader = curNodeID
}
com.NodeList = append(com.NodeList, curNodeID)
}
}
shardState = append(shardState, com)

@ -11,6 +11,13 @@ func init() {
bls.Init(bls.BLS12_381)
}
// RandPrivateKey returns a random private key.
func RandPrivateKey() *bls.SecretKey {
sec := bls.SecretKey{}
sec.SetByCSPRNG()
return &sec
}
// AggregateSig aggregates all the BLS signature into a single multi-signature.
func AggregateSig(sigs []*bls.Sign) *bls.Sign {
var aggregatedSig bls.Sign

@ -2,7 +2,6 @@ package drand
import (
"crypto/sha256"
"encoding/binary"
"errors"
"strconv"
"sync"
@ -67,7 +66,7 @@ type DRand struct {
}
// New creates a new dRand object
func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer, confirmedBlockChannel chan *types.Block, isLeader bool) *DRand {
func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer, confirmedBlockChannel chan *types.Block, isLeader bool, blsPriKey *bls.SecretKey) *DRand {
dRand := DRand{}
dRand.host = host
@ -108,12 +107,10 @@ func New(host p2p.Host, ShardID string, peers []p2p.Peer, leader p2p.Peer, confi
dRand.nodeID = utils.GetUniqueIDFromPeer(selfPeer)
// Set private key for myself so that I can sign messages.
nodeIDBytes := make([]byte, 32)
binary.LittleEndian.PutUint32(nodeIDBytes, dRand.nodeID)
privateKey := bls.SecretKey{}
err := privateKey.SetLittleEndian(nodeIDBytes)
dRand.priKey = &privateKey
dRand.pubKey = privateKey.GetPublicKey()
if blsPriKey != nil {
dRand.priKey = blsPriKey
dRand.pubKey = blsPriKey.GetPublicKey()
}
// VRF keys
priKey, pubKey := p256.GenerateKey()

@ -3,6 +3,8 @@ package drand
import (
"testing"
"github.com/harmony-one/harmony/crypto/bls"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -19,7 +21,7 @@ func TestConstructInitMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls.RandPrivateKey())
dRand.blockHash = [32]byte{}
msg := dRand.constructInitMessage()
@ -41,7 +43,7 @@ func TestProcessCommitMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls.RandPrivateKey())
dRand.blockHash = [32]byte{}
msg := dRand.constructCommitMessage([32]byte{}, []byte{})

@ -5,6 +5,8 @@ import (
"strings"
"testing"
bls2 "github.com/harmony-one/harmony/crypto/bls"
"github.com/ethereum/go-ethereum/common"
"github.com/harmony-one/bls/ffi/go/bls"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -22,7 +24,7 @@ func TestNew(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
if !dRand.IsLeader {
test.Error("dRand should belong to a leader")
@ -37,7 +39,7 @@ func TestGetValidatorPeers(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
if !dRand.IsLeader {
test.Error("dRand should belong to a leader")
@ -58,7 +60,7 @@ func TestAddPeers(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
if !dRand.IsLeader {
test.Error("dRand should belong to a leader")
@ -84,7 +86,7 @@ func TestGetValidatorByPeerId(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
if !dRand.IsLeader {
test.Error("dRand should belong to a leader")
@ -111,7 +113,7 @@ func TestResetState(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
dRand.ResetState()
}
@ -123,7 +125,7 @@ func TestSetLeaderPubKey(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
_, newPublicKey, _ := utils.GenKeyP2P("127.0.0.1", "9902")
newPublicKeyBytes, _ := newPublicKey.Bytes()
@ -140,7 +142,7 @@ func TestUpdatePublicKeys(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
_, pubKey1 := utils.GenKey("127.0.0.1", "5555")
_, pubKey2 := utils.GenKey("127.0.0.1", "6666")
@ -166,7 +168,7 @@ func TestVerifyMessageSig(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
message := &msg_pb.Message{
ReceiverType: msg_pb.ReceiverType_VALIDATOR,
@ -195,7 +197,7 @@ func TestVrf(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls2.RandPrivateKey())
tx1 := types.NewTransaction(1, common.BytesToAddress([]byte{0x11}), 0, big.NewInt(111), 1111, big.NewInt(11111), []byte{0x11, 0x11, 0x11})
txs := []*types.Transaction{tx1}

@ -3,6 +3,8 @@ package drand
import (
"testing"
"github.com/harmony-one/harmony/crypto/bls"
protobuf "github.com/golang/protobuf/proto"
"github.com/harmony-one/harmony/api/proto"
msg_pb "github.com/harmony-one/harmony/api/proto/message"
@ -19,7 +21,7 @@ func TestConstructCommitMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls.RandPrivateKey())
dRand.blockHash = [32]byte{}
msg := dRand.constructCommitMessage([32]byte{}, []byte{})
msgPayload, _ := proto.GetDRandMessagePayload(msg)
@ -40,7 +42,7 @@ func TestProcessInitMessage(test *testing.T) {
if err != nil {
test.Fatalf("newhost failure: %v", err)
}
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
dRand := New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, bls.RandPrivateKey())
dRand.blockHash = [32]byte{}
msg := dRand.constructInitMessage()

@ -18,7 +18,7 @@ func prepareNode(t *testing.T) *Node {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
return New(host, consensus, nil)
}

@ -3,9 +3,12 @@ package node
import (
"bytes"
"context"
"math"
"os"
"time"
"github.com/harmony-one/harmony/core"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
pb "github.com/golang/protobuf/proto"
@ -289,7 +292,46 @@ func (node *Node) PostConsensusProcessing(newBlock *types.Block) {
utils.GetLogInstance().Info("Updating staking list")
node.UpdateStakingList(node.QueryStakeInfo())
node.printStakingList()
node.blockchain.StoreNewShardState(newBlock, &node.CurrentStakes)
if core.IsEpochBlock(newBlock) {
shardState := node.blockchain.StoreNewShardState(newBlock, &node.CurrentStakes)
if shardState != nil {
myShard := uint32(math.MaxUint32)
isLeader := false
for _, shard := range shardState {
for _, nodeID := range shard.NodeList {
blsAddr := node.Consensus.PubKey.GetAddress()
blsAddrStr := common.BytesToAddress(blsAddr[:]).Hex()
if nodeID.BlsAddress == blsAddrStr {
myShard = shard.ShardID
isLeader = shard.Leader == nodeID
}
}
}
if myShard != uint32(math.MaxUint32) {
aboutLeader := ""
if node.Consensus.IsLeader {
aboutLeader = "I am not leader anymore"
if isLeader {
aboutLeader = "I am still leader"
}
} else {
aboutLeader = "I am still validator"
if isLeader {
aboutLeader = "I become the leader"
}
}
if node.blockchain.ShardID() == myShard {
utils.GetLogInstance().Info("[Resharding] I stay at", "shardID", myShard, "leader")
} else {
utils.GetLogInstance().Info("[Resharding] I got resharded to", "shardID", myShard, "isLeader", isLeader)
}
utils.GetLogInstance().Info("[Resharding] " + aboutLeader)
} else {
utils.GetLogInstance().Info("[Resharding] Somehow I got kicked out")
}
}
}
}
// AddNewBlock is usedd to add new block into the blockchain.

@ -18,7 +18,7 @@ func TestAddNewBlock(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
node := New(host, consensus, nil)
selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock)
@ -41,7 +41,7 @@ func TestVerifyNewBlock(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
node := New(host, consensus, nil)
selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock)

@ -26,7 +26,7 @@ func TestNewNode(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
node := New(host, consensus, nil)
if node.Consensus == nil {
t.Error("Consensus is not initialized for the node")
@ -51,7 +51,7 @@ func TestGetSyncingPeers(t *testing.T) {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
node := New(host, consensus, nil)
peer := p2p.Peer{IP: "127.0.0.1", Port: "8000"}
@ -93,8 +93,8 @@ func TestAddPeers(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
dRand := drand.New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
dRand := drand.New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, nil)
node := New(host, consensus, nil)
node.DRand = dRand
@ -138,8 +138,8 @@ func TestAddBeaconPeer(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
dRand := drand.New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
dRand := drand.New(host, "0", []p2p.Peer{leader, validator}, leader, nil, true, nil)
node := New(host, consensus, nil)
node.DRand = dRand
@ -209,7 +209,7 @@ func TestPingPongHandler(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader}, leader, nil)
node := New(host, consensus, nil)
//go sendPingMessage(leader)
go sendPongMessage(node, leader)

@ -31,7 +31,7 @@ func TestUpdateStakingList(t *testing.T) {
if err != nil {
t.Fatalf("newhost failure: %v", err)
}
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader)
consensus := consensus.New(host, "0", []p2p.Peer{leader, validator}, leader, nil)
node := New(host, consensus, nil)
for i := 0; i < 5; i++ {

@ -119,8 +119,9 @@ HMY_OPT=
HMY_OPT2=
HMY_OPT3=
for i in {0..4}
for i in 0{1..9} {10..99}
do
echo "launching new node $i ..."
($DRYRUN $ROOT/bin/harmony -ip 127.0.0.1 -port 910$i -log_folder $log_folder -is_newnode $DB -account_index $i -min_peers $MIN $HMY_OPT $HMY_OPT2 $HMY_OPT3 -key /tmp/127.0.0.1-910$i.key 2>&1 | tee -a $LOG_FILE ) &
($DRYRUN $ROOT/bin/harmony -ip 127.0.0.1 -port 91$i -log_folder $log_folder -is_newnode $DB -account_index $i -min_peers $MIN $HMY_OPT $HMY_OPT2 $HMY_OPT3 -key /tmp/127.0.0.1-91$i.key 2>&1 | tee -a $LOG_FILE ) &
sleep 3
done

Loading…
Cancel
Save