forked from tko22/simple-blockchain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
203 lines (176 loc) · 6.9 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// author: tko
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <memory>
#include <stdexcept>
#include "hash.hpp"
#include "Block.hpp"
#include "common.hpp"
#include "BlockChain.hpp"
#include "requests.hpp˜"
#include "json.hh"
using json = nlohmann::json;
using namespace std;
#include "client_http.hpp"
#include "server_http.hpp"
using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;
using HttpClient = SimpleWeb::Client<SimpleWeb::HTTP>;
/*
Hash header: index + prevHash + merkleRoot(data) + nonce
*/
/*
* Main function - sets up server, command line interface
*/
int main() {
printf("Welcome! To quit-> Control c \n");
HttpServer server;
// Set up ports
int port;
printf("Enter port: ");
scanf("%d",&port);
server.config.port = port; //server port
vector<int> listOfNodes; //vector of the ports of nodes in the network
// BLOCK CHAIN INITIALIZATION AND ADDING SELF TO NETWORK
char ch;
printf("Are you the initial Node? (y or n) ");
scanf(" %c",&ch);
BlockChain bc;
if (ch == 'y'){
// Initial Node: setup Blockchain with genesis block
bc = BlockChain(0);
}
else if(ch =='n'){
// New Node - need to add self to network by providing ports
bc = BlockChain(0);
char otherPorts[50];
// Example input: 8000,3000,3030
printf("Enter ports of nodes in network(with commas in between): ");
scanf("%s",otherPorts);
stringstream ss(otherPorts);
int i;
// parse string of nodes and add them to listOfNoes
while (ss >> i)
{
listOfNodes.push_back(i);
if (ss.peek() == ',' || ss.peek() == ' ')
ss.ignore();
}
addSelfToNetwork(&listOfNodes,server.config.port);
json chain = getChainFromNodes(&listOfNodes);
//skips first block - same genesis block across all nodes
for (int a = 1; a <chain["length"].get<int>(); a++ ){
auto block = chain["data"][a];
vector<string> data = block["data"].get<vector<string> >();
bc.addBlock(block["index"],block["previousHash"],block["hash"],block["nonce"],data);
}
}
else {
return 0;
}
// SERVER INITIALIZATION
/* POST /addnode - used to add node to network, called by new node to all the nodes in the network
* adds node(port) to listOfNodes
*/
server.resource["^/addnode$"]["POST"] = [&listOfNodes](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
printf("POST /addnode --- New Node adding to network....\n");
try {
json content = json::parse(request->content);
int port = content["port"].get<int>();
listOfNodes.push_back(port); // Adds port to listOfNodes
printf("----Adding node %d to listOfNodes\n",port);
response->write("Added You to our List");
}
catch(const exception &e) {
*response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
}
};
/* GET /latestchain gets latest blockchain and sends it*/
server.resource["^/latestchain$"]["GET"] = [&bc](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
printf("GET /latestchain --- Sending BlockChain....\n");
response->write(bc.toJSON());
printf("---Sent current BlockChain\n");
};
/* POST /newchain called by a node when a new block is added to it -
* checks whether the length of the blockchain is bigger than our own blockchain
* if it is bigger -> replace chain, else don't do anything
*/
server.resource["^/newchain$"]["POST"] = [&bc](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
cout << "POST /newchain --- Node in Network sent new chain\n";
try {
json content = json::parse(request->content);
if (content["length"].get<int>() > bc.getNumOfBlocks()){
bc.replaceChain(content);
cout << "----Replaced current chain with new one" << endl;
response->write("Replaced Chain\n");
}
else {
cout << "----Chain was not replaced: sent chain had same size" <<endl;
response->write("Same Chain Size -- invalid");
}
}
catch(const exception &e) {
*response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
}
};
// On error lambda function
server.on_error = [](shared_ptr<HttpServer::Request> /*request*/, const SimpleWeb::error_code & ec) {
if (ec.message() != "End of file") {
cout << "SERVER ERROR: " << ec.message() << endl;
}
};
printf("Starting server at %d",server.config.port);
// start server
thread server_thread([&server]() {
server.start();
});
//COMMAND LINE INTERFACE
// loop for 20 inputs - can change
for ( int i = 0; i < 20; i++ ) {
vector<string> v;
int temp;
// ask for what to do
printf("\n(1) Look at Blocks \n(2) Add block\n");
int valid = scanf("%d",&temp);
if ( (valid == 1) && (temp == 1)){ // queue up block if 1
printf("What Block do you want to look at? ");
scanf("%d",&temp);
try {
bc.getBlock(temp).toString();
}
catch (const exception& e){
cout << e.what() << endl;
}
}
else if (temp == 2){ // add a new block if 2
char tmp[201];
printf("\nADDING BLOCKS!\nEnter your message: ");
scanf("%200s",tmp);
string str = tmp;
printf("Entered '%s' into block\n",str.c_str());
v.push_back(str);
int in;
printf("Press any number to add block to blockchain: ");
scanf("%d",&in);
try {
if (bc.getNumOfBlocks() == 0) {
printf("----------------------------------\nPlease join the network... Your blockchain doesn't have any blocks ");
continue;
}
// mine for the has
auto pair = findHash(bc.getNumOfBlocks(),bc.getLatestBlockHash(),v);
// add the block to the blockchain
bc.addBlock(bc.getNumOfBlocks(),bc.getLatestBlockHash(),pair.first,pair.second,v );
// send the blockchain to the network
sendNewChain(&listOfNodes,bc.toJSON());
}
catch (const exception& e) {
cout << e.what() << "\n" << endl;
}
}
}
// bc.addBlock(0,string("00000000000000"),string("003d9dc40cad6b414d45555e4b83045cfde74bcee6b09fb42536ca2500087fd9"),string("46"),v);
printf("\n");
return 0;
}