added address_and_keys_from_seed (renamed from create_address in old mymonero-core-js), generate_key_derivation, derive_public_key, derive_subaddress_public_key, and decodeRct

pull/29/head
Paul Shapiro 6 years ago
parent a6e414dda2
commit 916b154e31

@ -144,6 +144,15 @@ In future, the key names could be compressed.
* Returns: `err_msg: String` *OR* `pub_spendKey_string: String`, `pub_viewKey_string: String`, `isInViewOnlyMode: Boolstring`, and `isValid: Boolstring`
**`address_and_keys_from_seed`**
* AKA `create_address` in legacy mymonero-core-js
* Args: `nettype_string: NettypeString`, `mnemonic_string: String`
* Returns: `err_msg: String` *OR* `address_string: String`, `pub_spendKey_string: String`, `pub_viewKey_string: String`, `sec_viewKey_string: String`, and `sec_spendKey_string: String`
#### Producing Misc. Values
**`new_integrated_address`**
@ -170,6 +179,43 @@ In future, the key names could be compressed.
* Returns: `err_msg: String` *OR* `retVal: String`
**`generate_key_derivation`**
* Args: `pub: String`, `sec: String`
* Returns: `err_msg: String` *OR* `retVal: String`
**`derive_public_key`**
* Args: `derivation: String`, `pub: String`, `out_index: UInt32String`
* Returns: `err_msg: String` *OR* `retVal: String`
**`derive_subaddress_public_key`**
* Args: `derivation: String`, `output_key: String`, `out_index: UInt32String`
* Returns: `err_msg: String` *OR* `retVal: String`
**`decodeRct`**
* Args: `i: UInt32String`, `sk: String`, `rv: DecodeRCT_RV`
* `DecodeRCT_RV: Dictionary` with `type: RCTTypeIntString`, `ecdhInfo: [DecodeRCT_ECDHInfo]`, `outPk: [DecodeRCT_OutPK]`
* `RCTTypeIntString: String` corresponding to values in `rct::RCTType*`
* `DecodeRCT_ECDHInfo: Dictionary` with `amount: String`, `mask: String`
* `DecodeRCT_OutPK: Dictionary` with `mask: String`
e.g.
```
{"i":"1","sk":"9b1529acb638f497d05677d7505d354b4ba6bc95484008f6362f93160ef3e503","rv":{"type":"1","ecdhInfo":[{"mask":"3ad9d0b3398691b94558e0f750e07e5e0d7d12411cd70b3841159e6c6b10db02","amount":"b3189d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506"},{"mask":"97b00af8ecba3cb71b9660cc9e1ac110abd21a4c5e50a2c125f964caa96bef0c","amount":"60269d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506"},{"mask":"db67f5066d9455db404aeaf435ad948bc9f27344bc743e3a32583a9e6695cb08","amount":"b3189d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506"}],"outPk":[{"mask":"9adc531a9c79a49a4257f24e5e5ea49c2fc1fb4eef49e00d5e5aba6cb6963a7d"},{"mask":"89f40499d6786a4027a24d6674d0940146fd12d8bc6007d338f19f05040e7a41"},{"mask":"f413d28bd5ffdc020528bcb2c19919d7484fbc9c3dd30de34ecff5b8a904e7f6"}]}}
```
* Returns `err_msg: String` *OR* `amount: String` and `mask: String`
#### Fees
**`estimate_rct_tx_size`**
@ -207,3 +253,4 @@ Convenience wrapper
* Returns: `err_msg: String` *OR* `serialized_signed_tx: String`, `tx_hash: String`, `tx_key: String`

