-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser.cpp
156 lines (127 loc) · 5.6 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <map>
#include <bits/stdc++.h>
#include <tuple>
// 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
*/
// From reference code executable.cpp, but it's being used differently
// in executable.cpp, this is called once to create a single quorum set for a network
// in our model, we want to support many quorum sets for a network, so we call this for each node
stellar::SCPQuorumSetPtr initQSet(xdr::xvector<stellar::NodeID> const& nodes) {
// TODO: support inner sets (we don't need to do this yet so maybe wait)
xdr::xvector<stellar::SCPQuorumSet> innerSets;
// first argument: threshold of nodes needed to agree to a statement
// second argument: vector of nodeIDs that are in the nodes's quorum slice
// third argument: inner set is a nested quorum set
auto qset = std::make_shared<stellar::SCPQuorumSet>((nodes.size())/2 + 1, nodes, innerSets);
normalizeQSet(*qset);
return qset;
}
// reads input file of nodes and their slices into a nodeID vec
// returns a tuple of nodeID vector, nodeID->quorum mapping, and nodeID->name mapping
tuple<
xdr::xvector<stellar::NodeID>,
map<stellar::NodeID, stellar::SCPQuorumSetPtr>,
map<stellar::NodeID, string>>
parseInput(string filename) {
// open file
ifstream input_file;
input_file.open(filename);
// return value: vector of nodeIDs
xdr::xvector<stellar::NodeID> node_vec;
// return value: nodeID->quorum mapping
map<stellar::NodeID, stellar::SCPQuorumSetPtr> node_to_quorum;
// return value: nodeID->name mapping
map<stellar::NodeID, string> node_to_name;
// mapping to hold the nodeID to the names of the nodes in it's quorum slice
map<stellar::NodeID, string> node_to_quorum_names;
// mapping to associate the name of a node to it's nodeID
// Used when constructing quorum slice of a node
map<string, stellar::NodeID> name_to_node;
string node_name;
string quorum_str;
stellar::NodeID new_node;
// run until End Of File is reached
while(!input_file.eof()){
// get name
getline(input_file, node_name);
// Generate new nodeID by creating random key
// NodeID type is just a public key
new_node = stellar::PubKeyUtils::random();
// Add new nodeID to the returned vector of nodeIDs
node_vec.push_back(new_node);
// Add new nodeID to the returned map nodeID->name
node_to_name[new_node] = node_name;
// Add new node to the name->nodeID map
name_to_node[node_name] = new_node;
// get quorum slice as string to be later converted to a qSet
getline(input_file, quorum_str);
node_to_quorum_names[new_node] = quorum_str;
// get a blank line
// doesn't matter which string buffer is used because it'll get overwritten
getline(input_file, node_name);
}
// loop through nodeID vector and construct qSet for each node
// This has to be done after to make sure we discovered all the nodes in node-input.txt
xdr::xvector<stellar::NodeID> quorum_nodes;
string quorum_nodes_str;
for (stellar::NodeID i : node_vec) {
// TODO: handle case when a nodeID isn't in this map
// String of node names
quorum_nodes_str = node_to_quorum_names.at(i);
// vector of nodeIDs
xdr::xvector<stellar::NodeID> quorum_vec;
// TODO: not sure if I need to add the node whos owns this slice to the vector, or if it is done in TestSCP initialization
quorum_vec.push_back(i);
stringstream ss(quorum_nodes_str);
string node_name;
stellar::NodeID curr_node;
// turns node name strings (space separated) into a vector of NodeID
while (ss >> node_name) {
// gets the nodeID of the current node name
// TODO: handle case when node_name doesn't yet exist in mapping
curr_node = name_to_node[node_name];
// Add the nodeID to the vector
quorum_vec.push_back(curr_node);
}
// map of nodeID to Qset
node_to_quorum[i] = initQSet(quorum_vec);
}
// close file
input_file.close();
// return tuple
return make_tuple(node_vec, node_to_quorum, node_to_name);
}