commit
7824d77df1
@ -0,0 +1,13 @@ |
||||
# IdeaIDE |
||||
.idea |
||||
|
||||
# Executables |
||||
*.exe |
||||
*.out |
||||
*.app |
||||
*.i*86 |
||||
*.x86_64 |
||||
*.hex |
||||
|
||||
# Mac |
||||
.DS_Store |
@ -0,0 +1,22 @@ |
||||
version: 0.0 |
||||
os: linux |
||||
files: |
||||
- source: ./ |
||||
destination: /home/ec2-user/projects/ |
||||
hooks: |
||||
BeforeInstall: |
||||
- location: aws-scripts/say_hello.sh |
||||
timeout: 300 |
||||
runas: root |
||||
AfterInstall: |
||||
- location: aws-scripts/say_hello.sh #maybe start the server |
||||
timeout: 300 |
||||
runas: root |
||||
ApplicationStart: |
||||
- location: aws-scripts/say_hello.sh #maybe start the server. |
||||
timeout: 300 |
||||
runas: root |
||||
ApplicationStop: |
||||
- location: aws-scripts/say_hello.sh |
||||
timeout: 300 |
||||
runas: root |
@ -0,0 +1,19 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io/ioutil" |
||||
"net" |
||||
) |
||||
|
||||
func main() { |
||||
conn, err := net.Dial("tcp", ":9000") |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
defer conn.Close() |
||||
|
||||
bs, _ := ioutil.ReadAll(conn) |
||||
fmt.Println(string(bs)) |
||||
|
||||
} |
@ -0,0 +1,26 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io" |
||||
"net" |
||||
"time" |
||||
) |
||||
|
||||
func main() { |
||||
ln, err := net.Listen("tcp", "localhost:9000") |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
defer ln.Close() |
||||
|
||||
for { |
||||
conn, err := ln.Accept() |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
io.WriteString(conn, fmt.Sprint("Hello World\n", time.Now(), "\n")) |
||||
conn.Close() |
||||
} |
||||
} |
@ -0,0 +1 @@ |
||||
echo "Hi, I am in aws-scripts and its seems to have worked." |
@ -0,0 +1,22 @@ |
||||
version: 0.0 |
||||
os: linux |
||||
files: |
||||
- source: ../ |
||||
destination: /projects/ |
||||
hooks: |
||||
BeforeInstall: |
||||
- location: aws-scripts/say_hello.sh |
||||
timeout: 300 |
||||
runas: root |
||||
AfterInstall: |
||||
- location: aws-scripts/say_hello.sh #maybe start the server |
||||
timeout: 300 |
||||
runas: root |
||||
ApplicationStart: |
||||
- location: aws-scripts/say_hello.sh #maybe start the server. |
||||
timeout: 300 |
||||
runas: root |
||||
ApplicationStop: |
||||
- location: aws-scripts/say_hello.sh |
||||
timeout: 300 |
||||
runas: root |
@ -0,0 +1 @@ |
||||
scp -i main.pem -r ~/Documents/goworkspace/src/github.com/harmony-benchmark/ ec2-user@ec2-34-219-218-239.us-west-2.compute.amazonaws.com:/home/ec2-user/projects/ |
@ -0,0 +1,34 @@ |
||||
import json |
||||
|
||||
def get_public_ip(all_reservations): |
||||
all_public_ip_addresses = [] |
||||
for individual_instances in all_reservations: |
||||
instance_information = individual_instances['Instances'][0] |
||||
if "running" != instance_information["State"]["Name"]: |
||||
continue |
||||
all_public_ip_addresses.append(instance_information['PublicIpAddress']) |
||||
return all_public_ip_addresses |
||||
|
||||
def make_peers_list(all_reservations,port="9001",filename="ipList.txt"): |
||||
p = get_public_ip(all_reservations) |
||||
f = open(filename,"w") |
||||
for i in range(len(p)): |
||||
if i == 0: |
||||
f.write(p[i] + " " + port + " " + "leader"+"\n") |
||||
else: |
||||
f.write(p[i] + " " + port + " " + "validator"+"\n") |
||||
f.close() |
||||
|
||||
def is_it_running(f): |
||||
pass |
||||
|
||||
if __name__ == "__main__": |
||||
json_data=open("aws.json").read() |
||||
f = json.loads(json_data) |
||||
all_reservations = f['Reservations'] |
||||
|
||||
make_peers_list(all_reservations) |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1 @@ |
||||
aws ec2 run-instances --image-id ami-e251209a --count 1 --instance-type t2.nano --key-name main --security-group-ids sg-066a8b0ec187c7247 |
@ -0,0 +1,9 @@ |
||||
#!/bin/bash -x |
||||
REGION=$(curl 169.254.169.254/latest/meta-data/placement/availability-zone/ | sed 's/[a-z]$//') |
||||
yum update -y |
||||
yum install ruby wget -y |
||||
cd /home/ec2-user |
||||
wget https://aws-codedeploy-$REGION.s3.amazonaws.com/latest/install |
||||
chmod +x ./install |
||||
./install auto |
||||
mkdir projects |
@ -0,0 +1,55 @@ |
||||
// Consensus package implements the Cosi PBFT consensus
|
||||
package consensus // consensus
|
||||
|
||||
import ( |
||||
"../p2p" |
||||
) |
||||
|
||||
// Consensus data containing all info related to one consensus process
|
||||
type Consensus struct { |
||||
State ConsensusState |
||||
// Signatures collected from validators
|
||||
Signatures []string |
||||
// Actual block data to reach consensus on
|
||||
Data string |
||||
// List of validators
|
||||
Validators []p2p.Peer |
||||
// Leader
|
||||
Leader p2p.Peer |
||||
// private key of current node
|
||||
PriKey string |
||||
// Whether I am leader. False means I am validator
|
||||
IsLeader bool |
||||
} |
||||
|
||||
// Consensus state enum for both leader and validator
|
||||
// States for leader:
|
||||
// READY, ANNOUNCE_DONE, CHALLENGE_DONE, FINISHED
|
||||
// States for validator:
|
||||
// READY, COMMIT_DONE, RESPONSE_DONE, FINISHED
|
||||
type ConsensusState int |
||||
|
||||
const ( |
||||
READY ConsensusState = iota |
||||
ANNOUNCE_DONE |
||||
COMMIT_DONE |
||||
CHALLENGE_DONE |
||||
RESPONSE_DONE |
||||
FINISHED |
||||
) |
||||
|
||||
// Returns string name for the ConsensusState enum
|
||||
func (state ConsensusState) String() string { |
||||
names := [...]string{ |
||||
"READY", |
||||
"ANNOUNCE_DONE", |
||||
"COMMIT_DONE", |
||||
"CHALLENGE_DONE", |
||||
"RESPONSE_DONE", |
||||
"FINISHED"} |
||||
|
||||
if state < READY || state > RESPONSE_DONE { |
||||
return "Unknown" |
||||
} |
||||
return names[state] |
||||
} |
@ -0,0 +1,79 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"log" |
||||
"fmt" |
||||
"../p2p" |
||||
"sync" |
||||
) |
||||
|
||||
var mutex = &sync.Mutex{} |
||||
|
||||
// Leader's consensus message dispatcher
|
||||
func (consensus *Consensus) ProcessMessageLeader(message []byte) { |
||||
msgType, err := GetConsensusMessageType(message) |
||||
if err != nil { |
||||
log.Print(err) |
||||
} |
||||
|
||||
payload, err := GetConsensusMessagePayload(message) |
||||
if err != nil { |
||||
log.Print(err) |
||||
} |
||||
|
||||
msg := string(payload) |
||||
fmt.Printf("[Leader] Received and processing message: %s, %s\n", msgType, msg) |
||||
switch msgType { |
||||
case ANNOUNCE: |
||||
fmt.Println("Unexpected message type: %s", msgType) |
||||
case COMMIT: |
||||
consensus.processCommitMessage(msg) |
||||
case CHALLENGE: |
||||
fmt.Println("Unexpected message type: %s", msgType) |
||||
case RESPONSE: |
||||
consensus.processResponseMessage(msg) |
||||
case START_CONSENSUS: |
||||
consensus.processStartConsensusMessage(msg) |
||||
default: |
||||
fmt.Println("Unexpected message type: %s", msgType) |
||||
} |
||||
} |
||||
|
||||
// Handler for message which triggers consensus process
|
||||
func (consensus *Consensus) processStartConsensusMessage(msg string) { |
||||
consensus.startConsensus(msg) |
||||
} |
||||
|
||||
func (consensus *Consensus) startConsensus(msg string) { |
||||
// prepare message and broadcast to validators
|
||||
|
||||
msgToSend := ConstructConsensusMessage(ANNOUNCE, []byte("block")) |
||||
p2p.BroadcastMessage(consensus.Validators, msgToSend) |
||||
// Set state to ANNOUNCE_DONE
|
||||
consensus.State = ANNOUNCE_DONE |
||||
} |
||||
|
||||
func (consensus *Consensus) processCommitMessage(msg string) { |
||||
// verify and aggregate all the signatures
|
||||
mutex.Lock() |
||||
consensus.Signatures = append(consensus.Signatures, msg) |
||||
|
||||
// Broadcast challenge
|
||||
// Set state to CHALLENGE_DONE
|
||||
consensus.State = CHALLENGE_DONE |
||||
mutex.Unlock() |
||||
|
||||
log.Printf("Number of signatures received: %d", len(consensus.Signatures)) |
||||
if len(consensus.Signatures) >= (2 * len(consensus.Validators)) / 3 + 1 { |
||||
log.Printf("Consensus reached with %d signatures: %s", len(consensus.Signatures), consensus.Signatures) |
||||
} |
||||
|
||||
} |
||||
|
||||
func (consensus *Consensus) processResponseMessage(msg string) { |
||||
// verify and aggregate all signatures
|
||||
|
||||
// Set state to FINISHED
|
||||
consensus.State = FINISHED |
||||
|
||||
} |
@ -0,0 +1,62 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"log" |
||||
"fmt" |
||||
"../p2p" |
||||
) |
||||
|
||||
// Validator's consensus message dispatcher
|
||||
func (consensus *Consensus) ProcessMessageValidator(message []byte) { |
||||
msgType, err := GetConsensusMessageType(message) |
||||
if err != nil { |
||||
log.Print(err) |
||||
} |
||||
|
||||
payload, err := GetConsensusMessagePayload(message) |
||||
if err != nil { |
||||
log.Print(err) |
||||
} |
||||
|
||||
msg := string(payload) |
||||
fmt.Printf("[Validator] Received and processing message: %s, %s\n", msgType, msg) |
||||
switch msgType { |
||||
case ANNOUNCE: |
||||
consensus.processAnnounceMessage(msg) |
||||
case COMMIT: |
||||
fmt.Println("Unexpected message type: %s", msgType) |
||||
case CHALLENGE: |
||||
consensus.processChallengeMessage(msg) |
||||
case RESPONSE: |
||||
fmt.Println("Unexpected message type: %s", msgType) |
||||
default: |
||||
fmt.Println("Unexpected message type: %s", msgType) |
||||
} |
||||
} |
||||
|
||||
func (consensus *Consensus) processAnnounceMessage(msg string) { |
||||
// verify block data
|
||||
|
||||
// sign block
|
||||
|
||||
// TODO: return the signature(commit) to leader
|
||||
// For now, simply return the private key of this node.
|
||||
msgToSend := ConstructConsensusMessage(COMMIT, []byte(consensus.PriKey)) |
||||
p2p.SendMessage(consensus.Leader, msgToSend) |
||||
|
||||
// Set state to COMMIT_DONE
|
||||
consensus.State = COMMIT_DONE |
||||
|
||||
} |
||||
|
||||
func (consensus *Consensus) processChallengeMessage(msg string) { |
||||
// verify block data and the aggregated signatures
|
||||
|
||||
// sign the message
|
||||
|
||||
// return the signature(response) to leader
|
||||
|
||||
// Set state to RESPONSE_DONE
|
||||
consensus.State = RESPONSE_DONE |
||||
} |
||||
|
@ -0,0 +1,74 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"bytes" |
||||
"errors" |
||||
) |
||||
|
||||
/* |
||||
Consensus message is the payload of p2p message. |
||||
Consensus message data structure: |
||||
|
||||
|
||||
---- message start ----- |
||||
1 byte - consensus.MessageType |
||||
0x00 - ANNOUNCE |
||||
0x01 - COMMIT |
||||
... |
||||
payload (n bytes) - consensus message payload (the data to run consensus with) |
||||
---- message end ----- |
||||
|
||||
*/ |
||||
|
||||
const MESSAGE_TYPE_BYTES = 1 |
||||
|
||||
// Consensus communication message type.
|
||||
// Leader and validator dispatch messages based on incoming message type
|
||||
type MessageType int |
||||
|
||||
const ( |
||||
ANNOUNCE MessageType = iota |
||||
COMMIT |
||||
CHALLENGE |
||||
RESPONSE |
||||
START_CONSENSUS |
||||
ERROR = -1 |
||||
) |
||||
|
||||
// Returns string name for the MessageType enum
|
||||
func (msgType MessageType) String() string { |
||||
names := [...]string{ |
||||
"ANNOUNCE", |
||||
"COMMIT", |
||||
"CHALLENGE", |
||||
"RESPONSE", |
||||
"START_CONSENSUS"} |
||||
|
||||
if msgType < ANNOUNCE || msgType > START_CONSENSUS { |
||||
return "Unknown" |
||||
} |
||||
return names[msgType] |
||||
} |
||||
|
||||
// Get the consensus message type from the p2p message payload
|
||||
func GetConsensusMessageType(message []byte) (MessageType, error) { |
||||
if len(message) < 1 { |
||||
return ERROR, errors.New("Failed to get consensus message type: no data available.") |
||||
} |
||||
return MessageType(message[0]), nil |
||||
} |
||||
|
||||
// Get the consensus message payload from the p2p message payload
|
||||
func GetConsensusMessagePayload(message []byte) ([]byte, error) { |
||||
if len(message) < 2 { |
||||
return []byte{}, errors.New("Failed to get consensus message payload: no data available.") |
||||
} |
||||
return message[MESSAGE_TYPE_BYTES:], nil |
||||
} |
||||
|
||||
// Concatenate msgType as one byte with payload, and return the whole byte array
|
||||
func ConstructConsensusMessage(msgType MessageType, payload []byte) []byte { |
||||
byteBuffer := bytes.NewBuffer([]byte{byte(msgType)}) |
||||
byteBuffer.Write(payload) |
||||
return byteBuffer.Bytes() |
||||
} |
@ -0,0 +1,6 @@ |
||||
./kill_node.sh |
||||
ipfile=$1 |
||||
while read ip port mode; do |
||||
echo $ip $port $mode $ipfile |
||||
go run ./benchmark_node.go -ip $ip -port $port -ipfile $ipfile& |
||||
done < $ipfile |
@ -1,8 +0,0 @@ |
||||
LEADER_PORT=3333 |
||||
SLAVE_START_PORT=3000 |
||||
SLAVE_END_PORT=3009 |
||||
for port in `seq $SLAVE_START_PORT $SLAVE_END_PORT`; |
||||
do |
||||
go run ./benchmark_node.go -mode slave -port $port & |
||||
done |
||||
go run ./benchmark_node.go -mode leader -port $LEADER_PORT & |
@ -0,0 +1,12 @@ |
||||
127.0.0.1 9000 leader |
||||
127.0.0.1 9001 validator |
||||
127.0.0.1 9002 validator |
||||
127.0.0.1 9003 validator |
||||
127.0.0.1 9004 validator |
||||
127.0.0.1 9005 validator |
||||
127.0.0.1 9006 validator |
||||
127.0.0.1 9007 validator |
||||
127.0.0.1 9008 validator |
||||
127.0.0.1 9009 validator |
||||
127.0.0.1 9010 validator |
||||
127.0.0.1 9011 validator |
@ -1,4 +1,5 @@ |
||||
for pid in `/bin/ps -fu $USER| grep "slave.go\|slave -port\|leader" | grep -v "grep" | awk '{print $2}'`; |
||||
for pid in `/bin/ps -fu $USER| grep "slave.go\|slave -port\|leader\|benchmark_node" | grep -v "grep" | awk '{print $2}'`; |
||||
do |
||||
echo $pid |
||||
kill -9 $pid |
||||
done |
||||
|
@ -0,0 +1,84 @@ |
||||
package p2p |
||||
|
||||
import ( |
||||
"bufio" |
||||
"bytes" |
||||
"encoding/binary" |
||||
"io" |
||||
"log" |
||||
"net" |
||||
) |
||||
|
||||
/* |
||||
P2p Message data structure: |
||||
|
||||
---- message start ----- |
||||
1 byte - message type |
||||
0x00 - normal message (no need to forward) |
||||
0x11 - p2p message (may need to forward to other neighbors) |
||||
4 bytes - message size n in number of bytes |
||||
payload (n bytes) - actual message payload |
||||
---- message end ----- |
||||
|
||||
*/ |
||||
|
||||
// Read the message type and payload size, and return the actual payload.
|
||||
func ReadMessagePayload(conn net.Conn) ([]byte, error) { |
||||
var ( |
||||
payloadBuf = bytes.NewBuffer([]byte{}) |
||||
r = bufio.NewReader(conn) |
||||
) |
||||
|
||||
//// Read 1 byte for messge type
|
||||
msgType, err := r.ReadByte() |
||||
if err != nil { |
||||
log.Fatalf("Error reading the p2p message type field") |
||||
return payloadBuf.Bytes(), err |
||||
} |
||||
log.Printf("Received p2p message with type: %x", msgType) |
||||
// TODO: check on msgType and take actions accordingly
|
||||
|
||||
//// Read 4 bytes for message size
|
||||
fourBytes := make([]byte, 4) |
||||
n, err := r.Read(fourBytes) |
||||
if err != nil { |
||||
log.Fatalf("Error reading the p2p message size field") |
||||
return payloadBuf.Bytes(), err |
||||
} else if n < len(fourBytes) { |
||||
log.Fatalf("Failed reading the p2p message size field: only read %d bytes", n) |
||||
return payloadBuf.Bytes(), err |
||||
} |
||||
|
||||
log.Print(fourBytes) |
||||
// Number of bytes for the message payload
|
||||
bytesToRead := binary.BigEndian.Uint32(fourBytes) |
||||
log.Printf("The payload size is %d bytes.", bytesToRead) |
||||
|
||||
//// Read the payload in chunk of 1024 bytes
|
||||
tmpBuf := make([]byte, 1024) |
||||
ILOOP: |
||||
for { |
||||
if bytesToRead < 1024 { |
||||
// Read the last number of bytes less than 1024
|
||||
tmpBuf = make([]byte, bytesToRead) |
||||
} |
||||
n, err := r.Read(tmpBuf) |
||||
payloadBuf.Write(tmpBuf[:n]) |
||||
|
||||
switch err { |
||||
case io.EOF: |
||||
// TODO: should we return error here, or just ignore it?
|
||||
log.Printf("EOF reached while reading p2p message") |
||||
break ILOOP |
||||
case nil: |
||||
bytesToRead -= uint32(n) // TODO: think about avoid the casting in every loop
|
||||
if bytesToRead <= 0 { |
||||
break ILOOP |
||||
} |
||||
default: |
||||
log.Printf("Error reading p2p message") |
||||
return []byte{}, err |
||||
} |
||||
} |
||||
return payloadBuf.Bytes(), nil |
||||
} |
@ -0,0 +1,79 @@ |
||||
package p2p |
||||
|
||||
import ( |
||||
"bytes" |
||||
"encoding/binary" |
||||
"fmt" |
||||
"log" |
||||
"net" |
||||
"strings" |
||||
) |
||||
|
||||
// Object for a p2p peer (node)
|
||||
type Peer struct { |
||||
// Ip address of the peer
|
||||
Ip string |
||||
// Port number of the peer
|
||||
Port string |
||||
// Public key of the peer
|
||||
PubKey string |
||||
} |
||||
|
||||
// Send the message to the peer
|
||||
func SendMessage(peer Peer, msg []byte) { |
||||
// Construct normal p2p message
|
||||
payload := ConstructP2pMessage(byte(0), msg) |
||||
|
||||
send(peer.Ip, peer.Port, payload) |
||||
} |
||||
|
||||
// Send the message to a list of peers
|
||||
func BroadcastMessage(peers []Peer, msg []byte) { |
||||
// Construct broadcast p2p message
|
||||
payload := ConstructP2pMessage(byte(17), msg) |
||||
|
||||
for _, peer := range peers { |
||||
send(peer.Ip, peer.Port, payload) |
||||
} |
||||
} |
||||
|
||||
// Construct the p2p message as [messageType, payloadSize, payload]
|
||||
func ConstructP2pMessage(msgType byte, payload []byte) []byte { |
||||
|
||||
firstByte := byte(17) // messageType
|
||||
sizeBytes := make([]byte, 4) // payloadSize
|
||||
|
||||
binary.BigEndian.PutUint32(sizeBytes, uint32(len(payload))) |
||||
|
||||
byteBuffer := bytes.NewBuffer([]byte{}) |
||||
byteBuffer.WriteByte(firstByte) |
||||
byteBuffer.Write(sizeBytes) |
||||
byteBuffer.Write(payload) |
||||
return byteBuffer.Bytes() |
||||
} |
||||
|
||||
// SocketClient is to connect a socket given a port and send the given message.
|
||||
func sendWithSocketClient(ip, port string, message []byte) (res string) { |
||||
log.Printf("Sending message to ip %s and port %s\n", ip, port) |
||||
addr := strings.Join([]string{ip, port}, ":") |
||||
conn, err := net.Dial("tcp", addr) |
||||
|
||||
if err != nil { |
||||
log.Fatalln(err) |
||||
} |
||||
defer conn.Close() |
||||
|
||||
conn.Write(message) |
||||
log.Printf("Sent to ip %s and port %s: %s\n", ip, port, message) |
||||
|
||||
// No ack (reply) message from the receiver for now.
|
||||
// TODO: think about
|
||||
return |
||||
} |
||||
|
||||
// Send a message to another node with given port.
|
||||
func send(ip, port string, message []byte) (returnMessage string) { |
||||
returnMessage = sendWithSocketClient(ip, port, message) |
||||
fmt.Println(returnMessage) |
||||
return |
||||
} |
@ -1,4 +1,4 @@ |
||||
for port in `seq 0 9`; |
||||
do |
||||
echo "3000 3001 3002 3003 3004 3005 3006 3007 3008 3009" | nc 127.0.0.1 3333 |
||||
done |
||||
# the hex is basically 0, 0032, 4, "9001 9002 9003 9004 9005 9006 9007 9008 9009 9010" |
||||
# explanation: type, size(50 bytes), [START_CONSENSUS, payload] |
||||
# START_CONSENSUS + payload = 50 bytes |
||||
echo -e '\x00\x00\x00\x00\x32\x04\x39\x30\x30\x31\x20\x39\x30\x30\x32\x20\x39\x30\x30\x33\x20\x39\x30\x30\x34\x20\x39\x30\x30\x35\x20\x39\x30\x30\x36\x20\x39\x30\x30\x37\x20\x39\x30\x30\x38\x20\x39\x30\x30\x39\x20\x39\x30\x31\x30' | nc 127.0.0.1 9000 |
||||
|
Loading…
Reference in new issue