The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
woop/internal/beaconchain/libs/beaconchain.go

134 lines
4.1 KiB

package beaconchain
import (
"math/rand"
"strconv"
"sync"
"github.com/dedis/kyber"
"github.com/harmony-one/harmony/api/proto/bcconn"
proto_identity "github.com/harmony-one/harmony/api/proto/identity"
"github.com/harmony-one/harmony/crypto/pki"
"github.com/harmony-one/harmony/internal/beaconchain/rpc"
"github.com/harmony-one/harmony/internal/utils"
"github.com/harmony-one/harmony/log"
"github.com/harmony-one/harmony/p2p"
"github.com/harmony-one/harmony/p2p/host"
"github.com/harmony-one/harmony/p2p/p2pimpl"
)
//BCState keeps track of the state the beaconchain is in
type BCState int
var mutex sync.Mutex
var identityPerBlock = 100000
// BeaconchainServicePortDiff is the positive port diff from beacon chain's self port
const BeaconchainServicePortDiff = 4444
// BeaconChain (Blockchain) keeps Identities per epoch, currently centralized!
type BeaconChain struct {
Leaders []*bcconn.NodeInfo
log log.Logger
ShardLeaderMap map[int]*bcconn.NodeInfo
PubKey kyber.Point
NumberOfShards int
NumberOfNodesAdded int
IP string
Port string
host host.Host
state BCState
rpcServer *beaconchain.Server
}
// Followings are the set of states of that beaconchain can be in.
const (
NodeInfoReceived BCState = iota
RandomInfoSent
)
// SupportRPC initializes and starts the rpc service
func (bc *BeaconChain) SupportRPC() {
bc.InitRPCServer()
bc.StartRPCServer()
}
// InitRPCServer initializes Rpc server.
func (bc *BeaconChain) InitRPCServer() {
bc.rpcServer = beaconchain.NewServer(bc.GetShardLeaderMap)
}
// StartRPCServer starts Rpc server.
func (bc *BeaconChain) StartRPCServer() {
port, err := strconv.Atoi(bc.Port)
if err != nil {
port = 0
}
bc.log.Info("support_client: StartRpcServer on port:", "port", strconv.Itoa(port+BeaconchainServicePortDiff))
bc.rpcServer.Start(bc.IP, strconv.Itoa(port+BeaconchainServicePortDiff))
}
// GetShardLeaderMap returns the map from shard id to leader.
func (bc *BeaconChain) GetShardLeaderMap() map[int]*bcconn.NodeInfo {
result := make(map[int]*bcconn.NodeInfo)
for i, leader := range bc.Leaders {
result[i] = leader
}
return result
}
//New beaconchain initialization
func New(numShards int, ip, port string) *BeaconChain {
bc := BeaconChain{}
bc.log = log.New()
bc.NumberOfShards = numShards
bc.PubKey = generateBCKey()
bc.NumberOfNodesAdded = 0
bc.ShardLeaderMap = make(map[int]*bcconn.NodeInfo)
bc.Port = port
bc.IP = ip
bc.host = p2pimpl.NewHost(p2p.Peer{IP: ip, Port: port})
return &bc
}
func generateBCKey() kyber.Point {
r := rand.Intn(1000)
priKey := pki.GetPrivateKeyFromInt(r)
pubkey := pki.GetPublicKeyFromPrivateKey(priKey)
return pubkey
}
//AcceptNodeInfo deserializes node information received via beaconchain handler
func (bc *BeaconChain) AcceptNodeInfo(b []byte) *bcconn.NodeInfo {
Node := bcconn.DeserializeNodeInfo(b)
bc.log.Info("New Node Connection", "IP", Node.Self.IP, "Port", Node.Self.Port)
bc.NumberOfNodesAdded = bc.NumberOfNodesAdded + 1
_, isLeader := utils.AllocateShard(bc.NumberOfNodesAdded, bc.NumberOfShards)
if isLeader {
bc.Leaders = append(bc.Leaders, Node)
}
bc.state = NodeInfoReceived
return Node
}
//RespondRandomness sends a randomness beacon to the node inorder for it process what shard it will be in
func (bc *BeaconChain) RespondRandomness(Node *bcconn.NodeInfo) {
response := bcconn.ResponseRandomNumber{NumberOfShards: bc.NumberOfShards, NumberOfNodesAdded: bc.NumberOfNodesAdded, Leaders: bc.Leaders}
msg := bcconn.SerializeRandomInfo(response)
msgToSend := proto_identity.ConstructIdentityMessage(proto_identity.Acknowledge, msg)
bc.log.Info("Sent Out Msg", "# Nodes", response.NumberOfNodesAdded)
host.SendMessage(bc.host, Node.Self, msgToSend, nil)
bc.state = RandomInfoSent
}
//AcceptConnections welcomes new connections
func (bc *BeaconChain) AcceptConnections(b []byte) {
node := bc.AcceptNodeInfo(b)
bc.RespondRandomness(node)
}
//StartServer a server and process the request by a handler.
func (bc *BeaconChain) StartServer() {
bc.host.BindHandlerAndServe(bc.BeaconChainHandler)
}