@ -304,7 +304,58 @@ bool monero_wallet_utils::wallet_with(
};
return true;
}
bool monero_wallet_utils::address_and_keys_from_seed(
const string &sec_seed_string,
network_type nettype,
ComponentsFromSeed_RetVals &retVals
) {
retVals = {};
//
unsigned long sec_seed_string_length = sec_seed_string.length();
//
crypto::secret_key sec_seed;
// Possibly factor this info shared function:
bool from_legacy16B_lw_seed = false;
if (sec_seed_string_length == sec_seed_hex_string_length) { // normal seed
from_legacy16B_lw_seed = false; // to be clear
bool r = string_tools::hex_to_pod(sec_seed_string, sec_seed);
if (!r) {
retVals.did_error = true;
retVals.err_string = "Invalid seed";
//
return false;
}
} else if (sec_seed_string_length == legacy16B__sec_seed_hex_string_length) {
from_legacy16B_lw_seed = true;
legacy16B_secret_key legacy16B_sec_seed;
bool r = string_tools::hex_to_pod(sec_seed_string, legacy16B_sec_seed);
if (!r) {
retVals.did_error = true;
retVals.err_string = "Invalid seed";
//
return false;
}
coerce_valid_sec_key_from(legacy16B_sec_seed, sec_seed);
}
//
cryptonote::account_base account{}; // this initializes the wallet and should call the default constructor
account.generate(
sec_seed,
true/*recover*/,
false/*two_random*/,
from_legacy16B_lw_seed // assumed set if r
);
const cryptonote::account_keys& keys = account.get_keys();
retVals.optl__val = ComponentsFromSeed{
account.get_public_address_str(nettype),
//
keys.m_spend_secret_key,
keys.m_view_secret_key,
keys.m_account_address.m_spend_public_key,
keys.m_account_address.m_view_public_key,
};
return true;
}
bool monero_wallet_utils::validate_wallet_components_with( // returns !did_error
const string &address_string,
const string &sec_viewKey_string,

@ -187,6 +187,25 @@ namespace monero_wallet_utils
network_type nettype,
WalletComponentsValidationResults &retVals
);
//
struct ComponentsFromSeed
{
string address_string;
//
secret_key sec_spendKey;
secret_key sec_viewKey;
public_key pub_spendKey;
public_key pub_viewKey;
};
struct ComponentsFromSeed_RetVals: RetVals_base
{
optional<ComponentsFromSeed> optl__val = boost::none;
};
bool address_and_keys_from_seed(
const string &sec_seed_string,
network_type nettype,
ComponentsFromSeed_RetVals &retVals
);
}

