From 42a752d12b96193d9adcb135cd79dfdcef8c8653 Mon Sep 17 00:00:00 2001 From: sowle Date: Thu, 30 Apr 2020 18:50:22 +0300 Subject: [PATCH] new addresses formats + unit tests --- src/currency_core/currency_basic.h | 26 ++--- .../currency_boost_serialization.h | 2 +- src/currency_core/currency_config.h | 5 +- src/currency_core/currency_format_utils.cpp | 86 ++++++++++++--- tests/unit_tests/base58.cpp | 100 ++++++++++++++++++ 5 files changed, 185 insertions(+), 34 deletions(-) diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index ab57f341..da8291dc 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -86,36 +86,26 @@ namespace currency #pragma pack(push, 1) struct account_public_address { - /*account_public_address() - {} - - account_public_address(const account_public_address_old& rhs) - : version(ACCOUNT_PUBLIC_ADDRESS_SERIZALIZATION_VER) - , flags(0) - , spend_public_key(rhs.spend_public_key) - , view_public_key(rhs.view_public_key) - {}*/ - - uint8_t version; - uint8_t flags; crypto::public_key spend_public_key; crypto::public_key view_public_key; + //uint8_t version; + uint8_t flags; DEFINE_SERIALIZATION_VERSION(ACCOUNT_PUBLIC_ADDRESS_SERIZALIZATION_VER) BEGIN_SERIALIZE_OBJECT() - VERSION_ENTRY(version) - FIELD(flags) FIELD(spend_public_key) FIELD(view_public_key) - if (version > ACCOUNT_PUBLIC_ADDRESS_SERIZALIZATION_VER) - return true; // backward compartibility + //VERSION_ENTRY(version) + FIELD(flags) + //if (version > ACCOUNT_PUBLIC_ADDRESS_SERIZALIZATION_VER) + // return true; // backward compartibility END_SERIALIZE() BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(version) // is it necessary? - KV_SERIALIZE(flags) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(spend_public_key) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(view_public_key) + //KV_SERIALIZE(version) // is it necessary? + KV_SERIALIZE(flags) END_KV_SERIALIZE_MAP() static account_public_address from_old(const account_public_address_old& rhs) diff --git a/src/currency_core/currency_boost_serialization.h b/src/currency_core/currency_boost_serialization.h index 5e39113c..0b6622e3 100644 --- a/src/currency_core/currency_boost_serialization.h +++ b/src/currency_core/currency_boost_serialization.h @@ -29,7 +29,7 @@ namespace boost template inline void serialize(Archive &a, currency::account_public_address &x, const boost::serialization::version_type ver) { - a & x.version; + //a & x.version; a & x.flags; a & x.spend_public_key; a & x.view_public_key; diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 95eee0db..019dd1bd 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -20,8 +20,11 @@ #define CURRENCY_MAX_BLOCK_NUMBER 500000000 #define CURRENCY_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used! #define CURRENCY_TX_MAX_ALLOWED_OUTS 2000 -#define CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX 197 // addresses start with 'Z' +#define CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX 0xc5 // addresses start with 'Zx' #define CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX 0x3678 // integrated addresses start with 'iZ' +#define CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX 0x36f8 // integrated addresses start with 'iZ' (new format) +#define CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX 0x98c8 // auditable addresses start with 'aZx' +#define CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX 0x8a49 // auditable integrated addresses start with 'aiZX' #define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10 #define CURRENT_TRANSACTION_VERSION 1 #define CURRENT_BLOCK_MAJOR_VERSION 1 diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 2c87a385..390d1b6d 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -2511,12 +2511,24 @@ namespace currency //----------------------------------------------------------------------- std::string get_account_address_as_str(const account_public_address& addr) { - return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); + if (addr.flags == 0) + return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr.to_old())); // classic Zano address + + if (addr.flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE) + return tools::base58::encode_addr(CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); // new format Zano address (auditable) + + return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); // new format Zano address (normal) } //----------------------------------------------------------------------- std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const payment_id_t& payment_id) { - return tools::base58::encode_addr(CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr) + payment_id); + if (addr.flags == 0) + return tools::base58::encode_addr(CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr.to_old()) + payment_id); // classic integrated Zano address + + if (addr.flags & ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE) + return tools::base58::encode_addr(CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr) + payment_id); // new format integrated Zano address (auditable) + + return tools::base58::encode_addr(CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX, t_serializable_object_to_blob(addr) + payment_id); // new format integrated Zano address (normal) } //----------------------------------------------------------------------- bool get_account_address_from_str(account_public_address& addr, const std::string& str) @@ -2527,7 +2539,7 @@ namespace currency //----------------------------------------------------------------------- bool get_account_address_and_payment_id_from_str(account_public_address& addr, payment_id_t& payment_id, const std::string& str) { - static const size_t addr_blob_size = sizeof(account_public_address); + payment_id.clear(); blobdata blob; uint64_t prefix; if (!tools::base58::decode_addr(str, prefix, blob)) @@ -2536,42 +2548,88 @@ namespace currency return false; } - if (blob.size() < addr_blob_size) + if (blob.size() < sizeof(account_public_address_old)) { - LOG_PRINT_L1("Address " << str << " has invalid format: blob size is " << blob.size() << " which is less, than expected " << addr_blob_size); + LOG_PRINT_L1("Address " << str << " has invalid format: blob size is " << blob.size() << " which is less, than expected " << sizeof(account_public_address_old)); return false; } - if (blob.size() > addr_blob_size + BC_PAYMENT_ID_SERVICE_SIZE_MAX) + if (blob.size() > sizeof(account_public_address) + BC_PAYMENT_ID_SERVICE_SIZE_MAX) { - LOG_PRINT_L1("Address " << str << " has invalid format: blob size is " << blob.size() << " which is more, than allowed " << addr_blob_size + BC_PAYMENT_ID_SERVICE_SIZE_MAX); + LOG_PRINT_L1("Address " << str << " has invalid format: blob size is " << blob.size() << " which is more, than allowed " << sizeof(account_public_address) + BC_PAYMENT_ID_SERVICE_SIZE_MAX); return false; } + bool parse_as_old_format = false; + if (prefix == CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX) { - // nothing + // normal address + if (blob.size() == sizeof(account_public_address_old)) + { + parse_as_old_format = true; + } + else if (blob.size() == sizeof(account_public_address)) + { + parse_as_old_format = false; + } + else + { + LOG_PRINT_L1("Account public address cannot be parsed from \"" << str << "\", incorrect size"); + return false; + } + } + else if (prefix == CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX) + { + // auditable, parse as new format + parse_as_old_format = false; } else if (prefix == CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX) { - payment_id = blob.substr(addr_blob_size); - blob = blob.substr(0, addr_blob_size); + payment_id = blob.substr(sizeof(account_public_address_old)); + blob = blob.substr(0, sizeof(account_public_address_old)); + parse_as_old_format = true; + } + else if (prefix == CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX || prefix == CURRENCY_PUBLIC_INTEG_ADDRESS_V2_BASE58_PREFIX) + { + payment_id = blob.substr(sizeof(account_public_address)); + blob = blob.substr(0, sizeof(account_public_address)); + parse_as_old_format = false; } else { - LOG_PRINT_L1("Address " << str << " has wrong prefix " << prefix << ", expected " << CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX << " or " << CURRENCY_PUBLIC_INTEG_ADDRESS_BASE58_PREFIX); + LOG_PRINT_L1("Address " << str << " has wrong prefix " << prefix); return false; } - if (!::serialization::parse_binary(blob, addr)) + if (parse_as_old_format) { - LOG_PRINT_L1("Account public address keys can't be parsed for address \"" << str << "\""); + account_public_address_old addr_old = AUTO_VAL_INIT(addr_old); + if (!::serialization::parse_binary(blob, addr_old)) + { + LOG_PRINT_L1("Account public address (old) cannot be parsed from \"" << str << "\""); + return false; + } + addr = account_public_address::from_old(addr_old); + } + else + { + if (!::serialization::parse_binary(blob, addr)) + { + LOG_PRINT_L1("Account public address cannot be parsed from \"" << str << "\""); + return false; + } + } + + if (payment_id.size() > BC_PAYMENT_ID_SERVICE_SIZE_MAX) + { + LOG_PRINT_L1("Failed to parse address from \"" << str << "\": payment id size exceeded: " << payment_id.size()); return false; } if (!crypto::check_key(addr.spend_public_key) || !crypto::check_key(addr.view_public_key)) { - LOG_PRINT_L1("Failed to validate address keys for address \"" << str << "\""); + LOG_PRINT_L1("Failed to validate address keys for public address \"" << str << "\""); return false; } diff --git a/tests/unit_tests/base58.cpp b/tests/unit_tests/base58.cpp index d55c9a74..33e209fc 100644 --- a/tests/unit_tests/base58.cpp +++ b/tests/unit_tests/base58.cpp @@ -551,3 +551,103 @@ TEST(integ_address, payment_id_sizes) ASSERT_NE(addr2, addr); ASSERT_NE(integrated_payment_id, payment_id); } + + +struct addr_entry_t +{ + std::string address; + std::string view_pub_key; + std::string spend_pub_key; + std::string payment_id_hex; + uint8_t flags; +}; + +addr_entry_t addr_entries[] = + { + { + // classic normal address + "ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH", // address + "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key + "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key + "", // payment_id_hex + 0 // flags + }, + { + // classic integrated address + "iZ2Zi6RmTWwcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTqEsjvJoco1aLSZXS6T", // address + "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key + "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key + "87440d0b9acc42f1", // payment_id_hex + 0 // flags + }, + { + // new format normal address with custom flags + "ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3APrDvRoL5C", // address + "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key + "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key + "", // payment_id_hex + 0xfe // flags + }, + { + // new format integrated address with custom flags + "iZ4mBxubNfqcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTrG7nU5rRCWmcozLaMoY95sAbo6", // address + "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key + "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key + "3ba0527bcfb1fa93630d28eed6", // payment_id + 0xfe // flags + }, + { + // normal auditable address + "aZxb9Et6FhP9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJMEmqQFn", // address + "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key + "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key + "", // payment_id + ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE // flags + }, + { + // auditable integrated address + "aiZXDondHWu9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJM9xJH8EbjuRiMJgFmPRATsEV9", // address + "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key + "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key + "3ba0527bcfb1fa93630d28eed6", // payment_id + ACCOUNT_PUBLIC_ADDRESS_FLAG_AUDITABLE // flags + } + }; + +void check_add_entry(const addr_entry_t& ae) +{ + std::string payment_id, payment_id_hex; + currency::account_public_address addr = AUTO_VAL_INIT(addr); + + ASSERT_TRUE(currency::get_account_address_and_payment_id_from_str(addr, payment_id, ae.address)); + payment_id_hex = epee::string_tools::buff_to_hex_nodelimer(payment_id); + + ASSERT_EQ(ae.flags, addr.flags); + ASSERT_EQ(ae.payment_id_hex, payment_id_hex); + ASSERT_EQ(ae.view_pub_key, epee::string_tools::pod_to_hex(addr.view_public_key)); + ASSERT_EQ(ae.spend_pub_key, epee::string_tools::pod_to_hex(addr.spend_public_key)); +} + +TEST(auditable_addresses, basic) +{ + /* + currency::account_keys keys = AUTO_VAL_INIT(keys); + epee::string_tools::parse_tpod_from_hex_string("248b019d145d485576ecb0367d92b5a12e8aa15084b59ef15014a7a22d1f3b0c", keys.spend_secret_key); + dependent_key(keys.spend_secret_key, keys.view_secret_key); + crypto::secret_key_to_public_key(keys.view_secret_key, keys.account_address.view_public_key); + crypto::secret_key_to_public_key(keys.spend_secret_key, keys.account_address.spend_public_key); + + keys.account_address.flags = 0xfe; + + std::string payment_id; + epee::string_tools::parse_hexstr_to_binbuff(std::string("3ba0527bcfb1fa93630d28eed6"), payment_id); + + std::cout << currency::get_account_address_as_str(keys.account_address) << " " << epee::string_tools::pod_to_hex(keys.account_address.view_public_key) << " " << epee::string_tools::pod_to_hex(keys.account_address.spend_public_key) << ENDL; + std::cout << currency::get_account_address_and_payment_id_as_str(keys.account_address, payment_id) << " " << epee::string_tools::pod_to_hex(keys.account_address.view_public_key) << " " << epee::string_tools::pod_to_hex(keys.account_address.spend_public_key) << ENDL; + */ + + + for (size_t i = 0; i < sizeof addr_entries / sizeof addr_entries[0]; ++i) + check_add_entry(addr_entries[i]); + +}