Merge pull request #126 from harmony-one/HAR-78_BeaconChain

HAR-78_Candidate_Node_Connects_BeaconChain
pull/128/head
alajko 6 years ago committed by GitHub
commit 40e13172c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 97
      beaconchain/beaconchain.go
  2. 36
      beaconchain/beaconchain_handler.go
  3. 23
      beaconchain/beaconchain_test.go
  4. 55
      benchmark.go
  5. 3
      deploy.sh
  6. 191
      newnode/newnode.go
  7. 63
      newnode/newnode_handler.go
  8. 18
      newnode/newnode_test.go
  9. 70
      proto/bcconn/bcconn.go
  10. 66
      proto/bcconn/bcconn_test.go
  11. 16
      runbeacon/run-beacon.go
  12. 19
      utils/utils.go

@ -1,7 +1,7 @@
package beaconchain
import (
"fmt"
"math/rand"
"net"
"os"
"sync"
@ -9,9 +9,10 @@ import (
"github.com/dedis/kyber"
"github.com/harmony-one/harmony/crypto/pki"
"github.com/harmony-one/harmony/log"
"github.com/harmony-one/harmony/node"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/proto/bcconn"
proto_identity "github.com/harmony-one/harmony/proto/identity"
"github.com/harmony-one/harmony/utils"
)
var mutex sync.Mutex
@ -19,83 +20,69 @@ var identityPerBlock = 100000
// BeaconChain (Blockchain) keeps Identities per epoch, currently centralized!
type BeaconChain struct {
//Identities []*IdentityBlock //No need to have the identity block as of now
Identities []*node.Node
Leaders []*bcconn.NodeInfo
log log.Logger
PeerToShardMap map[*node.Node]int
ShardLeaderMap map[int]*node.Node
ShardLeaderMap map[int]*bcconn.NodeInfo
PubKey kyber.Point
NumberOfShards int
NumberOfLeadersAdded int
NumberOfNodesAdded int
IP string
Port string
}
// New return BeaconChain.
func New(filename string) *BeaconChain {
idc := BeaconChain{}
//idc.NumberOfShards = readConfigFile(filename)
idc.log = log.New()
idc.NumberOfShards = 2
idc.PubKey = generateIDCKeys()
return &idc
}
func readConfigFile(filename string) int {
return 2
//New beaconchain initialization
func New(numShards int, ip, port string) *BeaconChain {
bc := BeaconChain{}
bc.log = log.New()
bc.NumberOfShards = numShards
bc.PubKey = generateIDCKeys()
bc.NumberOfNodesAdded = 0
bc.Port = port
bc.IP = ip
return &bc
}
func generateIDCKeys() kyber.Point {
priKey := pki.GetPrivateKeyFromInt(10)
r := rand.Intn(1000)
priKey := pki.GetPrivateKeyFromInt(r)
pubkey := pki.GetPublicKeyFromPrivateKey(priKey)
return pubkey
}
// AcceptConnections welcomes new connections
func (IDC *BeaconChain) AcceptConnections(b []byte) {
NewNode := node.DeserializeNode(b)
fmt.Println(NewNode)
}
func (IDC *BeaconChain) registerNode(Node *node.Node) {
IDC.Identities = append(IDC.Identities, Node)
fmt.Println(IDC.Identities)
//IDC.CommunicatePublicKeyToNode(Node.SelfPeer)
return
}
// CommunicatePublicKeyToNode communicates public key to node.
func (IDC *BeaconChain) CommunicatePublicKeyToNode(peer p2p.Peer) {
pbkey := pki.GetBytesFromPublicKey(IDC.PubKey)
msgToSend := proto_identity.ConstructIdentityMessage(proto_identity.Acknowledge, pbkey[:])
p2p.SendMessage(peer, msgToSend)
//AcceptConnections welcomes new connections
func (bc *BeaconChain) AcceptConnections(b []byte) {
Node := bcconn.DeserializeNodeInfo(b)
bc.log.Info("Obtained node information, updating local information")
bc.NumberOfNodesAdded = bc.NumberOfNodesAdded + 1
_, isLeader := utils.AllocateShard(bc.NumberOfNodesAdded, bc.NumberOfShards)
if isLeader {
bc.Leaders = append(bc.Leaders, Node)
}
response := bcconn.ResponseRandomNumber{NumberOfShards: bc.NumberOfShards, NumberOfNodesAdded: bc.NumberOfNodesAdded, Leaders: bc.Leaders}
msg := bcconn.SerializeRandomInfo(response)
msgToSend := proto_identity.ConstructIdentityMessage(proto_identity.Acknowledge, msg)
p2p.SendMessage(Node.Self, msgToSend)
}
//StartServer a server and process the request by a handler.
func (IDC *BeaconChain) StartServer() {
IDC.log.Info("Starting IDC server...") //log.Info does nothing for me! (ak)
IDC.listenOnPort()
}
func (IDC *BeaconChain) listenOnPort() {
addr := net.JoinHostPort("127.0.0.1", "8081")
func (bc *BeaconChain) StartServer() {
bc.log.Info("Starting Beaconchain server ...")
ip := bc.IP
port := bc.Port
addr := net.JoinHostPort(ip, port)
listen, err := net.Listen("tcp", addr)
if err != nil {
IDC.log.Crit("Socket listen port failed")
bc.log.Crit("Socket listen port failed")
os.Exit(1)
} else {
IDC.log.Info("Identity chain is now listening ..")
}
defer listen.Close()
for {
IDC.log.Info("I am accepting connections now")
bc.log.Info("beacon chain is now listening ..")
conn, err := listen.Accept()
fmt.Println(conn)
if err != nil {
IDC.log.Crit("Error listening on port. Exiting", "8081")
bc.log.Crit("Error listening on port. Exiting", "8081")
continue
} else {
IDC.log.Info("I am accepting connections now")
}
go IDC.BeaconChainHandler(conn)
go bc.BeaconChainHandler(conn)
}
}

@ -1,9 +1,7 @@
package beaconchain
import (
"fmt"
"net"
"os"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/proto"
@ -11,38 +9,31 @@ import (
)
// BeaconChainHandler handles registration of new Identities
// This could have been its seperate package like consensus, but am avoiding creating a lot of packages.
func (IDC *BeaconChain) BeaconChainHandler(conn net.Conn) {
func (bc *BeaconChain) BeaconChainHandler(conn net.Conn) {
content, err := p2p.ReadMessageContent(conn)
if err != nil {
IDC.log.Error("Read p2p data failed")
bc.log.Error("Read p2p data failed")
return
}
IDC.log.Info("received connection")
bc.log.Info("received connection", "connectionIp", conn.RemoteAddr())
msgCategory, err := proto.GetMessageCategory(content)
if err != nil {
IDC.log.Error("Read message category failed", "err", err)
bc.log.Error("Read message category failed", "err", err)
return
}
if msgCategory != proto.Identity {
IDC.log.Error("Identity Chain Recieved incorrect protocol message")
os.Exit(1)
} else {
fmt.Println("Message category is correct")
}
msgType, err := proto.GetMessageType(content)
if err != nil {
IDC.log.Error("Read action type failed")
bc.log.Error("Read action type failed")
return
}
msgPayload, err := proto.GetMessagePayload(content)
if err != nil {
IDC.log.Error("Read message payload failed")
bc.log.Error("Read message payload failed")
return
}
identityMsgPayload, err := proto_identity.GetIdentityMessagePayload(msgPayload)
if err != nil {
IDC.log.Error("Read message payload failed")
bc.log.Error("Read message payload failed")
return
}
switch msgCategory {
@ -50,17 +41,20 @@ func (IDC *BeaconChain) BeaconChainHandler(conn net.Conn) {
actionType := proto_identity.IDMessageType(msgType)
switch actionType {
case proto_identity.Identity:
bc.log.Info("Message category is of the type identity protocol, which is correct!")
idMsgType, err := proto_identity.GetIdentityMessageType(msgPayload)
if err != nil {
fmt.Println("Error finding the identity message type")
bc.log.Error("Error finding the identity message type")
}
switch idMsgType {
case proto_identity.Register:
IDC.AcceptConnections(identityMsgPayload)
case proto_identity.Acknowledge:
// IDC.acceptNewConnection(msgPayload)
bc.log.Info("Identity Message Type is of the type Register")
bc.AcceptConnections(identityMsgPayload)
default:
panic("Unrecognized identity message type")
}
default:
panic("Unrecognized message category")
}
}

@ -0,0 +1,23 @@
package beaconchain
import "testing"
func TestNewNode(t *testing.T) {
var ip, port string
ip = "127.0.0.1"
port = "8080"
numshards := 2
bc := New(numshards, ip, port)
if bc.PubKey == nil {
t.Error("beacon chain public key not initialized")
}
if bc.NumberOfNodesAdded != 0 {
t.Error("beacon chain number of nodes starting with is not zero! (should be zero)")
}
if bc.NumberOfShards != numshards {
t.Error("beacon chain number of shards not initialized to given number of desired shards")
}
}

@ -12,8 +12,8 @@ import (
"github.com/harmony-one/harmony/attack"
"github.com/harmony-one/harmony/consensus"
"github.com/harmony-one/harmony/db"
"github.com/harmony-one/harmony/discovery"
"github.com/harmony-one/harmony/log"
pkg_newnode "github.com/harmony-one/harmony/newnode"
"github.com/harmony-one/harmony/node"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/profiler"
@ -73,9 +73,11 @@ func loggingInit(logFolder, role, ip, port string, onlyLogTps bool) {
log.Root().SetHandler(h)
}
func main() {
accountModel := flag.Bool("account_model", true, "Whether to use account model")
// TODO: use http://getmyipaddress.org/ or http://www.get-myip.com/ to retrieve my IP address
ip := flag.String("ip", "127.0.0.1", "IP of the node")
port := flag.String("port", "9000", "port of the node.")
configFile := flag.String("config_file", "config.txt", "file containing all ip addresses")
@ -88,12 +90,12 @@ func main() {
syncNode := flag.Bool("sync_node", false, "Whether this node is a new node joining blockchain and it needs to get synced before joining consensus.")
onlyLogTps := flag.Bool("only_log_tps", false, "Only log TPS if true")
// This IP belongs to jenkins.harmony.one
idcIP := flag.String("idc", "54.183.5.66", "IP of the identity chain")
idcPort := flag.String("idc_port", "8080", "port of the identity chain")
peerDisvoery := flag.Bool("peer_discovery", false, "Enable Peer Discovery")
//This IP belongs to jenkins.harmony.one
idcIP := flag.String("idc", "127.0.0.1", "IP of the identity chain")
idcPort := flag.String("idc_port", "8081", "port of the identity chain")
peerDiscovery := flag.Bool("peer_discovery", false, "Enable Peer Discovery")
// Leader needs to have a minimal number of peers to start consensus
//Leader needs to have a minimal number of peers to start consensus
minPeers := flag.Int("min_peers", 100, "Minimal number of Peers in shard")
flag.Parse()
@ -113,37 +115,33 @@ func main() {
var leader p2p.Peer
var selfPeer p2p.Peer
var clientPeer *p2p.Peer
// Use Peer Discovery to get shard/leader/peer/...
priKey, pubKey := utils.GenKey(*ip, *port)
if *peerDisvoery {
// Contact Identity Chain
// This is a blocking call
// Assume @ak has get it working
// TODO: this has to work with @ak's fix
discoveryConfig := discovery.New(priKey, pubKey)
err := discoveryConfig.StartClientMode(*idcIP, *idcPort)
if err != nil {
fmt.Println("Unable to start peer discovery! ", err)
os.Exit(1)
}
//Use Peer Discovery to get shard/leader/peer/...
if *peerDiscovery {
candidateNode := pkg_newnode.New(*ip, *port)
BCPeer := p2p.Peer{IP: *idcIP, Port: *idcPort}
service := candidateNode.NewService(*ip, *port)
candidateNode.ConnectBeaconChain(BCPeer)
shardID = candidateNode.GetShardID()
leader = candidateNode.GetLeader()
selfPeer = candidateNode.GetSelfPeer()
clientPeer = candidateNode.GetClientPeer()
service.Stop()
selfPeer.PubKey = candidateNode.PubK
shardID = discoveryConfig.GetShardID()
leader = discoveryConfig.GetLeader()
peers = discoveryConfig.GetPeers()
selfPeer = discoveryConfig.GetSelfPeer()
} else {
distributionConfig := utils.NewDistributionConfig()
distributionConfig.ReadConfigFile(*configFile)
shardID = distributionConfig.GetShardID(*ip, *port)
peers = distributionConfig.GetPeers(*ip, *port, shardID)
leader = distributionConfig.GetLeader(shardID)
selfPeer = distributionConfig.GetSelfPeer(*ip, *port, shardID)
_, pubKey := utils.GenKey(*ip, *port)
peers = distributionConfig.GetPeers(*ip, *port, shardID)
selfPeer.PubKey = pubKey
// Create client peer.
clientPeer = distributionConfig.GetClientPeer()
}
selfPeer.PubKey = pubKey
fmt.Println(peers, leader, selfPeer, clientPeer, *logFolder, *minPeers) //TODO: to be replaced by a logger later: ak, rl
var role string
if leader.IP == *ip && leader.Port == *port {
@ -156,7 +154,6 @@ func main() {
// Attack determination.
attack.GetInstance().SetAttackEnabled(attackDetermination(*attackedMode))
}
// Init logging.
loggingInit(*logFolder, role, *ip, *port, *onlyLogTps)
@ -223,7 +220,7 @@ func main() {
}()
}
} else {
if *peerDisvoery {
if *peerDiscovery {
go currentNode.JoinShard(leader)
}
}

@ -73,7 +73,8 @@ while IFS='' read -r line || [[ -n "$line" ]]; do
IFS=' ' read ip port mode shardID <<< $line
#echo $ip $port $mode
if [ "$mode" != "client" ]; then
./bin/benchmark -ip $ip -port $port -config_file $config -log_folder $log_folder $DB $PEER -min_peers $MIN &
./bin/benchmark -ip $ip -port $port -log_folder $log_folder $DB $PEER -min_peers $MIN &
sleep 10
fi
done < $config

@ -0,0 +1,191 @@
package newnode
import (
"fmt"
"net"
"os"
"strconv"
"sync"
"time"
"github.com/dedis/kyber"
"github.com/harmony-one/harmony/crypto"
"github.com/harmony-one/harmony/log"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/proto/bcconn"
proto_identity "github.com/harmony-one/harmony/proto/identity"
"github.com/harmony-one/harmony/utils"
)
// Service is the server for listening.
type Service struct {
ch chan bool
waitGroup *sync.WaitGroup
}
//NewNode is ther struct for a candidate node
type NewNode struct {
Role string
ShardID int
ValidatorID int // Validator ID in its shard.
leader p2p.Peer
isLeader bool
Self p2p.Peer
peers []p2p.Peer
PubK kyber.Point
priK kyber.Scalar
log log.Logger
SetInfo bool
Service *Service
}
// New candidatenode initialization
func New(ip string, port string) *NewNode {
priKey, pubKey := utils.GenKey(ip, port)
var node NewNode
node.PubK = pubKey
node.priK = priKey
node.Self = p2p.Peer{IP: ip, Port: port, PubKey: pubKey, ValidatorID: -1}
node.log = log.New()
node.SetInfo = false
return &node
}
type registerResponseRandomNumber struct {
NumberOfShards int
NumberOfNodesAdded int
Leaders []*bcconn.NodeInfo
}
// NewService starts a newservice in the candidate node
func (node *NewNode) NewService(ip, port string) *Service {
laddr, err := net.ResolveTCPAddr("tcp", ip+":"+port)
if nil != err {
node.log.Crit("cannot resolve the tcp address of the new node", err)
}
listener, err := net.ListenTCP("tcp", laddr)
if nil != err {
node.log.Crit("cannot start a listener for new node", err)
}
node.log.Debug("listening on", "address", laddr.String())
node.Service = &Service{
ch: make(chan bool),
waitGroup: &sync.WaitGroup{},
}
node.Service.waitGroup.Add(1)
go node.Serve(listener)
return node.Service
}
// Serve Accept connections and spawn a goroutine to serve each one. Stop listening
// if anything is received on the service's channel.
func (node *NewNode) Serve(listener *net.TCPListener) {
defer node.Service.waitGroup.Done()
for {
select {
case <-node.Service.ch:
node.log.Debug("stopping listening on", "address", listener.Addr())
listener.Close()
node.log.Debug("stopped listening")
return
default:
}
listener.SetDeadline(time.Now().Add(1e9)) // This deadline is for 1 second to accept new connections.
conn, err := listener.AcceptTCP()
if nil != err {
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
continue
}
node.log.Error(err.Error())
}
node.Service.waitGroup.Add(1)
go node.NodeHandler(conn)
}
}
// Stop the service by closing the service's channel. Block until the service
// is really stopped.
func (s *Service) Stop() {
close(s.ch)
s.waitGroup.Wait()
}
func (node NewNode) String() string {
return fmt.Sprintf("idc: %v:%v and node infi %v", node.Self.IP, node.Self.Port, node.SetInfo)
}
// ConnectBeaconChain connects to beacon chain
func (node *NewNode) ConnectBeaconChain(BCPeer p2p.Peer) {
node.log.Info("connecting to beacon chain now ...")
pubk, err := node.PubK.MarshalBinary()
if err != nil {
node.log.Error("Could not Marshall public key into binary")
}
p := p2p.Peer{IP: node.Self.IP, Port: node.Self.Port}
nodeInfo := &bcconn.NodeInfo{Self: p, PubK: pubk}
msg := bcconn.SerializeNodeInfo(nodeInfo)
msgToSend := proto_identity.ConstructIdentityMessage(proto_identity.Register, msg)
gotShardInfo := false
timeout := time.After(300 * time.Second)
tick := time.Tick(5 * time.Second)
checkLoop:
for {
select {
case <-timeout:
gotShardInfo = false
break checkLoop
case <-tick:
if node.SetInfo {
gotShardInfo = true
break checkLoop
} else {
p2p.SendMessage(BCPeer, msgToSend)
}
}
}
if !gotShardInfo {
node.log.Crit("Could not get sharding info after 5 minutes")
os.Exit(1)
}
}
// ProcessShardInfo
func (node *NewNode) processShardInfo(msgPayload []byte) bool {
leadersInfo := bcconn.DeserializeRandomInfo(msgPayload)
leaders := leadersInfo.Leaders
shardNum, isLeader := utils.AllocateShard(leadersInfo.NumberOfNodesAdded, leadersInfo.NumberOfShards)
leaderNode := leaders[shardNum-1] //0 indexing.
leaderPeer := p2p.Peer{IP: leaderNode.Self.IP, Port: leaderNode.Self.Port}
leaderPeer.PubKey = crypto.Ed25519Curve.Point()
err := leaderPeer.PubKey.UnmarshalBinary(leaderNode.PubK[:])
if err != nil {
node.log.Info("Could not unmarshall leaders public key from binary to kyber.point")
}
node.leader = leaderPeer
node.isLeader = isLeader
node.ShardID = shardNum - 1 //0 indexing.
node.SetInfo = true
node.log.Info("Shard information obtained ..")
return true
}
// GetShardID gives shardid of node
func (node *NewNode) GetShardID() string {
return strconv.Itoa(node.ShardID)
}
// GetLeader gives the leader of the node
func (node *NewNode) GetLeader() p2p.Peer {
return node.leader
}
// GetClientPeer gives the client of the node
func (node *NewNode) GetClientPeer() *p2p.Peer {
return nil
}
// GetSelfPeer gives the peer part of the node's own struct
func (node *NewNode) GetSelfPeer() p2p.Peer {
return node.Self
}

@ -0,0 +1,63 @@
package newnode
import (
"net"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/proto"
proto_identity "github.com/harmony-one/harmony/proto/identity"
)
// NodeHandler handles a new incoming connection.
func (node *NewNode) NodeHandler(conn net.Conn) {
defer conn.Close()
defer node.Service.waitGroup.Done()
content, err := p2p.ReadMessageContent(conn)
if err != nil {
node.log.Error("Read p2p data failed", "err", err, "node", node)
return
}
msgCategory, err := proto.GetMessageCategory(content)
if err != nil {
node.log.Error("Read node type failed", "err", err, "node", node)
return
}
msgType, err := proto.GetMessageType(content)
if err != nil {
node.log.Error("Read action type failed", "err", err, "node", node)
return
}
msgPayload, err := proto.GetMessagePayload(content)
if err != nil {
node.log.Error("Read message payload failed", "err", err, "node", node)
return
}
identityMsgPayload, err := proto_identity.GetIdentityMessagePayload(msgPayload)
if err != nil {
node.log.Error("Read message payload failed")
return
}
switch msgCategory {
case proto.Identity:
actionType := proto_identity.IDMessageType(msgType)
switch actionType {
case proto_identity.Identity:
idMsgType, err := proto_identity.GetIdentityMessageType(msgPayload)
if err != nil {
node.log.Error("Error finding the identity message type", err)
}
switch idMsgType {
case proto_identity.Acknowledge:
node.processShardInfo(identityMsgPayload)
default:
panic("The identity message type is wrong/missing and newnode does not handle this identity message type")
}
default:
panic("The msgCategory is wrong/missing and newnode does not handle this protocol message type")
}
}
}

@ -0,0 +1,18 @@
package newnode
import "testing"
func TestNewNode(t *testing.T) {
var ip, port string
ip = "127.0.0.1"
port = "8080"
nnode := New(ip, port)
if nnode.PubK == nil {
t.Error("new node public key not initialized")
}
if nnode.SetInfo {
t.Error("new node setinfo initialized to true! (should be false)")
}
}

@ -0,0 +1,70 @@
package bcconn
import (
"bytes"
"encoding/gob"
"github.com/harmony-one/harmony/log"
"github.com/harmony-one/harmony/p2p"
)
//NodeInfo struct exists to share information on the node
type NodeInfo struct { //TODO: to be merged with Leo's nodeinfo.
Self p2p.Peer
PubK []byte
}
//ResponseRandomNumber struct for exchanging random information
type ResponseRandomNumber struct {
NumberOfShards int
NumberOfNodesAdded int
Leaders []*NodeInfo
}
// SerializeNodeInfo is for serializing nodeinfo
func SerializeNodeInfo(nodeinfo *NodeInfo) []byte {
var result bytes.Buffer
encoder := gob.NewEncoder(&result)
err := encoder.Encode(nodeinfo)
if err != nil {
log.Error("Could not serialize node info", err)
}
return result.Bytes()
}
// DeserializeNodeInfo deserializes the nodeinfo
func DeserializeNodeInfo(d []byte) *NodeInfo {
var wn NodeInfo
r := bytes.NewBuffer(d)
decoder := gob.NewDecoder(r)
err := decoder.Decode(&wn)
if err != nil {
log.Error("Could not de-serialize node info", err)
}
return &wn
}
// SerializeRandomInfo serializes random number informations
func SerializeRandomInfo(response ResponseRandomNumber) []byte {
//Needs to escape the serialization of unexported fields
var result bytes.Buffer
encoder := gob.NewEncoder(&result)
err := encoder.Encode(response)
if err != nil {
log.Crit("Could not serialize randomn number information", "error", err)
}
return result.Bytes()
}
// DeserializeRandomInfo deserializes the random informations
func DeserializeRandomInfo(d []byte) ResponseRandomNumber {
var wn ResponseRandomNumber
r := bytes.NewBuffer(d)
decoder := gob.NewDecoder(r)
err := decoder.Decode(&wn)
if err != nil {
log.Crit("Could not de-serialize random number information")
}
return wn
}

@ -0,0 +1,66 @@
package bcconn
import (
"fmt"
"reflect"
"testing"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/utils"
)
func TestSerializeDeserializeNodeInfo(t *testing.T) {
var ip, port string
ip = "127.0.0.1"
port = "8080"
self := p2p.Peer{IP: ip, Port: port}
_, pk := utils.GenKey(ip, port)
pkb, err := pk.MarshalBinary()
if err != nil {
fmt.Println("problem marshalling binary from public key")
}
nodeInfo := &NodeInfo{Self: self, PubK: pkb}
serializedNI := SerializeNodeInfo(nodeInfo)
deserializedNI := DeserializeNodeInfo(serializedNI)
if !reflect.DeepEqual(nodeInfo, deserializedNI) {
t.Fatalf("serialized and deserializing nodeinfo does not lead to origina nodeinfo")
}
}
func TestSerializeDeserializeRandomInfo(t *testing.T) {
var ip, port string
ip = "127.0.0.1"
port = "8080"
self := p2p.Peer{IP: ip, Port: port}
_, pk := utils.GenKey(ip, port)
pkb, err := pk.MarshalBinary()
if err != nil {
fmt.Println("problem marshalling binary from public key")
}
nodeInfo1 := &NodeInfo{Self: self, PubK: pkb}
ip = "127.0.0.1"
port = "9080"
self2 := p2p.Peer{IP: ip, Port: port}
_, pk2 := utils.GenKey(ip, port)
pkb2, err := pk2.MarshalBinary()
if err != nil {
fmt.Println("problem marshalling binary from public key")
}
nodeInfo2 := &NodeInfo{Self: self2, PubK: pkb2}
leaders := make([]*NodeInfo, 2)
leaders[0] = nodeInfo1
leaders[1] = nodeInfo2
rrn := ResponseRandomNumber{NumberOfShards: 5, NumberOfNodesAdded: 10, Leaders: leaders}
serializedrrn := SerializeRandomInfo(rrn)
deserializedrrn := DeserializeRandomInfo(serializedrrn)
fmt.Println(rrn)
fmt.Println(deserializedrrn)
if !reflect.DeepEqual(rrn, deserializedrrn) {
t.Fatalf("serializin g and deserializing random response does not lead to original randominfo")
}
}

@ -0,0 +1,16 @@
package main
import (
"flag"
"github.com/harmony-one/harmony/beaconchain"
)
func main() {
numShards := flag.Int("numShards", 1, "number of shards of identity chain")
ip := flag.String("ip", "127.0.0.1", "ip on which beaconchain listens")
port := flag.String("port", "8081", "port on which beaconchain listens")
flag.Parse()
bc := beaconchain.New(*numShards, *ip, *port)
bc.StartServer()
}

@ -67,3 +67,22 @@ func GenKey(ip, port string) (kyber.Scalar, kyber.Point) {
return priKey, pubKey
}
// AllocateShard uses the number of current nodes and number of shards
// to return the shardnum a new node belongs to, it also tells whether the node is a leader
func AllocateShard(numnode, numshards int) (int, bool) {
if numshards == 1 {
if numnode == 1 {
return 1, true
}
return 1, false
}
if numnode > numshards {
shardnum := numnode % numshards
if shardnum == 0 {
return numshards, false
}
return shardnum, false
}
return numnode, true
}

Loading…
Cancel
Save