Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42d8dc5ece | |||
| 89d426a739 | |||
| 199e47e076 | |||
| d24ed9e0cc | |||
| 872303f6ad | |||
| c56cfc6754 | |||
| de4e974e4c | |||
| 4607939ab6 | |||
| 9a37188885 | |||
| aee0f479c1 | |||
| 9f5e18495b | |||
| ae28c7a900 | |||
| b0ce6d2969 | |||
| 34b2f9b315 | |||
| 7bafd2866c | |||
| 606580a173 | |||
| a3a7f686f3 | |||
| a0d2044b5d | |||
| 3a032c58a4 |
@@ -37,6 +37,7 @@
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <typeinfo>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
@@ -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())
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <cstdint>
|
||||
|
||||
namespace tools {
|
||||
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 += "×tamp=" + 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace cryptonote
|
||||
TRANSFER = 3,
|
||||
CONVERT = 4,
|
||||
BURN = 5,
|
||||
YIELD = 6
|
||||
YIELD = 6,
|
||||
RETURN = 7
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 ");
|
||||
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+409
-142
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user