added private viewkey support; upgraded scanner; bumped version

This commit is contained in:
Some Random Crypto Guy
2025-01-21 13:49:53 +00:00
parent 89180a6727
commit 6571df4c76
11 changed files with 252 additions and 27 deletions
+1 -1
View File
@@ -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
+3
View File
@@ -297,6 +297,9 @@ monero_add_executable(blockchain_scanner
target_link_libraries(blockchain_scanner
PRIVATE
wallet
crypto
cncrypto
cryptonote_core
blockchain_db
version
+155 -16
View File
@@ -29,6 +29,8 @@
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#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<std::string> 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<std::string> arg_delimiter = {"delimiter", "\"<string>\"", DELIM};
const command_line::arg_descriptor<std::string> arg_stake_mode = {"stake", "\"<string>\"", DEF_STAKE_MODE};
const command_line::arg_descriptor<bool> arg_audit = {"audit", "Scan for audit issues", false};
const command_line::arg_descriptor<bool> arg_decode_pvk = {"decodepvk", "Attempt to decode private view key data", false};
const command_line::arg_descriptor<bool> 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<std::pair<uint64_t, crypto::hash>> txs;
std::vector<std::pair<uint64_t, std::pair<crypto::hash, std::string>>> txs;
bool seen_closing_tx;
crypto::public_key viewkey;
std::string enc_view_privkey_str;
bool flagged;
std::string reason;
};
const std::map<uint8_t, std::pair<std::string, std::string>> 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<crypto::public_key, wallet_summary> 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<suspect_output_pubkeys.size(); ++n) {
if (ephemeral_pub_str == suspect_output_pubkeys[n]) {
ws.txs.back().second.second = "SUSPECT OUTPUT PUBKEY DETECTED : '" + ephemeral_pub_str + "'";
ws.flagged = true;
break;
}
}
}
}
currblks++;
@@ -433,6 +521,57 @@ skip:
break;
}
// Iterate over all the flagged wallets
for (const auto &wallet_entry: wallet_details) {
// Was the wallet flagged?
if (!wallet_entry.second.flagged) continue;
// Decrypt the wallet private viewkey
crypto::secret_key wallet_private_view_key;
bool ok = cryptonote::decrypt_pvk(wallet_entry.second.enc_view_privkey_str, SK, wallet_private_view_key);
if (!ok) {
// report error
throw std::runtime_error("Well shit");
}
// Why was it flagged?
for (const auto &tx: wallet_entry.second.txs) {
// Check for a reason on this TX
if (tx.second.second != "") {
}
}
// Create a new "view only" wallet file
try {
// Derive the public view key from the private view key
crypto::public_key wallet_public_view_key;
bool ok = crypto::secret_key_to_public_key(wallet_private_view_key, wallet_public_view_key);
// Construct the Monero address with the public keys
cryptonote::account_public_address address;
address.m_view_public_key = wallet_public_view_key;
address.m_spend_public_key = wallet_entry.first;
std::string daemon_address = (opt_testnet) ? "http://127.0.0.1:29081" : (opt_stagenet) ? "http://127.0.0.1:39081" : "http://127.0.0.1:19081";
std::string wallet_password = "1234";
std::string wallet_path = epee::string_tools::pod_to_hex(wallet_entry.first) + "_wallet";
// Initialize the view-only wallet
tools::wallet2 w{net_type};
w.set_daemon(daemon_address);
w.set_refresh_from_block_height(0); // Set scanning from the genesis block
// Generate the wallet file
w.generate(wallet_path, wallet_password, address, wallet_private_view_key, true);
// Save the wallet file
w.store();
std::cout << "View-only wallet created successfully at: " << wallet_path << std::endl;
} catch (const std::exception &e) {
std::cerr << "Error creating view-only wallet: " << e.what() << std::endl;
}
}
return 0;
CATCH_ENTRY("Stats reporting error", 1);
@@ -376,7 +376,7 @@ namespace boost
a & x.cz_proof;
a & x.input_verification_data;
a & x.spend_pubkey;
a & x.view_pubkey;
a & x.enc_view_privkey_str;
}
}
+4 -1
View File
@@ -178,6 +178,9 @@
#define THREAD_STACK_SIZE 5 * 1024 * 1024
#define SECRET_ENCRYPTION_PK_STR "5e860406bf9221dba6409faa6eb8fecd6f34acc4935634e76b64b90bf2b6d6a6"
/*
#define HF_VERSION_DYNAMIC_FEE 4
#define HF_VERSION_MIN_MIXIN_4 6
@@ -290,7 +293,7 @@ namespace config
const uint64_t AUDIT_LOCK_PERIOD = 30*24*10;
std::string const TREASURY_ADDRESS = "SaLvdZR6w1A21sf2Wh6jYEh1wzY4GSbT7RX6FjyPsnLsffWLrzFQeXUXJcmBLRWDzZC2YXeYe5t7qKsnrg9FpmxmEcxPHsEYfqA";
// Hash domain separators
const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof";
const char HASH_KEY_BULLETPROOF_PLUS_EXPONENT[] = "bulletproof_plus";
+78 -1
View File
@@ -513,6 +513,76 @@ namespace cryptonote
return addr.m_view_public_key;
}
//---------------------------------------------------------------
// Encrypt function
std::string encrypt_pvk(const crypto::secret_key &pvk, const crypto::public_key &PK) {
// Step 1: Generate ephemeral keypair
crypto::secret_key ephemeral_sk;
crypto::public_key ephemeral_pk;
crypto::generate_keys(ephemeral_pk, ephemeral_sk);
// Step 2: Derive shared secret
crypto::ec_scalar shared_secret;
crypto::key_derivation derivation;
if (!crypto::generate_key_derivation(PK, ephemeral_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: Encrypt the data (AES-256-CBC or ChaCha20)
std::string ciphertext(sizeof(crypto::secret_key), '\0');
crypto::chacha_key symmetric_key;
memcpy(&symmetric_key, &symmetric_key_hash, sizeof(symmetric_key));
crypto::chacha_iv iv = crypto::rand<crypto::chacha_iv>();
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<char*>(&ephemeral_pk), sizeof(ephemeral_pk)) +
std::string(reinterpret_cast<char*>(&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<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& 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<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &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;
}
@@ -173,6 +173,9 @@ namespace cryptonote
crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr);
bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry> &sources, const std::vector<tx_destination_entry>& destinations, const uint8_t hf_version, const std::string& asset_type, const cryptonote::transaction_type& tx_type, const boost::optional<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &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<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& 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<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &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<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, std::vector<tx_destination_entry>& 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<cryptonote::account_public_address>& change_addr, const std::vector<uint8_t> &extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false, const rct::RCTConfig &rct_config = { rct::RangeProofBorromean, 0 }, bool use_view_tags = false);
+2 -2
View File
@@ -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;
+2 -2
View File
@@ -351,7 +351,7 @@ namespace rct {
zk_proof cz_proof; // change is zero proof
std::vector<salvium_input_data_t> 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()
};
+2 -2
View File
@@ -1532,7 +1532,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& 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);
}
}
+1 -1
View File
@@ -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"