diff --git a/consensus/consensus_leader_msg.go b/consensus/consensus_leader_msg.go index a03f5d85d..3ff9b3e4f 100644 --- a/consensus/consensus_leader_msg.go +++ b/consensus/consensus_leader_msg.go @@ -75,6 +75,36 @@ func (consensus *Consensus) constructChallengeMessage() []byte { return proto_consensus.ConstructConsensusMessage(proto_consensus.CHALLENGE, buffer.Bytes()) } +// Construct the collective signature message +func (consensus *Consensus) constructCollectiveSigMessage(collectiveSig [64]byte, bitmap []byte) []byte { + buffer := bytes.NewBuffer([]byte{}) + + // 4 byte consensus id + fourBytes := make([]byte, 4) + binary.BigEndian.PutUint32(fourBytes, consensus.consensusId) + buffer.Write(fourBytes) + + // 32 byte block hash + buffer.Write(consensus.blockHash[:]) + + // 2 byte leader id + twoBytes := make([]byte, 2) + binary.BigEndian.PutUint16(twoBytes, consensus.nodeId) + buffer.Write(twoBytes) + + // 64 byte collective signature + buffer.Write(collectiveSig[:]) + + // N byte bitmap + buffer.Write(bitmap) + + // 64 byte of signature on previous data + signature := consensus.signMessage(buffer.Bytes()) + buffer.Write(signature) + + return proto_consensus.ConstructConsensusMessage(proto_consensus.COLLECTIVE_SIG, buffer.Bytes()) +} + func getAggregatedCommit(commitments []kyber.Point) (commitment kyber.Point, bytes []byte) { aggCommitment := crypto.AggregateCommitmentsOnly(crypto.Ed25519Curve, commitments) bytes, err := aggCommitment.MarshalBinary() diff --git a/consensus/consensus_validator.go b/consensus/consensus_validator.go index 3db72733d..61bd25bbf 100644 --- a/consensus/consensus_validator.go +++ b/consensus/consensus_validator.go @@ -120,7 +120,7 @@ func (consensus *Consensus) processAnnounceMessage(payload []byte) { return } - secret, msgToSend := consensus.constructCommitMessage() + secret, msgToSend := consensus.constructCommitMessage(proto_consensus.COMMIT) // Store the commitment secret consensus.secret = secret diff --git a/consensus/consensus_validator_msg.go b/consensus/consensus_validator_msg.go index fc0b1fa65..c999adcc4 100644 --- a/consensus/consensus_validator_msg.go +++ b/consensus/consensus_validator_msg.go @@ -9,7 +9,7 @@ import ( ) // Construct the commit message to send to leader (assumption the consensus data is already verified) -func (consensus *Consensus) constructCommitMessage() (secret kyber.Scalar, commitMsg []byte) { +func (consensus *Consensus) constructCommitMessage(msgType proto_consensus.MessageType) (secret kyber.Scalar, commitMsg []byte) { buffer := bytes.NewBuffer([]byte{}) // 4 byte consensus id @@ -33,7 +33,7 @@ func (consensus *Consensus) constructCommitMessage() (secret kyber.Scalar, commi signature := consensus.signMessage(buffer.Bytes()) buffer.Write(signature) - return secret, proto_consensus.ConstructConsensusMessage(proto_consensus.COMMIT, buffer.Bytes()) + return secret, proto_consensus.ConstructConsensusMessage(msgType, buffer.Bytes()) } // Construct the response message to send to leader (assumption the consensus data is already verified) diff --git a/consensus/consensus_validator_msg_test.go b/consensus/consensus_validator_msg_test.go index de4124ab9..6facaaccc 100644 --- a/consensus/consensus_validator_msg_test.go +++ b/consensus/consensus_validator_msg_test.go @@ -5,6 +5,7 @@ import ( "github.com/simple-rules/harmony-benchmark/crypto" "github.com/simple-rules/harmony-benchmark/p2p" + consensus_proto "github.com/simple-rules/harmony-benchmark/proto/consensus" ) func TestConstructCommitMessage(test *testing.T) { @@ -12,7 +13,7 @@ func TestConstructCommitMessage(test *testing.T) { validator := p2p.Peer{Ip: "3", Port: "5"} consensus := NewConsensus("1", "2", "0", []p2p.Peer{leader, validator}, leader) consensus.blockHash = [32]byte{} - _, msg := consensus.constructCommitMessage() + _, msg := consensus.constructCommitMessage(consensus_proto.COMMIT) if len(msg) != 1+1+1+4+32+2+32+64 { test.Errorf("Commit message is not constructed in the correct size: %d", len(msg)) diff --git a/identitychain/identityblock.go b/identitychain/identityblock.go index 53c7403b1..395417b35 100644 --- a/identitychain/identityblock.go +++ b/identitychain/identityblock.go @@ -43,13 +43,8 @@ func DeserializeBlock(d []byte) *IdentityBlock { // NewBlock creates and returns a new block. func NewBlock(Identities []*waitnode.WaitNode, prevBlockHash [32]byte) *IdentityBlock { - numIds := int32(len(Identities)) - var Ids []*waitnode.WaitNode - for _, ids := range Identities { - Ids = append(Ids, ids) - } - block := &IdentityBlock{Timestamp: time.Now().Unix(), PrevBlockHash: prevBlockHash, NumIdentities: numIds, Identities: Ids} - return block + block := &IdentityBlock{Timestamp: time.Now().Unix(), PrevBlockHash: prevBlockHash, NumIdentities: int32(len(Identities)), Identities: Identities} + return &block } // CalculateBlockHash returns a hash of the block diff --git a/identitychain/identitychain.go b/identitychain/identitychain.go index ca3fc40b5..1e4114162 100644 --- a/identitychain/identitychain.go +++ b/identitychain/identitychain.go @@ -1,7 +1,6 @@ package identitychain import ( - "fmt" "net" "os" "sync" @@ -12,7 +11,7 @@ import ( ) var mutex sync.Mutex - +var IdentityPerBlock := 100000 // IdentityChain (Blockchain) keeps Identities per epoch, currently centralized! type IdentityChain struct { Identities []*IdentityBlock @@ -20,10 +19,67 @@ type IdentityChain struct { log log.Logger } -//IdentityChainHandler handles transactions +//IdentityChainHandler handles registration of new Identities func (IDC *IdentityChain) IdentityChainHandler(conn net.Conn) { - fmt.Println("yay") + // Read p2p message payload + content, err := p2p.ReadMessageContent(conn) + if err != nil { + IDC.log.Error("Read p2p data failed", "err", err, "node", node) + return + } + + msgCategory, err := proto.GetMessageCategory(content) + if err != nil { + IDC.log.Error("Read node type failed", "err", err, "node", node) + return + } + + msgType, err := proto.GetMessageType(content) + if err != nil { + IDC.log.Error("Read action type failed", "err", err, "node", node) + return + } + + msgPayload, err := proto.GetMessagePayload(content) + if err != nil { + IDC.log.Error("Read message payload failed", "err", err, "node", node) + return + } + content, err := p2p.ReadMessageContent(conn) + if err != nil { + IDC.log.Error("Read p2p data failed", "err", err, "node", node) + return + } +} + +// GetLatestBlock gests the latest block at the end of the chain +func (IDC *IdentityChain) GetLatestBlock() *IdentityBlock { + if len(IDC.Identities) == 0 { + return nil + } + return IDC.Identities[len(IDC.Identities)-1] } + +//CreateNewBlock is to create the Blocks to be added to the chain +func (IDC *IdentityChain) MakeNewBlock() *IdentityBlock { + + if len(IDC.Identities) == 0 { + return NewGenesisBlock() + } + //If there are no more Identities registring the blockchain is dead + if len(IDC.PendingIdentities) == 0 { + // This is abd, because previous block might not be alive + return IDC.GetLatestBlock() + } + prevBlock := IDC.GetLatestBlock() + NewIdentities := IDC.PendingIdentities[:IdentityPerBlock] + IDC.PendingIdentities = IDC.PendingIdentities[IdentityPerBlock]: + //All other blocks are dropped. + IDBlock = NewBlock(NewIdentities,prevBlock.CalculateBlockHash()) + IDC.Identities = append(IDBlock,IDC.Identities) + } +} + func (IDC *IdentityChain) listenOnPort(port string) { listen, err := net.Listen("tcp4", ":"+port) defer listen.Close() @@ -49,6 +105,5 @@ func main() { mutex.Lock() IDC.Identities = append(IDC.Identities, genesisBlock) mutex.Unlock() - }() } diff --git a/proto/common.go b/proto/common.go index fd697013b..c3b2f5f1a 100644 --- a/proto/common.go +++ b/proto/common.go @@ -24,10 +24,12 @@ n - 2 bytes - actual message payload // The message category enum type MessageCategory byte +//CONSENSUS and other message categories const ( CONSENSUS MessageCategory = iota NODE CLIENT + IDENTITY // TODO: add more types ) diff --git a/proto/identity/identity.go b/proto/identity/identity.go new file mode 100644 index 000000000..95ac0c652 --- /dev/null +++ b/proto/identity/identity.go @@ -0,0 +1,42 @@ +package identity + +import ( + "errors" +) + +// the number of bytes consensus message type occupies +const IDENTITY_MESSAGE_TYPE_BYTES = 1 + +type MessageType int + +const ( + REGISTER MessageType = iota +) + +// Returns string name for the MessageType enum +func (msgType MessageType) String() string { + names := [...]string{ + "REGISTER", + } + + if msgType < REGISTER || msgType > REGISTER { + return "Unknown" + } + return names[msgType] +} + +// GetIdentityMessageType Get the consensus message type from the identity message +func GetIdentityMessageType(message []byte) (MessageType, error) { + if len(message) < 1 { + return 0, errors.New("Failed to get consensus message type: no data available.") + } + return MessageType(message[0]), nil +} + +// GetIdentityMessagePayload message payload from the identity message +func GetIdentityMessagePayload(message []byte) ([]byte, error) { + if len(message) < 2 { + return []byte{}, errors.New("Failed to get consensus message payload: no data available.") + } + return message[IDENTITY_MESSAGE_TYPE_BYTES:], nil +}