@ -44,6 +44,7 @@
#include "monero_key_image_utils.hpp"
#include "wallet_errors.h"
#include "string_tools.h"
#include "ringct/rctSigs.h"
//
//
using namespace std;
@ -92,6 +93,8 @@ string serial_bridge::string_from_nettype(network_type nettype)
// Shared - Parsing - Args
bool parsed_json_root(const string &args_string, boost::property_tree::ptree &json_root)
{
cout << "args_string: " << args_string << endl;
std::stringstream ss;
ss << args_string;
try {
@ -279,6 +282,34 @@ string serial_bridge::are_equal_mnemonics(const string &args_string)
//
return ret_json_from_root(root);
}
string serial_bridge::address_and_keys_from_seed(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");
}
monero_wallet_utils::ComponentsFromSeed_RetVals retVals;
bool r = monero_wallet_utils::address_and_keys_from_seed(
json_root.get<string>("seed_string"),
nettype_from_string(json_root.get<string>("nettype_string")),
retVals
);
bool did_error = retVals.did_error;
if (!r) {
return error_ret_json_from_message(*(retVals.err_string));
}
THROW_WALLET_EXCEPTION_IF(did_error, error::wallet_internal_error, "Illegal success flag but did_error");
//
boost::property_tree::ptree root;
root.put(ret_json_key__address_string(), (*(retVals.optl__val)).address_string);
root.put(ret_json_key__pub_viewKey_string(), epee::string_tools::pod_to_hex((*(retVals.optl__val)).pub_viewKey));
root.put(ret_json_key__sec_viewKey_string(), epee::string_tools::pod_to_hex((*(retVals.optl__val)).sec_viewKey));
root.put(ret_json_key__pub_spendKey_string(), epee::string_tools::pod_to_hex((*(retVals.optl__val)).pub_spendKey));
root.put(ret_json_key__sec_spendKey_string(), epee::string_tools::pod_to_hex((*(retVals.optl__val)).sec_spendKey));
//
return ret_json_from_root(root);
}
string serial_bridge::mnemonic_from_seed(const string &args_string)
{
boost::property_tree::ptree json_root;
@ -539,3 +570,150 @@ string serial_bridge::create_transaction(const string &args_string)
//
return ret_json_from_root(root);
}
//
string serial_bridge::decodeRct(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");
}
rct::key sk;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("sk"), sk)) {
return error_ret_json_from_message("Invalid 'sk'");
}
uint i = stoul(json_root.get<string>("i"));
// NOTE: this rv structure parsing could be factored but it presently does not implement a number of sub-components of rv, such as .pseudoOuts
auto rv_desc = json_root.get_child("rv");
rct::rctSig rv = AUTO_VAL_INIT(rv);
uint rv_type_int = stoul(rv_desc.get<string>("type"));
// got to be a better way to do this
if (rv_type_int == rct::RCTTypeNull) {
rv.type = rct::RCTTypeNull;
} else if (rv_type_int == rct::RCTTypeSimple) {
rv.type = rct::RCTTypeSimple;
} else if (rv_type_int == rct::RCTTypeFull) {
rv.type = rct::RCTTypeFull;
} else if (rv_type_int == rct::RCTTypeSimpleBulletproof) {
rv.type = rct::RCTTypeSimpleBulletproof;
} else if (rv_type_int == rct::RCTTypeFullBulletproof) {
rv.type = rct::RCTTypeFullBulletproof;
} else {
return error_ret_json_from_message("Invalid 'rv.type'");
}
BOOST_FOREACH(boost::property_tree::ptree::value_type &ecdh_info_desc, rv_desc.get_child("ecdhInfo"))
{
assert(ecdh_info_desc.first.empty()); // array elements have no names
auto ecdh_info = rct::ecdhTuple{};
if (!epee::string_tools::hex_to_pod(ecdh_info_desc.second.get<string>("mask"), ecdh_info.mask)) {
return error_ret_json_from_message("Invalid rv.ecdhInfo[].mask");
}
if (!epee::string_tools::hex_to_pod(ecdh_info_desc.second.get<string>("amount"), ecdh_info.amount)) {
return error_ret_json_from_message("Invalid rv.ecdhInfo[].amount");
}
rv.ecdhInfo.push_back(ecdh_info);
}
BOOST_FOREACH(boost::property_tree::ptree::value_type &outPk_desc, rv_desc.get_child("outPk"))
{
assert(outPk_desc.first.empty()); // array elements have no names
auto outPk = rct::ctkey{};
if (!epee::string_tools::hex_to_pod(outPk_desc.second.get<string>("mask"), outPk.mask)) {
return error_ret_json_from_message("Invalid rv.outPk[].mask");
}
// FIXME: does dest need to be placed on the key?
rv.outPk.push_back(outPk);
}
//
rct::key mask;
rct::xmr_amount/*uint64_t*/ decoded_amount;
try {
decoded_amount = rct::decodeRct(
rv, sk, i, mask,
hw::get_device("default") // presently this uses the default device but we could let a string be passed to switch the type
);
} catch (std::exception const& e) {
return error_ret_json_from_message(e.what());
}
stringstream decoded_amount_ss;
decoded_amount_ss << decoded_amount;
//
boost::property_tree::ptree root;
root.put(ret_json_key__decodeRct_mask(), epee::string_tools::pod_to_hex(mask));
root.put(ret_json_key__decodeRct_amount(), decoded_amount_ss.str());
//
return ret_json_from_root(root);
}
string serial_bridge::generate_key_derivation(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");
}
public_key pub_key;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("pub"), pub_key)) {
return error_ret_json_from_message("Invalid 'pub'");
}
secret_key sec_key;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("sec"), sec_key)) {
return error_ret_json_from_message("Invalid 'sec'");
}
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
if (!crypto::generate_key_derivation(pub_key, sec_key, derivation)) {
return error_ret_json_from_message("Unable to generate key derivation");
}
boost::property_tree::ptree root;
root.put(ret_json_key__generic_retVal(), epee::string_tools::pod_to_hex(derivation));
//
return ret_json_from_root(root);
}
string serial_bridge::derive_public_key(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");
}
crypto::key_derivation derivation;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("derivation"), derivation)) {
return error_ret_json_from_message("Invalid 'derivation'");
}
std::size_t output_index = stoul(json_root.get<string>("out_index"));
crypto::public_key base;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("pub"), base)) {
return error_ret_json_from_message("Invalid 'pub'");
}
crypto::public_key derived_key = AUTO_VAL_INIT(derived_key);
if (!crypto::derive_public_key(derivation, output_index, base, derived_key)) {
return error_ret_json_from_message("Unable to derive public key");
}
boost::property_tree::ptree root;
root.put(ret_json_key__generic_retVal(), epee::string_tools::pod_to_hex(derived_key));
//
return ret_json_from_root(root);
}
string serial_bridge::derive_subaddress_public_key(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");
}
crypto::key_derivation derivation;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("derivation"), derivation)) {
return error_ret_json_from_message("Invalid 'derivation'");
}
std::size_t output_index = stoul(json_root.get<string>("out_index"));
crypto::public_key out_key;
if (!epee::string_tools::hex_to_pod(json_root.get<string>("output_key"), out_key)) {
return error_ret_json_from_message("Invalid 'output_key'");
}
crypto::public_key derived_key = AUTO_VAL_INIT(derived_key);
if (!crypto::derive_subaddress_public_key(out_key, derivation, output_index, derived_key)) {
return error_ret_json_from_message("Unable to derive public key");
}
boost::property_tree::ptree root;
root.put(ret_json_key__generic_retVal(), epee::string_tools::pod_to_hex(derived_key));
//
return ret_json_from_root(root);
}

