diff --git a/src/monero_address_utils.cpp b/src/monero_address_utils.cpp index 19dbbc8..07b5ee3 100644 --- a/src/monero_address_utils.cpp +++ b/src/monero_address_utils.cpp @@ -42,14 +42,14 @@ using namespace epee; #include "monero_paymentID_utils.hpp" // // Accessors - Implementations -DecodedAddress_RetVals address_utils::decodedAddress(const string &addressString, bool isTestnet) +DecodedAddress_RetVals address_utils::decodedAddress(const string &addressString, cryptonote::network_type nettype) { DecodedAddress_RetVals retVals; // init // cryptonote::address_parse_info info; bool didSucceed = cryptonote::get_account_address_from_str( info, - isTestnet ? cryptonote::TESTNET : cryptonote::MAINNET, + nettype, addressString ); if (didSucceed == false) { @@ -72,20 +72,20 @@ DecodedAddress_RetVals address_utils::decodedAddress(const string &addressString } return retVals; } -bool address_utils::isSubAddress(const string &addressString, bool isTestnet) +bool address_utils::isSubAddress(const string &addressString, cryptonote::network_type nettype) { - DecodedAddress_RetVals retVals = decodedAddress(addressString, isTestnet); + DecodedAddress_RetVals retVals = decodedAddress(addressString, nettype); // return retVals.isSubaddress; } -bool address_utils::isIntegratedAddress(const string &addressString, bool isTestnet) +bool address_utils::isIntegratedAddress(const string &addressString, cryptonote::network_type nettype) { - DecodedAddress_RetVals retVals = decodedAddress(addressString, isTestnet); + DecodedAddress_RetVals retVals = decodedAddress(addressString, nettype); // return retVals.paymentID_string != boost::none; } // -optional address_utils::new_integratedAddrFromStdAddr(const string &std_address_string, const string &short_paymentID_string, bool isTestnet) +optional address_utils::new_integratedAddrFromStdAddr(const string &std_address_string, const string &short_paymentID_string, cryptonote::network_type nettype) { crypto::hash8 payment_id_short; bool didParse = monero_paymentID_utils::parse_short_payment_id(short_paymentID_string, payment_id_short); @@ -95,7 +95,7 @@ optional address_utils::new_integratedAddrFromStdAddr(const string &std_ cryptonote::address_parse_info info; bool didSucceed = cryptonote::get_account_address_from_str( info, - isTestnet ? cryptonote::TESTNET : cryptonote::MAINNET, + nettype, std_address_string ); if (didSucceed == false) { @@ -111,7 +111,7 @@ optional address_utils::new_integratedAddrFromStdAddr(const string &std_ return none; // that was not a std_address! } std::string int_address_string = cryptonote::get_account_integrated_address_as_str( - isTestnet ? cryptonote::TESTNET : cryptonote::MAINNET, + nettype, info.address, payment_id_short ); diff --git a/src/monero_address_utils.hpp b/src/monero_address_utils.hpp index fa96c45..45c8469 100644 --- a/src/monero_address_utils.hpp +++ b/src/monero_address_utils.hpp @@ -34,6 +34,7 @@ using namespace std; using namespace boost; // +#include "cryptonote_config.h" #include "tools__ret_vals.hpp" // namespace monero @@ -50,10 +51,10 @@ namespace monero // // TODO: migrate these methods to use nettype // - DecodedAddress_RetVals decodedAddress(const string &addressString, bool isTestnet); - bool isSubAddress(const string &addressString, bool isTestnet); - bool isIntegratedAddress(const string &addressString, bool isTestnet); + DecodedAddress_RetVals decodedAddress(const string &addressString, cryptonote::network_type nettype); + bool isSubAddress(const string &addressString, cryptonote::network_type nettype); + bool isIntegratedAddress(const string &addressString, cryptonote::network_type nettype); // - optional new_integratedAddrFromStdAddr(const string &std_address_string, const string &short_paymentID, bool isTestnet); + optional new_integratedAddrFromStdAddr(const string &std_address_string, const string &short_paymentID, cryptonote::network_type nettype); } } diff --git a/src/serial_bridge_index.cpp b/src/serial_bridge_index.cpp index b1467f7..ae67885 100644 --- a/src/serial_bridge_index.cpp +++ b/src/serial_bridge_index.cpp @@ -38,6 +38,7 @@ // #include "monero_fork_rules.hpp" #include "monero_transfer_utils.hpp" +#include "monero_address_utils.hpp" // TODO: split this/these out into a different namespaces or file so this file can scale (leave file for shared utils) #include "wallet_errors.h" // // @@ -49,7 +50,7 @@ using namespace monero_fork_rules; // using namespace serial_bridge; // -network_type nettype_from_string(string nettype_string) +network_type serial_bridge::nettype_from_string(const string &nettype_string) { // TODO: possibly move this to network_type declaration if (nettype_string == "MAINNET") { return MAINNET; @@ -65,6 +66,40 @@ network_type nettype_from_string(string nettype_string) THROW_WALLET_EXCEPTION_IF(false, error::wallet_internal_error, "Unrecognized nettype_string") return UNDEFINED; } +string serial_bridge::string_from_nettype(network_type nettype) +{ + switch (nettype) { + case MAINNET: + return "MAINNET"; + case TESTNET: + return "TESTNET"; + case STAGENET: + return "STAGENET"; + case FAKECHAIN: + return "FAKECHAIN"; + case UNDEFINED: + return "UNDEFINED"; + default: + THROW_WALLET_EXCEPTION_IF(false, error::wallet_internal_error, "Unrecognized nettype for string conversion") + return "UNDEFINED"; + } +} +// +// Shared - Parsing - Args +bool parsed_json_root(const string &args_string, boost::property_tree::ptree &json_root) +{ + std::stringstream ss; + ss << args_string; + try { + boost::property_tree::read_json(ss, json_root); + } catch (std::exception const& e) { + THROW_WALLET_EXCEPTION_IF(false, error::wallet_internal_error, "Invalid JSON"); + return false; + } + return true; +} +// +// Shared - Factories - Return values string error_ret_json_from_message(string err_msg) { boost::property_tree::ptree root; @@ -84,16 +119,90 @@ string error_ret_json_from_code(int code) return ss.str(); } // -string serial_bridge::create_transaction(std::string args_string) +string serial_bridge::decode_address(const string &args_string) { - std::stringstream ss; - ss << args_string; boost::property_tree::ptree json_root; - try { - boost::property_tree::read_json(ss, json_root); - } catch (std::exception const& e) { - THROW_WALLET_EXCEPTION_IF(false, error::wallet_internal_error, "Invalid JSON"); - return error_ret_json_from_message("Invalid JSON"); // TODO: centralize + if (!parsed_json_root(args_string, json_root)) { + // it will already have thrown an exception + return error_ret_json_from_message("Invalid JSON"); + } + network_type nettype = nettype_from_string(json_root.get("nettype_string")); + auto retVals = monero::address_utils::decodedAddress(json_root.get("address"), nettype); + if (retVals.did_error) { + return error_ret_json_from_message(*(retVals.err_string)); + } + boost::property_tree::ptree root; + root.put(ret_json_key__decode_address__isSubaddress(), retVals.isSubaddress); + root.put(ret_json_key__decode_address__pub_viewKey_string(), std::move(*(retVals.pub_viewKey_string))); + root.put(ret_json_key__decode_address__pub_spendKey_string(), std::move(*(retVals.pub_spendKey_string))); + if (retVals.paymentID_string != none) { + root.put(ret_json_key__decode_address__paymentID_string(), std::move(*(retVals.paymentID_string))); + } + stringstream ret_ss; + boost::property_tree::write_json(ret_ss, root); + // + return ret_ss.str(); +} +string serial_bridge::is_subaddress(const string &args_string) +{ + +} +string serial_bridge::is_integrated_address(const string &args_string) +{ + +} +string serial_bridge::new_integrated_address(const string &args_string) +{ + // standard addr + short pid +} +string serial_bridge::new_fake_address_for_rct_tx(const string &args_string) +{ + // TODO: probably take random scalar as an argument +} +string serial_bridge::new_payment_id(const string &args_string) +{ + +} +// +string serial_bridge::newly_created_wallet(const string &args_string) +{ + +} +string serial_bridge::mnemonic_from_seed(const string &args_string) +{ + +} +string serial_bridge::seed_and_keys_from_mnemonic(const string &args_string) +{ + +} +string serial_bridge::verified_components_for_login(const string &args_string) +{ + +} +// +string serial_bridge::estimate_rct_size(const string &args_string) +{ + +} +string serial_bridge::calculate_fee(const string &args_string) +{ + +} +// +string serial_bridge::generate_key_image(const string &args_string) +{ + +} +// +// +// TODO: probably take transaction secret key as an argument so we don't have to worry about randomness there +string serial_bridge::create_transaction(const string &args_string) +{ + boost::property_tree::ptree json_root; + if (!parsed_json_root(args_string, json_root)) { + // it will already have thrown an exception + return error_ret_json_from_message("Invalid JSON"); } network_type nettype = nettype_from_string(json_root.get("nettype_string")); // diff --git a/src/serial_bridge_index.hpp b/src/serial_bridge_index.hpp index 981b30a..93a2b32 100644 --- a/src/serial_bridge_index.hpp +++ b/src/serial_bridge_index.hpp @@ -34,19 +34,50 @@ #define serial_bridge_index_hpp // #include +#include "cryptonote_config.h" // namespace serial_bridge { using namespace std; + using namespace cryptonote; // // Bridging Functions - these take and return JSON strings - string create_transaction(string args_string); + string create_transaction(const string &args_string); // TODO: probably expose tx key as arg + // + string decode_address(const string &args_string); + string is_subaddress(const string &args_string); + string is_integrated_address(const string &args_string); + // + string new_integrated_address(const string &args_string); + string new_fake_address_for_rct_tx(const string &args_string); // TODO: probably expose random scalar as arg + string new_payment_id(const string &args_string); + // + string newly_created_wallet(const string &args_string); // TODO: probably expose random scalar as arg + string mnemonic_from_seed(const string &args_string); + string seed_and_keys_from_mnemonic(const string &args_string); + string verified_components_for_login(const string &args_string); + // + string estimate_rct_size(const string &args_string); + string calculate_fee(const string &args_string); + // TODO: possibly add EstimatedTransaction_networkFee analog + // + string generate_key_image(const string &args_string); + // + // JSON values + network_type nettype_from_string(const string &nettype_string); + string string_from_nettype(network_type nettype); // // JSON keys - Ret vals - static inline string ret_json_key__any__err_msg() { return "err_msg"; } - static inline string ret_json_key__any__err_code() { return "err_code"; } + static inline string ret_json_key__any__err_msg() { return "err_msg"; } // optional + static inline string ret_json_key__any__err_code() { return "err_code"; } // optional + // - - create_transaction static inline string ret_json_key__create_transaction__serialized_signed_tx() { return "serialized_signed_tx"; } static inline string ret_json_key__create_transaction__tx_hash() { return "tx_hash"; } + // - - decode_address + static inline string ret_json_key__decode_address__pub_viewKey_string() { return "pub_viewKey_string"; } + static inline string ret_json_key__decode_address__pub_spendKey_string() { return "pub_spendKey_string"; } + static inline string ret_json_key__decode_address__paymentID_string() { return "paymentID_string"; } // optional + static inline string ret_json_key__decode_address__isSubaddress() { return "isSubaddress"; } // JSON keys - Args // TODO: // static inline string args_json_key__ diff --git a/test/test_all.cpp b/test/test_all.cpp index 3aa118c..b380653 100644 --- a/test/test_all.cpp +++ b/test/test_all.cpp @@ -53,7 +53,7 @@ using namespace boost; BOOST_AUTO_TEST_CASE(decodeAddress) { string address = "43zxvpcj5Xv9SEkNXbMCG7LPQStHMpFCQCmkmR4u5nzjWwq5Xkv5VmGgYEsHXg4ja2FGRD5wMWbBVMijDTqmmVqm93wHGkg"; - auto result = monero::address_utils::decodedAddress(address, false); + auto result = monero::address_utils::decodedAddress(address, cryptonote::MAINNET); if (result.err_string) { std::cout << *result.err_string << endl; BOOST_REQUIRE(!result.err_string); @@ -122,8 +122,8 @@ BOOST_AUTO_TEST_CASE(transfers__create) cryptonote::network_type nettype = cryptonote::MAINNET; string from_addressString = "43zxvpcj5Xv9SEkNXbMCG7LPQStHMpFCQCmkmR4u5nzjWwq5Xkv5VmGgYEsHXg4ja2FGRD5wMWbBVMijDTqmmVqm93wHGkg"; - string sec_viewKey_string = "..."; - string sec_spendKey_string = "..."; + string sec_viewKey_string = "7bea1907940afdd480eff7c4bcadb478a0fbb626df9e3ed74ae801e18f53e104"; + string sec_spendKey_string = "4e6d43cd03812b803c6f3206689f5fcc910005fc7e91d50d79b0776dbefcd803"; cryptonote::address_parse_info from_addr_info; BOOST_REQUIRE(cryptonote::get_account_address_from_str(from_addr_info, nettype, from_addressString)); @@ -332,10 +332,10 @@ BOOST_AUTO_TEST_CASE(bridged__transfers__create) string amount_string = "10000000000"; // boost::property_tree::ptree root; - root.put("nettype_string", "MAINNET"); // TODO: specify this by constant and transform fn + root.put("nettype_string", string_from_nettype(MAINNET)); // TODO: specify this by constant and transform fn root.put("from_address_string", from_address_string); - root.put("sec_viewKey_string", "..."); - root.put("sec_spendKey_string", "..."); + root.put("sec_viewKey_string", "7bea1907940afdd480eff7c4bcadb478a0fbb626df9e3ed74ae801e18f53e104"); + root.put("sec_spendKey_string", "4e6d43cd03812b803c6f3206689f5fcc910005fc7e91d50d79b0776dbefcd803"); root.put("to_address_string", to_address_string); root.put("payment_id_string", "b79f8efc81f58f67"); root.put("amount", amount_string); @@ -451,3 +451,40 @@ BOOST_AUTO_TEST_CASE(bridged__transfers__create) BOOST_REQUIRE((*tx_hash).size() > 0); cout << "bridged: tx_hash: " << *tx_hash << endl; } +// +BOOST_AUTO_TEST_CASE(bridged__decode_address) +{ + using namespace serial_bridge; + // + boost::property_tree::ptree root; + root.put("nettype_string", string_from_nettype(MAINNET)); // TODO: specify this by constant and transform fn + root.put("address", "4L6Gcy9TAHqPVPMnqa5cPtJK25tr7maE7LrJe67vzumiCtWwjDBvYnHZr18wFexJpih71Mxsjv8b7EpQftpB9NjPaL41VrjstLM5WevLZx"); + // + stringstream args_ss; + boost::property_tree::write_json(args_ss, root); + auto ret_string = serial_bridge::decode_address(args_ss.str()); + stringstream ret_stream; + ret_stream << ret_string; + boost::property_tree::ptree ret_tree; + boost::property_tree::read_json(ret_stream, ret_tree); + optional err_string = ret_tree.get_optional(ret_json_key__any__err_msg()); + if (err_string != none) { + BOOST_REQUIRE_MESSAGE(false, *err_string); + } + optional pub_viewKey_string = ret_tree.get_optional(ret_json_key__decode_address__pub_viewKey_string()); + BOOST_REQUIRE(pub_viewKey_string != none); + BOOST_REQUIRE((*pub_viewKey_string).size() > 0); + cout << "bridged: pub_viewKey_string: " << *pub_viewKey_string << endl; + optional pub_spendKey_string = ret_tree.get_optional(ret_json_key__decode_address__pub_spendKey_string()); + BOOST_REQUIRE(pub_spendKey_string != none); + BOOST_REQUIRE((*pub_spendKey_string).size() > 0); + cout << "bridged: pub_viewKey_string: " << *pub_spendKey_string << endl; + optional paymentID_string = ret_tree.get_optional(ret_json_key__decode_address__paymentID_string()); + BOOST_REQUIRE(paymentID_string != none); + BOOST_REQUIRE((*paymentID_string).size() > 0); + cout << "bridged: paymentID_string: " << *paymentID_string << endl; + optional isSubaddress = ret_tree.get_optional(ret_json_key__decode_address__isSubaddress()); + BOOST_REQUIRE(isSubaddress != none); + BOOST_REQUIRE(*isSubaddress == false); + cout << "bridged: isSubaddress: " << *isSubaddress << endl; +}