diff --git a/beaconchain/beaconchain.go b/beaconchain/beaconchain.go index 77a2ebc68..757e1227a 100644 --- a/beaconchain/beaconchain.go +++ b/beaconchain/beaconchain.go @@ -1,17 +1,18 @@ package beaconchain import ( - "fmt" + "math/rand" "net" "os" "sync" "github.com/dedis/kyber" + "github.com/harmony-one/harmony/bcconn" "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" proto_identity "github.com/harmony-one/harmony/proto/identity" + "github.com/harmony-one/harmony/utils" ) var mutex sync.Mutex @@ -19,83 +20,79 @@ 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 - log log.Logger - PeerToShardMap map[*node.Node]int - ShardLeaderMap map[int]*node.Node - PubKey kyber.Point - NumberOfShards int - NumberOfLeadersAdded int + Leaders []*bcconn.NodeInfo + log log.Logger + ShardLeaderMap map[int]*bcconn.NodeInfo + PubKey kyber.Point + NumberOfShards 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 +//Init +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) -} +//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) + } + /** -func (IDC *BeaconChain) registerNode(Node *node.Node) { - IDC.Identities = append(IDC.Identities, Node) - fmt.Println(IDC.Identities) - //IDC.CommunicatePublicKeyToNode(Node.SelfPeer) - return -} + **IMPORTANT** -// 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) -} + Note that public key is not in kyber.Scalar form it is in byte form. + Use following conversion to get back the actual key + //peer.PubKey = crypto.Ed25519Curve.Point() + //err = peer.PubKey.UnmarshalBinary(p.PubKey[:]) -//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() + **/ + 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) } -func (IDC *BeaconChain) listenOnPort() { - addr := net.JoinHostPort("127.0.0.1", "8081") +//StartServer a server and process the request by a handler. +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) } - } diff --git a/beaconchain/beaconchain_handler.go b/beaconchain/beaconchain_handler.go index a7a2f0127..351e39bf4 100644 --- a/beaconchain/beaconchain_handler.go +++ b/beaconchain/beaconchain_handler.go @@ -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") } } diff --git a/beaconchain/beaconchain_test.go b/beaconchain/beaconchain_test.go new file mode 100644 index 000000000..ab5e2baf7 --- /dev/null +++ b/beaconchain/beaconchain_test.go @@ -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") + } +}