Compare commits

..

19 Commits

Author SHA1 Message Date
ncoggins 42d8dc5ece fixed output of show_transfers, including filtering by TX type; bumped version number 2024-05-20 20:57:10 +01:00
Some Random Crypto Guy 89d426a739 Merge branch 'updated_return_address' into develop 2024-05-20 10:33:48 +01:00
ncoggins 199e47e076 small fix to prevent wallets from abandoning scanning when encountering protocol_tx not intended for them - duh! 2024-05-20 09:28:44 +01:00
Some Random Crypto Guy d24ed9e0cc fixes to the CLI wallet output of staking and protocol_tx outputs 2024-05-18 13:51:10 +01:00
ncoggins 872303f6ad fixed removal of m_locked_coins entries when PROTOCOL_TX pays out 2024-05-18 08:41:54 +01:00
Some Random Crypto Guy c56cfc6754 added versioning to avoid inadvertent use of old nodes 2024-05-17 13:09:57 +01:00
Neil Coggins de4e974e4c resolved MacOS wallet build issues 2024-05-17 11:30:58 +01:00
Some Random Crypto Guy 4607939ab6 fixed unlock time info displayed for mined blocks; added tx_type to get_return_address() call - needed for F point on transfers; bumped version 2024-05-16 22:29:32 +01:00
Some Random Crypto Guy 9a37188885 fixed issue with Hardfork 2; removed PRs from HardFork 1 as unnecessary / slowing the chain down 2024-05-16 10:58:02 +01:00
Some Random Crypto Guy aee0f479c1 changed NETWORK_ID and GENESIS_TX for new Salvium networks; fixed genesis_tx calculation for non-mainnet 2024-05-15 12:58:39 +01:00
Some Random Crypto Guy 9f5e18495b fixed windows build issues 2024-05-14 20:58:18 +01:00
Some Random Crypto Guy ae28c7a900 implementation of yield_info function 2024-05-14 14:23:31 +01:00
Some Random Crypto Guy b0ce6d2969 resolved the yield calculation issue 2024-05-12 22:59:43 +01:00
Some Random Crypto Guy 34b2f9b315 commenced removal of pricing_record touchpoints for MVP release 2024-05-07 14:34:19 +01:00
Some Random Crypto Guy 7bafd2866c a number of fixes; disabled return_payment as the functionality is changing to NOT require returning the same output 2024-03-27 14:50:31 +00:00
Some Random Crypto Guy 606580a173 Interim checkin
This code contains working "return address" semantics for CONVERT and YIELD.
2024-02-16 11:02:11 +00:00
Some Random Crypto Guy a3a7f686f3 Added functions to cache and manage yield calculations
Removed "tx.amount_locked" field - "tx.amount_burnt" is technically correct for all cases.
Removed invalid checkpoint data.
2024-01-30 14:22:46 +00:00
Some Random Crypto Guy a0d2044b5d fixed a bug with serialization of the pricing record when communicating between daemon and wallet for conversions 2024-01-17 14:54:41 +00:00
Some Random Crypto Guy 3a032c58a4 Fixed a number of issues with serialization of pricing_record entries. 2024-01-17 12:43:10 +00:00
79 changed files with 2166 additions and 888 deletions
@@ -37,6 +37,7 @@
#include "misc_log_ex.h"
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <typeinfo>
#include <iomanip>
+61 -21
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2014-2022, The Monero Project
// Portions Copyright (c) 2023, Fulmo (author: SRCG)
// Portions Copyright (c) 2023, Salvium (author: SRCG)
//
// All rights reserved.
//
@@ -232,21 +232,33 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
{
// miner v2 txes have their coinbase output in one single out to save space,
// and we store them as rct outputs with an identity mask
uint64_t unlock_time = 0;
if (!cryptonote::get_output_unlock_time(tx.vout[i], unlock_time)) {
LOG_PRINT_L1("Failed to get output unlock time, aborting transaction addition");
throw std::runtime_error("Unexpected error getting output unlock_time, aborting");
}
if (miner_tx && tx.version == 2)
{
cryptonote::tx_out vout = tx.vout[i];
rct::key commitment = rct::zeroCommit(vout.amount);
vout.amount = 0;
amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time,
amount_output_indices[i] = add_output(tx_hash, vout, i, unlock_time,
&commitment);
}
else
{
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, unlock_time,
tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL);
}
}
add_tx_amount_output_indices(tx_id, amount_output_indices);
// Check to see if this is a YIELD TX
if (tx.type == cryptonote::transaction_type::YIELD) {
// We now need to insert a record into the "yield_tx_data" table to record the TX
}
}
uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
@@ -255,6 +267,8 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, const std::vector<std::pair<transaction, blobdata>>& txs
, const cryptonote::network_type& nettype
, cryptonote::yield_block_info& ybi
)
{
const block &blk = blck.first;
@@ -295,6 +309,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
}
std::map<std::string, int64_t> slippage_counts;
uint64_t yield_total = 0;
if (blk.protocol_tx.version == 2)
{
num_rct_outs += blk.protocol_tx.vout.size();
@@ -333,44 +348,69 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
num_rct_outs_by_asset_type.add(asset_type, 1);
}
// Update the amount tallies by ADDING the burnt amount
// Is this a CONVERT TX?
if (tx.first.type == cryptonote::transaction_type::CONVERT) {
// Update the amount tallies by ADDING the burnt amount
if (slippage_counts.count(asset_type) == 0)
slippage_counts[asset_type] = 0;
slippage_counts[asset_type] += tx.first.amount_burnt;
}
// Is this a YIELD TX?
if (tx.first.type == cryptonote::transaction_type::YIELD) {
yield_total += tx.first.amount_burnt;
}
}
++tx_i;
}
// SRCG: This is the code that calculates the total slippage for the block
// Now convert all of the residual balances into FULM
/*
// Now convert all of the residual balances into SAL
boost::multiprecision::int128_t slippage_total_128 = 0;
uint64_t slippage_total = 0;
for (const auto& tally: slippage_counts) {
if (tally.second < 0)
throw std::runtime_error("Found a negative tally when summing the burnt/minted amounts");
uint64_t slippage_amount = 0;
if (tally.first == "FULM") {
slippage_amount = tally.second;
} else {
// Sanity check - do we have a price for this asset type in the PR?
if (blk.pricing_record.count(tally.first) == 0) {
// No price available - bail out, because block is invalid
throw std::runtime_error("Asset type is not present in available pricing record:" + tally.first);
if (blk.major_version >= HF_VERSION_ENABLE_CONVERT) {
for (const auto& tally: slippage_counts) {
boost::multiprecision::int128_t slippage_amount_128 = 0;
if (tally.first == "SAL") {
slippage_amount_128 = tally.second;
} else {
// Sanity check - do we have a price for both source asset type and SAL in the PR?
boost::multiprecision::int128_t sal_price = blk.pricing_record["SAL"];
boost::multiprecision::int128_t asset_price = blk.pricing_record[tally.first];
if (sal_price == 0) {
// No price available - bail out, because block is invalid
throw std::runtime_error("Asset type 'SAL' is not present in available pricing record");
}
if (asset_price == 0) {
// No price available - bail out, because block is invalid
throw std::runtime_error("Asset type '" + tally.first + "' is not present in available pricing record");
}
// Convert the VSD amount into SAL
boost::multiprecision::int128_t tally_128 = tally.second;
tally_128 *= asset_price;
tally_128 /= sal_price;
slippage_amount_128 = tally_128.convert_to<int64_t>();
}
// Convert the amount
//boost::multiprecision::uint128_t tally_128 = tally.second;
slippage_total_128 += slippage_amount_128;
}
if (slippage_total_128 < 0)
throw std::runtime_error("Found a negative slippage total when summing the burnt/minted amounts");
slippage_total = slippage_total_128.convert_to<uint64_t>();
} else {
// Prior to activation of conversions, the staking reward is purely a percentage of the block reward
if (blk.miner_tx.amount_burnt == 0 and prev_height != 0)
throw std::runtime_error("Staking reward is zero, but block reward is present");
slippage_total = blk.miner_tx.amount_burnt;
}
*/
TIME_MEASURE_FINISH(time1);
time_add_transaction += time1;
// call out to subclass implementation to add the block & metadata
time1 = epee::misc_utils::get_tick_count();
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash);
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, nettype, ybi);
TIME_MEASURE_FINISH(time1);
time_add_block1 += time1;
+30 -10
View File
@@ -157,7 +157,7 @@ struct txpool_tx_meta_t
{
crypto::hash max_used_block_id;
crypto::hash last_failed_id;
crypto::key_image input_k_image;
crypto::public_key return_pubkey;
crypto::public_key return_address;
crypto::public_key one_time_public_key;
uint64_t weight;
@@ -197,6 +197,14 @@ struct txpool_tx_meta_t
}
};
typedef struct yield_tx_info {
uint64_t block_height;
crypto::hash tx_hash;
uint64_t locked_coins;
crypto::public_key return_address;
crypto::public_key P_change;
crypto::public_key return_pubkey;
} yield_tx_info;
#define DBF_SAFE 1
#define DBF_FAST 2
@@ -408,16 +416,22 @@ private:
* @param cumulative_difficulty the accumulated difficulty after this block
* @param coins_generated the number of coins generated total after this block
* @param blk_hash the hash of the block
* @param slippage_total the total value (expressed in SAL coins) of all slippage for this block
* @param yield_total the total of SAL coins that have been locked for yield in this block
*/
virtual void add_block( const block& blk
, size_t block_weight
, uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, oracle::asset_type_counts& cum_rct_by_asset_type
, const crypto::hash& blk_hash
) = 0;
virtual void add_block( const block& blk,
size_t block_weight,
uint64_t long_term_block_weight,
const difficulty_type& cumulative_difficulty,
const uint64_t& coins_generated,
uint64_t num_rct_outs,
oracle::asset_type_counts& cum_rct_by_asset_type,
const crypto::hash& blk_hash,
uint64_t slippage_total,
uint64_t yield_total,
const cryptonote::network_type& nettype,
cryptonote::yield_block_info& ybi
) = 0;
/**
* @brief remove data about the top block
@@ -869,6 +883,8 @@ public:
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, const std::vector<std::pair<transaction, blobdata>>& txs
, const cryptonote::network_type& nettype
, cryptonote::yield_block_info& ybi
);
/**
@@ -1898,6 +1914,10 @@ public:
*/
virtual uint64_t get_database_size() const = 0;
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) = 0;
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) = 0;
/**
* @brief set whether or not to automatically remove logs
*
+175 -72
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2014-2023, The Monero Project
// Portions Copyright (c) 2023, Fulmo (author: SRCG)
// Portions Copyright (c) 2023, Salvium (author: SRCG)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
@@ -212,8 +212,8 @@ namespace
*
* alt_blocks block hash {block data, block blob}
*
* yield_block_data block height {}
* yield_tx_data block height {txn hash, dest address, amount}
* yield_block_data block height {slippage_coins, locked_coins, lc_total, network_health}
* yield_tx_data block height {txn hash, locked_coins, return_address}
*
* Note: where the data items are of uniform size, DUPFIXED tables have
* been used to save space. In most of these cases, a dummy "zerokval"
@@ -223,6 +223,7 @@ namespace
*
* The output_amounts table doesn't use a dummy key, but uses DUPSORT.
*/
const char* const LMDB_BLOCKS = "blocks";
const char* const LMDB_BLOCK_HEIGHTS = "block_heights";
const char* const LMDB_BLOCK_INFO = "block_info";
@@ -256,19 +257,20 @@ const char* const LMDB_CIRC_SUPPLY_TALLY = "circ_supply_tally";
/**
* We have the following information that will go into a "yield_txs" table in the blockchain:
*
* block_height (uint64_t) (this is the key field)
* ---------------------------------------------------------
* txn_hash (crypto:hash) (so we can verify)
* dest_address (crypto::key) (where to send the yield)
* amount_locked (uint64_t) (how much was locked)
* block_height (uint64_t) (this is the key field)
* ------------------------------------------------------------
* txn_hash (crypto:hash) (so we can verify)
* dest_address (crypto::key) (where to send the yield)
* amount_locked (uint64_t) (how much was locked)
*
* We also have the following information that will go into a "yield_blocks" table:
*
* block_height (uint64_t) (this is the key field)
* --------------------------------------------------------
* slippage_amount (uint64_t) (amount needed to determine yield payout for the block)
* coins_locked (uint64_t) (total number of coins locked at this height)
* network_health (uint8_t) (a fudge factor used to adjust the slippage:yield ratio dynamically)
* block_height (uint64_t) (this is the key field)
* ------------------------------------------------------------
* slippage_amount (uint64_t) (amount needed to determine yield payout for the block)
* locked_coins (uint64_t) (total number of coins locked at this height)
* locked_coins_total (uint64_t) (total number of coins locked at this height)
* network_health (uint8_t) (a fudge factor used to adjust the slippage:yield ratio dynamically)
*
* So, let's say that we have a block height h for which we want to assess the yield payments. First off,
* we are ONLY interested in making ANY payment if we have YIELD.block_height == h + 21600 (i.e. the yield
@@ -375,31 +377,12 @@ typedef struct outassettype {
uint64_t output_id;
} outassettype;
typedef struct circ_supply {
crypto::hash tx_hash;
uint32_t asset_type;
uint64_t amount_burnt;
uint64_t amount_minted;
} circ_supply;
typedef struct circ_supply_tally {
bool is_negative;
uint64_t amount_hi;
uint64_t amount_lo;
} circ_supply_tally;
typedef struct yield_tx_data {
crypto::hash tx_hash;
crypto::public_key return_address;
uint64_t amount;
} yield_tx_data;
typedef struct yield_block_data {
uint64_t slippage_total;
uint64_t locked_coins_total;
uint8_t network_health_percentage;
} yield_block_data;
std::atomic<uint64_t> mdb_txn_safe::num_active_txns{0};
std::atomic_flag mdb_txn_safe::creation_gate = ATOMIC_FLAG_INIT;
@@ -817,7 +800,69 @@ estim:
return threshold_size;
}
void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, uint64_t num_rct_outs, oracle::asset_type_counts& cum_rct_by_asset_type, const crypto::hash& blk_hash)
int BlockchainLMDB::get_yield_block_info(const uint64_t height, yield_block_info& ybi)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
// Clear the YBI, just in case
std::memset(&ybi, 0, sizeof(struct yield_block_info));
// Query for the matured YIELD_BLOCK_INFO information
TXN_PREFIX_RDONLY();
RCURSOR(yield_blocks);
MDB_val v;
MDB_val_set(k, height);
int ret = mdb_cursor_get(m_cur_yield_blocks, &k, &v, MDB_SET);
if (ret == MDB_NOTFOUND) {
LOG_ERROR("Failed to locate YBI for block height " << height);
return ret;
}
if (ret)
throw0(DB_ERROR(lmdb_error("Failed to enumerate yield block info: ", ret).c_str()));
yield_block_info *p = (yield_block_info*)v.mv_data;
ybi = *p;
// Return success to caller
return ret;
}
int BlockchainLMDB::get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
// Clear the container
yti_container.clear();
// Query for the (presumably matured) YIELD_TX_INFO information
TXN_PREFIX_RDONLY();
RCURSOR(yield_txs);
MDB_val v;
MDB_val_set(k, height);
MDB_cursor_op op = MDB_SET;
while (1)
{
int ret = mdb_cursor_get(m_cur_yield_txs, &k, &v, op);
op = MDB_NEXT;
if (ret == MDB_NOTFOUND)
break;
if (ret)
throw0(DB_ERROR(lmdb_error("Failed to enumerate yield TX info: ", ret).c_str()));
// Push result back into the container
yield_tx_info *p = (yield_tx_info*)v.mv_data;
yti_container.emplace_back(*p);
}
// Return success to caller
return 0;
}
void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, uint64_t num_rct_outs, oracle::asset_type_counts& cum_rct_by_asset_type, const crypto::hash& blk_hash, uint64_t slippage_total, uint64_t yield_total, const cryptonote::network_type& nettype, cryptonote::yield_block_info& ybi)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -847,11 +892,50 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
int result = 0;
CURSOR(yield_blocks)
yield_block_info ybi_matured, ybi_prev;
uint64_t yield_lock_period = cryptonote::get_config(nettype).YIELD_LOCK_PERIOD;
if (m_height > yield_lock_period) {
uint64_t height_matured = m_height - yield_lock_period - 1;
result = get_yield_block_info(height_matured, ybi_matured);
if (result)
{
throw0(DB_ERROR(lmdb_error("Failed to get YBI for matured height: ", result).c_str()));
}
} else {
// Chain is too new - just clear the memory of the "matured" YBI struct
std::memset(&ybi_matured, 0, sizeof(struct yield_block_info));
ybi_prev.network_health_percentage = 100;
}
if (m_height >= 1) {
// Query for the latest YIELD_BLOCK_INFO information
result = get_yield_block_info(m_height - 1, ybi_prev);
if (result)
{
throw0(DB_ERROR(lmdb_error("Failed to get YBI for last block: ", result).c_str()));
}
} else {
// Chain is too new - just clear the memory of the "prev" YBI struct
std::memset(&ybi_prev, 0, sizeof(struct yield_block_info));
ybi_prev.network_health_percentage = 100;
}
// Create the YIELD_BLOCK_INFO instance for this block
ybi.block_height = m_height;
ybi.slippage_total_this_block = slippage_total;
ybi.locked_coins_this_block = yield_total;
ybi.locked_coins_tally = ybi_prev.locked_coins_tally - ybi_matured.locked_coins_this_block + yield_total;
ybi.network_health_percentage = 100;
// Put the YBI into the table
MDB_val_set(key, m_height);
MDB_val_set(ybi_val, ybi);
result = mdb_cursor_put(m_cur_yield_blocks, &key, &ybi_val, MDB_APPEND);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to add YBI to db: ", result).c_str()));
CURSOR(blocks)
CURSOR(block_info)
CURSOR(circ_supply_tally)
// this call to mdb_cursor_put will change height()
cryptonote::blobdata block_blob(block_to_blob(blk));
@@ -915,6 +999,7 @@ void BlockchainLMDB::remove_block()
CURSOR(block_heights)
CURSOR(blocks)
CURSOR(circ_supply_tally)
CURSOR(yield_blocks)
MDB_val_copy<uint64_t> k(m_height - 1);
MDB_val h = k;
if ((result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &h, MDB_GET_BOTH)))
@@ -935,6 +1020,13 @@ void BlockchainLMDB::remove_block()
if ((result = mdb_cursor_del(m_cur_block_info, 0)))
throw1(DB_ERROR(lmdb_error("Failed to add removal of block info to db transaction: ", result).c_str()));
MDB_val_copy<uint64_t> k2(m_height - 1);
MDB_val v = k2;
if ((result = mdb_cursor_get(m_cur_yield_blocks, &k2, NULL, MDB_SET)))
throw1(BLOCK_DNE(lmdb_error("Attempting to remove yield block info that's not in the db: ", result).c_str()));
if ((result = mdb_cursor_del(m_cur_yield_blocks, 0)))
throw1(DB_ERROR(lmdb_error("Failed to add removal of yield block info to db transaction: ", result).c_str()));
}
boost::multiprecision::int128_t
@@ -1087,7 +1179,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
throw0(DB_ERROR(lmdb_error("Failed to add prunable tx prunable hash to db transaction: ", result).c_str()));
}
if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN) {
if (tx.type == cryptonote::transaction_type::BURN || tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::YIELD) {
// Get the current tally value for the source currency type
MDB_val_copy<uint64_t> source_idx(cryptonote::asset_id_from_type(tx.source_asset_type));
@@ -1096,10 +1188,10 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
boost::multiprecision::int128_t final_source_tally = source_tally - tx.amount_burnt;
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
if (source_tally == 0 && result == MDB_NOTFOUND) {
if (tx.source_asset_type == "FULM") {
if (tx.source_asset_type == "SAL") {
final_source_tally += coinbase;
} else {
throw0(DB_ERROR("burn underflow - asset balance is zero for non-FULM asset"));
throw0(DB_ERROR("burn underflow - asset balance is zero for non-SAL asset"));
}
}
write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally);
@@ -1130,7 +1222,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
boost::multiprecision::int128_t final_source_tally = source_tally + asset.second;
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
if (source_tally == 0 && result == MDB_NOTFOUND) {
if (tx.source_asset_type == "FULM") {
if (tx.source_asset_type == "SAL") {
final_source_tally += coinbase;
}
}
@@ -1141,11 +1233,22 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
// Is there yield_tx data to add?
if (tx.type == cryptonote::transaction_type::YIELD) {
// Create the object we are going to write to the database
yield_tx_data yield_data;
yield_tx_info yield_data;
yield_data.block_height = m_height;
yield_data.tx_hash = tx_hash;
yield_data.return_address = tx.return_address;
yield_data.amount = tx.amount_burnt; // SRCG - this feels as though we are bastardising the variable for an invalid purpose
yield_data.locked_coins = tx.amount_burnt;
if (tx.vin.empty())
throw0(DB_ERROR("tx.vin is empty (needed to create yield data for the PROTOCOL_TX)"));
if (tx.vin[0].type() != typeid(cryptonote::txin_to_key))
throw0(DB_ERROR("tx.vin[0] is wrong type (needed to create yield data for the PROTOCOL_TX)"));
yield_data.return_pubkey = tx.return_pubkey;
if (tx.vout.size() != 1)
throw0(DB_ERROR("tx.vout is wrong size (needed to create yield data for the PROTOCOL_TX)"));
if (!cryptonote::get_output_public_key(tx.vout[0], yield_data.P_change))
throw0(DB_ERROR("failed to get P_change from tx.vout[0] (needed to create yield data for the PROTOCOL_TX)"));
MDB_val_set(val_height, m_height);
MDB_val_set(val_yield_tx_data, yield_data);
result = mdb_cursor_put(m_cur_yield_txs, &val_height, &val_yield_tx_data, MDB_APPEND);
@@ -1173,7 +1276,6 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
CURSOR(txs_prunable_hash)
CURSOR(txs_prunable_tip)
CURSOR(tx_outputs)
CURSOR(circ_supply)
CURSOR(circ_supply_tally)
CURSOR(yield_txs)
@@ -1264,20 +1366,6 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before undoing mint =" << source_tally.str() << "\n\tTally after undoing mint =" << final_source_tally.str());
}
}
/*
// Update the circ_supply table by deleting all entries for this TX
if ((result = mdb_cursor_get(m_cur_circ_supply, &val_tx_id, NULL, MDB_SET))) {
if (result == MDB_NOTFOUND) {
LOG_PRINT_L1("failed to obtain circulating supply data - no burns / conversions made yet?");
} else {
throw1(DB_ERROR(lmdb_error("Failed to locate circulating supply for removal: ", result).c_str()));
}
} else {
result = mdb_cursor_del(m_cur_circ_supply, 0);
if (result)
throw1(DB_ERROR(lmdb_error("Failed to add removal of circulating supply to db transaction: ", result).c_str()));
}
*/
remove_tx_outputs(tip->data.tx_id, tx);
result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_id, NULL, MDB_SET);
@@ -1295,16 +1383,21 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
// Is there yield_tx data to remove?
if (tx.type == cryptonote::transaction_type::YIELD) {
// Remove any yield_tx data for this transaction
result = mdb_cursor_get(m_cur_yield_txs, &val_tx_id, NULL, MDB_SET);
if (result == MDB_NOTFOUND)
LOG_PRINT_L1("tx has no yield_tx data to remove: " << tx_hash);
else if (result)
throw1(DB_ERROR(lmdb_error("Failed to locate yield_tx data for removal: ", result).c_str()));
if (!result)
{
result = mdb_cursor_del(m_cur_yield_txs, 0);
if (result)
throw1(DB_ERROR(lmdb_error("Failed to add removal of yield_tx data to db transaction: ", result).c_str()));
MDB_val_set(val_height, m_height);
MDB_val v;
while (1) {
result = mdb_cursor_get(m_cur_yield_txs, &val_height, &v, MDB_SET);
if (result == MDB_NOTFOUND)
break;
else if (result)
throw1(DB_ERROR(lmdb_error("Failed to locate yield_tx data for removal: ", result).c_str()));
const yield_tx_info yti = *(const yield_tx_info*)v.mv_data;
if (yti.tx_hash == tx_hash) {
result = mdb_cursor_del(m_cur_yield_txs, 0);
if (result)
throw1(DB_ERROR(lmdb_error("Failed to add removal of yield_tx data to db transaction: ", result).c_str()));
break;
}
}
}
@@ -1788,6 +1881,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
lmdb_db_open(txn, LMDB_CIRC_SUPPLY_TALLY, MDB_CREATE, m_circ_supply_tally, "Failed to open db handle for m_circ_supply_tally");
lmdb_db_open(txn, LMDB_YIELD_TXS, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_yield_txs, "Failed to open db handle for m_yield_txs");
lmdb_db_open(txn, LMDB_YIELD_BLOCKS, MDB_INTEGERKEY | MDB_CREATE, m_yield_blocks, "Failed to open db handle for m_yield_blocks");
mdb_set_dupsort(txn, m_spent_keys, compare_hash32);
mdb_set_dupsort(txn, m_block_heights, compare_hash32);
@@ -1849,7 +1943,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
mdb_env_close(m_env);
m_open = false;
MFATAL("Existing lmdb database needs to be converted, which cannot be done on a read-only database.");
MFATAL("Please run fulmod once to convert the database.");
MFATAL("Please run salviumd once to convert the database.");
return;
}
// Note that there was a schema change within version 0 as well.
@@ -1991,6 +2085,8 @@ void BlockchainLMDB::reset()
throw0(DB_ERROR(lmdb_error("Failed to drop m_properties: ", result).c_str()));
if (auto result = mdb_drop(txn, m_yield_txs, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_yield_txs: ", result).c_str()));
if (auto result = mdb_drop(txn, m_yield_blocks, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_yield_blocks: ", result).c_str()));
// init with current version
MDB_val_str(k, "version");
@@ -3298,7 +3394,13 @@ std::map<std::string,uint64_t> BlockchainLMDB::get_circulating_supply() const
}
uint64_t m_coinbase = get_block_already_generated_coins(m_height-1);
LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " - mined supply for FULM = " << m_coinbase);
LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " - mined supply for SAL = " << m_coinbase);
// SRCG: For V1, we can simply return this number, because there is no other source of coins
circulating_supply["SAL"] = m_coinbase;
return circulating_supply;
/*
check_open();
TXN_PREFIX_RDONLY();
@@ -3324,9 +3426,9 @@ std::map<std::string,uint64_t> BlockchainLMDB::get_circulating_supply() const
const std::string currency_label = cryptonote::asset_type_from_id(currency_type);
boost::multiprecision::int128_t amount = import_tally_from_cst(cst);
// Check for FULM - we need to adjust the total for them
// Check for SAL - we need to adjust the total for them
if (currency_type == 0) {
// Get the current circulating supply for FULM
// Get the current circulating supply for SAL
amount += m_coinbase;
}
@@ -3337,9 +3439,10 @@ std::map<std::string,uint64_t> BlockchainLMDB::get_circulating_supply() const
// NEAC: check for empty supply tally - only happens prior to first conversion on chain
if (circulating_supply.empty()) {
circulating_supply["FULM"] = m_coinbase;
circulating_supply["SAL"] = m_coinbase;
}
return circulating_supply;
*/
}
uint64_t BlockchainLMDB::num_outputs() const
@@ -4530,7 +4633,7 @@ void BlockchainLMDB::block_rtxn_abort() const
}
uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
const std::vector<std::pair<transaction, blobdata>>& txs)
const std::vector<std::pair<transaction, blobdata>>& txs, const cryptonote::network_type& nettype, cryptonote::yield_block_info& ybi)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -4548,7 +4651,7 @@ uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t
try
{
BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, nettype, ybi);
}
catch (const DB_ERROR_TXN_START& e)
{
+20 -9
View File
@@ -341,6 +341,8 @@ public:
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, const std::vector<std::pair<transaction, blobdata>>& txs
, const cryptonote::network_type& nettype
, cryptonote::yield_block_info& ybi
);
virtual void set_batch_transactions(bool batch_transactions);
@@ -388,15 +390,19 @@ private:
void check_and_resize_for_batch(uint64_t batch_num_blocks, uint64_t batch_bytes);
uint64_t get_estimated_batch_size(uint64_t batch_num_blocks, uint64_t batch_bytes) const;
virtual void add_block( const block& blk
, size_t block_weight
, uint64_t long_term_block_weight
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, oracle::asset_type_counts& cum_rct_by_asset_type
, const crypto::hash& block_hash
);
virtual void add_block( const block& blk,
size_t block_weight,
uint64_t long_term_block_weight,
const difficulty_type& cumulative_difficulty,
const uint64_t& coins_generated,
uint64_t num_rct_outs,
oracle::asset_type_counts& cum_rct_by_asset_type,
const crypto::hash& blk_hash,
uint64_t slippage_total,
uint64_t yield_total,
const cryptonote::network_type& nettype,
cryptonote::yield_block_info& ybi
);
virtual void remove_block();
@@ -453,6 +459,9 @@ private:
//void migrate_0_1();
void cleanup_batch();
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi);
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container);
private:
MDB_env* m_env;
@@ -486,7 +495,9 @@ private:
MDB_dbi m_circ_supply;
MDB_dbi m_circ_supply_tally;
MDB_dbi m_yield_txs;
MDB_dbi m_yield_blocks;
mutable uint64_t m_cum_size; // used in batch size estimation
mutable unsigned int m_cum_count;
+9 -9
View File
@@ -157,7 +157,7 @@ endif()
set_property(TARGET blockchain_import
PROPERTY
OUTPUT_NAME "fulmo-blockchain-import")
OUTPUT_NAME "salvium-blockchain-import")
install(TARGETS blockchain_import DESTINATION bin)
monero_add_executable(blockchain_export
@@ -178,7 +178,7 @@ target_link_libraries(blockchain_export
set_property(TARGET blockchain_export
PROPERTY
OUTPUT_NAME "fulmo-blockchain-export")
OUTPUT_NAME "salvium-blockchain-export")
install(TARGETS blockchain_export DESTINATION bin)
monero_add_executable(blockchain_blackball
@@ -200,7 +200,7 @@ target_link_libraries(blockchain_blackball
set_property(TARGET blockchain_blackball
PROPERTY
OUTPUT_NAME "fulmo-blockchain-mark-spent-outputs")
OUTPUT_NAME "salvium-blockchain-mark-spent-outputs")
install(TARGETS blockchain_blackball DESTINATION bin)
@@ -222,7 +222,7 @@ target_link_libraries(blockchain_usage
set_property(TARGET blockchain_usage
PROPERTY
OUTPUT_NAME "fulmo-blockchain-usage")
OUTPUT_NAME "salvium-blockchain-usage")
install(TARGETS blockchain_usage DESTINATION bin)
monero_add_executable(blockchain_ancestry
@@ -243,7 +243,7 @@ target_link_libraries(blockchain_ancestry
set_property(TARGET blockchain_ancestry
PROPERTY
OUTPUT_NAME "fulmo-blockchain-ancestry")
OUTPUT_NAME "salvium-blockchain-ancestry")
install(TARGETS blockchain_ancestry DESTINATION bin)
monero_add_executable(blockchain_depth
@@ -264,7 +264,7 @@ target_link_libraries(blockchain_depth
set_property(TARGET blockchain_depth
PROPERTY
OUTPUT_NAME "fulmo-blockchain-depth")
OUTPUT_NAME "salvium-blockchain-depth")
install(TARGETS blockchain_depth DESTINATION bin)
monero_add_executable(blockchain_stats
@@ -285,7 +285,7 @@ target_link_libraries(blockchain_stats
set_property(TARGET blockchain_stats
PROPERTY
OUTPUT_NAME "fulmo-blockchain-stats")
OUTPUT_NAME "salvium-blockchain-stats")
install(TARGETS blockchain_stats DESTINATION bin)
monero_add_executable(blockchain_prune_known_spent_data
@@ -307,7 +307,7 @@ target_link_libraries(blockchain_prune_known_spent_data
set_property(TARGET blockchain_prune_known_spent_data
PROPERTY
OUTPUT_NAME "fulmo-blockchain-prune-known-spent-data")
OUTPUT_NAME "salvium-blockchain-prune-known-spent-data")
install(TARGETS blockchain_prune_known_spent_data DESTINATION bin)
monero_add_executable(blockchain_prune
@@ -316,7 +316,7 @@ monero_add_executable(blockchain_prune
set_property(TARGET blockchain_prune
PROPERTY
OUTPUT_NAME "fulmo-blockchain-prune")
OUTPUT_NAME "salvium-blockchain-prune")
install(TARGETS blockchain_prune DESTINATION bin)
target_link_libraries(blockchain_prune
@@ -386,7 +386,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -1219,7 +1219,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -88,7 +88,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -90,7 +90,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -487,8 +487,9 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
try
{
cryptonote::yield_block_info ybi; // This just gets discarded because we aren't looking to maintain a cache of YBI data in the import utility
uint64_t long_term_block_weight = core.get_blockchain_storage().get_next_long_term_block_weight(block_weight);
core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, ybi);
}
catch (const std::exception& e)
{
@@ -637,7 +638,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -483,7 +483,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -137,7 +137,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -175,7 +175,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -242,7 +242,7 @@ int main(int argc, char* argv[])
/*
* The default output can be plotted with GnuPlot using these commands:
set key autotitle columnhead
set title "Fulmo Blockchain Growth"
set title "Salvium Blockchain Growth"
set timefmt "%Y-%m-%d"
set xdata time
set xrange ["2014-04-17":*]
@@ -120,7 +120,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
Binary file not shown.
+2 -1
View File
@@ -110,7 +110,8 @@ namespace tools
catch(...)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(file_path, file_path + ".unportable");
data_file.close();
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
if(data_file.fail())
+1
View File
@@ -34,6 +34,7 @@
#include <iostream>
#include <vector>
#include <stdexcept>
#include <cstdint>
namespace tools {
+1 -1
View File
@@ -122,7 +122,7 @@ public:
* @brief Gets a DNS address from OpenAlias format
*
* If the address looks good, but contains one @ symbol, replace that with a .
* e.g. donate@fulmo.network becomes donate.fulmo.network
* e.g. donate@salvium.network becomes donate.salvium.network
*
* @param oa_addr OpenAlias address
*
+1 -1
View File
@@ -102,7 +102,7 @@ namespace tools
std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
{
const char *base = user ? "https://downloads.fulmo.network/" : "https://updates.fulmo.network/";
const char *base = user ? "https://downloads.salvium.network/" : "https://updates.salvium.network/";
#ifdef _WIN32
static const char *extension = strncmp(buildtag.c_str(), "source", 6) ? (strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe") : ".tar.bz2";
#elif defined(__APPLE__)
+18
View File
@@ -115,6 +115,24 @@ static int flock_exnb(int fd)
namespace tools
{
void copy_file(const std::string& from, const std::string& to)
{
using boost::filesystem::path;
#if BOOST_VERSION < 107400
// Remove this preprocessor if/else when we are bumping the boost version.
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_option::overwrite_if_exists);
#else
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_options::overwrite_existing);
#endif
}
std::function<void(int)> signal_handler::m_handler;
private_file::private_file() noexcept : m_handle(), m_filename() {}
+2
View File
@@ -67,6 +67,8 @@ namespace tools
}
};
void copy_file(const std::string& from, const std::string& to);
//! A file restricted to process owner AND process. Deletes file on destruction.
class private_file {
std::unique_ptr<std::FILE, close_file> m_handle;
+7
View File
@@ -74,6 +74,13 @@ namespace crypto {
const crypto::public_key null_pkey = crypto::public_key{};
const crypto::secret_key null_skey = crypto::secret_key{};
static inline crypto::key_image get_null_ki() {
crypto::key_image ki;
std::memset(ki.data, 0, sizeof(ki.data));
return ki;
}
const crypto::key_image null_ki = get_null_ki();
static inline unsigned char *operator &(ec_point &point) {
return &reinterpret_cast<unsigned char &>(point);
}
+2
View File
@@ -366,6 +366,8 @@ namespace crypto {
const extern crypto::public_key null_pkey;
const extern crypto::secret_key null_skey;
const extern crypto::key_image null_ki;
inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
}
+31 -68
View File
@@ -199,8 +199,10 @@ namespace cryptonote
std::vector<uint8_t> extra;
// TX type
cryptonote::transaction_type type;
// Return address (encrypted)
// Return address
crypto::public_key return_address;
// Return TX public key
crypto::public_key return_pubkey;
// Source asset type
std::string source_asset_type;
// Destination asset type (this is only necessary for CONVERT transactions)
@@ -213,16 +215,20 @@ namespace cryptonote
BEGIN_SERIALIZE()
VARINT_FIELD(version)
if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false;
VARINT_FIELD(unlock_time)
FIELD(vin)
FIELD(vout)
FIELD(extra)
VARINT_FIELD(type)
FIELD(return_address)
FIELD(source_asset_type)
FIELD(destination_asset_type)
VARINT_FIELD(amount_burnt)
VARINT_FIELD(amount_slippage_limit)
if (type != cryptonote::transaction_type::PROTOCOL) {
VARINT_FIELD(amount_burnt)
if (type != cryptonote::transaction_type::MINER) {
FIELD(return_address)
FIELD(return_pubkey)
FIELD(source_asset_type)
FIELD(destination_asset_type)
VARINT_FIELD(amount_slippage_limit)
}
}
END_SERIALIZE()
public:
@@ -236,6 +242,7 @@ namespace cryptonote
extra.clear();
type = cryptonote::transaction_type::UNSET;
return_address = crypto::null_pkey;
return_pubkey = crypto::null_pkey;
source_asset_type.clear();
destination_asset_type.clear();
amount_burnt = 0;
@@ -491,68 +498,23 @@ namespace cryptonote
return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
}
/************************************************************************/
/* */
/************************************************************************/
/*
struct asset_data {
std::string asset_type;
uint64_t spot_price;
uint64_t ma_price;
struct yield_block_info {
uint64_t block_height;
uint64_t slippage_total_this_block;
uint64_t locked_coins_this_block;
uint64_t locked_coins_tally;
uint8_t network_health_percentage;
public:
BEGIN_SERIALIZE_OBJECT()
FIELD(asset_type)
VARINT_FIELD(spot_price)
VARINT_FIELD(ma_price)
BEGIN_SERIALIZE()
VARINT_FIELD(block_height)
VARINT_FIELD(slippage_total_this_block)
VARINT_FIELD(locked_coins_this_block)
VARINT_FIELD(locked_coins_tally)
VARINT_FIELD(network_health_percentage)
END_SERIALIZE()
};
inline bool operator==(const asset_data& a, const asset_data& b) noexcept
{
return (a.asset_type == b.asset_type &&
a.spot_price == b.spot_price &&
a.ma_price == b.ma_price);
}
struct pricing_record
{
uint64_t pr_version;
std::vector<asset_data> assets;
uint64_t timestamp;
std::string signature;
public:
//! Load from epee p2p format
bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent);
//! Store in epee p2p format
bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const;
inline uint64_t operator[](const std::string& asset_type) const
{
return 0;
}
inline bool operator==(const pricing_record& other) noexcept
{
return ((pr_version == other.pr_version) &&
(assets == other.assets) &&
(timestamp == other.timestamp) &&
(signature == other.signature));
}
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(pr_version)
FIELD(assets)
VARINT_FIELD(timestamp)
FIELD(signature)
END_SERIALIZE()
};
*/
/************************************************************************/
/* */
@@ -572,7 +534,8 @@ namespace cryptonote
VARINT_FIELD(timestamp)
FIELD(prev_id)
FIELD(nonce)
FIELD(pricing_record)
if (major_version >= HF_VERSION_ENABLE_ORACLE)
FIELD(pricing_record)
END_SERIALIZE()
};
@@ -593,7 +556,7 @@ namespace cryptonote
transaction miner_tx;
/**
* Ok, the "protocol_tx" is a large part of what makes Fulmo unique, and requires a bit of explaining...
* Ok, the "protocol_tx" is a large part of what makes Salvium unique, and requires a bit of explaining...
*
* In Haven, and therefore Zephyr also, conversions take place "in-transaction". That is to say,
* amounts of coin A are burnt, and amounts of coin B are minted, and the conversion rate is known,
@@ -622,14 +585,14 @@ namespace cryptonote
* Therefore, it follows that slippage can only accurately be assessed when we know ALL of the changes
* to the above parameters that will occur at a given point in time (specifically, when the block is
* mined). There is a fundamental interdependence between each conversion TX in a given block. This
* means that, in Fulmo, you can't tell in advance precisely how much you will get minted by a given
* means that, in Salvium, you can't tell in advance precisely how much you will get minted by a given
* conversion TX until the block is mined. Instead, when creating a conversion TX, the user is asked
* to specify a minimum amount they will accept - if the transaction can satisfy that criterion when
* it is mined, the conversion will be processed and the minted amount will be sent to the user. If
* the transaction cannot satisfy the minimum minted requirement, the user will be refunded their
* money, minus a nominal transaction fee.
*
* Welcome to Fulmo, and the protocol_tx.
* Welcome to Salvium, and the protocol_tx.
* --------------------------------------
* The protocol_tx is a per-block TX (much like the miner_tx, where the block reward gets paid out).
* It is created at the time of populating the block template to be sent to the miner. Specifically,
@@ -38,6 +38,7 @@
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp>
#include "blockchain_db/blockchain_db.h"
#include "cryptonote_basic.h"
#include "difficulty.h"
#include "common/unordered_containers_boost_serialization.h"
@@ -104,12 +105,16 @@ namespace boost
inline void serialize(Archive &a, cryptonote::txout_to_key &x, const boost::serialization::version_type ver)
{
a & x.key;
a & x.asset_type;
a & x.unlock_time;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::txout_to_tagged_key &x, const boost::serialization::version_type ver)
{
a & x.key;
a & x.asset_type;
a & x.unlock_time;
a & x.view_tag;
}
@@ -162,44 +167,57 @@ namespace boost
inline void serialize(Archive &a, cryptonote::transaction_prefix &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.unlock_time;
//a & x.unlock_time;
a & x.vin;
a & x.vout;
a & x.extra;
a & x.type;
a & x.return_address;
a & x.source_asset_type;
a & x.destination_asset_type;
a & x.amount_burnt;
a & x.amount_slippage_limit;
if (x.type != cryptonote::transaction_type::MINER && x.type != cryptonote::transaction_type::PROTOCOL) {
a & x.return_address;
a & x.return_pubkey;
a & x.source_asset_type;
a & x.destination_asset_type;
a & x.amount_burnt;
a & x.amount_slippage_limit;
}
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::transaction &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.unlock_time;
//a & x.unlock_time;
a & x.vin;
a & x.vout;
a & x.extra;
a & x.type;
a & x.return_address;
a & x.source_asset_type;
a & x.destination_asset_type;
a & x.amount_burnt;
a & x.amount_slippage_limit;
if (x.version == 1)
{
a & x.signatures;
}
else
{
a & (rct::rctSigBase&)x.rct_signatures;
if (x.rct_signatures.type != rct::RCTTypeNull)
a & x.rct_signatures.p;
if (x.type != cryptonote::transaction_type::MINER && x.type != cryptonote::transaction_type::PROTOCOL) {
a & x.return_address;
a & x.return_pubkey;
a & x.source_asset_type;
a & x.destination_asset_type;
a & x.amount_burnt;
a & x.amount_slippage_limit;
if (x.version == 1)
{
a & x.signatures;
}
else
{
a & (rct::rctSigBase&)x.rct_signatures;
if (x.rct_signatures.type != rct::RCTTypeNull)
a & x.rct_signatures.p;
}
}
}
template <class Archive>
inline void serialize(Archive &a, oracle::supply_data &sd, const boost::serialization::version_type ver)
{
a & sd.sal;
a & sd.vsd;
}
template <class Archive>
inline void serialize(Archive &a, oracle::asset_data &ad, const boost::serialization::version_type ver)
{
@@ -212,11 +230,23 @@ namespace boost
inline void serialize(Archive &a, oracle::pricing_record &pr, const boost::serialization::version_type ver)
{
a & pr.pr_version;
a & pr.height;
a & pr.supply;
a & pr.assets;
a & pr.timestamp;
a & pr.signature;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::yield_block_info &ybi, const boost::serialization::version_type ver)
{
a & ybi.block_height;
a & ybi.slippage_total_this_block;
a & ybi.locked_coins_this_block;
a & ybi.locked_coins_tally;
a & ybi.network_health_percentage;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::block &b, const boost::serialization::version_type ver)
{
@@ -225,7 +255,8 @@ namespace boost
a & b.timestamp;
a & b.prev_id;
a & b.nonce;
a & b.pricing_record;
if (b.major_version >= HF_VERSION_ENABLE_ORACLE)
a & b.pricing_record;
//------------------
a & b.miner_tx;
a & b.protocol_tx;
@@ -391,7 +391,8 @@ namespace cryptonote
*/
// 1. Obtain P_change from the output (it is the subaddress public key)
crypto::public_key P_change = crypto::null_pkey;
hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, P_change);
//hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, P_change);
hwdev.derive_subaddress_public_key(out_key, recv_derivation, origin_tx_data.uniqueness, P_change);
// 2. Obtain a separate key_derivation for the _original_ P_change output
// (using the TX public key from the CONVERT TX and the sender's private view key)
@@ -408,7 +409,8 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(P_change == change_pk, false, "derived P_change public key does not match P_change");
// 5. Calculate the secret spend key "x_return"
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, real_output_index, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'");
//CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, real_output_index, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'");
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, origin_tx_data.uniqueness, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'");
in_ephemeral.sec = scalar_step1;
CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive one-time output public key 'P_return'");
CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key,
@@ -1057,10 +1059,10 @@ namespace cryptonote
std::string asset_type_from_id(const uint32_t asset_type_id)
{
switch (asset_type_id) {
case 0x46554c4d:
return "FULM";
case 0x46555344:
return "FUSD";
case 0x53414C00:
return "SAL";
case 0x56534400:
return "VSD";
case 0x4255524E:
return "BURN";
case 0x00000000:
@@ -1074,10 +1076,10 @@ namespace cryptonote
//---------------------------------------------------------------
uint32_t asset_id_from_type(const std::string asset_type)
{
if (asset_type == "FULM") {
return 0x46554c4d;
} else if (asset_type == "FUSD") {
return 0x46555344;
if (asset_type == "SAL") {
return 0x53414C00;
} else if (asset_type == "VSD") {
return 0x56534400;
} else if (asset_type == "BURN") {
return 0x4255524E;
} else if (asset_type == "") {
@@ -1089,17 +1091,17 @@ namespace cryptonote
}
//---------------------------------------------------------------
/**
* The various scenarios that are permitted for Fulmo are more extensive than
* The various scenarios that are permitted for Salvium are more extensive than
* they are for Zepyhr / Havan. Specifically, we permit:
*
* MINER_TX: (SRCG => all fees are to be paid in FULM?)
* - input txin_gen (FULM)
* - outputs txout_to_key (FULM) / txout_to_tagged_key (FULM)
* MINER_TX: (SRCG => all fees are to be paid in SAL?)
* - input txin_gen (SAL)
* - outputs txout_to_key (SAL) / txout_to_tagged_key (SAL)
*
* PROTOCOL_TX:
* - input txin_gen (FULM) --- ONLY if there are outputs
* - input txin_gen (SAL) --- ONLY if there are outputs
* - input void ("") --- ONLY if there are NO outputs
* - outputs txout_to_key (FULM, FUSD) / txout_to_tagged_key (FULM, FUSD)
* - outputs txout_to_key (SAL, VSD) / txout_to_tagged_key (SAL, VSD)
*
* BURN:
*
@@ -1121,7 +1123,7 @@ namespace cryptonote
LOG_ERROR("txin_gen detected in non-miner TX. Rejecting..");
return false;
}
source_asset_types.insert("FULM");
source_asset_types.insert("SAL");
} else if (tx.vin[i].type() == typeid(txin_to_key)) {
source_asset_types.insert(boost::get<txin_to_key>(tx.vin[i]).asset_type);
} else {
@@ -1181,7 +1183,7 @@ namespace cryptonote
// Handle miner_txs differently - full validation is performed in validate_miner_transaction()
if (is_miner_tx) {
destination = "FULM";
destination = "SAL";
} else {
// Sanity check that we only have 1 or 2 destination asset types
@@ -1200,7 +1202,7 @@ namespace cryptonote
destination = dat[0];
} else {
if (sat.size() == 2) {
if (!((dat[0] == "FULM" && dat[1] == "FUSD") || (dat[0] == "FUSD" && dat[1] == "FULM"))) {
if (!((dat[0] == "SAL" && dat[1] == "VSD") || (dat[0] == "VSD" && dat[1] == "SAL"))) {
LOG_ERROR("Impossible input asset types. Rejecting..");
return false;
}
@@ -1428,7 +1430,7 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations");
if (out_can_be_to_acc(view_tag_opt, additional_derivations[output_index], output_index, &hwdev))
{
CHECK_AND_ASSERT_MES(hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey), boost::none, "Failed to derive subaddress public key");
CHECK_AND_ASSERT_MES(hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], uniqueness, subaddress_spendkey), boost::none, "Failed to derive subaddress public key");
auto found = subaddresses.find(subaddress_spendkey);
if (found != subaddresses.end())
return subaddress_receive_info{ found->second, additional_derivations[output_index] };
@@ -1558,11 +1560,11 @@ namespace cryptonote
return "piconero";
*/
case 8:
return "fulmo";
return "sal";
case 5:
return "millifulmo";
return "millisal";
case 2:
return "microfulmo";
return "microsal";
default:
ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point);
}
@@ -59,6 +59,7 @@ namespace cryptonote
bool m_fee_too_low;
bool m_too_few_outputs;
bool m_tx_extra_too_big;
bool m_invalid_version;
};
struct block_verification_context
+56 -38
View File
@@ -51,13 +51,12 @@
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60
// MONEY_SUPPLY - total number coins to be generated
#define MONEY_SUPPLY ((uint64_t)(1800000000000000ull))
#define EMISSION_SPEED_FACTOR_PER_MINUTE (19)
#define MONEY_SUPPLY ((uint64_t)(18440000000000000ull)) // 184.4M coins * pow(10, 8)
#define EMISSION_SPEED_FACTOR_PER_MINUTE (20)
#define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)30000000) // 3 * pow(10, 7)
#define BURN_LOCK_PERIOD 0
#define CONVERT_LOCK_PERIOD 0
#define YIELD_LOCK_PERIOD 30*24*30
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size
@@ -70,7 +69,7 @@
// COIN - number of smallest units in one coin
#define COIN ((uint64_t)100000000) // pow(10, 8)
#define FEE_PER_KB_OLD ((uint64_t)1000000) // pow(10, 6)
//#define FEE_PER_KB_OLD ((uint64_t)1000000) // pow(10, 6)
#define FEE_PER_KB ((uint64_t)200000) // 2 * pow(10, 5)
#define FEE_PER_BYTE ((uint64_t)30)
#define DYNAMIC_FEE_PER_KB_BASE_FEE ((uint64_t)200000) // 2 * pow(10,5)
@@ -80,7 +79,9 @@
#define ORPHANED_BLOCKS_MAX_COUNT 100
#define PREMINE_AMOUNT ((uint64_t)90000000000000ull) // 5% of supply (9 * pow(10,13))
#define PREMINE_AMOUNT ((uint64_t)2210000000000000ull) // 12% of MONEY_SUPPLY
#define PREMINE_AMOUNT_UPFRONT ((uint64_t)650000000000000ull) // 3.4% of MONEY_SUPPLY
#define PREMINE_AMOUNT_MONTHLY ((uint64_t)65000000000000ull) // 8.6%/24 of MONEY_SUPPLY
#define DIFFICULTY_TARGET_V2 120 // seconds
#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork
@@ -163,7 +164,7 @@
#define RPC_IP_FAILS_BEFORE_BLOCK 3
#define CRYPTONOTE_NAME "fulmo"
#define CRYPTONOTE_NAME "salvium"
#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "data.mdb"
#define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME "lock.mdb"
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
@@ -210,8 +211,12 @@
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 2
#define HF_VERSION_VIEW_TAGS 2
#define HF_VERSION_2021_SCALING 2
#define HF_VERSION_ENABLE_CONVERT 2
#define HF_VERSION_ENABLE_ORACLE 2
#define HF_VERSION_SLIPPAGE_YIELD 2
#define HF_VERSION_SLIPPAGE_YIELD 3
#define TESTNET_VERSION 4
#define STAGENET_VERSION 1
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
#define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2
@@ -247,27 +252,24 @@ namespace config
uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)2000000000); // 2 * pow(10, 9)
uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8)
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x1c1a4a68; // fuLMo
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x1bda4a68; // fuLMoi
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x5bbfa4a68; // fuLMos
//uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18;
//uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 19;
//uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 42;
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x3ef318; // SaLv
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x55ef318; // SaLvi
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0xf5ef318; // SaLvs
uint16_t const P2P_DEFAULT_PORT = 19080;
uint16_t const RPC_DEFAULT_PORT = 19081;
uint16_t const ZMQ_RPC_DEFAULT_PORT = 19082;
boost::uuids::uuid const NETWORK_ID = { {
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10
} }; // Bender's nightmare
//std::string const GENESIS_TX = "023c01ff000180c09e90acbb1402ba4fcfcff0d4a91441c87615e514be3938e173179ac34a7fc98c0286e7320fdc0446554c4d3c0000000000000021019e809607ceda9ae7ae6755e05bcdc9c555acc8e95dcaede402eca1166a032e1a0100000000000000000000000000000000000000000000000000000000000000000000000000";
//M2
//std::string const GENESIS_TX = "023c01ff000180c09e90acbb1402ae6cfc932cab508d92455942efbb2ec5a8632e33ff6bcac04a8e31be271efb8c0446554c4d3c0000000000000021015a71ac0441d4ee3f321df5ffd4bd3d0f04755152e7e6485a3b6c965356cb92ed0100000000000000000000000000000000000000000000000000000000000000000000000000";
//M3
std::string const GENESIS_TX = "020001ff000180c09e90acbb1402fd5c232c394e6ea4e99672cae46d28b0dc56e1883637fc9445018b1e282901000446554c4d3c0000000000000021017c46e0a3f65ec0de58a78350f6dceddd77a9a1bebf94685009a7c7e5e2cdc8ce0100000000000000000000000000000000000000000000000000000000000000000000000000";
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x82, 0x53, 0x41, 0x4C, 0xFF, 0x10
} };
std::string const GENESIS_TX = "0201ff000180c0d0c7bbbff60302c33815291bac1b6d5c685129c1de6383e550688d005a3ce2b66a96b7050579060353414c3c00000000000000210149117096744b390170a118fc14d8f13edb40a7d2764fde3043d9fbae7d2efdef010000";
uint32_t const GENESIS_NONCE = 10000;
const uint64_t YIELD_LOCK_PERIOD = 30*24*30;
std::string const TREASURY_ADDRESS = "SaLvdVTaMJp5hrGv2rDWzaCrM6Wrq2T4tNBPX8kvuAJv7iUiYNy4vceFskGRAawnBDiqZ9jWYXZmWemRnEKtWmNMeuSXZg6jwtx";
// Hash domain separators
const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof";
const char HASH_KEY_BULLETPROOF_PLUS_EXPONENT[] = "bulletproof_plus";
@@ -295,7 +297,7 @@ namespace config
// Multisig
const uint32_t MULTISIG_MAX_SIGNERS{16};
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.fulmo.network:8443", "oracle.fulmo.network:8443", "oracle.fulmo.network:8443"}};
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.network:8443", "oracle.salvium.network:8443", "oracle.salvium.network:8443"}};
std::string const ORACLE_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n"
"MIIDRDCCAjYGByqGSM44BAEwggIpAoIBAQCZP7IJ5PcNvGbWiEqAioKF9wViVxEN\n"
@@ -325,46 +327,54 @@ namespace config
*/
namespace testnet
{
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0xa8bfa4a68; // fuLMot
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x9dbfa4a68; // fuLMoti
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x5a3bfa4a68; // fuLMots
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x15beb318; // SaLvT
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0xd055eb318; // SaLvTi
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0xa59eb318; // SaLvTs
uint16_t const P2P_DEFAULT_PORT = 29080;
uint16_t const RPC_DEFAULT_PORT = 29081;
uint16_t const ZMQ_RPC_DEFAULT_PORT = 29082;
boost::uuids::uuid const NETWORK_ID = { {
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x11
} }; // Bender's daydream
std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1";
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x82, 0x53, 0x41, 0x4C, 0x00, 0x01
} };
std::string const GENESIS_TX = "0201ff000180c0d0c7bbbff6030204f30dcd0ffa78009527d89113e104e49486b14abd230a03becca67c15b2bbba0353414c3c000000000000002101b26ac50aaf94cf9df780e2c57bd61983123d96325fffa8e6603665a255d3810c010000";
uint32_t const GENESIS_NONCE = 10001;
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.fulmo.network:8443", "oracle.fulmo.network:8443", "oracle.fulmo.network:8443"}};
const uint64_t YIELD_LOCK_PERIOD = 20;
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.network:8443", "oracle.salvium.network:8443", "oracle.salvium.network:8443"}};
std::string const ORACLE_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
"-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS = "SaLvTyLFta9BiAXeUfFkKvViBkFt4ay5nEUBpWyDKewYggtsoxBbtCUVqaBjtcCDyY1euun8Giv7LLEgvztuurLo5a6Km1zskZn36";
}
namespace stagenet
{
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0xafb7a4a68; // fuLMoS
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0xa4b7a4a68; // fuLMoSi
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0xabb7a4a68; // fuLMoSt
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x149eb318; // SaLvS
uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0xf343eb318; // SaLvSi
uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x2d47eb318; // SaLvSs
uint16_t const P2P_DEFAULT_PORT = 39080;
uint16_t const RPC_DEFAULT_PORT = 39081;
uint16_t const ZMQ_RPC_DEFAULT_PORT = 39082;
boost::uuids::uuid const NETWORK_ID = { {
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x12
} }; // Bender's daydream
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x82, 0x53, 0x41, 0x4C, 0x80, 0x01
} };
std::string const GENESIS_TX = "013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b";
uint32_t const GENESIS_NONCE = 10002;
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.fulmo.network:8443", "oracle.fulmo.network:8443", "oracle.fulmo.network:8443"}};
const uint64_t YIELD_LOCK_PERIOD = 20;
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.network:8443", "oracle.salvium.network:8443", "oracle.salvium.network:8443"}};
std::string const ORACLE_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
"-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A";
}
}
@@ -391,6 +401,8 @@ namespace cryptonote
uint32_t const GENESIS_NONCE;
std::array<std::string, 3> const ORACLE_URLS;
std::string const ORACLE_PUBLIC_KEY;
uint64_t YIELD_LOCK_PERIOD;
std::string TREASURY_ADDRESS;
};
inline const config_t& get_config(network_type nettype)
{
@@ -405,7 +417,9 @@ namespace cryptonote
::config::GENESIS_TX,
::config::GENESIS_NONCE,
::config::ORACLE_URLS,
::config::ORACLE_PUBLIC_KEY
::config::ORACLE_PUBLIC_KEY,
::config::YIELD_LOCK_PERIOD,
::config::TREASURY_ADDRESS
};
static const config_t testnet = {
::config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX,
@@ -418,7 +432,9 @@ namespace cryptonote
::config::testnet::GENESIS_TX,
::config::testnet::GENESIS_NONCE,
::config::testnet::ORACLE_URLS,
::config::testnet::ORACLE_PUBLIC_KEY
::config::testnet::ORACLE_PUBLIC_KEY,
::config::testnet::YIELD_LOCK_PERIOD,
::config::testnet::TREASURY_ADDRESS
};
static const config_t stagenet = {
::config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX,
@@ -431,7 +447,9 @@ namespace cryptonote
::config::stagenet::GENESIS_TX,
::config::stagenet::GENESIS_NONCE,
::config::stagenet::ORACLE_URLS,
::config::stagenet::ORACLE_PUBLIC_KEY
::config::stagenet::ORACLE_PUBLIC_KEY,
::config::stagenet::YIELD_LOCK_PERIOD,
::config::stagenet::TREASURY_ADDRESS
};
switch (nettype)
{
+303 -70
View File
@@ -459,13 +459,13 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
return false;
}
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
{
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
if (seedhash != crypto::null_hash)
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
}
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
if (seedhash != crypto::null_hash)
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
// Preload the yield_block_info cache
rebuild_ybi_cache();
return true;
}
//------------------------------------------------------------------
@@ -581,11 +581,8 @@ void Blockchain::pop_blocks(uint64_t nblocks)
if (stop_batch)
m_db->batch_stop();
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
{
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
}
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
}
//------------------------------------------------------------------
// This function tells BlockchainDB to remove the top block from the
@@ -622,6 +619,9 @@ block Blockchain::pop_block_from_blockchain()
throw;
}
// Rebuild the YBI cache
rebuild_ybi_cache();
// make sure the hard fork object updates its current version
m_hardfork->on_block_popped(1);
@@ -1280,8 +1280,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
}
}
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
return true;
@@ -1449,6 +1448,18 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
money_in_use += o.amount;
partial_block_reward = false;
switch (version) {
case HF_VERSION_BULLETPROOF_PLUS:
if (b.miner_tx.amount_burnt > 0) {
CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt");
money_in_use += b.miner_tx.amount_burnt;
}
break;
default:
assert(false);
break;
}
uint64_t median_weight = m_current_block_cumul_weight_median;
if (!get_block_reward(median_weight, cumulative_block_weight, already_generated_coins, base_reward, version))
{
@@ -1564,6 +1575,23 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
}
*/
}
// Now consider the payouts from matured YIELD transactions
// Get the data for the block that matured this time
cryptonote::yield_block_info ybi_matured;
uint64_t lock_period = get_config(m_nettype).YIELD_LOCK_PERIOD;
uint64_t start_height = (height > lock_period) ? height - lock_period - 1 : 0;
bool ok = get_ybi_entry(start_height, ybi_matured);
if (ok && ybi_matured.locked_coins_this_block > 0) {
// Iterate over the cached data for block yield, calculating the yield payouts due
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
if (!calculate_yield_payouts(start_height, yield_payouts)) {
LOG_ERROR("Failed to obtain yield payout information - aborting");
return false;
}
}
return true;
}
@@ -1717,12 +1745,10 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
uint64_t from_block_height = cryptonote::get_block_height(prev_block);
height = from_block_height + 1;
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
{
uint64_t next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
seed_hash = get_block_id_by_height(seed_height);
}
uint64_t next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
seed_hash = get_block_id_by_height(seed_height);
}
else
{
@@ -1779,12 +1805,10 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
median_weight = m_current_block_cumul_weight_limit / 2;
diffic = get_difficulty_for_next_block();
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
{
uint64_t next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
seed_hash = get_block_id_by_height(seed_height);
}
uint64_t next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
seed_hash = get_block_id_by_height(seed_height);
}
b.timestamp = time(NULL);
@@ -1795,15 +1819,25 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
}
std::map<std::string, uint64_t> circ_supply = get_db().get_circulating_supply();
oracle::pricing_record pr;
if (!get_pricing_record(pr, circ_supply, b.timestamp)) {
LOG_ERROR("Creating block template: error: failed to get pricing record");
return false;
}
// Copy the returned record
b.pricing_record = pr;
// Check if we are supposed to be obtaining PRs from the Oracle
if (b.major_version >= HF_VERSION_ENABLE_ORACLE) {
// Yep - go get the pricing records
oracle::pricing_record pr;
if (!get_pricing_record(pr, circ_supply, b.timestamp)) {
LOG_ERROR("Creating block template: error: failed to get pricing record");
return false;
}
// Copy the returned record
b.pricing_record = pr;
} else {
// Nope - set it to an empty record - it won't get serialised anyway
b.pricing_record = oracle::pricing_record();
}
CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
@@ -1826,7 +1860,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
*/
std::vector<txpool_tx_meta_t> protocol_metadata;
std::vector<cryptonote::protocol_data_entry> protocol_entries;
if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.major_version, pr, circ_supply, protocol_metadata))
if (!m_tx_pool.fill_block_template(b, median_weight, already_generated_coins, txs_weight, fee, expected_reward, b.major_version, b.pricing_record, circ_supply, protocol_metadata))
{
return false;
}
@@ -1842,13 +1876,47 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
entry.return_address = meta.return_address;
entry.type = meta.tx_type;
entry.P_change = meta.one_time_public_key;
entry.input_k_image = meta.input_k_image;
entry.return_pubkey = meta.return_pubkey;
protocol_entries.push_back(entry);
}
// Check to see if there are any matured YIELD TXs
uint64_t yield_lock_period = get_config(m_nettype).YIELD_LOCK_PERIOD;
uint64_t start_height = (height > yield_lock_period) ? height - yield_lock_period - 1 : 0;
cryptonote::yield_block_info ybi_matured;
bool ok = get_ybi_entry(start_height, ybi_matured);
if (ok && ybi_matured.locked_coins_this_block > 0) {
// Iterate over the cached data for block yield, calculating the yield payouts due
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
if (!calculate_yield_payouts(start_height, yield_payouts)) {
LOG_ERROR("Failed to obtain yield payout information - aborting");
return false;
}
// Create the protocol_metadata entries here
for (const auto& yield_entry: yield_payouts) {
cryptonote::protocol_data_entry entry;
entry.amount_burnt = yield_entry.second;
entry.amount_minted = 0;
entry.amount_slippage_limit = 0;
entry.source_asset = "SAL";
entry.destination_asset = "SAL";
entry.return_address = yield_entry.first.return_address;
entry.type = cryptonote::transaction_type::YIELD;
entry.P_change = yield_entry.first.P_change;
entry.return_pubkey = yield_entry.first.return_pubkey;
protocol_entries.push_back(entry);
}
}
// Time to construct the protocol_tx
uint64_t protocol_fee = 0;
bool ok = construct_protocol_tx(height, protocol_fee, b.protocol_tx, protocol_entries, circ_supply, pr, b.major_version);
address_parse_info treasury_address_info;
ok = cryptonote::get_account_address_from_str(treasury_address_info, m_nettype, get_config(m_nettype).TREASURY_ADDRESS);
CHECK_AND_ASSERT_MES(ok, false, "Failed to obtain treasury address info");
ok = construct_protocol_tx(height, protocol_fee, b.protocol_tx, protocol_entries, circ_supply, b.pricing_record, miner_address, treasury_address_info.address, b.major_version);
CHECK_AND_ASSERT_MES(ok, false, "Failed to construct protocol tx");
pool_cookie = m_tx_pool.cookie();
@@ -1986,12 +2054,9 @@ bool Blockchain::get_miner_data(uint8_t& major_version, uint64_t& height, crypto
major_version = m_hardfork->get_ideal_version(height);
seed_hash = crypto::null_hash;
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
{
uint64_t seed_height, next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
seed_hash = get_block_id_by_height(seed_height);
}
uint64_t seed_height, next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
seed_hash = get_block_id_by_height(seed_height);
difficulty = get_difficulty_for_next_block();
median_weight = m_current_block_cumul_weight_median;
@@ -2162,30 +2227,25 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
crypto::hash proof_of_work;
memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data));
if (b.major_version >= RX_BLOCK_VERSION)
crypto::hash seedhash = null_hash;
uint64_t seedheight = rx_seedheight(bei.height);
// seedblock is on the alt chain somewhere
if (alt_chain.size() && alt_chain.front().height <= seedheight)
{
crypto::hash seedhash = null_hash;
uint64_t seedheight = rx_seedheight(bei.height);
// seedblock is on the alt chain somewhere
if (alt_chain.size() && alt_chain.front().height <= seedheight)
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
{
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
if (it->height == seedheight+1)
{
if (it->height == seedheight+1)
{
seedhash = it->bl.prev_id;
break;
}
seedhash = it->bl.prev_id;
break;
}
} else
{
seedhash = get_block_id_by_height(seedheight);
}
get_altblock_longhash(bei.bl, proof_of_work, seedhash);
} else
{
get_block_longhash(this, bei.bl, proof_of_work, bei.height, 0);
seedhash = get_block_id_by_height(seedheight);
}
get_altblock_longhash(bei.bl, proof_of_work, seedhash);
if(!check_hash(proof_of_work, current_diff))
{
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
@@ -2689,8 +2749,8 @@ bool Blockchain::get_pricing_record(oracle::pricing_record &pr, std::map<std::st
std::shuffle(oracle_urls.begin(), oracle_urls.end(), std::default_random_engine(crypto::rand<unsigned>()));
std::string url = "/price?height=" + std::to_string(height);
//url += "&timestamp=" + boost::lexical_cast<std::string>(timestamp) + "&version=" + std::to_string(hf_version);
url += "&fulm=" + (circ_supply.count("FULM") ? std::to_string(circ_supply["FULM"]) : "0");
url += "&fusd=" + (circ_supply.count("FUSD") ? std::to_string(circ_supply["FUSD"]) : "0");
url += "&sal=" + (circ_supply.count("SAL") ? std::to_string(circ_supply["SAL"]) : "0");
url += "&vsd=" + (circ_supply.count("VSD") ? std::to_string(circ_supply["VSD"]) : "0");
for (size_t n = 0; n < oracle_urls.size(); n++) {
http_client.set_server(oracle_urls[n], boost::none, epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
r = epee::net_utils::invoke_http_json(url, req, res, http_client, std::chrono::seconds(10), "GET");
@@ -2706,19 +2766,19 @@ bool Blockchain::get_pricing_record(oracle::pricing_record &pr, std::map<std::st
res.pr = oracle::pricing_record();
}
// Copy the PR
pr = res.pr;
// Verify the signature
if (pr.verifySignature(get_config(m_nettype).ORACLE_PUBLIC_KEY)) {
if (res.pr.verifySignature(get_config(m_nettype).ORACLE_PUBLIC_KEY)) {
// Copy the PR
pr = res.pr;
} else {
LOG_PRINT_L0("Failed to verify signature of pricing record from Oracle - returning empty PR");
pr = oracle::pricing_record();
}
std::string sig_hex;
for (size_t i = 0; i < 64; i++) {
for (size_t i = 0; i < pr.signature.size(); i++) {
std::stringstream ss;
ss << std::hex << std::setw(2) << std::setfill('0') << (0xff & pr.signature[i]);
ss << std::hex << std::setw(2) << std::setfill('0') << (0xff & pr.signature.at(i));
sig_hex += ss.str();
}
LOG_PRINT_L1("Received pricing record - signature = " << sig_hex);
@@ -4227,6 +4287,170 @@ uint64_t Blockchain::get_adjusted_time(uint64_t height) const
return (adjusted_current_block_ts < median_ts ? adjusted_current_block_ts : median_ts);
}
//------------------------------------------------------------------
bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vector<std::pair<yield_tx_info, uint64_t>>& yield_container)
{
LOG_PRINT_L3("Blockchain::" << __func__);
// Clear the yield payout amounts
yield_container.empty();
// Get the YIELD TX information for matured staked coins
std::vector<cryptonote::yield_tx_info> yield_entries;
// We get the yield_tx_info from the block _before_ they started to accrue yield
int yield_tx_result = m_db->get_yield_tx_info(start_height, yield_entries);
if (!yield_entries.size()) {
// Report error and abort
LOG_ERROR("calculate_yield_payouts() called, but no yield TXs found at height " << start_height << " - aborting");
return false;
}
// Get the YBI information for the 21,600 blocks that the matured TX(s), we can calculate yield
for (const auto& entry: yield_entries) {
yield_container.emplace_back(std::make_pair(entry, entry.locked_coins));
}
// Iterate over the cached yield_block_info data
uint64_t yield_lock_period = cryptonote::get_config(m_nettype).YIELD_LOCK_PERIOD;
for (uint64_t idx = start_height+1; idx <= start_height + yield_lock_period; ++idx) {
// Get the next block
if (m_yield_block_info_cache.count(idx) == 0) {
LOG_ERROR("failed to locate yield information for block height " << idx <<" - aborting");
return false;
}
yield_block_info ybi = m_yield_block_info_cache[idx];
if (ybi.slippage_total_this_block == 0) continue;
boost::multiprecision::int128_t slippage_128 = ybi.slippage_total_this_block;
// Get the total number of coins locked at this height
boost::multiprecision::int128_t locked_total_128 = ybi.locked_coins_tally;
// Iterate over the yield_container, adding each proportion of the yield
for (auto& entry: yield_container) {
boost::multiprecision::int128_t locked_coins_128 = entry.first.locked_coins;
boost::multiprecision::int128_t yield_128 = (slippage_128 * locked_coins_128) / locked_total_128;
entry.second += yield_128.convert_to<uint64_t>();
}
}
// Return success to caller
return true;
}
//------------------------------------------------------------------
bool Blockchain::rebuild_ybi_cache()
{
LOG_PRINT_L3("Blockchain::" << __func__);
// If we need to (re)build the cache, we need to pull the data from the blockchain directly
// Clear the existing cache
m_yield_block_info_cache.clear();
// Get the size that the cache should be when fully populated (could be less than the lock period if the chain is young)
uint64_t height = m_db->height();
uint64_t yield_lock_period = cryptonote::get_config(m_nettype).YIELD_LOCK_PERIOD;
uint64_t ybi_cache_expected_size = std::min(height, yield_lock_period+1);
// Now get this number of entries from the blockchain
for (uint64_t idx = height - ybi_cache_expected_size; idx < height; ++idx) {
// Get the specified YBI entry
yield_block_info ybi;
int result = m_db->get_yield_block_info(idx, ybi);
if (result) {
// Request failed - report error and bail out
LOG_ERROR("failed to retrieve YBI entry for height " << idx << " - aborting");
return false;
}
// Store in the map
m_yield_block_info_cache[idx] = ybi;
}
// Return success to caller
return true;
}
//------------------------------------------------------------------
bool Blockchain::validate_ybi_cache()
{
LOG_PRINT_L3("Blockchain::" << __func__);
// Get the size that the cache should be if fully populated
uint64_t height = m_db->height();
uint64_t yield_lock_period = cryptonote::get_config(m_nettype).YIELD_LOCK_PERIOD;
uint64_t ybi_cache_expected_size = std::min(height, yield_lock_period + 1);
if (m_yield_block_info_cache.size() != ybi_cache_expected_size) {
// It's not the right size - report error and bail out
LOG_ERROR("YBI cache is incorrect size - should be " << ybi_cache_expected_size << ", but found " << m_yield_block_info_cache.size() << " - aborting");
return false;
}
// It's the right size - check we have the correct limits
if (m_yield_block_info_cache.count(height - 1) == 0) {
// Missing the latest block - report error and bail out
LOG_ERROR("Failed to locate YBI entry for height " << (height - 1) << " - aborting");
return false;
}
if (m_yield_block_info_cache.count(height - ybi_cache_expected_size) == 0) {
// Missing the latest block - report error and bail out
LOG_ERROR("Failed to locate YBI entry for height " << (height - ybi_cache_expected_size) << " - aborting");
return false;
}
return true;
}
//------------------------------------------------------------------
bool Blockchain::get_ybi_cache(std::map<uint64_t, yield_block_info>& ybi_cache)
{
LOG_PRINT_L3("Blockchain::" << __func__);
// Clear the provided container
ybi_cache.clear();
// Make sure the cache is fully populated and up to date
if (!validate_ybi_cache()) {
LOG_PRINT_L1("yield information cache is invalid - rebuilding cache");
if (!rebuild_ybi_cache()) {
LOG_ERROR("Failed to rebuild yield information cache - aborting");
return false;
}
}
// Copy the cache
ybi_cache = m_yield_block_info_cache;
return true;
}
//------------------------------------------------------------------
bool Blockchain::get_ybi_entry(const uint64_t height, cryptonote::yield_block_info& ybi)
{
LOG_PRINT_L3("Blockchain::" << __func__);
// Clear the provided container
std::memset(&ybi, 0, sizeof(struct cryptonote::yield_block_info));
// Make sure the cache is fully populated and up to date
if (!validate_ybi_cache()) {
LOG_PRINT_L1("yield information cache is invalid - rebuilding cache");
if (!rebuild_ybi_cache()) {
LOG_ERROR("Failed to rebuild yield information cache - aborting");
return false;
}
}
// Check to see if the height is in the cache
if (m_yield_block_info_cache.count(height) == 0) {
LOG_ERROR("Failed to locate yield block info for height " << height << " - aborting");
return false;
}
// Copy the specified entry
ybi = m_yield_block_info_cache[height];
return true;
}
//------------------------------------------------------------------
//TODO: revisit, has changed a bit on upstream
bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b, uint64_t& median_ts) const
{
@@ -4630,7 +4854,6 @@ leave:
return_tx_to_pool(txs);
goto leave;
}
TIME_MEASURE_FINISH(vmt);
TIME_MEASURE_START(gcs);
@@ -4645,7 +4868,6 @@ leave:
return_tx_to_pool(txs);
goto leave;
}
TIME_MEASURE_FINISH(vpt);
size_t block_weight;
@@ -4675,7 +4897,19 @@ leave:
{
uint64_t long_term_block_weight = get_next_long_term_block_weight(block_weight);
cryptonote::blobdata bd = cryptonote::block_to_blob(bl);
new_height = m_db->add_block(std::make_pair(std::move(bl), std::move(bd)), block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs);
yield_block_info new_ybi;
std::memset(&new_ybi, 0, sizeof(struct yield_block_info));
new_height = m_db->add_block(std::make_pair(std::move(bl), std::move(bd)), block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs, m_nettype, new_ybi);
// Update the YBI cache data
uint64_t yield_lock_period = cryptonote::get_config(m_nettype).YIELD_LOCK_PERIOD;
uint64_t ybi_cache_expected_size = std::min(new_height, yield_lock_period);
if (new_height > yield_lock_period) {
if (m_yield_block_info_cache.count(new_height - yield_lock_period - 2) != 0) {
m_yield_block_info_cache.erase(new_height - yield_lock_period - 2);
}
}
m_yield_block_info_cache[new_ybi.block_height] = new_ybi;
}
catch (const KEY_IMAGE_EXISTS& e)
{
@@ -4747,8 +4981,7 @@ leave:
for (const auto& notifier: m_block_notifiers)
notifier(new_height - 1, {std::addressof(bl), 1});
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
return true;
}
+56
View File
@@ -746,6 +746,8 @@ namespace cryptonote
*/
uint64_t get_current_cumulative_block_weight_median() const;
int get_yield_info(const uint64_t start_height, const uint64_t end_height, std::vector<std::pair<yield_tx_info, uint64_t>>& yield_container);
/**
* @brief gets the difficulty of the block with a given height
*
@@ -1145,6 +1147,55 @@ namespace cryptonote
*/
uint64_t get_adjusted_time(uint64_t height) const;
/**
* calculate the yield payouts
*
* @return TRUE if the payouts were calculated successfully, FALSE otherwise
*/
bool calculate_yield_payouts(const uint64_t start_height, std::vector<std::pair<yield_tx_info, uint64_t>>& yield_payouts);
/**
* @brief get the complete YBI cache
*
* Retrieve the YBI local cache.
* If the cache is out of date, the cache will (attempt to) be rebuilt
* before being returned.
*
* @return TRUE if the call is successful, FALSE otherwise
*/
bool get_ybi_cache(std::map<uint64_t, yield_block_info>& ybi_cache);
/**
* @brief get the YBI entry for a particular height from the cache
*
* Retrieve the YBI entry for the specified height from the local cache.
* If the cache is out of date, the cache will (attempt to) be rebuilt
* before the entry is obtained.
*
* @return TRUE if the entry was located and returned, FALSE otherwise
*/
bool get_ybi_entry(const uint64_t height, cryptonote::yield_block_info& ybi);
/**
* (re)build the yield_block_info cache from the blockchain
*
* @return TRUE if the cache rebuilt correctly, FALSE otherwise
*/
bool rebuild_ybi_cache();
/**
* @brief validate the yield_block_info cache
*
* Checks that the m_yield_block_info_cache is fully populated by
* checking the size of the map, and making sure it has the most recent entry
* and the oldest expected entry as well
*
* Returns TRUE if the cache is intact, full, and up-to-date, FALSE otherwise
*
* @return TRUE if cache is OK, FALSE otherwise
*/
bool validate_ybi_cache();
#ifndef IN_UNIT_TESTS
private:
#endif
@@ -1250,6 +1301,11 @@ namespace cryptonote
// cache for verifying transaction RCT non semantics
mutable rct_ver_cache_t m_rct_ver_cache;
/**
* @brief hashmap linking blockchain height to YBI struct for that height
*/
std::map<uint64_t, yield_block_info> m_yield_block_info_cache;
/**
* @brief collects the keys for all outputs being "spent" as an input
*
+23 -7
View File
@@ -518,10 +518,16 @@ namespace cryptonote
LOG_ERROR("Failed to initialize a database");
return false;
}
if (m_nettype == STAGENET) {
folder /= std::to_string(STAGENET_VERSION);
} else if (m_nettype == TESTNET) {
folder /= std::to_string(TESTNET_VERSION);
}
folder /= db->get_db_name();
MGINFO("Loading blockchain from folder " << folder.string() << " ...");
const std::string filename = folder.string();
// default to fast:async:1 if overridden
blockchain_db_sync_mode sync_mode = db_defaultsync;
@@ -925,7 +931,12 @@ namespace cryptonote
tx_info[n].result = false;
break;
case rct::RCTTypeSimple:
if (!rct::verRctSemanticsSimple(rv, tx_info[n].tx->amount_burnt))
if (!rct::verRctSemanticsSimple(rv,
tx_info[n].tx->type == cryptonote::transaction_type::BURN ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::CONVERT ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::YIELD ? tx_info[n].tx->amount_burnt :
0
))
{
MERROR_VER("rct signature semantics check failed");
set_semantics_failed(tx_info[n].tx_hash);
@@ -978,7 +989,7 @@ namespace cryptonote
}
if (!rvv.empty())
{
LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
LOG_PRINT_L1("Verifying one TX at a time");
ret = false;
for (size_t n = 0; n < tx_info.size(); ++n)
{
@@ -986,7 +997,12 @@ namespace cryptonote
continue;
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus)
continue;
if (!rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures, tx_info[n].tx->amount_burnt))
if (!rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures,
tx_info[n].tx->type == cryptonote::transaction_type::BURN ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::CONVERT ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::YIELD ? tx_info[n].tx->amount_burnt :
0
))
{
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
@@ -1850,7 +1866,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::check_updates()
{
static const char software[] = "monero";
static const char software[] = "salvium";
#ifdef BUILD_TAG
static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
static const char subdir[] = "cli"; // because it can never be simple
@@ -1870,7 +1886,7 @@ namespace cryptonote
if (!tools::check_updates(software, buildtag, version, hash))
return false;
if (tools::vercmp(version.c_str(), MONERO_VERSION) <= 0)
if (tools::vercmp(version.c_str(), SALVIUM_VERSION) <= 0)
{
m_update_available = false;
return true;
+279 -110
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2014-2022, The Monero Project
// Portions Copyright (c) 2023, Fulmo (author: SRCG)
// Portions Copyright (c) 2023, Salvium (author: SRCG)
//
// All rights reserved.
//
@@ -151,29 +151,19 @@ namespace cryptonote
rate = COIN;
return true;
}
if (from_asset == "FULM") {
// FULM as source
if (to_asset not_eq "FUSD") {
// Invalid conversion - abort
LOG_ERROR("Invalid conversion (" << from_asset << "," << to_asset << ") - aborting");
return false;
}
// Scale to FUSD
rate = pr["FUSD"];
} else if (from_asset == "FUSD") {
// FUSD as source
if (to_asset not_eq "FULM") {
// Invalid conversion - abort
LOG_ERROR("Invalid conversion (" << from_asset << "," << to_asset << ") - aborting");
return false;
}
// Scale to FULM
boost::multiprecision::uint128_t rate_128 = COIN;
rate_128 *= COIN;
rate_128 /= pr["FUSD"];
rate = rate_128.convert_to<uint64_t>();
rate -= (rate % 10000);
if ((from_asset == "SAL" && to_asset != "VSD") ||
(from_asset == "VSD" && to_asset != "SAL")) {
// Invalid conversion - abort
LOG_ERROR("Invalid conversion (" << from_asset << "," << to_asset << ") - aborting");
return false;
}
// Scale to correct value
boost::multiprecision::uint128_t rate_128 = COIN;
rate_128 *= pr[from_asset];
rate_128 /= pr[to_asset];
rate = rate_128.convert_to<uint64_t>();
rate -= (rate % 10000);
return true;
}
//---------------------------------------------------------------
@@ -207,18 +197,12 @@ namespace cryptonote
// Apply slippage to the burnt amount
amount_slippage = amount_burnt >> 5; // (1/32)
if (hf_version >= HF_VERSION_SLIPPAGE_YIELD) {
// Apply slippage to the burnt amount
amount_slippage = amount_burnt >> 5; // (1/32)
// Check that the slippage is acceptable
if (amount_slippage > amount_slippage_limit) {
// Bail out with no conversion
LOG_PRINT_L1("Unable to convert - slippage limit was too low");
amount_minted = 0;
return true;
}
// Check that the slippage is acceptable
if (amount_slippage > amount_slippage_limit) {
// Bail out with no conversion
LOG_PRINT_L1("Unable to convert - slippage limit was too low");
amount_minted = 0;
return true;
}
// Work out the converted amount
@@ -234,11 +218,13 @@ namespace cryptonote
std::vector<protocol_data_entry>& protocol_data,
std::map<std::string, uint64_t> circ_supply,
const oracle::pricing_record& pr,
const account_public_address &miner_address,
const account_public_address &treasury_address,
const uint8_t hf_version) {
// A vector to contain all of the additional _tx_secret_keys_
//std::vector<crypto::secret_key>& additional_tx_keys;
// Clear the TX contents
tx.set_null();
tx.type = cryptonote::transaction_type::PROTOCOL;
@@ -246,9 +232,6 @@ namespace cryptonote
// Force the TX type to 2
tx.version = 2;
// Clear the unlock_time
tx.unlock_time = 0;
keypair txkey = keypair::generate(hw::get_device("default"));
add_tx_pub_key_to_extra(tx, txkey.pub);
if (!sort_tx_extra(tx.extra, tx.extra))
@@ -268,6 +251,7 @@ namespace cryptonote
// Calculate the slippage for the output amounts
LOG_PRINT_L2("Creating protocol_tx...");
uint64_t slippage_total = 0;
std::vector<crypto::public_key> additional_tx_public_keys;
for (auto const& entry: protocol_data) {
if (entry.destination_asset == "BURN") {
@@ -275,7 +259,7 @@ namespace cryptonote
continue;
}
// CONVERT TX
/*
// Create a secret TX key (= s)
crypto::secret_key s = keypair::generate(hw::get_device("default")).sec;
//additional_tx_keys.push_back(s);
@@ -309,6 +293,7 @@ namespace cryptonote
r = crypto::derive_subaddress_public_key(out_eph_public_key, derivation_syF, output_index, P_change_verify);
CHECK_AND_ASSERT_MES(r, false, "while creating protocol_tx outs: failed sanity check calling derive_subaddress_public_key(" << out_eph_public_key << ", " << derivation_syF << ", " << key_y << ", " << P_change_verify << ")");
CHECK_AND_ASSERT_MES(entry.P_change == P_change_verify, false, "while creating protocol_tx outs: failed sanity check (keys do not match)");
*/
/*
LOG_ERROR("***************************************************************************************");
LOG_ERROR("output_index : " << output_index);
@@ -322,40 +307,108 @@ namespace cryptonote
LOG_ERROR("P_change_ver : " << P_change_verify);
LOG_ERROR("***************************************************************************************");
*/
// Now calculate the slippage, and decide if it is going to be converted or refunded
uint64_t amount_slippage = 0, amount_minted = 0;
bool ok = cryptonote::calculate_conversion(entry.source_asset, entry.destination_asset, entry.amount_burnt, entry.amount_slippage_limit, amount_minted, amount_slippage, circ_supply, pr, hf_version);
if (!ok) {
LOG_ERROR("failed to calculate slippage when trying to build protocol_tx");
return false;
}
if (amount_minted == 0) {
// REFUND
LOG_PRINT_L2("Conversion TX refunded - slippage too high");
txin_gen_totals[entry.source_asset] += entry.amount_burnt;
if (entry.type == cryptonote::transaction_type::CONVERT) {
// Now calculate the slippage, and decide if it is going to be converted or refunded
uint64_t amount_slippage = 0, amount_minted = 0;
bool ok = cryptonote::calculate_conversion(entry.source_asset, entry.destination_asset, entry.amount_burnt, entry.amount_slippage_limit, amount_minted, amount_slippage, circ_supply, pr, hf_version);
if (!ok) {
LOG_ERROR("failed to calculate slippage when trying to build protocol_tx");
return false;
}
if (amount_minted == 0) {
// REFUND
LOG_PRINT_L2("Conversion TX refunded - slippage too high");
txin_gen_totals[entry.source_asset] += entry.amount_burnt;
// Create the TX output for this refund
tx_out out;
//cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
} else {
// CONVERTED
LOG_PRINT_L2("Conversion TX submitted - converted " << print_money(entry.amount_burnt) << " " << entry.source_asset << " to " << print_money(amount_minted) << " " << entry.destination_asset << "(slippage " << print_money(amount_slippage) << ")");
txin_gen_totals[entry.destination_asset] += amount_minted;
// Add the slippage to our total for the block
if (entry.source_asset == "SAL") {
slippage_total += amount_slippage;
} else {
// Convert the slippage into a SAL amount so we can pay a proportion to the miner
uint64_t conversion_rate = 0, amount_slippage_converted = 0;
ok = get_conversion_rate(pr, entry.source_asset, entry.destination_asset, conversion_rate);
CHECK_AND_ASSERT_MES(ok, false, "Failed to get conversion rate for miner payout");
ok = get_converted_amount(conversion_rate, amount_slippage, amount_slippage_converted);
CHECK_AND_ASSERT_MES(ok, false, "Failed to get converted slippage amount for miner payout");
slippage_total += amount_slippage_converted;
}
// Create the TX output for this conversion
tx_out out;
//cryptonote::set_tx_out(amount_minted, entry.destination_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
cryptonote::set_tx_out(amount_minted, entry.destination_asset, 0, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
}
} else if (entry.type == cryptonote::transaction_type::YIELD) {
// PAYOUT
LOG_PRINT_L2("Yield TX payout submitted " << entry.amount_burnt << entry.source_asset);
txin_gen_totals[entry.source_asset] += entry.amount_burnt;
// Create the TX output for this refund
tx_out out;
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
tx.vout.push_back(out);
} else {
// CONVERTED
LOG_PRINT_L2("Conversion TX submitted - converted " << entry.amount_burnt << entry.source_asset << " to " << amount_minted << entry.destination_asset << "(slippage " << amount_slippage << ")");
txin_gen_totals[entry.destination_asset] += amount_minted;
// Create the TX output for this conversion
tx_out out;
cryptonote::set_tx_out(amount_minted, entry.destination_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
//cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
}
}
// Add in all of the additional TX pubkeys we need to process the payments
add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys);
if (slippage_total > 0) {
// Add a payout for the miner
uint64_t slippage_miner = slippage_total / 5;
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
// Calculate the uniqueness
crypto::key_image k_image;
ec_scalar uniqueness;
CHECK_AND_ASSERT_MES(calculate_uniqueness(tx.type, k_image, height, ((size_t)-1), uniqueness), false, "while constructing protocol_tx: failed to calculate uniqueness");
r = crypto::derive_public_key(derivation, uniqueness, miner_address.m_spend_public_key, out_eph_public_key);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
// TODO: create the YIELD outputs
tx_out out_miner;
cryptonote::set_tx_out(slippage_miner, "SAL", 0, out_eph_public_key, false, crypto::view_tag{}, out_miner);
tx.vout.push_back(out_miner);
// Add a payout for the treasury
crypto::key_derivation derivation_treasury = AUTO_VAL_INIT(derivation_treasury);
crypto::public_key out_eph_public_key_treasury = AUTO_VAL_INIT(out_eph_public_key_treasury);
r = crypto::generate_key_derivation(treasury_address.m_view_public_key, txkey.sec, derivation_treasury);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << treasury_address.m_view_public_key << ", " << txkey.sec << ")");
r = crypto::derive_public_key(derivation_treasury, uniqueness, treasury_address.m_spend_public_key, out_eph_public_key_treasury);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
uint64_t slippage_treasury = slippage_miner >> 1;
tx_out out_treasury;
cryptonote::set_tx_out(slippage_treasury, "SAL", 0, out_eph_public_key_treasury, false, crypto::view_tag{}, out_treasury);
tx.vout.push_back(out_treasury);
}
// Create the txin_gen now
txin_gen in;
@@ -426,18 +479,49 @@ namespace cryptonote
crypto::view_tag view_tag;
if (use_view_tags)
crypto::derive_view_tag(derivation, 0, view_tag);
tx_out out;
cryptonote::set_tx_out(amount, "FULM", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, out_eph_public_key, use_view_tags, view_tag, out);
tx.vout.push_back(out);
// Should we award some of the block reward to the stakers?
if (height != 0) {
// Different forks take a different proportion of the block_reward for stakers
switch (hard_fork_version) {
case HF_VERSION_BULLETPROOF_PLUS:
// MVP - subtract 20% that will be rewarded to staking users
CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero");
tx.amount_burnt = amount / 5;
amount -= tx.amount_burnt;
break;
default:
assert(false);
}
tx_out out;
cryptonote::set_tx_out(amount, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, out_eph_public_key, use_view_tags, view_tag, out);
tx.vout.push_back(out);
} else {
// Genesis TX - create the necessary distribution for Salvium seed funds
tx_out out;
cryptonote::set_tx_out(PREMINE_AMOUNT, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, out_eph_public_key, use_view_tags, view_tag, out);
tx.vout.push_back(out);
/*
tx_out out;
cryptonote::set_tx_out(PREMINE_AMOUNT_UPFRONT, "SAL", CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, out_eph_public_key, use_view_tags, view_tag, out);
tx.vout.push_back(out);
for (size_t i=1; i<=24; ++i) {
tx_out out_monthly;
cryptonote::set_tx_out(PREMINE_AMOUNT_MONTHLY, "SAL", i*21600, out_eph_public_key, use_view_tags, view_tag, out_monthly);
tx.vout.push_back(out_monthly);
}
*/
}
CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward);
tx.version = 2;
//lock
tx.unlock_time = 0;//height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
tx.vin.push_back(in);
tx.invalidate_hashes();
@@ -483,8 +567,6 @@ namespace cryptonote
buf.height = height;
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
LOG_ERROR("*** DOMAIN = " << buf.domain_separator << ", HEIGHT = " << height);
} else if (type == cryptonote::transaction_type::PROTOCOL) {
// Sanity checks
@@ -555,21 +637,17 @@ namespace cryptonote
assert(false);
}
/*
// Print out the uniqueness
crypto::public_key pk_uniq;
std::memcpy(pk_uniq.data, uniqueness.data, sizeof(crypto::public_key));
LOG_ERROR("*** UNIQUENESS : " << pk_uniq);
*/
return true;
}
//---------------------------------------------------------------
bool get_return_address(const size_t tx_version, // needed in case we change implementation down the line
const cryptonote::transaction_type& tx_type, // needed because TRANSFER needs to use F point instead of return_address and TX pubkey
const crypto::ec_scalar& uniqueness,
const cryptonote::account_keys &sender_account_keys, // needed to calculate pretty much anything
const crypto::public_key &P_change, // one-time public key from CONVERT/YIELD change
const crypto::public_key &txkey_pub, // public TX key from CONVERT/YIELD TX
crypto::public_key& F, // OUTPUT
crypto::public_key& F, // OUTPUT return address OTPK
crypto::public_key& F_txkey_pub, // OUTPUT TX pub key
hw::device& hwdev // hardware device to use (usually a software dev)
) {
@@ -599,7 +677,7 @@ namespace cryptonote
}
*/
// Now generate the return address
// Now generate the return address EC point
// F = (y^-1).a.P_change
// First, we need to produce the multiplicative inverse of the scalar "y" (aka "y^-1")
@@ -617,22 +695,49 @@ namespace cryptonote
// Sanity check that we can reverse the invert safely
rct::key key_aP_change = rct::pk2rct(pk_aP_change);
rct::key key_test = rct::scalarmultKey(key_aP_change, key_inv_y);
rct::key key_verify = rct::scalarmultKey(key_test, key_y);
rct::key key_F = rct::scalarmultKey(key_aP_change, key_inv_y);
rct::key key_verify = rct::scalarmultKey(key_F, key_y);
CHECK_AND_ASSERT_MES(key_verify == key_aP_change, false, "at get_return_address: failed to verify invert() function with smK() approach");
F = rct::rct2pk(key_test);
/*
// From this point forward, we are departing from the original "return address" scheme
// Create a secret TX key (= s)
crypto::secret_key s = keypair::generate(hw::get_device("default")).sec;
// Now add the correct TX public key (= sP_change)
// This has to be done using smK() call because of g_k_d() performing a torsion clear
F_txkey_pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(P_change), rct::sk2rct(s)));
// Calculate the actual return address, because the field we already have is actually the TX pubkey to use
// return address = Hs(syF || i)G + P_change = Hs(saP_change || i)G + P_change
// Generate the uniqueness for the input
crypto::public_key syF = rct::rct2pk(rct::scalarmultKey(rct::scalarmultKey(key_F, key_y), rct::sk2rct(s)));
crypto::key_derivation derivation_syF = AUTO_VAL_INIT(derivation_syF);
std::memcpy(derivation_syF.data, syF.data, sizeof(crypto::key_derivation));
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
r = crypto::derive_public_key(derivation_syF, uniqueness, P_change, out_eph_public_key);
CHECK_AND_ASSERT_MES(r, false, "while creating protocol_tx outs: failed to derive_public_key(" << derivation_syF << ", " << key_y << ", "<< P_change << ")");
// Sanity checks
crypto::public_key P_change_verify = crypto::null_pkey;
r = crypto::derive_subaddress_public_key(out_eph_public_key, derivation_syF, uniqueness, P_change_verify);
CHECK_AND_ASSERT_MES(r, false, "while creating protocol_tx outs: failed sanity check calling derive_subaddress_public_key(" << out_eph_public_key << ", " << derivation_syF << ", " << key_y << ", " << P_change_verify << ")");
CHECK_AND_ASSERT_MES(P_change == P_change_verify, false, "while creating protocol_tx outs: failed sanity check (keys do not match)");
// All is well - copy the return address
F = out_eph_public_key;
LOG_ERROR("*****************************************************************************");
LOG_ERROR("uniqueness: " << uniqueness.data);
//LOG_ERROR("uniqueness: " << uniqueness.data);
LOG_ERROR("txkey_pub : " << txkey_pub);
LOG_ERROR("a : " << sender_account_keys.m_view_secret_key);
LOG_ERROR("s : " << s);
LOG_ERROR("y : " << key_y);
LOG_ERROR("P_change : " << P_change);
LOG_ERROR("aP_change : " << pk_aP_change);
LOG_ERROR("F : " << F);
LOG_ERROR("*****************************************************************************");
*/
return true;
}
@@ -703,7 +808,6 @@ namespace cryptonote
} else {
tx.version = 2;
}
tx.unlock_time = 0;//unlock_time;
tx.extra = extra;
crypto::public_key txkey_pub;
@@ -896,6 +1000,7 @@ namespace cryptonote
uint64_t summary_outs_money = 0;
//fill outputs
size_t output_index = 0;
size_t change_index = 0;
for(const tx_destination_entry& dst_entr: destinations)
{
CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount);
@@ -907,8 +1012,20 @@ namespace cryptonote
// Do not create outputs that are for the destination asset type - discard them as unused
if (dst_entr.asset_type == dest_asset) {
tx.amount_burnt += dst_entr.amount;
tx.amount_slippage_limit = dst_entr.slippage_limit;
continue;
}
} else if (tx_type == cryptonote::transaction_type::YIELD) {
// Do not create outputs that are staked for yield - discard them as unused
if (!dst_entr.is_change) {
tx.amount_burnt += dst_entr.amount;
continue;
}
}
// Check to see if this is the change output
if (dst_entr.is_change) {
change_index = output_index;
}
// Get the uniqueness for this TX
@@ -931,6 +1048,8 @@ namespace cryptonote
summary_outs_money += dst_entr.amount;
}
CHECK_AND_ASSERT_MES(additional_tx_public_keys.size() == additional_tx_keys.size(), false, "Internal error creating additional public keys");
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_additional_pub_keys));
// Is this a CONVERT tx?
if (tx_type == cryptonote::transaction_type::CONVERT) {
@@ -943,17 +1062,52 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(calculate_uniqueness(tx.type, k_image, 0, 0, uniqueness), false, "Failed to calculate uniqueness for the transaction");
// Get the output public key for the change output
crypto::public_key P_change;
crypto::public_key P_change = crypto::null_pkey;
CHECK_AND_ASSERT_MES(tx.vout.size() == 1, false, "Internal error - too many outputs for CONVERT tx");
CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(tx.vout[0], P_change), false, "Internal error - failed to get TX change output public key");
CHECK_AND_ASSERT_MES(P_change != crypto::null_pkey, false, "Internal error - not found TX change output for CONVERT tx");
// Now generate the return address
CHECK_AND_ASSERT_MES(get_return_address(tx.version, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, hwdev), false, "Failed to get protocol destination address");
// Now generate the return address and TX pubkey
CHECK_AND_ASSERT_MES(get_return_address(tx.version, tx.type, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, tx.return_pubkey, hwdev), false, "Failed to get protocol destination address");
} else if (tx_type == cryptonote::transaction_type::YIELD) {
// Get the uniqueness for this TX - must be output zero we are interested in for a CONVERT or YIELD TX
CHECK_AND_ASSERT_MES(!tx.vin.empty(), false, "tx.vin[] is empty");
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), false, "incorrect tx.vin[0] type for YIELD TX");
crypto::key_image k_image = boost::get<cryptonote::txin_to_key>(tx.vin[0]).k_image;
ec_scalar uniqueness;
CHECK_AND_ASSERT_MES(calculate_uniqueness(tx.type, k_image, 0, 0, uniqueness), false, "Failed to calculate uniqueness for the transaction");
// Get the output public key for the change output
crypto::public_key P_change = crypto::null_pkey;
CHECK_AND_ASSERT_MES(tx.vout.size() == 1, false, "Internal error - incorrect number of outputs for YIELD tx");
CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(tx.vout[0], P_change), false, "Internal error - failed to get TX change output public key");
CHECK_AND_ASSERT_MES(P_change != crypto::null_pkey, false, "Internal error - not found TX change output for YIELD tx");
// Now generate the return address and TX pubkey
CHECK_AND_ASSERT_MES(get_return_address(tx.version, tx.type, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, tx.return_pubkey, hwdev), false, "Failed to get protocol destination address");
} else if (tx_type == cryptonote::transaction_type::TRANSFER) {
// Get the uniqueness for this TX
CHECK_AND_ASSERT_MES(!tx.vin.empty(), false, "tx.vin[] is empty");
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), false, "incorrect tx.vin[0] type for TRANSFER TX");
crypto::key_image k_image = boost::get<cryptonote::txin_to_key>(tx.vin[0]).k_image;
ec_scalar uniqueness;
CHECK_AND_ASSERT_MES(calculate_uniqueness(tx.type, k_image, 0, 0, uniqueness), false, "Failed to calculate uniqueness for the transaction");
// Get the output public key for the change output
crypto::public_key P_change = crypto::null_pkey;
CHECK_AND_ASSERT_MES(tx.vout.size() == 2, false, "Internal error - incorrect number of outputs (!=2) for TRANSFER tx");
CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(tx.vout[change_index], P_change), false, "Internal error - failed to get TX change output public key");
CHECK_AND_ASSERT_MES(P_change != crypto::null_pkey, false, "Internal error - not found TX change output for TRANSFER tx");
// Now generate the return address and TX pubkey
CHECK_AND_ASSERT_MES(get_return_address(tx.version, tx.type, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, tx.return_pubkey, hwdev), false, "Failed to get protocol destination address");
}
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_additional_pub_keys));
LOG_PRINT_L2("tx pubkey: " << txkey_pub);
LOG_PRINT_L2("return tx pubkey: " << tx.return_pubkey);
if (need_additional_txkeys)
{
LOG_PRINT_L2("additional tx pubkeys: ");
@@ -1127,9 +1281,29 @@ namespace cryptonote
if (sources[i].rct)
boost::get<txin_to_key>(tx.vin[i]).amount = 0;
}
for (size_t i = 0; i < tx.vout.size(); ++i)
tx.vout[i].amount = 0;
std::vector<bool> zero_masks;
zero_masks.reserve(tx.vout.size());
for (size_t i = 0; i < tx.vout.size(); ++i) {
if (tx.type == cryptonote::transaction_type::YIELD) {
uint64_t unlock_time = 0;
bool ok = get_output_unlock_time(tx.vout[i], unlock_time);
if (!ok) {
LOG_ERROR("failed to get output asset type for tx.vout[" << i << "]");
return false;
}
if (unlock_time == 0) {
zero_masks.emplace_back(false);
} else {
zero_masks.emplace_back(true);
}
} else {
zero_masks.emplace_back(false);
}
// Clear the amount in the output
tx.vout[i].amount = 0;
}
crypto::hash tx_prefix_hash;
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
rct::ctkeyV outSk;
@@ -1141,6 +1315,7 @@ namespace cryptonote
tx_type,
source_asset,
destination_asset_types,
zero_masks,
inamounts,
outamounts,
fee,
@@ -1247,22 +1422,16 @@ namespace cryptonote
epee::string_tools::hex_to_pod(longhash_202612, res);
return true;
}
if (major_version >= RX_BLOCK_VERSION)
crypto::hash hash;
if (pbc != NULL)
{
crypto::hash hash;
if (pbc != NULL)
{
const uint64_t seed_height = rx_seedheight(height);
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
} else
{
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
}
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
} else {
const int pow_variant = major_version >= 7 ? major_version - 6 : 0;
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
const uint64_t seed_height = rx_seedheight(height);
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
} else
{
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
}
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
return true;
}
+7 -5
View File
@@ -62,10 +62,10 @@ namespace cryptonote
std::string destination_asset;
uint8_t type;
crypto::public_key P_change;
crypto::key_image input_k_image;
crypto::public_key return_pubkey;
};
bool construct_protocol_tx(const size_t height, uint64_t& protocol_fee, transaction& tx, std::vector<protocol_data_entry>& protocol_data, std::map<std::string, uint64_t> circ_supply, const oracle::pricing_record& pr, const uint8_t hf_version);
bool construct_protocol_tx(const size_t height, uint64_t& protocol_fee, transaction& tx, std::vector<protocol_data_entry>& protocol_data, std::map<std::string, uint64_t> circ_supply, const oracle::pricing_record& pr, const account_public_address &miner_address, const account_public_address &treasury_address, const uint8_t hf_version);
//---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
bool construct_protocol_tx(size_t height, transaction& tx, size_t max_outs = 999, uint8_t hard_fork_version = 1);
@@ -111,15 +111,16 @@ namespace cryptonote
{
std::string original;
uint64_t amount; //money
uint64_t slippage_limit; //percentage of slippage permitted
account_public_address addr; //destination address
std::string asset_type;
bool is_subaddress;
bool is_integrated;
bool is_change;
tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)), asset_type("FULM"), is_subaddress(false), is_integrated(false), is_change(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { }
tx_destination_entry() : amount(0), slippage_limit(0), addr(AUTO_VAL_INIT(addr)), asset_type("SAL"), is_subaddress(false), is_integrated(false), is_change(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { }
std::string address(network_type nettype, const crypto::hash &payment_id) const
{
@@ -139,6 +140,7 @@ namespace cryptonote
BEGIN_SERIALIZE_OBJECT()
FIELD(original)
VARINT_FIELD(amount)
VARINT_FIELD(slippage_limit)
FIELD(addr)
FIELD(asset_type)
FIELD(is_subaddress)
+8 -1
View File
@@ -139,6 +139,13 @@ namespace cryptonote
{
const bool kept_by_block = (tx_relay == relay_method::block);
if(tx.type == cryptonote::transaction_type::CONVERT && version < HF_VERSION_ENABLE_CONVERT)
{
tvc.m_verifivation_failed = true;
tvc.m_invalid_version = true;
return false;
}
// this should already be called with that lock, but let's make it explicit for clarity
CRITICAL_REGION_LOCAL(m_transactions_lock);
@@ -379,7 +386,7 @@ namespace cryptonote
if (!ok)
return false;
meta.one_time_public_key = change_output_public_key;
meta.input_k_image = boost::get<cryptonote::txin_to_key>(tx.vin[0]).k_image;
meta.return_pubkey = tx.return_pubkey;
if (!insert_key_images(tx, id, tx_relay))
return false;
+2 -1
View File
@@ -51,6 +51,7 @@ namespace cryptonote
TRANSFER = 3,
CONVERT = 4,
BURN = 5,
YIELD = 6
YIELD = 6,
RETURN = 7
};
}
+1 -1
View File
@@ -71,5 +71,5 @@ target_link_libraries(daemon
${Blocks})
set_property(TARGET daemon
PROPERTY
OUTPUT_NAME "fulmod")
OUTPUT_NAME "salviumd")
install(TARGETS daemon DESTINATION bin)
+1 -1
View File
@@ -35,7 +35,7 @@
namespace daemon_args
{
std::string const WINDOWS_SERVICE_NAME = "Fulmo Daemon";
std::string const WINDOWS_SERVICE_NAME = "Salvium Daemon";
const command_line::arg_descriptor<std::string, false, true, 2> arg_config_file = {
"config-file"
+1 -1
View File
@@ -412,7 +412,7 @@ bool t_command_server::apropos(const std::vector<std::string>& args)
std::string t_command_server::get_commands_str()
{
std::stringstream ss;
ss << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
ss << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
ss << "Commands: " << std::endl;
std::string usage = m_command_lookup.get_usage();
boost::replace_all(usage, "\n", "\n ");
+2 -2
View File
@@ -40,7 +40,7 @@
namespace daemonize
{
std::string const t_executor::NAME = "Fulmo Daemon";
std::string const t_executor::NAME = "Salvium Daemon";
void t_executor::init_options(
boost::program_options::options_description & configurable_options
@@ -58,7 +58,7 @@ namespace daemonize
boost::program_options::variables_map const & vm
)
{
LOG_PRINT_L0("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised");
LOG_PRINT_L0("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised");
return t_daemon{vm, public_rpc_port};
}
+6 -4
View File
@@ -241,7 +241,7 @@ int main(int argc, char const * argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Usage: " + std::string{argv[0]} + " [options|settings] [daemon_command...]" << std::endl << std::endl;
std::cout << visible_options << std::endl;
return 0;
@@ -250,7 +250,7 @@ int main(int argc, char const * argv[])
// Monero Version
if (command_line::get_arg(vm, command_line::arg_version))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
return 0;
}
@@ -264,7 +264,9 @@ int main(int argc, char const * argv[])
// OS
if (command_line::get_arg(vm, daemon_args::arg_print_genesis_tx))
{
print_genesis_tx_hex(cryptonote::MAINNET);
const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
print_genesis_tx_hex(testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET);
return 0;
}
@@ -351,7 +353,7 @@ int main(int argc, char const * argv[])
tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency));
// logging is now set up
MGINFO("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")");
MGINFO("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")");
// If there are positional options, we're running a daemon command
{
+1 -1
View File
@@ -100,7 +100,7 @@ namespace daemonizer
}
else
{
//LOG_PRINT_L0("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
//LOG_PRINT_L0("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
return executor.run_interactive(vm);
}
}
+1 -1
View File
@@ -181,7 +181,7 @@ namespace daemonizer
}
else // interactive
{
//LOG_PRINT_L0("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
//LOG_PRINT_L0("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
if (command_line::has_arg(vm, arg_non_interactive))
return executor.run_non_interactive(vm);
else
+3 -3
View File
@@ -46,7 +46,7 @@ target_link_libraries(cn_deserialize
set_property(TARGET cn_deserialize
PROPERTY
OUTPUT_NAME "monero-utils-deserialize")
OUTPUT_NAME "salvium-utils-deserialize")
set(object_sizes_sources
@@ -67,7 +67,7 @@ target_link_libraries(object_sizes
set_property(TARGET object_sizes
PROPERTY
OUTPUT_NAME "monero-utils-object-sizes")
OUTPUT_NAME "salvium-utils-object-sizes")
set(dns_checks_sources
@@ -89,5 +89,5 @@ target_link_libraries(dns_checks
set_property(TARGET dns_checks
PROPERTY
OUTPUT_NAME "monero-utils-dns-checks")
OUTPUT_NAME "salvium-utils-dns-checks")
+1 -1
View File
@@ -103,7 +103,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
+1 -1
View File
@@ -121,7 +121,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
+1 -1
View File
@@ -50,5 +50,5 @@ add_dependencies(gen_multisig
version)
set_property(TARGET gen_multisig
PROPERTY
OUTPUT_NAME "fulmo-gen-trusted-multisig")
OUTPUT_NAME "salvium-gen-trusted-multisig")
install(TARGETS gen_multisig DESTINATION bin)
+1 -1
View File
@@ -45,5 +45,5 @@ add_dependencies(gen_ssl_cert
version)
set_property(TARGET gen_ssl_cert
PROPERTY
OUTPUT_NAME "fulmo-gen-ssl-cert")
OUTPUT_NAME "salvium-gen-ssl-cert")
install(TARGETS gen_ssl_cert DESTINATION bin)
+2 -2
View File
@@ -121,13 +121,13 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 0;
}
if (command_line::get_arg(vm, command_line::arg_version))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
return 0;
}
+5 -5
View File
@@ -36,26 +36,26 @@ const hardfork_t mainnet_hard_forks[] = {
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 1000, which is on or around the 20th of March, 2016. Fork time finalised on 2015-09-20. No fork voting occurs for the v2 fork.
{ 2, 1000, 0, 1442763710 },
//{ 2, 1000, 0, 1442763710 },
};
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
const uint64_t mainnet_hard_fork_version_1_till = 1000;
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
const hardfork_t testnet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 1000, which is on or around the 23rd of November, 2015. Fork time finalised on 2015-11-20. No fork voting occurs for the v2 fork.
{ 1, 1000, 0, 1445355000 },
//{ 2, 1000, 0, 1445355000 },
};
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = 1000;
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
const hardfork_t stagenet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// versions 2-7 in rapid succession from March 13th, 2018
{ 2, 1000, 0, 1521000000 },
//{ 2, 1000, 0, 1521000000 },
};
const size_t num_stagenet_hard_forks = sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]);
+1 -1
View File
@@ -100,7 +100,7 @@ namespace multisig
cryptonote::keypair in_ephemeral;
//crypto::hash uniqueness = crypto::cn_fast_hash(reinterpret_cast<void*>(&real_output_index), sizeof(size_t));
// Populate this struct if you want to make use of multisig for Fulmo!!!
// Populate this struct if you want to make use of multisig for Salvium!!!
assert(false);
cryptonote::origin_data origin_tx_data;
+3 -4
View File
@@ -109,7 +109,7 @@ static bool compute_keys_for_sources(
if (src.real_output >= src.outputs.size())
return false;
// Populate this struct if you want to make use of multisig for Fulmo!!!
// Populate this struct if you want to make use of multisig for Salvium!!!
assert(false);
cryptonote::origin_data origin_tx_data;
@@ -514,7 +514,7 @@ static bool set_tx_outputs(const rct::keyV& output_public_keys, cryptonote::tran
const std::size_t num_destinations = output_public_keys.size();
unsigned_tx.vout.resize(num_destinations);
for (std::size_t i = 0; i < num_destinations; ++i)
cryptonote::set_tx_out(0, "FULM", 0, rct::rct2pk(output_public_keys[i]), false, crypto::view_tag{}, unsigned_tx.vout[i]);
cryptonote::set_tx_out(0, "SAL", 0, rct::rct2pk(output_public_keys[i]), false, crypto::view_tag{}, unsigned_tx.vout[i]);
return true;
}
@@ -536,7 +536,7 @@ static bool set_tx_outputs_with_view_tags(
"multisig signing protocol: internal error, view tag size mismatch.");
unsigned_tx.vout.resize(num_destinations);
for (std::size_t i = 0; i < num_destinations; ++i)
cryptonote::set_tx_out(0, "FULM", 0, rct::rct2pk(output_public_keys[i]), true, view_tags[i], unsigned_tx.vout[i]);
cryptonote::set_tx_out(0, "SAL", 0, rct::rct2pk(output_public_keys[i]), true, view_tags[i], unsigned_tx.vout[i]);
return true;
}
@@ -866,7 +866,6 @@ bool tx_builder_ringct_t::init(
// misc. fields
unsigned_tx.version = 2; //rct = 2
unsigned_tx.unlock_time = unlock_time;
// sort inputs
sort_sources(sources);
+13 -13
View File
@@ -31,7 +31,7 @@
namespace oracle {
const std::vector<std::string> ASSET_TYPES = {"FULM", "FUSD", "BURN"};
const std::vector<std::string> ASSET_TYPES = {"SAL", "VSD", "BURN"};
class asset_type_counts
{
@@ -39,23 +39,23 @@ namespace oracle {
public:
// Fields
uint64_t FULM;
uint64_t FUSD;
uint64_t SAL;
uint64_t VSD;
uint64_t BURN;
asset_type_counts() noexcept
: FULM(0)
, FUSD(0)
: SAL(0)
, VSD(0)
, BURN(0)
{
}
uint64_t operator[](const std::string asset_type) const noexcept
{
if (asset_type == "FULM") {
return FULM;
} else if (asset_type == "FUSD") {
return FUSD;
if (asset_type == "SAL") {
return SAL;
} else if (asset_type == "VSD") {
return VSD;
} else if (asset_type == "BURN") {
return BURN;
}
@@ -65,10 +65,10 @@ namespace oracle {
void add(const std::string asset_type, const uint64_t val)
{
if (asset_type == "FULM") {
FULM += val;
} else if (asset_type == "FUSD") {
FUSD += val;
if (asset_type == "SAL") {
SAL += val;
} else if (asset_type == "VSD") {
VSD += val;
} else if (asset_type == "BURN") {
BURN += val;
}
+25 -23
View File
@@ -54,12 +54,12 @@ namespace oracle
struct supply_data_serialized
{
uint64_t FULM;
uint64_t FUSD;
uint64_t SAL;
uint64_t VSD;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(FULM)
KV_SERIALIZE(FUSD)
KV_SERIALIZE(SAL)
KV_SERIALIZE(VSD)
END_KV_SERIALIZE_MAP()
};
@@ -85,20 +85,26 @@ namespace oracle
pricing_record::pricing_record() noexcept
: pr_version(0)
, height(0)
, supply()
, assets()
, timestamp(0)
, signature()
{
}
pricing_record::~pricing_record() noexcept
{
}
bool supply_data::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
{
supply_data_serialized in{};
if (in._load(src, hparent))
{
// Copy everything into the local instance
fulm = in.FULM;
fusd = in.FUSD;
sal = in.SAL;
vsd = in.VSD;
return true;
}
// Report error here?
@@ -107,8 +113,8 @@ namespace oracle
bool supply_data::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const
{
assert(false);
return true;
const supply_data_serialized out{sal, vsd};
return out.store(dest, hparent);
}
bool asset_data::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
@@ -128,8 +134,8 @@ namespace oracle
bool asset_data::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const
{
assert(false);
return true;
const asset_data_serialized out{asset_type, spot_price, ma_price};
return out.store(dest, hparent);
}
bool pricing_record::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent)
@@ -145,10 +151,12 @@ namespace oracle
timestamp = in.timestamp;
// Signature arrives in HEX format, but needs to be used in BINARY format - convert it here
signature.resize(in.signature.length() >> 1);
for (unsigned int i = 0; i < in.signature.length(); i += 2) {
signature.resize(0);
assert(in.signature.size()%2 == 0);
signature.reserve(in.signature.size() >> 1);
for (unsigned int i = 0; i < in.signature.size(); i += 2) {
std::string byteString = in.signature.substr(i, 2);
signature[i>>1] = (char) strtol(byteString.c_str(), NULL, 16);
signature.emplace_back((uint8_t)strtol(byteString.c_str(), NULL, 16));
}
return true;
}
@@ -160,9 +168,9 @@ namespace oracle
bool pricing_record::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const
{
std::string sig_hex;
for (unsigned int i=0; i<64; i++) {
for (size_t i=0; i<signature.size(); ++i) {
std::stringstream ss;
ss << std::hex << std::setw(2) << std::setfill('0') << (0xff & signature[i]);
ss << std::hex << std::setw(2) << std::setfill('0') << (0xff & signature.at(i));
sig_hex += ss.str();
}
const pr_serialized out{pr_version, height, supply, assets, timestamp, sig_hex};
@@ -194,13 +202,7 @@ namespace oracle
{
for (const auto& asset: assets) {
if (asset.asset_type != asset_type) continue;
if (asset_type == "FULM") return asset.spot_price;
if (asset_type == "FUSD") {
boost::multiprecision::uint128_t exchange_128 = COIN;
exchange_128 *= COIN;
exchange_128 /= asset.spot_price;
return exchange_128.convert_to<uint64_t>();
}
return asset.spot_price;
}
return 0;
}
@@ -239,7 +241,7 @@ namespace oracle
std::ostringstream oss;
oss << "{\"pr_version\":" << pr_version;
oss << ",\"height\":" << height;
oss << ",\"supply\":{\"FULM\":" << supply.fulm <<",\"FUSD\":" << supply.fusd << "}";
oss << ",\"supply\":{\"SAL\":" << supply.sal <<",\"VSD\":" << supply.vsd << "}";
oss << ",\"assets\":[";
bool first = true;
for (const auto& asset: assets) {
+26 -9
View File
@@ -67,19 +67,24 @@ namespace oracle
#pragma pack(pop)
struct supply_data {
uint64_t fulm;
uint64_t fusd;
uint64_t sal;
uint64_t vsd;
//! Load from epee p2p format
bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent);
//! Store in epee p2p format
bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const;
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(sal)
VARINT_FIELD(vsd)
END_SERIALIZE()
};
inline bool operator==(const supply_data& a, const supply_data& b) noexcept
{
return (a.fulm == b.fulm &&
a.fusd == b.fusd);
return (a.sal == b.sal &&
a.vsd == b.vsd);
}
struct asset_data {
@@ -91,6 +96,12 @@ namespace oracle
bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent);
//! Store in epee p2p format
bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const;
BEGIN_SERIALIZE_OBJECT()
FIELD(asset_type)
VARINT_FIELD(spot_price)
VARINT_FIELD(ma_price)
END_SERIALIZE()
};
inline bool operator==(const asset_data& a, const asset_data& b) noexcept
@@ -100,11 +111,8 @@ namespace oracle
a.ma_price == b.ma_price);
}
class pricing_record
struct pricing_record
{
public:
// Fields
uint64_t pr_version;
uint64_t height;
@@ -120,7 +128,7 @@ namespace oracle
//! Store in epee p2p format
bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const;
pricing_record(const pricing_record& orig) noexcept;
~pricing_record() = default;
~pricing_record() noexcept;
bool equal(const pricing_record& other) const noexcept;
bool empty() const noexcept;
bool verifySignature(const std::string& public_key) const;
@@ -128,6 +136,15 @@ namespace oracle
pricing_record& operator=(const pricing_record& orig) noexcept;
uint64_t operator[](const std::string& asset_type) const;
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(pr_version)
VARINT_FIELD(height)
FIELD(supply)
FIELD(assets)
VARINT_FIELD(timestamp)
FIELD(signature)
END_SERIALIZE()
};
inline bool operator==(const pricing_record& a, const pricing_record& b) noexcept
+2 -1
View File
@@ -42,6 +42,7 @@
#include <boost/serialization/version.hpp>
#include "net_peerlist_boost_serialization.h"
#include "common/util.h"
namespace nodetool
@@ -200,7 +201,7 @@ namespace nodetool
if (!out)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(path, path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(path, path + ".unportable");
src_file.close();
src_file.open( path , std::ios_base::binary | std::ios_base::in);
if(src_file.fail())
+40 -21
View File
@@ -121,12 +121,18 @@ namespace
namespace rct {
Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<bool> &zero_masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
{
CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes");
CHECK_AND_ASSERT_THROW_MES(amounts.size() == zero_masks.size(), "Invalid amounts/zero_masks sizes");
masks.resize(amounts.size());
for (size_t i = 0; i < masks.size(); ++i)
masks[i] = hwdev.genCommitmentMask(sk[i]);
for (size_t i = 0; i < masks.size(); ++i) {
if (zero_masks[i] == true) {
masks[i] = rct::identity();
} else {
masks[i] = hwdev.genCommitmentMask(sk[i]);
}
}
Bulletproof proof = bulletproof_PROVE(amounts, masks);
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
C = proof.V;
@@ -147,12 +153,18 @@ namespace rct {
catch (...) { return false; }
}
BulletproofPlus proveRangeBulletproofPlus(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
BulletproofPlus proveRangeBulletproofPlus(keyV &C, keyV &masks, const std::vector<bool> &zero_masks, const std::vector<uint64_t> &amounts, epee::span<const key> sk, hw::device &hwdev)
{
CHECK_AND_ASSERT_THROW_MES(amounts.size() == sk.size(), "Invalid amounts/sk sizes");
CHECK_AND_ASSERT_THROW_MES(amounts.size() == zero_masks.size(), "Invalid amounts/zero_masks sizes");
masks.resize(amounts.size());
for (size_t i = 0; i < masks.size(); ++i)
masks[i] = hwdev.genCommitmentMask(sk[i]);
for (size_t i = 0; i < masks.size(); ++i) {
if (zero_masks[i] == true) {
masks[i] = rct::identity();
} else {
masks[i] = hwdev.genCommitmentMask(sk[i]);
}
}
BulletproofPlus proof = bulletproof_plus_PROVE(amounts, masks);
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
C = proof.V;
@@ -1110,8 +1122,9 @@ namespace rct {
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const vector<xmr_amount> &inamounts,
const vector<xmr_amount> &outamounts,
const std::vector<bool> &zero_masks,
const std::vector<xmr_amount> &inamounts,
const std::vector<xmr_amount> &outamounts,
xmr_amount txnFee,
const ctkeyM & mixRing,
const keyV &amount_keys,
@@ -1126,6 +1139,7 @@ namespace rct {
CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk");
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
CHECK_AND_ASSERT_THROW_MES(zero_masks.size() == destinations.size(), "Different number of zero_masks/destinations");
CHECK_AND_ASSERT_THROW_MES(index.size() == inSk.size(), "Different number of index/inSk");
CHECK_AND_ASSERT_THROW_MES(mixRing.size() == inSk.size(), "Different number of mixRing/inSk");
for (size_t n = 0; n < mixRing.size(); ++n) {
@@ -1192,9 +1206,9 @@ namespace rct {
{
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
if (plus)
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, outamounts, keys, hwdev));
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, zero_masks, outamounts, keys, hwdev));
else
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, zero_masks, outamounts, keys, hwdev));
#ifdef DBG
if (plus)
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof");
@@ -1230,9 +1244,9 @@ namespace rct {
{
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
if (plus)
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, batch_amounts, keys, hwdev));
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, zero_masks, batch_amounts, keys, hwdev));
else
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, zero_masks, batch_amounts, keys, hwdev));
#ifdef DBG
if (plus)
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof");
@@ -1273,14 +1287,15 @@ namespace rct {
rv.p.MGs.resize(inamounts.size());
key sumpouts = zero(); //sum pseudoOut masks
keyV a(inamounts.size());
for (i = 0 ; i < inamounts.size() - 1; i++) {
for (i = 0 ; i < inamounts.size(); i++) {
skGen(a[i]);
sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes);
genC(pseudoOuts[i], a[i], inamounts[i]);
}
sc_sub(a[i].bytes, sumout.bytes, sumpouts.bytes);
genC(pseudoOuts[i], a[i], inamounts[i]);
DP(pseudoOuts[i]);
key difference;
sc_sub(difference.bytes, sumpouts.bytes, sumout.bytes);
genC(rv.p_r, difference, 0);
DP(rv.p_r);
key full_message = get_pre_mlsag_hash(rv,hwdev);
@@ -1308,9 +1323,10 @@ namespace rct {
const keyV & destinations,
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const vector<xmr_amount> &inamounts,
const vector<xmr_amount> &outamounts,
const std::vector<std::string> & destination_asset_types,
const std::vector<bool> &zero_masks,
const std::vector<xmr_amount> &inamounts,
const std::vector<xmr_amount> &outamounts,
const keyV &amount_keys,
xmr_amount txnFee,
unsigned int mixin,
@@ -1326,7 +1342,7 @@ namespace rct {
mixRing[i].resize(mixin+1);
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
}
return genRctSimple(message, inSk, destinations, tx_type, in_asset_type, destination_asset_types, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev);
return genRctSimple(message, inSk, destinations, tx_type, in_asset_type, destination_asset_types, zero_masks, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev);
}
//RingCT protocol
@@ -1463,7 +1479,10 @@ namespace rct {
const key txnAmountBurntKey = scalarmultH(d2h(amount_burnt));
addKeys(sumOutpks, txnAmountBurntKey, sumOutpks);
// Account for the "blinding factor remainder" term `p_r`
addKeys(sumOutpks, rv.p_r, sumOutpks);
key sumPseudoOuts = addKeys(pseudoOuts);
DP(sumPseudoOuts);
+2
View File
@@ -135,6 +135,7 @@ namespace rct {
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const std::vector<bool> &zero_masks,
const std::vector<xmr_amount> & inamounts,
const std::vector<xmr_amount> & outamounts,
const keyV &amount_keys,
@@ -150,6 +151,7 @@ namespace rct {
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const std::vector<bool> &zero_masks,
const std::vector<xmr_amount> & inamounts,
const std::vector<xmr_amount> & outamounts,
xmr_amount txnFee,
+3
View File
@@ -324,6 +324,7 @@ namespace rct {
std::vector<ecdhTuple> ecdhInfo;
ctkeyV outPk;
xmr_amount txnFee; // contains b
key p_r;
template<bool W, template <bool> class Archive>
bool serialize_rctsig_base(Archive<W> &ar, size_t inputs, size_t outputs)
@@ -390,6 +391,7 @@ namespace rct {
ar.delimit_array();
}
ar.end_array();
FIELD(p_r)
return ar.good();
}
@@ -401,6 +403,7 @@ namespace rct {
FIELD(ecdhInfo)
FIELD(outPk)
VARINT_FIELD(txnFee)
FIELD(p_r)
END_SERIALIZE()
};
struct rctSigPrunable {
+39 -13
View File
@@ -1910,12 +1910,10 @@ namespace cryptonote
crypto::hash seed_hash, next_seed_hash;
if (!get_block_template(info.address, req.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, b, res.seed_height, seed_hash, next_seed_hash, error_resp))
return false;
if (b.major_version >= RX_BLOCK_VERSION)
{
res.seed_hash = string_tools::pod_to_hex(seed_hash);
if (seed_hash != next_seed_hash)
res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash);
}
res.seed_hash = string_tools::pod_to_hex(seed_hash);
if (seed_hash != next_seed_hash)
res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash);
res.reserved_offset = reserved_offset;
store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
@@ -2228,7 +2226,7 @@ namespace cryptonote
}
b.nonce = req.starting_nonce;
crypto::hash seed_hash = crypto::null_hash;
if (b.major_version >= RX_BLOCK_VERSION && !epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash))
if (!epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Error converting seed hash";
@@ -2270,6 +2268,7 @@ namespace cryptonote
response.timestamp = blk.timestamp;
response.prev_hash = string_tools::pod_to_hex(blk.prev_id);
response.nonce = blk.nonce;
response.pricing_record = blk.pricing_record;
response.orphan_status = orphan_status;
response.height = height;
response.depth = m_core.get_current_blockchain_height() - height - 1;
@@ -2940,6 +2939,35 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_yield_info(const COMMAND_RPC_GET_YIELD_INFO::request& req, COMMAND_RPC_GET_YIELD_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
PERF_TIMER(on_get_yield_info);
uint64_t height = m_core.get_current_blockchain_height();
std::map<uint64_t, yield_block_info> ybi_cache;
if (!m_core.get_blockchain_storage().get_ybi_cache(ybi_cache)) {
res.status = "failed to get YBI data from blockchain";
return true;
}
// Iterate over the cache, supplying the data in a more accessible format
res.yield_data.clear();
for (const auto& entry: ybi_cache) {
// Skip this entry if out-of=range
if (req.from_height > 0 and entry.first < req.from_height) continue;
if (req.to_height > 0 and entry.first > req.to_height) continue;
// Clone the data into the response
COMMAND_RPC_GET_YIELD_INFO::yield_data_t yd;
yd.block_height = entry.second.block_height;
yd.slippage_total_this_block = entry.second.slippage_total_this_block;
yd.locked_coins_this_block = entry.second.locked_coins_this_block;
yd.locked_coins_tally = entry.second.locked_coins_tally;
yd.network_health_percentage = entry.second.network_health_percentage;
res.yield_data.push_back(yd);
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_base_fee_estimate(const COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
RPC_TRACKER(get_base_fee_estimate);
@@ -3457,12 +3485,10 @@ namespace cryptonote
}
res.hashing_blob = epee::string_tools::buff_to_hex_nodelimer(hashing_blob);
res.top_hash = epee::string_tools::pod_to_hex(top_hash);
if (hashing_blob[0] >= RX_BLOCK_VERSION)
{
res.seed_hash = string_tools::pod_to_hex(seed_hash);
if (seed_hash != next_seed_hash)
res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash);
}
res.seed_hash = string_tools::pod_to_hex(seed_hash);
if (seed_hash != next_seed_hash)
res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash);
res.status = CORE_RPC_STATUS_OK;
return true;
+2
View File
@@ -175,6 +175,7 @@ namespace cryptonote
MAP_JON_RPC_WE("get_version", on_get_version, COMMAND_RPC_GET_VERSION)
MAP_JON_RPC_WE_IF("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM, !m_restricted)
MAP_JON_RPC_WE("get_circulating_supply", on_get_circulating_supply, COMMAND_RPC_GET_CIRCULATING_SUPPLY)
MAP_JON_RPC_WE("get_yield_info", on_get_yield_info, COMMAND_RPC_GET_YIELD_INFO)
MAP_JON_RPC_WE("get_fee_estimate", on_get_base_fee_estimate, COMMAND_RPC_GET_BASE_FEE_ESTIMATE)
MAP_JON_RPC_WE_IF("get_alternate_chains",on_get_alternate_chains, COMMAND_RPC_GET_ALTERNATE_CHAINS, !m_restricted)
MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted)
@@ -253,6 +254,7 @@ namespace cryptonote
bool on_get_version(const COMMAND_RPC_GET_VERSION::request& req, COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_circulating_supply(const COMMAND_RPC_GET_CIRCULATING_SUPPLY::request& req, COMMAND_RPC_GET_CIRCULATING_SUPPLY::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_yield_info(const COMMAND_RPC_GET_YIELD_INFO::request& req, COMMAND_RPC_GET_YIELD_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_base_fee_estimate(const COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request& req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
+45
View File
@@ -33,6 +33,7 @@
#include "string_tools.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "blockchain_db/blockchain_db.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/difficulty.h"
#include "crypto/hash.h"
@@ -1222,6 +1223,50 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_GET_YIELD_INFO
{
struct yield_data_t
{
uint64_t block_height;
uint64_t slippage_total_this_block;
uint64_t locked_coins_this_block;
uint64_t locked_coins_tally;
uint8_t network_health_percentage;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(block_height)
KV_SERIALIZE(slippage_total_this_block)
KV_SERIALIZE(locked_coins_this_block)
KV_SERIALIZE(locked_coins_tally)
KV_SERIALIZE(network_health_percentage)
END_KV_SERIALIZE_MAP()
};
struct request_t
{
uint64_t from_height;
uint64_t to_height;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(from_height, (uint64_t)0)
KV_SERIALIZE_OPT(to_height, (uint64_t)0)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct response_t
{
std::string status;
std::vector<COMMAND_RPC_GET_YIELD_INFO::yield_data_t> yield_data;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(yield_data)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_GET_LAST_BLOCK_HEADER
{
struct request_t: public rpc_access_request_base
+4 -10
View File
@@ -234,16 +234,10 @@ namespace cryptonote
block = is_current ? info.block : info.previous_block;
*(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(nonce);
if (block.major_version >= RX_BLOCK_VERSION)
{
const crypto::hash &seed_hash = is_current ? info.seed_hash : info.previous_seed_hash;
crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data);
}
else
{
const int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0;
crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash, cn_variant, cryptonote::get_block_height(block));
}
const crypto::hash &seed_hash = is_current ? info.seed_hash : info.previous_seed_hash;
crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data);
if (!check_hash(hash, m_diff))
{
MWARNING("Payment too low");
+25 -16
View File
@@ -270,16 +270,18 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, version, tx.version);
INSERT_INTO_JSON_OBJECT(dest, unlock_time, tx.unlock_time);
INSERT_INTO_JSON_OBJECT(dest, inputs, tx.vin);
INSERT_INTO_JSON_OBJECT(dest, outputs, tx.vout);
INSERT_INTO_JSON_OBJECT(dest, extra, tx.extra);
INSERT_INTO_JSON_OBJECT(dest, type, static_cast<uint8_t>(tx.type));
INSERT_INTO_JSON_OBJECT(dest, return_address, tx.return_address);
INSERT_INTO_JSON_OBJECT(dest, source_asset_type, tx.source_asset_type);
INSERT_INTO_JSON_OBJECT(dest, destination_asset_type, tx.destination_asset_type);
INSERT_INTO_JSON_OBJECT(dest, amount_burnt, tx.amount_burnt);
INSERT_INTO_JSON_OBJECT(dest, amount_slippage_limit, tx.amount_slippage_limit);
if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) {
INSERT_INTO_JSON_OBJECT(dest, return_address, tx.return_address);
INSERT_INTO_JSON_OBJECT(dest, return_pubkey, tx.return_pubkey);
INSERT_INTO_JSON_OBJECT(dest, source_asset_type, tx.source_asset_type);
INSERT_INTO_JSON_OBJECT(dest, destination_asset_type, tx.destination_asset_type);
INSERT_INTO_JSON_OBJECT(dest, amount_burnt, tx.amount_burnt);
INSERT_INTO_JSON_OBJECT(dest, amount_slippage_limit, tx.amount_slippage_limit);
}
if (!tx.pruned)
{
INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures);
@@ -298,16 +300,18 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx)
}
GET_FROM_JSON_OBJECT(val, tx.version, version);
GET_FROM_JSON_OBJECT(val, tx.unlock_time, unlock_time);
GET_FROM_JSON_OBJECT(val, tx.vin, inputs);
GET_FROM_JSON_OBJECT(val, tx.vout, outputs);
GET_FROM_JSON_OBJECT(val, tx.extra, extra);
GET_FROM_JSON_OBJECT(val, tx.type, type);
GET_FROM_JSON_OBJECT(val, tx.return_address, return_address);
GET_FROM_JSON_OBJECT(val, tx.source_asset_type, source_asset_type);
GET_FROM_JSON_OBJECT(val, tx.destination_asset_type, destination_asset_type);
GET_FROM_JSON_OBJECT(val, tx.amount_burnt, amount_burnt);
GET_FROM_JSON_OBJECT(val, tx.amount_slippage_limit, amount_slippage_limit);
if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) {
GET_FROM_JSON_OBJECT(val, tx.return_address, return_address);
GET_FROM_JSON_OBJECT(val, tx.return_pubkey, return_pubkey);
GET_FROM_JSON_OBJECT(val, tx.source_asset_type, source_asset_type);
GET_FROM_JSON_OBJECT(val, tx.destination_asset_type, destination_asset_type);
GET_FROM_JSON_OBJECT(val, tx.amount_burnt, amount_burnt);
GET_FROM_JSON_OBJECT(val, tx.amount_slippage_limit, amount_slippage_limit);
}
GET_FROM_JSON_OBJECT(val, tx.rct_signatures, ringct);
const auto& sigs = val.FindMember("signatures");
@@ -1132,8 +1136,8 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::suppl
{
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, fulm, supply_data.fulm);
INSERT_INTO_JSON_OBJECT(dest, fusd, supply_data.fusd);
INSERT_INTO_JSON_OBJECT(dest, sal, supply_data.sal);
INSERT_INTO_JSON_OBJECT(dest, vsd, supply_data.vsd);
dest.EndObject();
}
@@ -1145,8 +1149,8 @@ void fromJsonValue(const rapidjson::Value& val, oracle::supply_data& supply_data
throw WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, supply_data.fulm, fulm);
GET_FROM_JSON_OBJECT(val, supply_data.fusd, fusd);
GET_FROM_JSON_OBJECT(val, supply_data.sal, sal);
GET_FROM_JSON_OBJECT(val, supply_data.vsd, vsd);
}
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::asset_data& asset_data)
@@ -1177,6 +1181,8 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::prici
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, pr_version, pricing_record.pr_version);
INSERT_INTO_JSON_OBJECT(dest, height, pricing_record.height);
INSERT_INTO_JSON_OBJECT(dest, supply, pricing_record.supply);
INSERT_INTO_JSON_OBJECT(dest, assets, pricing_record.assets);
INSERT_INTO_JSON_OBJECT(dest, timestamp, pricing_record.timestamp);
INSERT_INTO_JSON_OBJECT(dest, signature, pricing_record.signature);
@@ -1186,12 +1192,15 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::prici
void fromJsonValue(const rapidjson::Value& val, oracle::pricing_record& pricing_record)
{
LOG_ERROR("Oracle::" << __func__ << ":" << __LINE__);
if (!val.IsObject())
{
throw WRONG_TYPE("json object");
}
GET_FROM_JSON_OBJECT(val, pricing_record.pr_version, pr_version);
GET_FROM_JSON_OBJECT(val, pricing_record.height, height);
GET_FROM_JSON_OBJECT(val, pricing_record.supply, supply);
GET_FROM_JSON_OBJECT(val, pricing_record.assets, assets);
GET_FROM_JSON_OBJECT(val, pricing_record.timestamp, timestamp);
std::string sig_hex;
-2
View File
@@ -197,8 +197,6 @@ void fromJsonValue(const rapidjson::Value& val, long& i);
// end integers
//void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::pair<std::string, std::pair<uint64_t, uint64_t>>& entry);
//void fromJsonValue(const rapidjson::Value& val, std::pair<std::string, std::pair<uint64_t, uint64_t>>& entry);
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::supply_data& supply_data);
void fromJsonValue(const rapidjson::Value& val, oracle::supply_data& supply_data);
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::asset_data& asset_data);
+83 -24
View File
@@ -39,21 +39,27 @@
// read
template <template <bool> class Archive>
bool do_serialize(Archive<false> &ar, oracle::supply_data &ad, uint8_t version)
bool do_serialize(Archive<false> &ar, oracle::supply_data &sd, uint8_t version)
{
assert(false);
return false;
ar.serialize_varint(sd.sal);
if (!ar.good())
return false;
ar.serialize_varint(sd.vsd);
if (!ar.good())
return false;
return true;
}
// write
template <template <bool> class Archive>
bool do_serialize(Archive<true> &ar, oracle::supply_data &sd, uint8_t version)
{
ar.begin_string();
ar.serialize_blob(&sd, sizeof(oracle::supply_data), "");
if (!ar.good())
return false;
ar.end_string();
ar.serialize_varint(sd.sal);
ar.serialize_varint(sd.vsd);
if (!ar.good())
return false;
return true;
}
@@ -61,19 +67,33 @@ bool do_serialize(Archive<true> &ar, oracle::supply_data &sd, uint8_t version)
template <template <bool> class Archive>
bool do_serialize(Archive<false> &ar, oracle::asset_data &ad, uint8_t version)
{
assert(false);
return false;
ar.serialize_string(ad.asset_type);
if (!ar.good())
return false;
ar.serialize_varint(ad.spot_price);
if (!ar.good())
return false;
ar.serialize_varint(ad.ma_price);
if (!ar.good())
return false;
return true;
}
// write
template <template <bool> class Archive>
bool do_serialize(Archive<true> &ar, oracle::asset_data &ad, uint8_t version)
{
ar.begin_string();
ar.serialize_blob(&ad, sizeof(oracle::asset_data), "");
if (!ar.good())
return false;
ar.end_string();
ar.serialize_string(ad.asset_type);
if (!ar.good())
return false;
ar.serialize_varint(ad.spot_price);
if (!ar.good())
return false;
ar.serialize_varint(ad.ma_price);
if (!ar.good())
return false;
return true;
}
@@ -81,15 +101,40 @@ bool do_serialize(Archive<true> &ar, oracle::asset_data &ad, uint8_t version)
template <template <bool> class Archive>
bool do_serialize(Archive<false> &ar, oracle::pricing_record &pr, uint8_t version)
{
// very basic sanity check
if (ar.remaining_bytes() < sizeof(oracle::pricing_record)) {
return false;
}
ar.serialize_blob(&pr, sizeof(oracle::pricing_record), "");
// very basic sanity checks
if (!ar.good())
return false;
ar.serialize_varint(pr.pr_version);
if (!ar.good())
return false;
ar.serialize_varint(pr.height);
if (!ar.good())
return false;
if (!do_serialize(ar, pr.supply, version))
return false;
/*
// The next line should never do anything, but better safe than sorry
pr.asset_data.empty();
size_t asset_count;
ar.begin_array(asset_count);
if (!ar.good())
return false;
for (size_t idx=0; idx<asset_count; idx++) {
if (idx > 0) ar.delimit_array();
asset_data ad;
if (!do_serialize(ar, ad, version))
return false;
pr.asset_data.emplace_back(ad);
}
ar.end_array();
*/
if (!do_serialize_container(ar, pr.assets))
return false;
ar.serialize_varint(pr.timestamp);
if (!ar.good())
return false;
if (!do_serialize_container(ar, pr.signature))
return false;
return true;
}
@@ -97,14 +142,28 @@ bool do_serialize(Archive<false> &ar, oracle::pricing_record &pr, uint8_t versio
template <template <bool> class Archive>
bool do_serialize(Archive<true> &ar, oracle::pricing_record &pr, uint8_t version)
{
ar.begin_string();
ar.serialize_blob(&pr, sizeof(oracle::pricing_record), "");
// very basic sanity checks
if (!ar.good())
return false;
ar.end_string();
ar.serialize_varint(pr.pr_version);
if (!ar.good())
return false;
ar.serialize_varint(pr.height);
if (!ar.good())
return false;
if (!do_serialize(ar, pr.supply, version))
return false;
if (!do_serialize_container(ar, pr.assets))
return false;
ar.serialize_varint(pr.timestamp);
if (!ar.good())
return false;
pr.signature.empty();
if (!do_serialize_container(ar, pr.signature))
return false;
return true;
}
BLOB_SERIALIZER(oracle::supply_data);
BLOB_SERIALIZER(oracle::asset_data);
BLOB_SERIALIZER(oracle::pricing_record);
//BLOB_SERIALIZER(oracle::supply_data);
//BLOB_SERIALIZER(oracle::asset_data);
//BLOB_SERIALIZER(oracle::pricing_record);
+1 -1
View File
@@ -61,5 +61,5 @@ target_link_libraries(simplewallet
${EXTRA_LIBRARIES})
set_property(TARGET simplewallet
PROPERTY
OUTPUT_NAME "fulmo-wallet-cli")
OUTPUT_NAME "salvium-wallet-cli")
install(TARGETS simplewallet DESTINATION bin)
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -52,8 +52,8 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.simplewallet"
// Hardcode Fulmo's donation address
constexpr const char FULMO_DONATION_ADDR[] = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
// Hardcode Salvium's donation address
constexpr const char SALVIUM_DONATION_ADDR[] = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
/*!
* \namespace cryptonote
@@ -180,6 +180,7 @@ namespace cryptonote
bool sweep_below(const std::vector<std::string> &args);
bool sweep_single(const std::vector<std::string> &args);
bool sweep_unmixable(const std::vector<std::string> &args);
bool return_payment(const std::vector<std::string> &args);
bool burn(const std::vector<std::string> &args);
bool convert(const std::vector<std::string> &args);
bool lock_for_yield(const std::vector<std::string> &args);
@@ -352,7 +353,7 @@ namespace cryptonote
//----------------- i_wallet2_callback ---------------------
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const std::string& asset_type, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time);
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const std::string& asset_type, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time, const uint64_t& origin_td_idx);
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index);
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const std::string& asset_type, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index);
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx);
+5 -3
View File
@@ -1,13 +1,15 @@
#define DEF_FULMO_VERSION_TAG "7f6b8da"
#define DEF_FULMO_VERSION "0.0.1"
#define DEF_SALVIUM_VERSION_TAG "7f6b8da"
#define DEF_SALVIUM_VERSION "0.0.8"
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "0.18.2.2"
#define DEF_MONERO_RELEASE_NAME "Zero"
#define DEF_MONERO_VERSION_FULL DEF_FULMO_VERSION "-" DEF_FULMO_VERSION_TAG ", based on Monero " DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_FULL DEF_SALVIUM_VERSION "-" DEF_SALVIUM_VERSION_TAG ", based on Monero " DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
#include "version.h"
const char* const SALVIUM_VERSION_TAG = DEF_SALVIUM_VERSION_TAG;
const char* const SALVIUM_VERSION = DEF_SALVIUM_VERSION;
const char* const MONERO_VERSION_TAG = DEF_MONERO_VERSION_TAG;
const char* const MONERO_VERSION = DEF_MONERO_VERSION;
const char* const MONERO_RELEASE_NAME = DEF_MONERO_RELEASE_NAME;
+2
View File
@@ -1,5 +1,7 @@
#pragma once
extern const char* const SALVIUM_VERSION_TAG;
extern const char* const SALVIUM_VERSION;
extern const char* const MONERO_VERSION_TAG;
extern const char* const MONERO_VERSION;
extern const char* const MONERO_RELEASE_NAME;
+1 -1
View File
@@ -100,7 +100,7 @@ if(NOT IOS)
${EXTRA_LIBRARIES})
set_property(TARGET wallet_rpc_server
PROPERTY
OUTPUT_NAME "fulmo-wallet-rpc")
OUTPUT_NAME "salvium-wallet-rpc")
install(TARGETS wallet_rpc_server DESTINATION bin)
endif()
+5 -5
View File
@@ -154,20 +154,20 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
}
}
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time)
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time, const uint64_t& tx_origin_idx)
{
std::string tx_hash = epee::string_tools::pod_to_hex(txid);
LOG_PRINT_L3(__FUNCTION__ << ": money received. height: " << height
<< ", tx: " << tx_hash
<< ", amount: " << print_money(amount - burnt)
<< ", burnt: " << print_money(burnt)
<< ", raw_output_value: " << print_money(amount)
<< ", amount: " << print_money(amount)
<< ", burnt: " << print_money(tx.amount_burnt)
<< ", raw_output_value: " << print_money(amount - tx.amount_burnt)
<< ", idx: " << subaddr_index);
// do not signal on received tx if wallet is not syncronized completely
if (m_listener && m_wallet->synchronized()) {
m_listener->moneyReceived(tx_hash, amount - burnt);
m_listener->moneyReceived(tx_hash, amount - tx.amount_burnt);
m_listener->updated();
}
}
+165 -67
View File
@@ -1,5 +1,5 @@
// Copyright (c) 2014-2022, The Monero Project
// Portions Copyright (c) 2023, Fulmo (author: SRCG)
// Portions Copyright (c) 2023, Salvium (author: SRCG)
//
// All rights reserved.
//
@@ -804,7 +804,7 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra
size += n_inputs * (1+6+(mixin+1)*2+32);
// vout
size += n_outputs * (6+32);
size += n_outputs * (1+32+4+8);
// extra
size += extra_size;
@@ -839,6 +839,8 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra
// pseudoOuts
size += 32 * n_inputs;
// p_r
size += 32;
// ecdhInfo
size += 8 * n_outputs;
// outPk - only commitment is saved
@@ -1871,9 +1873,10 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
crypto::public_key pk_change = crypto::null_pkey;
bool ok = m_account.get_device().derive_subaddress_public_key(output_public_key, tx_scan_info.received->derivation, i, pk_change);
THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to derive subaddress public key for CONVERT/YIELD TX");
// Find the TX public key for P_change
auto search = m_protocol_txs.find(pk_change);
//auto search = m_protocol_txs.find(pk_change);
auto search = m_protocol_txs.find(output_public_key);
THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate protocol_tx entry to permit source usage");
size_t idx = search->second;
THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate protocol_txs index in m_transfers");
@@ -2034,6 +2037,36 @@ bool wallet2::get_circulating_supply(std::vector<std::pair<std::string, std::str
}
}
//----------------------------------------------------------------------------------------------------
bool wallet2::get_yield_info(std::vector<cryptonote::yield_block_info>& ybi_data)
{
// Issue an RPC call to get the block header (and thus the pricing record) at the specified height
cryptonote::COMMAND_RPC_GET_YIELD_INFO::request req = AUTO_VAL_INIT(req);
cryptonote::COMMAND_RPC_GET_YIELD_INFO::response res = AUTO_VAL_INIT(res);
m_daemon_rpc_mutex.lock();
bool r = invoke_http_json_rpc("/json_rpc", "get_yield_info", req, res, rpc_timeout);
m_daemon_rpc_mutex.unlock();
if (r && res.status == CORE_RPC_STATUS_OK)
{
ybi_data.clear();
for (const auto& entry: res.yield_data) {
// Create a YBI
cryptonote::yield_block_info ybi;
ybi.block_height = entry.block_height;
ybi.slippage_total_this_block = entry.slippage_total_this_block;
ybi.locked_coins_this_block = entry.locked_coins_this_block;
ybi.locked_coins_tally = entry.locked_coins_tally;
ybi.network_health_percentage = entry.network_health_percentage;
ybi_data.push_back(ybi);
}
return true;
}
else
{
MERROR("Failed to retrieve yield info from daemon");
return false;
}
}
//----------------------------------------------------------------------------------------------------
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, const std::vector<uint64_t> &asset_type_output_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
{
PERF_TIMER(process_new_transaction);
@@ -2044,11 +2077,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
std::string source_asset = tx.source_asset_type;
std::string dest_asset = tx.destination_asset_type;
cryptonote::transaction_type tx_type_verify = tx.type;
if (!miner_tx) {
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_tx_type(source_asset, dest_asset, tx_type_verify), error::wallet_internal_error, "Failed to get TX type");
THROW_WALLET_EXCEPTION_IF(tx_type_verify != tx.type, error::wallet_internal_error, "Incorrect TX type");
}
// per receiving subaddress index
std::unordered_map<cryptonote::subaddress_index, std::map<std::string, uint64_t>> tx_money_got_in_outs;
@@ -2073,6 +2101,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
std::vector<tx_scan_info_t> tx_scan_info(tx.vout.size());
std::deque<bool> output_found(tx.vout.size(), false);
uint64_t total_received_1 = 0;
uint64_t origin_td_idx = ((uint64_t)-1);
while (!tx.vout.empty())
{
std::vector<size_t> outs;
@@ -2203,9 +2232,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
crypto::public_key pk_change = crypto::null_pkey;
bool ok = m_account.get_device().derive_subaddress_public_key(output_public_key, additional_derivations[i], i, pk_change);
THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to derive subaddress public key for CONVERT/YIELD TX");
// Find the TX public key for P_change
auto search = m_protocol_txs.find(pk_change);
//auto search = m_protocol_txs.find(pk_change);
auto search = m_protocol_txs.find(output_public_key);
if (search == m_protocol_txs.end()) {
LOG_PRINT_L3("failed to locate protocol_tx entry for this vout - skipping");
continue;
}
THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate protocol_tx entry to permit source usage");
size_t idx = search->second;
THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate protocol_txs index in m_transfers");
@@ -2222,6 +2256,17 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
THROW_WALLET_EXCEPTION_IF(!cryptonote::calculate_uniqueness(td_origin.m_tx.type, k_image, td_origin.m_block_height, i, tx_scan_info[i].uniqueness),
error::wallet_internal_error,
"Failed to calculate uniqueness from origin TX");
// At this point, we know that we are receiving something - store the origin TD index
origin_td_idx = idx;
// At this point, we need to clear the "locked coins" count, because otherwise we will be counting yield stakes twice in our balance
// Get the output key for the change entry
crypto::public_key pk_locked_coins = crypto::null_pkey;
THROW_WALLET_EXCEPTION_IF(!get_output_public_key(td_origin.m_tx.vout[td_origin.m_internal_output_index], pk_locked_coins), error::wallet_internal_error, "Failed to get output public key for locked coins");
THROW_WALLET_EXCEPTION_IF(!m_locked_coins.erase(pk_locked_coins), error::wallet_internal_error, "Failed to remove PROTOCOL_TX entry from m_locked_coins");
} else {
// Get the uniqueness value
@@ -2257,20 +2302,20 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
//usually we have only one transfer for user in transaction
if (!pool)
{
THROW_WALLET_EXCEPTION_IF(tx.vout.size() != o_indices.size() || tx.vout.size() != asset_type_output_indices.size(), error::wallet_internal_error,
"transactions outputs size=" + std::to_string(tx.vout.size()) +
" not match with daemon response size=" + std::to_string(o_indices.size())
+ " or with asset outputs size=" + std::to_string(asset_type_output_indices.size()));
THROW_WALLET_EXCEPTION_IF(tx.vout.size() != o_indices.size() || tx.vout.size() != asset_type_output_indices.size(), error::wallet_internal_error,
"transactions outputs size=" + std::to_string(tx.vout.size()) +
" not match with daemon response size=" + std::to_string(o_indices.size())
+ " or with asset outputs size=" + std::to_string(asset_type_output_indices.size()));
}
for(size_t o: outs)
{
THROW_WALLET_EXCEPTION_IF(tx.vout.size() <= o, error::wallet_internal_error, "wrong out in transaction: internal index=" +
std::to_string(o) + ", total_outs=" + std::to_string(tx.vout.size()));
THROW_WALLET_EXCEPTION_IF(tx.vout.size() <= o, error::wallet_internal_error, "wrong out in transaction: internal index=" +
std::to_string(o) + ", total_outs=" + std::to_string(tx.vout.size()));
auto kit = m_pub_keys.find(tx_scan_info[o].in_ephemeral.pub);
THROW_WALLET_EXCEPTION_IF(kit != m_pub_keys.end() && kit->second >= m_transfers.size(),
THROW_WALLET_EXCEPTION_IF(kit != m_pub_keys.end() && kit->second >= m_transfers.size(),
error::wallet_internal_error, std::string("Unexpected transfer index from public key: ")
+ "got " + (kit == m_pub_keys.end() ? "<none>" : boost::lexical_cast<std::string>(kit->second))
+ ", m_transfers.size() is " + boost::lexical_cast<std::string>(m_transfers.size()));
@@ -2294,6 +2339,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_txid = txid;
td.m_asset_type_output_index = asset_type_output_indices[o];
td.asset_type = asset_type;
td.m_origin_td_idx = origin_td_idx;
td.m_key_image = tx_scan_info[o].ki;
td.m_key_image_known = !m_watch_only && !m_multisig;
if (!td.m_key_image_known)
@@ -2337,10 +2383,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_rct = false;
}
td.m_frozen = false;
set_unspent(m_transfers.size()-1);
set_unspent(m_transfers.size()-1);
if (td.m_key_image_known)
m_key_images[td.m_key_image] = m_transfers.size()-1;
m_pub_keys[tx_scan_info[o].in_ephemeral.pub] = m_transfers.size()-1;
m_key_images[td.m_key_image] = m_transfers.size()-1;
m_pub_keys[tx_scan_info[o].in_ephemeral.pub] = m_transfers.size()-1;
if (output_tracker_cache)
(*output_tracker_cache)[std::make_pair(tx.vout[o].amount, td.m_global_output_index)] = m_transfers.size() - 1;
if (m_multisig)
@@ -2352,7 +2398,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (0 != m_callback)
m_callback->on_money_received(height, txid, tx, td.m_amount, 0, td.asset_type, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time);
m_callback->on_money_received(height, txid, tx, td.m_amount, td.asset_type, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time, td.m_origin_td_idx);
}
total_received_1 += amount;
notify = true;
@@ -2366,14 +2412,22 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
// Add the change output_public_key to the list of subaddresses to check
crypto::public_key P_change = crypto::null_pkey;
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(tx.vout[0], P_change), error::wallet_internal_error, "Failed to get change output public key");
//m_subaddresses[P_change] = {0x50524F54,0x4F434F4C};
//m_subaddresses[P_change] = {0x50524F54,0x4F434F4C}; /* {PROT,OCOL} - seemed like a good idea at the time, but harder to implement! */
m_subaddresses[P_change] = {0,0};
m_protocol_txs.insert({P_change, m_transfers.size()-1});
//m_protocol_txs.insert({P_change, m_transfers.size()-1});
m_protocol_txs.insert({tx.return_address, m_transfers.size()-1});
if (tx.type == cryptonote::transaction_type::YIELD) {
// Additionally, with YIELD TXs, we need to update our "balance staked" subtotal, because otherwise our balance is out by the staked coins until they mature!
// SRCG: must remember to deduct the number of staked coins when they mature!!
LOG_ERROR("***** STAKED COINS : " << tx.amount_burnt << " *****");
m_locked_coins.insert({P_change, {0, tx.amount_burnt}});
}
}
}
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx_scan_info[o].amount)
{
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
<< " from received " << print_money(tx_scan_info[o].amount) << " output already exists with "
<< (m_transfers[kit->second].m_spent ? "spent" : "unspent") << " "
<< print_money(m_transfers[kit->second].amount()) << " in tx " << m_transfers[kit->second].m_txid << ", received output ignored");
@@ -2389,7 +2443,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
else
{
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
<< " from received " << print_money(tx_scan_info[o].amount) << " output already exists with "
<< print_money(m_transfers[kit->second].amount()) << ", replacing with new output");
// The new larger output replaced a previous smaller one
@@ -2414,6 +2468,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_asset_type(tx.vout[o], asset_type), error::wallet_internal_error, "failed to get output_asset_type");
td.m_asset_type_output_index = asset_type_output_indices[o];
td.asset_type = asset_type;
td.m_origin_td_idx = origin_td_idx;
td.m_amount = amount;
td.m_pk_index = pk_index - 1;
td.m_subaddr_index = tx_scan_info[o].received->index;
@@ -2448,7 +2503,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (0 != m_callback)
m_callback->on_money_received(height, txid, tx, td.m_amount, burnt, td.asset_type, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time);
m_callback->on_money_received(height, txid, tx, td.m_amount, td.asset_type, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time, td.m_origin_td_idx);
}
total_received_1 += extra_amount;
notify = true;
@@ -2464,7 +2519,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(tx.vout[0], P_change), error::wallet_internal_error, "Failed to get change output public key");
//m_subaddresses[P_change] = {0x50524F54,0x4F434F4C};
m_subaddresses[P_change] = {0,0};
m_protocol_txs.insert({P_change, m_transfers.size()-1});
//m_protocol_txs.insert({P_change, m_transfers.size()-1});
m_protocol_txs.insert({tx.return_address, m_transfers.size()-1});
}
}
}
@@ -2675,13 +2731,25 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
payment.m_fee = fee;
// SRCG - figure out what this needs to be (pretty sure we should never get here with CONVERT!)
payment.m_amount = source_asset == dest_asset ? i.second[dest_asset] : tx.amount_burnt;
payment.m_asset_type = dest_asset;
payment.m_asset_type = (tx.type == cryptonote::transaction_type::PROTOCOL) ? "SAL" : dest_asset;
payment.m_amounts = tx_amounts_individual_outs[i.first];
payment.m_block_height = height;
payment.m_unlock_time = tx.unlock_time;
payment.m_unlock_time = tx.unlock_time; // SRCG: this is incorrect - work out which vout entry it is and query that
payment.m_timestamp = ts;
payment.m_coinbase = miner_tx;
payment.m_subaddr_index = i.first;
if (tx.type == cryptonote::transaction_type::PROTOCOL) {
if (origin_td_idx != ((uint64_t)-1)) {
// Get the origin TD information
payment.m_amount = payment.m_amounts[0];
payment.m_tx_type = m_transfers[origin_td_idx].m_tx.type;
payment.m_fee = m_transfers[origin_td_idx].m_tx.amount_burnt;
} else {
assert(false);
}
} else {
payment.m_tx_type = tx.type;
}
if (pool) {
if (emplace_or_replace(m_unconfirmed_payments, payment_id, pool_payment_details{payment, double_spend_seen}))
all_same = false;
@@ -2766,6 +2834,8 @@ void wallet2::process_outgoing(const crypto::hash &txid, const cryptonote::trans
entry.first->second.m_timestamp = ts;
entry.first->second.m_unlock_time = tx.unlock_time;
entry.first->second.m_tx = (cryptonote::transaction_prefix)tx;
add_rings(tx);
}
//----------------------------------------------------------------------------------------------------
@@ -4031,6 +4101,7 @@ bool wallet2::clear()
m_blockchain.clear();
m_transfers.clear();
m_transfers_indices.clear();
m_locked_coins.clear();
m_key_images.clear();
m_pub_keys.clear();
m_unconfirmed_txs.clear();
@@ -4054,6 +4125,7 @@ void wallet2::clear_soft(bool keep_key_images)
m_blockchain.clear();
m_transfers.clear();
m_transfers_indices.clear();
m_locked_coins.clear();
if (!keep_key_images)
m_key_images.clear();
m_pub_keys.clear();
@@ -5870,8 +5942,9 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
catch (...)
{
LOG_PRINT_L0("Failed to open portable binary, trying unportable");
if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
std::stringstream iss;
//if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
if (use_fs) tools::copy_file(m_wallet_file, m_wallet_file + ".unportable");
std::stringstream iss;
iss.str("");
iss << cache_data;
boost::archive::binary_iarchive ar(iss);
@@ -5892,7 +5965,8 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
catch (...)
{
LOG_PRINT_L0("Failed to open portable binary, trying unportable");
if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
if (use_fs) tools::copy_file(m_wallet_file, m_wallet_file + ".unportable");
std::stringstream iss;
iss.str("");
iss << cache_file_buf;
@@ -6163,6 +6237,11 @@ uint64_t wallet2::balance(uint32_t index_major, const std::string& asset_type, b
uint64_t amount = 0;
for (const auto& i : balance_per_subaddress(index_major, asset_type, strict))
amount += i.second;
if (asset_type == "SAL") {
// Iterate over the locked coins, adding them to the _locked_ balance
for (const auto& i : m_locked_coins)
amount += i.second.m_amount;
}
return amount;
}
//----------------------------------------------------------------------------------------------------
@@ -6260,6 +6339,8 @@ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> wallet2::
uint64_t unlock_height = td.m_block_height + std::max<uint64_t>(CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE, CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS);
if (td.m_tx.unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER && td.m_tx.unlock_time > unlock_height)
unlock_height = td.m_tx.unlock_time;
if (td.m_tx.type == cryptonote::transaction_type::MINER)
unlock_height = td.m_block_height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
uint64_t unlock_time = td.m_tx.unlock_time >= CRYPTONOTE_MAX_BLOCK_NUMBER ? td.m_tx.unlock_time : 0;
blocks_to_unlock = unlock_height > blockchain_height ? unlock_height - blockchain_height : 0;
time_to_unlock = unlock_time > now ? unlock_time - now : 0;
@@ -6986,8 +7067,8 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
std::vector<std::pair<std::string, std::string>> circ_amounts;
THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
// To-do - work out the source_asset and dest_asset.
std::string source_asset = "FULM";
std::string dest_asset = "FULM";
std::string source_asset = "SAL";
std::string dest_asset = "SAL";
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, hf_version, source_asset, dest_asset, sd.tx_type, sd.change_dts.addr, sd.extra, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, sd.use_rct, rct_config, sd.use_view_tags);
THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype);
// we don't test tx size, because we don't know the current limit, due to not having a blockchain,
@@ -9049,8 +9130,8 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
LOG_PRINT_L2("constructing tx");
// To-do - work out if the "transfer_selected()" method will ever get called - if not, just remove it.
// If it _does_ get called, it's necessary to work out the source_asset and dest_asset as well.
std::string source_asset = "FULM";
std::string dest_asset = "FULM";
std::string source_asset = "SAL";
std::string dest_asset = "SAL";
cryptonote::transaction_type tx_type = TRANSFER;
bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sources, splitted_dsts, hf_version, source_asset, dest_asset, tx_type, change_dts.addr, extra, tx, unlock_time, tx_key, additional_tx_keys, false, {}, use_view_tags);
LOG_PRINT_L2("constructed tx, r="<<r);
@@ -9114,8 +9195,8 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
bool use_view_tags,
const std::string& source_asset,
const std::string& dest_asset,
const transaction_type& tx_type,
const oracle::pricing_record& pr)
const transaction_type& tx_type/*,
const oracle::pricing_record& pr*/)
{
using namespace cryptonote;
// throw if attempting a transaction with no destinations
@@ -9233,7 +9314,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
// check to see if the tx_source_entry was a payout from a protocol_tx
if (td.m_tx.type == cryptonote::transaction_type::PROTOCOL) {
// 1. Get the correct TX pub key for this output (we know it is an ADDITIONAL TX PUB KEY)
std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
THROW_WALLET_EXCEPTION_IF(additional_tx_pub_keys.size() < td.m_internal_output_index, error::wallet_internal_error, "failed to obtain additional tx pub keys for PROTOCOL TX");
@@ -9251,7 +9332,8 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to derive subaddress public key for PROTOCOL TX");
// 4. Find the CONVERT/YIELD TX that created P_change
auto search = m_protocol_txs.find(P_change);
//auto search = m_protocol_txs.find(P_change);
auto search = m_protocol_txs.find(output_public_key);
THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate m_protocol_txs entry to permit origin TX usage");
size_t idx = search->second;
THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate m_protocol_txs index in m_transfers");
@@ -9329,6 +9411,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
// we still keep a copy, since we want to keep dsts free of change for user feedback purposes
std::vector<cryptonote::tx_destination_entry> splitted_dsts = dsts;
cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
change_dts.amount = found_money - needed_money;
change_dts.asset_type = source_asset;
@@ -9697,7 +9780,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
uint32_t priority,
const std::vector<uint8_t>& extra,
uint32_t subaddr_account,
std::set<uint32_t> subaddr_indices
std::set<uint32_t> subaddr_indices,
const crypto::key_image& ki_return
){
//ensure device is let in NONE mode in any case
hw::device &hwdev = m_account.get_device();
@@ -9779,8 +9863,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
uint32_t hf_version = get_current_hard_fork();
//const auto specific_transfers = m_transfers.at(source_asset);
oracle::pricing_record pricing_record;
std::vector<std::pair<std::string, std::string>> circ_amounts;
//oracle::pricing_record pricing_record;
//std::vector<std::pair<std::string, std::string>> circ_amounts;
bool b = false;
// Now perform all sanity checks specific to each tx type
@@ -9794,13 +9878,13 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
case transaction_type::CONVERT:
THROW_WALLET_EXCEPTION_IF(source_asset == dest_asset, error::wallet_internal_error, "Conversion TX must specify different source and destination asset types");
// Get the pricing record
b = get_pricing_record(pricing_record, current_height);
THROW_WALLET_EXCEPTION_IF(!b, error::wallet_internal_error, "Failed to get pricing record");
//b = get_pricing_record(pricing_record, current_height);
//THROW_WALLET_EXCEPTION_IF(!b, error::wallet_internal_error, "Failed to get pricing record");
// Get the circulating supply data
THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
//THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply");
break;
case transaction_type::YIELD:
THROW_WALLET_EXCEPTION_IF(dest_asset != "FULM", error::wallet_internal_error, "Yield TX must specify 'FULM' destination asset type");
THROW_WALLET_EXCEPTION_IF(dest_asset != "SAL", error::wallet_internal_error, "Yield TX must specify 'SAL' destination asset type");
break;
default:
THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Invalid tx type specified: " + static_cast<uint64_t>(tx_type));
@@ -10177,7 +10261,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " <<
tx.selected_transfers.size() << " inputs");
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type, pricing_record);
test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type/*, pricing_record*/);
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask);
available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0);
@@ -10198,7 +10282,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(
LOG_PRINT_L2("We made a tx, adjusting fee and saving it, we need " << print_money(needed_fee) << " and we have " << print_money(test_ptx.fee));
while (needed_fee > test_ptx.fee) {
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type, pricing_record);
test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type/*, pricing_record*/);
txBlob = t_serializable_object_to_blob(test_ptx.tx);
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask);
LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) <<
@@ -10272,8 +10356,8 @@ skip_tx:
use_view_tags, /* const bool use_view_tags */
source_asset,
dest_asset,
tx_type,
pricing_record);
tx_type/*,
pricing_record*/);
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
tx.tx = test_tx;
tx.ptx = test_ptx;
@@ -10351,7 +10435,14 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, s
check_tx_proof(ptx.tx, address, r.second.second, "automatic-sanity-check", proof, received);
}
catch (const std::exception &e) { received = 0; }
received += ptx.tx.amount_burnt;
if (ptx.tx.type == cryptonote::transaction_type::BURN)
received += ptx.tx.amount_burnt;
else if (ptx.tx.type == cryptonote::transaction_type::CONVERT)
received += ptx.tx.amount_burnt;
else if (ptx.tx.type == cryptonote::transaction_type::YIELD)
received += ptx.tx.amount_burnt;
total_received += received;
}
@@ -10446,7 +10537,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
std::vector<size_t> unused_transfers_indices;
std::vector<size_t> unused_dust_indices;
const bool use_rct = use_fork_rules(4, 0);
std::string asset_type = "FULM";
std::string asset_type = "SAL";
// Verify that we have outputs in our wallet for the correct asset_type
THROW_WALLET_EXCEPTION_IF(!m_transfers_indices.count(asset_type), error::wallet_internal_error, "Cannot find outputs with correct asset_type to pay for TX");
@@ -10578,7 +10669,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
tx.selected_transfers.size() << " outputs");
if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER, oracle::pricing_record());
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER/*, oracle::pricing_record()*/);
else
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
@@ -10615,7 +10706,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
}
if (use_rct)
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER, oracle::pricing_record());
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER/*, oracle::pricing_record()*/);
else
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
@@ -10654,7 +10745,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
pending_tx test_ptx;
if (use_rct) {
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra,
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER, oracle::pricing_record());
test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER/*, oracle::pricing_record()*/);
} else {
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra,
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags);
@@ -10965,7 +11056,7 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions()
unmixable_transfer_outputs.push_back(n);
}
return create_transactions_from(m_account_public_address, "FULM", false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector<uint8_t>());
return create_transactions_from(m_account_public_address, "SAL", false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector<uint8_t>());
}
//----------------------------------------------------------------------------------------------------
void wallet2::discard_unmixable_outputs()
@@ -11415,7 +11506,7 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
k_image = boost::get<cryptonote::txin_to_key>(tx.vin[0]).k_image;
}
crypto::ec_scalar uniqueness;
THROW_WALLET_EXCEPTION_IF(!cryptonote::calculate_uniqueness(tx.type, k_image, ((size_t)(-1)), 0, uniqueness), error::wallet_internal_error, "Failed to calculate uniqueness");
THROW_WALLET_EXCEPTION_IF(!cryptonote::calculate_uniqueness(tx.type, k_image, ((size_t)(-1)), n, uniqueness), error::wallet_internal_error, "Failed to calculate uniqueness");
crypto::key_derivation found_derivation;
if (is_out_to_acc(address, output_public_key, derivation, additional_derivations, n, uniqueness, get_output_view_tag(tx.vout[n]), found_derivation))
@@ -11431,7 +11522,13 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
//crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&n), sizeof(size_t));
crypto::derivation_to_scalar(found_derivation, uniqueness, scalar1);
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
if (tx.type == cryptonote::transaction_type::YIELD) {
uint64_t unlock_time = 0;
THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_unlock_time(tx.vout[n], unlock_time), error::wallet_internal_error, "Failed to get output unlock time");
if (unlock_time == get_config(m_nettype).YIELD_LOCK_PERIOD)
ecdh_info.mask = rct::identity();
}
const rct::key C = tx.rct_signatures.outPk[n].mask;
rct::key Ctmp;
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask");
@@ -11878,13 +11975,13 @@ bool wallet2::check_tx_proof(const cryptonote::transaction &tx, const cryptonote
std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t, uint64_t>> &account_minreserve, const std::string &message)
{
THROW_WALLET_EXCEPTION_IF(m_watch_only || m_multisig, error::wallet_internal_error, "Reserve proof can only be generated by a full wallet");
THROW_WALLET_EXCEPTION_IF(balance_all(true, "FULM") == 0, error::wallet_internal_error, "Zero balance");
THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first, "FULM", true) < account_minreserve->second, error::wallet_internal_error,
THROW_WALLET_EXCEPTION_IF(balance_all(true, "SAL") == 0, error::wallet_internal_error, "Zero balance");
THROW_WALLET_EXCEPTION_IF(account_minreserve && balance(account_minreserve->first, "SAL", true) < account_minreserve->second, error::wallet_internal_error,
"Not enough balance in this account for the requested minimum reserve amount");
// determine which outputs to include in the proof
std::vector<size_t> selected_transfers;
for (const auto& i: m_transfers_indices["FULM"])
for (const auto& i: m_transfers_indices["SAL"])
{
const transfer_details &td = m_transfers[i];
if (!is_spent(td, true) && !td.m_frozen && (!account_minreserve || account_minreserve->first == td.m_subaddr_index.major))
@@ -11973,7 +12070,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
crypto::ec_scalar uniqueness;
THROW_WALLET_EXCEPTION_IF(!cryptonote::calculate_uniqueness(td.m_tx.type, k_image, td.m_block_height, td.m_internal_output_index, uniqueness), error::wallet_internal_error, "Failed to calculate uniqueness");
// Populate this struct if you want to make use of get_reserve_proof() for Fulmo!!!
// Populate this struct if you want to make use of get_reserve_proof() for Salvium!!!
assert(false);
cryptonote::origin_data origin_tx_data;
@@ -12639,7 +12736,7 @@ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>
//uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
}
// Populate this struct if you want to make use of check_reserve_proof() for Fulmo!!!
// Populate this struct if you want to make use of check_reserve_proof() for Salvium!!!
assert(false);
cryptonote::origin_data origin_tx_data;
@@ -13260,7 +13357,7 @@ process:
//uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
}
// Populate this struct if you want to make use of "import_outputs" for Fulmo!!!
// Populate this struct if you want to make use of "import_outputs" for Salvium!!!
assert(false);
origin_data origin_tx_data;
@@ -13338,6 +13435,7 @@ size_t wallet2::import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<
td.m_key_image_partial = false;
td.m_subaddr_index.major = etd.m_subaddr_index_major;
td.m_subaddr_index.minor = etd.m_subaddr_index_minor;
td.m_origin_td_idx = ((uint64_t)-1);
// skip those we've already imported, or which have different data
if (i + offset < original_size)
@@ -13402,7 +13500,7 @@ size_t wallet2::import_outputs(const std::tuple<uint64_t, uint64_t, std::vector<
//uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
}
// Populate this struct if you want to make use of "import_outputs" for Fulmo!!!
// Populate this struct if you want to make use of "import_outputs" for Salvium!!!
assert(false);
origin_data origin_tx_data;
+33 -5
View File
@@ -140,7 +140,7 @@ private:
// Full wallet callbacks
virtual void on_new_block(uint64_t height, const cryptonote::block& block) {}
virtual void on_reorg(uint64_t height, uint64_t blocks_detached, size_t transfers_detached) {}
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const std::string& asset_type, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) {}
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const std::string& asset_type, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time, const uint64_t& origin_td_idx) {}
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index) {}
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const std::string& asset_type, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index) {}
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) {}
@@ -346,6 +346,7 @@ private:
std::vector<multisig_info> m_multisig_info; // one per other participant
std::vector<std::pair<uint64_t, crypto::hash>> m_uses;
std::string asset_type;
uint64_t m_origin_td_idx;
bool is_rct() const { return m_rct; }
uint64_t amount() const { return m_amount; }
@@ -381,6 +382,7 @@ private:
FIELD(m_multisig_info)
FIELD(m_uses)
FIELD(asset_type)
FIELD(m_origin_td_idx)
END_SERIALIZE()
};
@@ -437,6 +439,7 @@ private:
uint64_t m_timestamp;
bool m_coinbase;
cryptonote::subaddress_index m_subaddr_index;
cryptonote::transaction_type m_tx_type;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
@@ -450,6 +453,7 @@ private:
VARINT_FIELD(m_timestamp)
FIELD(m_coinbase)
FIELD(m_subaddr_index)
VARINT_FIELD(m_tx_type)
END_SERIALIZE()
};
@@ -471,6 +475,18 @@ private:
END_SERIALIZE()
};
struct locked_yield_details
{
uint32_t m_index_major;
uint64_t m_amount;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
VARINT_FIELD(m_index_major)
VARINT_FIELD(m_amount)
END_SERIALIZE()
};
struct unconfirmed_transfer_details
{
cryptonote::transaction_prefix m_tx;
@@ -1071,8 +1087,8 @@ private:
const bool use_view_tags,
const std::string& source_asset,
const std::string& dest_asset,
const cryptonote::transaction_type& tx_type,
const oracle::pricing_record& pr);
const cryptonote::transaction_type& tx_type/*,
const oracle::pricing_record& pr*/);
void commit_tx(pending_tx& ptx_vector);
void commit_tx(std::vector<pending_tx>& ptx_vector);
@@ -1094,7 +1110,7 @@ private:
bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type& tx_type, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices); // pass subaddr_indices by value on purpose
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type& tx_type, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const crypto::key_image& ki_return); // pass subaddr_indices by value on purpose
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const std::string &asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
std::vector<wallet2::pending_tx> create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, const std::string &asset_type, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
@@ -1154,7 +1170,8 @@ private:
a & m_blockchain;
}
a & m_transfers;
a & m_transfers_indices;
a & m_transfers_indices.parent();
a & m_locked_coins.parent();
a & m_account_public_address;
a & m_key_images.parent();
if(ver < 6)
@@ -1266,6 +1283,7 @@ private:
FIELD(m_blockchain)
FIELD(m_transfers)
FIELD(m_transfers_indices)
FIELD(m_locked_coins)
FIELD(m_account_public_address)
FIELD(m_key_images)
FIELD(m_unconfirmed_txs)
@@ -1681,6 +1699,7 @@ private:
bool get_pricing_record(oracle::pricing_record& pr, const uint64_t height);
bool get_circulating_supply(std::vector<std::pair<std::string, std::string>> &amounts);
bool get_yield_info(std::vector<cryptonote::yield_block_info>& ybi_data);
private:
/*!
@@ -1807,6 +1826,7 @@ private:
transfer_container m_transfers;
transfer_details_indices m_transfers_indices;
serializable_unordered_map<crypto::public_key, locked_yield_details> m_locked_coins;
payment_container m_payments;
serializable_unordered_map<crypto::key_image, size_t> m_key_images;
serializable_unordered_map<crypto::public_key, size_t> m_pub_keys;
@@ -1933,6 +1953,7 @@ BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0)
BOOST_CLASS_VERSION(tools::wallet2::multisig_tx_set, 1)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 5)
BOOST_CLASS_VERSION(tools::wallet2::pool_payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::locked_yield_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 8)
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 6)
BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 18)
@@ -2127,6 +2148,13 @@ namespace boost
a & x.m_signers;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::locked_yield_details &x, const boost::serialization::version_type ver)
{
a & x.m_index_major;
a & x.m_amount;
}
template <class Archive>
inline void serialize(Archive &a, tools::wallet2::unconfirmed_transfer_details &x, const boost::serialization::version_type ver)
{
+3 -3
View File
@@ -148,7 +148,7 @@ namespace wallet_args
if (command_line::get_arg(vm, command_line::arg_help))
{
Print(print) << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
Print(print) << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
Print(print) << wallet_args::tr("This is the command line monero wallet. It needs to connect to a monero\n"
"daemon to work correctly.") << ENDL;
Print(print) << wallet_args::tr("Usage:") << ENDL << " " << usage;
@@ -158,7 +158,7 @@ namespace wallet_args
}
else if (command_line::get_arg(vm, command_line::arg_version))
{
Print(print) << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
Print(print) << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
should_terminate = true;
return true;
}
@@ -209,7 +209,7 @@ namespace wallet_args
if (!command_line::is_arg_defaulted(vm, arg_max_concurrency))
tools::set_max_concurrency(command_line::get_arg(vm, arg_max_concurrency));
Print(print) << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
Print(print) << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
if (!command_line::is_arg_defaulted(vm, arg_log_level))
MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level));
+1 -9
View File
@@ -153,15 +153,7 @@ bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads
tpool.submit(&waiter, [&, i] {
*(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(local_nonce-i);
const uint8_t major_version = hashing_blob[0];
if (major_version >= RX_BLOCK_VERSION)
{
crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data);
}
else
{
int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0;
crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash[i], cn_variant, height);
}
crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data);
});
}
waiter.wait();
+8 -6
View File
@@ -451,7 +451,7 @@ namespace tools
if (!m_wallet) return not_open(er);
std::vector<std::string> assets_in_wallet = m_wallet->list_asset_types();
std::string asset_type = req.asset_type.empty() ? "FULM" : boost::algorithm::to_upper_copy(req.asset_type);
std::string asset_type = req.asset_type.empty() ? "SAL" : boost::algorithm::to_upper_copy(req.asset_type);
// verify that the asset is in the list of in-wallet assets
if (std::find(assets_in_wallet.begin(), assets_in_wallet.end(), asset_type) == assets_in_wallet.end()) {
er.message = std::string("Invalid source asset specified: ") + asset_type;
@@ -667,8 +667,8 @@ namespace tools
info.base_address = m_wallet->get_subaddress_as_str(subaddr_index);
//for (const auto& asset: asset_types) {
info.balance = m_wallet->balance(subaddr_index.major, "FULM", req.strict_balances);
info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major, "FULM", req.strict_balances);
info.balance = m_wallet->balance(subaddr_index.major, "SAL", req.strict_balances);
info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major, "SAL", req.strict_balances);
//}
info.label = m_wallet->get_subaddress_label(subaddr_index);
info.tag = account_tags.second[subaddr_index.major];
@@ -1102,7 +1102,8 @@ namespace tools
{
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
uint32_t priority = m_wallet->adjust_priority(req.priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
const crypto::key_image ki_return = crypto::null_ki;
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, ki_return);
if (ptx_vector.empty())
{
@@ -1156,8 +1157,9 @@ namespace tools
{
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
uint32_t priority = m_wallet->adjust_priority(req.priority);
const crypto::key_image ki_return = crypto::null_ki;
LOG_PRINT_L2("on_transfer_split calling create_transactions_2");
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, ki_return);
LOG_PRINT_L2("on_transfer_split called create_transactions_2");
if (ptx_vector.empty())
@@ -1587,7 +1589,7 @@ namespace tools
destination.push_back(wallet_rpc::transfer_destination());
destination.back().amount = 0;
destination.back().address = req.address;
std::string asset_type = req.asset_type.empty() ? "FULM" : req.asset_type;
std::string asset_type = req.asset_type.empty() ? "SAL" : req.asset_type;
if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
{
return false;
+3 -1
View File
@@ -35,6 +35,7 @@
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/filesystem/operations.hpp>
#include "common/util.h"
namespace tools
{
@@ -110,7 +111,8 @@ namespace tools
catch(...)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(file_path, file_path + ".unportable");
data_file.close();
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
if(data_file.fail())