Electroneum
Loading...
Searching...
No Matches
checkpoints.cpp
Go to the documentation of this file.
1// Copyrights(c) 2017-2021, The Electroneum Project
2// Copyrights(c) 2014-2019, The Monero Project
3//
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without modification, are
7// permitted provided that the following conditions are met:
8//
9// 1. Redistributions of source code must retain the above copyright notice, this list of
10// conditions and the following disclaimer.
11//
12// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13// of conditions and the following disclaimer in the documentation and/or other
14// materials provided with the distribution.
15//
16// 3. Neither the name of the copyright holder nor the names of its contributors may be
17// used to endorse or promote products derived from this software without specific
18// prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31
32#include "checkpoints.h"
33
34#include "common/dns_utils.h"
35#include "string_tools.h"
36#include "storages/portable_storage_template_helper.h" // epee json include
38#include <functional>
39#include <vector>
40
41using namespace epee;
42
43#undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
44#define ELECTRONEUM_DEFAULT_LOG_CATEGORY "checkpoints"
45
46namespace cryptonote
47{
60
64 struct t_hash_json {
65 std::vector<t_hashline> hashlines;
69 };
70
71 //---------------------------------------------------------------------------
75 //---------------------------------------------------------------------------
76 bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str)
77 {
78 crypto::hash h = crypto::null_hash;
79 bool r = epee::string_tools::hex_to_pod(hash_str, h);
80 CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!");
81
82 // return false if adding at a height we already have AND the hash is different
83 if (m_points.count(height))
84 {
85 CHECK_AND_ASSERT_MES(h == m_points[height], false, "Checkpoint at given height already exists, and hash for new checkpoint was different!");
86 }
87 m_points[height] = h;
88 return true;
89 }
90 //---------------------------------------------------------------------------
92 {
93 return !m_points.empty() && (height <= (--m_points.end())->first);
94 }
95 //---------------------------------------------------------------------------
96 bool checkpoints::check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const
97 {
98 auto it = m_points.find(height);
99 is_a_checkpoint = it != m_points.end();
100 if(!is_a_checkpoint)
101 return true;
102
103 if(it->second == h)
104 {
105 MINFO("CHECKPOINT PASSED FOR HEIGHT " << height << " " << h);
106 return true;
107 }else
108 {
109 MWARNING("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH: " << it->second << ", FETCHED HASH: " << h);
110 return false;
111 }
112 }
113 //---------------------------------------------------------------------------
115 {
116 bool ignored;
117 return check_block(height, h, ignored);
118 }
119 //---------------------------------------------------------------------------
120 //FIXME: is this the desired behavior?
121 bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
122 {
123 if (0 == block_height)
124 return false;
125
126 auto it = m_points.upper_bound(blockchain_height);
127 // Is blockchain_height before the first checkpoint?
128 if (it == m_points.begin())
129 return true;
130
131 --it;
132 uint64_t checkpoint_height = it->first;
133 return checkpoint_height < block_height;
134 }
135 //---------------------------------------------------------------------------
137 {
138 if (m_points.empty())
139 return 0;
140 return m_points.rbegin()->first;
141 }
142 //---------------------------------------------------------------------------
143 const std::map<uint64_t, crypto::hash>& checkpoints::get_points() const
144 {
145 return m_points;
146 }
147
149 {
150 for (auto& pt : other.get_points())
151 {
152 if (m_points.count(pt.first))
153 {
154 CHECK_AND_ASSERT_MES(pt.second == m_points.at(pt.first), false, "Checkpoint at given height already exists, and hash for new checkpoint was different!");
155 }
156 }
157 return true;
158 }
159
161 {
162 if (nettype == MAINNET)
163 {
164 ADD_CHECKPOINT(1, "4536e1e23ff7179a126a7e61cd9e89ded0e258176f2bc879c999caa155f68cc3");
165 ADD_CHECKPOINT(10, "e5aefcb1d575a788ecfb65bb7be3bdd135eb76ccefb38a60d7800e86d25d408e");
166 ADD_CHECKPOINT(100, "e3548600cc0e2991af4f36bbf44addd95051748fc09e8cac5f8237fd841132c0");
167 ADD_CHECKPOINT(1000, "d7ec8a6329948fee02cdc95b13f286bd69fe9540863a80dfff7fe14940756293");
168 ADD_CHECKPOINT(10000, "95dad4575ba43eb0d4ba9b6081d5d52e6a74fc8fe3391d9628f78ddd3b71c965");
169 ADD_CHECKPOINT(100000, "a7b51ca66b2525903efbd4a32604a7ad5000df4b9da8bdd9cb3062cb014b0cad");
170 ADD_CHECKPOINT(150000, "e9b66d3f12f9cedece7d9925721b15f1ec6cb2f6b438b3ddd288237c27ffe20e");
171 ADD_CHECKPOINT(179839, "f8631f50ef79b840cba9fe3484764d0c7515ff2884e1f5be2f7298a4d08e88ee");
172 ADD_CHECKPOINT(179840, "74958c1b19505ab49babc91dfd14251146256873ae875ac97c26fb2000490e70");
173 ADD_CHECKPOINT(179841, "8a793f1aef368e83fa72ac3a236309c06ae7726958120514e0f6d33ff3b24548");
174 ADD_CHECKPOINT(200000, "9a7853584fbe0d88746d3d7bb6a3efd02ecaa3f0158808fde9f3c8339b3d5d8f");
175 ADD_CHECKPOINT(250000, "0b4d542eeaf6fbd5ceb196ca5ed44edb6ee0c0f1cdf391ba62710b04e1da9f29");
176 ADD_CHECKPOINT(300000, "e3d192196c70c259164fec04868d5cf21a57242cccf54ca0ba9fd8eaeddb8d72");
177 ADD_CHECKPOINT(307499, "c08f9eecdebf4f1f99c4c273368df54422e6861829213ad5d0dbde1cf6f4f08c");
178 ADD_CHECKPOINT(307500, "a65844a64acf5d0aa421892dee64e3552ef390fd29894b7d6c77d08d6609952e");
179 ADD_CHECKPOINT(307501, "4a5a86a4c6ecee29c2d41d8f633e82a5b3340e354c55f2767f722fc03b950fae");
180 ADD_CHECKPOINT(310000, "82dfd6ee74a5ae7526af923f1637b59082ef917d84ad80944edb1debd557bb96");
181 ADD_CHECKPOINT(400000, "251e07872ce8b05dedafbce2dd27f978e71a46aca7fa3b6cdbd94d6b357b5078");
182 ADD_CHECKPOINT(500000, "c2f37b178f4e1cf3460bcefd6eaf14eeaf4258ee67b97e6146b171766bd8101d");
183 ADD_CHECKPOINT(600000, "e8eeceec76ea9718ebf7fac34250403f586d01224b343c6e122baa0799023a4f");
184 ADD_CHECKPOINT(700000, "09af67f7f5b01219dd18c59a424a7570cadfe3c50408180fcaf12cec205155f7");
185 ADD_CHECKPOINT(800000, "748bfc3c736ac106a8c731114648b8c11c0c2bc3d6b9ab074bbbfc8cc1914a3f");
186 ADD_CHECKPOINT(900000, "e0fce3c156932d38d8bde4e21fabbf2a8208e96fb1b0848cc796d7338a70f7de");
187 ADD_CHECKPOINT(1000000, "26da34bde63cfb6447e0dcc190b00e4db04127e2673d48316e63e64c661ab19c");
188 ADD_CHECKPOINT(1100000, "d9d9637c9468c3d8a3a552cef38e52effbe79d0f140b0a0551d5c15f61e07a08");
189 ADD_CHECKPOINT(1811310, "f09bc360b87fd1161e28391528e432e7bde14e5183249c06a9db93a0c624499a");
190 }
191 if (nettype == TESTNET){
192 }
193 return true;
194 }
195
196 bool checkpoints::load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
197 {
198 boost::system::error_code errcode;
199 if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
200 {
201 LOG_PRINT_L1("Blockchain checkpoints file not found");
202 return true;
203 }
204
205 LOG_PRINT_L1("Adding checkpoints from blockchain hashfile");
206
207 uint64_t prev_max_height = get_max_height();
208 LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
210 if (!epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath))
211 {
212 MERROR("Error loading checkpoints from " << json_hashfile_fullpath);
213 return false;
214 }
215 for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
216 {
218 height = it->height;
219 if (height <= prev_max_height) {
220 LOG_PRINT_L1("ignoring checkpoint height " << height);
221 } else {
222 std::string blockhash = it->hash;
223 LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
224 ADD_CHECKPOINT(height, blockhash);
225 }
226 ++it;
227 }
228
229 return true;
230 }
231
233 {
234 std::vector<std::string> records;
235
236 // All four ElectroneumPulse domains have DNSSEC on and valid
237 static const std::vector<std::string> dns_urls = {
238 "checkpoints.electroneumpulse.com",
239 "checkpoints.electroneumpulse.info",
240 "checkpoints.electroneumpulse.net",
241 "checkpoints.electroneumpulse.org"
242 };
243
244 static const std::vector<std::string> testnet_dns_urls = {
245 "testpoints.electroneumpulse.com",
246 "testpoints.electroneumpulse.info",
247 "testpoints.electroneumpulse.net",
248 "testpoints.electroneumpulse.org"
249 };
250
251 static const std::vector<std::string> stagenet_dns_urls = {
252 "stagenetpoints.electroneumpulse.com",
253 "stagenetpoints.electroneumpulse.info",
254 "stagenetpoints.electroneumpulse.net",
255 "stagenetpoints.electroneumpulse.org"
256 };
257
258 if (!tools::dns_utils::load_txt_records_from_dns(records, nettype == TESTNET ? testnet_dns_urls : nettype == STAGENET ? stagenet_dns_urls : dns_urls, "checkpoints"))
259 return true; // why true ?
260
261 for (const auto& record : records)
262 {
263 auto pos = record.find(":");
264 if (pos != std::string::npos)
265 {
268
269 // parse the first part as uint64_t,
270 // if this fails move on to the next record
271 std::stringstream ss(record.substr(0, pos));
272 if (!(ss >> height))
273 {
274 continue;
275 }
276
277 // parse the second part as crypto::hash,
278 // if this fails move on to the next record
279 std::string hashStr = record.substr(pos + 1);
281 {
282 continue;
283 }
284
285 ADD_CHECKPOINT(height, hashStr);
286 }
287 }
288 return true;
289 }
290
291 bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, network_type nettype, bool dns)
292 {
293 bool result;
294
295 result = load_checkpoints_from_json(json_hashfile_fullpath);
296 if (dns)
297 {
298 result &= load_checkpoints_from_dns(nettype);
299 }
300
301 return result;
302 }
303}
uint64_t height
#define ADD_CHECKPOINT(h, hash)
Definition checkpoints.h:38
bool check_block(uint64_t height, const crypto::hash &h, bool &is_a_checkpoint) const
checks if the given height and hash agree with the checkpoints
checkpoints()
default constructor
bool load_checkpoints_from_dns(network_type nettype=MAINNET)
load new checkpoints from DNS
bool init_default_checkpoints(network_type nettype)
loads the default main chain checkpoints
bool load_new_checkpoints(const std::string &json_hashfile_fullpath, network_type nettype=MAINNET, bool dns=true)
load new checkpoints
bool add_checkpoint(uint64_t height, const std::string &hash_str)
adds a checkpoint to the container
bool is_in_checkpoint_zone(uint64_t height) const
checks if there is a checkpoint in the future
bool check_for_conflicts(const checkpoints &other) const
checks if our checkpoints container conflicts with another
bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
checks if alternate chain blocks should be kept for a given height
bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
load new checkpoints from json
const std::map< uint64_t, crypto::hash > & get_points() const
gets the checkpoints container
uint64_t get_max_height() const
gets the highest checkpoint height
#define KV_SERIALIZE(varialble)
#define END_KV_SERIALIZE_MAP()
#define BEGIN_KV_SERIALIZE_MAP()
#define MERROR(x)
Definition misc_log_ex.h:73
#define MWARNING(x)
Definition misc_log_ex.h:74
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define LOG_PRINT_L1(x)
#define MINFO(x)
Definition misc_log_ex.h:75
POD_CLASS hash
Definition hash.h:50
Holds cryptonote related classes and helpers.
Definition ban.cpp:40
bool load_t_from_json_file(t_struct &out, const std::string &json_file)
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
bool load_txt_records_from_dns(std::vector< std::string > &good_records, const std::vector< std::string > &dns_urls, std::string type)
unsigned __int64 uint64_t
Definition stdint.h:136
struct for loading many checkpoints from json
std::vector< t_hashline > hashlines
the checkpoint lines from the file
struct for loading a checkpoint from json
uint64_t height
the height of the checkpoint
std::string hash
the hash for the checkpoint
struct hash_func hashes[]