From 6571df4c761998c8b9773f202f536570a9aadebe Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Tue, 21 Jan 2025 13:49:53 +0000 Subject: [PATCH] added private viewkey support; upgraded scanner; bumped version --- README.md | 2 +- src/blockchain_utilities/CMakeLists.txt | 3 + .../blockchain_scanner.cpp | 171 ++++++++++++++++-- .../cryptonote_boost_serialization.h | 2 +- src/cryptonote_config.h | 5 +- src/cryptonote_core/cryptonote_tx_utils.cpp | 79 +++++++- src/cryptonote_core/cryptonote_tx_utils.h | 3 + src/ringct/rctSigs.cpp | 4 +- src/ringct/rctTypes.h | 4 +- src/serialization/json_object.cpp | 4 +- src/version.cpp.in | 2 +- 11 files changed, 252 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 4b395b963..b1981ee8f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Salvium Zero v0.9.0-rc1 +# Salvium Zero v0.9.0-rc2 Copyright (c) 2023-2024, Salvium Portions Copyright (c) 2014-2023, The Monero Project diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 6fefd9a4d..e6e126253 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -297,6 +297,9 @@ monero_add_executable(blockchain_scanner target_link_libraries(blockchain_scanner PRIVATE + wallet + crypto + cncrypto cryptonote_core blockchain_db version diff --git a/src/blockchain_utilities/blockchain_scanner.cpp b/src/blockchain_utilities/blockchain_scanner.cpp index 95eed526a..77cd89169 100644 --- a/src/blockchain_utilities/blockchain_scanner.cpp +++ b/src/blockchain_utilities/blockchain_scanner.cpp @@ -29,6 +29,8 @@ #include #include #include "common/command_line.h" +#include "common/i18n.h" +#include "common/password.h" #include "common/varint.h" #include "cryptonote_basic/cryptonote_boost_serialization.h" #include "cryptonote_core/tx_pool.h" @@ -38,6 +40,7 @@ #include "blockchain_db/blockchain_db.h" #include "oracle/pricing_record.h" #include "version.h" +#include "wallet/wallet2.h" #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "bcutil" @@ -49,8 +52,20 @@ namespace po = boost::program_options; using namespace epee; using namespace cryptonote; +namespace scanner +{ + const char* tr(const char* str) + { + return i18n_translate(str, "tools::scanner"); + } +} + static bool stop_requested = false; +static const std::vector suspect_output_pubkeys = { +"1234567890123456789012345678901234567890123456789012345678901234" +}; + int main(int argc, char* argv[]) { TRY_ENTRY(); @@ -73,6 +88,7 @@ int main(int argc, char* argv[]) const command_line::arg_descriptor arg_delimiter = {"delimiter", "\"\"", DELIM}; const command_line::arg_descriptor arg_stake_mode = {"stake", "\"\"", DEF_STAKE_MODE}; const command_line::arg_descriptor arg_audit = {"audit", "Scan for audit issues", false}; + const command_line::arg_descriptor arg_decode_pvk = {"decodepvk", "Attempt to decode private view key data", false}; const command_line::arg_descriptor arg_check_asset_types = {"check-asset-types", "Scan for asset-type issues", false}; command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir); @@ -84,6 +100,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_cmd_sett, arg_delimiter); command_line::add_arg(desc_cmd_sett, arg_stake_mode); command_line::add_arg(desc_cmd_sett, arg_audit); + command_line::add_arg(desc_cmd_sett, arg_decode_pvk); command_line::add_arg(desc_cmd_sett, arg_check_asset_types); command_line::add_arg(desc_cmd_only, command_line::arg_help); @@ -125,6 +142,7 @@ int main(int argc, char* argv[]) std::string delimiter = command_line::get_arg(vm, arg_delimiter); std::string stake_mode = command_line::get_arg(vm, arg_stake_mode); bool opt_audit = command_line::get_arg(vm, arg_audit); + bool opt_decode_pvk = command_line::get_arg(vm, arg_decode_pvk); bool opt_check_asset_types = command_line::get_arg(vm, arg_check_asset_types); // If we wanted to use the memory pool, we would set up a fake_core. @@ -159,6 +177,26 @@ int main(int argc, char* argv[]) LOG_PRINT_L0("Loading blockchain from folder " << folder << " ..."); const std::string filename = folder.string(); + crypto::secret_key SK = crypto::null_skey; + if (opt_decode_pvk) { + epee::wipeable_string private_key_passphrase; + auto pwd_container = tools::password_container::prompt(true, "Enter passphrase for decoding private keys"); + if (!pwd_container) { + std::cerr << scanner::tr("Failed to read passphrase") << std::endl; + return 1; + } + private_key_passphrase = pwd_container->password(); + crypto::hash_to_scalar(private_key_passphrase.data(), private_key_passphrase.size(), SK); + crypto::public_key PK; + crypto::secret_key_to_public_key(SK, PK); + std::string PK_str = epee::string_tools::pod_to_hex(PK); + const std::string expected_PK_str = "5e860406bf9221dba6409faa6eb8fecd6f34acc4935634e76b64b90bf2b6d6a6"; + if (PK_str != expected_PK_str) { + std::cerr << scanner::tr("Invalid passphrase - PK produced was ") << PK_str << std::endl; + return 1; + } + } + try { db->open(filename, DBF_RDONLY); @@ -168,7 +206,7 @@ int main(int argc, char* argv[]) LOG_PRINT_L0("Error opening database: " << e.what()); return 1; } - r = core_storage->blockchain.init(db, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET); + r = core_storage->blockchain.init(db, net_type); CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); LOG_PRINT_L0("Source blockchain storage initialized OK"); @@ -215,12 +253,15 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, '' struct wallet_summary { uint64_t total_amount; - std::vector> txs; + std::vector>> txs; bool seen_closing_tx; - crypto::public_key viewkey; + std::string enc_view_privkey_str; + bool flagged; + std::string reason; }; const std::map> audit_hard_forks = get_config(net_type).AUDIT_HARD_FORKS; + const uint64_t audit_lock_period = get_config(net_type).AUDIT_LOCK_PERIOD; // Create a map of wallet addresses and total amounts in them std::map wallet_details; @@ -272,8 +313,10 @@ skip: std::string asset_type; if (!cryptonote::get_output_asset_type(miner_tx_vout, asset_type)) { throw std::runtime_error("Aborting: failed to get output asset type from miner_tx"); - } else if (asset_type != "SAL") { - throw std::runtime_error("Aborting: invalid output asset type from miner_tx"); + } else if (blk.major_version >= HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL1") { + throw std::runtime_error("Aborting: invalid output asset type from miner_tx: " + asset_type); + } else if (blk.major_version < HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL") { + throw std::runtime_error("Aborting: invalid output asset type from miner_tx: " + asset_type + ", HF:" + std::to_string(blk.major_version)); } miner_tx_assets.insert(asset_type); if (miner_tx_vout.amount > 13500000000 && h>0) { @@ -293,12 +336,14 @@ skip: std::string asset_type; if (!cryptonote::get_output_asset_type(protocol_tx_vout, asset_type)) { throw std::runtime_error("Aborting: failed to get output asset type from protocol_tx"); - } else if (asset_type != "SAL") { - throw std::runtime_error("Aborting: invalid output asset type from protocol_tx"); + } else if (blk.major_version >= HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL1") { + throw std::runtime_error("Aborting: invalid output asset type from protocol_tx: " + asset_type); + } else if (blk.major_version < HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL") { + throw std::runtime_error("Aborting: invalid output asset type from protocol_tx: " + asset_type + ", HF:" + std::to_string(blk.major_version)); } protocol_tx_assets.insert(asset_type); if (protocol_tx_vout.amount > 25000000000000) { - std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "large protocol TX amount detected from height " << (h-21601) << delimiter << "amount:" << protocol_tx_vout.amount << std::endl; + std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "large protocol TX amount detected from height " << (h-audit_lock_period) << delimiter << "amount:" << protocol_tx_vout.amount << std::endl; } crypto::public_key key; cryptonote::get_output_public_key(protocol_tx_vout, key); @@ -329,7 +374,10 @@ skip: currsz += bd.size(); currtxs++; - if (tx.type != cryptonote::transaction_type::TRANSFER && tx.type != cryptonote::transaction_type::BURN && tx.type != cryptonote::transaction_type::STAKE) { + if (tx.type != cryptonote::transaction_type::TRANSFER && + tx.type != cryptonote::transaction_type::BURN && + tx.type != cryptonote::transaction_type::STAKE && + tx.type != cryptonote::transaction_type::AUDIT) { std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "invalid TX type detected" << delimiter << "type:" << (uint8_t)tx.type << std::endl; } @@ -372,11 +420,13 @@ skip: // Are we auditing? if (!opt_audit) continue; - // Audit checks + // Audit commencing - check hard fork version for _this_block_ if (audit_hard_forks.find(hf_version) == audit_hard_forks.end()) continue; // Pre-check - only attempt to verify legitimate AUDIT TXs if (tx.type != cryptonote::transaction_type::AUDIT) continue; + + // Make sure the RCT data is correct if (tx.rct_signatures.type != rct::RCTTypeSalviumOne) { std::cerr << "Aborting: Invalid RCT type " << tx.rct_signatures.type << " detected in AUDIT tx:" << tx_id << std::endl; throw std::runtime_error("Aborting: Invalid RCT type detected in AUDIT tx"); @@ -393,38 +443,76 @@ skip: std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "REVIEW: interval detected between audit TXs" << delimiter << "amount:" << (tx.amount_burnt / 100000000) << std::endl; } } else { - ws.viewkey = tx.rct_signatures.salvium_data.view_pubkey; + ws.enc_view_privkey_str = tx.rct_signatures.salvium_data.enc_view_privkey_str; + ws.flagged = false; + ws.seen_closing_tx = false; } - ws.txs.push_back({h, tx_id}); + ws.txs.push_back({h, {tx_id, ""}}); // Increment the total amount for this wallet that has been audited if (ws.total_amount + tx.amount_burnt < ws.total_amount) { - std::cerr << "Aborting: overflow in total_amount for Ks:" << tx.rct_signatures.salvium_data.spend_pubkey << std::endl; - throw std::runtime_error("Aborting: overflow in total_amount for Ks"); + std::cerr << "overflow in total_amount for Ks:" << tx.rct_signatures.salvium_data.spend_pubkey << std::endl; + //throw std::runtime_error("Aborting: overflow in total_amount for Ks"); + ws.txs.back().second.second = "wallet overflow"; + ws.flagged = true; } ws.total_amount += tx.amount_burnt; // Check - asset_type of SAL on all inputs if (tx.source_asset_type != "SAL") { // TX must spend SALs in audit - throw std::runtime_error("Aborting: invalid source asset type found in tx"); + std::cerr << "invalid source asset_type for Ks:" << tx.rct_signatures.salvium_data.spend_pubkey << std::endl; + //throw std::runtime_error("Aborting: invalid source asset type found in tx"); + ws.txs.back().second.second = "invalid source asset_type '" + tx.source_asset_type + "'"; + ws.flagged = true; } // Check - amount in STAKE TX if (tx.amount_burnt >= 25000000000000llu) { std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "BLACKLIST: large AUDIT TX detected" << delimiter << "amount:" << (tx.amount_burnt / 100000000) << std::endl; + ws.txs.back().second.second = "large AUDIT TX detected - amount:" + std::to_string(tx.amount_burnt/100000000) + std::string(" SAL"); + ws.flagged = true; } else if (tx.amount_burnt >= 10000000000000llu) { std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "REVIEW: large AUDIT TX detected" << delimiter << "amount:" << (tx.amount_burnt / 100000000) << std::endl; + ws.txs.back().second.second = "large AUDIT TX detected - amount:" + std::to_string(tx.amount_burnt/100000000) + std::string(" SAL"); + ws.flagged = true; } // Check - total amount for this wallet if (ws.total_amount >= 25000000000000llu) { std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "BLACKLIST: large BALANCE detected" << delimiter << "amount:" << (ws.total_amount / 100000000) << std::endl; + ws.txs.back().second.second = "large wallet balance detected - amount:" + std::to_string(ws.total_amount/100000000) + std::string(" SAL"); + ws.flagged = true; } else if (ws.total_amount >= 10000000000000llu) { std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "REVIEW: large BALANCE TX detected" << delimiter << "amount:" << (ws.total_amount / 100000000) << std::endl; + ws.txs.back().second.second = "large wallet balance detected - amount:" + std::to_string(ws.total_amount/100000000) + std::string(" SAL"); + ws.flagged = true; + } + + // Validate the Salvium audit data + //CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.outPk[0].mask, rv.salvium_data.cz_proof), "PRProof_Ver() failed on change proof"); + //CHECK_AND_ASSERT_THROW_MES(pseudoOuts.size() == rv.salvium_data.input_verification_data.size(), "incorrect number of input verification datasets"); + //CHECK_AND_ASSERT_THROW_MES(rv.salvium_data.spend_pubkey != crypto::null_pkey, "Invalid spend pubkey provided in audit data"); + //CHECK_AND_ASSERT_THROW_MES(rv.salvium_data.enc_view_privkey_str != "", "Invalid encrypted viewkey provided in audit data"); + for (size_t i=0; i < tx.rct_signatures.salvium_data.input_verification_data.size(); ++i) { + + // Recalculate the value of Ks from the Ko value + crypto::public_key ephemeral_pub = crypto::null_pkey; + CHECK_AND_ASSERT_THROW_MES(crypto::derive_public_key(tx.rct_signatures.salvium_data.input_verification_data[i].aR, + tx.rct_signatures.salvium_data.input_verification_data[i].i, + tx.rct_signatures.salvium_data.spend_pubkey, ephemeral_pub), + "Failed to derive ephemeral public key from audit data"); + // Now check this isn't in the list of suspect_output_pubkeys + std::string ephemeral_pub_str = epee::string_tools::pod_to_hex(ephemeral_pub); + for (size_t n=0; n(); + crypto::chacha20(pvk.data, sizeof(crypto::secret_key), symmetric_key, iv, &ciphertext[0]); + + // Step 5: Package ephemeral_pk and ciphertext together + std::string encrypted_data = std::string(reinterpret_cast(&ephemeral_pk), sizeof(ephemeral_pk)) + + std::string(reinterpret_cast(&iv), sizeof(iv)) + + ciphertext; + return encrypted_data; + } + //--------------------------------------------------------------- + // Decrypt function + bool decrypt_pvk(const std::string &encrypted_data, const crypto::secret_key &SK, crypto::secret_key &pvk) { + //std::string decrypt_pvk(const std::string &encrypted_data, const crypto::secret_key &SK) { + // Step 1: Extract ephemeral_pk, iv, and ciphertext from encrypted_data + const char *data_ptr = encrypted_data.data(); + crypto::public_key ephemeral_pk; + memcpy(&ephemeral_pk, data_ptr, sizeof(ephemeral_pk)); + data_ptr += sizeof(ephemeral_pk); + + crypto::chacha_iv iv; + memcpy(&iv, data_ptr, sizeof(iv)); + data_ptr += sizeof(iv); + + std::string ciphertext(data_ptr, encrypted_data.size() - sizeof(ephemeral_pk) - sizeof(iv)); + + // Step 2: Derive shared secret + crypto::ec_scalar shared_secret; + crypto::key_derivation derivation; + if (!crypto::generate_key_derivation(ephemeral_pk, SK, derivation)) { + throw std::runtime_error("Failed to generate key derivation"); + } + crypto::derivation_to_scalar(derivation, 0, shared_secret); + + // Step 3: Symmetric key generation (using Keccak hash) + crypto::hash symmetric_key_hash; + crypto::cn_fast_hash(&shared_secret, sizeof(shared_secret), symmetric_key_hash); + + // Step 4: Decrypt the data + std::string plaintext(ciphertext.size(), '\0'); + crypto::chacha_key symmetric_key; + memcpy(&symmetric_key, &symmetric_key_hash, sizeof(symmetric_key)); + crypto::chacha20(ciphertext.data(), ciphertext.size(), symmetric_key, iv, &plaintext[0]); + + memcpy(pvk.data, &plaintext[0], sizeof(crypto::secret_key)); + return true; + } + //--------------------------------------------------------------- bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const uint8_t hf_version, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type& tx_type, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool rct, const rct::RCTConfig &rct_config, bool shuffle_outs, bool use_view_tags) { hw::device &hwdev = sender_account_keys.get_device(); @@ -627,10 +697,17 @@ namespace cryptonote bool audit = (tx_type == cryptonote::transaction_type::AUDIT); rct::salvium_data_t salvium_data; if (audit) { + + // Generate the encrypted private view key + crypto::public_key PK; + epee::string_tools::hex_to_pod(SECRET_ENCRYPTION_PK_STR, PK); + salvium_data.enc_view_privkey_str = encrypt_pvk(sender_account_keys.m_view_secret_key, PK); + + // And now the rest of the structure salvium_data.salvium_data_type = rct::SalviumAudit; salvium_data.input_verification_data.reserve(sources.size()); salvium_data.spend_pubkey = sender_account_keys.m_account_address.m_spend_public_key; - salvium_data.view_pubkey = sender_account_keys.m_account_address.m_view_public_key; + } else { salvium_data.salvium_data_type = rct::SalviumNormal; } diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index ff8d782d8..4fbb9956d 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -173,6 +173,9 @@ namespace cryptonote crypto::public_key get_destination_view_key_pub(const std::vector &destinations, const boost::optional& change_addr); bool construct_tx(const account_keys& sender_account_keys, std::vector &sources, const std::vector& destinations, const uint8_t hf_version, const std::string& asset_type, const cryptonote::transaction_type& tx_type, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time); + std::string encrypt_pvk(const crypto::secret_key &pvk, const crypto::public_key &PK); + bool decrypt_pvk(const std::string &encrypted_data, const crypto::secret_key &SK, crypto::secret_key &pvk); + bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const uint8_t hf_version, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type& tx_type, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool shuffle_outs = true, bool use_view_tags = false); bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map& subaddresses, std::vector& sources, std::vector& destinations, const uint8_t hf_version, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type& tx_type, const boost::optional& change_addr, const std::vector &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool use_view_tags = false); diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 3d070ae36..d80f9c129 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1395,7 +1395,7 @@ namespace rct { // SRCG: populate the audit proof here rv.salvium_data.input_verification_data = salvium_data.input_verification_data; rv.salvium_data.spend_pubkey = salvium_data.spend_pubkey; - rv.salvium_data.view_pubkey = salvium_data.view_pubkey; + rv.salvium_data.enc_view_privkey_str = salvium_data.enc_view_privkey_str; rv.salvium_data.cz_proof = PRProof_Gen(outSk[0].mask); #ifdef DBG CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.outPk[0].mask, rv.salvium_data.cz_proof), "PRProof_Ver() failed on recently created change proof"); @@ -1724,7 +1724,7 @@ namespace rct { CHECK_AND_ASSERT_THROW_MES(PRProof_Ver(rv.outPk[0].mask, rv.salvium_data.cz_proof), "PRProof_Ver() failed on change proof"); CHECK_AND_ASSERT_THROW_MES(pseudoOuts.size() == rv.salvium_data.input_verification_data.size(), "incorrect number of input verification datasets"); CHECK_AND_ASSERT_THROW_MES(rv.salvium_data.spend_pubkey != crypto::null_pkey, "Invalid spend pubkey provided in audit data"); - CHECK_AND_ASSERT_THROW_MES(rv.salvium_data.view_pubkey != crypto::null_pkey, "Invalid view pubkey provided in audit data"); + CHECK_AND_ASSERT_THROW_MES(rv.salvium_data.enc_view_privkey_str != "", "Invalid encrypted viewkey provided in audit data"); for (size_t i=0; i < rv.salvium_data.input_verification_data.size(); ++i) { // Recalculate the value of Ks from the Ko value crypto::public_key ephemeral_pub = crypto::null_pkey; diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index f8181d97b..8c88f36e1 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -351,7 +351,7 @@ namespace rct { zk_proof cz_proof; // change is zero proof std::vector input_verification_data; crypto::public_key spend_pubkey; - crypto::public_key view_pubkey; + std::string enc_view_privkey_str; BEGIN_SERIALIZE_OBJECT() VARINT_FIELD(salvium_data_type) @@ -362,7 +362,7 @@ namespace rct { FIELD(cz_proof) FIELD(input_verification_data) FIELD(spend_pubkey) - FIELD(view_pubkey) + FIELD(enc_view_privkey_str) } END_SERIALIZE() }; diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index fd74c7406..ba8f28888 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1532,7 +1532,7 @@ void toJsonValue(rapidjson::Writer& dest, const rct::salvium_ INSERT_INTO_JSON_OBJECT(dest, cz_proof, salvium_data.cz_proof); INSERT_INTO_JSON_OBJECT(dest, input_verification_data, salvium_data.input_verification_data); INSERT_INTO_JSON_OBJECT(dest, spend_pubkey, salvium_data.spend_pubkey); - INSERT_INTO_JSON_OBJECT(dest, view_pubkey, salvium_data.view_pubkey); + INSERT_INTO_JSON_OBJECT(dest, enc_view_privkey_str, salvium_data.enc_view_privkey_str); } dest.EndObject(); @@ -1552,7 +1552,7 @@ void fromJsonValue(const rapidjson::Value& val, rct::salvium_data_t& salvium_dat GET_FROM_JSON_OBJECT(val, salvium_data.cz_proof, cz_proof); GET_FROM_JSON_OBJECT(val, salvium_data.input_verification_data, input_verification_data); GET_FROM_JSON_OBJECT(val, salvium_data.spend_pubkey, spend_pubkey); - GET_FROM_JSON_OBJECT(val, salvium_data.view_pubkey, view_pubkey); + GET_FROM_JSON_OBJECT(val, salvium_data.enc_view_privkey_str, enc_view_privkey_str); } } diff --git a/src/version.cpp.in b/src/version.cpp.in index 3d5b40143..b3b67b111 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" -#define DEF_SALVIUM_VERSION "0.9.0-rc1" +#define DEF_SALVIUM_VERSION "0.9.0-rc2" #define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero"