From 1b7900d223ac966402010221156c852aab06e173 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Mon, 15 Aug 2022 16:06:09 +0300 Subject: [PATCH 01/50] Build tests and export compile commands --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 395f5bd0c8..1e30fd99b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,8 @@ project(LetheanVPN) # shhhhh sleepy time errors, we know... add_definitions(-w) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + function (die msg) if (NOT WIN32) string(ASCII 27 Esc) @@ -722,7 +724,7 @@ add_subdirectory(src) #treat_warnings_as_errors(contrib src) -option(BUILD_TESTS "Build tests." OFF) +option(BUILD_TESTS "Build tests." ON) if(BUILD_TESTS) add_subdirectory(tests) From 9b31bc066a99471da2779e1e9065ed323445d478 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Mon, 15 Aug 2022 16:07:17 +0300 Subject: [PATCH 02/50] Save swap addr flag alongside address struct --- src/cryptonote_basic/cryptonote_basic.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index bdbe3c5ab2..6c158e2557 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -527,7 +527,7 @@ namespace cryptonote /************************************************************************/ /* */ /************************************************************************/ - struct account_public_address + struct account_public_address_base { crypto::public_key m_spend_public_key; crypto::public_key m_view_public_key; @@ -543,6 +543,13 @@ namespace cryptonote END_KV_SERIALIZE_MAP() }; + struct account_public_address : public account_public_address_base + { + + account_public_address() : is_swap_addr(false) {} + bool is_swap_addr; + }; + struct keypair { crypto::public_key pub; From 5f24b29d9437ced0ef77dbecd391e349bb4c31ed Mon Sep 17 00:00:00 2001 From: bubafistah Date: Wed, 17 Aug 2022 15:33:21 +0300 Subject: [PATCH 03/50] Additional hash function for short cn hash version --- src/crypto/hash.c | 9 +++++++++ src/crypto/hash.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/src/crypto/hash.c b/src/crypto/hash.c index ed95391d88..8e10b14f26 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -48,3 +48,12 @@ void cn_fast_hash(const void *data, size_t length, char *hash) { hash_process(&state, data, length); memcpy(hash, &state, HASH_SIZE); } + +uint64_t cn_fast_hash_64(const void *data, size_t length) { + union hash_state state; + uint8_t hash[HASH_SIZE]; + hash_process(&state, data, length); + memcpy(hash, &state, HASH_SIZE); + uint8_t idx = hash[5] % 4; + return ((uint64_t*)(hash))[idx]; +} diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 0132ba16cb..982948f02f 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -88,6 +88,10 @@ namespace crypto { return h; } + inline uint64_t cn_fast_hash_64(const void *data, std::size_t length) { + return cn_fast_hash_64(data, length); + } + inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0, uint64_t height = 0) { cn_slow_hash(data, length, reinterpret_cast(&hash), variant, 0/*prehashed*/, height); } From 0da7519b19a44731d92a33fe2d540e073f17aad4 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Wed, 17 Aug 2022 16:14:04 +0300 Subject: [PATCH 04/50] Hash func correction --- src/crypto/hash.c | 9 --------- src/crypto/hash.h | 6 ++++-- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/crypto/hash.c b/src/crypto/hash.c index 8e10b14f26..ed95391d88 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -48,12 +48,3 @@ void cn_fast_hash(const void *data, size_t length, char *hash) { hash_process(&state, data, length); memcpy(hash, &state, HASH_SIZE); } - -uint64_t cn_fast_hash_64(const void *data, size_t length) { - union hash_state state; - uint8_t hash[HASH_SIZE]; - hash_process(&state, data, length); - memcpy(hash, &state, HASH_SIZE); - uint8_t idx = hash[5] % 4; - return ((uint64_t*)(hash))[idx]; -} diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 982948f02f..458d654e69 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -88,8 +88,10 @@ namespace crypto { return h; } - inline uint64_t cn_fast_hash_64(const void *data, std::size_t length) { - return cn_fast_hash_64(data, length); + inline uint64_t cn_fast_hash_64(const void *data, size_t length) { + hash result_hash = cn_fast_hash(data, length); + uint8_t idx = reinterpret_cast(&result_hash)[5] % 4; + return reinterpret_cast(&result_hash)[idx]; } inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0, uint64_t height = 0) { From f46a1eedfd397e31142c0f5d35c881821f98836c Mon Sep 17 00:00:00 2001 From: bubafistah Date: Wed, 17 Aug 2022 16:15:55 +0300 Subject: [PATCH 05/50] Structure for swap addr inclusion in extra --- src/cryptonote_core/swap_address.h | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/cryptonote_core/swap_address.h diff --git a/src/cryptonote_core/swap_address.h b/src/cryptonote_core/swap_address.h new file mode 100644 index 0000000000..4ab2a1b762 --- /dev/null +++ b/src/cryptonote_core/swap_address.h @@ -0,0 +1,31 @@ +#pragma once + +#include "cryptonote_basic/cryptonote_basic.h" +#include "crypto/hash.h" + +#define SWAP_PUBLIC_ADDRESS_BASE58_PREFIX 0x73f7 // 'iT' +#define SWAP_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x6af7 // 'iTH' + +namespace cryptonote { +#pragma pack(push, 1) + + struct swap_addr_extra_userdata_entry { + account_public_address_base addr; + uint32_t checksum; + + void calc_checksum(); + bool is_checksum_valid(); + }; + +#pragma pack(pop) + + inline void swap_addr_extra_userdata_entry::calc_checksum() + { + checksum = static_cast(cn_fast_hash_64(&addr, sizeof addr)); + } + + inline bool swap_addr_extra_userdata_entry::is_checksum_valid() + { + return (checksum == static_cast(cn_fast_hash_64(&addr, sizeof addr))); + } +} From 6c855185fb4b9d65142ab8f85958647b50050f88 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Wed, 17 Aug 2022 16:17:47 +0300 Subject: [PATCH 06/50] Frame for swap related unit tests --- tests/unit_tests/CMakeLists.txt | 1 + tests/unit_tests/swap_test.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/unit_tests/swap_test.cpp diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index ce88c2fb2f..863c4ed6e1 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -64,6 +64,7 @@ set(unit_tests_sources varint.cpp ringct.cpp output_selection.cpp + swap_test.cpp vercmp.cpp) set(unit_tests_headers diff --git a/tests/unit_tests/swap_test.cpp b/tests/unit_tests/swap_test.cpp new file mode 100644 index 0000000000..264d5f49fd --- /dev/null +++ b/tests/unit_tests/swap_test.cpp @@ -0,0 +1,17 @@ +#include "gtest/gtest.h" +#include "cryptonote_basic/cryptonote_basic.h" +#include "crypto/random.h" +#include "cryptonote_core/swap_address.h" + +TEST(swap_address, swap_addr_extra_userdata_entry_from_addr) +{ + cryptonote::account_public_address swap_addr = AUTO_VAL_INIT(swap_addr); + generate_random_bytes_not_thread_safe(sizeof(swap_addr.m_view_public_key), &swap_addr.m_view_public_key); + generate_random_bytes_not_thread_safe(sizeof(swap_addr.m_spend_public_key), &swap_addr.m_spend_public_key); + swap_addr.is_swap_addr = true; + + cryptonote::swap_addr_extra_userdata_entry entry; + entry.addr = static_cast(swap_addr); + entry.calc_checksum(); + ASSERT_TRUE(entry.is_checksum_valid()); +} From aa3cca818a0e98eb8bf30c4d63adf7525ba2063b Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 13:23:25 +0300 Subject: [PATCH 07/50] Additional chacha crypt funcs --- src/crypto/chacha8.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/crypto/chacha8.h b/src/crypto/chacha8.h index f9d373fff6..0898b0b80b 100644 --- a/src/crypto/chacha8.h +++ b/src/crypto/chacha8.h @@ -77,6 +77,32 @@ namespace crypto { memcpy(&unwrap(unwrap(key)), pwd_hash.data(), sizeof(key)); } + inline void generate_chacha8_key_keccak(const void *data, size_t size, chacha8_key& key) { + char result[HASH_SIZE]; + cn_fast_hash(data, size, result); + memcpy(&key, data, sizeof(key)); + // Clean, for safety ??? + memset(result, 0, HASH_SIZE); + } + + inline void do_chacha_crypt(const void *src, size_t src_size, void *target, const void *key, size_t key_size) { + crypto::chacha8_key ckey; + crypto::chacha8_iv civ; + memset(&civ, 0, sizeof(civ)); + crypto::generate_chacha8_key_keccak(key, key_size, ckey); + crypto::chacha8(src, src_size, ckey, civ, (char*)target); + } + + template + inline bool do_chacha_crypt(std::string& buff, const T& pass) + { + std::string buff_target; + buff_target.resize(buff.size()); + do_chacha_crypt(buff.data(), buff.size(), (void*)buff_target.data(), &pass, sizeof(pass)); + buff = buff_target; + return true; + } + inline void generate_chacha8_key(std::string password, chacha8_key& key) { return generate_chacha8_key(password.data(), password.size(), key); } From 956fd0627812385668a61b238a0fb54a07c100bb Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 13:24:08 +0300 Subject: [PATCH 08/50] Add test swap keys --- src/cryptonote_core/swap_address.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/swap_address.h b/src/cryptonote_core/swap_address.h index 4ab2a1b762..d55d46c6bc 100644 --- a/src/cryptonote_core/swap_address.h +++ b/src/cryptonote_core/swap_address.h @@ -6,6 +6,10 @@ #define SWAP_PUBLIC_ADDRESS_BASE58_PREFIX 0x73f7 // 'iT' #define SWAP_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x6af7 // 'iTH' +// Just for testing +#define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "f2de2998375bd562ca98a2f9b576fa0f659651fc15b557c4d411e0004a47df24" +#define SWAP_ADDRESS_ENCRYPTION_SEC_KEY "72ae3e7de47bbb5af78ed6608a1eabe77a2429c385d28e708c01afaa82737900" + namespace cryptonote { #pragma pack(push, 1) @@ -14,7 +18,7 @@ namespace cryptonote { uint32_t checksum; void calc_checksum(); - bool is_checksum_valid(); + bool is_checksum_valid() const; }; #pragma pack(pop) @@ -24,7 +28,7 @@ namespace cryptonote { checksum = static_cast(cn_fast_hash_64(&addr, sizeof addr)); } - inline bool swap_addr_extra_userdata_entry::is_checksum_valid() + inline bool swap_addr_extra_userdata_entry::is_checksum_valid() const { return (checksum == static_cast(cn_fast_hash_64(&addr, sizeof addr))); } From f8d4596386a1fd6b787ec54180c44fe186078df7 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 13:26:51 +0300 Subject: [PATCH 09/50] Functions for building / parsing swap txs --- .../cryptonote_format_utils.cpp | 216 ++++++++++++++++++ .../cryptonote_format_utils.h | 5 + 2 files changed, 221 insertions(+) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index f57c32b644..6d43ca9737 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -39,6 +39,7 @@ using namespace epee; #include "ringct/rctSigs.h" #include "serialization/binary_utils.h" #include "cryptonote_core/cryptonote_tx_utils.h" +#include "cryptonote_core/swap_address.h" #include "miner.h" #undef MONERO_DEFAULT_LOG_CATEGORY @@ -363,8 +364,45 @@ namespace cryptonote std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce)); } //--------------------------------------------------------------- + bool fill_swapinfo_userdata_entry(blobdata& extra_nonce, const account_public_address &swap_addr) + { + if (swap_addr.is_swap_addr) { + swap_addr_extra_userdata_entry swap_entry; + swap_entry.addr = static_cast(swap_addr); + swap_entry.calc_checksum(); + + extra_nonce.push_back(TX_EXTRA_NONCE_SWAP_DATA); + extra_nonce.push_back(static_cast(sizeof swap_entry)); + std::copy(reinterpret_cast(&swap_entry), reinterpret_cast(&swap_entry) + sizeof swap_entry, std::back_inserter(extra_nonce)); + return true; + } + return false; + } + //--------------------------------------------------------------- + bool set_swap_tx_extra(std::vector &extra, crypto::hash &payment_id, account_public_address &swap_addr) + { + // TODO maybe should use vector, not sure if '\0' from blob aka string can be problem + cryptonote::blobdata payment_id_userdata_entry; + cryptonote::blobdata swap_address_userdata_entry; + + cryptonote::set_payment_id_to_tx_extra_nonce(payment_id_userdata_entry, payment_id); + bool ret = fill_swapinfo_userdata_entry(swap_address_userdata_entry, swap_addr); + + if (ret) { + extra.push_back(TX_EXTRA_NONCE); + extra.push_back(static_cast(payment_id_userdata_entry.size() + swap_address_userdata_entry.size())); + extra.insert(extra.end(), payment_id_userdata_entry.begin(), payment_id_userdata_entry.end()); + extra.insert(extra.end(), swap_address_userdata_entry.begin(), swap_address_userdata_entry.end()); + } else { + LOG_ERROR("Setting tx swap data failed!"); + } + + return ret; + } + //--------------------------------------------------------------- bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id) { + if(sizeof(crypto::hash) + 1 != extra_nonce.size()) return false; if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0]) @@ -373,6 +411,18 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + /* Should be used only on swap tx */ + bool get_payment_id_from_swap_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id) + { + LOG_ERROR("ID : " + to_string((int)extra_nonce[0]) + " size: " + to_string(extra_nonce.size())); + if(sizeof(crypto::hash) + 1 > extra_nonce.size()) + return false; + if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0]) + return false; + payment_id = *reinterpret_cast(extra_nonce.data() + 1); + return true; + } + //--------------------------------------------------------------- bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id) { if(sizeof(crypto::hash8) + 1 != extra_nonce.size()) @@ -406,6 +456,172 @@ namespace cryptonote // Encryption and decryption are the same operation (xor with a key) return encrypt_payment_id(payment_id, public_key, secret_key); } + +bool encrypt_swap_data_with_tx_secret_key(const crypto::secret_key& sk, uint8_t* data, size_t size) + { + crypto::public_key pub_key = AUTO_VAL_INIT(pub_key); + bool r = string_tools::hex_to_pod(SWAP_ADDRESS_ENCRYPTION_PUB_KEY, pub_key); + CHECK_AND_ASSERT_MES(r, false, "failed to load SWAP_ADDRESS_ENCRYPTION_PUB_KEY"); + + crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); + r = crypto::generate_key_derivation(pub_key, sk, derivation); + CHECK_AND_ASSERT_MES(r, false, "generate_key_derivation failed"); + + std::vector buff(size, '\0'); + crypto::do_chacha_crypt(data, size, buff.data(), &derivation, sizeof derivation); + + memcpy(data, buff.data(), size); + + return true; + } + + bool encrypt_user_data_with_tx_secret_key(const crypto::secret_key& sk, std::vector& extra) + { + bool padding_started = false; + for (size_t i = 0; i < extra.size(); /* nothing */) + { + if (padding_started) + { + CHECK_AND_ASSERT_MES(extra[i] == 0, false, "Failed to parse transaction extra (not 0 after padding)"); + } + else if (extra[i] == TX_EXTRA_TAG_PUBKEY) + { + CHECK_AND_ASSERT_MES(extra.size() - 1 - i >= sizeof(crypto::public_key), false, "Failed to parse transaction extra (TX_EXTRA_TAG_PUBKEY have not enough bytes)"); + i += 1 + sizeof(crypto::public_key); + continue; + } + else if (extra[i] == TX_EXTRA_NONCE) + { + CHECK_AND_ASSERT_MES(extra.size() - 1 - i >= 1, false, "Failed to parse transaction extra (TX_EXTRA_NOUNCE have not enough bytes)"); + ++i; + CHECK_AND_ASSERT_MES(extra.size() - 1 - i >= extra[i], false, "Failed to parse transaction extra (TX_EXTRA_NONCE have wrong bytes counter)"); + if (extra[i] > 0) + { + uint8_t* user_data = &extra[i + 1]; + const size_t user_data_size = static_cast(extra[i]); + + size_t j = 0; + while (j < user_data_size) + { + if (user_data[j] != TX_EXTRA_NONCE_SWAP_DATA) + { + CHECK_AND_ASSERT_MES(user_data_size - 1 - j >= 1, false, "not enough data for TX_EXTRA_NONCE_SWAP_DATA: " << user_data_size - 1 - j); + if (user_data[j] == TX_EXTRA_NONCE_PAYMENT_ID || user_data[j] == TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID) { + j += (sizeof(crypto::hash) + 1); + } else { + return false; + } + } + else + { + CHECK_AND_ASSERT_MES(user_data_size - 1 - j >= 1, false, "not enough data for TX_EXTRA_NONCE_SWAP_DATA: " << user_data_size - 1 - j); + ++j; + size_t swap_addr_size = user_data[j]; + CHECK_AND_ASSERT_MES(swap_addr_size == sizeof(swap_addr_extra_userdata_entry), false, "wrong TX_EXTRA_NONCE_SWAP_DATA semantics! size: " << swap_addr_size << ", expected: " << sizeof(swap_addr_extra_userdata_entry)); + CHECK_AND_ASSERT_MES(user_data_size - 1 - j >= swap_addr_size, false, "not enough data for TX_EXTRA_NONCE_SWAP_DATA: " << user_data_size - 1 - j); + ++j; + uint8_t *swap_addr = &user_data[j]; + + // Encrypt just swap_data portion of extra data + encrypt_swap_data_with_tx_secret_key(sk, swap_addr, swap_addr_size); + + return true; + } + } + } + i += extra[i]; + } + else if (extra[i] == 0) + { + padding_started = true; + continue; + } + else + { + CHECK_AND_ASSERT_MES(false, false, "unknown tx extra tag: 0x" << std::hex << extra[i]); + } + ++i; + } + + return true; + } + //--------------------------------------------------------------- + bool get_swapdata_encrypted_buff_from_extra_nonce(const std::string& extra_nonce, std::string& encrypted_buff) + { + if (!extra_nonce.size()) + return false; + + size_t i = 0; + while (i < extra_nonce.size()) + { + if (extra_nonce[i] != TX_EXTRA_NONCE_SWAP_DATA) + { + CHECK_AND_ASSERT_MES(extra_nonce.size() - 1 - i >= 1, false, "not enough data for user data tag " << extra_nonce[i] << " : " << extra_nonce.size() - 1 - i); + if (extra_nonce[i] == TX_EXTRA_NONCE_PAYMENT_ID || extra_nonce[i] == TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID) { + i += (sizeof(crypto::hash) + 1); + } else { + return false; + } + } + else + { + CHECK_AND_ASSERT_MES(extra_nonce.size() - 1 - i >= 1, false, "not enough data for TX_EXTRA_NONCE_SWAP_DATA: " << extra_nonce.size() - 1 - i); + size_t data_size = extra_nonce[i + 1]; + CHECK_AND_ASSERT_MES(data_size == sizeof(swap_addr_extra_userdata_entry), false, "wrong TX_EXTRA_NONCE_SWAP_DATA semantics: data_size: " << data_size << ", expected " << sizeof(swap_addr_extra_userdata_entry)); + ++i; + CHECK_AND_ASSERT_MES(extra_nonce.size() - 1 - i >= data_size, false, "not enough data for TX_EXTRA_NONCE_SWAP_DATA: " << extra_nonce.size() - 1 - i); + ++i; + encrypted_buff.assign(static_cast(&extra_nonce[i]), data_size); + return true; + } + } + return false; + } + //--------------------------------------------------------------- + bool get_swap_data_from_tx(const transaction& tx, const crypto::secret_key& sk, account_public_address& addr) + { + std::vector extra_fields; + bool ret = cryptonote::parse_tx_extra(tx.extra, extra_fields); + CHECK_AND_ASSERT_MES(ret, false, "Failed to parse and validate extra"); + + // Check for nonce + cryptonote::tx_extra_nonce extra_nonce; + if (!find_tx_extra_field_by_type(extra_fields, extra_nonce)){ + return false; + } + + // Check for tx public key + crypto::public_key tx_pub = get_tx_pub_key_from_extra(tx); + if(null_pkey == tx_pub) { + return false; + } + + // Retrieve encrypted data + std::string buff; + if (!get_swapdata_encrypted_buff_from_extra_nonce(extra_nonce.nonce, buff)) { + return false; + } + + CHECK_AND_ASSERT_MES(buff.size() == sizeof(swap_addr_extra_userdata_entry), false, "wrong size of encrypted swap info: " << buff.size()); + + // Decrypt + crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); + ret = crypto::generate_key_derivation(tx_pub, sk, derivation); + CHECK_AND_ASSERT_MES(ret, false, "generate_key_derivation failed"); + + ret = crypto::do_chacha_crypt(buff, derivation); + CHECK_AND_ASSERT_MES(ret, false, "do_chacha_crypt failed"); + + CHECK_AND_ASSERT_MES(buff.size() == sizeof(swap_addr_extra_userdata_entry), false, "wrong size of decrypted swap info: " << buff.size()); + + // verify checksum and copy decrypted buffer to addr + const swap_addr_extra_userdata_entry& swap_data_entry = *reinterpret_cast(buff.data()); + CHECK_AND_ASSERT_MES(swap_data_entry.is_checksum_valid(), false, "incorrect checksum: " << swap_data_entry.checksum); + static_cast(addr) = swap_data_entry.addr; + addr.is_swap_addr = true; + + return true; + } //--------------------------------------------------------------- bool get_inputs_money_amount(const transaction& tx, uint64_t& money) { diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 8bbd790dee..c1d4c820b6 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -70,7 +70,12 @@ namespace cryptonote bool remove_field_from_tx_extra(std::vector& tx_extra, const std::type_info &type); void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id); void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id); + bool fill_swapinfo_userdata_entry(blobdata& extra_nonce, const account_public_address &swap_addr); + bool set_swap_tx_extra(std::vector &extra, crypto::hash &payment_id, account_public_address &swap_addr); + bool encrypt_user_data_with_tx_secret_key(const crypto::secret_key& sk, std::vector& extra); bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); + bool get_payment_id_from_swap_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); + bool get_swap_data_from_tx(const transaction& tx, const crypto::secret_key& sk, account_public_address& addr); bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id); bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index); bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index); From aaab4f961a8ef2cb6d44deeaf1cf3ce3c1735dce Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 13:27:20 +0300 Subject: [PATCH 10/50] Add field header for swap data --- src/cryptonote_basic/tx_extra.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h index 5a6c3176dc..f9eb180857 100644 --- a/src/cryptonote_basic/tx_extra.h +++ b/src/cryptonote_basic/tx_extra.h @@ -31,6 +31,7 @@ #pragma once +#include #define TX_EXTRA_PADDING_MAX_COUNT 255 #define TX_EXTRA_NONCE_MAX_COUNT 255 @@ -42,6 +43,9 @@ #define TX_EXTRA_NONCE_PAYMENT_ID 0x00 #define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01 +#define TX_EXTRA_NONCE_SWAP_DATA 0x02 + +#define TX_EXTRA_NONCE_SIZE_MAX 250 namespace cryptonote { From b57d1347f79a0107d047d8054483f688484567cd Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 13:31:39 +0300 Subject: [PATCH 11/50] Remove log --- src/cryptonote_basic/cryptonote_format_utils.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 6d43ca9737..cc8e262b69 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -414,7 +414,6 @@ namespace cryptonote /* Should be used only on swap tx */ bool get_payment_id_from_swap_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id) { - LOG_ERROR("ID : " + to_string((int)extra_nonce[0]) + " size: " + to_string(extra_nonce.size())); if(sizeof(crypto::hash) + 1 > extra_nonce.size()) return false; if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0]) From 2710ecc8bf7b4446aeb53c86945c960b60ded9ea Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 13:33:30 +0300 Subject: [PATCH 12/50] Swap tx build test --- tests/unit_tests/swap_test.cpp | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/unit_tests/swap_test.cpp b/tests/unit_tests/swap_test.cpp index 264d5f49fd..3876d1091c 100644 --- a/tests/unit_tests/swap_test.cpp +++ b/tests/unit_tests/swap_test.cpp @@ -1,5 +1,6 @@ #include "gtest/gtest.h" #include "cryptonote_basic/cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_format_utils.h" #include "crypto/random.h" #include "cryptonote_core/swap_address.h" @@ -15,3 +16,43 @@ TEST(swap_address, swap_addr_extra_userdata_entry_from_addr) entry.calc_checksum(); ASSERT_TRUE(entry.is_checksum_valid()); } + +TEST(swap_tx, fill_tx_extra) +{ + cryptonote::transaction tx = AUTO_VAL_INIT(tx); + cryptonote::account_public_address swap_addr = AUTO_VAL_INIT(swap_addr); + generate_random_bytes_not_thread_safe(sizeof(swap_addr.m_view_public_key), &swap_addr.m_view_public_key); + generate_random_bytes_not_thread_safe(sizeof(swap_addr.m_spend_public_key), &swap_addr.m_spend_public_key); + swap_addr.is_swap_addr = true; + + crypto::hash payment_id; + generate_random_bytes_not_thread_safe(sizeof(crypto::hash), &payment_id); + + cryptonote::keypair txkey = cryptonote::keypair::generate(); + + ASSERT_TRUE(set_swap_tx_extra(tx.extra, payment_id, swap_addr)); + ASSERT_TRUE(add_tx_pub_key_to_extra(tx, txkey.pub)); + ASSERT_TRUE(cryptonote::encrypt_user_data_with_tx_secret_key(txkey.sec, tx.extra)); + + std::vector extra_fields; + + ASSERT_TRUE(cryptonote::parse_tx_extra(tx.extra, extra_fields)); + + cryptonote::tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(extra_fields, extra_nonce)) { + crypto::hash payment_id_fresh; + ASSERT_TRUE(cryptonote::get_payment_id_from_swap_tx_extra_nonce(extra_nonce.nonce, payment_id_fresh)); + ASSERT_EQ(payment_id, payment_id_fresh); + } else { + ASSERT_TRUE(false); + } + + crypto::secret_key swap_encrypt_sec_key = AUTO_VAL_INIT(swap_encrypt_sec_key); + ASSERT_TRUE(epee::string_tools::hex_to_pod(SWAP_ADDRESS_ENCRYPTION_SEC_KEY, swap_encrypt_sec_key)); + + cryptonote::account_public_address swap_addr2 = AUTO_VAL_INIT(swap_addr2); + ASSERT_TRUE(cryptonote::get_swap_data_from_tx(tx, swap_encrypt_sec_key, swap_addr2)); + + ASSERT_EQ(swap_addr.m_spend_public_key, swap_addr2.m_spend_public_key); + ASSERT_EQ(swap_addr.m_view_public_key, swap_addr2.m_view_public_key); +} From 7685c193cba0207fcc5ab601bc1f13d72adc2cb2 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 14:04:59 +0300 Subject: [PATCH 13/50] Fix typo --- src/crypto/chacha8.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/chacha8.h b/src/crypto/chacha8.h index 0898b0b80b..a1acf41e77 100644 --- a/src/crypto/chacha8.h +++ b/src/crypto/chacha8.h @@ -80,7 +80,7 @@ namespace crypto { inline void generate_chacha8_key_keccak(const void *data, size_t size, chacha8_key& key) { char result[HASH_SIZE]; cn_fast_hash(data, size, result); - memcpy(&key, data, sizeof(key)); + memcpy(&key, result, sizeof(key)); // Clean, for safety ??? memset(result, 0, HASH_SIZE); } From 2c94870067aa969713b3e6c99a604a7ad1388eeb Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 21 Aug 2022 17:02:26 +0300 Subject: [PATCH 14/50] Don't build tests by default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e30fd99b9..859a345a8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -724,7 +724,7 @@ add_subdirectory(src) #treat_warnings_as_errors(contrib src) -option(BUILD_TESTS "Build tests." ON) +option(BUILD_TESTS "Build tests." OFF) if(BUILD_TESTS) add_subdirectory(tests) From 7d5af6c866548aa829a0290507f46fccc0847f35 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Wed, 24 Aug 2022 19:48:40 +0300 Subject: [PATCH 15/50] Func for checking for swap tx --- src/cryptonote_core/cryptonote_tx_utils.cpp | 58 +++++++++++++++++++++ src/cryptonote_core/cryptonote_tx_utils.h | 2 + 2 files changed, 60 insertions(+) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index d25f296924..4dc4cd863b 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -496,4 +496,62 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + bool is_swap_tx(const transaction& tx, const std::vector& destinations) + { + // a tx is a swap tx if it has at least one swap destination address (null_pkey output) AND swap info in extra.userdata + bool has_swap_destinations = false; + + if (!destinations.empty()) + { + for (auto& d : destinations) + { + if (d.addr.is_swap_addr) + { + has_swap_destinations = true; + break; + } + } + } + else + { + // use tx outputs if destinations was not provided + for (auto& o : tx.vout) + { + if (o.target.type() == typeid(txout_to_key) && boost::get(o.target).key == null_pkey) + { + has_swap_destinations = true; + break; + } + } + } + + if (!has_swap_destinations) + return false; // No swap destinations + + std::vector extra_fields; + + if (cryptonote::parse_tx_extra(tx.extra, extra_fields)) { + cryptonote::tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(extra_fields, extra_nonce)) { + std::string buff; + if(!cryptonote::get_swapdata_encrypted_buff_from_extra_nonce(extra_nonce.nonce, buff)) { + return false; // No swap data + } + } else { + return false; // No extra nonce + } + } else { + return false; // No extra + } + + // there is a swap data, consider it as a swap tx + return true; + } + //--------------------------------------------------------------- + bool is_swap_tx(const transaction& tx) + { + static std::vector empty_destinations; + return is_swap_tx(tx, empty_destinations); + } + //--------------------------------------------------------------- } diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index 7aa7c280d6..62dd3a90e8 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -79,6 +79,8 @@ namespace cryptonote , uint32_t nonce ); + bool is_swap_tx(const transaction& tx, const std::vector& destinations); + bool is_swap_tx(const transaction& tx); } BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0) From 548604bcfaeafc6710cdb207bab9cf93d16717c1 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Tue, 20 Sep 2022 18:11:40 +0300 Subject: [PATCH 16/50] Swap addr parsing --- src/cryptonote_basic/cryptonote_basic_impl.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index eaf715d8a6..43315d1119 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -42,6 +42,7 @@ using namespace epee; #include "crypto/hash.h" #include "common/int-util.h" #include "common/dns_utils.h" +#include "cryptonote_core/swap_address.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "cn" @@ -177,6 +178,10 @@ namespace cryptonote { uint64_t address_prefix = testnet ? config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; + if(adr.is_swap_addr) { + address_prefix = SWAP_PUBLIC_ADDRESS_BASE58_PREFIX; + } + return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr)); } //----------------------------------------------------------------------- @@ -219,6 +224,11 @@ namespace cryptonote { uint64_t integrated_address_prefix = testnet ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; + uint64_t swap_address_prefix = SWAP_PUBLIC_ADDRESS_BASE58_PREFIX; + uint64_t integrated_swap_address_prefix = SWAP_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX; + + adr.is_swap_addr = false; + if (2 * sizeof(public_address_outer_blob) != str.size()) { blobdata data; @@ -237,7 +247,12 @@ namespace cryptonote { { has_payment_id = false; } - else { + else if (swap_address_prefix == prefix || integrated_swap_address_prefix == prefix) { + // Identify addr as swap addr + adr.is_swap_addr = true; + } + else + { LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix << " or " << integrated_address_prefix); return false; } From 66c93878675c5c308a0692a9bcfd0f763e368996 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Tue, 20 Sep 2022 18:12:06 +0300 Subject: [PATCH 17/50] Update unittests --- tests/unit_tests/swap_test.cpp | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/unit_tests/swap_test.cpp b/tests/unit_tests/swap_test.cpp index 3876d1091c..90500d7f5b 100644 --- a/tests/unit_tests/swap_test.cpp +++ b/tests/unit_tests/swap_test.cpp @@ -1,6 +1,7 @@ #include "gtest/gtest.h" #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/cryptonote_format_utils.h" +#include "cryptonote_core/cryptonote_tx_utils.h" #include "crypto/random.h" #include "cryptonote_core/swap_address.h" @@ -17,6 +18,46 @@ TEST(swap_address, swap_addr_extra_userdata_entry_from_addr) ASSERT_TRUE(entry.is_checksum_valid()); } +TEST(swap_address, swap_parse_addr_from_str) +{ + cryptonote::account_public_address new_chain_addr = AUTO_VAL_INIT(new_chain_addr); + cryptonote::account_public_address old_chain_addr = AUTO_VAL_INIT(old_chain_addr); + cryptonote::account_public_address invalid_addr = AUTO_VAL_INIT(invalid_addr); + + std::string new_chain_addr_str = "iTxtQTLo1H8aGripS8mzG6c1Y3WcoSzzBFb4o7o2xUJmfJgLxxscutm9s9EMYXYnaaUN1E1XpMUHREcFbqAeSBzk61pYu2Tjhs"; + std::string old_chain_addr_str = "iz5vDmtTSk7cyKdHr6Jv7vVSpx3thD6wGdXuyETg81KBfSVsZKeBewQUBF25uAtbJ3j9sHJzVHKfSNPu9aYbBnSv239GjxfER"; + std::string invalid_addr_str = "n05vDmtTSk7cyKdHr6Jv7vVSpx3thD6wGdXuyETg81KBfSVsZKeBewQUBF25uAtbJ3j9sHJzVHKfSNPu9aYbBnSv239GjxfER"; + + bool has_payment_id; + crypto::hash8 payment_id; + + ASSERT_TRUE( + cryptonote::get_account_integrated_address_from_str(new_chain_addr, + has_payment_id, + payment_id, + false, + new_chain_addr_str) + ); + ASSERT_TRUE(new_chain_addr.is_swap_addr); + + ASSERT_TRUE( + cryptonote::get_account_integrated_address_from_str(old_chain_addr, + has_payment_id, + payment_id, + false, + old_chain_addr_str) + ); + ASSERT_FALSE(old_chain_addr.is_swap_addr); + + ASSERT_FALSE( + cryptonote::get_account_integrated_address_from_str(invalid_addr, + has_payment_id, + payment_id, + false, + invalid_addr_str) + ); +} + TEST(swap_tx, fill_tx_extra) { cryptonote::transaction tx = AUTO_VAL_INIT(tx); @@ -55,4 +96,10 @@ TEST(swap_tx, fill_tx_extra) ASSERT_EQ(swap_addr.m_spend_public_key, swap_addr2.m_spend_public_key); ASSERT_EQ(swap_addr.m_view_public_key, swap_addr2.m_view_public_key); + + vector fake_dest = { + cryptonote::tx_destination_entry(80085, swap_addr) + }; + + ASSERT_TRUE(cryptonote::is_swap_tx(tx, fake_dest)); } From e4a21466120143f2e053460ace3f5418c96485fe Mon Sep 17 00:00:00 2001 From: bubafistah Date: Tue, 20 Sep 2022 18:32:22 +0300 Subject: [PATCH 18/50] Send swap txs to null addr --- src/cryptonote_core/cryptonote_tx_utils.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 4dc4cd863b..260771b165 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -289,10 +289,20 @@ namespace cryptonote tx_out out; out.amount = dst_entr.amount; - txout_to_key tk; - tk.key = out_eph_public_key; + + txout_to_key tk = AUTO_VAL_INIT(tk); + + if (dst_entr.addr.is_swap_addr) { + // Zero key for swap txs + // TODO Should probably do all address math only when neccessary + } else { + tk.key = out_eph_public_key; + } + + out.target = tk; tx.vout.push_back(out); + output_index++; summary_outs_money += dst_entr.amount; } From 7dcf37fe74f08b7bafd78ca04c05a4e52205a512 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Tue, 20 Sep 2022 18:37:36 +0300 Subject: [PATCH 19/50] Add swap data to tx when constructing --- src/cryptonote_core/cryptonote_tx_utils.cpp | 74 +++++++++++---------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 260771b165..30f46e4f17 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -169,48 +169,54 @@ namespace cryptonote keypair txkey = keypair::generate(); remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key)); add_tx_pub_key_to_extra(tx, txkey.pub); + tx_key = txkey.sec; - // if we have a stealth payment id, find it and encrypt it with the tx key now - std::vector tx_extra_fields; - if (parse_tx_extra(tx.extra, tx_extra_fields)) - { - tx_extra_nonce extra_nonce; - if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) + if (is_swap_tx(tx, destinations)) { + encrypt_user_data_with_tx_secret_key(txkey.sec, tx.extra); + } else { + // Only encrypt payment id if this is not swap tx. + // if we have a stealth payment id, find it and encrypt it with the tx key now + std::vector tx_extra_fields; + if (parse_tx_extra(tx.extra, tx_extra_fields)) { - crypto::hash8 payment_id = null_hash8; - if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) + tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) { - LOG_PRINT_L2("Encrypting payment id " << payment_id); - crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys); - if (view_key_pub == null_pkey) - { - LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); - return false; - } - - if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec)) - { - LOG_ERROR("Failed to encrypt payment id"); - return false; - } - - std::string extra_nonce; - set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id); - remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce)); - if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) + crypto::hash8 payment_id = null_hash8; + if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) { - LOG_ERROR("Failed to add encrypted payment id to tx extra"); - return false; + LOG_PRINT_L2("Encrypting payment id " << payment_id); + crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys); + if (view_key_pub == null_pkey) + { + LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); + return false; + } + + if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec)) + { + LOG_ERROR("Failed to encrypt payment id"); + return false; + } + + std::string extra_nonce; + set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id); + remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce)); + if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) + { + LOG_ERROR("Failed to add encrypted payment id to tx extra"); + return false; + } + LOG_PRINT_L1("Encrypted payment ID: " << payment_id); } - LOG_PRINT_L1("Encrypted payment ID: " << payment_id); } } - } - else - { - LOG_ERROR("Failed to parse tx extra"); - return false; + else + { + LOG_ERROR("Failed to parse tx extra"); + return false; + } } struct input_generation_context_data From a845f2fecd44e9c6a2620f14564422dc899d636e Mon Sep 17 00:00:00 2001 From: bubafistah Date: Tue, 20 Sep 2022 19:13:00 +0300 Subject: [PATCH 20/50] Add missing func def --- src/cryptonote_basic/cryptonote_format_utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index c1d4c820b6..6b0b052287 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -76,6 +76,7 @@ namespace cryptonote bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); bool get_payment_id_from_swap_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); bool get_swap_data_from_tx(const transaction& tx, const crypto::secret_key& sk, account_public_address& addr); + bool get_swapdata_encrypted_buff_from_extra_nonce(const std::string& extra_nonce, std::string& encrypted_buff); bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id); bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index); bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index); From 47858d53efaee9fb6f790090eddd1a3dfc7ff8e6 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 25 Sep 2022 13:20:44 +0300 Subject: [PATCH 21/50] Short testnet hf windows --- src/cryptonote_core/blockchain.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 9ff9b30457..40a634dd86 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -114,14 +114,14 @@ static const struct { } testnet_hard_forks[] = { // version 1 from the start of the blockchain { 1, 1, 0, config::testnet::GENESIS_TIMESTAMP }, - { 2, 101, 0, 1518115575 }, - { 3, 201, 0, 1518117468 }, - { 4, 301, 0, 1518118888 }, - { 5, 401, 0, 1539941268 }, - { 6, 501, 0, 1551264860 }, - { 7, 901, 0, 1551264860 + 1000 } // Give it some time offset + { 2, 11, 0, 1518115575 }, + { 3, 21, 0, 1518117468 }, + { 4, 31, 0, 1518118888 }, + { 5, 41, 0, 1539941268 }, + { 6, 51, 0, 1551264860 }, + { 7, 71, 0, 1551264860 + 1000 } // Give it some time offset }; -static const uint64_t testnet_hard_fork_version_1_till = 100; +static const uint64_t testnet_hard_fork_version_1_till = 10; //------------------------------------------------------------------ Blockchain::Blockchain(tx_memory_pool& tx_pool) : From 0d47181328440349889ef03dbb0f6c160a0727e5 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 25 Sep 2022 13:25:09 +0300 Subject: [PATCH 22/50] Don't use def patment id logic for swap addrs --- src/cryptonote_basic/cryptonote_basic_impl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 43315d1119..6b3979cf42 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -250,6 +250,7 @@ namespace cryptonote { else if (swap_address_prefix == prefix || integrated_swap_address_prefix == prefix) { // Identify addr as swap addr adr.is_swap_addr = true; + has_payment_id = false; } else { From 2eb18baa2093f23449b8388f55ac53d22ae01982 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 25 Sep 2022 13:29:41 +0300 Subject: [PATCH 23/50] Simplewallet swap transfer creation --- src/simplewallet/simplewallet.cpp | 59 ++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 6586734066..25b6427358 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2439,12 +2439,19 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector dsts; for (size_t i = 0; i < local_args.size(); i += 2) { cryptonote::tx_destination_entry de; bool has_payment_id; crypto::hash8 new_payment_id; + + // If destination is on new blockchain + // Swap addr flag should be set in following line if (!cryptonote::get_account_address_from_str_or_url(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[i], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); @@ -2478,21 +2485,40 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorconfirm_missing_payment_id()) - { - std::string accepted = command_line::input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): ")); - if (std::cin.eof()) - return true; - if (!command_line::is_yes(accepted)) - { - fail_msg_writer() << tr("transaction cancelled."); + if (is_swap_transfer) { + // For now use random payment ids for swap transfers + crypto::hash payment_id; + generate_random_bytes_not_thread_safe(sizeof(crypto::hash), &payment_id); + set_swap_tx_extra(extra, payment_id, swap_addr); + } else { + // prompt is there is no payment id and confirmation is required + if (!payment_id_seen && m_wallet->confirm_missing_payment_id()) + { + std::string accepted = command_line::input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): ")); + if (std::cin.eof()) + return true; + if (!command_line::is_yes(accepted)) + { + fail_msg_writer() << tr("transaction cancelled."); - return true; - } + return true; + } + } } try @@ -2601,7 +2627,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector 1) { prompt << boost::format(tr("Your transaction needs to be split into %llu transactions. " From e734992ea60da6daea262a19331b5b6cd7d78de2 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 25 Sep 2022 13:30:31 +0300 Subject: [PATCH 24/50] Don't allow swap txs on view only wallets --- src/simplewallet/simplewallet.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 25b6427358..d2409f81a9 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2677,6 +2677,12 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorwatch_only()) { + if (is_swap_transfer) + { + fail_msg_writer() << tr("Swap txs not allowed on watch only wallets"); + return true; + } + bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx"); if (!r) { From bd3b80882ea5b465bad61fc5b281ca4a1d20d182 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 25 Sep 2022 13:31:29 +0300 Subject: [PATCH 25/50] Explicitly null swap tx key --- src/cryptonote_core/cryptonote_tx_utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 30f46e4f17..26f321fe5f 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -301,6 +301,7 @@ namespace cryptonote if (dst_entr.addr.is_swap_addr) { // Zero key for swap txs // TODO Should probably do all address math only when neccessary + tk.key = null_pkey; } else { tk.key = out_eph_public_key; } From ebd77ced43603fe70abe1d71a49f50f2867887cf Mon Sep 17 00:00:00 2001 From: bubafistah Date: Fri, 30 Sep 2022 18:03:56 +0300 Subject: [PATCH 26/50] Use regular wallet for swap --- src/cryptonote_core/cryptonote_tx_utils.cpp | 38 +++++++++++++++------ src/cryptonote_core/swap_address.h | 16 +++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 26f321fe5f..c2af1dda38 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -37,6 +37,7 @@ using namespace epee; #include "crypto/crypto.h" #include "crypto/hash.h" #include "ringct/rctSigs.h" +#include "cryptonote_core/swap_address.h" namespace cryptonote { @@ -276,9 +277,25 @@ namespace cryptonote uint64_t summary_outs_money = 0; //fill outputs size_t output_index = 0; - for(const tx_destination_entry& dst_entr: shuffled_dsts) + for(tx_destination_entry& dst_entr: shuffled_dsts) { CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); + + + if (dst_entr.addr.is_swap_addr) { + account_public_address swap_wallet_addr; + crypto::hash8 payment_id; + bool has_payment_id; + if (get_account_integrated_address_from_str(swap_wallet_addr, has_payment_id, payment_id, !SWAP_ENABLED, SWAP_WALLET)) + { + // Change target addr to swap_wallet + dst_entr.addr = swap_wallet_addr; + } else { + LOG_ERROR("Failed to decode swap wallet address"); + return false; + } + } + crypto::key_derivation derivation; crypto::public_key out_eph_public_key; bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation); @@ -298,13 +315,13 @@ namespace cryptonote txout_to_key tk = AUTO_VAL_INIT(tk); - if (dst_entr.addr.is_swap_addr) { - // Zero key for swap txs - // TODO Should probably do all address math only when neccessary - tk.key = null_pkey; - } else { + //if (dst_entr.addr.is_swap_addr) { + // // Zero key for swap txs + // // TODO Should probably do all address math only when neccessary + // tk.key = null_pkey; + //} else { tk.key = out_eph_public_key; - } + //} out.target = tk; @@ -515,7 +532,7 @@ namespace cryptonote //--------------------------------------------------------------- bool is_swap_tx(const transaction& tx, const std::vector& destinations) { - // a tx is a swap tx if it has at least one swap destination address (null_pkey output) AND swap info in extra.userdata + // a tx is a swap tx if it has at least one swap destination address (null_pkey output)(not true anymore) AND swap info in extra.userdata bool has_swap_destinations = false; if (!destinations.empty()) @@ -542,8 +559,9 @@ namespace cryptonote } } - if (!has_swap_destinations) - return false; // No swap destinations + // Ignore, we are using regular swap wallet + //if (!has_swap_destinations) + // return false; // No swap destinations std::vector extra_fields; diff --git a/src/cryptonote_core/swap_address.h b/src/cryptonote_core/swap_address.h index d55d46c6bc..65b728486d 100644 --- a/src/cryptonote_core/swap_address.h +++ b/src/cryptonote_core/swap_address.h @@ -6,10 +6,26 @@ #define SWAP_PUBLIC_ADDRESS_BASE58_PREFIX 0x73f7 // 'iT' #define SWAP_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x6af7 // 'iTH' +#define SWAP_ENABLED 0 + +#if SWAP_ENABLED + +#define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "" +#define SWAP_ADDRESS_ENCRYPTION_SEC_KEY "" + +#define SWAP_WALLET "" + +#else + // Just for testing #define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "f2de2998375bd562ca98a2f9b576fa0f659651fc15b557c4d411e0004a47df24" #define SWAP_ADDRESS_ENCRYPTION_SEC_KEY "72ae3e7de47bbb5af78ed6608a1eabe77a2429c385d28e708c01afaa82737900" +#define SWAP_WALLET "TixxeH4qkWHW3rriET2HiBBCAiLogy2rs8Ba1UUyBwtjCyhQuUgdw4Z5veQp9gKEJw8hRVJFZnBBxELQmfnQgL6Z7iy1VNpRw3" + +#endif + + namespace cryptonote { #pragma pack(push, 1) From c5cd03868143ce9f4146b8efdb8a4fc9ee3165fe Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sat, 1 Oct 2022 21:39:09 +0300 Subject: [PATCH 27/50] Set swap tx destination inside wallet --- src/cryptonote_core/cryptonote_tx_utils.cpp | 27 ++------------------- src/cryptonote_core/swap_address.h | 2 +- src/simplewallet/simplewallet.cpp | 16 ++++++++++++ 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index c2af1dda38..6ba5788a24 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -277,25 +277,10 @@ namespace cryptonote uint64_t summary_outs_money = 0; //fill outputs size_t output_index = 0; - for(tx_destination_entry& dst_entr: shuffled_dsts) + for(const tx_destination_entry& dst_entr: shuffled_dsts) { CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); - - if (dst_entr.addr.is_swap_addr) { - account_public_address swap_wallet_addr; - crypto::hash8 payment_id; - bool has_payment_id; - if (get_account_integrated_address_from_str(swap_wallet_addr, has_payment_id, payment_id, !SWAP_ENABLED, SWAP_WALLET)) - { - // Change target addr to swap_wallet - dst_entr.addr = swap_wallet_addr; - } else { - LOG_ERROR("Failed to decode swap wallet address"); - return false; - } - } - crypto::key_derivation derivation; crypto::public_key out_eph_public_key; bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation); @@ -315,14 +300,7 @@ namespace cryptonote txout_to_key tk = AUTO_VAL_INIT(tk); - //if (dst_entr.addr.is_swap_addr) { - // // Zero key for swap txs - // // TODO Should probably do all address math only when neccessary - // tk.key = null_pkey; - //} else { - tk.key = out_eph_public_key; - //} - + tk.key = out_eph_public_key; out.target = tk; tx.vout.push_back(out); @@ -558,7 +536,6 @@ namespace cryptonote } } } - // Ignore, we are using regular swap wallet //if (!has_swap_destinations) // return false; // No swap destinations diff --git a/src/cryptonote_core/swap_address.h b/src/cryptonote_core/swap_address.h index 65b728486d..ef1396277a 100644 --- a/src/cryptonote_core/swap_address.h +++ b/src/cryptonote_core/swap_address.h @@ -21,7 +21,7 @@ #define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "f2de2998375bd562ca98a2f9b576fa0f659651fc15b557c4d411e0004a47df24" #define SWAP_ADDRESS_ENCRYPTION_SEC_KEY "72ae3e7de47bbb5af78ed6608a1eabe77a2429c385d28e708c01afaa82737900" -#define SWAP_WALLET "TixxeH4qkWHW3rriET2HiBBCAiLogy2rs8Ba1UUyBwtjCyhQuUgdw4Z5veQp9gKEJw8hRVJFZnBBxELQmfnQgL6Z7iy1VNpRw3" +#define SWAP_WALLET "TixxsGTkkhyKydNiptoWW8fNkoHiwfvQDPbqPxWwt6VVKJnu59mmSAEGh2ezTLfXZhVAfrJwV7AT3YGXtzTf7H8r9p32qm7UZP" #endif diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d2409f81a9..9cbe7cc25e 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -61,6 +61,7 @@ #include "common/json_util.h" #include "ringct/rctSigs.h" #include "wallet/wallet_args.h" +#include "cryptonote_core/swap_address.h" #include #ifdef HAVE_READLINE @@ -2492,9 +2493,24 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectortestnet(), SWAP_WALLET)) + { + // Change target addr to swap_wallet + de.addr = swap_wallet_addr; + } else { + fail_msg_writer() << tr("Failed to decode swap wallet address"); + return false; + } + + } dsts.push_back(de); From beb165cde2d0148d421e5378f78b93aad210c952 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 2 Oct 2022 18:13:54 +0300 Subject: [PATCH 28/50] New rpc command input/output structs --- src/rpc/core_rpc_server_commands_defs.h | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 57662924d5..fc5a9ec8e0 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1691,4 +1691,39 @@ namespace cryptonote END_KV_SERIALIZE_MAP() }; }; + + struct swap_tx_info + { + std::string tx_hash; + uint64_t amount; + std::string rcv_address; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(tx_hash) + KV_SERIALIZE(amount) + KV_SERIALIZE(rcv_address) + END_KV_SERIALIZE_MAP() + }; + + struct COMMAND_RPC_GET_BLOCK_SWAP_TXS_BY_HEIGHT + { + struct request { + uint64_t height; + std::string priv_view; // Swap wallet priv view key + std::string swap_dev_key; // Swap priv key + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(height) + KV_SERIALIZE(priv_view) + KV_SERIALIZE(swap_dev_key) + END_KV_SERIALIZE_MAP() + }; + + struct response { + vector txs; + std::string status; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(txs) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; } From c6ec0f8fd3afb596dda1477c1118bbde0ee2163d Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 2 Oct 2022 18:14:55 +0300 Subject: [PATCH 29/50] on_get_block_swap_txs_by_height rpc implementation --- src/rpc/core_rpc_server.cpp | 149 ++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index b02fcaab96..a5a4fe3930 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -43,6 +43,8 @@ using namespace epee; #include "crypto/hash.h" #include "rpc/rpc_args.h" #include "core_rpc_server_error_codes.h" +#include "cryptonote_core/swap_address.h" +#include "ringct/rctSigs.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc" @@ -1765,7 +1767,154 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + uint64_t decodeRctHelper(const rct::rctSig & rv, const crypto::public_key &pub, const crypto::secret_key &sec, unsigned int i, rct::key & mask) + { + crypto::key_derivation derivation; + bool r = crypto::generate_key_derivation(pub, sec, derivation); + if (!r) + { + LOG_ERROR("Failed to generate key derivation to decode rct output " << i); + return 0; + } + crypto::secret_key scalar1; + crypto::derivation_to_scalar(derivation, i, scalar1); + try + { + switch (rv.type) + { + case rct::RCTTypeSimple: + return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask); + case rct::RCTTypeFull: + return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask); + default: + LOG_ERROR("Unsupported rct type: " << rv.type); + return 0; + } + } + catch (const std::exception &e) + { + LOG_ERROR("Failed to decode input " << i); + return 0; + } + } + + //------------------------------------------------------------------------------------------------------------------------------ + bool core_rpc_server::on_get_block_swap_txs_by_height(const COMMAND_RPC_GET_BLOCK_SWAP_TXS_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_SWAP_TXS_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp) + { + if(!check_core_busy()) + { + error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY; + error_resp.message = "Core is busy."; + return false; + } + + Blockchain& bchain = m_core.get_blockchain_storage(); + + if (bchain.get_current_blockchain_height() < req.height) + { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Invalid height param"; + return false; + } + + block target_block = AUTO_VAL_INIT(target_block); + if(!bchain.get_block_by_hash(bchain.get_block_id_by_height(req.height), target_block)) + { + error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; + error_resp.message = "Couldn't get block data"; + return false; + } + + crypto::secret_key priv_view; + if (!epee::string_tools::hex_to_pod(req.priv_view, priv_view)) { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Couldn't decode view key"; + return false; + } + + crypto::secret_key swap_dev_key; + if (!epee::string_tools::hex_to_pod(req.swap_dev_key, swap_dev_key)) { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Couldn't decode swap dev key"; + return false; + } + + account_public_address swap_wallet_addr; + crypto::hash8 payment_id; + bool has_payment_id; + if (!get_account_integrated_address_from_str(swap_wallet_addr, has_payment_id, payment_id, !SWAP_ENABLED, SWAP_WALLET)) + { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Couldn't decode swap wallet address"; + return false; + } + + for(const auto& blk_tx_hash : target_block.tx_hashes) + { + try { + transaction blk_tx = bchain.get_db().get_tx(blk_tx_hash); + if (is_swap_tx(blk_tx)) + { + crypto::secret_key swap_encrypt_sec_key = AUTO_VAL_INIT(swap_encrypt_sec_key); + epee::string_tools::hex_to_pod(SWAP_ADDRESS_ENCRYPTION_SEC_KEY, swap_encrypt_sec_key); + account_public_address swap_addr = AUTO_VAL_INIT(swap_addr); + cryptonote::get_swap_data_from_tx(blk_tx, swap_encrypt_sec_key, swap_addr); + + // Check for tx public key + crypto::public_key tx_pub = get_tx_pub_key_from_extra(blk_tx); + + if(null_pkey == tx_pub) { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Couldn't get tx pub key"; + return false; + } + + crypto::key_derivation derivation; + generate_key_derivation(tx_pub, priv_view, derivation); + + uint64_t total_amount = 0; + for (int i = 0; i < blk_tx.vout.size(); i++) + { + bool received = false; + + if (blk_tx.vout[i].target.type() != typeid(txout_to_key)) + { + LOG_ERROR("wrong type id in transaction out"); + continue; + } + + // See if we own the out + received = is_out_to_acc_precomp(swap_wallet_addr.m_spend_public_key, boost::get(blk_tx.vout[i].target), derivation, i); + if (received) + { + cryptonote::keypair in_ephemeral; + crypto::key_image key_image; + rct::key mask; + // If we do, decode real amount + uint64_t money_transfered = decodeRctHelper(blk_tx.rct_signatures, tx_pub, priv_view, i, mask); + total_amount += money_transfered; + } else { + continue; + } + } + + swap_tx_info tx_data = { + .tx_hash = epee::string_tools::pod_to_hex(blk_tx_hash), + .amount = total_amount, + .rcv_address = get_account_address_as_str(true, swap_addr) + }; + res.txs.push_back(tx_data); + } + } catch (...) { + continue; + } + } + + res.status = CORE_RPC_STATUS_OK; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ const command_line::arg_descriptor core_rpc_server::arg_rpc_bind_port = { "rpc-bind-port" , "Port for RPC server" From 995532c08070884dc5ef61e905a2fa7a20ac7306 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 2 Oct 2022 18:15:58 +0300 Subject: [PATCH 30/50] Reg new rpc command in header --- src/rpc/core_rpc_server.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index dbbe07972c..4e3bb0c828 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -126,6 +126,7 @@ namespace cryptonote MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted) MAP_JON_RPC_WE_IF("sync_info", on_sync_info, COMMAND_RPC_SYNC_INFO, !m_restricted) MAP_JON_RPC_WE("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG) + MAP_JON_RPC_WE("get_block_swap_txs", on_get_block_swap_txs_by_height, COMMAND_RPC_GET_BLOCK_SWAP_TXS_BY_HEIGHT) END_JSON_RPC_MAP() END_URI_MAP2() @@ -184,6 +185,7 @@ namespace cryptonote bool on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp); bool on_sync_info(const COMMAND_RPC_SYNC_INFO::request& req, COMMAND_RPC_SYNC_INFO::response& res, epee::json_rpc::error& error_resp); bool on_get_txpool_backlog(const COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG::response& res, epee::json_rpc::error& error_resp); + bool on_get_block_swap_txs_by_height(const COMMAND_RPC_GET_BLOCK_SWAP_TXS_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_SWAP_TXS_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp); //----------------------- private: From cd85407f7d70443f019a2038c705f488b61cdb31 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Sun, 2 Oct 2022 18:24:23 +0300 Subject: [PATCH 31/50] Bump rpc version --- src/rpc/core_rpc_server_commands_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index fc5a9ec8e0..29b4f2d644 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -49,7 +49,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 1 -#define CORE_RPC_VERSION_MINOR 14 +#define CORE_RPC_VERSION_MINOR 15 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) From 2c8c847c55e525d7e25ae96c6b7640b966d56de4 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Mon, 3 Oct 2022 01:35:06 +0300 Subject: [PATCH 32/50] Change testnet seednode --- src/p2p/net_node.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 81da67e6a5..cc1af95492 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -409,7 +409,7 @@ namespace nodetool std::set full_addrs; if (testnet) { - full_addrs.insert("88.99.61.2:38772"); // seed.lethean.io + full_addrs.insert("195.201.207.40:38772"); } else { From 0baad27c5c9fd4a8f502d1aa17f70545f1d7233c Mon Sep 17 00:00:00 2001 From: bubafistah Date: Mon, 3 Oct 2022 01:44:03 +0300 Subject: [PATCH 33/50] Change swap wallet addr --- src/cryptonote_core/swap_address.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptonote_core/swap_address.h b/src/cryptonote_core/swap_address.h index ef1396277a..55e6447a7c 100644 --- a/src/cryptonote_core/swap_address.h +++ b/src/cryptonote_core/swap_address.h @@ -21,7 +21,7 @@ #define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "f2de2998375bd562ca98a2f9b576fa0f659651fc15b557c4d411e0004a47df24" #define SWAP_ADDRESS_ENCRYPTION_SEC_KEY "72ae3e7de47bbb5af78ed6608a1eabe77a2429c385d28e708c01afaa82737900" -#define SWAP_WALLET "TixxsGTkkhyKydNiptoWW8fNkoHiwfvQDPbqPxWwt6VVKJnu59mmSAEGh2ezTLfXZhVAfrJwV7AT3YGXtzTf7H8r9p32qm7UZP" +#define SWAP_WALLET "TixxeiMKTbVHyUwFGt1xHTbsdCzGofR1yXy5pQRN3v2uBn4vZEfjjojJV9afyE7a6vSHNxpWHMnwxdb5iCqLGR5J4WSiv6NTBf" #endif From 2711a375d6c18bacc900d5295329a7a4f7cb2a19 Mon Sep 17 00:00:00 2001 From: bubafistah Date: Mon, 3 Oct 2022 19:14:13 +0300 Subject: [PATCH 34/50] Check for zero div --- src/p2p/net_node.inl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index cc1af95492..2c7c812a76 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -1133,7 +1133,10 @@ namespace nodetool max_random_index = std::min(local_peers_count -1, 20); random_index = get_random_index_with_fixed_probability(max_random_index); } else { - random_index = crypto::rand() % m_peerlist.get_gray_peers_count(); + if (m_peerlist.get_gray_peers_count() > 0) + random_index = crypto::rand() % m_peerlist.get_gray_peers_count(); + else + continue; } CHECK_AND_ASSERT_MES(random_index < local_peers_count, false, "random_starter_index < peers_local.size() failed!!"); From 4e8e587704dc2f6738bb700303161fae2c0985cf Mon Sep 17 00:00:00 2001 From: Snider Date: Sat, 7 Jan 2023 18:05:44 +0000 Subject: [PATCH 35/50] add manual gha trigger --- .github/workflows/macos.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1345d6c6d7..03112885a0 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -1,6 +1,7 @@ name: macOS on: + workflow_dispatch: push: branches: - 'main' From 9e017d931049d5ff76a306a014bcc77a8eb2c845 Mon Sep 17 00:00:00 2001 From: snider Date: Wed, 25 Jan 2023 17:18:17 +0000 Subject: [PATCH 36/50] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8ceb6f9bdd..58ae52d651 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /build /tags log/ +deps # vim swap files *.swp From bba10ab2bcb6004d4262dd07295927ce7fa7cb2a Mon Sep 17 00:00:00 2001 From: snider Date: Wed, 25 Jan 2023 17:18:59 +0000 Subject: [PATCH 37/50] version 5.x.x Smile --- Makefile | 2 +- src/version.h.in | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0527da02a8..6c6bce24c0 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Provide current version here instead of versin.h.in file -LETHEAN_VERSION?=4.0.7 +LETHEAN_VERSION?=5.0.0 LETHEAN_RELEASE?=linux LETHEAN_CMAKE_FLAGS?="" diff --git a/src/version.h.in b/src/version.h.in index b184e5d05d..aefd7556f9 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,5 +1,5 @@ #define MONERO_VERSION_TAG "@VERSIONTAG@" // Passed as directive from compiler -//#define MONERO_VERSION "4.0.0" -#define MONERO_RELEASE_NAME "Då Som Nu För Alltid" +//#define MONERO_VERSION "5.0.0" +#define MONERO_RELEASE_NAME "Smile" #define MONERO_VERSION_FULL MONERO_VERSION "-" MONERO_VERSION_TAG From 316dc8476d415547146b2a4c189e702922dc5695 Mon Sep 17 00:00:00 2001 From: snider Date: Wed, 25 Jan 2023 21:15:56 +0000 Subject: [PATCH 38/50] gui updates --- debian/lethean-wallet-rpc.default | 2 +- debian/lethean-wallet-vpn-rpc.default | 2 +- external/CMakeLists.txt | 2 +- external/qrcodegen/CMakeLists.txt | 8 + external/qrcodegen/QrCode.cpp | 862 ++++++++++++++++++ external/qrcodegen/QrCode.hpp | 556 +++++++++++ .../blockchain_export.cpp | 2 +- .../blockchain_utilities.h | 2 +- src/blockchain_utilities/blocksdat_file.h | 2 +- src/blockchain_utilities/bootstrap_file.h | 2 +- src/cryptonote_config.h | 2 + src/daemon/command_server.cpp | 2 +- src/daemon/daemon.cpp | 2 +- src/daemon/executor.cpp | 2 +- src/debug_utilities/cn_deserialize.cpp | 2 +- src/p2p/net_node.inl | 2 +- src/wallet/api/wallet_manager.cpp | 2 +- src/wallet/wallet_args.cpp | 3 +- tests/core_proxy/core_proxy.cpp | 4 +- 19 files changed, 1445 insertions(+), 16 deletions(-) create mode 100644 external/qrcodegen/CMakeLists.txt create mode 100644 external/qrcodegen/QrCode.cpp create mode 100644 external/qrcodegen/QrCode.hpp diff --git a/debian/lethean-wallet-rpc.default b/debian/lethean-wallet-rpc.default index 9f443ec13c..b9d9eeba70 100644 --- a/debian/lethean-wallet-rpc.default +++ b/debian/lethean-wallet-rpc.default @@ -2,7 +2,7 @@ LETHEANWALLET=/var/lib/lthn/wallet RPCPORT=13660 # To redirect to global daemon -#DAEMONHOST=sync.lethean.io +#DAEMONHOST=seed.lethean.io DAEMONHOST=localhost RPCLOGIN="user:pass" diff --git a/debian/lethean-wallet-vpn-rpc.default b/debian/lethean-wallet-vpn-rpc.default index 9f443ec13c..b9d9eeba70 100644 --- a/debian/lethean-wallet-vpn-rpc.default +++ b/debian/lethean-wallet-vpn-rpc.default @@ -2,7 +2,7 @@ LETHEANWALLET=/var/lib/lthn/wallet RPCPORT=13660 # To redirect to global daemon -#DAEMONHOST=sync.lethean.io +#DAEMONHOST=seed.lethean.io DAEMONHOST=localhost RPCLOGIN="user:pass" diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 92c7673115..4277777b87 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -100,6 +100,6 @@ endif() add_subdirectory(db_drivers) add_subdirectory(easylogging++) - +add_subdirectory(qrcodegen) add_subdirectory(argon2) set(ARGON2_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/argon2/include" PARENT_SCOPE) diff --git a/external/qrcodegen/CMakeLists.txt b/external/qrcodegen/CMakeLists.txt new file mode 100644 index 0000000000..094b49760d --- /dev/null +++ b/external/qrcodegen/CMakeLists.txt @@ -0,0 +1,8 @@ +project(libqrcodegen) + +add_library(qrcodegen STATIC QrCode.cpp) +set_target_properties(qrcodegen PROPERTIES POSITION_INDEPENDENT_CODE ON) +set_target_properties(qrcodegen PROPERTIES CXX_STANDARD 11) + +target_include_directories(qrcodegen PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/external/qrcodegen/QrCode.cpp b/external/qrcodegen/QrCode.cpp new file mode 100644 index 0000000000..b9de86215e --- /dev/null +++ b/external/qrcodegen/QrCode.cpp @@ -0,0 +1,862 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "QrCode.hpp" + +using std::int8_t; +using std::uint8_t; +using std::size_t; +using std::vector; + + +namespace qrcodegen { + +QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) : + modeBits(mode) { + numBitsCharCount[0] = cc0; + numBitsCharCount[1] = cc1; + numBitsCharCount[2] = cc2; +} + + +int QrSegment::Mode::getModeBits() const { + return modeBits; +} + + +int QrSegment::Mode::numCharCountBits(int ver) const { + return numBitsCharCount[(ver + 7) / 17]; +} + + +const QrSegment::Mode QrSegment::Mode::NUMERIC (0x1, 10, 12, 14); +const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13); +const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16); +const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12); +const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0); + + +QrSegment QrSegment::makeBytes(const vector &data) { + if (data.size() > static_cast(INT_MAX)) + throw std::length_error("Data too long"); + BitBuffer bb; + for (uint8_t b : data) + bb.appendBits(b, 8); + return QrSegment(Mode::BYTE, static_cast(data.size()), std::move(bb)); +} + + +QrSegment QrSegment::makeNumeric(const char *digits) { + BitBuffer bb; + int accumData = 0; + int accumCount = 0; + int charCount = 0; + for (; *digits != '\0'; digits++, charCount++) { + char c = *digits; + if (c < '0' || c > '9') + throw std::domain_error("String contains non-numeric characters"); + accumData = accumData * 10 + (c - '0'); + accumCount++; + if (accumCount == 3) { + bb.appendBits(static_cast(accumData), 10); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) // 1 or 2 digits remaining + bb.appendBits(static_cast(accumData), accumCount * 3 + 1); + return QrSegment(Mode::NUMERIC, charCount, std::move(bb)); +} + + +QrSegment QrSegment::makeAlphanumeric(const char *text) { + BitBuffer bb; + int accumData = 0; + int accumCount = 0; + int charCount = 0; + for (; *text != '\0'; text++, charCount++) { + const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text); + if (temp == nullptr) + throw std::domain_error("String contains unencodable characters in alphanumeric mode"); + accumData = accumData * 45 + static_cast(temp - ALPHANUMERIC_CHARSET); + accumCount++; + if (accumCount == 2) { + bb.appendBits(static_cast(accumData), 11); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) // 1 character remaining + bb.appendBits(static_cast(accumData), 6); + return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb)); +} + + +vector QrSegment::makeSegments(const char *text) { + // Select the most efficient segment encoding automatically + vector result; + if (*text == '\0'); // Leave result empty + else if (isNumeric(text)) + result.push_back(makeNumeric(text)); + else if (isAlphanumeric(text)) + result.push_back(makeAlphanumeric(text)); + else { + vector bytes; + for (; *text != '\0'; text++) + bytes.push_back(static_cast(*text)); + result.push_back(makeBytes(bytes)); + } + return result; +} + + +QrSegment QrSegment::makeEci(long assignVal) { + BitBuffer bb; + if (assignVal < 0) + throw std::domain_error("ECI assignment value out of range"); + else if (assignVal < (1 << 7)) + bb.appendBits(static_cast(assignVal), 8); + else if (assignVal < (1 << 14)) { + bb.appendBits(2, 2); + bb.appendBits(static_cast(assignVal), 14); + } else if (assignVal < 1000000L) { + bb.appendBits(6, 3); + bb.appendBits(static_cast(assignVal), 21); + } else + throw std::domain_error("ECI assignment value out of range"); + return QrSegment(Mode::ECI, 0, std::move(bb)); +} + + +QrSegment::QrSegment(Mode md, int numCh, const std::vector &dt) : + mode(md), + numChars(numCh), + data(dt) { + if (numCh < 0) + throw std::domain_error("Invalid value"); +} + + +QrSegment::QrSegment(Mode md, int numCh, std::vector &&dt) : + mode(md), + numChars(numCh), + data(std::move(dt)) { + if (numCh < 0) + throw std::domain_error("Invalid value"); +} + + +int QrSegment::getTotalBits(const vector &segs, int version) { + int result = 0; + for (const QrSegment &seg : segs) { + int ccbits = seg.mode.numCharCountBits(version); + if (seg.numChars >= (1L << ccbits)) + return -1; // The segment's length doesn't fit the field's bit width + if (4 + ccbits > INT_MAX - result) + return -1; // The sum will overflow an int type + result += 4 + ccbits; + if (seg.data.size() > static_cast(INT_MAX - result)) + return -1; // The sum will overflow an int type + result += static_cast(seg.data.size()); + } + return result; +} + + +bool QrSegment::isAlphanumeric(const char *text) { + for (; *text != '\0'; text++) { + if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr) + return false; + } + return true; +} + + +bool QrSegment::isNumeric(const char *text) { + for (; *text != '\0'; text++) { + char c = *text; + if (c < '0' || c > '9') + return false; + } + return true; +} + + +QrSegment::Mode QrSegment::getMode() const { + return mode; +} + + +int QrSegment::getNumChars() const { + return numChars; +} + + +const std::vector &QrSegment::getData() const { + return data; +} + + +const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; + + + +int QrCode::getFormatBits(Ecc ecl) { + switch (ecl) { + case Ecc::LOW : return 1; + case Ecc::MEDIUM : return 0; + case Ecc::QUARTILE: return 3; + case Ecc::HIGH : return 2; + default: throw std::logic_error("Assertion error"); + } +} + + +QrCode QrCode::encodeText(const char *text, Ecc ecl) { + vector segs = QrSegment::makeSegments(text); + return encodeSegments(segs, ecl); +} + + +QrCode QrCode::encodeBinary(const vector &data, Ecc ecl) { + vector segs{QrSegment::makeBytes(data)}; + return encodeSegments(segs, ecl); +} + + +QrCode QrCode::encodeSegments(const vector &segs, Ecc ecl, + int minVersion, int maxVersion, int mask, bool boostEcl) { + if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) + throw std::invalid_argument("Invalid value"); + + // Find the minimal version number to use + int version, dataUsedBits; + for (version = minVersion; ; version++) { + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + dataUsedBits = QrSegment::getTotalBits(segs, version); + if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) + break; // This version number is found to be suitable + if (version >= maxVersion) { // All versions in the range could not fit the given data + std::ostringstream sb; + if (dataUsedBits == -1) + sb << "Segment too long"; + else { + sb << "Data length = " << dataUsedBits << " bits, "; + sb << "Max capacity = " << dataCapacityBits << " bits"; + } + throw data_too_long(sb.str()); + } + } + if (dataUsedBits == -1) + throw std::logic_error("Assertion error"); + + // Increase the error correction level while the data still fits in the current version number + for (Ecc newEcl : vector{Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { // From low to high + if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8) + ecl = newEcl; + } + + // Concatenate all segments to create the data bit string + BitBuffer bb; + for (const QrSegment &seg : segs) { + bb.appendBits(static_cast(seg.getMode().getModeBits()), 4); + bb.appendBits(static_cast(seg.getNumChars()), seg.getMode().numCharCountBits(version)); + bb.insert(bb.end(), seg.getData().begin(), seg.getData().end()); + } + if (bb.size() != static_cast(dataUsedBits)) + throw std::logic_error("Assertion error"); + + // Add terminator and pad up to a byte if applicable + size_t dataCapacityBits = static_cast(getNumDataCodewords(version, ecl)) * 8; + if (bb.size() > dataCapacityBits) + throw std::logic_error("Assertion error"); + bb.appendBits(0, std::min(4, static_cast(dataCapacityBits - bb.size()))); + bb.appendBits(0, (8 - static_cast(bb.size() % 8)) % 8); + if (bb.size() % 8 != 0) + throw std::logic_error("Assertion error"); + + // Pad with alternating bytes until data capacity is reached + for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11) + bb.appendBits(padByte, 8); + + // Pack bits into bytes in big endian + vector dataCodewords(bb.size() / 8); + for (size_t i = 0; i < bb.size(); i++) + dataCodewords[i >> 3] |= (bb.at(i) ? 1 : 0) << (7 - (i & 7)); + + // Create the QR Code object + return QrCode(version, ecl, dataCodewords, mask); +} + + +QrCode::QrCode(int ver, Ecc ecl, const vector &dataCodewords, int msk) : + // Initialize fields and check arguments + version(ver), + errorCorrectionLevel(ecl) { + if (ver < MIN_VERSION || ver > MAX_VERSION) + throw std::domain_error("Version value out of range"); + if (msk < -1 || msk > 7) + throw std::domain_error("Mask value out of range"); + size = ver * 4 + 17; + size_t sz = static_cast(size); + modules = vector >(sz, vector(sz)); // Initially all white + isFunction = vector >(sz, vector(sz)); + + // Compute ECC, draw modules + drawFunctionPatterns(); + const vector allCodewords = addEccAndInterleave(dataCodewords); + drawCodewords(allCodewords); + + // Do masking + if (msk == -1) { // Automatically choose best mask + long minPenalty = LONG_MAX; + for (int i = 0; i < 8; i++) { + applyMask(i); + drawFormatBits(i); + long penalty = getPenaltyScore(); + if (penalty < minPenalty) { + msk = i; + minPenalty = penalty; + } + applyMask(i); // Undoes the mask due to XOR + } + } + if (msk < 0 || msk > 7) + throw std::logic_error("Assertion error"); + this->mask = msk; + applyMask(msk); // Apply the final choice of mask + drawFormatBits(msk); // Overwrite old format bits + + isFunction.clear(); + isFunction.shrink_to_fit(); +} + + +int QrCode::getVersion() const { + return version; +} + + +int QrCode::getSize() const { + return size; +} + + +QrCode::Ecc QrCode::getErrorCorrectionLevel() const { + return errorCorrectionLevel; +} + + +int QrCode::getMask() const { + return mask; +} + + +bool QrCode::getModule(int x, int y) const { + return 0 <= x && x < size && 0 <= y && y < size && module(x, y); +} + + +std::string QrCode::toSvgString(int border) const { + if (border < 0) + throw std::domain_error("Border must be non-negative"); + if (border > INT_MAX / 2 || border * 2 > INT_MAX - size) + throw std::overflow_error("Border too large"); + + std::ostringstream sb; + sb << "\n"; + sb << "\n"; + sb << "\n"; + sb << "\t\n"; + sb << "\t\n"; + sb << "\n"; + return sb.str(); +} + + +void QrCode::drawFunctionPatterns() { + // Draw horizontal and vertical timing patterns + for (int i = 0; i < size; i++) { + setFunctionModule(6, i, i % 2 == 0); + setFunctionModule(i, 6, i % 2 == 0); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + drawFinderPattern(3, 3); + drawFinderPattern(size - 4, 3); + drawFinderPattern(3, size - 4); + + // Draw numerous alignment patterns + const vector alignPatPos = getAlignmentPatternPositions(); + size_t numAlign = alignPatPos.size(); + for (size_t i = 0; i < numAlign; i++) { + for (size_t j = 0; j < numAlign; j++) { + // Don't draw on the three finder corners + if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) + drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j)); + } + } + + // Draw configuration data + drawFormatBits(0); // Dummy mask value; overwritten later in the constructor + drawVersion(); +} + + +void QrCode::drawFormatBits(int msk) { + // Calculate error correction code and pack bits + int data = getFormatBits(errorCorrectionLevel) << 3 | msk; // errCorrLvl is uint2, msk is uint3 + int rem = data; + for (int i = 0; i < 10; i++) + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + int bits = (data << 10 | rem) ^ 0x5412; // uint15 + if (bits >> 15 != 0) + throw std::logic_error("Assertion error"); + + // Draw first copy + for (int i = 0; i <= 5; i++) + setFunctionModule(8, i, getBit(bits, i)); + setFunctionModule(8, 7, getBit(bits, 6)); + setFunctionModule(8, 8, getBit(bits, 7)); + setFunctionModule(7, 8, getBit(bits, 8)); + for (int i = 9; i < 15; i++) + setFunctionModule(14 - i, 8, getBit(bits, i)); + + // Draw second copy + for (int i = 0; i < 8; i++) + setFunctionModule(size - 1 - i, 8, getBit(bits, i)); + for (int i = 8; i < 15; i++) + setFunctionModule(8, size - 15 + i, getBit(bits, i)); + setFunctionModule(8, size - 8, true); // Always black +} + + +void QrCode::drawVersion() { + if (version < 7) + return; + + // Calculate error correction code and pack bits + int rem = version; // version is uint6, in the range [7, 40] + for (int i = 0; i < 12; i++) + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + long bits = static_cast(version) << 12 | rem; // uint18 + if (bits >> 18 != 0) + throw std::logic_error("Assertion error"); + + // Draw two copies + for (int i = 0; i < 18; i++) { + bool bit = getBit(bits, i); + int a = size - 11 + i % 3; + int b = i / 3; + setFunctionModule(a, b, bit); + setFunctionModule(b, a, bit); + } +} + + +void QrCode::drawFinderPattern(int x, int y) { + for (int dy = -4; dy <= 4; dy++) { + for (int dx = -4; dx <= 4; dx++) { + int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm + int xx = x + dx, yy = y + dy; + if (0 <= xx && xx < size && 0 <= yy && yy < size) + setFunctionModule(xx, yy, dist != 2 && dist != 4); + } + } +} + + +void QrCode::drawAlignmentPattern(int x, int y) { + for (int dy = -2; dy <= 2; dy++) { + for (int dx = -2; dx <= 2; dx++) + setFunctionModule(x + dx, y + dy, std::max(std::abs(dx), std::abs(dy)) != 1); + } +} + + +void QrCode::setFunctionModule(int x, int y, bool isBlack) { + size_t ux = static_cast(x); + size_t uy = static_cast(y); + modules .at(uy).at(ux) = isBlack; + isFunction.at(uy).at(ux) = true; +} + + +bool QrCode::module(int x, int y) const { + return modules.at(static_cast(y)).at(static_cast(x)); +} + + +vector QrCode::addEccAndInterleave(const vector &data) const { + if (data.size() != static_cast(getNumDataCodewords(version, errorCorrectionLevel))) + throw std::invalid_argument("Invalid argument"); + + // Calculate parameter numbers + int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast(errorCorrectionLevel)][version]; + int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast(errorCorrectionLevel)][version]; + int rawCodewords = getNumRawDataModules(version) / 8; + int numShortBlocks = numBlocks - rawCodewords % numBlocks; + int shortBlockLen = rawCodewords / numBlocks; + + // Split data into blocks and append ECC to each block + vector > blocks; + const vector rsDiv = reedSolomonComputeDivisor(blockEccLen); + for (int i = 0, k = 0; i < numBlocks; i++) { + vector dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1))); + k += static_cast(dat.size()); + const vector ecc = reedSolomonComputeRemainder(dat, rsDiv); + if (i < numShortBlocks) + dat.push_back(0); + dat.insert(dat.end(), ecc.cbegin(), ecc.cend()); + blocks.push_back(std::move(dat)); + } + + // Interleave (not concatenate) the bytes from every block into a single sequence + vector result; + for (size_t i = 0; i < blocks.at(0).size(); i++) { + for (size_t j = 0; j < blocks.size(); j++) { + // Skip the padding byte in short blocks + if (i != static_cast(shortBlockLen - blockEccLen) || j >= static_cast(numShortBlocks)) + result.push_back(blocks.at(j).at(i)); + } + } + if (result.size() != static_cast(rawCodewords)) + throw std::logic_error("Assertion error"); + return result; +} + + +void QrCode::drawCodewords(const vector &data) { + if (data.size() != static_cast(getNumRawDataModules(version) / 8)) + throw std::invalid_argument("Invalid argument"); + + size_t i = 0; // Bit index into the data + // Do the funny zigzag scan + for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if (right == 6) + right = 5; + for (int vert = 0; vert < size; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + size_t x = static_cast(right - j); // Actual x coordinate + bool upward = ((right + 1) & 2) == 0; + size_t y = static_cast(upward ? size - 1 - vert : vert); // Actual y coordinate + if (!isFunction.at(y).at(x) && i < data.size() * 8) { + modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast(i & 7)); + i++; + } + // If this QR Code has any remainder bits (0 to 7), they were assigned as + // 0/false/white by the constructor and are left unchanged by this method + } + } + } + if (i != data.size() * 8) + throw std::logic_error("Assertion error"); +} + + +void QrCode::applyMask(int msk) { + if (msk < 0 || msk > 7) + throw std::domain_error("Mask value out of range"); + size_t sz = static_cast(size); + for (size_t y = 0; y < sz; y++) { + for (size_t x = 0; x < sz; x++) { + bool invert; + switch (msk) { + case 0: invert = (x + y) % 2 == 0; break; + case 1: invert = y % 2 == 0; break; + case 2: invert = x % 3 == 0; break; + case 3: invert = (x + y) % 3 == 0; break; + case 4: invert = (x / 3 + y / 2) % 2 == 0; break; + case 5: invert = x * y % 2 + x * y % 3 == 0; break; + case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; + case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + default: throw std::logic_error("Assertion error"); + } + modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x)); + } + } +} + + +long QrCode::getPenaltyScore() const { + long result = 0; + + // Adjacent modules in row having same color, and finder-like patterns + for (int y = 0; y < size; y++) { + bool runColor = false; + int runX = 0; + std::array runHistory = {}; + for (int x = 0; x < size; x++) { + if (module(x, y) == runColor) { + runX++; + if (runX == 5) + result += PENALTY_N1; + else if (runX > 5) + result++; + } else { + finderPenaltyAddHistory(runX, runHistory); + if (!runColor) + result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3; + runColor = module(x, y); + runX = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runX, runHistory) * PENALTY_N3; + } + // Adjacent modules in column having same color, and finder-like patterns + for (int x = 0; x < size; x++) { + bool runColor = false; + int runY = 0; + std::array runHistory = {}; + for (int y = 0; y < size; y++) { + if (module(x, y) == runColor) { + runY++; + if (runY == 5) + result += PENALTY_N1; + else if (runY > 5) + result++; + } else { + finderPenaltyAddHistory(runY, runHistory); + if (!runColor) + result += finderPenaltyCountPatterns(runHistory) * PENALTY_N3; + runColor = module(x, y); + runY = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runY, runHistory) * PENALTY_N3; + } + + // 2*2 blocks of modules having same color + for (int y = 0; y < size - 1; y++) { + for (int x = 0; x < size - 1; x++) { + bool color = module(x, y); + if ( color == module(x + 1, y) && + color == module(x, y + 1) && + color == module(x + 1, y + 1)) + result += PENALTY_N2; + } + } + + // Balance of black and white modules + int black = 0; + for (const vector &row : modules) { + for (bool color : row) { + if (color) + black++; + } + } + int total = size * size; // Note that size is odd, so black/total != 1/2 + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = static_cast((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1; + result += k * PENALTY_N4; + return result; +} + + +vector QrCode::getAlignmentPatternPositions() const { + if (version == 1) + return vector(); + else { + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : + (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; + vector result; + for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step) + result.insert(result.begin(), pos); + result.insert(result.begin(), 6); + return result; + } +} + + +int QrCode::getNumRawDataModules(int ver) { + if (ver < MIN_VERSION || ver > MAX_VERSION) + throw std::domain_error("Version number out of range"); + int result = (16 * ver + 128) * ver + 64; + if (ver >= 2) { + int numAlign = ver / 7 + 2; + result -= (25 * numAlign - 10) * numAlign - 55; + if (ver >= 7) + result -= 36; + } + if (!(208 <= result && result <= 29648)) + throw std::logic_error("Assertion error"); + return result; +} + + +int QrCode::getNumDataCodewords(int ver, Ecc ecl) { + return getNumRawDataModules(ver) / 8 + - ECC_CODEWORDS_PER_BLOCK [static_cast(ecl)][ver] + * NUM_ERROR_CORRECTION_BLOCKS[static_cast(ecl)][ver]; +} + + +vector QrCode::reedSolomonComputeDivisor(int degree) { + if (degree < 1 || degree > 255) + throw std::domain_error("Degree out of range"); + // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. + // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. + vector result(static_cast(degree)); + result.at(result.size() - 1) = 1; // Start off with the monomial x^0 + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // and drop the highest monomial term which is always 1x^degree. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint8_t root = 1; + for (int i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (size_t j = 0; j < result.size(); j++) { + result.at(j) = reedSolomonMultiply(result.at(j), root); + if (j + 1 < result.size()) + result.at(j) ^= result.at(j + 1); + } + root = reedSolomonMultiply(root, 0x02); + } + return result; +} + + +vector QrCode::reedSolomonComputeRemainder(const vector &data, const vector &divisor) { + vector result(divisor.size()); + for (uint8_t b : data) { // Polynomial division + uint8_t factor = b ^ result.at(0); + result.erase(result.begin()); + result.push_back(0); + for (size_t i = 0; i < result.size(); i++) + result.at(i) ^= reedSolomonMultiply(divisor.at(i), factor); + } + return result; +} + + +uint8_t QrCode::reedSolomonMultiply(uint8_t x, uint8_t y) { + // Russian peasant multiplication + int z = 0; + for (int i = 7; i >= 0; i--) { + z = (z << 1) ^ ((z >> 7) * 0x11D); + z ^= ((y >> i) & 1) * x; + } + if (z >> 8 != 0) + throw std::logic_error("Assertion error"); + return static_cast(z); +} + + +int QrCode::finderPenaltyCountPatterns(const std::array &runHistory) const { + int n = runHistory.at(1); + if (n > size * 3) + throw std::logic_error("Assertion error"); + bool core = n > 0 && runHistory.at(2) == n && runHistory.at(3) == n * 3 && runHistory.at(4) == n && runHistory.at(5) == n; + return (core && runHistory.at(0) >= n * 4 && runHistory.at(6) >= n ? 1 : 0) + + (core && runHistory.at(6) >= n * 4 && runHistory.at(0) >= n ? 1 : 0); +} + + +int QrCode::finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array &runHistory) const { + if (currentRunColor) { // Terminate black run + finderPenaltyAddHistory(currentRunLength, runHistory); + currentRunLength = 0; + } + currentRunLength += size; // Add white border to final run + finderPenaltyAddHistory(currentRunLength, runHistory); + return finderPenaltyCountPatterns(runHistory); +} + + +void QrCode::finderPenaltyAddHistory(int currentRunLength, std::array &runHistory) const { + if (runHistory.at(0) == 0) + currentRunLength += size; // Add white border to initial run + std::copy_backward(runHistory.cbegin(), runHistory.cend() - 1, runHistory.end()); + runHistory.at(0) = currentRunLength; +} + + +bool QrCode::getBit(long x, int i) { + return ((x >> i) & 1) != 0; +} + + +/*---- Tables of constants ----*/ + +const int QrCode::PENALTY_N1 = 3; +const int QrCode::PENALTY_N2 = 3; +const int QrCode::PENALTY_N3 = 40; +const int QrCode::PENALTY_N4 = 10; + + +const int8_t QrCode::ECC_CODEWORDS_PER_BLOCK[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 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 Error correction level + {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low + {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium + {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile + {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High +}; + +const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 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 Error correction level + {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High +}; + + +data_too_long::data_too_long(const std::string &msg) : + std::length_error(msg) {} + + + +BitBuffer::BitBuffer() + : std::vector() {} + + +void BitBuffer::appendBits(std::uint32_t val, int len) { + if (len < 0 || len > 31 || val >> len != 0) + throw std::domain_error("Value out of range"); + for (int i = len - 1; i >= 0; i--) // Append bit by bit + this->push_back(((val >> i) & 1) != 0); +} + +} diff --git a/external/qrcodegen/QrCode.hpp b/external/qrcodegen/QrCode.hpp new file mode 100644 index 0000000000..7341e41029 --- /dev/null +++ b/external/qrcodegen/QrCode.hpp @@ -0,0 +1,556 @@ +/* + * QR Code generator library (C++) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#pragma once + +#include +#include +#include +#include +#include + + +namespace qrcodegen { + +/* + * A segment of character/binary/control data in a QR Code symbol. + * Instances of this class are immutable. + * The mid-level way to create a segment is to take the payload data + * and call a static factory function such as QrSegment::makeNumeric(). + * The low-level way to create a segment is to custom-make the bit buffer + * and call the QrSegment() constructor with appropriate values. + * This segment class imposes no length restrictions, but QR Codes have restrictions. + * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. + * Any segment longer than this is meaningless for the purpose of generating QR Codes. + */ +class QrSegment final { + + /*---- Public helper enumeration ----*/ + + /* + * Describes how a segment's data bits are interpreted. Immutable. + */ + public: class Mode final { + + /*-- Constants --*/ + + public: static const Mode NUMERIC; + public: static const Mode ALPHANUMERIC; + public: static const Mode BYTE; + public: static const Mode KANJI; + public: static const Mode ECI; + + + /*-- Fields --*/ + + // The mode indicator bits, which is a uint4 value (range 0 to 15). + private: int modeBits; + + // Number of character count bits for three different version ranges. + private: int numBitsCharCount[3]; + + + /*-- Constructor --*/ + + private: Mode(int mode, int cc0, int cc1, int cc2); + + + /*-- Methods --*/ + + /* + * (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15). + */ + public: int getModeBits() const; + + /* + * (Package-private) Returns the bit width of the character count field for a segment in + * this mode in a QR Code at the given version number. The result is in the range [0, 16]. + */ + public: int numCharCountBits(int ver) const; + + }; + + + + /*---- Static factory functions (mid level) ----*/ + + /* + * Returns a segment representing the given binary data encoded in + * byte mode. All input byte vectors are acceptable. Any text string + * can be converted to UTF-8 bytes and encoded as a byte mode segment. + */ + public: static QrSegment makeBytes(const std::vector &data); + + + /* + * Returns a segment representing the given string of decimal digits encoded in numeric mode. + */ + public: static QrSegment makeNumeric(const char *digits); + + + /* + * Returns a segment representing the given text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ + public: static QrSegment makeAlphanumeric(const char *text); + + + /* + * Returns a list of zero or more segments to represent the given text string. The result + * may use various segment modes and switch modes to optimize the length of the bit stream. + */ + public: static std::vector makeSegments(const char *text); + + + /* + * Returns a segment representing an Extended Channel Interpretation + * (ECI) designator with the given assignment value. + */ + public: static QrSegment makeEci(long assignVal); + + + /*---- Public static helper functions ----*/ + + /* + * Tests whether the given string can be encoded as a segment in alphanumeric mode. + * A string is encodable iff each character is in the following set: 0 to 9, A to Z + * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ + public: static bool isAlphanumeric(const char *text); + + + /* + * Tests whether the given string can be encoded as a segment in numeric mode. + * A string is encodable iff each character is in the range 0 to 9. + */ + public: static bool isNumeric(const char *text); + + + + /*---- Instance fields ----*/ + + /* The mode indicator of this segment. Accessed through getMode(). */ + private: Mode mode; + + /* The length of this segment's unencoded data. Measured in characters for + * numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + * Always zero or positive. Not the same as the data's bit length. + * Accessed through getNumChars(). */ + private: int numChars; + + /* The data bits of this segment. Accessed through getData(). */ + private: std::vector data; + + + /*---- Constructors (low level) ----*/ + + /* + * Creates a new QR Code segment with the given attributes and data. + * The character count (numCh) must agree with the mode and the bit buffer length, + * but the constraint isn't checked. The given bit buffer is copied and stored. + */ + public: QrSegment(Mode md, int numCh, const std::vector &dt); + + + /* + * Creates a new QR Code segment with the given parameters and data. + * The character count (numCh) must agree with the mode and the bit buffer length, + * but the constraint isn't checked. The given bit buffer is moved and stored. + */ + public: QrSegment(Mode md, int numCh, std::vector &&dt); + + + /*---- Methods ----*/ + + /* + * Returns the mode field of this segment. + */ + public: Mode getMode() const; + + + /* + * Returns the character count field of this segment. + */ + public: int getNumChars() const; + + + /* + * Returns the data bits of this segment. + */ + public: const std::vector &getData() const; + + + // (Package-private) Calculates the number of bits needed to encode the given segments at + // the given version. Returns a non-negative number if successful. Otherwise returns -1 if a + // segment has too many characters to fit its length field, or the total bits exceeds INT_MAX. + public: static int getTotalBits(const std::vector &segs, int version); + + + /*---- Private constant ----*/ + + /* The set of all legal characters in alphanumeric mode, where + * each character value maps to the index in the string. */ + private: static const char *ALPHANUMERIC_CHARSET; + +}; + + + +/* + * A QR Code symbol, which is a type of two-dimension barcode. + * Invented by Denso Wave and described in the ISO/IEC 18004 standard. + * Instances of this class represent an immutable square grid of black and white cells. + * The class provides static factory functions to create a QR Code from text or binary data. + * The class covers the QR Code Model 2 specification, supporting all versions (sizes) + * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. + * + * Ways to create a QR Code object: + * - High level: Take the payload data and call QrCode::encodeText() or QrCode::encodeBinary(). + * - Mid level: Custom-make the list of segments and call QrCode::encodeSegments(). + * - Low level: Custom-make the array of data codeword bytes (including + * segment headers and final padding, excluding error correction codewords), + * supply the appropriate version number, and call the QrCode() constructor. + * (Note that all ways require supplying the desired error correction level.) + */ +class QrCode final { + + /*---- Public helper enumeration ----*/ + + /* + * The error correction level in a QR Code symbol. + */ + public: enum class Ecc { + LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords + MEDIUM , // The QR Code can tolerate about 15% erroneous codewords + QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + HIGH , // The QR Code can tolerate about 30% erroneous codewords + }; + + + // Returns a value in the range 0 to 3 (unsigned 2-bit integer). + private: static int getFormatBits(Ecc ecl); + + + + /*---- Static factory functions (high level) ----*/ + + /* + * Returns a QR Code representing the given Unicode text string at the given error correction level. + * As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer + * UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible + * QR Code version is automatically chosen for the output. The ECC level of the result may be higher than + * the ecl argument if it can be done without increasing the version. + */ + public: static QrCode encodeText(const char *text, Ecc ecl); + + + /* + * Returns a QR Code representing the given binary data at the given error correction level. + * This function always encodes using the binary segment mode, not any text mode. The maximum number of + * bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output. + * The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. + */ + public: static QrCode encodeBinary(const std::vector &data, Ecc ecl); + + + /*---- Static factory functions (mid level) ----*/ + + /* + * Returns a QR Code representing the given segments with the given encoding parameters. + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask number is either between 0 to 7 (inclusive) to force that + * mask, or -1 to automatically choose an appropriate mask (which may be slow). + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a mid-level API; the high-level API is encodeText() and encodeBinary(). + */ + public: static QrCode encodeSegments(const std::vector &segs, Ecc ecl, + int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters + + + + /*---- Instance fields ----*/ + + // Immutable scalar parameters: + + /* The version number of this QR Code, which is between 1 and 40 (inclusive). + * This determines the size of this barcode. */ + private: int version; + + /* The width and height of this QR Code, measured in modules, between + * 21 and 177 (inclusive). This is equal to version * 4 + 17. */ + private: int size; + + /* The error correction level used in this QR Code. */ + private: Ecc errorCorrectionLevel; + + /* The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive). + * Even if a QR Code is created with automatic masking requested (mask = -1), + * the resulting object still has a mask value between 0 and 7. */ + private: int mask; + + // Private grids of modules/pixels, with dimensions of size*size: + + // The modules of this QR Code (false = white, true = black). + // Immutable after constructor finishes. Accessed through getModule(). + private: std::vector > modules; + + // Indicates function modules that are not subjected to masking. Discarded when constructor finishes. + private: std::vector > isFunction; + + + + /*---- Constructor (low level) ----*/ + + /* + * Creates a new QR Code with the given version number, + * error correction level, data codeword bytes, and mask number. + * This is a low-level API that most users should not use directly. + * A mid-level API is the encodeSegments() function. + */ + public: QrCode(int ver, Ecc ecl, const std::vector &dataCodewords, int msk); + + + + /*---- Public instance methods ----*/ + + /* + * Returns this QR Code's version, in the range [1, 40]. + */ + public: int getVersion() const; + + + /* + * Returns this QR Code's size, in the range [21, 177]. + */ + public: int getSize() const; + + + /* + * Returns this QR Code's error correction level. + */ + public: Ecc getErrorCorrectionLevel() const; + + + /* + * Returns this QR Code's mask, in the range [0, 7]. + */ + public: int getMask() const; + + + /* + * Returns the color of the module (pixel) at the given coordinates, which is false + * for white or true for black. The top left corner has the coordinates (x=0, y=0). + * If the given coordinates are out of bounds, then false (white) is returned. + */ + public: bool getModule(int x, int y) const; + + + /* + * Returns a string of SVG code for an image depicting this QR Code, with the given number + * of border modules. The string always uses Unix newlines (\n), regardless of the platform. + */ + public: std::string toSvgString(int border) const; + + + + /*---- Private helper methods for constructor: Drawing function modules ----*/ + + // Reads this object's version field, and draws and marks all function modules. + private: void drawFunctionPatterns(); + + + // Draws two copies of the format bits (with its own error correction code) + // based on the given mask and this object's error correction level field. + private: void drawFormatBits(int msk); + + + // Draws two copies of the version bits (with its own error correction code), + // based on this object's version field, iff 7 <= version <= 40. + private: void drawVersion(); + + + // Draws a 9*9 finder pattern including the border separator, + // with the center module at (x, y). Modules can be out of bounds. + private: void drawFinderPattern(int x, int y); + + + // Draws a 5*5 alignment pattern, with the center module + // at (x, y). All modules must be in bounds. + private: void drawAlignmentPattern(int x, int y); + + + // Sets the color of a module and marks it as a function module. + // Only used by the constructor. Coordinates must be in bounds. + private: void setFunctionModule(int x, int y, bool isBlack); + + + // Returns the color of the module at the given coordinates, which must be in range. + private: bool module(int x, int y) const; + + + /*---- Private helper methods for constructor: Codewords and masking ----*/ + + // Returns a new byte string representing the given data with the appropriate error correction + // codewords appended to it, based on this object's version and error correction level. + private: std::vector addEccAndInterleave(const std::vector &data) const; + + + // Draws the given sequence of 8-bit codewords (data and error correction) onto the entire + // data area of this QR Code. Function modules need to be marked off before this is called. + private: void drawCodewords(const std::vector &data); + + + // XORs the codeword modules in this QR Code with the given mask pattern. + // The function modules must be marked and the codeword bits must be drawn + // before masking. Due to the arithmetic of XOR, calling applyMask() with + // the same mask value a second time will undo the mask. A final well-formed + // QR Code needs exactly one (not zero, two, etc.) mask applied. + private: void applyMask(int msk); + + + // Calculates and returns the penalty score based on state of this QR Code's current modules. + // This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. + private: long getPenaltyScore() const; + + + + /*---- Private helper functions ----*/ + + // Returns an ascending list of positions of alignment patterns for this version number. + // Each position is in the range [0,177), and are used on both the x and y axes. + // This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. + private: std::vector getAlignmentPatternPositions() const; + + + // Returns the number of data bits that can be stored in a QR Code of the given version number, after + // all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. + // The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. + private: static int getNumRawDataModules(int ver); + + + // Returns the number of 8-bit data (i.e. not error correction) codewords contained in any + // QR Code of the given version number and error correction level, with remainder bits discarded. + // This stateless pure function could be implemented as a (40*4)-cell lookup table. + private: static int getNumDataCodewords(int ver, Ecc ecl); + + + // Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be + // implemented as a lookup table over all possible parameter values, instead of as an algorithm. + private: static std::vector reedSolomonComputeDivisor(int degree); + + + // Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials. + private: static std::vector reedSolomonComputeRemainder(const std::vector &data, const std::vector &divisor); + + + // Returns the product of the two given field elements modulo GF(2^8/0x11D). + // All inputs are valid. This could be implemented as a 256*256 lookup table. + private: static std::uint8_t reedSolomonMultiply(std::uint8_t x, std::uint8_t y); + + + // Can only be called immediately after a white run is added, and + // returns either 0, 1, or 2. A helper function for getPenaltyScore(). + private: int finderPenaltyCountPatterns(const std::array &runHistory) const; + + + // Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). + private: int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, std::array &runHistory) const; + + + // Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). + private: void finderPenaltyAddHistory(int currentRunLength, std::array &runHistory) const; + + + // Returns true iff the i'th bit of x is set to 1. + private: static bool getBit(long x, int i); + + + /*---- Constants and tables ----*/ + + // The minimum version number supported in the QR Code Model 2 standard. + public: static constexpr int MIN_VERSION = 1; + + // The maximum version number supported in the QR Code Model 2 standard. + public: static constexpr int MAX_VERSION = 40; + + + // For use in getPenaltyScore(), when evaluating which mask is best. + private: static const int PENALTY_N1; + private: static const int PENALTY_N2; + private: static const int PENALTY_N3; + private: static const int PENALTY_N4; + + + private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41]; + private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41]; + +}; + + + +/*---- Public exception class ----*/ + +/* + * Thrown when the supplied data does not fit any QR Code version. Ways to handle this exception include: + * - Decrease the error correction level if it was greater than Ecc::LOW. + * - If the encodeSegments() function was called with a maxVersion argument, then increase + * it if it was less than QrCode::MAX_VERSION. (This advice does not apply to the other + * factory functions because they search all versions up to QrCode::MAX_VERSION.) + * - Split the text data into better or optimal segments in order to reduce the number of bits required. + * - Change the text or binary data to be shorter. + * - Change the text to fit the character set of a particular segment mode (e.g. alphanumeric). + * - Propagate the error upward to the caller/user. + */ +class data_too_long : public std::length_error { + + public: explicit data_too_long(const std::string &msg); + +}; + + + +/* + * An appendable sequence of bits (0s and 1s). Mainly used by QrSegment. + */ +class BitBuffer final : public std::vector { + + /*---- Constructor ----*/ + + // Creates an empty bit buffer (length 0). + public: BitBuffer(); + + + + /*---- Method ----*/ + + // Appends the given number of low-order bits of the given value + // to this buffer. Requires 0 <= len <= 31 and val < 2^len. + public: void appendBits(std::uint32_t val, int len); + +}; + +} diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp index fc99e692a3..7abbad37bf 100644 --- a/src/blockchain_utilities/blockchain_export.cpp +++ b/src/blockchain_utilities/blockchain_export.cpp @@ -32,7 +32,7 @@ #include "cryptonote_core/tx_pool.h" #include "blockchain_db/blockchain_db.h" #include "blockchain_db/db_types.h" -#include "version.h" +//#include "version.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "bcutil" diff --git a/src/blockchain_utilities/blockchain_utilities.h b/src/blockchain_utilities/blockchain_utilities.h index f908ffddc8..2aba5caace 100644 --- a/src/blockchain_utilities/blockchain_utilities.h +++ b/src/blockchain_utilities/blockchain_utilities.h @@ -28,7 +28,7 @@ #pragma once -#include "version.h" +//#include "version.h" // bounds checking is done before writing to buffer, but buffer size diff --git a/src/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h index 0a59130582..794640270c 100644 --- a/src/blockchain_utilities/blocksdat_file.h +++ b/src/blockchain_utilities/blocksdat_file.h @@ -46,7 +46,7 @@ #include #include "common/command_line.h" -#include "version.h" +//#include "version.h" #include "blockchain_utilities.h" diff --git a/src/blockchain_utilities/bootstrap_file.h b/src/blockchain_utilities/bootstrap_file.h index 1a646b54b8..bb2334e915 100644 --- a/src/blockchain_utilities/bootstrap_file.h +++ b/src/blockchain_utilities/bootstrap_file.h @@ -44,7 +44,7 @@ #include #include "common/command_line.h" -#include "version.h" +//#include "version.h" #include "blockchain_utilities.h" diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index c20255f9ce..cab5efa2a1 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -33,6 +33,8 @@ #include #include +#define MONERO_VERSION_FULL "5.0.0 - Smile" +#define MONERO_RELEASE_NAME "Smile" #define CRYPTONOTE_DNS_TIMEOUT_MS 20000 #define CRYPTONOTE_MAX_BLOCK_NUMBER 500000000 diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 70f1cb68d1..42d5c2f31e 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -27,7 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cryptonote_config.h" -#include "version.h" +//#include "version.h" #include "daemon/command_server.h" #undef MONERO_DEFAULT_LOG_CATEGORY diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 683eaf4ff4..8b473f6b64 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -40,7 +40,7 @@ #include "daemon/protocol.h" #include "daemon/rpc.h" #include "daemon/command_server.h" -#include "version.h" +//#include "version.h" #include "syncobj.h" using namespace epee; diff --git a/src/daemon/executor.cpp b/src/daemon/executor.cpp index b767523158..3a32773335 100644 --- a/src/daemon/executor.cpp +++ b/src/daemon/executor.cpp @@ -32,7 +32,7 @@ #include "common/command_line.h" #include "cryptonote_config.h" -#include "version.h" +//#include "version.h" #include diff --git a/src/debug_utilities/cn_deserialize.cpp b/src/debug_utilities/cn_deserialize.cpp index f74e755dfa..410262b60b 100644 --- a/src/debug_utilities/cn_deserialize.cpp +++ b/src/debug_utilities/cn_deserialize.cpp @@ -30,7 +30,7 @@ #include "cryptonote_basic/tx_extra.h" #include "cryptonote_core/blockchain.h" #include "common/command_line.h" -#include "version.h" +//#include "version.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "debugtools.deserialize" diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 2c7c812a76..1eddcf569d 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -37,7 +37,7 @@ #include #include -#include "version.h" +//#include "version.h" #include "string_tools.h" #include "common/util.h" #include "common/dns_utils.h" diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index a23533530d..ecde691f32 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp @@ -35,7 +35,7 @@ #include "common/dns_utils.h" #include "common/util.h" #include "common/updates.h" -#include "version.h" +//#include "version.h" #include "net/http_client.h" #include diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index d1ef044d1f..61851629fb 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -34,7 +34,8 @@ #include "common/util.h" #include "misc_log_ex.h" #include "string_tools.h" -#include "version.h" +#include "cryptonote_config.h" +//#include "version.h" #if defined(WIN32) #include diff --git a/tests/core_proxy/core_proxy.cpp b/tests/core_proxy/core_proxy.cpp index 366937e1d8..dbebf7ba86 100644 --- a/tests/core_proxy/core_proxy.cpp +++ b/tests/core_proxy/core_proxy.cpp @@ -33,7 +33,7 @@ #include "include_base_utils.h" -#include "version.h" +//#include "version.h" using namespace epee; @@ -49,7 +49,7 @@ using namespace std; //#include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" #include "core_proxy.h" -#include "version.h" +//#include "version.h" #if defined(WIN32) #include From 1e3bef9f341ba5eb3052ccb3db233d5fa46f712e Mon Sep 17 00:00:00 2001 From: snider Date: Tue, 20 Jun 2023 22:44:09 +0100 Subject: [PATCH 39/50] removes compile dependencies. --- CMakeLists.txt | 22 +- .../Hunter/HunterCacheServers-passwords.cmake | 18 + cmake/Hunter/HunterCacheServers.cmake | 27 + cmake/Hunter/config.cmake | 1 + cmake/HunterGate.cmake | 537 ++++++++++++++++++ 5 files changed, 603 insertions(+), 2 deletions(-) create mode 100644 cmake/Hunter/HunterCacheServers-passwords.cmake create mode 100644 cmake/Hunter/HunterCacheServers.cmake create mode 100644 cmake/Hunter/config.cmake create mode 100644 cmake/HunterGate.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 859a345a8c..3d1a5b9a8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,20 @@ endif() cmake_minimum_required(VERSION 2.8.7) + +list(INSERT CMAKE_MODULE_PATH 0 + "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +include(HunterGate) +include(Hunter/HunterCacheServers) +set(HUNTER_CONFIGURATION_TYPES Release CACHE STRING "Build type of Hunter packages") +set(HUNTER_JOBS_NUMBER 6 CACHE STRING "Number of parallel builds used by Hunter") +HunterGate( + URL "https://github.com/cpp-pm/hunter/archive/v0.24.15.tar.gz" + SHA1 "8010d63d5ae611c564889d5fe12d3cb7a45703ac" + LOCAL +) + project(LetheanVPN) # shhhhh sleepy time errors, we know... add_definitions(-w) @@ -265,6 +279,7 @@ if (DATABASE STREQUAL "lmdb") set(BLOCKCHAIN_DB DB_LMDB) add_definitions("-DDEFAULT_DB_TYPE=\"lmdb\"") elseif (DATABASE STREQUAL "berkeleydb") + hunter_add_package(BerkeleyDB) find_package(BerkeleyDB) if(NOT BERKELEY_DB) die("Found BerkeleyDB includes, but could not find BerkeleyDB library. Please make sure you have installed libdb and libdb-dev / libdb++-dev or the equivalent.") @@ -306,6 +321,7 @@ elseif (ARM AND STATIC) set(DEFAULT_STACK_TRACE OFF) set(LIBUNWIND_LIBRARIES "") else() + hunter_add_package(Libunwind) find_package(Libunwind) if(LIBUNWIND_FOUND) set(DEFAULT_STACK_TRACE ON) @@ -332,7 +348,7 @@ if (APPLE AND NOT IOS) message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}") endif() endif() - +hunter_add_package(OpenSSL) find_package(OpenSSL REQUIRED) if(STATIC AND NOT IOS) if(UNIX) @@ -655,6 +671,7 @@ if(STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) endif() +hunter_add_package(Boost COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale log) find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options) set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES}) @@ -691,7 +708,8 @@ if(BUILD_GUI_DEPS) endif() if(USE_READLINE) - find_package(Readline) + hunter_add_package(readline) + find_package(readline) if(READLINE_FOUND AND GNU_READLINE_FOUND) add_definitions(-DHAVE_READLINE) include_directories(${Readline_INCLUDE_DIR}) diff --git a/cmake/Hunter/HunterCacheServers-passwords.cmake b/cmake/Hunter/HunterCacheServers-passwords.cmake new file mode 100644 index 0000000000..b4da3acf77 --- /dev/null +++ b/cmake/Hunter/HunterCacheServers-passwords.cmake @@ -0,0 +1,18 @@ +# Cable: CMake Bootstrap Library. +# Copyright 2018 Pawel Bylica. +# Licensed under the Apache License, Version 2.0. See the LICENSE file. + +# Hunter passwords file used by HunterCacheServers.cmake. +# Do not include directly. + +hunter_upload_password( + # REPO_OWNER + REPO = https://github.com/letheanVPN/hunter-cache + REPO_OWNER letheanVPN + REPO hunter-cache + + # USERNAME = https://github.com/snider + USERNAME snider + + # PASSWORD = GitHub token saved as a secure environment variable + PASSWORD "$ENV{HUNTER_CACHE_TOKEN}" +) diff --git a/cmake/Hunter/HunterCacheServers.cmake b/cmake/Hunter/HunterCacheServers.cmake new file mode 100644 index 0000000000..30504c93e7 --- /dev/null +++ b/cmake/Hunter/HunterCacheServers.cmake @@ -0,0 +1,27 @@ +# Cable: CMake Bootstrap Library. +# Copyright 2018 Pawel Bylica. +# Licensed under the Apache License, Version 2.0. See the LICENSE file. + +# This module, when included, sets default values for params related to +# Hunter cache servers, including upload options. + +# Default Hunter cache servers. +set(HUNTER_CACHE_SERVERS + "https://github.com/letheanVPN/hunter-cache" + CACHE STRING "Hunter cache servers") + +# Default path to Hunter passwords file containing information how to access +# Ethereum's cache server. +set(HUNTER_PASSWORDS_PATH + ${CMAKE_CURRENT_LIST_DIR}/HunterCacheServers-passwords.cmake + CACHE STRING "Hunter passwords file") + +# In CI builds upload the binaries if the HUNTER_CACHE_TOKEN was decrypted +# (only for branches and internal PRs). +if(NOT "$ENV{HUNTER_CACHE_TOKEN}" STREQUAL "") + set(run_upload YES) +else() + set(run_upload NO) +endif() +option(HUNTER_RUN_UPLOAD "Upload binaries to the Hunter cache server" ${run_upload}) +unset(run_upload) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake new file mode 100644 index 0000000000..4c63ba5ace --- /dev/null +++ b/cmake/Hunter/config.cmake @@ -0,0 +1 @@ +hunter_config(Boost VERSION 1.58.0 CMAKE_ARGS USE_CONFIG_FROM_BOOST=ON) diff --git a/cmake/HunterGate.cmake b/cmake/HunterGate.cmake new file mode 100644 index 0000000000..64ccde563b --- /dev/null +++ b/cmake/HunterGate.cmake @@ -0,0 +1,537 @@ +# Copyright (c) 2013-2019, Ruslan Baratov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This is a gate file to Hunter package manager. +# Include this file using `include` command and add package you need, example: +# +# cmake_minimum_required(VERSION 3.2) +# +# include("cmake/HunterGate.cmake") +# HunterGate( +# URL "https://github.com/path/to/hunter/archive.tar.gz" +# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" +# ) +# +# project(MyProject) +# +# hunter_add_package(Foo) +# hunter_add_package(Boo COMPONENTS Bar Baz) +# +# Projects: +# * https://github.com/hunter-packages/gate/ +# * https://github.com/ruslo/hunter + +option(HUNTER_ENABLED "Enable Hunter package manager support" ON) + +if(HUNTER_ENABLED) + if(CMAKE_VERSION VERSION_LESS "3.2") + message( + FATAL_ERROR + "At least CMake version 3.2 required for Hunter dependency management." + " Update CMake or set HUNTER_ENABLED to OFF." + ) + endif() +endif() + +include(CMakeParseArguments) # cmake_parse_arguments + +option(HUNTER_STATUS_PRINT "Print working status" ON) +option(HUNTER_STATUS_DEBUG "Print a lot info" OFF) +option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON) +set(HUNTER_ROOT "" CACHE FILEPATH "Override the HUNTER_ROOT.") + +set(HUNTER_ERROR_PAGE "https://hunter.readthedocs.io/en/latest/reference/errors") + +function(hunter_gate_status_print) + if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + message(STATUS "[hunter] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_status_debug) + if(HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + string(TIMESTAMP timestamp) + message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_error_page error_page) + message("------------------------------ ERROR ------------------------------") + message(" ${HUNTER_ERROR_PAGE}/${error_page}.html") + message("-------------------------------------------------------------------") + message("") + message(FATAL_ERROR "") +endfunction() + +function(hunter_gate_internal_error) + message("") + foreach(print_message ${ARGV}) + message("[hunter ** INTERNAL **] ${print_message}") + endforeach() + message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_error_page("error.internal") +endfunction() + +function(hunter_gate_fatal_error) + cmake_parse_arguments(hunter "" "ERROR_PAGE" "" "${ARGV}") + if("${hunter_ERROR_PAGE}" STREQUAL "") + hunter_gate_internal_error("Expected ERROR_PAGE") + endif() + message("") + foreach(x ${hunter_UNPARSED_ARGUMENTS}) + message("[hunter ** FATAL ERROR **] ${x}") + endforeach() + message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_error_page("${hunter_ERROR_PAGE}") +endfunction() + +function(hunter_gate_user_error) + hunter_gate_fatal_error(${ARGV} ERROR_PAGE "error.incorrect.input.data") +endfunction() + +function(hunter_gate_self root version sha1 result) + string(COMPARE EQUAL "${root}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("root is empty") + endif() + + string(COMPARE EQUAL "${version}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("version is empty") + endif() + + string(COMPARE EQUAL "${sha1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("sha1 is empty") + endif() + + string(SUBSTRING "${sha1}" 0 7 archive_id) + + if(EXISTS "${root}/cmake/Hunter") + set(hunter_self "${root}") + else() + set( + hunter_self + "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked" + ) + endif() + + set("${result}" "${hunter_self}" PARENT_SCOPE) +endfunction() + +# Set HUNTER_GATE_ROOT cmake variable to suitable value. +function(hunter_gate_detect_root) + # Check CMake variable + if(HUNTER_ROOT) + set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable") + return() + endif() + + # Check environment variable + if(DEFINED ENV{HUNTER_ROOT}) + set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by environment variable") + return() + endif() + + # Check HOME environment variable + if(DEFINED ENV{HOME}) + set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable") + return() + endif() + + # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only) + if(WIN32) + if(DEFINED ENV{SYSTEMDRIVE}) + set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using SYSTEMDRIVE environment variable" + ) + return() + endif() + + if(DEFINED ENV{USERPROFILE}) + set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using USERPROFILE environment variable" + ) + return() + endif() + endif() + + hunter_gate_fatal_error( + "Can't detect HUNTER_ROOT" + ERROR_PAGE "error.detect.hunter.root" + ) +endfunction() + +function(hunter_gate_download dir) + string( + COMPARE + NOTEQUAL + "$ENV{HUNTER_DISABLE_AUTOINSTALL}" + "" + disable_autoinstall + ) + if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL) + hunter_gate_fatal_error( + "Hunter not found in '${dir}'" + "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'" + "Settings:" + " HUNTER_ROOT: ${HUNTER_GATE_ROOT}" + " HUNTER_SHA1: ${HUNTER_GATE_SHA1}" + ERROR_PAGE "error.run.install" + ) + endif() + string(COMPARE EQUAL "${dir}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("Empty 'dir' argument") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_SHA1 empty") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_URL empty") + endif() + + set(done_location "${dir}/DONE") + set(sha1_location "${dir}/SHA1") + + set(build_dir "${dir}/Build") + set(cmakelists "${dir}/CMakeLists.txt") + + hunter_gate_status_debug("Locking directory: ${dir}") + file(LOCK "${dir}" DIRECTORY GUARD FUNCTION) + hunter_gate_status_debug("Lock done") + + if(EXISTS "${done_location}") + # while waiting for lock other instance can do all the job + hunter_gate_status_debug("File '${done_location}' found, skip install") + return() + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(MAKE_DIRECTORY "${build_dir}") # check directory permissions + + # Disabling languages speeds up a little bit, reduces noise in the output + # and avoids path too long windows error + file( + WRITE + "${cmakelists}" + "cmake_minimum_required(VERSION 3.2)\n" + "project(HunterDownload LANGUAGES NONE)\n" + "include(ExternalProject)\n" + "ExternalProject_Add(\n" + " Hunter\n" + " URL\n" + " \"${HUNTER_GATE_URL}\"\n" + " URL_HASH\n" + " SHA1=${HUNTER_GATE_SHA1}\n" + " DOWNLOAD_DIR\n" + " \"${dir}\"\n" + " TLS_VERIFY\n" + " ${HUNTER_TLS_VERIFY}\n" + " SOURCE_DIR\n" + " \"${dir}/Unpacked\"\n" + " CONFIGURE_COMMAND\n" + " \"\"\n" + " BUILD_COMMAND\n" + " \"\"\n" + " INSTALL_COMMAND\n" + " \"\"\n" + ")\n" + ) + + if(HUNTER_STATUS_DEBUG) + set(logging_params "") + else() + set(logging_params OUTPUT_QUIET) + endif() + + hunter_gate_status_debug("Run generate") + + # Need to add toolchain file too. + # Otherwise on Visual Studio + MDD this will fail with error: + # "Could not find an appropriate version of the Windows 10 SDK installed on this machine" + if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") + get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE) + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}") + else() + # 'toolchain_arg' can't be empty + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=") + endif() + + string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make) + if(no_make) + set(make_arg "") + else() + # Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM + set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") + endif() + + execute_process( + COMMAND + "${CMAKE_COMMAND}" + "-H${dir}" + "-B${build_dir}" + "-G${CMAKE_GENERATOR}" + "${toolchain_arg}" + ${make_arg} + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error( + "Configure project failed." + "To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}" + "In directory ${dir}" + ) + endif() + + hunter_gate_status_print( + "Initializing Hunter workspace (${HUNTER_GATE_SHA1})" + " ${HUNTER_GATE_URL}" + " -> ${dir}" + ) + execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error("Build project failed") + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}") + file(WRITE "${done_location}" "DONE") + + hunter_gate_status_debug("Finished") +endfunction() + +# Must be a macro so master file 'cmake/Hunter' can +# apply all variables easily just by 'include' command +# (otherwise PARENT_SCOPE magic needed) +macro(HunterGate) + if(HUNTER_GATE_DONE) + # variable HUNTER_GATE_DONE set explicitly for external project + # (see `hunter_download`) + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() + + # First HunterGate command will init Hunter, others will be ignored + get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET) + + if(NOT HUNTER_ENABLED) + # Empty function to avoid error "unknown function" + function(hunter_add_package) + endfunction() + + set( + _hunter_gate_disabled_mode_dir + "${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode" + ) + if(EXISTS "${_hunter_gate_disabled_mode_dir}") + hunter_gate_status_debug( + "Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}" + ) + list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}") + endif() + elseif(_hunter_gate_done) + hunter_gate_status_debug("Secondary HunterGate (use old settings)") + hunter_gate_self( + "${HUNTER_CACHED_ROOT}" + "${HUNTER_VERSION}" + "${HUNTER_SHA1}" + _hunter_self + ) + include("${_hunter_self}/cmake/Hunter") + else() + set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}") + + string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name) + if(_have_project_name) + hunter_gate_fatal_error( + "Please set HunterGate *before* 'project' command. " + "Detected project: ${PROJECT_NAME}" + ERROR_PAGE "error.huntergate.before.project" + ) + endif() + + cmake_parse_arguments( + HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV} + ) + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1) + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url) + string( + COMPARE + NOTEQUAL + "${HUNTER_GATE_UNPARSED_ARGUMENTS}" + "" + _have_unparsed + ) + string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global) + string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath) + + if(_have_unparsed) + hunter_gate_user_error( + "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}" + ) + endif() + if(_empty_sha1) + hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory") + endif() + if(_empty_url) + hunter_gate_user_error("URL suboption of HunterGate is mandatory") + endif() + if(_have_global) + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)") + endif() + endif() + if(HUNTER_GATE_LOCAL) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)") + endif() + endif() + if(_have_filepath) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)") + endif() + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)") + endif() + endif() + + hunter_gate_detect_root() # set HUNTER_GATE_ROOT + + # Beautify path, fix probable problems with windows path slashes + get_filename_component( + HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE + ) + hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}") + if(NOT HUNTER_ALLOW_SPACES_IN_PATH) + string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces) + if(NOT _contain_spaces EQUAL -1) + hunter_gate_fatal_error( + "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces." + "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error" + "(Use at your own risk!)" + ERROR_PAGE "error.spaces.in.hunter.root" + ) + endif() + endif() + + string( + REGEX + MATCH + "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*" + HUNTER_GATE_VERSION + "${HUNTER_GATE_URL}" + ) + string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty) + if(_is_empty) + set(HUNTER_GATE_VERSION "unknown") + endif() + + hunter_gate_self( + "${HUNTER_GATE_ROOT}" + "${HUNTER_GATE_VERSION}" + "${HUNTER_GATE_SHA1}" + _hunter_self + ) + + set(_master_location "${_hunter_self}/cmake/Hunter") + if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter") + # Hunter downloaded manually (e.g. by 'git clone') + set(_unused "xxxxxxxxxx") + set(HUNTER_GATE_SHA1 "${_unused}") + set(HUNTER_GATE_VERSION "${_unused}") + else() + get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE) + set(_done_location "${_archive_id_location}/DONE") + set(_sha1_location "${_archive_id_location}/SHA1") + + # Check Hunter already downloaded by HunterGate + if(NOT EXISTS "${_done_location}") + hunter_gate_download("${_archive_id_location}") + endif() + + if(NOT EXISTS "${_done_location}") + hunter_gate_internal_error("hunter_gate_download failed") + endif() + + if(NOT EXISTS "${_sha1_location}") + hunter_gate_internal_error("${_sha1_location} not found") + endif() + file(READ "${_sha1_location}" _sha1_value) + string(TOLOWER "${_sha1_value}" _sha1_value_lower) + string(TOLOWER "${HUNTER_GATE_SHA1}" _HUNTER_GATE_SHA1_lower) + string(COMPARE EQUAL "${_sha1_value_lower}" "${_HUNTER_GATE_SHA1_lower}" _is_equal) + if(NOT _is_equal) + hunter_gate_internal_error( + "Short SHA1 collision:" + " ${_sha1_value} (from ${_sha1_location})" + " ${HUNTER_GATE_SHA1} (HunterGate)" + ) + endif() + if(NOT EXISTS "${_master_location}") + hunter_gate_user_error( + "Master file not found:" + " ${_master_location}" + "try to update Hunter/HunterGate" + ) + endif() + endif() + include("${_master_location}") + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() +endmacro() From a78deeda5639ae375ee3a9452a9004f1571cd78e Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 10:51:39 +0100 Subject: [PATCH 40/50] Revert "removes compile dependencies." This reverts commit 1e3bef9f341ba5eb3052ccb3db233d5fa46f712e. --- CMakeLists.txt | 22 +- .../Hunter/HunterCacheServers-passwords.cmake | 18 - cmake/Hunter/HunterCacheServers.cmake | 27 - cmake/Hunter/config.cmake | 1 - cmake/HunterGate.cmake | 537 ------------------ 5 files changed, 2 insertions(+), 603 deletions(-) delete mode 100644 cmake/Hunter/HunterCacheServers-passwords.cmake delete mode 100644 cmake/Hunter/HunterCacheServers.cmake delete mode 100644 cmake/Hunter/config.cmake delete mode 100644 cmake/HunterGate.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d1a5b9a8b..859a345a8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,20 +33,6 @@ endif() cmake_minimum_required(VERSION 2.8.7) - -list(INSERT CMAKE_MODULE_PATH 0 - "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -include(HunterGate) -include(Hunter/HunterCacheServers) -set(HUNTER_CONFIGURATION_TYPES Release CACHE STRING "Build type of Hunter packages") -set(HUNTER_JOBS_NUMBER 6 CACHE STRING "Number of parallel builds used by Hunter") -HunterGate( - URL "https://github.com/cpp-pm/hunter/archive/v0.24.15.tar.gz" - SHA1 "8010d63d5ae611c564889d5fe12d3cb7a45703ac" - LOCAL -) - project(LetheanVPN) # shhhhh sleepy time errors, we know... add_definitions(-w) @@ -279,7 +265,6 @@ if (DATABASE STREQUAL "lmdb") set(BLOCKCHAIN_DB DB_LMDB) add_definitions("-DDEFAULT_DB_TYPE=\"lmdb\"") elseif (DATABASE STREQUAL "berkeleydb") - hunter_add_package(BerkeleyDB) find_package(BerkeleyDB) if(NOT BERKELEY_DB) die("Found BerkeleyDB includes, but could not find BerkeleyDB library. Please make sure you have installed libdb and libdb-dev / libdb++-dev or the equivalent.") @@ -321,7 +306,6 @@ elseif (ARM AND STATIC) set(DEFAULT_STACK_TRACE OFF) set(LIBUNWIND_LIBRARIES "") else() - hunter_add_package(Libunwind) find_package(Libunwind) if(LIBUNWIND_FOUND) set(DEFAULT_STACK_TRACE ON) @@ -348,7 +332,7 @@ if (APPLE AND NOT IOS) message(STATUS "Using OpenSSL found at ${OPENSSL_ROOT_DIR}") endif() endif() -hunter_add_package(OpenSSL) + find_package(OpenSSL REQUIRED) if(STATIC AND NOT IOS) if(UNIX) @@ -671,7 +655,6 @@ if(STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) endif() -hunter_add_package(Boost COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options locale log) find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options) set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES}) @@ -708,8 +691,7 @@ if(BUILD_GUI_DEPS) endif() if(USE_READLINE) - hunter_add_package(readline) - find_package(readline) + find_package(Readline) if(READLINE_FOUND AND GNU_READLINE_FOUND) add_definitions(-DHAVE_READLINE) include_directories(${Readline_INCLUDE_DIR}) diff --git a/cmake/Hunter/HunterCacheServers-passwords.cmake b/cmake/Hunter/HunterCacheServers-passwords.cmake deleted file mode 100644 index b4da3acf77..0000000000 --- a/cmake/Hunter/HunterCacheServers-passwords.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Cable: CMake Bootstrap Library. -# Copyright 2018 Pawel Bylica. -# Licensed under the Apache License, Version 2.0. See the LICENSE file. - -# Hunter passwords file used by HunterCacheServers.cmake. -# Do not include directly. - -hunter_upload_password( - # REPO_OWNER + REPO = https://github.com/letheanVPN/hunter-cache - REPO_OWNER letheanVPN - REPO hunter-cache - - # USERNAME = https://github.com/snider - USERNAME snider - - # PASSWORD = GitHub token saved as a secure environment variable - PASSWORD "$ENV{HUNTER_CACHE_TOKEN}" -) diff --git a/cmake/Hunter/HunterCacheServers.cmake b/cmake/Hunter/HunterCacheServers.cmake deleted file mode 100644 index 30504c93e7..0000000000 --- a/cmake/Hunter/HunterCacheServers.cmake +++ /dev/null @@ -1,27 +0,0 @@ -# Cable: CMake Bootstrap Library. -# Copyright 2018 Pawel Bylica. -# Licensed under the Apache License, Version 2.0. See the LICENSE file. - -# This module, when included, sets default values for params related to -# Hunter cache servers, including upload options. - -# Default Hunter cache servers. -set(HUNTER_CACHE_SERVERS - "https://github.com/letheanVPN/hunter-cache" - CACHE STRING "Hunter cache servers") - -# Default path to Hunter passwords file containing information how to access -# Ethereum's cache server. -set(HUNTER_PASSWORDS_PATH - ${CMAKE_CURRENT_LIST_DIR}/HunterCacheServers-passwords.cmake - CACHE STRING "Hunter passwords file") - -# In CI builds upload the binaries if the HUNTER_CACHE_TOKEN was decrypted -# (only for branches and internal PRs). -if(NOT "$ENV{HUNTER_CACHE_TOKEN}" STREQUAL "") - set(run_upload YES) -else() - set(run_upload NO) -endif() -option(HUNTER_RUN_UPLOAD "Upload binaries to the Hunter cache server" ${run_upload}) -unset(run_upload) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake deleted file mode 100644 index 4c63ba5ace..0000000000 --- a/cmake/Hunter/config.cmake +++ /dev/null @@ -1 +0,0 @@ -hunter_config(Boost VERSION 1.58.0 CMAKE_ARGS USE_CONFIG_FROM_BOOST=ON) diff --git a/cmake/HunterGate.cmake b/cmake/HunterGate.cmake deleted file mode 100644 index 64ccde563b..0000000000 --- a/cmake/HunterGate.cmake +++ /dev/null @@ -1,537 +0,0 @@ -# Copyright (c) 2013-2019, Ruslan Baratov -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# This is a gate file to Hunter package manager. -# Include this file using `include` command and add package you need, example: -# -# cmake_minimum_required(VERSION 3.2) -# -# include("cmake/HunterGate.cmake") -# HunterGate( -# URL "https://github.com/path/to/hunter/archive.tar.gz" -# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" -# ) -# -# project(MyProject) -# -# hunter_add_package(Foo) -# hunter_add_package(Boo COMPONENTS Bar Baz) -# -# Projects: -# * https://github.com/hunter-packages/gate/ -# * https://github.com/ruslo/hunter - -option(HUNTER_ENABLED "Enable Hunter package manager support" ON) - -if(HUNTER_ENABLED) - if(CMAKE_VERSION VERSION_LESS "3.2") - message( - FATAL_ERROR - "At least CMake version 3.2 required for Hunter dependency management." - " Update CMake or set HUNTER_ENABLED to OFF." - ) - endif() -endif() - -include(CMakeParseArguments) # cmake_parse_arguments - -option(HUNTER_STATUS_PRINT "Print working status" ON) -option(HUNTER_STATUS_DEBUG "Print a lot info" OFF) -option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON) -set(HUNTER_ROOT "" CACHE FILEPATH "Override the HUNTER_ROOT.") - -set(HUNTER_ERROR_PAGE "https://hunter.readthedocs.io/en/latest/reference/errors") - -function(hunter_gate_status_print) - if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) - foreach(print_message ${ARGV}) - message(STATUS "[hunter] ${print_message}") - endforeach() - endif() -endfunction() - -function(hunter_gate_status_debug) - if(HUNTER_STATUS_DEBUG) - foreach(print_message ${ARGV}) - string(TIMESTAMP timestamp) - message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}") - endforeach() - endif() -endfunction() - -function(hunter_gate_error_page error_page) - message("------------------------------ ERROR ------------------------------") - message(" ${HUNTER_ERROR_PAGE}/${error_page}.html") - message("-------------------------------------------------------------------") - message("") - message(FATAL_ERROR "") -endfunction() - -function(hunter_gate_internal_error) - message("") - foreach(print_message ${ARGV}) - message("[hunter ** INTERNAL **] ${print_message}") - endforeach() - message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") - message("") - hunter_gate_error_page("error.internal") -endfunction() - -function(hunter_gate_fatal_error) - cmake_parse_arguments(hunter "" "ERROR_PAGE" "" "${ARGV}") - if("${hunter_ERROR_PAGE}" STREQUAL "") - hunter_gate_internal_error("Expected ERROR_PAGE") - endif() - message("") - foreach(x ${hunter_UNPARSED_ARGUMENTS}) - message("[hunter ** FATAL ERROR **] ${x}") - endforeach() - message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") - message("") - hunter_gate_error_page("${hunter_ERROR_PAGE}") -endfunction() - -function(hunter_gate_user_error) - hunter_gate_fatal_error(${ARGV} ERROR_PAGE "error.incorrect.input.data") -endfunction() - -function(hunter_gate_self root version sha1 result) - string(COMPARE EQUAL "${root}" "" is_bad) - if(is_bad) - hunter_gate_internal_error("root is empty") - endif() - - string(COMPARE EQUAL "${version}" "" is_bad) - if(is_bad) - hunter_gate_internal_error("version is empty") - endif() - - string(COMPARE EQUAL "${sha1}" "" is_bad) - if(is_bad) - hunter_gate_internal_error("sha1 is empty") - endif() - - string(SUBSTRING "${sha1}" 0 7 archive_id) - - if(EXISTS "${root}/cmake/Hunter") - set(hunter_self "${root}") - else() - set( - hunter_self - "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked" - ) - endif() - - set("${result}" "${hunter_self}" PARENT_SCOPE) -endfunction() - -# Set HUNTER_GATE_ROOT cmake variable to suitable value. -function(hunter_gate_detect_root) - # Check CMake variable - if(HUNTER_ROOT) - set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE) - hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable") - return() - endif() - - # Check environment variable - if(DEFINED ENV{HUNTER_ROOT}) - set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE) - hunter_gate_status_debug("HUNTER_ROOT detected by environment variable") - return() - endif() - - # Check HOME environment variable - if(DEFINED ENV{HOME}) - set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE) - hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable") - return() - endif() - - # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only) - if(WIN32) - if(DEFINED ENV{SYSTEMDRIVE}) - set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE) - hunter_gate_status_debug( - "HUNTER_ROOT set using SYSTEMDRIVE environment variable" - ) - return() - endif() - - if(DEFINED ENV{USERPROFILE}) - set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE) - hunter_gate_status_debug( - "HUNTER_ROOT set using USERPROFILE environment variable" - ) - return() - endif() - endif() - - hunter_gate_fatal_error( - "Can't detect HUNTER_ROOT" - ERROR_PAGE "error.detect.hunter.root" - ) -endfunction() - -function(hunter_gate_download dir) - string( - COMPARE - NOTEQUAL - "$ENV{HUNTER_DISABLE_AUTOINSTALL}" - "" - disable_autoinstall - ) - if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL) - hunter_gate_fatal_error( - "Hunter not found in '${dir}'" - "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'" - "Settings:" - " HUNTER_ROOT: ${HUNTER_GATE_ROOT}" - " HUNTER_SHA1: ${HUNTER_GATE_SHA1}" - ERROR_PAGE "error.run.install" - ) - endif() - string(COMPARE EQUAL "${dir}" "" is_bad) - if(is_bad) - hunter_gate_internal_error("Empty 'dir' argument") - endif() - - string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad) - if(is_bad) - hunter_gate_internal_error("HUNTER_GATE_SHA1 empty") - endif() - - string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad) - if(is_bad) - hunter_gate_internal_error("HUNTER_GATE_URL empty") - endif() - - set(done_location "${dir}/DONE") - set(sha1_location "${dir}/SHA1") - - set(build_dir "${dir}/Build") - set(cmakelists "${dir}/CMakeLists.txt") - - hunter_gate_status_debug("Locking directory: ${dir}") - file(LOCK "${dir}" DIRECTORY GUARD FUNCTION) - hunter_gate_status_debug("Lock done") - - if(EXISTS "${done_location}") - # while waiting for lock other instance can do all the job - hunter_gate_status_debug("File '${done_location}' found, skip install") - return() - endif() - - file(REMOVE_RECURSE "${build_dir}") - file(REMOVE_RECURSE "${cmakelists}") - - file(MAKE_DIRECTORY "${build_dir}") # check directory permissions - - # Disabling languages speeds up a little bit, reduces noise in the output - # and avoids path too long windows error - file( - WRITE - "${cmakelists}" - "cmake_minimum_required(VERSION 3.2)\n" - "project(HunterDownload LANGUAGES NONE)\n" - "include(ExternalProject)\n" - "ExternalProject_Add(\n" - " Hunter\n" - " URL\n" - " \"${HUNTER_GATE_URL}\"\n" - " URL_HASH\n" - " SHA1=${HUNTER_GATE_SHA1}\n" - " DOWNLOAD_DIR\n" - " \"${dir}\"\n" - " TLS_VERIFY\n" - " ${HUNTER_TLS_VERIFY}\n" - " SOURCE_DIR\n" - " \"${dir}/Unpacked\"\n" - " CONFIGURE_COMMAND\n" - " \"\"\n" - " BUILD_COMMAND\n" - " \"\"\n" - " INSTALL_COMMAND\n" - " \"\"\n" - ")\n" - ) - - if(HUNTER_STATUS_DEBUG) - set(logging_params "") - else() - set(logging_params OUTPUT_QUIET) - endif() - - hunter_gate_status_debug("Run generate") - - # Need to add toolchain file too. - # Otherwise on Visual Studio + MDD this will fail with error: - # "Could not find an appropriate version of the Windows 10 SDK installed on this machine" - if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") - get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE) - set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}") - else() - # 'toolchain_arg' can't be empty - set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=") - endif() - - string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make) - if(no_make) - set(make_arg "") - else() - # Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM - set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") - endif() - - execute_process( - COMMAND - "${CMAKE_COMMAND}" - "-H${dir}" - "-B${build_dir}" - "-G${CMAKE_GENERATOR}" - "${toolchain_arg}" - ${make_arg} - WORKING_DIRECTORY "${dir}" - RESULT_VARIABLE download_result - ${logging_params} - ) - - if(NOT download_result EQUAL 0) - hunter_gate_internal_error( - "Configure project failed." - "To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}" - "In directory ${dir}" - ) - endif() - - hunter_gate_status_print( - "Initializing Hunter workspace (${HUNTER_GATE_SHA1})" - " ${HUNTER_GATE_URL}" - " -> ${dir}" - ) - execute_process( - COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" - WORKING_DIRECTORY "${dir}" - RESULT_VARIABLE download_result - ${logging_params} - ) - - if(NOT download_result EQUAL 0) - hunter_gate_internal_error("Build project failed") - endif() - - file(REMOVE_RECURSE "${build_dir}") - file(REMOVE_RECURSE "${cmakelists}") - - file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}") - file(WRITE "${done_location}" "DONE") - - hunter_gate_status_debug("Finished") -endfunction() - -# Must be a macro so master file 'cmake/Hunter' can -# apply all variables easily just by 'include' command -# (otherwise PARENT_SCOPE magic needed) -macro(HunterGate) - if(HUNTER_GATE_DONE) - # variable HUNTER_GATE_DONE set explicitly for external project - # (see `hunter_download`) - set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) - endif() - - # First HunterGate command will init Hunter, others will be ignored - get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET) - - if(NOT HUNTER_ENABLED) - # Empty function to avoid error "unknown function" - function(hunter_add_package) - endfunction() - - set( - _hunter_gate_disabled_mode_dir - "${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode" - ) - if(EXISTS "${_hunter_gate_disabled_mode_dir}") - hunter_gate_status_debug( - "Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}" - ) - list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}") - endif() - elseif(_hunter_gate_done) - hunter_gate_status_debug("Secondary HunterGate (use old settings)") - hunter_gate_self( - "${HUNTER_CACHED_ROOT}" - "${HUNTER_VERSION}" - "${HUNTER_SHA1}" - _hunter_self - ) - include("${_hunter_self}/cmake/Hunter") - else() - set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}") - - string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name) - if(_have_project_name) - hunter_gate_fatal_error( - "Please set HunterGate *before* 'project' command. " - "Detected project: ${PROJECT_NAME}" - ERROR_PAGE "error.huntergate.before.project" - ) - endif() - - cmake_parse_arguments( - HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV} - ) - - string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1) - string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url) - string( - COMPARE - NOTEQUAL - "${HUNTER_GATE_UNPARSED_ARGUMENTS}" - "" - _have_unparsed - ) - string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global) - string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath) - - if(_have_unparsed) - hunter_gate_user_error( - "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}" - ) - endif() - if(_empty_sha1) - hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory") - endif() - if(_empty_url) - hunter_gate_user_error("URL suboption of HunterGate is mandatory") - endif() - if(_have_global) - if(HUNTER_GATE_LOCAL) - hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)") - endif() - if(_have_filepath) - hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)") - endif() - endif() - if(HUNTER_GATE_LOCAL) - if(_have_global) - hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)") - endif() - if(_have_filepath) - hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)") - endif() - endif() - if(_have_filepath) - if(_have_global) - hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)") - endif() - if(HUNTER_GATE_LOCAL) - hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)") - endif() - endif() - - hunter_gate_detect_root() # set HUNTER_GATE_ROOT - - # Beautify path, fix probable problems with windows path slashes - get_filename_component( - HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE - ) - hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}") - if(NOT HUNTER_ALLOW_SPACES_IN_PATH) - string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces) - if(NOT _contain_spaces EQUAL -1) - hunter_gate_fatal_error( - "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces." - "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error" - "(Use at your own risk!)" - ERROR_PAGE "error.spaces.in.hunter.root" - ) - endif() - endif() - - string( - REGEX - MATCH - "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*" - HUNTER_GATE_VERSION - "${HUNTER_GATE_URL}" - ) - string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty) - if(_is_empty) - set(HUNTER_GATE_VERSION "unknown") - endif() - - hunter_gate_self( - "${HUNTER_GATE_ROOT}" - "${HUNTER_GATE_VERSION}" - "${HUNTER_GATE_SHA1}" - _hunter_self - ) - - set(_master_location "${_hunter_self}/cmake/Hunter") - if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter") - # Hunter downloaded manually (e.g. by 'git clone') - set(_unused "xxxxxxxxxx") - set(HUNTER_GATE_SHA1 "${_unused}") - set(HUNTER_GATE_VERSION "${_unused}") - else() - get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE) - set(_done_location "${_archive_id_location}/DONE") - set(_sha1_location "${_archive_id_location}/SHA1") - - # Check Hunter already downloaded by HunterGate - if(NOT EXISTS "${_done_location}") - hunter_gate_download("${_archive_id_location}") - endif() - - if(NOT EXISTS "${_done_location}") - hunter_gate_internal_error("hunter_gate_download failed") - endif() - - if(NOT EXISTS "${_sha1_location}") - hunter_gate_internal_error("${_sha1_location} not found") - endif() - file(READ "${_sha1_location}" _sha1_value) - string(TOLOWER "${_sha1_value}" _sha1_value_lower) - string(TOLOWER "${HUNTER_GATE_SHA1}" _HUNTER_GATE_SHA1_lower) - string(COMPARE EQUAL "${_sha1_value_lower}" "${_HUNTER_GATE_SHA1_lower}" _is_equal) - if(NOT _is_equal) - hunter_gate_internal_error( - "Short SHA1 collision:" - " ${_sha1_value} (from ${_sha1_location})" - " ${HUNTER_GATE_SHA1} (HunterGate)" - ) - endif() - if(NOT EXISTS "${_master_location}") - hunter_gate_user_error( - "Master file not found:" - " ${_master_location}" - "try to update Hunter/HunterGate" - ) - endif() - endif() - include("${_master_location}") - set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) - endif() -endmacro() From 6b02ac4285503d826b7f59e2707a8a4b20d6dbd6 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 11:37:23 +0100 Subject: [PATCH 41/50] adds swap wallet pub data --- src/cryptonote_core/swap_address.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptonote_core/swap_address.h b/src/cryptonote_core/swap_address.h index 55e6447a7c..bba1b34c8a 100644 --- a/src/cryptonote_core/swap_address.h +++ b/src/cryptonote_core/swap_address.h @@ -10,10 +10,10 @@ #if SWAP_ENABLED -#define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "" +#define SWAP_ADDRESS_ENCRYPTION_PUB_KEY "065d5f161cb39b2cf013183d34986f209bb7fc474f3633fa4cdc660296b4b433" #define SWAP_ADDRESS_ENCRYPTION_SEC_KEY "" -#define SWAP_WALLET "" +#define SWAP_WALLET "iz469K3VwJ2SxQ2rKgRen3Kb5LTy7UnnR9hFT7g7kigbX9BczkYWgNdJrFjsaiJfdXMJnGgDggtPDBQx8nf9xPMA2uhvbb77Q" #else From c3221427c2dde497a54c04c19d3e2a41978a7c89 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 11:37:57 +0100 Subject: [PATCH 42/50] use provided dev key from rpc command. --- src/rpc/core_rpc_server.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a5a4fe3930..cf0bcd87d3 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1855,10 +1855,8 @@ namespace cryptonote transaction blk_tx = bchain.get_db().get_tx(blk_tx_hash); if (is_swap_tx(blk_tx)) { - crypto::secret_key swap_encrypt_sec_key = AUTO_VAL_INIT(swap_encrypt_sec_key); - epee::string_tools::hex_to_pod(SWAP_ADDRESS_ENCRYPTION_SEC_KEY, swap_encrypt_sec_key); account_public_address swap_addr = AUTO_VAL_INIT(swap_addr); - cryptonote::get_swap_data_from_tx(blk_tx, swap_encrypt_sec_key, swap_addr); + cryptonote::get_swap_data_from_tx(blk_tx, swap_dev_key, swap_addr); // Check for tx public key crypto::public_key tx_pub = get_tx_pub_key_from_extra(blk_tx); From 56640e954b506c69a8af7e0bc8192b32f5c263a7 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 11:57:02 +0100 Subject: [PATCH 43/50] windows compile fix --- src/wallet/wallet2_api.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 8da8c62eb5..1419cd934e 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -35,6 +35,7 @@ #include #include #include +#include // Public interface for libwallet library namespace Monero { From 23dd1046a8289d83a946a273fcb393ba95f56f75 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 12:32:06 +0100 Subject: [PATCH 44/50] remove failing extra build --- .github/workflows/docker-wallet.yml | 52 ----------------------------- 1 file changed, 52 deletions(-) delete mode 100644 .github/workflows/docker-wallet.yml diff --git a/.github/workflows/docker-wallet.yml b/.github/workflows/docker-wallet.yml deleted file mode 100644 index 30ccbb7a5f..0000000000 --- a/.github/workflows/docker-wallet.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: lthn/wallet - -on: - push: - paths-ignore: - - 'docs/**' - - '**/*.md' - -jobs: - clear: - runs-on: ubuntu-latest - steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.9.1 - with: - access_token: ${{ github.token }} - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - uses: docker/setup-buildx-action@v2 - id: buildx - with: - install: true - - name: Docker meta - id: meta - uses: docker/metadata-action@v4 - with: - tags: | - # set latest tag for master branch - type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} - flavor: | - latest=auto - prefix= - suffix= - images: lthn/wallet - - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build - uses: docker/build-push-action@v2 - with: - context: . - file: utils/docker/wallet.Dockerfile - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - From fc784c70857db9e173abeed636f7c9ea31d46247 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 12:32:19 +0100 Subject: [PATCH 45/50] fixes macos compile --- .github/workflows/macos.yml | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 03112885a0..912a7300c8 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -50,30 +50,17 @@ jobs: run: | ${{env.CCACHE_SETTINGS}} make release-static-mac-x86_64 -j${HOMEBREW_MAKE_JOBS} - - name: Import Code-Signing Certificates for macOS - uses: Apple-Actions/import-codesign-certs@v1 - with: - p12-file-base64: ${{ secrets.MAC_DEVELOPER_CERT }} - p12-password: ${{ secrets.MAC_DEVELOPER_PASS }} - - run: make ci-release + - run: LETHEAN_RELEASE=lethean-cli-macos make zip-release - run: chmod +x build/packaged/lethean* - - name: Codesign - env: - APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} - run: | - cp LICENSE build/packaged/LICENSE - gon -log-level=info ./.github/gon-notarize.json - uses: actions/upload-artifact@v2 with: - name: macOS + name: lethean-cli-macos path: | - lethean-cli-macos.dmg - lethean-cli-macos.zip + lethean-cli-macos.tar - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: files: | - lethean-cli-macos.dmg - lethean-cli-macos.zip + lethean-cli-macos.tar From 8edaec69d012e476b8e9d2e5fdc8d492ce8f4920 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 12:32:33 +0100 Subject: [PATCH 46/50] renames build assets --- .github/workflows/linux.yml | 6 +++--- .github/workflows/windows.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 1635aceb1b..b4b4fbc58e 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -61,11 +61,11 @@ jobs: run: | ${{env.CCACHE_SETTINGS}} ${{env.BUILD_DEFAULT_LINUX}} - - run: LETHEAN_RELEASE=linux make zip-release + - run: LETHEAN_RELEASE=lethean-cli-linux make zip-release - uses: actions/upload-artifact@v2 with: name: linux.tar - path: ${{ github.workspace }}/build/linux.tar + path: ${{ github.workspace }}/build/lethean-cli-linux.tar - name: Get the version id: get_version if: startsWith(github.ref, 'refs/tags/') @@ -74,4 +74,4 @@ jobs: uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: - files: ${{ github.workspace }}/build/linux.tar + files: ${{ github.workspace }}/build/lethean-cli-linux.tar diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b471494eb6..674fdcd4b3 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -51,11 +51,11 @@ jobs: ${{env.CCACHE_SETTINGS}} make release-static-win64-boost make release-static-win64 -j2 - - run: LETHEAN_RELEASE=windows make zip-release + - run: LETHEAN_RELEASE=lethean-cli-windows make zip-release - uses: actions/upload-artifact@v2 with: name: windows.tar - path: ${{ github.workspace }}/build/windows.tar + path: ${{ github.workspace }}/build/lethean-cli-windows.tar - name: Get the version id: get_version if: startsWith(github.ref, 'refs/tags/') @@ -64,5 +64,5 @@ jobs: uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: - files: ${{ github.workspace }}/build/windows.tar + files: ${{ github.workspace }}/build/lethean-cli-windows.tar From 93404a4a8dd8ec9a870733d14089a90cfb3c179c Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 13:08:41 +0100 Subject: [PATCH 47/50] linux CI fix --- .github/workflows/linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index b4b4fbc58e..acc079ba8b 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -39,7 +39,7 @@ jobs: CCACHE_TEMPDIR: /tmp/.ccache-temp strategy: matrix: - os: [ubuntu-18.04] + os: [ubuntu-20.04] steps: - uses: actions/checkout@v1 with: From 9a6423b930b2426c3b2fde7e3e2bace047a8457a Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 13:16:16 +0100 Subject: [PATCH 48/50] linux CI fix --- .github/workflows/linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index acc079ba8b..c30d014c7f 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -22,7 +22,7 @@ on: env: REMOVE_BUNDLED_BOOST : rm -rf /usr/local/share/boost BUILD_DEFAULT_LINUX: | - make release-static-linux-x86_64 + make release-static-linux-x86_64-local-boost APT_INSTALL_LINUX: 'sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler ccache' APT_SET_CONF: | echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom From bcb9b1a5ec9fe188770ee9a3941eb5baa1df3fb3 Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 14:43:50 +0100 Subject: [PATCH 49/50] HF-8 1500000 - Friday, 11 August 2023 --- src/cryptonote_basic/cryptonote_basic.h | 2 +- src/cryptonote_basic/cryptonote_basic_impl.cpp | 2 +- src/cryptonote_basic/cryptonote_format_utils.cpp | 2 +- src/cryptonote_config.h | 1 + src/cryptonote_core/blockchain.cpp | 9 ++++++--- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 6c158e2557..a6733e4414 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -471,7 +471,7 @@ namespace cryptonote BEGIN_SERIALIZE() VARINT_FIELD(major_version) - if (major_version > BLOCK_MAJOR_VERSION_7) { + if (major_version > BLOCK_MAJOR_VERSION_8) { MERROR("Block version is too high " << (unsigned)major_version); return false; } diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 6b3979cf42..91dbf7e265 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -94,7 +94,7 @@ namespace cryptonote { const int emission_speed_factor = EMISSION_SPEED_FACTOR_PER_MINUTE - (target_minutes-1); const uint64_t orig_already_generated_coins = already_generated_coins; - if (version < BLOCK_MAJOR_VERSION_7) + if (version < BLOCK_MAJOR_VERSION_8) { if (orig_already_generated_coins >= UINT64_C(14992413379483553)) { already_generated_coins -= UINT64_C(14992032107906461); //premine minus the normal block 2 emission diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index cc8e262b69..2550bfa199 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -1045,7 +1045,7 @@ bool encrypt_swap_data_with_tx_secret_key(const crypto::secret_key& sk, uint8_t* blobdata bd = get_block_hashing_blob(b); // From BLOCK_MAJOR_VERSION_7 use Argon2 Chukwa v2 - if (b.major_version == BLOCK_MAJOR_VERSION_7){ + if (b.major_version >= BLOCK_MAJOR_VERSION_7){ crypto::chukwa_slow_hash_v2(bd.data(), bd.size(), res); return true; }else{ diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index cab5efa2a1..8fa008bbf7 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -53,6 +53,7 @@ #define BLOCK_MAJOR_VERSION_5 5 #define BLOCK_MAJOR_VERSION_6 6 #define BLOCK_MAJOR_VERSION_7 7 +#define BLOCK_MAJOR_VERSION_8 8 #define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 500 #define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 0 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 40a634dd86..5e8194907e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -102,7 +102,8 @@ static const struct { { 5, 296287, 0, 1540279084 }, // version 6 { 6, 391500, 0, 1552132800 }, - { 7, 1147126, 0, 1644148989 } + { 7, 1147126, 0, 1644148989 }, + { 8, 1500000, 0, 1691752271 } }; static const uint64_t mainnet_hard_fork_version_1_till = 50000; @@ -119,7 +120,8 @@ static const struct { { 4, 31, 0, 1518118888 }, { 5, 41, 0, 1539941268 }, { 6, 51, 0, 1551264860 }, - { 7, 71, 0, 1551264860 + 1000 } // Give it some time offset + { 7, 71, 0, 1551264860 + 1000 }, + { 8, 100, 0, 1551264860 + 9000 } // Give it some time offset }; static const uint64_t testnet_hard_fork_version_1_till = 10; @@ -3540,7 +3542,8 @@ bool Blockchain::update_next_cumulative_size_limit() get_current_hard_fork_version() == BLOCK_MAJOR_VERSION_4 || get_current_hard_fork_version() == BLOCK_MAJOR_VERSION_5 || get_current_hard_fork_version() == BLOCK_MAJOR_VERSION_6 || - get_current_hard_fork_version() == BLOCK_MAJOR_VERSION_7) + get_current_hard_fork_version() == BLOCK_MAJOR_VERSION_7|| + get_current_hard_fork_version() == BLOCK_MAJOR_VERSION_8) { //support LTHN max cumulative size limit change since 65k: large blocks every 5 blocks only //transaction size is also checked here. From cdb964248df2070545d67e486bfe6d3b992b5c1f Mon Sep 17 00:00:00 2001 From: snider Date: Fri, 14 Jul 2023 15:00:01 +0100 Subject: [PATCH 50/50] Checkpoint block 1480026 --- src/cryptonote_basic/checkpoints.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cryptonote_basic/checkpoints.cpp b/src/cryptonote_basic/checkpoints.cpp index f212839134..7e504a73e5 100644 --- a/src/cryptonote_basic/checkpoints.cpp +++ b/src/cryptonote_basic/checkpoints.cpp @@ -148,6 +148,7 @@ namespace cryptonote ADD_CHECKPOINT(76501, "be1ccf38a7a9f5509303f594c65192b4cb611e38507c0aca1810f38e55cfd0a1"); ADD_CHECKPOINT(100000, "52648fe3c9b2485c0823652d46c9900fa9593e10db75cac6ba3f13adc9d78ec8"); ADD_CHECKPOINT(110000, "099d1185f1fdd5f0023400bf5b868782fbd0c4d7362fc906e577af2415378dfd"); + ADD_CHECKPOINT(1480026, "d7c1998e4c3b722d84dbba5be0bbe068b5be2b0b6368c59d9765674c466c9b8e"); return true; }