@ -54,6 +54,7 @@ namespace serial_bridge
//
string newly_created_wallet(const string &args_string);
string are_equal_mnemonics(const string &args_string);
string address_and_keys_from_seed(const string &args_string); // aka legacy mymonero-core-js:create_address
string mnemonic_from_seed(const string &args_string);
string seed_and_keys_from_mnemonic(const string &args_string);
string validate_components_for_login(const string &args_string);
@ -64,6 +65,11 @@ namespace serial_bridge
//
string generate_key_image(const string &args_string);
//
string generate_key_derivation(const string &args_string);
string derive_public_key(const string &args_string);
string derive_subaddress_public_key(const string &args_string);
string decodeRct(const string &args_string);
//
// JSON values
network_type nettype_from_string(const string &nettype_string);
string string_from_nettype(network_type nettype);
@ -90,7 +96,9 @@ namespace serial_bridge
static inline string ret_json_key__sec_viewKey_string() { return "sec_viewKey_string"; }
static inline string ret_json_key__sec_spendKey_string() { return "sec_spendKey_string"; }
static inline string ret_json_key__isValid() { return "isValid"; }
static inline string ret_json_key__isInViewOnlyMode() { return "isInViewOnlyMode"; }
static inline string ret_json_key__isInViewOnlyMode() { return "isInViewOnlyMode"; }
static inline string ret_json_key__decodeRct_mask() { return "mask"; }
static inline string ret_json_key__decodeRct_amount() { return "amount"; }
// JSON keys - Args
// TODO:
// static inline string args_json_key__

