Electroneum
Loading...
Searching...
No Matches
validators.h
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification, are
6// permitted provided that the following conditions are met:
7//
8// 1. Redistributions of source code must retain the above copyright notice, this list of
9// conditions and the following disclaimer.
10//
11// 2. Redistributions in binary form must reproduce the above copyright notice, this list
12// of conditions and the following disclaimer in the documentation and/or other
13// materials provided with the distribution.
14//
15// 3. Neither the name of the copyright holder nor the names of its contributors may be
16// used to endorse or promote products derived from this software without specific
17// prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29
30#ifndef ELECTRONEUM_VALIDATORS_H
31#define ELECTRONEUM_VALIDATORS_H
32
33#include <boost/algorithm/hex.hpp>
34
36#include "include_base_utils.h"
37#include "net/http_client.h"
40#include "crypto/crypto.h"
42#include "math_helper.h"
44
45namespace electroneum {
46 namespace basic {
47 using namespace std;
48 using namespace std::chrono;
49 using namespace boost::algorithm;
50 using namespace epee::math_helper;
51 using namespace epee::serialization;
52
60
71
72 class Validator {
73 private:
74 string publicKey;
75 uint64_t startHeight;
76 uint64_t endHeight;
77 string name;
78 string domain;
79 string page_link;
80 public:
81
83 Validator(const string &publicKey, uint64_t startHeight, uint64_t endHeight, string name = "", string domain = "", string page_link = "");
84
85 inline const string getPublicKey() {
86 return this->publicKey;
87 }
88
90 return this->startHeight;
91 }
92
94 return this->endHeight;
95 }
96
97 inline void setEndHeight(uint64_t end_height) {
98 this->endHeight = end_height;
99 }
100
102 return height >= this->startHeight && (height <= this->endHeight || this->endHeight == 0);
103 }
104
105 inline void setName(string name) {
106 this->name = name;
107 }
108
109 inline string getName() {
110 return this->name;
111 }
112
113 inline void setDomain(string domain) {
114 this->domain = domain;
115 }
116
117 inline string getdomain() {
118 return this->domain;
119 }
120
121 inline void setPageLink(string page_link) {
122 this->page_link = page_link;
123 }
124
125 inline string getPageLink() {
126 return this->page_link;
127 }
128
130 Validator v;
131 v.name = this->name;
132 v.domain = this->domain;
133 v.page_link = this->page_link;
134
135 return v;
136 }
137 };
138
140 private:
141 vector<std::unique_ptr<Validator>> list;
142 uint64_t current_list_timestamp;
144 string endpoint_addr = "vl.electroneum.com";
145 string endpoint_port = "80";
146 string testnet_endpoint_addr = "vl.thesecurityteam.rocks";
147 string testnet_endpoint_port = "80";
148 milliseconds endpoint_timeout = milliseconds(10000);
149 string serialized_v_list;
151 time_t last_updated;
152 uint32_t timeout = 60*60*12; //12 hours
153 uint32_t timeout_grace_period = this->timeout * 0.1; //10% of timeout
154 once_a_time_seconds<60, true> m_load_validators_interval;
156 bool testnet = false;
157
159
160 void add(const string &key, uint64_t startHeight, uint64_t endHeight, string name = "", string domain ="", string page_link = "");
161 void addOrUpdate(const string &key, uint64_t startHeight, uint64_t endHeight, string name = "", string domain ="", string page_link = "");
162 void update(const string &key, uint64_t endHeight, string name = "", string domain ="", string page_link = "");
163 std::unique_ptr<Validator> find(const string &key);
164 bool exists(const string &key);
165 list_update_outcome validate_and_update(v_list_struct res, bool saveToDB, bool isEmergencyUpdate = false);
166 ValidatorsState validate_expiration();
167
168 public:
169 explicit Validators(cryptonote::BlockchainDB &db, cryptonote::i_cryptonote_protocol* pprotocol, bool testnet) : m_db(db), current_list_timestamp(0) {
170 testnet ? this->http_client.set_server(this->testnet_endpoint_addr, this->testnet_endpoint_port, boost::none) :
171 this->http_client.set_server(this->endpoint_addr, this->endpoint_port, boost::none);
172 this->testnet = testnet;
173 this->m_p2p = pprotocol;
174 };
175
176 inline vector<string> getApplicablePublicKeys(uint64_t height, bool convert_to_byte = false) {
177 vector<string> keys;
178 all_of(this->list.begin(), this->list.end(), [&height, &keys, &convert_to_byte](std::unique_ptr<Validator> &v) {
179 if (v->isWithinRange(height)) {
180 const string k = convert_to_byte ? unhex(v->getPublicKey()) : v->getPublicKey();
181 keys.push_back(k);
182 }
183 return true;
184 });
185 return keys;
186 }
187
189 Validator result;
190 all_of(this->list.begin(), this->list.end(), [&key, &result](std::unique_ptr<Validator> &v) {
191 if (v->getPublicKey() == key) {
192 result = v->getValidatorInfo();
193 }
194 return true;
195 });
196 return result;
197 }
198
199 inline bool loadValidatorsList() {
200
203
204 // Try fetching list of validators from JSON endpoint
205 if(this->status == ValidatorsState::Invalid || this->status == ValidatorsState::Expired || this->status == ValidatorsState::NeedsUpdate) {
206 if (!get_http_json("/", res, this->http_client)) {
207 LOG_PRINT_L1("Unable to get validator_list json from " << this->endpoint_addr << ":" << this->endpoint_port);
208 }
209
210 this->timeout = 60*60*24;
211 list_update_outcome isJsonValid = validate_and_update(res, true);
212
213 if(isJsonValid == list_update_outcome::Success || isJsonValid == list_update_outcome::Same_List) {
214 MGINFO("Validators list loaded from JSON endpoint! Refresh in 12 hours");
215 return true;
216 }
217
218 //If the list was old, invalid, or had an invalid public key, try getting list of validators from peers
219 if(m_p2p->request_validators_list_to_all() && this->status == ValidatorsState::Valid) {
220 this->timeout = 60*60*1;
221 MGINFO("Validators list loaded from peers! Refresh in 1 hour");
222 return true;
223 }
224
225 //Keep returning true during the grace period
226 if(this->status == ValidatorsState::NeedsUpdate) {
227 LOG_PRINT_L1("Validator List Grace Period");
228 return true;
229 }
230
231 // If we there was an issue with getting the list from peers, try getting list of validators from db.
232 // This code will only be reached at the daemon start if both endpoint & p2p list are unavailable.
233 string v = m_db.get_validator_list();
234 if(!v.empty()) {
235 this->timeout = 60*60*1;
236 list_update_outcome isDBListValid = setValidatorsList(v, true);
238 MGINFO("Validators list loaded from database! Refresh in 1 hour");
239 return true;
240 }
241 }
242
243
244 return false;
245 }
246
247 return true;
248 }
249
251
252 if(this->status == ValidatorsState::NeedsUpdate || this->status == ValidatorsState::Expired) {
253 return string("");
254 }
255
256 return this->serialized_v_list;
257 }
258
259 inline list_update_outcome setValidatorsList(const string &v_list, bool saveToDB, bool isEmergencyUpdate = false) {
261 load_t_from_json(res, v_list);
262
263 return validate_and_update(res, saveToDB, isEmergencyUpdate);
264 }
265
266 inline bool isValid() {
267 return this->status == ValidatorsState::Valid || this->status == ValidatorsState::NeedsUpdate;
268 }
269
270 inline bool isEnabled() {
271 return this->status != ValidatorsState::Disabled;
272 }
273
274 inline void enable() {
275 this->status = ValidatorsState::Expired;
276 }
277
278 inline void on_idle() {
279 if(this->status != ValidatorsState::Disabled) {
280 if(validate_expiration() != ValidatorsState::Valid) {
281 m_load_validators_interval.do_call(boost::bind(&Validators::loadValidatorsList, this));
282 }
283 }
284 }
285 };
286 }
287}
288
289#endif //ELECTRONEUM_VALIDATORS_H
uint64_t height
The BlockchainDB backing store interface declaration/contract.
void setPageLink(string page_link)
Definition validators.h:121
void setDomain(string domain)
Definition validators.h:113
bool isWithinRange(uint64_t height)
Definition validators.h:101
void setName(string name)
Definition validators.h:105
void setEndHeight(uint64_t end_height)
Definition validators.h:97
list_update_outcome setValidatorsList(const string &v_list, bool saveToDB, bool isEmergencyUpdate=false)
Definition validators.h:259
Validator getValidatorByKey(string key)
Definition validators.h:188
Validators(cryptonote::BlockchainDB &db, cryptonote::i_cryptonote_protocol *pprotocol, bool testnet)
Definition validators.h:169
vector< string > getApplicablePublicKeys(uint64_t height, bool convert_to_byte=false)
Definition validators.h:176
bool set_server(const std::string &address, boost::optional< login > user, ssl_options_t ssl_options=ssl_support_t::e_ssl_support_autodetect)
const char * res
const char * key
#define AUTO_VAL_INIT(v)
#define LOG_PRINT_L1(x)
#define MGINFO(x)
Definition misc_log_ex.h:80
http_simple_client_template< blocked_mode_client > http_simple_client
bool load_t_from_json(t_struct &out, const std::string &json_buff)
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136