forked from JossDuff/standalone-scp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.cpp
133 lines (110 loc) · 4.82 KB
/
parser.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
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <map>
#include <bits/stdc++.h>
#include <tuple>
#include "colors.h"
#include <sstream>
// Stellar includes
#include <crypto/Hex.h>
#include <crypto/SecretKey.h>
#include <crypto/SHA.h>
#include <scp/SCP.h>
#include <scp/Slot.h>
#include <scp/QuorumSetUtils.h>
#include <util/Logging.h>
#include <util/XDROperators.h>
#include <lib/json/json.h>
using namespace std;
/* format for node-input.txt
NODE_NAME
NODE_IN_QUORUM_SLICE,NODE_IN_QUORUM_SLICE,NODE_IN_QUORUM_SLICE
NODE_NAME
NODE_IN_QUORUM_SLICE,NODE_IN_QUORUM_SLICE,NODE_IN_QUORUM_SLICE
NODE_NAME
NODE_IN_QUORUM_SLICE,NODE_IN_QUORUM_SLICE,NODE_IN_QUORUM_SLICE
etc.
First line is the name of the node (turned into a NodeID type), second line is the names of the
nodes in it's quorum slice (turned into a SCPQuorumSet type), and the third line is blank.
*/
/*
GENERAL TODOs
[] when accessing a mapping like "curr_node = name_to_node[node_name];" if the key node_name doesn't
yet exist in the mapping name_to_node it will create a new entry to the mapping. We don't really
want this so maybe throw an error if this happens.
[] mess around with node-input.txt until you find some unexpected behavior. Look at the printed output,
specifically with the "printing quorum slices" section because that is where the parser is weakest.
[] (later) If we eventually find the need to, modify the parser to support inner sets. This would
be a large change because we would have to change the format of node-input.txt
*/
stellar::SCPQuorumSetPtr initQSet(xdr::xvector<stellar::NodeID> const& nodes) {
xdr::xvector<stellar::SCPQuorumSet> innerSets;
auto qset = std::make_shared<stellar::SCPQuorumSet>((nodes.size())/2 + 1, nodes, innerSets);
normalizeQSet(*qset);
return qset;
}
// checks if node exists in node_to_name
bool checkNodeExists(const string& node_name, const map<stellar::NodeID, string>& node_to_name) {
return std::find_if(node_to_name.begin(), node_to_name.end(), [&](const auto& pair) { return pair.second == node_name; }) != node_to_name.end();
}
tuple<
xdr::xvector<stellar::NodeID>,
map<stellar::NodeID, stellar::SCPQuorumSetPtr>,
map<stellar::NodeID, string>>
parseInput(string filename) {
ifstream input_file;
input_file.open(filename);
xdr::xvector<stellar::NodeID> node_vec;
map<stellar::NodeID, stellar::SCPQuorumSetPtr> node_to_quorum;
map<stellar::NodeID, string> node_to_name;
map<stellar::NodeID, vector<string>> node_to_quorum_names;
map<string, stellar::NodeID> name_to_node;
string node_name;
string quorum_str;
stellar::NodeID new_node;
while(getline(input_file, node_name)) {
if(checkNodeExists(node_name, node_to_name)) {
cout << RED << "ERROR: Node name '" << node_name << "' already exists. Skipping this node and its quorum." << RESET << endl;
getline(input_file, quorum_str); // skip the quorum line
getline(input_file, node_name); // read the blank line
continue; // skip the rest of the loop iteration
}
new_node = stellar::PubKeyUtils::random();
node_vec.push_back(new_node);
node_to_name[new_node] = node_name;
name_to_node[node_name] = new_node;
if(getline(input_file, quorum_str)) {
stringstream ss(quorum_str);
string token;
vector<string> quorum_names;
while (getline(ss, token, ',')) {
token.erase(0, token.find_first_not_of(' '));
token.erase(token.find_last_not_of(' ') + 1);
quorum_names.push_back(token);
}
node_to_quorum_names[new_node] = quorum_names;
}
getline(input_file, node_name); // Read the blank line
}
for(stellar::NodeID i : node_vec) {
vector<string> quorum_names = node_to_quorum_names.at(i);
xdr::xvector<stellar::NodeID> quorum_vec;
quorum_vec.push_back(i); // Add node itself to its quorum slice
// set to track unique nodes in the quorum slice
set<string> unique_nodes;
unique_nodes.insert(node_to_name[i]); // Add the current node to the set
for(const string& node_name : quorum_names) {
// check if the node is already in the set
if(unique_nodes.find(node_name) == unique_nodes.end()) {
stellar::NodeID curr_node = name_to_node[node_name];
quorum_vec.push_back(curr_node);
unique_nodes.insert(node_name); // Add the node to the set
}
}
node_to_quorum[i] = initQSet(quorum_vec);
}
input_file.close();
return make_tuple(node_vec, node_to_quorum, node_to_name);
}