@ -873,3 +873,189 @@ BOOST_AUTO_TEST_CASE(bridged__generate_key_image)
BOOST_REQUIRE(*key_image_string == "ae30ee23051dc0bdf10303fbd3b7d8035a958079eb66516b1740f2c9b02c804e");
cout << "bridged__generate_key_image: " << *key_image_string << endl;
}
//
BOOST_AUTO_TEST_CASE(bridged__address_and_keys_from_seed)
{
using namespace serial_bridge;
//
boost::property_tree::ptree root;
root.put("seed_string", "9c973aa296b79bbf452781dd3d32ad7f");
root.put("nettype_string", string_from_nettype(MAINNET));
//
auto ret_string = serial_bridge::address_and_keys_from_seed(args_string_from_root(root));
stringstream ret_stream;
ret_stream << ret_string;
boost::property_tree::ptree ret_tree;
boost::property_tree::read_json(ret_stream, ret_tree);
optional<string> err_string = ret_tree.get_optional<string>(ret_json_key__any__err_msg());
if (err_string != none) {
BOOST_REQUIRE_MESSAGE(false, *err_string);
}
optional<string> address_string = ret_tree.get_optional<string>(ret_json_key__address_string());
BOOST_REQUIRE(address_string != none);
BOOST_REQUIRE((*address_string).size() > 0);
cout << "bridged__address_and_keys_from_seed: address: " << *address_string << endl;
BOOST_REQUIRE(*address_string == "43zxvpcj5Xv9SEkNXbMCG7LPQStHMpFCQCmkmR4u5nzjWwq5Xkv5VmGgYEsHXg4ja2FGRD5wMWbBVMijDTqmmVqm93wHGkg");
optional<string> pub_viewKey_string = ret_tree.get_optional<string>(ret_json_key__pub_viewKey_string());
BOOST_REQUIRE(pub_viewKey_string != none);
BOOST_REQUIRE((*pub_viewKey_string).size() > 0);
cout << "bridged__address_and_keys_from_seed: pub_viewKey_string: " << *pub_viewKey_string << endl;
optional<string> pub_spendKey_string = ret_tree.get_optional<string>(ret_json_key__pub_spendKey_string());
BOOST_REQUIRE(pub_spendKey_string != none);
BOOST_REQUIRE((*pub_spendKey_string).size() > 0);
cout << "bridged__address_and_keys_from_seed: pub_spendKey_string: " << *pub_spendKey_string << endl;
optional<string> sec_viewKey_string = ret_tree.get_optional<string>(ret_json_key__sec_viewKey_string());
BOOST_REQUIRE(sec_viewKey_string != none);
BOOST_REQUIRE((*sec_viewKey_string).size() > 0);
BOOST_REQUIRE(*sec_viewKey_string == "7bea1907940afdd480eff7c4bcadb478a0fbb626df9e3ed74ae801e18f53e104");
cout << "bridged__address_and_keys_from_seed: sec_viewKey_string: " << *sec_viewKey_string << endl;
optional<string> sec_spendKey_string = ret_tree.get_optional<string>(ret_json_key__sec_spendKey_string());
BOOST_REQUIRE(sec_spendKey_string != none);
BOOST_REQUIRE((*sec_spendKey_string).size() > 0);
BOOST_REQUIRE(*sec_spendKey_string == "4e6d43cd03812b803c6f3206689f5fcc910005fc7e91d50d79b0776dbefcd803");
cout << "bridged__address_and_keys_from_seed: sec_spendKey_string: " << *sec_spendKey_string << endl;
}
//
BOOST_AUTO_TEST_CASE(bridged__derive_public_key)
{
using namespace serial_bridge;
//
boost::property_tree::ptree root;
root.put("derivation", "591c749f1868c58f37ec3d2a9d2f08e7f98417ac4f8131e3a57c1fd71273ad00");
root.put("out_index", "1");
root.put("pub", "904e49462268d771cc1649084c35aa1296bfb214880fe2e7f373620a3e2ba597");
//
auto ret_string = serial_bridge::derive_public_key(args_string_from_root(root));
stringstream ret_stream;
ret_stream << ret_string;
boost::property_tree::ptree ret_tree;
boost::property_tree::read_json(ret_stream, ret_tree);
optional<string> err_string = ret_tree.get_optional<string>(ret_json_key__any__err_msg());
if (err_string != none) {
BOOST_REQUIRE_MESSAGE(false, *err_string);
}
optional<string> str = ret_tree.get_optional<string>(ret_json_key__generic_retVal());
BOOST_REQUIRE(str != none);
BOOST_REQUIRE((*str).size() > 0);
BOOST_REQUIRE(*str == "da26518ddb54cde24ccfc59f36df13bbe9bdfcb4ef1b223d9ab7bef0a50c8be3");
cout << "bridged__derive_public_key: " << *str << endl;
}
BOOST_AUTO_TEST_CASE(bridged__derive_subaddress_public_key)
{
using namespace serial_bridge;
//
boost::property_tree::ptree root;
root.put("derivation", "591c749f1868c58f37ec3d2a9d2f08e7f98417ac4f8131e3a57c1fd71273ad00");
root.put("out_index", "1");
root.put("output_key", "904e49462268d771cc1649084c35aa1296bfb214880fe2e7f373620a3e2ba597");
//
auto ret_string = serial_bridge::derive_subaddress_public_key(args_string_from_root(root));
stringstream ret_stream;
ret_stream << ret_string;
boost::property_tree::ptree ret_tree;
boost::property_tree::read_json(ret_stream, ret_tree);
optional<string> err_string = ret_tree.get_optional<string>(ret_json_key__any__err_msg());
if (err_string != none) {
BOOST_REQUIRE_MESSAGE(false, *err_string);
}
optional<string> str = ret_tree.get_optional<string>(ret_json_key__generic_retVal());
BOOST_REQUIRE(str != none);
BOOST_REQUIRE((*str).size() > 0);
BOOST_REQUIRE(*str == "dfc9e4a0039e913204c1c0f78e954a7ec7ce291d8ffe88265632f0da9d8de1be");
cout << "bridged__derive_subaddress_public_key: " << *str << endl;
}
BOOST_AUTO_TEST_CASE(bridged__generate_key_derivation)
{
using namespace serial_bridge;
//
boost::property_tree::ptree root;
root.put("pub", "904e49462268d771cc1649084c35aa1296bfb214880fe2e7f373620a3e2ba597");
root.put("sec", "52aa4c69b93b780885c9d7f51e6fd5795904962c61a2e07437e130784846f70d");
//
auto ret_string = serial_bridge::generate_key_derivation(args_string_from_root(root));
stringstream ret_stream;
ret_stream << ret_string;
boost::property_tree::ptree ret_tree;
boost::property_tree::read_json(ret_stream, ret_tree);
optional<string> err_string = ret_tree.get_optional<string>(ret_json_key__any__err_msg());
if (err_string != none) {
BOOST_REQUIRE_MESSAGE(false, *err_string);
}
optional<string> derivation = ret_tree.get_optional<string>(ret_json_key__generic_retVal());
BOOST_REQUIRE(derivation != none);
BOOST_REQUIRE((*derivation).size() > 0);
BOOST_REQUIRE(*derivation == "591c749f1868c58f37ec3d2a9d2f08e7f98417ac4f8131e3a57c1fd71273ad00");
cout << "bridged__generate_key_derivation: derivation: " << *derivation << endl;
}
//
BOOST_AUTO_TEST_CASE(bridged__decodeRct)
{
using namespace serial_bridge;
//
boost::property_tree::ptree root;
root.put("i", "1");
root.put("sk", "9b1529acb638f497d05677d7505d354b4ba6bc95484008f6362f93160ef3e503");
boost::property_tree::ptree rv;
{
rv.put("type", "1");
//
boost::property_tree::ptree ecdhInfo;
{
boost::property_tree::ptree ecdh_info;
ecdh_info.put("mask", "3ad9d0b3398691b94558e0f750e07e5e0d7d12411cd70b3841159e6c6b10db02");
ecdh_info.put("amount", "b3189d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506");
ecdhInfo.push_back(std::make_pair("", ecdh_info));
}
{
boost::property_tree::ptree ecdh_info;
ecdh_info.put("mask", "97b00af8ecba3cb71b9660cc9e1ac110abd21a4c5e50a2c125f964caa96bef0c");
ecdh_info.put("amount", "60269d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506");
ecdhInfo.push_back(std::make_pair("", ecdh_info));
}
{
boost::property_tree::ptree ecdh_info;
ecdh_info.put("mask", "db67f5066d9455db404aeaf435ad948bc9f27344bc743e3a32583a9e6695cb08");
ecdh_info.put("amount", "b3189d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506");
ecdhInfo.push_back(std::make_pair("", ecdh_info));
}
rv.add_child("ecdhInfo", ecdhInfo);
//
boost::property_tree::ptree outPk;
{
boost::property_tree::ptree an_outPk;
an_outPk.put("mask", "9adc531a9c79a49a4257f24e5e5ea49c2fc1fb4eef49e00d5e5aba6cb6963a7d");
outPk.push_back(std::make_pair("", an_outPk));
}
{
boost::property_tree::ptree an_outPk;
an_outPk.put("mask", "89f40499d6786a4027a24d6674d0940146fd12d8bc6007d338f19f05040e7a41");
outPk.push_back(std::make_pair("", an_outPk));
}
{
boost::property_tree::ptree an_outPk;
an_outPk.put("mask", "f413d28bd5ffdc020528bcb2c19919d7484fbc9c3dd30de34ecff5b8a904e7f6");
outPk.push_back(std::make_pair("", an_outPk));
}
rv.add_child("outPk", outPk);
}
root.add_child("rv", rv);
//
auto ret_string = serial_bridge::decodeRct(args_string_from_root(root));
stringstream ret_stream;
ret_stream << ret_string;
boost::property_tree::ptree ret_tree;
boost::property_tree::read_json(ret_stream, ret_tree);
optional<string> err_string = ret_tree.get_optional<string>(ret_json_key__any__err_msg());
if (err_string != none) {
BOOST_REQUIRE_MESSAGE(false, *err_string);
}
string mask_string = ret_tree.get<string>(ret_json_key__decodeRct_mask());
BOOST_REQUIRE(mask_string.size() > 0);
cout << "bridged__decodeRct: mask_string: " << mask_string << endl;
BOOST_REQUIRE(mask_string == "3f59c741c9ad560bfea92f42449a180bc8362f1b5ddd957e3b5772dbaf7f840e");
string amount_string = ret_tree.get<string>(ret_json_key__decodeRct_amount());
BOOST_REQUIRE(amount_string.size() > 0);
cout << "bridged__decodeRct: amount_string: " << amount_string << endl;
BOOST_REQUIRE(amount_string == "4501"); // FIXME is this correct?
}

Loading…
Cancel
Save