prep for alpha binary release
This commit is contained in:
@@ -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,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -231,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
|
||||
@@ -254,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;
|
||||
@@ -293,16 +308,27 @@ 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();
|
||||
|
||||
// count the current block's rct outs by asset type
|
||||
for (auto& vout: blk.protocol_tx.vout) {
|
||||
|
||||
// Get the output asset type
|
||||
std::string asset_type;
|
||||
if (!get_output_asset_type(vout, asset_type))
|
||||
throw std::runtime_error("Failed to get output asset type");
|
||||
|
||||
// Update the RCT outs
|
||||
num_rct_outs_by_asset_type.add(asset_type, 1);
|
||||
|
||||
// Update the amount tallies by DEDUCTING the minted amount
|
||||
if (slippage_counts.count(asset_type) == 0)
|
||||
slippage_counts[asset_type] = 0;
|
||||
slippage_counts[asset_type] -= vout.amount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,22 +340,77 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
add_transaction(blk_hash, tx, &tx_hash);
|
||||
for (const auto &vout: tx.first.vout)
|
||||
{
|
||||
if (vout.amount == 0) {
|
||||
++num_rct_outs;
|
||||
std::string asset_type;
|
||||
if (!get_output_asset_type(vout, asset_type))
|
||||
throw std::runtime_error("Failed to get output asset type");
|
||||
if (vout.amount == 0) {
|
||||
++num_rct_outs;
|
||||
num_rct_outs_by_asset_type.add(asset_type, 1);
|
||||
}
|
||||
|
||||
// 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 SAL
|
||||
boost::multiprecision::int128_t slippage_total_128 = 0;
|
||||
uint64_t slippage_total = 0;
|
||||
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>();
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -480,590 +561,6 @@ void BlockchainDB::show_stats()
|
||||
);
|
||||
}
|
||||
|
||||
void BlockchainDB::fixup()
|
||||
{
|
||||
if (is_read_only()) {
|
||||
LOG_PRINT_L1("Database is opened read only - skipping fixup check");
|
||||
return;
|
||||
}
|
||||
|
||||
// There was a bug that would cause key images for transactions without
|
||||
// any outputs to not be added to the spent key image set. There are two
|
||||
// instances of such transactions, in blocks 202612 and 685498.
|
||||
// The key images below are those from the inputs in those transactions.
|
||||
// On testnet, there are no such transactions
|
||||
// See commit 533acc30eda7792c802ea8b6417917fa99b8bc2b for the fix
|
||||
static const char * const mainnet_genesis_hex = "418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3";
|
||||
crypto::hash mainnet_genesis_hash;
|
||||
epee::string_tools::hex_to_pod(mainnet_genesis_hex, mainnet_genesis_hash );
|
||||
set_batch_transactions(true);
|
||||
batch_start();
|
||||
|
||||
if (get_block_hash_from_height(0) == mainnet_genesis_hash)
|
||||
{
|
||||
// block 202612 (511 key images in 511 transactions)
|
||||
static const char * const key_images_202612[] =
|
||||
{
|
||||
"51fc647fb27439fbb3672197d2068e4110391edf80d822f58607bd5757cba7f3",
|
||||
"d8cf1c1bd41f13c4553186e130e6e2c1cd80135ddb418f350088926997a95ca9",
|
||||
"95d2556c8acd1457dce7bfd9c83b1d82b821a55a9c9588b04b7b5cf562a65949",
|
||||
"4b5d987fee1bb563a162d23e41741ad73560c003e26a09b6655f09496538daac",
|
||||
"1d25ea86323d1578579d3894a54b99ea1c3e2dca547c6726c44aef67db958b02",
|
||||
"92e46fb70be5d9df39ca83c4fc6ae26c594118314bb75502a9c9752a781d0b33",
|
||||
"924d0cb9060d429be7e59d164a0f80a4dabc3607d44401b26fb93e7182ab435d",
|
||||
"f63e4a23fec860fd4c3734623891330ac1ff5af251e83a0e6247287818b8a72f",
|
||||
"5b14c5ef13738d015619b61dacefc2ade3660d25b35ef96330a8f4e2afc26526",
|
||||
"d5016b012a2fb6ca23fd56ece544d847962264b4aee15efe1465805fd824a8fb",
|
||||
"0a7f3da1d9dd341cd96829e484b07163099763ac7bd60603b7ee14f7dbcb278d",
|
||||
"d716c03d7447d2b693f6f61b6ad36bd57344033fc1a11feaf60d569f40014530",
|
||||
"23154a812e99ce226f6a87087e0812f419aed51289f1c0c359b0b61303b53a36",
|
||||
"03940341e1a99d5b0c68eacfdf5a20df90d7d0a3d6089d39709cdd964490755c",
|
||||
"ef09648814cfe071f5d8e9cfde57247ad09409265c4b6c84697bbb046809bd7e",
|
||||
"8843ec52b0496ca4e895813cfe00bb18ea777d3618e9bd2e200287e888e2f5c7",
|
||||
"8558bf39baf3df62b5d33cdf97163a365e6c44f4d6deef920730b4982b66449f",
|
||||
"504d9380ce581de0af97d5800d5ca9e61d78df368907151ab1e567eb6445332a",
|
||||
"673797763593c23b3ee07b43bd8760365e2c251a8a60a275528ff34a477110cc",
|
||||
"25178c95e4d402c58d79c160d2c52dd3c45db2c78e6aaa8d24d35c64f19d4957",
|
||||
"407c3a05dcc8bdcb0446b5d562cf05b4536fc7337344765215130d5f1e7ee906",
|
||||
"4e7fa771a5455d8ee8295f01181a360cdc6467cc185c2834c7daf9fbf85b6f1d",
|
||||
"6beb64cb024f9c5c988f942177fc9c1ec5ecfa85b7db0f13a17f9f98e8e46fe7",
|
||||
"6406bfc4e486e64c889ea15577d66e5835c65c6a39ec081af8ac5acdc153b4b5",
|
||||
"1b1da638709f9f85898af70ffaa5b88d5a4c9f2663ca92113c400ab25caf553c",
|
||||
"da49407a9e1ed27abd28076a647177157c42517e2542e9b6a4921fdadf4e8742",
|
||||
"3c3fdba2a792fddaeb033605163991a09933e8f05c6c934d718e50a613b64d69",
|
||||
"82c60429171173739fa67c4807cab359620299e6ed2a9da80139b5b1e23c5456",
|
||||
"0a19e5767e1381ac16f57cfa5aabd8463551d19f069f7f3465c11a8583253f3e",
|
||||
"d0fae6ffdd4818399eae6224978f170f696150eaf699f2f218abc00c68530f96",
|
||||
"0937889aeb3af5c64608d9a9f88229a068e53417448f00f9aa5e28c570cca8f8",
|
||||
"d6072d269753020912524961ce8c6930cf35abe5c4b2bdc7fd678338d20a68fb",
|
||||
"0e8bc9b06fcc842bdaa7df029bfd1f252d5defc014d58a006c10ab678ecf543f",
|
||||
"9d42f90520f02c9258be53b123d69ddbce5f33f92a903d3fb4cf3358ff0e07b5",
|
||||
"1cc05416b12cbe719617158773c3e6173435fc64e1ee44310dc696baecaeaa95",
|
||||
"266b15222913c11ef6403ee15dc42c8c0e16bc5fa2f49110447802236e045797",
|
||||
"791b123af3b71ac9497a010610f72207ff8ec642969b5cf0d2891b21e7eee562",
|
||||
"946d4d7b084dc32495f22b35fc30394144c8e0ba04f3ad6e2c2bfb0173a2266d",
|
||||
"2c015cb990c1583228d08b2d5de9227b950c3f57364fc1033bca5c0fbfd08c58",
|
||||
"13fdc41862fd85507f579c69accb9cc6a40f5971bfa41e3caff598a3dcffd2fc",
|
||||
"64b06d9874a83917c583c9439d1c736083377d67fda2961b623f7124663134c3",
|
||||
"2fa49cd19e0aa02989991a4c3760f44be800fe8fb4d58b23aca382e10dc0d2d6",
|
||||
"377628f265f799772e9fb6065be8b6eee200c329f729fe36c25ee179e4d20df9",
|
||||
"ba94fa79134ce383b6a98b04dc6ad3d1b950e410d50a292bc770f9685e59fe91",
|
||||
"875c924329f0733e31fe8d8aed70dc1906335b8a9984932b6368ea24edb39765",
|
||||
"f31f4abb3f5ee42a5aae86d70b3bd9a9c1934933641893864dd333f89719d608",
|
||||
"2bcd629e125514a780f568d3c2e8b12a2e7fbbee06e652bbeed3e7825508e31c",
|
||||
"918b43581163ca1963de21bb9ac401756e75c3f00ac8dcfafc139f1ad5d7d998",
|
||||
"5730dd57fa52749a0d6502b11c9d802ac495875542431310c674a65655b7c2a3",
|
||||
"03f84b990683e569e2f6143bb963a2a8de411e7c4b7923117b94c7afcb4b43ea",
|
||||
"b298c8510d35bd2be0ff0753ad7d98d480f4c6490bb67fb93cd4632ea726e8a7",
|
||||
"0a771afbf9be104c01b89eaeb57073297d35ac8fbbcc0816820fdb9a29d26625",
|
||||
"713d90d6ca1be1a4e05a5f8441dc528c699caa09eda49c09072f5f8291354c2e",
|
||||
"988827f45c19330d9404309f63d536a447803cca7cb182ef005b074def09ab7d",
|
||||
"9dcaa105b4def895f3faee704c250bdc924316f153cb972f3fb565beec0b7942",
|
||||
"1c06c30afe65b59e9e22d6bb454e4209a03efe53cdbf27b3945d5d75b1b90427",
|
||||
"49e08c13d1da209ec1aea7b7fbe0daa648e30febeb2aa5ffbaaabdd71a278ac2",
|
||||
"e1c2e49ab7b829854c46a64772ded35459908e0f563edbcf5c612913b7767046",
|
||||
"e08bb7d133490ca85a6325d46807170cd07618b6a5f6e1d069e44890cc366fab",
|
||||
"5c73ca0691cde2f35b7933d6db33f0b642ec70d0bd3f2b0ebbd97754ca67e248",
|
||||
"6404399151872a521dae767311712225dba65d810ba2feba209204221b5d772d",
|
||||
"4a0c3aa6cef36f44edf08ad8fb1533d7e1186e317da8a3afb3d81af072043233",
|
||||
"104b3e1af37cf10b663a7ec8452ea882082018c4d5be4cd49e7f532e2fea64e5",
|
||||
"e723a46bf9684b4476c3005eb5c26511c58b7eb3c708ddf7470ee30a40834b32",
|
||||
"18e6f0fa3aa779a73ceefabea27bff3202003fd2c558ec5f5d07920528947d57",
|
||||
"c97e73eb593ff39e63307220796cc64974c0c8adac860a2559ab47c49bc0c860",
|
||||
"13c363a962955b00db6d5a68b8307cd900ae9202d9b2deb357b8d433545244ac",
|
||||
"76a488865151fab977d3639bac6cba4ba9b52aa17d28ac3580775ed0bff393e4",
|
||||
"a14de587c9f4cd50bb470ecffd10026de97b9b5e327168a0a8906891d39d4319",
|
||||
"b1d38ee1c4ca8ae2754a719706e6f71865e8c512310061b8d26438fedf78707e",
|
||||
"772bb8a3f74be96fa84be5fa8f9a8ef355e2df54869c2e8ae6ad2bf54ed5057e",
|
||||
"3083a7011da36be63e3f7cacd70ab52e364dd58783302f1cb07535a66b5735f5",
|
||||
"2b1d892e3002aa3201deb4ffe28c0c43b75b8f30c96b5d43f6d5829049ecbd94",
|
||||
"cb738aabe44c6fb17ade284bf27db0169e309bf8cf9c91c4e4e62856619a4c64",
|
||||
"1707e04b792f4953f460f217b9bb94c84cef60736a749fb01277cfe0eaaa48c7",
|
||||
"ab8b6bac9b8a4f00b78acb4bd50ed2758e0fa100964b6f298d2a943eb2af2b30",
|
||||
"dd317193fef72490f3be01293b29e9c2f94eda10824a76ca74bf39dd7cb40ab2",
|
||||
"4fb3d995b087af7517fcb79e71f43bac0c4fbda64d89417a40ca4a708f2e8bc1",
|
||||
"549ba38c31bf926b2cb7e8f7f15d15df6388dce477a3aff0245caa44606849fc",
|
||||
"7585c14ab9abbffb89d0fa9f00c78ecae9f7c9062e5d4f1fae8453b3951fc60b",
|
||||
"953f855323f72461b7167e3df0f4fd746a06f5a7f98aa42acdce2eef822a0b2f",
|
||||
"0931932d57dde94dcfb017179a5a0954b7d671422149738260a365ca44f50eb8",
|
||||
"a3d179d16a4a275a3bb0f260cee9284db243abad637a9dbe92d02940f1c7ee8c",
|
||||
"959843f1e76ff0785dafe312c2ea66380fdc32b9d6180920f05f874c74599a80",
|
||||
"fbc36b3e1718fe6c338968b04caa01a7adb315d206abc63e56768d69e008a65d",
|
||||
"f054de7eac5e2ea48072e7fb4db93594c5f5d2dfa0afe8266042b6adc80dfdca",
|
||||
"39dfc68dc6ba8c457b2995562c867cef2f2cf994e8d6776a6b20869e25053f70",
|
||||
"19ad7ca7629758c22ac83643605c8a32a6665bae8e35dbc9b4ad90343756ebb3",
|
||||
"e89e80ea5c64cf7840f614f26e35a12c9c3091fa873e63b298835d9eda31a9ea",
|
||||
"572c1b9a83c947f62331b83009cc2ec9e62eab7260b49929388e6500c45cd917",
|
||||
"df0b21f679e6c0bf97f7b874e9f07c93c3467b092f3d9e1484e5646fda6eca5f",
|
||||
"8f3b7c0f4b403af62fe83d3cfac3f1e2572af8afa4cea3f3e2e04291efe84cf6",
|
||||
"aae8b8db243009d021d8c9897d52ee8125a17212f0a8b85f681ad8950ae45f0e",
|
||||
"3d45a4957d27447dea83d9ae2ef392a3a86619bfcf8dda2db405a7b304997797",
|
||||
"a5b0a619a8e3030b691bdba1ed951cd54e4bc2063602eae26d9791fb18e60301",
|
||||
"14650df217dd64a2905cd058114e761502dff37d40e80789200bc53af29b265f",
|
||||
"fd6a245ab5e4e6e18d7ba9b37478ce38248f0ab864e5511d2208ae3d25017e5f",
|
||||
"fbe0be6dd42a11feb5db5ae56fcbbac41041ab04a35f1df075580e960c8eeab0",
|
||||
"72f3f1213d9bec92ba9705b447d99cd0a6a446e37a3c1c50bb8ece1090bfe56e",
|
||||
"20df836554e1534f62b2a6df9ce58e11c1b9b4746ce8ee3c462300a8c01f5e76",
|
||||
"5c3d2a81b7331c86420ad32b6e9a212b73b1c3413724a0f91bf073eba18e2f1f",
|
||||
"63264ddfb29cd36fc18f3ee6614c4101ba7229bc5ac375f912590d3f0df982f4",
|
||||
"5ec4eb637761c1c9dbc6aa6649d4410508ef8d25d61ad6caa40c6ee3236d5515",
|
||||
"270c70940536017915e1cdbc003de7279ec1c94cba1ef6130f4236f7e306e4f0",
|
||||
"c1d1d57a7c03f6ddeeab5230a4910db8355e2143f473dea6e1d57c2f8d882b76",
|
||||
"218c030a7fdc9917e9f87e2921e258d34d7740a68b5bee48a392b8a2acf1f347",
|
||||
"ac47861c01c89ea64abee14cf6e1f317859ed56b69ae66377dc63e6575b7b1eb",
|
||||
"23bf549c8a03f9870983c8098e974308ec362354b0dcf636c242a88f24fc2718",
|
||||
"a3ce8b817e5212c851c6b95e693849a396c79b0d04b2a554de9b78933fbea2b7",
|
||||
"7310120c1cc1961b0d3fce13743c8a7075ae426fe6cccaf83600f24cee106236",
|
||||
"8fa0630f193777dcc4f5eccd1ad9ceacf80acdf65e52e4e01bf3a2b2fdd0dac6",
|
||||
"4a5f5c87f67d573d0673f01abaebc26eaa62e6d04627588549cc9e6c142dc994",
|
||||
"78971cccacc645116f9d380c167f955d54b386a22af112233f7de004fc0c8316",
|
||||
"badc67216868e1de1bbe044bf0e6070e6ee0353d05c13fa0c43b1897db5219a2",
|
||||
"c45b2a168bc51cbb615a79f97432cc4bb6b104da9cdc1fc640c930657452f71b",
|
||||
"c17eda13541d14554c5db542155b08b6bf9cb403d425745b662ebc2b2b9b3a3b",
|
||||
"313210cd9d2efc1603f07859bae7bd5fb5914f4a631b943f2f6ff5927a4e681a",
|
||||
"6ee94ec8af4e6828f9b46c590ea55da640ef50e810a247d3e8cdf4b91c42d2c2",
|
||||
"505b7a4d9f1ba6577aa2a941843f86c205b23b1ea21035925e587022e2f0aeed",
|
||||
"98e6a7cd687e8192e300a8202999ec31ad57bc34f656f2ae90d148607ff6d29f",
|
||||
"1be5db002c0a446cc2c1da363e5d08ae045cd8f5e76c8cccd65d5166393c0bdf",
|
||||
"17c02ac6d390c5c735e1e873c40294220e89071fca08a5da396a131fa1ba8670",
|
||||
"2540507c39ae6fdcd90de826077f0ca390da126166a25c15c048a60606a27367",
|
||||
"5ab9328e525c7a017ef4f591d995ad4595d74cbf8ff4112af33b08c70661a304",
|
||||
"9c105587a96c51d81422f64e46016564d22329760648c95dcac7218f3733f915",
|
||||
"525afb1b94a75f1edc2b55c700071e14a2166acda003370047c30dba8ea80278",
|
||||
"745d4a5d9f95ca4efa6261b6bcd4ecacd504b5b901a2ce1353c522a5c0c15dcc",
|
||||
"5a5a568cd87ba34252ba254e6a320e1a7f52f13e7451bb887efb34ff881785f2",
|
||||
"1ec50a80198cd830b51f4f7a0222015a268d9b40f04e7f838c7b8dc7abf63b01",
|
||||
"68836b662d79349cb42f5cef54e6a066157d398cc87d3b13f29fc04e5cf364a5",
|
||||
"658db317f355a9cbd86f673775cac0c308fe14967428fd283a36e300a6a53b2f",
|
||||
"677d79a8c467dd9db38f0ef45c2787dd368f701a6b47bf7a5f06112c38da643e",
|
||||
"2baa455d4066f5d628f9ecd315cb57deca71069db5d0d112ae0aa18a84b6f0d7",
|
||||
"5e7b0889f351560081360ac2b1429b48b2f7d886227f144e3b198e2f1fa56ed9",
|
||||
"c3d317fbf26e15add8b4f8f93df9de9b22297b8e4945ebab9ee249d4f72f4e45",
|
||||
"3c0b705a5c1e31abc7e46d8ff3c148a033f6875454cfb67f8d2a2b9a57a5ba7e",
|
||||
"a0ab74663561af2adc2d38be3569fbe7aa2454346416ac96e5eb26b1e01b1e2f",
|
||||
"53526cffdb74327670566c1dacacffb7d30a43a7f1862ff8bab87737bfa5edb6",
|
||||
"24c5d36ab98d88f87b2c71afb4ea8562e05c7aa0b50f3bc0f9ed50a4cd52989b",
|
||||
"c3ce4de5f94dff65d11e33a865855a4404259cf45263914c884f79db4f35169d",
|
||||
"f1009b6dcf30030cff872d636fb96ed233eb6ecb8ffed003c7da64e4f5a02f4c",
|
||||
"e3729f58614d3b42450d1599d863983ab7e3e5c29fb57aad7958c8923a2627c4",
|
||||
"31cf4792f7b5ce01b217ec80184edd2a7c49c0b21701f5494ee2c9bac67c28ca",
|
||||
"b42a5c9c92a656c5bb2b759ce160fdfd245243aeb1786338faea63b62e9a60ce",
|
||||
"a1efc8d5d0855933d5ac8fe5960c7acacb92fcb09bfbc929e5002f168251e648",
|
||||
"c4322c7f3682ec94b0dcb42f13b498c36cf575d505aacc8ec8bf67a6a2abf4c9",
|
||||
"684ee5aa3c98357aeaddcc30c6620939b52aeef729e24b4a46ccafc44f24d831",
|
||||
"36180f2ae11d105e0efbfbddb94e6b45b08609a383e4e1a8fa3b06d7a8051de9",
|
||||
"96c2d183eacc87581a0b17b8d07878bc10d436728510715109a7565d9972f8b5",
|
||||
"3068c9d04d561c7e29e3f621280b61a61885de0e9ec35a66a3116ca7a9e09627",
|
||||
"2eb94b9673ad6f8f88288fddfceae4baaeccb37bed88a35611d826ba06a5363b",
|
||||
"fc8cd5fae8b81121001f7767dcd5f185c0fdcc88cce1fbb184ddbcfad697ba54",
|
||||
"51521da1ecedea6d588d774eb155d936b32a14913c2f11d989bcc5116e65bf41",
|
||||
"3d23542e597a83dd6307700d79058b920f281c65f832333734d8a0adec510495",
|
||||
"11d2e01913ff0d4bd21970d709d88e63289492c0bbad7bff99c0d36858a841ca",
|
||||
"de674f1eee3068d2bc8c2f2897d8556e5deb872869652f7d3a4e5dbc6f1063c8",
|
||||
"e722d7f728526110c0921791b417afde4af1e87ae48ccc01911786197843104b",
|
||||
"aaba3a4e2a7d20ab76edfbcccefc27acfd509db3638582c28230e73ffd71d340",
|
||||
"1385a7209dafb9622dd4274179832e40c7fae19445383c34ef79adb0e4de0c98",
|
||||
"108408531fca288d74de4a2c596eab8569e355d9ab2f8380f4d24073a6b3fa95",
|
||||
"294476a86fcd39351ae452cdb8af9584067ec4501ec6182d0062bb154559fed3",
|
||||
"e64b175e0284c5cb69c8db46344ed43b5ced8abfe3cbf0c197103cfd116944cd",
|
||||
"cdd73a0f1fa7c14ed2177ae2163035333718847e49dd5cca6775bd20fc7553ad",
|
||||
"d423d2a374bc66a4587a5e3affa327ca75b8116051320759a3b88a868a7b80d4",
|
||||
"f13ad1e5b1315557d5497b58516eb3b0759d909725ddd0eb8a0dee439c6c0a48",
|
||||
"3a600b547a6061186a54e491344fd50cc7d4f0566a386a40aba6545254773728",
|
||||
"37a6f3f221fe17cc04a65aa544d5135e8297ecaf0853ba784dffacb74feb481b",
|
||||
"0ca42d67d0f84b28861d63e919e6ce5ad527447fdc53a03d8497a0241bee9376",
|
||||
"c7dbda42459e6fadb92c416eaef3e04674fc57915a93f3be4e656634c9654075",
|
||||
"0e34d728ae4fe347a5afecdf886fbd4d48a65c5d0dfab807da6ae95b6b2d7a3a",
|
||||
"f1bc69257ed510db5b2ed370010b037f452a29c49e36337264b3011ce2516216",
|
||||
"33f98f6b8a8e202463955998fba3b790199daa893e5471554826cfd9daa5c02f",
|
||||
"f8a0a37a2c9ebd7022d7cded1ee0318fd363020070b4cdaea800e44dcc1300d2",
|
||||
"6862714daedb908a4d86a3a3f1e65ec2c29ae61501b4ddcaf184243dd095d71b",
|
||||
"555cd19a6d21941c1174129b8bbcc70edcf0d6874262ce9e1e542351990d523d",
|
||||
"2cd6b44326828f23a2aa33699754bfa072c4883f39d53616f6a6b74149b664b6",
|
||||
"127f45d2eacb565c21c1030fe8054fd0a3a75705bc368924712aa145d414fa47",
|
||||
"19225e2dae6e1166f21cdab1290194470ded09df9b66f3faad3c1cc9ebcf340f",
|
||||
"b7b3f53f0539b2b4837b8bb9dae0ccbd200c8d36126d9f50199d68a4293a46d3",
|
||||
"6b6323be01f27d6d759d9670825e8ebb9c4cd8016351702328df91cef36cfec8",
|
||||
"020c31cfdfc5b22b10235745b89b311d271cf82f2ba16d03fdf7a8bc8538694b",
|
||||
"62573218530182b79e40d0113b7d281dace6da33bfcd0f9318558de5e5c76f08",
|
||||
"37d928416b15982f5bb8be40c5b62fae0b664e412c25891f8860c4242927e610",
|
||||
"b07ad11134a5c0542d2b418ef3863e8ea8477de68d9310681818ddd40825fdb0",
|
||||
"4af77cb76bab845b56470c95ce7b8cd84ce49a095984c1f3eed67b0ee344316e",
|
||||
"e3fdd4668d8726ba6adc401ac662c0cf6b5c1872082c488ed7da966d425fb1c0",
|
||||
"3dec71c81c7e78e879abc8da8b30e2446edbe98eeb8df9dafe9201ebb4c6a834",
|
||||
"7105467d9c5e855f1362fbddf820ed5e757997862efc9000317d3830a2f60ef3",
|
||||
"2821df94b021d3e77e8d9c0f3972340210f5ea2c0935cbf125cfc578d4d6722f",
|
||||
"114e5807accc337a22598bded30ebf3e0cfd75877e239f10cb043f829c315ab5",
|
||||
"d658a1c0354628cd7312593ab25d5b9083de8f0def6e8425f188101d256cd136",
|
||||
"4818d3be9b2a38fcc8c85d6c46f69b502943f79cf2462dfb0b6499e761bcc836",
|
||||
"92b8c943cb017b5f2d39264640c069f1ecced1d3ce9b3fd755d6df2fddb99458",
|
||||
"6edbd0fdf064fcbccd4a9e7a8ea520b87cb7faf867f7fe8a5f53625beb575119",
|
||||
"bf3b49c477dafb06af65bf09851c0fbef9dbc3152a7268d31b55a8e7a9a95860",
|
||||
"0e234dbadfda1393be2f068182615dbb83736f84f87710b5c7965bdce9f4a26a",
|
||||
"df5ceae34429e47b92bbd5505ba27666552e0eb619997f359c55699c3252b1ff",
|
||||
"08c1c7d940d699a91a83249bd578772e8958ffe23179e6150f07b96f1b47ce1e",
|
||||
"6f919a429270da0022d70062537bdc1b21c43a8abc552d8e366647e5b719d310",
|
||||
"63c66e5fd5d27f6fda87912ce46fa91a5e5b3634ed147fa2986330fc2696d3fa",
|
||||
"bde070b75296bca3aa494e7f549cd2bd1ff003776712bc98a3164b139b2054ab",
|
||||
"66694196dac5b60cf5e0ae05db8f3894fe04d65910686806551f471a0a0472e9",
|
||||
"0d2e97524b7ce4cf30b54e61b2689df036d099c53d42e2977b1671834bac39e7",
|
||||
"e081af76e923455f408127862be5c9baf7de6b19b952aa2a1da997d4dfe594c0",
|
||||
"121bf6ae1596983b703d62fecf60ea7dd3c3909acf1e0911652e7dadb420ed12",
|
||||
"a25e7b17464df71cd84ad08b17c5268520923bc33fe78c21b756f17353ea39a0",
|
||||
"e985f078fb44dbfdf3f4f34388f0f233a4e413e02297ee9a7dcc3fcceacd44f9",
|
||||
"b9184cf45e6e6b112cd863b1719de1bcab2137eb957e8028edca3a204a9ebb96",
|
||||
"157d177d5e4bcce0040eb4bddb681eacf9e2942e1c542a57ce851b4742a9cc4f",
|
||||
"0823e06635c9a1a69fd8833d1e48df98d711c1c47c06f27bb384932db1bbe9ee",
|
||||
"8beeec1fd1bcdecba235b449cc49abca69b6486ed1c0861a2bfb6a43c970b86f",
|
||||
"349f61a1cfc9112e537522858a0edae732a2f8434cf4780d3d2ec1e96f581cca",
|
||||
"587cdf72b5914d364f7e214a70481cf1131ee4a09e6b43e52428d2e56b000c13",
|
||||
"a6aa0c179316534c7b9ffb5f42a2af98d1d3a166bfb413199579f259c7b5e6df",
|
||||
"f9f3bb1ba8da5899b79186008ecfbd416b49f3b86d94045b91e34a40e41d5cff",
|
||||
"0cdda65a60b7b4d94e794c9397e01f69fb29309ce4fac83e7392dbba6bc497f9",
|
||||
"8fa5fce5ad09d43af7218ea5724cff2c4849a59ff73caf3bbca466e3c8538ba8",
|
||||
"8874ef46008753fcc0b77eb7a4a8560e35966bf5a12bcad4203ad2b4c1f8bfbe",
|
||||
"a8ee9a3aa2d0c08a951439ffb0e6d10315fc4776997b275de1ec19663e88c2c2",
|
||||
"9c184cbbff464ab4d5f6bfa78c39bf0880fb93b1574139306a97acb940d415c9",
|
||||
"5493a38c255c91ca49b958ed417f6c57e5bc444779d8f536f290596a31bc63d3",
|
||||
"3e1e82b96cc599d9fc55ae74330692ccbfb538a4cc923975fd8876efe4b81552",
|
||||
"16aaaf820c24c2726e349b0e49bbab72ca6eef7b3a2835de88d0cececa4da684",
|
||||
"7fa52ba349f7203c3dbc2249f9881101a3318d21869dd59f17abf953d234db65",
|
||||
"713d8018bb9ba3ab55c3a110120b9d7593514111075ef05f0fdb233ff2ceddc8",
|
||||
"56063afb495759a0942f1c33f28a4fb8320c6d376cb3c9513249453e45f24a04",
|
||||
"f9a6bacd9e055749b45174ecf3c3db18b78f3474761948a68adf601f54e59660",
|
||||
"7ddd7c6d41572f93fe07c0300c34e455b6d1f4372204933bf45035241c8b060c",
|
||||
"f81021b893a36b201de71330a2ea050b59dbf7560c62fa9cbea9261ab47a0ba2",
|
||||
"a01fbe4114c18fd534ae1621404d25c08e3b6775a2631ff40279bafd8c9304f4",
|
||||
"350fad8ebc938c6eb508a1483f385f577794a002bc1229db70a1b0131d174b9d",
|
||||
"570cb8bce87f532c5051d8c4c864012408e672a7d492669e660251fb1e066bec",
|
||||
"8cb6efbb129c84eba26d894c4293b476a6e9a1fe969c6ad18b554d2a57885f36",
|
||||
"f384a98467bf7f084ca31bea121a4ec76e530f523d3225c21ed25a18544a9916",
|
||||
"da127ab58ce557c2c95c20d6a291c2e5d880fff09dc28927b7bdfec97b995d72",
|
||||
"a4d95b4f74366ec920d0a0c5d81265688cc18733ffc444cac9b01ae2431568aa",
|
||||
"5ae2a71470570733422468bb733d53c85b1c8a6e7e6df5c05941556bcf342d1a",
|
||||
"65a2d161ff0e095d3afe37584dbbe649f1e9cd440755b5a3c5b2a252d5c0b8bc",
|
||||
"25ef70a8e41bb422ed7996a41160294e33238d6af17a532232f0a50b123431a2",
|
||||
"f1f0f76ee901664a65b97104296babb9c7422370e99bb677ae07c2ee420e7f40",
|
||||
"c3c66dda180b0330e75c8139b9f315a8c6b937f55d87d7be42e172bbac60d71e",
|
||||
"5881786695a9e58e19d79f790c7d9243a847c0269c5770bdd01f5149c2a62a88",
|
||||
"f2f816d3c8ebc7df06ab68d39223181aacc7be04364d1d4e69a56c33949bb983",
|
||||
"80a1c3b6b2778d4846ad9fe0bb2dd5afd99aa897f8231bfaac45fde43d602d9f",
|
||||
"72ad67cb043aa5df0c3dcc2464953a66893259d81c9cc7778c12bca3447fbd58",
|
||||
"ad72420a7963b8d4536d8eba00b4b989992247cd8c01660e242a8e71edaf0e19",
|
||||
"999d603d1cf6068e3bb6abe1bca976fa0ab84c4660b29ea8973de8b5cf5fd283",
|
||||
"e137a5910f02a764c3a3d8f1579ac0c7e3cc34e58933216868efe010332c1e6e",
|
||||
"10e0fa2362f59317626ae989bd1f962c583339d8d74d76c3e585243d152b91e8",
|
||||
"1951c652704962f5c6e33a4d4aadfee5d53ce2253644d1ed542da3e278524a07",
|
||||
"c938bccb7ba6c0217d8ba35ed91502aee051c8ae5bff05e88aab3b322aec936f",
|
||||
"4d6386c689785edd5beb55911a3a9fc8914838c8192184199589beef8b6ddf9f",
|
||||
"26f6f45a6468bc4b1f085fd28d63c264ee17564f9e247fc03ee179a0b579dcda",
|
||||
"235b7bb82b72c61acd5979ca5f2ca740aee805a780ba22e11aae5cd34f6ec760",
|
||||
"c027ffb585a1e4844b4907490b621b08c7e40a5e6f93e97bd4bb1b615bba9908",
|
||||
"aa77fc8053d139b998577319de29457b78b1cc8b35a5f3526c0621eaa42ce6e8",
|
||||
"afd0af9a11c5ae2a7c4a4571ce39ad57d8df70ef146ed83ad8eaff97b2387fb8",
|
||||
"a1f8fee9f1da9a2b306489d00edf754187b55e97f4fe6f249432fe6c7f44d6be",
|
||||
"4f12e8a123465a862060efb656299e6bef732e5954b02194308817b243e84d32",
|
||||
"6a1ca62f7d6952ad2eba1c64035260319baf03deabf856ca860744fc886b3d3a",
|
||||
"c72dd1fe890d6e4c1f7325a4f224e85aef6cdca8bf9441d228efaf126e02ba63",
|
||||
"2f6ddcea18d891ef4252e657989de68adcc43c2175d49c0c059c5e49b9dd5aed",
|
||||
"24efac0f240ed183c30398ee40307623f52113598f66c5864c90fc62643a2aec",
|
||||
"6ba3ebc935e7cf7fbb446e7f5c12b19c4455e6894412b0eedee4fc945e429e9a",
|
||||
"3519d6e5bc9649f97d07a07ef5471a553ffce35c7619f4f63e91a2ba38cbb729",
|
||||
"65e073df352fa9917e5c2475167e6c523b68c1406e1b6e81109e2d4cc87c740d",
|
||||
"d73bf816c3648a7d53d34be938c454e515efb0c974d5a225f33635540b2db90d",
|
||||
"bce167790fc86a273db011757d09e2d1148521ce242c2ded58f26cc49993aacb",
|
||||
"2d4286ed4039916f29602e86f47ea4c5b05998c0198509ca7799fcadfb337e8d",
|
||||
"9837c495b1af4f76b09177514a0f3e1dceb509c52b91712f3c7d29dc1b91d09b",
|
||||
"5c848b8291f39759903ce77f151acf40f3ab5afa2d4a45af62b320371c29a697",
|
||||
"b92df5016ee947ce6a21365d3361977f7f2f6c14025a983c44e13d3e8cc72152",
|
||||
"71d2f57222a39b1a7ed2df5e6fb23a964439b5a8e7d49b49d87e5cd5354baa75",
|
||||
"88b44d0198fb15b0c20a97f87e021c744606bfd35eae2874f35c447aa4ac3cd4",
|
||||
"29bb4c2557714119cd684da2867e689e37e3ca9c912db83ab84746816f6092ab",
|
||||
"b1836d98a288752675b133b9018fa1edf174f311921d01926c1e1a5900c21029",
|
||||
"a00645e090c7d96f3155ffbcfc41e526a763b0f53a98151ac4a7d4a5b14066b6",
|
||||
"78aab09919d17773b0d62799b37bd2e2970f72f5d1eb6472489c367b6135374f",
|
||||
"eb6123aeb28608f1c97b2bf62ef69f977cd0658a0ab491deebb1e972caa938c5",
|
||||
"8dd7ef1650b1b30cdf7814ae4d61a237eb0acc3ec3ce0f72b1c25780329c2d7d",
|
||||
"b1998419be3172858b990eea84fe10bb24b76c219cde277cb4305955fc7e0b65",
|
||||
"1b10560016c4bc506eef9056dedc2943a17179081e6eaf85b48d37dc20eac3cc",
|
||||
"1fb1d9d4d408a6734234910f554d272739a0d6fa401918d79b57be62c3f23ba2",
|
||||
"dec878f54ce36788289b61d32de0d9539032aba22cd15522752f729659c7cc5c",
|
||||
"fdbfd0773f5a66637b093dabf812197940d1134619a7e60a931b19915b7dab0a",
|
||||
"21bd2c9aae052a1c187947d2964f2be4afa7b30248409c41a75522e88a4e7977",
|
||||
"59326adab03416ec1d36699c18e5e4fa13ca1f2212d48c23bfdecb0be7263616",
|
||||
"bcf263d39457c0aef8ef42fd98f8131198ec4fb203155dd5bcd759e499a9ca5c",
|
||||
"f1ad083bcd8c7630eef93336d8a971ae8ae37166a6a00ac39684420c5f9afef8",
|
||||
"d82ee2ac41b36e3c1787a01835bf054070486dc20f6565efedbbc37cd3bf5fa5",
|
||||
"eba91a0dcbd3986299b0a3e66c116f77bd3421829291fd769522f01da26f107b",
|
||||
"11016558b7e8c6386c6a3e862691dcba47e33e257f0e7df38901ea7c0eba894c",
|
||||
"04f02795e34a0030e5186c8e700da8a46b1aa6bc0abed6b35c9c1cd6a73776b9",
|
||||
"2628dc8ad7fb731d59456b2755a99c6701467125fa69816c21bfccabc31edf6b",
|
||||
"9b7ca249ee5b45cd264492f30df09f708a7d9caed7beb9a5c6292f22e4c31f85",
|
||||
"5c42e7caedf382092faaf392174792b3cf5f2fe29cb586387ee55611af0617c9",
|
||||
"373f2fd5940a01feb79659c8b9099477f6d3e7b570ebb749c2ac336ea4be583d",
|
||||
"fea22887147adc3a659a14902080b03e86b4b8b16985fdf0bbacaed00d812422",
|
||||
"6a3e51a1443cff62af9fa12fafc8ea78ae74dac7792c9ae0f436f570ab33eb71",
|
||||
"796be21e213d6d0cd6fbe2de1555fb73d1cf9edc041a9f1ff1ad583c4ca92460",
|
||||
"03fcbcb31d3fd17f0eedb45ac5a51678c7c8b2b8498225d05f74e2892f017f72",
|
||||
"d28da07c6c22daf9ae987b3033c33d3140e5a56fa1ffd7dc5c7853d55a45bcc7",
|
||||
"fbb0ce02f50018741a12fc08eea80a18067d7bb0fcd96153d40bb8c808473aae",
|
||||
"2bf7c05a0209b4ea31314f04bd754cd01c58102d7cde8c496c655b6494924354",
|
||||
"1968a9e6e14ae86a1e02e6078fc4631851fce5dbac6aa34f860defd1ccfd0ded",
|
||||
"d886181329c9e06462a1407f547d77b38ff2c868b86d8976aa478e1cbb3d66d4",
|
||||
"0d465e02ff2f8eb0b5fb2fa9a38579c5d66337d4a16b58f8ed28d2d89fc02392",
|
||||
"3196419015289807880ef24b6781734822d654dc260c0560d00bac65eacd5219",
|
||||
"fa08390ddc333a2a12248d5ec3e51fff9b782227069fe5a0afbd8eba967ae8d1",
|
||||
"49ae36a791cb84516688d59a1ed3e5112851d65f265078aa2d433b45fa984c8a",
|
||||
"35daa428e12c59da6730760979aca3444d8b31149c6febd99fbfefa4b2372082",
|
||||
"5ef1d697beba612ff31d1dc139817c313a4e2ad3977775943b635c141ef0f2a1",
|
||||
"674256037ec00edb66b9355fb1d33a30a47a5d1f4bce2dd5475d89f1ea6502db",
|
||||
"7b6f017bc550933af91eec32a79464f540c5e0c208703e175843ee4e9ffc0a50",
|
||||
"bf0eb91da1d18dbb18fd9ff36c837387887ba142961176a44889718b2becb9dc",
|
||||
"3e5ac43a05164b074a2ff6353e9882917c5a3dbe168c2695de895f7decf1a56c",
|
||||
"35e8f004965347c2b18a000a83dd3a8084b8a4bf00522061ed1179aa1107c413",
|
||||
"fccb0fff3a24e555ec96f702ec11d420338910d148fc7b039d67568ad3a0e032",
|
||||
"5cab231048032dbf921b4fafa1951dd2da93bc3740667f31d5a1d5665b141261",
|
||||
"ffedb24be73441fbcd069f7785ebb865870e0f3ed228190732e4ffd5962bb82d",
|
||||
"a4fcfec18adf92f4ed822f64d2da9f5ae630885a1bfa626530f641db99aa7a30",
|
||||
"f98bcee41b0e3deafa1efaa1863750dbfd9bd7430b82529b670867d852230b5d",
|
||||
"8ab8d5fca047a52364a737c1af57bf656c9ad5049f08ef4c5aa252e61aa72123",
|
||||
"91318b39ad94c1d58143586b6d90dd6092a9d7487e321f4976967b6ac445ff43",
|
||||
"fabfbd4569ab018e12d5ffa9b1a40ca8eb2ca60a685817351d90eaa770d5eccb",
|
||||
"bbc5ef34428d980e2401942ceecfe07cdf21bfb1acae0596ea1d43fccf504f69",
|
||||
"26943e4201ea407a5667103fe07ca6e08ef76940f274349b0e2e776bcfb0acb6",
|
||||
"e3b305ffe33e72841f8e2a8688cc5cc27d42aee7624b33b7b6399b42db392437",
|
||||
"17c5a763dd57e6bcc7c4cf2db0eb5cf3e97116b67fe0dd519c97e4a4d55d5a62",
|
||||
"bbd260216879ce86af8318ffcf73c9e063ca76dd8bc35d3b6be45b2b4184888b",
|
||||
"41285591d0595bc42ab663051b410d51af39fe1720592e27acb1a8af72360a76",
|
||||
"f29acd6068ce494d0c0fe294cad91bb8968e3fff3f595a113227ab545c3ca3e6",
|
||||
"ec9013c6394528e7dd788ce7cc085ca79fcdfbb37565999d5b4b5a4e39452ecc",
|
||||
"27829bd7f1a8fcddcad0cc34a3b3fc67d62a2f3e09f8e75d35035c2281e83afd",
|
||||
"666bea9db4e15087204d076294d221d4cf5864f5d94de38f29132b1934a17ace",
|
||||
"a3a30924cad3dbda3446e5a6324e0a1390c70f795d5ecfe17ee5c70b14f7d87d",
|
||||
"19567fe5fdb10711d60aa4d9843e1c49c2a6d2fd1b5cf662e2105606bb7815d3",
|
||||
"b139f1c3a2f15596b9320334e37e4184d5d584c4a81e72d821a7edcad3aa62d5",
|
||||
"08f1531e0e3e8f8bae313b2c60a72d5601bf8b60d7a4d2f60e8481650340d250",
|
||||
"c5895669e1ff182bf1dd6c00dc955265e08ded0952b8ca62a1c63ba11c99f4ca",
|
||||
"84d1c28153f66c1a4eb5fa0df695e936d83294df31a08d8d8e2d4798d19d8ce0",
|
||||
"b8699f6af853fdbe897848feb46a05d733363f304eac4c8c1932e6ea4bc062cb",
|
||||
"10eb3f6c1d0661468d9ed83593e5e9c0b43c6feec6a5405a498194905ea6ed48",
|
||||
"509e215a600d9cadcbf5d62632ba321d7314764218db00ce8c907e425fccc445",
|
||||
"e62119b7be84c8eaad41ba7f4a35da403f4ed96b967a3134e89ee8b78f8792c2",
|
||||
"f790754a95d59ea5ffe6b9b5cc386c600a9e19e8bec997c192764365f1d05376",
|
||||
"990121b5aa4d6badfb7154db4cdbb4512124bc2f442bebac71ea90b5cc86f203",
|
||||
"b6983dedaa891eb14c964d84461e5cd37ed27b61771c64978ba83e3ecea194fa",
|
||||
"00fba1ceaa6aa1e378cd5b22a771d6070250ac37f4e17d7bf1a70b3139e9a860",
|
||||
"429854e7738abf2ecf46909454039e2fc5a080eb9a3c0c5ea13b07426dac3ad9",
|
||||
"ceb3e017944b0dd787be219d8629930b3f2e20e22b12dc88fd838488ebb896f3",
|
||||
"eb9e5d14424c63e675fe771b73ca865f7d38cf334d65e2426e12a0b88c1a2236",
|
||||
"556ee713449e6e59ac4b8b2e8310180c8f6280484e9db23456526cceb9216168",
|
||||
"bc89c3aa889e0144ac526a1f861227430dde7e439cc6a7e9b25c9a049c3ca7b3",
|
||||
"56d070c62ea99be66fff741a8e45fafda5f9ff783e84d5395b251f356ce4e16f",
|
||||
"ace15859c399e5ecd13b1420d3c3703c6a88dfb4a084f7225e7ba40a4b444fc8",
|
||||
"f03f1261ab6eb879fe9c5b0028cd400b3ffdfac4344e4c75f6cde3c05ded1f26",
|
||||
"955b2fda8d0068226f89270028b316b5adac871f1c1c85435479aba14a381b0f",
|
||||
"422509a98d7461a6b8ec87cbb173b2486577b59ea9b269e01c20567b38b3b3b2",
|
||||
"007d4de62ad89a4f5985f0cd9b76a7293acf383b4e9e734e813b9df1d57f986f",
|
||||
"13a04e32948225b7e22aa0137341ebbb811e0743032fac16be9d691a652db2eb",
|
||||
"8244b11d880a52f9f9e1830a822e6eeeaf0b12fc759f8261bc2f490cb0794f3b",
|
||||
"27d3415f8f8fd3048a1ee0d9487256dd1b0f9e31be663778efa5b3add63868ec",
|
||||
"0053f888db916a8905320e253fe2f0666355e6fb6de36f897231920a3edfe39f",
|
||||
"0bc5c0a2ea47fa3bb8be107e3b9d6b7226b1c8bd16ca1bab8f51b8e1de08aa8b",
|
||||
"4ca13aaa161c79025b5cd6c9a8ac33554f5ceb479fe293d9a342c865cd9c9948",
|
||||
"333afbe82e2a3df38bd1ef998f39c5feef2554697aa21b5410c0e95ef9156249",
|
||||
"587c4fcabd18ff890064171fce3d5be0c4aa1bba46893fb6a827a85ab54d20f3",
|
||||
"964328e4d51d67c4e2f1fd102a66b861d98199f81d18d660b1b4b52504cd772a",
|
||||
"196aad5594651efd679d30b9feb0f0d172cf977b4f89aa670ec741a8bf21e669",
|
||||
"9137bfd66bbf47bfa0bfcbb9f6e71b6eb3fd9776530e9fd30d3dab19e182f35d",
|
||||
"8217392c4ed2313188f295d94148a027a7f43824a5f5fba33a0b8c1045d509b4",
|
||||
"be9e12761519a4836e73015544163254877e1c4912fcea67a10e7026421dde75",
|
||||
"7b5220421a520b876cc6cdba0d3895104d7fac914dca5b93f9fe8b226566b71e",
|
||||
"5c83fccfeb4bf0eb8a94d43ebc84a81639a32f26c7ef77d0a2b626b7de7befdb",
|
||||
"132fd6c92cf176f975efdb5ded53470b462a48a2815c6f54a93ce4f935784cc7",
|
||||
"46a3dba364022d11aa616a2bc20e3be5c4390f38b9446edfa464d90d9af5d48f",
|
||||
"34b3f3fd8a83905a37762060f51d0b116377b4820b031b8e668e16f46c5b0285",
|
||||
"f0e397e033dabec859a4b9a9043c5f1fb0dba504764d6bcf2fe9bf2ffd318474",
|
||||
"85ecf59c7dd3b24ad17f591bc4737f32f1384c370a7a6f2add06a811dc824b6c",
|
||||
"4d03cdb1e6ad8e066a83654626d8c221433e8d4fd901c671300af37e000177f2",
|
||||
"61cb9c651893e6401b25f2bdf79c9f3ddc9ffe69cf6c791c420462bd73e347e1",
|
||||
"85f2686a42158cd5ad327781ecccd1bdcd346941dd4b4edc45f717de6a011800",
|
||||
"92de2ab82cac528e6d4ccd61e5b7c79591dcad9909c8ad3c8276ece6d48c0f08",
|
||||
"23a878a06bb94bff33083349149f3c860f2b00bc3fb28f04cbaf717c08af19a3",
|
||||
"1b1cce18ff0323566b192885d7ced30f9a9531a2580240f2c593a7d5b8580974",
|
||||
"08fcdec7ea1376d84f3b13a47a4b73c7781c9c7890bb28f712b58af4fd3f24fe",
|
||||
"03cc08fc4ece807c6495272c412be23b045622cc6b786ed8d5c94156ae678a0e",
|
||||
"c4d8a61dc3f5dcf4b83f27a90cbc37e816cf4754e12309626ec5679c99087c46",
|
||||
"b29d00681e29001cdd63c4bc50e5e25715faef692aeebb678c8050e1c095e888",
|
||||
"ac154617e93f2bb1afa232675f2135437a9cc9700c14c51c40084946596ba11a",
|
||||
"ce9549de8e68ae89f424dd9e1cde8a4eea2069da667cfcfbe837691d37366668",
|
||||
"426c45a98e2af35cc9708149f6c086ff5a3972e77d62c627d5e20de5d731cad8",
|
||||
"7e21bfe240a3d9b77a129c734a1d428dbc890379fbaf862853f48b2f7470b2b0",
|
||||
"fa090a71f77223a7210de6db18d9aa809e89fb15253aea28131df6c5a7639140",
|
||||
"7094ad044c5ab025e088b43aa0b947601fabe58ed700a412fd96e4b917ced0c8",
|
||||
"936d5cdc4f081b6fe36c356af4378d472cd7990303f2ea44da645afd7d5d7f9c",
|
||||
"05342037d3b69349dce7b95529d4b2a63ceb9d9393217a68f7cc8c958a96c3ea",
|
||||
"ff9e1c414ef27b1178b1de296526f50520b7ddb06286bf9c47792bfb449e40b6",
|
||||
"2f2b7bedb34d2854b17ccb702cddd8bc0157e39721d58be0b2ad54ee291fc9f1",
|
||||
"0d8db1f34140bbf7eb809137018a74af08cb3345b8a3e368cdda8521dab45791",
|
||||
"b109e4bfabcfe4a1c38be1156d9ca851c75e6aa2e57c0869e40cd9056f571e07",
|
||||
"5cb363547ca077c806fc69bc8c2006831ab89e72fd778ac1a48fa810934e350e",
|
||||
"85ee928bb110fd64eae54a91fc8548883e7fc4c60a3c61b505c31cea2d295c86",
|
||||
"1ec3df7d10ee6fd5f0532ad4fe771e6befc28b0bed0250bf523695d6d49a8246",
|
||||
"de9db2fc07c866bd7b885fb41522b63d550d0ce2e8ac5e14464a41733c2319e6",
|
||||
"9a27136422a8f56768db29ba172a7ba26c3c7aa910324e78e5ab3a3268ac3674",
|
||||
"60213c315119bf9005cb533d1a5b403b4a13c59982fe7773d30fdd8f519f4205",
|
||||
"40eb61ef1812eb8a4d389599bf449fc86653b2c4986061b952f46fc049de53f4",
|
||||
"658ef0d8140162b5f04591be13b47456245f531208bbca3260b857ca09b803c5",
|
||||
"02270fa66255048d724894e2206b4e773cc6a7b6d17ca090cdc25f317d5f53b9",
|
||||
"2ec6a0147f419161f7198d05be5f93152d9ccc10672db0ea47ff1687c0f0dd15",
|
||||
"4be1d8ceb96eb80ef7ce30079ded31163272aeccff5c18fe3aaa32ea2f5bed9d",
|
||||
"04ecaf48f44de87243b17b4c71ebff00020738639336010fa57435a54b623798",
|
||||
"e313a9feb7cfd1d56ec87b1f1062ff9a80da498f7b761af4bef0cecd1b4c385b",
|
||||
"ede3748f971f22341f7f5844dc60fc03cdb30c7cc720ebe13ae588c17a78aa94",
|
||||
"d90c0faa70e39b7c0a8c55457ed6e6478a4e4bf3707b08104326a1ee8377c3ab",
|
||||
"c79ffd0bbc8d004cc542e212990df6498abddd3deb50fd00ed00a2ff690974d6",
|
||||
"35c37d88cf73a89c4124b0ee537347c37fdb47156c8b0ecc509efc58236ed3f0",
|
||||
"a99182f343ccf05e557ffa6df71f03688b2afcf314c59daa774fe78db6f47add",
|
||||
"01115397a78af8a4ae2727ca7a01843235b626bd3db80888d3dfd0020d4135e2",
|
||||
"4a55aced578470d2f7280096d7fe8095f294095fba4778d1977d6db9270472f0",
|
||||
"4624adf8a5633f65b213b8ca46b55cb0ee36c41495f39b1ae70cbd545779b1a0",
|
||||
"d72bcd5b57a9c47e7bd5e9a1103657d10beb7b6c6d41f2b2985bc3bd3cc74860",
|
||||
"48baadb9a46293c92f29e7617846171356a42c3b5d18d49a05a7e173993785f7",
|
||||
"3da927737af8cb0e1c77097e35c54158d18aabfb3051c45bcc7ddfe00b157b1f",
|
||||
"b4a24bfdb2cb802c8d48a3a18fbfe18622a767fe7eddfca57d4555550ccd1643",
|
||||
"c58f82ac7c49dcba1721a88358f07636c9df60d3fd383e5789b808dc57a1dc9d",
|
||||
"5e1f756eff5155df073d30f4452bdafc4adaf4f35960771bf2c1e30137fd7a79",
|
||||
"be4a332f289338d67bd4834eae3128c488a61d255e972da484b6252b67a46b89",
|
||||
"d496e4a36238d03a83d8b45cf33d9388aa7568a279b034d1cdd87b457356cc5b",
|
||||
"a1c5212730ccda34de393210e276bbd44720dda777bcfd602315a3eee582f7dc",
|
||||
"08914ec63f6ef7fe1d678937dc0f6178883440b26b4aca29fce79068947e8397",
|
||||
"49e2cd2bd9b974074d9814f93eed371620bd4ea5fbf97a625065704e8fb382d7",
|
||||
"047c194111818b48ce93a4b006e4a09b9a2650757a87357111796e11e847bf23",
|
||||
"5955b0baa8265341f35a6f24fdc79066ba3ca9c5354c69b6b37a9ef3a26be556",
|
||||
"d7c962f3ea1938c5267cca4072548acf3afcce4d438ed62027caa211a5f98e8b",
|
||||
"c8cfba67cb4ce7e291b35154a50476d9a5c6bbb5d6cbaaa5d2408547fea7b02b",
|
||||
"de8a940d8a69a64ce264d2ab7320662aef2e391c587cb2aae22a86718d5dffbb",
|
||||
"94176f1310b26e54d4de48f87b74aa0b60532f184a2268508dece86dd7f85d36",
|
||||
"9ce6ee3fca56c9256a69df404782301300a6e5e7f5a25a1f6d68c0e9e42584c9",
|
||||
"7c423c4a220c6ff43ab6432f92b166323c58ee77f8c096ba0b00d52d7bd507e8",
|
||||
"0b62b9c1ae4d4988720e8d41d980b334458189de0a3dd01699338d7b07c3894e",
|
||||
"64f45f6f75110624506c53716f2fc1d5fe5f88f82a5bc6a7459ce70eae56dbb3",
|
||||
"12ffbeb8e52fed161af4d8a015d1a5c45dcb8240e5c8933ce3a88ba2c58f97e8",
|
||||
"2ee6b7b96043c8ded9fb52f87cdd0d0580ca6f8cef183c8a656394a11c0aa393",
|
||||
"aaef26b1f5726258bf9ce305a3e54bca65cf68779f90f9d24287245c27362e27",
|
||||
"ef59588dce57c35d010bea4d209f44c62f0b7c7e65bc0226c0e4971934da9435",
|
||||
"0e606c2f6f8dcd579faf4739312bd7327ac7796fa44a81780fe0d66fc7761fb9",
|
||||
"2f307198afdbde5f95989a17e06ce1bb9ff36c441cf3b2248431534fe13bb9fe",
|
||||
"51418e6df23d450aaacc74ef2df53a6b1693727b70bda9ebc43acfc23d8fb5ea",
|
||||
"6e9e3ac46705ed80520695b924435b00d2b3079598bf7faca7fd1524be777e5e",
|
||||
"1e96241e2876aad29ce64f5d7e7fbb8db7265449df816c0d30a96633778c5cb6",
|
||||
"81788f00eb72696d811f946e65d2c96528c45590874a1defdd46651e9b79a3a1",
|
||||
"d9aa5a9f1df50e933d7105a5d72b5fe96bfbb9fd4b5b0eaa5e80af12e72d497a",
|
||||
"e1b6976a732d27fc5d6a96b6d3d0d1d5eaa6ec46bae4665f17e7a43aefc75280",
|
||||
"9151c75edcec1cc90aa2d2c240ff657b0eef3f5f1ec37418c8854b2493114f1d",
|
||||
"3e7c12d0132421f08ea0a390cfa325e422a6b35120fb2eb650f108a165237934",
|
||||
"1ee0e85c7d8a91089c03f37318cdc9127026bf789e3ce4b75046eaa3eebd3458",
|
||||
"4ae64a3ef66cad847409ce175bd5365c9097fd21647a05730ac6b45841add3c8",
|
||||
"f0ea0f334cf1d64678a6dab08c07e2f94f339e8389bd17ebc882b5c8b736cbf2",
|
||||
"da904db96060546ff69e28993ce8183766da9402ac10fae9fc1f1d67ebd83c90",
|
||||
"db11820615f7b5e47778c45d2e083e77f49b608b587dc09ec26f077aba07a242",
|
||||
"ff5c726a83bd785484de75bb03b421f9e8e382bf2740120a2fcf72326aa01c75",
|
||||
"f8643a7efd6304980db323303ab73a6fd4f4ee1047520d39d571580395b97f21",
|
||||
"8facf9737d07838aedf6030593bfb247d8c29fe8d9b18b2913408627a4424d7e",
|
||||
"f0672964aa6e4c7dd4768e18827023787386927f4db89fd661444979afb43c18",
|
||||
"6fd3649c8401f2704ed2be18518b870eb6bf2b9a6689d1b336f05bd8b49017f6",
|
||||
"ed172dac7de827493e0c0fdd8d3299333acb678e72ed499e0224b389cc1e0fba",
|
||||
"7f9a8a8cc8e34add11934a1a5882be5978a6d28405cb0a053ec5699a502b1cef",
|
||||
"6ca829ebd2a0a40994f68c1db7978ec274b45c46e9b351df869a2bfe0630bbd4",
|
||||
"0bbb017c437573a55db88258a9d9a01188bdd23bb6b26903b137814871661f47",
|
||||
"9a6358d2541f46b6d05b80fe25a2cb025fbe9e4b227a6275908d5ee31c948569",
|
||||
"a75d26c6d4ce944024f10e6d23e8b5b888d680120e15dc0e4fee8d8833ee0c6a",
|
||||
"1d43d33556699b42c124b46e41243abf48727fe488428056fdd174a3861c1e3c",
|
||||
"7b5bd3fecbaa093f005c4f806ea67846c0df6b04df7729925cb14724f6a8b582",
|
||||
"6bdf2b54f2f5ab90191261d33dee80fede75896994016422b28db8ba62327d82",
|
||||
"1a16181b250085a91ccecc118473fa2ab98515e894a7b63b347c24b5be560c7a",
|
||||
"22d24891755910b48ad632358c26245bdcc375abc41f7e2c9fb3c7773dbf4e22",
|
||||
"5b70c5d4a373d541619c944fcc3b61259550b0e9fba3eca16f0879e5845b43b9",
|
||||
"b78f9098c9d76987b7409e63426a8d49972bb4e75289576c680cf96513d44b6d",
|
||||
"916b53b8e85eb7e0a2a76d6fc8d2163430e7183ccb103d6705f54af4bb070907",
|
||||
"dc3d78f43110d2aa9df83c5485ec33663ad5452b8cdeb1aeeac9d6b1487fb781",
|
||||
"3975539ed5402cb9f5ab503584524dd141cc4296b666ec66d807f94f62b1c026",
|
||||
"bd1f97fd89183643423073f22733880616456ca41960699f18e868cb9ac35508",
|
||||
"90b468ff0f83460c3dd8cfe778c39d32c6bb1eeff9ac5de7804a4050d3b8073e",
|
||||
"0e886d49d88b82c9f8dbdd2f38a535992f35ab16629724d746394db3898235fa",
|
||||
"76c22e965242d1ca5614e829d9028dcad9c4b09393bcbdd318b0365557335fb9",
|
||||
"59b168488ec8629f820a1efd8fc5a0c2adec4253e61d6a2945a68a9a43be9035",
|
||||
"ff172b42854eaf2865caa985d2fb6283c5ab19574126623ffd615a761a5bce72",
|
||||
"cb46ac9ccc024ee74c96e3cf1c13a6949a432e855dfa881b6a307c0e6daac59e",
|
||||
"9971574924c0f413bf4c0f96bb9c2fbdfea8f475e33a8fb6f15fa40903b63444",
|
||||
"1a95567deb0f45a8941e2248f33286485984a5e9d86d16c37d42169ad864dc36",
|
||||
"205fc7f7ec7a83f0bc22d5269c91762cd00adc7428456d799be5a0cd76f08b0f",
|
||||
"849dd41ef59a722901b7a0deb2c1fd3c110a91a726120a0a119cb7a15cf98438",
|
||||
"a32880917c714612101af95e5c8d8eb5fb046fdcc68bae76c05b829b3fa73c2e",
|
||||
"70b38d6d510d13b359dffa910329952c620a4bce4ee7a8552b9bb3a14572394d",
|
||||
"ef257ab2f4226faa6ba288a6793f026609068effb866c18496a847e8b60b102d",
|
||||
"e5196ab42ff53c8352288bde6b6b7312cd6f39f7d21b556b0db178d8470d5790",
|
||||
"ca98f128bf085f2b718f2b3c12da7c4d98887cc94251a2b1705b637611bd83bb",
|
||||
"79508f0b93a49ec19c5cb05906ca1ba3d3db8ed4f9c6884873d0d7e3e985ea51",
|
||||
"9088be3f47f9debc63e928739f7163182b49eab044518b151f0b89f6b6aefdd0",
|
||||
"46b2782fd669b6288a4d7348cf6671360277ba4864cc69bce3497369ac2ec31e",
|
||||
"0fa5131557db67b430d516530be939ff25882adf68a076602f3dfad8c77c963a",
|
||||
"3404302cc097d5457244453a4c9990804201ee8161188df811bcb32404998c71",
|
||||
"856939710dbb90a8eeda875a31f9a52af759bd932b88e7b08df35414c54d4721",
|
||||
"72569573b9b41d0ac5ce17764a139c6b8b36ef3ca6d92cec625dbcdae758ba22",
|
||||
"9746da344e435a008d6acb4847211bb676376ecc76c825b5d44a28b89ceeb40e",
|
||||
"3eafded1595516f032e33ec975f4c9c3a1055d13aa5575cf8a801d6103fdbeb4",
|
||||
"e88a6d2daa863c0787cc523a2cab45c546fad788951b10d75e2b0954db24cca7",
|
||||
"38f531e67f88f66de44d3357c8e8f2db456160ca31dd2024c9562f6afd260278",
|
||||
};
|
||||
// block 685498 (13 key images in one transaction)
|
||||
static const char * const key_images_685498[] =
|
||||
{
|
||||
"749b7277aa21c70c417f255fb181c3a30b44277edf657eaaebf28a2709dd2a90",
|
||||
"5a9b3e1a87332d735cedaa2b5623a6a5e99d99f5a2887c8fc84293577e8bf25c",
|
||||
"bea438768445eb3650cf619bf6758e94035abfe0ccda91d4a58c582df143d835",
|
||||
"376e237ff4da5e5cbd6e1bba4b01412fa751f2959c0c57006589f382413df429",
|
||||
"14ac2f2e044f8635a3a42ecb46c575424073c1f6e5ed5e905f516d57f63184b5",
|
||||
"2d1d2ecb77b69a2901de00897d0509c1b7855a3b2f8eb1afe419008fc03cd15a",
|
||||
"ea01658f0972b77ae9112d525ec073e3ec5c3b98d5ad912d95ab2636354b70b6",
|
||||
"d3934864a46101d8c242415282e7fc9ee73ad16cd40355535d226ab45ecdb61a",
|
||||
"ee379b05c5d02432330ebd4ea9c4f1c87d14c388568d526a0f8a22649a14e453",
|
||||
"aeb7b842b410b13ca4af7a5ffd5ae6caddc8bfec653df1b945e478839a2e0057",
|
||||
"451806929d9f5c3a7f365472703871abadc25b2a5a2d75472a45e86cd76c610b",
|
||||
"272d9b9fcc9e253c08da9caf8233471150019582eaefef461c1f9ceff7e2c337",
|
||||
"633cdedeb3b96ec4f234c670254c6f721e0b368d00b48c6b26759db7d62cf52d",
|
||||
};
|
||||
|
||||
if (height() > 202612)
|
||||
{
|
||||
for (const auto &kis: key_images_202612)
|
||||
{
|
||||
crypto::key_image ki;
|
||||
epee::string_tools::hex_to_pod(kis, ki);
|
||||
if (!has_key_image(ki))
|
||||
{
|
||||
LOG_PRINT_L1("Fixup: adding missing spent key " << ki);
|
||||
add_spent_key(ki);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (height() > 685498)
|
||||
{
|
||||
for (const auto &kis: key_images_685498)
|
||||
{
|
||||
crypto::key_image ki;
|
||||
epee::string_tools::hex_to_pod(kis, ki);
|
||||
if (!has_key_image(ki))
|
||||
{
|
||||
LOG_PRINT_L1("Fixup: adding missing spent key " << ki);
|
||||
add_spent_key(ki);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
batch_stop();
|
||||
}
|
||||
|
||||
bool BlockchainDB::txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -127,7 +127,7 @@ struct output_data_t
|
||||
crypto::public_key pubkey; //!< the output's public key (for spend verification)
|
||||
uint64_t unlock_time; //!< the output's unlock time (or height)
|
||||
uint64_t height; //!< the height of the block which created the output
|
||||
char asset_type[8]; //!< the asset type of the output
|
||||
uint32_t asset_type; //!< the asset type of the output
|
||||
rct::key commitment; //!< the output's amount commitment (for spend verification)
|
||||
};
|
||||
#pragma pack(pop)
|
||||
@@ -157,7 +157,9 @@ struct txpool_tx_meta_t
|
||||
{
|
||||
crypto::hash max_used_block_id;
|
||||
crypto::hash last_failed_id;
|
||||
crypto::public_key destination_address;
|
||||
crypto::public_key return_pubkey;
|
||||
crypto::public_key return_address;
|
||||
crypto::public_key one_time_public_key;
|
||||
uint64_t weight;
|
||||
uint64_t fee;
|
||||
uint64_t amount_burnt;
|
||||
@@ -168,7 +170,8 @@ struct txpool_tx_meta_t
|
||||
uint64_t last_relayed_time; //!< If received over i2p/tor, randomized forward time. If Dandelion++stem, randomized embargo time. Otherwise, last relayed timestamp
|
||||
uint32_t source_asset_id;
|
||||
uint32_t destination_asset_id;
|
||||
// 168 bytes
|
||||
// 232 bytes
|
||||
uint8_t tx_type;
|
||||
uint8_t kept_by_block;
|
||||
uint8_t relayed;
|
||||
uint8_t do_not_relay;
|
||||
@@ -179,7 +182,7 @@ struct txpool_tx_meta_t
|
||||
uint8_t is_forwarding: 1;
|
||||
uint8_t bf_padding: 3;
|
||||
|
||||
uint8_t padding[20]; // till 192 bytes
|
||||
uint8_t padding[19]; // till 256 bytes
|
||||
|
||||
void set_relay_method(relay_method method) noexcept;
|
||||
relay_method get_relay_method() const noexcept;
|
||||
@@ -194,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
|
||||
@@ -405,15 +416,21 @@ 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
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -866,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
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -1895,12 +1914,9 @@ public:
|
||||
*/
|
||||
virtual uint64_t get_database_size() const = 0;
|
||||
|
||||
// TODO: this should perhaps be (or call) a series of functions which
|
||||
// progressively update through version updates
|
||||
/**
|
||||
* @brief fix up anything that may be wrong due to past bugs
|
||||
*/
|
||||
virtual void fixup();
|
||||
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
|
||||
|
||||
+213
-120
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2023, The Monero Project
|
||||
// Portions Copyright (c) 2023, Salvium (author: SRCG)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
@@ -71,7 +72,7 @@ struct pre_rct_output_data_t
|
||||
crypto::public_key pubkey; //!< the output's public key (for spend verification)
|
||||
uint64_t unlock_time; //!< the output's unlock time (or height)
|
||||
uint64_t height; //!< the height of the block which created the output
|
||||
char asset_type[8]; //!< the asset type of the output
|
||||
uint32_t asset_type; //!< the asset type of the output
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -211,7 +212,8 @@ namespace
|
||||
*
|
||||
* alt_blocks block hash {block data, block blob}
|
||||
*
|
||||
* yield_txs 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"
|
||||
@@ -221,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";
|
||||
@@ -252,33 +255,40 @@ const char* const LMDB_CIRC_SUPPLY = "circ_supply";
|
||||
const char* const LMDB_CIRC_SUPPLY_TALLY = "circ_supply_tally";
|
||||
|
||||
/**
|
||||
* We have the following information that will go into a table in the blockchain:
|
||||
* block_height (this is the key field)
|
||||
* -----------------------------------------
|
||||
* txn_hash (so we can verify)
|
||||
* dest_address (where to send the yield)
|
||||
* amount (how much was locked)
|
||||
* 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)
|
||||
*
|
||||
* If we only allow a 30-day (actually 21,600 block) lock, and no variation on that period, then the code
|
||||
* to identify locks that are earning yield in a given block is probably pretty simple. It gets a LOT more
|
||||
* complicated if you can lock for a variable period, of course.
|
||||
* 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)
|
||||
* 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
|
||||
* TX has matured).
|
||||
*
|
||||
* Now, to calculate the payable yield, we need to know:
|
||||
* # how much slippage accrued in each of the last 21600 blocks
|
||||
* (call this slippage_amounts, which is a vector of slippage_height and slippage_amount tuples)
|
||||
* # the list of all yield TXs that fulfil the criteria
|
||||
* (YIELD.block_height > (h - 21600)) and (YIELD.block_height <= h) (call this yield_txs)
|
||||
* # how much slippage is burnt from each of the (21,600) blocks (and therefore how much yield is payable)
|
||||
* (this is "slippage_amount")
|
||||
* # the total number of coins that are locked for yield for each of the (21,600) blocks
|
||||
* (this is "coins_locked")
|
||||
*
|
||||
* Given this information, we would sort yield_txs by block_height. Then we iterate over slippage_amounts,
|
||||
* and for each entry, we look to see which of the yield_txs overlaps the height for the given slippage_height.
|
||||
* This allows us to work out the % of the slippage_amount that should be paid to the maturing yield TX.
|
||||
* Given this information, we would (for _each_ yield TX that matures in the current block)
|
||||
* 1. perform the sum "yield_amount" = "slippage_amount" * "network_health" / "100" for each block
|
||||
* 2. perform the sum "result" = "yield_amount" * "amount_locked" / "coins_locked" for each block
|
||||
* 3. perform the aggregation of all "result" values to determine the total yield payable
|
||||
*/
|
||||
const char* const LMDB_YIELD_TXS = "yield_txs";
|
||||
const char* const LMDB_YIELD_BLOCKS = "yield_blocks";
|
||||
|
||||
const char zerokey[8] = {0};
|
||||
const MDB_val zerokval = { sizeof(zerokey), (void *)zerokey };
|
||||
@@ -367,25 +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 destination_address;
|
||||
uint64_t amount;
|
||||
} yield_tx_data;
|
||||
|
||||
std::atomic<uint64_t> mdb_txn_safe::num_active_txns{0};
|
||||
std::atomic_flag mdb_txn_safe::creation_gate = ATOMIC_FLAG_INIT;
|
||||
|
||||
@@ -803,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();
|
||||
@@ -833,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));
|
||||
@@ -901,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)))
|
||||
@@ -921,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
|
||||
@@ -1073,30 +1179,19 @@ 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) {
|
||||
// Conversion TX - update our records
|
||||
circ_supply cs;
|
||||
cs.tx_hash = tx_hash;
|
||||
cs.asset_type = cryptonote::asset_id_from_type(tx.source_asset_type);
|
||||
cs.amount_burnt = tx.amount_burnt;
|
||||
cs.amount_minted = 0;
|
||||
|
||||
MDB_val_set(val_circ_supply, cs);
|
||||
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
|
||||
if (result)
|
||||
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
|
||||
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(cs.asset_type);
|
||||
MDB_val_copy<uint64_t> source_idx(cryptonote::asset_id_from_type(tx.source_asset_type));
|
||||
boost::multiprecision::int128_t source_tally = 0;
|
||||
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
|
||||
boost::multiprecision::int128_t final_source_tally = source_tally - cs.amount_burnt;
|
||||
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);
|
||||
@@ -1114,19 +1209,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
|
||||
bool ok = cryptonote::get_output_asset_type(out, asset_type);
|
||||
if (!ok)
|
||||
throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)"));
|
||||
|
||||
circ_supply cs;
|
||||
cs.tx_hash = tx_hash;
|
||||
cs.asset_type = cryptonote::asset_id_from_type(asset_type);
|
||||
cs.amount_burnt = 0;
|
||||
cs.amount_minted = out.amount;
|
||||
|
||||
minted_amounts[cs.asset_type] += out.amount;
|
||||
|
||||
MDB_val_set(val_circ_supply, cs);
|
||||
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
|
||||
if (result)
|
||||
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
|
||||
minted_amounts[cryptonote::asset_id_from_type(asset_type)] += out.amount;
|
||||
}
|
||||
|
||||
// Now update the overall tally entries
|
||||
@@ -1139,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;
|
||||
}
|
||||
}
|
||||
@@ -1150,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.destination_address = tx.destination_address;
|
||||
yield_data.amount = tx.amount_burnt; // SRCG - this feels as though we are bastardising the variable for an invalid purpose
|
||||
yield_data.return_address = tx.return_address;
|
||||
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);
|
||||
@@ -1182,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)
|
||||
|
||||
@@ -1273,19 +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);
|
||||
@@ -1303,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);
|
||||
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)
|
||||
LOG_PRINT_L1("tx has no yield_tx data to remove: " << tx_hash);
|
||||
break;
|
||||
else if (result)
|
||||
throw1(DB_ERROR(lmdb_error("Failed to locate yield_tx data for removal: ", result).c_str()));
|
||||
if (!result)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1356,6 +1441,8 @@ std::pair<uint64_t, uint64_t> BlockchainLMDB::add_output(const crypto::hash& tx_
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add output tx hash to db transaction: ", result).c_str()));
|
||||
|
||||
uint32_t asset_type = cryptonote::asset_id_from_type(output_asset_type);
|
||||
|
||||
outkey ok;
|
||||
MDB_val data;
|
||||
MDB_val_copy<uint64_t> val_amount(tx_output.amount);
|
||||
@@ -1376,11 +1463,7 @@ std::pair<uint64_t, uint64_t> BlockchainLMDB::add_output(const crypto::hash& tx_
|
||||
ok.data.pubkey = output_public_key;
|
||||
ok.data.unlock_time = unlock_time;
|
||||
ok.data.height = m_height;
|
||||
|
||||
if(output_asset_type.length() >= sizeof(ok.data.asset_type))
|
||||
throw0(DB_ERROR(lmdb_error("Invalid asset_type " + output_asset_type, result).c_str()));
|
||||
memset(ok.data.asset_type, 0, sizeof(ok.data.asset_type));
|
||||
memcpy(ok.data.asset_type, output_asset_type.c_str(), output_asset_type.length());
|
||||
ok.data.asset_type = asset_type;
|
||||
|
||||
if (tx_output.amount == 0)
|
||||
{
|
||||
@@ -1397,7 +1480,7 @@ std::pair<uint64_t, uint64_t> BlockchainLMDB::add_output(const crypto::hash& tx_
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add output pubkey to db transaction: ", result).c_str()));
|
||||
|
||||
|
||||
MDB_val_copy<const char *> k(output_asset_type.c_str());
|
||||
MDB_val_copy<uint32_t> k(asset_type);
|
||||
MDB_val v;
|
||||
|
||||
mdb_size_t num_outputs_of_asset_type = 0;
|
||||
@@ -1416,7 +1499,7 @@ std::pair<uint64_t, uint64_t> BlockchainLMDB::add_output(const crypto::hash& tx_
|
||||
oat.output_id = ok.output_id;
|
||||
MDB_val_set(voat, oat);
|
||||
|
||||
MDB_val_copy<const char *> koat(output_asset_type.c_str());
|
||||
MDB_val_copy<uint32_t> koat(asset_type);
|
||||
if ((result = mdb_cursor_put(m_cur_output_types, &koat, &voat, MDB_APPENDDUP)))
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add output type to db transaction: ", result).c_str()));
|
||||
|
||||
@@ -1465,14 +1548,14 @@ void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction&
|
||||
for (size_t i = tx.vout.size(); i-- > 0;)
|
||||
{
|
||||
uint64_t amount = is_pseudo_rct ? 0 : tx.vout[i].amount;
|
||||
std::string output_asset_type;
|
||||
if (!get_output_asset_type(tx.vout[i], output_asset_type))
|
||||
std::string output_asset_type_str;
|
||||
if (!get_output_asset_type(tx.vout[i], output_asset_type_str))
|
||||
throw0(DB_ERROR("Could not get an output asset_type from a tx output (removing)."));
|
||||
remove_output(amount, amount_output_indices[i].first, output_asset_type, amount_output_indices[i].second);
|
||||
remove_output(amount, amount_output_indices[i].first, output_asset_type_str, amount_output_indices[i].second);
|
||||
}
|
||||
}
|
||||
|
||||
void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_index, const std::string& output_asset_type, const uint64_t& asset_type_output_id)
|
||||
void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_index, const std::string& output_asset_type_str, const uint64_t& asset_type_output_id)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -1502,8 +1585,8 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in
|
||||
throw1(DB_ERROR(lmdb_error("Error adding removal of output tx to db transaction", result).c_str()));
|
||||
}
|
||||
|
||||
|
||||
MDB_val_copy<const char *> koat(output_asset_type.c_str());
|
||||
uint32_t output_asset_type = cryptonote::asset_id_from_type(output_asset_type_str);
|
||||
MDB_val_copy<uint32_t> koat(output_asset_type);
|
||||
MDB_val_set(voat, asset_type_output_id);
|
||||
|
||||
result = mdb_cursor_get(m_cur_output_types, &koat, &voat, MDB_GET_BOTH);
|
||||
@@ -1798,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);
|
||||
@@ -1818,6 +1902,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
|
||||
mdb_set_compare(txn, m_properties, compare_string);
|
||||
|
||||
mdb_set_compare(txn, m_circ_supply, compare_uint64);
|
||||
mdb_set_dupsort(txn, m_circ_supply, compare_uint64);
|
||||
mdb_set_compare(txn, m_circ_supply_tally, compare_uint64);
|
||||
|
||||
mdb_set_dupsort(txn, m_yield_txs, compare_uint64);
|
||||
@@ -1858,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 elbowd 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.
|
||||
@@ -2000,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");
|
||||
@@ -2908,7 +2995,10 @@ std::pair<std::vector<uint64_t>, uint64_t> BlockchainLMDB::get_block_cumulative_
|
||||
}
|
||||
const mdb_block_info *bi = ((const mdb_block_info *)v.mv_data) + (height - range_begin);
|
||||
|
||||
res.push_back(bi->bi_cum_rct_by_asset_type[asset_type]);
|
||||
// if no asset type is provided in the request, an old client is requesting the cumulative outputs,
|
||||
// and is expecting the global output distribution that isn't bucketed by asset type in response
|
||||
res.push_back(asset_type.empty() ? bi->bi_cum_rct : bi->bi_cum_rct_by_asset_type[asset_type]);
|
||||
|
||||
if (height == heights[heights.size() - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE])
|
||||
num_spendable_global_outs = bi->bi_cum_rct;
|
||||
|
||||
@@ -3304,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();
|
||||
@@ -3330,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;
|
||||
}
|
||||
|
||||
@@ -3343,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
|
||||
@@ -3817,7 +3914,7 @@ uint64_t BlockchainLMDB::get_num_outputs(const uint64_t& amount) const
|
||||
return num_elems;
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::get_num_outputs_of_asset_type(const std::string asset_type) const
|
||||
uint64_t BlockchainLMDB::get_num_outputs_of_asset_type(const std::string asset_type_str) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -3825,7 +3922,8 @@ uint64_t BlockchainLMDB::get_num_outputs_of_asset_type(const std::string asset_t
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(output_types);
|
||||
|
||||
MDB_val_copy<const char *> k(asset_type.c_str());
|
||||
uint32_t asset_type = cryptonote::asset_id_from_type(asset_type_str);
|
||||
MDB_val_copy<uint32_t> k(asset_type);
|
||||
MDB_val v;
|
||||
mdb_size_t num_outputs_of_asset_type = 0;
|
||||
auto result = mdb_cursor_get(m_cur_output_types, &k, &v, MDB_SET);
|
||||
@@ -3877,7 +3975,7 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint6
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::string asset_type, const std::vector<uint64_t> &asset_type_output_indices, std::vector<uint64_t> &output_indices) const
|
||||
void BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::string asset_type_str, const std::vector<uint64_t> &asset_type_output_indices, std::vector<uint64_t> &output_indices) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -3888,7 +3986,8 @@ void BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::strin
|
||||
|
||||
RCURSOR(output_types);
|
||||
|
||||
MDB_val_copy<const char *> k_type(asset_type.c_str());
|
||||
uint32_t asset_type = cryptonote::asset_id_from_type(asset_type_str);
|
||||
MDB_val_copy<uint32_t> k_type(asset_type);
|
||||
|
||||
for (size_t i = 0; i < asset_type_output_indices.size(); ++i)
|
||||
{
|
||||
@@ -3897,7 +3996,7 @@ void BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::strin
|
||||
auto get_result = mdb_cursor_get(m_cur_output_types, &k_type, &v, MDB_GET_BOTH);
|
||||
if (get_result == MDB_NOTFOUND)
|
||||
{
|
||||
throw1(OUTPUT_DNE((std::string("Attempting to get output id by asset type output id (asset type " + asset_type + " asset type ouput id " + boost::lexical_cast<std::string>(asset_type_output_indices[i]) + "), but key does not exist (current height " + boost::lexical_cast<std::string>(height()) + ")").c_str())));
|
||||
throw1(OUTPUT_DNE((std::string("Attempting to get output id by asset type output id (asset type " + asset_type_str + " asset type ouput id " + boost::lexical_cast<std::string>(asset_type_output_indices[i]) + "), but key does not exist (current height " + boost::lexical_cast<std::string>(height()) + ")").c_str())));
|
||||
}
|
||||
else if (get_result)
|
||||
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output id by asset type output id from the db", get_result).c_str()));
|
||||
@@ -3909,7 +4008,7 @@ void BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::strin
|
||||
TXN_POSTFIX_RDONLY();
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::string asset_type, const uint64_t &asset_type_output_index) const
|
||||
uint64_t BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::string asset_type_str, const uint64_t &asset_type_output_index) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -3917,13 +4016,14 @@ uint64_t BlockchainLMDB::get_output_id_from_asset_type_output_index(const std::s
|
||||
TXN_PREFIX_RDONLY();
|
||||
RCURSOR(output_types);
|
||||
|
||||
MDB_val_copy<const char *> k_type(asset_type.c_str());
|
||||
uint32_t asset_type = cryptonote::asset_id_from_type(asset_type_str);
|
||||
MDB_val_copy<uint32_t> k_type(asset_type);
|
||||
MDB_val_set(v, asset_type_output_index);
|
||||
|
||||
auto get_result = mdb_cursor_get(m_cur_output_types, &k_type, &v, MDB_GET_BOTH);
|
||||
if (get_result == MDB_NOTFOUND)
|
||||
{
|
||||
throw1(OUTPUT_DNE((std::string("Attempting to get output id by asset type output id (asset type " + asset_type + " asset type output id " + boost::lexical_cast<std::string>(asset_type_output_index) + "), but key does not exist (current height " + boost::lexical_cast<std::string>(height()) + ")").c_str())));
|
||||
throw1(OUTPUT_DNE((std::string("Attempting to get output id by asset type output id (asset type " + asset_type_str + " asset type output id " + boost::lexical_cast<std::string>(asset_type_output_index) + "), but key does not exist (current height " + boost::lexical_cast<std::string>(height()) + ")").c_str())));
|
||||
}
|
||||
else if (get_result)
|
||||
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output id by asset type output id from the db", get_result).c_str()));
|
||||
@@ -4533,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();
|
||||
@@ -4551,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)
|
||||
{
|
||||
@@ -5024,13 +5124,6 @@ uint64_t BlockchainLMDB::get_database_size() const
|
||||
return size;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::fixup()
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
// Always call parent as well
|
||||
BlockchainDB::fixup();
|
||||
}
|
||||
|
||||
#define RENAME_DB(name) do { \
|
||||
char n2[] = name; \
|
||||
MDB_dbi tdbi; \
|
||||
|
||||
@@ -77,6 +77,7 @@ typedef struct mdb_txn_cursors
|
||||
MDB_cursor *m_txc_circ_supply;
|
||||
MDB_cursor *m_txc_circ_supply_tally;
|
||||
MDB_cursor *m_txc_yield_txs;
|
||||
MDB_cursor *m_txc_yield_blocks;
|
||||
|
||||
} mdb_txn_cursors;
|
||||
|
||||
@@ -102,6 +103,7 @@ typedef struct mdb_txn_cursors
|
||||
#define m_cur_circ_supply m_cursors->m_txc_circ_supply
|
||||
#define m_cur_circ_supply_tally m_cursors->m_txc_circ_supply_tally
|
||||
#define m_cur_yield_txs m_cursors->m_txc_yield_txs
|
||||
#define m_cur_yield_blocks m_cursors->m_txc_yield_blocks
|
||||
|
||||
typedef struct mdb_rflags
|
||||
{
|
||||
@@ -128,6 +130,7 @@ typedef struct mdb_rflags
|
||||
bool m_rf_circ_supply;
|
||||
bool m_rf_circ_supply_tally;
|
||||
bool m_rf_yield_txs;
|
||||
bool m_rf_yield_blocks;
|
||||
} mdb_rflags;
|
||||
|
||||
typedef struct mdb_threadinfo
|
||||
@@ -338,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);
|
||||
@@ -385,14 +390,18 @@ 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();
|
||||
@@ -443,9 +452,6 @@ private:
|
||||
uint64_t get_max_block_size();
|
||||
void add_max_block_size(uint64_t sz);
|
||||
|
||||
// fix up anything that may be wrong due to past bugs
|
||||
virtual void fixup();
|
||||
|
||||
// migrate from older DB version to current
|
||||
void migrate(const uint32_t oldversion);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+13
-6
@@ -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);
|
||||
}
|
||||
@@ -263,11 +270,11 @@ namespace crypto {
|
||||
|
||||
/**
|
||||
* The following functions are designed to perform the correct encoding / decoding for protocol_tx outputs,
|
||||
* which use a hash of a crypto::key_image for uniqueness
|
||||
* which use an ec_scalar to provide uniqueness
|
||||
*/
|
||||
void crypto_ops::derivation_to_scalar(const key_derivation &derivation, const hash& uniqueness, ec_scalar &res) {
|
||||
void crypto_ops::derivation_to_scalar(const key_derivation &derivation, const ec_scalar& uniqueness, ec_scalar &res) {
|
||||
struct {
|
||||
hash uniqueness;
|
||||
ec_scalar uniqueness;
|
||||
key_derivation derivation;
|
||||
} buf;
|
||||
buf.uniqueness = uniqueness;
|
||||
@@ -275,7 +282,7 @@ namespace crypto {
|
||||
hash_to_scalar(&buf, sizeof(buf), res);
|
||||
}
|
||||
|
||||
bool crypto_ops::derive_public_key(const key_derivation &derivation, const hash& uniqueness,
|
||||
bool crypto_ops::derive_public_key(const key_derivation &derivation, const ec_scalar& uniqueness,
|
||||
const public_key &base, public_key &derived_key) {
|
||||
ec_scalar scalar;
|
||||
ge_p3 point1;
|
||||
@@ -295,7 +302,7 @@ namespace crypto {
|
||||
return true;
|
||||
}
|
||||
|
||||
void crypto_ops::derive_secret_key(const key_derivation &derivation, const hash& uniqueness,
|
||||
void crypto_ops::derive_secret_key(const key_derivation &derivation, const ec_scalar& uniqueness,
|
||||
const secret_key &base, secret_key &derived_key) {
|
||||
ec_scalar scalar;
|
||||
assert(sc_check(&base) == 0);
|
||||
@@ -303,7 +310,7 @@ namespace crypto {
|
||||
sc_add(&unwrap(derived_key), &unwrap(base), &scalar);
|
||||
}
|
||||
|
||||
bool crypto_ops::derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, const hash& uniqueness, public_key &derived_key) {
|
||||
bool crypto_ops::derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, const ec_scalar& uniqueness, public_key &derived_key) {
|
||||
ec_scalar scalar;
|
||||
ge_p3 point1;
|
||||
ge_p3 point2;
|
||||
|
||||
+15
-13
@@ -140,14 +140,14 @@ namespace crypto {
|
||||
* The following functions are designed to perform the correct encoding / decoding for protocol_tx outputs,
|
||||
* which use a hash of a crypto::key_image for uniqueness
|
||||
*/
|
||||
static void derivation_to_scalar(const key_derivation &derivation, const hash& uniqueness, ec_scalar &res);
|
||||
friend void derivation_to_scalar(const key_derivation &derivation, const hash& uniqueness, ec_scalar &res);
|
||||
static bool derive_public_key(const key_derivation &, const hash&, const public_key &, public_key &);
|
||||
friend bool derive_public_key(const key_derivation &, const hash&, const public_key &, public_key &);
|
||||
static void derive_secret_key(const key_derivation &, const hash&, const secret_key &, secret_key &);
|
||||
friend void derive_secret_key(const key_derivation &, const hash&, const secret_key &, secret_key &);
|
||||
static bool derive_subaddress_public_key(const public_key &, const key_derivation &, const hash&, public_key &);
|
||||
friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, const hash&, public_key &);
|
||||
static void derivation_to_scalar(const key_derivation &derivation, const ec_scalar& uniqueness, ec_scalar &res);
|
||||
friend void derivation_to_scalar(const key_derivation &derivation, const ec_scalar& uniqueness, ec_scalar &res);
|
||||
static bool derive_public_key(const key_derivation &, const ec_scalar&, const public_key &, public_key &);
|
||||
friend bool derive_public_key(const key_derivation &, const ec_scalar&, const public_key &, public_key &);
|
||||
static void derive_secret_key(const key_derivation &, const ec_scalar&, const secret_key &, secret_key &);
|
||||
friend void derive_secret_key(const key_derivation &, const ec_scalar&, const secret_key &, secret_key &);
|
||||
static bool derive_subaddress_public_key(const public_key &, const key_derivation &, const ec_scalar&, public_key &);
|
||||
friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, const ec_scalar&, public_key &);
|
||||
|
||||
static void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
|
||||
friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &);
|
||||
@@ -261,20 +261,20 @@ namespace crypto {
|
||||
|
||||
/**
|
||||
* The following functions are designed to perform the correct encoding / decoding for protocol_tx outputs,
|
||||
* which use a hash of a crypto::key_image for uniqueness
|
||||
* which use an ec_scalar to provide uniqueness
|
||||
*/
|
||||
inline bool derive_public_key(const key_derivation &derivation, const hash& uniqueness,
|
||||
inline bool derive_public_key(const key_derivation &derivation, const ec_scalar& uniqueness,
|
||||
const public_key &base, public_key &derived_key) {
|
||||
return crypto_ops::derive_public_key(derivation, uniqueness, base, derived_key);
|
||||
}
|
||||
inline void derivation_to_scalar(const key_derivation &derivation, const hash& uniqueness, ec_scalar &res) {
|
||||
inline void derivation_to_scalar(const key_derivation &derivation, const ec_scalar& uniqueness, ec_scalar &res) {
|
||||
return crypto_ops::derivation_to_scalar(derivation, uniqueness, res);
|
||||
}
|
||||
inline void derive_secret_key(const key_derivation &derivation, const hash& uniqueness,
|
||||
inline void derive_secret_key(const key_derivation &derivation, const ec_scalar& uniqueness,
|
||||
const secret_key &base, secret_key &derived_key) {
|
||||
crypto_ops::derive_secret_key(derivation, uniqueness, base, derived_key);
|
||||
}
|
||||
inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, const hash& uniqueness, public_key &result) {
|
||||
inline bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, const ec_scalar& uniqueness, public_key &result) {
|
||||
return crypto_ops::derive_subaddress_public_key(out_key, derivation, uniqueness, result);
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -43,12 +43,20 @@ namespace crypto {
|
||||
}
|
||||
|
||||
inline
|
||||
bool derive_subaddress_public_key(const public_key &output_pub, const key_derivation &d, const crypto::hash& uniqueness, public_key &out)
|
||||
bool derive_subaddress_public_key(const public_key &output_pub, const key_derivation &d, const ec_scalar& uniqueness, public_key &out)
|
||||
{
|
||||
ec_scalar scalar;
|
||||
derivation_to_scalar(d, uniqueness, scalar);
|
||||
return monero_crypto_generate_subaddress_public_key(out.data, output_pub.data, scalar.data) == 0;
|
||||
}
|
||||
|
||||
inline
|
||||
bool derive_subaddress_public_key(const public_key &output_pub, const key_derivation &d, std::size_t output_index, public_key &out)
|
||||
{
|
||||
ec_scalar scalar;
|
||||
derivation_to_scalar(d, output_index, scalar);
|
||||
return monero_crypto_generate_subaddress_public_key(out.data, output_pub.data, scalar.data) == 0;
|
||||
}
|
||||
#else
|
||||
using ::crypto::generate_key_derivation;
|
||||
using ::crypto::derive_subaddress_public_key;
|
||||
|
||||
@@ -199,8 +199,10 @@ namespace cryptonote
|
||||
std::vector<uint8_t> extra;
|
||||
// TX type
|
||||
cryptonote::transaction_type type;
|
||||
// Destination address (encrypted)
|
||||
crypto::public_key destination_address;
|
||||
// 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(destination_address)
|
||||
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_burnt)
|
||||
VARINT_FIELD(amount_slippage_limit)
|
||||
}
|
||||
}
|
||||
END_SERIALIZE()
|
||||
|
||||
public:
|
||||
@@ -235,7 +241,8 @@ namespace cryptonote
|
||||
vout.clear();
|
||||
extra.clear();
|
||||
type = cryptonote::transaction_type::UNSET;
|
||||
destination_address = crypto::null_pkey;
|
||||
return_address = crypto::null_pkey;
|
||||
return_pubkey = crypto::null_pkey;
|
||||
source_asset_type.clear();
|
||||
destination_asset_type.clear();
|
||||
amount_burnt = 0;
|
||||
@@ -491,6 +498,23 @@ namespace cryptonote
|
||||
return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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()
|
||||
};
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
@@ -510,6 +534,7 @@ namespace cryptonote
|
||||
VARINT_FIELD(timestamp)
|
||||
FIELD(prev_id)
|
||||
FIELD(nonce)
|
||||
if (major_version >= HF_VERSION_ENABLE_ORACLE)
|
||||
FIELD(pricing_record)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
@@ -531,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,
|
||||
@@ -560,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,
|
||||
@@ -645,6 +670,20 @@ namespace cryptonote
|
||||
};
|
||||
//---------------------------------------------------------------
|
||||
|
||||
struct origin_data
|
||||
{
|
||||
uint8_t tx_type;
|
||||
crypto::public_key tx_pub_key;
|
||||
crypto::key_image input_k_image;
|
||||
crypto::ec_scalar uniqueness;
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
VARINT_FIELD(tx_type)
|
||||
FIELD(tx_pub_key)
|
||||
FIELD(input_k_image)
|
||||
//FIELD(uniqueness)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
@@ -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,28 +167,33 @@ 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.destination_address;
|
||||
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.destination_address;
|
||||
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;
|
||||
@@ -199,6 +209,43 @@ namespace boost
|
||||
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)
|
||||
{
|
||||
a & ad.asset_type;
|
||||
a & ad.spot_price;
|
||||
a & ad.ma_price;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
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)
|
||||
@@ -208,6 +255,7 @@ namespace boost
|
||||
a & b.timestamp;
|
||||
a & b.prev_id;
|
||||
a & b.nonce;
|
||||
if (b.major_version >= HF_VERSION_ENABLE_ORACLE)
|
||||
a & b.pricing_record;
|
||||
//------------------
|
||||
a & b.miner_tx;
|
||||
@@ -436,16 +484,6 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, oracle::pricing_record &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.pr_version;
|
||||
a & x.timestamp;
|
||||
a & x.spot;
|
||||
a & x.moving_average;
|
||||
a & x.signature;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace cryptonote
|
||||
return is_v1_tx(blobdata_ref{tx_blob.data(), tx_blob.size()});
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, const crypto::hash& uniqueness, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev)
|
||||
bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const origin_data& origin_tx_data)
|
||||
{
|
||||
crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation);
|
||||
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
|
||||
@@ -314,13 +314,193 @@ namespace cryptonote
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<subaddress_receive_info> subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index,hwdev);
|
||||
boost::optional<subaddress_receive_info> subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index, origin_tx_data.uniqueness, hwdev);
|
||||
CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address");
|
||||
|
||||
return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, uniqueness, subaddr_recv_info->index, in_ephemeral, ki, hwdev);
|
||||
//assert(false);
|
||||
return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, subaddr_recv_info->index, in_ephemeral, ki, hwdev, origin_tx_data);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const crypto::hash& uniqueness, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev)
|
||||
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const origin_data& origin_tx_data)
|
||||
{
|
||||
if (hwdev.compute_key_image(ack, out_key, recv_derivation, real_output_index, received_index, in_ephemeral, ki))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ack.m_spend_secret_key == crypto::null_skey)
|
||||
{
|
||||
// for watch-only wallet, simply copy the known output pubkey
|
||||
in_ephemeral.pub = out_key;
|
||||
in_ephemeral.sec = crypto::null_skey;
|
||||
}
|
||||
else
|
||||
{
|
||||
// derive secret key with subaddress - step 1: original CN derivation
|
||||
crypto::secret_key scalar_step1;
|
||||
crypto::secret_key spend_skey = crypto::null_skey;
|
||||
|
||||
if (ack.m_multisig_keys.empty())
|
||||
{
|
||||
// if not multisig, use normal spend skey
|
||||
spend_skey = ack.m_spend_secret_key;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if multisig, use sum of multisig privkeys (local account's share of aggregate spend key)
|
||||
for (const auto &multisig_key : ack.m_multisig_keys)
|
||||
{
|
||||
sc_add((unsigned char*)spend_skey.data,
|
||||
(const unsigned char*)multisig_key.data,
|
||||
(const unsigned char*)spend_skey.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (origin_tx_data.tx_type == (uint8_t)(cryptonote::transaction_type::PROTOCOL)) {
|
||||
/**
|
||||
* Okay so PROTOCOL_TX payments are triggered by a previously-made CONVERT or YIELD transaction.
|
||||
* The math works as follows (I will use a CONVERT TX as an example):
|
||||
*
|
||||
* 1. The CONVERT TX is submitted by the user, containing:
|
||||
* a. a mathematical imbalance (ins - outs = "tx.amount_burnt")
|
||||
* b. a "return_address" (F), which is calculated using the formula:
|
||||
*
|
||||
* F = (y^-1).a.P_change
|
||||
* (where "y" = Hs(tx.vin[0].k_image),
|
||||
* "a" = sender's private view key, and
|
||||
* "P_change" is the one-time public key of the change output of the CONVERT TX)
|
||||
*
|
||||
* This has the effect of making the subaddress (to which the return payment will be sent)
|
||||
* (y.F, P_change), which facilitates simple detection of incoming payments.
|
||||
*
|
||||
* 2. The PROTOCOL TX performs the conversion of the "tx.amount_burnt" sum into the desired
|
||||
* asset type (* subject to slippage etc) and then calculates the TX pub key and one-time
|
||||
* public key to which the converted amount is sent. These values are calculated as
|
||||
* follows:
|
||||
*
|
||||
* TX pub key R = s.P_change (*s is a scalar selected randomly from a uniform distribution)
|
||||
* one-time output pub key P_return = Hs(s.y.F || i)G + P_change
|
||||
*
|
||||
* 3. This has the effect of the sender's wallet automatically recognising the incoming
|
||||
* return payment as belonging to them. HOWEVER, the ability to SPEND the return payment is
|
||||
* dependent upon being able to calculate the one-time output secret key "x_return", which
|
||||
* is a little more involved than the normal process.
|
||||
*
|
||||
* The following code calculates the "x_return" value, and the corresponding key_image that is
|
||||
* required to be able to spend the output.
|
||||
*/
|
||||
// 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, 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)
|
||||
crypto::key_derivation derivation_P_change_tx = AUTO_VAL_INIT(derivation_P_change_tx);
|
||||
CHECK_AND_ASSERT_MES(hwdev.generate_key_derivation(origin_tx_data.tx_pub_key, ack.m_view_secret_key, derivation_P_change_tx), false, "Failed to generate key_derivation for P_change");
|
||||
|
||||
// 3. Calculate the secret spend key "x_change" for the change output of the CONVERT TX
|
||||
crypto::secret_key sk_spend = crypto::null_skey;
|
||||
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(derivation_P_change_tx, origin_tx_data.uniqueness, spend_skey, sk_spend), false, "Failed to derive secret key for P_change");
|
||||
|
||||
// 4. Derive the public key from the secret key for verification purposes
|
||||
crypto::public_key change_pk;
|
||||
CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(sk_spend, change_pk), false, "Failed to derive public key for P_change");
|
||||
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, 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,
|
||||
false, "key image helper precomp: given output pubkey doesn't match the derived one");
|
||||
|
||||
// 6. Create the key_image needed to be able to spend the output
|
||||
hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki);
|
||||
return true;
|
||||
|
||||
} else if (origin_tx_data.tx_type == (uint8_t)(cryptonote::transaction_type::TRANSFER)) {
|
||||
|
||||
// 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, 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)
|
||||
crypto::key_derivation derivation_P_change_tx = AUTO_VAL_INIT(derivation_P_change_tx);
|
||||
CHECK_AND_ASSERT_MES(hwdev.generate_key_derivation(origin_tx_data.tx_pub_key, ack.m_view_secret_key, derivation_P_change_tx), false, "Failed to generate key_derivation for P_change");
|
||||
|
||||
// 3. Calculate the secret spend key "x_change" for the change output of the CONVERT TX
|
||||
crypto::secret_key sk_spend = crypto::null_skey;
|
||||
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(derivation_P_change_tx, origin_tx_data.uniqueness, spend_skey, sk_spend), false, "Failed to derive secret key for P_change");
|
||||
|
||||
// 4. Derive the public key from the secret key for verification purposes
|
||||
crypto::public_key change_pk;
|
||||
CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(sk_spend, change_pk), false, "Failed to derive public key for P_change");
|
||||
if (P_change == change_pk) {
|
||||
|
||||
// 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, 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'");
|
||||
if (in_ephemeral.pub == out_key) {
|
||||
|
||||
// 6. Create the key_image needed to be able to spend the output
|
||||
hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// computes Hs(a*R || uniqueness) + b
|
||||
hwdev.derive_secret_key(recv_derivation, origin_tx_data.uniqueness, spend_skey, scalar_step1);
|
||||
|
||||
// step 2: add Hs(a || index_major || index_minor)
|
||||
crypto::secret_key subaddr_sk;
|
||||
crypto::secret_key scalar_step2;
|
||||
if (received_index.is_zero())
|
||||
{
|
||||
scalar_step2 = scalar_step1; // treat index=(0,0) as a special case representing the main address
|
||||
}
|
||||
else
|
||||
{
|
||||
subaddr_sk = hwdev.get_subaddress_secret_key(ack.m_view_secret_key, received_index);
|
||||
hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk);
|
||||
}
|
||||
|
||||
in_ephemeral.sec = scalar_step2;
|
||||
|
||||
if (ack.m_multisig_keys.empty())
|
||||
{
|
||||
// when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase
|
||||
CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key");
|
||||
}
|
||||
else
|
||||
{
|
||||
// when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation
|
||||
CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, origin_tx_data.uniqueness, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key");
|
||||
// and don't forget to add the contribution from the subaddress part
|
||||
if (!received_index.is_zero())
|
||||
{
|
||||
crypto::public_key subaddr_pk;
|
||||
CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key");
|
||||
add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk);
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key,
|
||||
false, "key image helper precomp: given output pubkey doesn't match the derived one");
|
||||
}
|
||||
|
||||
hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki);
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
//---------------------------------------------------------------
|
||||
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const crypto::ec_scalar& uniqueness, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev)
|
||||
{
|
||||
if (hwdev.compute_key_image(ack, out_key, recv_derivation, real_output_index, received_index, in_ephemeral, ki))
|
||||
{
|
||||
@@ -356,7 +536,6 @@ namespace cryptonote
|
||||
}
|
||||
|
||||
// computes Hs(a*R || uniqueness) + b
|
||||
//crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&real_output_index), sizeof(size_t));
|
||||
hwdev.derive_secret_key(recv_derivation, uniqueness, spend_skey, scalar_step1);
|
||||
|
||||
// step 2: add Hs(a || index_major || index_minor)
|
||||
@@ -399,6 +578,7 @@ namespace cryptonote
|
||||
hwdev.generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
//---------------------------------------------------------------
|
||||
uint64_t power_integral(uint64_t a, uint64_t b)
|
||||
{
|
||||
@@ -913,10 +1093,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:
|
||||
@@ -930,10 +1110,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 == "") {
|
||||
@@ -945,17 +1125,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:
|
||||
*
|
||||
@@ -977,7 +1157,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 {
|
||||
@@ -1037,7 +1217,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
|
||||
@@ -1056,7 +1236,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;
|
||||
}
|
||||
@@ -1233,29 +1413,17 @@ namespace cryptonote
|
||||
return view_tag == derived_view_tag;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index, const boost::optional<crypto::view_tag>& view_tag_opt)
|
||||
bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index, const crypto::ec_scalar& uniqueness, const boost::optional<crypto::view_tag>& view_tag_opt)
|
||||
{
|
||||
// Calculate the uniqueness
|
||||
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index), sizeof(size_t));
|
||||
|
||||
crypto::key_derivation derivation;
|
||||
bool r = acc.get_device().generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
|
||||
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
LOG_ERROR("derivation: " << derivation);
|
||||
LOG_ERROR("uniqueness: " << uniqueness);
|
||||
LOG_ERROR("txkey_pub : " << tx_pub_key);
|
||||
|
||||
crypto::public_key pk;
|
||||
if (out_can_be_to_acc(view_tag_opt, derivation, output_index, &acc.get_device()))
|
||||
{
|
||||
r = acc.get_device().derive_public_key(derivation, uniqueness, acc.m_account_address.m_spend_public_key, pk);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
|
||||
|
||||
LOG_ERROR("output_key: " << pk);
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
|
||||
if (pk == output_public_key)
|
||||
return true;
|
||||
}
|
||||
@@ -1268,7 +1436,7 @@ namespace cryptonote
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
|
||||
if (out_can_be_to_acc(view_tag_opt, derivation, output_index, &acc.get_device()))
|
||||
{
|
||||
r = acc.get_device().derive_public_key(derivation, uniqueness, acc.m_account_address.m_spend_public_key, pk);
|
||||
r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
|
||||
return pk == output_public_key;
|
||||
}
|
||||
@@ -1276,10 +1444,9 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt)
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, const crypto::ec_scalar& uniqueness, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt)
|
||||
{
|
||||
// Calculate the uniqueness
|
||||
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index), sizeof(size_t));
|
||||
LOG_PRINT_L3("Cryptonote::" << __func__ << ":" << __LINE__);
|
||||
|
||||
// try the shared tx pubkey
|
||||
crypto::public_key subaddress_spendkey;
|
||||
@@ -1306,8 +1473,11 @@ namespace cryptonote
|
||||
return boost::none;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::hash& uniqueness, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt)
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::ec_scalar& uniqueness, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt)
|
||||
{
|
||||
assert(false);
|
||||
LOG_PRINT_L3("Cryptonote::" << __func__ << ":" << __LINE__);
|
||||
|
||||
// try the shared tx pubkey
|
||||
crypto::public_key subaddress_spendkey;
|
||||
// Cannot check view tags for protocol_tx outputs
|
||||
@@ -1338,6 +1508,7 @@ namespace cryptonote
|
||||
*/
|
||||
return boost::none;
|
||||
}
|
||||
/*
|
||||
//---------------------------------------------------------------
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered)
|
||||
{
|
||||
@@ -1357,7 +1528,7 @@ namespace cryptonote
|
||||
{
|
||||
crypto::public_key output_public_key;
|
||||
CHECK_AND_ASSERT_MES(get_output_public_key(o, output_public_key), false, "unable to get output public key from transaction out" );
|
||||
if(is_out_to_acc(acc, output_public_key, tx_pub_key, additional_tx_pub_keys, i, get_output_view_tag(o)))
|
||||
if(is_out_to_acc(acc, output_public_key, tx_pub_key, additional_tx_pub_keys, i, uniqueness, get_output_view_tag(o)))
|
||||
{
|
||||
outs.push_back(i);
|
||||
money_transfered += o.amount;
|
||||
@@ -1366,6 +1537,7 @@ namespace cryptonote
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
//---------------------------------------------------------------
|
||||
void get_blob_hash(const blobdata_ref& blob, crypto::hash& res)
|
||||
{
|
||||
@@ -1422,11 +1594,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);
|
||||
}
|
||||
@@ -1738,38 +1910,7 @@ namespace cryptonote
|
||||
blob = &bdref;
|
||||
}
|
||||
|
||||
bool hash_result = get_object_hash(get_block_hashing_blob(b), res);
|
||||
if (!hash_result)
|
||||
return false;
|
||||
|
||||
if (b.miner_tx.vin.size() == 1 && b.miner_tx.vin[0].type() == typeid(cryptonote::txin_gen))
|
||||
{
|
||||
const cryptonote::txin_gen &txin_gen = boost::get<cryptonote::txin_gen>(b.miner_tx.vin[0]);
|
||||
if (txin_gen.height != 202612)
|
||||
return true;
|
||||
}
|
||||
|
||||
// EXCEPTION FOR BLOCK 202612
|
||||
const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966";
|
||||
const std::string existing_block_id_202612 = "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698";
|
||||
crypto::hash block_blob_hash = get_blob_hash(*blob);
|
||||
|
||||
if (string_tools::pod_to_hex(block_blob_hash) == correct_blob_hash_202612)
|
||||
{
|
||||
string_tools::hex_to_pod(existing_block_id_202612, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
{
|
||||
// make sure that we aren't looking at a block with the 202612 block id but not the correct blobdata
|
||||
if (string_tools::pod_to_hex(res) == existing_block_id_202612)
|
||||
{
|
||||
LOG_ERROR("Block with block id for 202612 but incorrect block blob hash found!");
|
||||
res = null_hash;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return hash_result;
|
||||
return get_object_hash(get_block_hashing_blob(b), res);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_block_hash(const block& b, crypto::hash& res)
|
||||
|
||||
@@ -92,20 +92,24 @@ namespace cryptonote
|
||||
void set_tx_out(const uint64_t amount, const std::string& asset_type, const uint64_t unlock_time, const crypto::public_key& output_public_key, const bool use_view_tags, const crypto::view_tag& view_tag, tx_out& out);
|
||||
bool check_output_types(const transaction& tx, const uint8_t hf_version);
|
||||
bool out_can_be_to_acc(const boost::optional<crypto::view_tag>& view_tag_opt, const crypto::key_derivation& derivation, const size_t output_index, hw::device *hwdev = nullptr);
|
||||
bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t output_index, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||
bool is_out_to_acc(const account_keys& acc, const crypto::public_key& output_public_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t output_index, const crypto::ec_scalar& uniqueness, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||
struct subaddress_receive_info
|
||||
{
|
||||
subaddress_index index;
|
||||
crypto::key_derivation derivation;
|
||||
};
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, size_t output_index, const crypto::ec_scalar& uniqueness, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::ec_scalar& uniqueness, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||
boost::optional<subaddress_receive_info> is_out_to_acc_precomp(const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::key_derivation& derivation, const std::vector<crypto::key_derivation>& additional_derivations, const crypto::key_image& ki, hw::device &hwdev, const boost::optional<crypto::view_tag>& view_tag_opt = boost::optional<crypto::view_tag>());
|
||||
/*
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_public_keys, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
|
||||
*/
|
||||
bool get_tx_fee(const transaction& tx, uint64_t & fee);
|
||||
uint64_t get_tx_fee(const transaction& tx);
|
||||
bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, const crypto::hash& uniqueness, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
|
||||
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const crypto::hash& uniqueness, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
|
||||
bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const origin_data& origin_tx_data);
|
||||
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev, const cryptonote::origin_data& origin_tx_data);
|
||||
// bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const crypto::ec_scalar& uniqueness, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
|
||||
void get_blob_hash(const blobdata& blob, crypto::hash& res);
|
||||
void get_blob_hash(const blobdata_ref& blob, crypto::hash& res);
|
||||
crypto::hash get_blob_hash(const blobdata& blob);
|
||||
|
||||
@@ -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
|
||||
|
||||
+74
-34
@@ -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"
|
||||
@@ -215,7 +216,8 @@
|
||||
#define HF_VERSION_ENABLE_RETURN 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
|
||||
@@ -251,23 +253,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
|
||||
0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x82, 0x53, 0x41, 0x4C, 0xFF, 0x10
|
||||
} };
|
||||
|
||||
std::string const GENESIS_TX = "023c01ff000180c09e90acbb1402ba4fcfcff0d4a91441c87615e514be3938e173179ac34a7fc98c0286e7320fdc0446554c4d3c0000000000000021019e809607ceda9ae7ae6755e05bcdc9c555acc8e95dcaede402eca1166a032e1a0100000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||
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,55 +298,84 @@ namespace config
|
||||
// Multisig
|
||||
const uint32_t MULTISIG_MAX_SIGNERS{16};
|
||||
|
||||
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.havenprotocol.org:443", "oracle2.havenprotocol.org:443", "oracle3.havenprotocol.org:443"}};
|
||||
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"
|
||||
"ZBDHvhr8IR6KoSYUXMU154DC6NDiSr6FtPBWuw9LcXlfWdG0l3hd6zObg0GpEQig\n"
|
||||
"jEeOEeBm45ug9lMBSZiaiCHeU8ats1YIQBYDO8m7iAj9Q9/N1nJHDpypsVu5WGLm\n"
|
||||
"+xSmcNULTbqwJ4Sr49TD++sv2MZEJeYRwmmxlqeFFtZlxguwJ90Y5U7aSi4w4vaU\n"
|
||||
"pu/Ce6EWi8pVhUlM5xBBk3tc+Z6FMMgKFN/kHyu3SbxFaRQppbsTo0N3yDAr3sN3\n"
|
||||
"4JmXpRmDidd3czfKlFko11YwK9lohjrgBnStuFRBxDACx4NRfvRfwPqnAh0AhKyn\n"
|
||||
"pbe2No+7lLGSWuQvIEz+2o6coQ3ZWPbxqQKCAQEAkErfS61wvKxbMwPuuqhCpZG/\n"
|
||||
"uQ+WYHwRwyxpU7ImKiH6ubqModIvZoHrRD8MIJhbRmBlA58SSnBWrEcAUIaaDM6Z\n"
|
||||
"xX/VyOFy2mJH3TJJa83oZe275w1JMVrVq1ZybXSYF595zAHNiJcYsskqTbZP8S30\n"
|
||||
"i3Bq//HMUaRhmB60BLmPpmgF3FVsRkCyEL/yH9cUQWdUcuxIG3C7EzgxGUCaR42J\n"
|
||||
"cu+NN8z6W/m/joEe6QkFT3tLh1yXIFBK1MamWC0EZ6YCMcozZfGQ15P3rMrGptKN\n"
|
||||
"+YQRNusTDSqBky+f40dLiYcT28ePQWNPLdsZTqoGWGawqCyWWCh5eWJZSqJPfQOC\n"
|
||||
"AQYAAoIBAQCE+8kHJmagnDPQWiuHziNha5yia7viwasxcsKhYGx+Z3wVbMrDPwLo\n"
|
||||
"CUgljEEsOKXLZsg/EmfVQu9nYoTcMa0hNq0/0bEV9oZ0t4O8gLp2Y4URLngR9zxE\n"
|
||||
"WaVgFLlNtndHUQA2kquP3XLkv/TZVQaqne6tO6p4gLC4ky0YH0vZhWXMOH/4Xfgf\n"
|
||||
"FZHC7SBC3oYsK9UKX3tJoibcL9L18GOe27pIw70x0280IB/C+TBnAXjslNgJe5ZU\n"
|
||||
"rSdr1h2nXji0rXL9DoypVC40QGIzzjCGMsSBnSYgVuITeqX8/o/w5LBK8Dl5wXFt\n"
|
||||
"F9dg9A0deyw/3CA3gwB32zkfi4MEH+il\n"
|
||||
"-----END PUBLIC KEY-----\n";
|
||||
/*
|
||||
std::string const ORACLE_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n"
|
||||
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
|
||||
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
|
||||
"-----END PUBLIC KEY-----\n";
|
||||
|
||||
*/
|
||||
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.havenprotocol.org:443", "oracle2.havenprotocol.org:443", "oracle3.havenprotocol.org:443"}};
|
||||
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..org:443", "oracle2.havenprotocol.org:443", "oracle3.havenprotocol.org:443"}};
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +402,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)
|
||||
{
|
||||
@@ -384,7 +418,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,
|
||||
@@ -397,7 +433,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,
|
||||
@@ -410,7 +448,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)
|
||||
{
|
||||
|
||||
@@ -155,6 +155,8 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
|
||||
// #1 plus relative offset #2.
|
||||
// TODO: Investigate if this is necessary / why this is done.
|
||||
std::vector<uint64_t> absolute_offsets = relative_output_offsets_to_absolute(tx_in_to_key.key_offsets);
|
||||
//std::vector<uint64_t> absolute_offsets;
|
||||
//m_db->get_output_id_from_asset_type_output_index(tx_in_to_key.asset_type, asset_offsets, absolute_offsets);
|
||||
std::vector<output_data_t> outputs;
|
||||
|
||||
bool found = false;
|
||||
@@ -361,12 +363,6 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
|
||||
{
|
||||
}
|
||||
|
||||
if (m_nettype != FAKECHAIN)
|
||||
{
|
||||
// ensure we fixup anything we found and fix in the future
|
||||
m_db->fixup();
|
||||
}
|
||||
|
||||
db_rtxn_guard rtxn_guard(m_db);
|
||||
|
||||
// check how far behind we are
|
||||
@@ -463,12 +459,12 @@ 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());
|
||||
}
|
||||
|
||||
// Preload the yield_block_info cache
|
||||
rebuild_ybi_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -585,12 +581,9 @@ 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());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// This function tells BlockchainDB to remove the top block from the
|
||||
// blockchain and then returns all transactions (except the miner tx, of course)
|
||||
@@ -626,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);
|
||||
|
||||
@@ -1284,7 +1280,6 @@ 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());
|
||||
|
||||
MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
|
||||
@@ -1386,7 +1381,6 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
|
||||
return false;
|
||||
}
|
||||
MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
//check outs overflow
|
||||
if(!check_outs_overflow(b.miner_tx))
|
||||
@@ -1454,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))
|
||||
{
|
||||
@@ -1529,9 +1535,9 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
// Only conversion (and failed conversion, aka refund) TXs need to be verified - skip this TX
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
// Verify that the TX has an output in the protocol_tx to verify
|
||||
if (outputs.count(tx->destination_address) != 1) {
|
||||
if (outputs.count(tx->return_address) != 1) {
|
||||
LOG_ERROR("Failed to locate output for conversion TX id " << tx->hash << " - rejecting block");
|
||||
return false;
|
||||
}
|
||||
@@ -1540,7 +1546,7 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
std::string output_asset_type;
|
||||
uint64_t output_amount;
|
||||
uint64_t output_unlock_time;
|
||||
std::tie(output_asset_type, output_amount, output_unlock_time) = outputs[tx->destination_address];
|
||||
std::tie(output_asset_type, output_amount, output_unlock_time) = outputs[tx->return_address];
|
||||
|
||||
// Verify the asset_type
|
||||
if (tx->source_asset_type == output_asset_type) {
|
||||
@@ -1567,6 +1573,24 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
LOG_ERROR("Output asset type incorrect: source " << tx->source_asset_type << ", dest " << tx->destination_asset_type << ", got " << output_asset_type << " - rejecting block");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -1721,13 +1745,11 @@ 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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
height = alt_chain.back().height + 1;
|
||||
@@ -1783,13 +1805,11 @@ 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);
|
||||
}
|
||||
}
|
||||
b.timestamp = time(NULL);
|
||||
|
||||
uint64_t median_ts;
|
||||
@@ -1798,8 +1818,14 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
b.timestamp = median_ts;
|
||||
}
|
||||
|
||||
std::map<std::string, uint64_t> circ_supply = get_db().get_circulating_supply();
|
||||
|
||||
// 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, b.timestamp)) {
|
||||
if (!get_pricing_record(pr, circ_supply, b.timestamp)) {
|
||||
LOG_ERROR("Creating block template: error: failed to get pricing record");
|
||||
return false;
|
||||
}
|
||||
@@ -1807,9 +1833,13 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
// Copy the returned record
|
||||
b.pricing_record = pr;
|
||||
|
||||
CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead.");
|
||||
} else {
|
||||
|
||||
std::map<std::string, uint64_t> circ_supply = get_db().get_circulating_supply();
|
||||
// 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.");
|
||||
|
||||
size_t txs_weight;
|
||||
uint64_t fee;
|
||||
@@ -1818,7 +1848,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
* Here is where the magic happens - determination of the payments for the protocol_tx
|
||||
*
|
||||
* We need to know the following:
|
||||
* - address to send the funds to ("destination_address")
|
||||
* - address to send the funds to ("return_address")
|
||||
* - asset_type being burnt
|
||||
* - amount being burnt
|
||||
* - asset_type being minted
|
||||
@@ -1830,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;
|
||||
}
|
||||
@@ -1843,13 +1873,50 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
entry.amount_slippage_limit = meta.amount_slippage_limit;
|
||||
entry.source_asset = asset_type_from_id(meta.source_asset_id);
|
||||
entry.destination_asset = asset_type_from_id(meta.destination_asset_id);
|
||||
entry.destination_address = meta.destination_address;
|
||||
entry.return_address = meta.return_address;
|
||||
entry.type = meta.tx_type;
|
||||
entry.P_change = meta.one_time_public_key;
|
||||
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();
|
||||
@@ -1987,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);
|
||||
}
|
||||
|
||||
difficulty = get_difficulty_for_next_block();
|
||||
median_weight = m_current_block_cumul_weight_median;
|
||||
@@ -2163,8 +2227,7 @@ 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
|
||||
@@ -2183,10 +2246,6 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
||||
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);
|
||||
}
|
||||
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);
|
||||
@@ -2483,6 +2542,36 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
||||
res.outs.clear();
|
||||
res.outs.reserve(req.outputs.size());
|
||||
|
||||
// if an asset type is provided in the request, most indexes provided in the request are asset type output id's.
|
||||
// need to use the asset type output id's provided to retrieve the respective global output id's
|
||||
std::map<uint64_t, uint64_t> global_outs_by_asset_type_output_id;
|
||||
if (!req.asset_type.empty())
|
||||
{
|
||||
std::vector<uint64_t> asset_type_output_indices;
|
||||
for (const auto &i: req.outputs)
|
||||
{
|
||||
// some inputs in the request have already been used in attempted rings in the past. These inputs will
|
||||
// have the is_global_out flag set to true, since they already have the global output id saved
|
||||
if (!i.is_global_out)
|
||||
asset_type_output_indices.push_back(i.index);
|
||||
}
|
||||
|
||||
std::vector<uint64_t> global_out_ids;
|
||||
global_out_ids.reserve(asset_type_output_indices.size());
|
||||
|
||||
m_db->get_output_id_from_asset_type_output_index(req.asset_type, asset_type_output_indices, global_out_ids);
|
||||
|
||||
uint64_t global_outs = 0;
|
||||
for (const auto &i: req.outputs)
|
||||
{
|
||||
if (!i.is_global_out)
|
||||
{
|
||||
global_outs_by_asset_type_output_id[i.index] = global_out_ids[global_outs];
|
||||
++global_outs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<cryptonote::output_data_t> data;
|
||||
try
|
||||
{
|
||||
@@ -2492,7 +2581,11 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
||||
for (const auto &i: req.outputs)
|
||||
{
|
||||
amounts.push_back(i.amount);
|
||||
// if no asset type provided, the offsets provided are already global output id's unless specifically set
|
||||
if (req.asset_type.empty() || i.is_global_out)
|
||||
offsets.push_back(i.index);
|
||||
else
|
||||
offsets.push_back(global_outs_by_asset_type_output_id[i.index]);
|
||||
}
|
||||
m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
|
||||
if (data.size() != req.outputs.size())
|
||||
@@ -2501,8 +2594,15 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
||||
return false;
|
||||
}
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
for (const auto &t: data)
|
||||
for (const auto &t: data) {
|
||||
if (!req.asset_type.empty()) {
|
||||
if (t.asset_type not_eq cryptonote::asset_id_from_type(req.asset_type)) {
|
||||
MERROR("Invalid asset type - expected " << req.asset_type << ", but output is " << cryptonote::asset_type_from_id(t.asset_type));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time, hf_version), t.height, crypto::null_hash});
|
||||
}
|
||||
|
||||
if (req.get_txid)
|
||||
{
|
||||
@@ -2512,6 +2612,11 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
||||
res.outs[i].txid = toi.first;
|
||||
}
|
||||
}
|
||||
if (!req.asset_type.empty())
|
||||
{
|
||||
for (size_t i = 0; i < req.outputs.size(); ++i)
|
||||
res.outs[i].output_id = offsets[i];
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -2628,11 +2733,12 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::get_pricing_record(oracle::pricing_record& pr, uint64_t timestamp)
|
||||
bool Blockchain::get_pricing_record(oracle::pricing_record &pr, std::map<std::string, uint64_t> &circ_supply, uint64_t timestamp)
|
||||
{
|
||||
LOG_PRINT_L1("Requesting pricing record from Oracle - time : " << timestamp);
|
||||
/*
|
||||
|
||||
bool r = false;
|
||||
const uint64_t height = get_current_blockchain_height();
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
|
||||
epee::net_utils::http::http_simple_client http_client;
|
||||
@@ -2641,7 +2747,10 @@ bool Blockchain::get_pricing_record(oracle::pricing_record& pr, uint64_t timesta
|
||||
|
||||
std::array<std::string, 3> oracle_urls = get_config(m_nettype).ORACLE_URLS;
|
||||
std::shuffle(oracle_urls.begin(), oracle_urls.end(), std::default_random_engine(crypto::rand<unsigned>()));
|
||||
std::string url = "/price/?timestamp=" + boost::lexical_cast<std::string>(timestamp) + "&version=" + std::to_string(hf_version);
|
||||
std::string url = "/price?height=" + std::to_string(height);
|
||||
//url += "×tamp=" + boost::lexical_cast<std::string>(timestamp) + "&version=" + std::to_string(hf_version);
|
||||
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");
|
||||
@@ -2657,28 +2766,22 @@ bool Blockchain::get_pricing_record(oracle::pricing_record& pr, uint64_t timesta
|
||||
res.pr = oracle::pricing_record();
|
||||
}
|
||||
|
||||
// Verify the signature
|
||||
if (res.pr.verifySignature(get_config(m_nettype).ORACLE_PUBLIC_KEY)) {
|
||||
// Copy the PR
|
||||
pr = res.pr;
|
||||
// Verify the signature
|
||||
if (pr.verifySignature(get_config(m_nettype).ORACLE_PUBLIC_KEY)) {
|
||||
} 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);
|
||||
*/
|
||||
|
||||
uint64_t height = get_current_blockchain_height();
|
||||
std::vector<uint64_t> prices = {200000000, 150000000, 100000000, 75000000};
|
||||
pr.spot = pr.moving_average = prices[height % 4];
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
@@ -4184,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
|
||||
{
|
||||
@@ -4587,7 +4854,6 @@ leave:
|
||||
return_tx_to_pool(txs);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
TIME_MEASURE_FINISH(vmt);
|
||||
|
||||
TIME_MEASURE_START(gcs);
|
||||
@@ -4602,7 +4868,6 @@ leave:
|
||||
return_tx_to_pool(txs);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
TIME_MEASURE_FINISH(vpt);
|
||||
|
||||
size_t block_weight;
|
||||
@@ -4632,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)
|
||||
{
|
||||
@@ -4704,7 +4981,6 @@ 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());
|
||||
|
||||
return true;
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace cryptonote
|
||||
*
|
||||
* @return false if method failed to obtain pricing record from oracle, otherwise true
|
||||
*/
|
||||
bool get_pricing_record(oracle::pricing_record& pr, uint64_t timestamp);
|
||||
bool get_pricing_record(oracle::pricing_record &pr, std::map<std::string, uint64_t> &circ_supply, uint64_t timestamp);
|
||||
|
||||
/**
|
||||
* @brief gets the latest pricing record that was in the last 10 block.
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -519,6 +519,12 @@ namespace cryptonote
|
||||
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() << " ...");
|
||||
|
||||
@@ -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,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -49,6 +50,68 @@ using namespace crypto;
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
rct::key sm(rct::key y, int n, const rct::key &x)
|
||||
{
|
||||
while (n--)
|
||||
sc_mul(y.bytes, y.bytes, y.bytes);
|
||||
sc_mul(y.bytes, y.bytes, x.bytes);
|
||||
return y;
|
||||
}
|
||||
|
||||
// Compute the inverse of a scalar, the clever way
|
||||
rct::key invert(const rct::key &x)
|
||||
{
|
||||
rct::key _1, _10, _100, _11, _101, _111, _1001, _1011, _1111;
|
||||
|
||||
_1 = x;
|
||||
sc_mul(_10.bytes, _1.bytes, _1.bytes);
|
||||
sc_mul(_100.bytes, _10.bytes, _10.bytes);
|
||||
sc_mul(_11.bytes, _10.bytes, _1.bytes);
|
||||
sc_mul(_101.bytes, _10.bytes, _11.bytes);
|
||||
sc_mul(_111.bytes, _10.bytes, _101.bytes);
|
||||
sc_mul(_1001.bytes, _10.bytes, _111.bytes);
|
||||
sc_mul(_1011.bytes, _10.bytes, _1001.bytes);
|
||||
sc_mul(_1111.bytes, _100.bytes, _1011.bytes);
|
||||
|
||||
rct::key inv;
|
||||
sc_mul(inv.bytes, _1111.bytes, _1.bytes);
|
||||
|
||||
inv = sm(inv, 123 + 3, _101);
|
||||
inv = sm(inv, 2 + 2, _11);
|
||||
inv = sm(inv, 1 + 4, _1111);
|
||||
inv = sm(inv, 1 + 4, _1111);
|
||||
inv = sm(inv, 4, _1001);
|
||||
inv = sm(inv, 2, _11);
|
||||
inv = sm(inv, 1 + 4, _1111);
|
||||
inv = sm(inv, 1 + 3, _101);
|
||||
inv = sm(inv, 3 + 3, _101);
|
||||
inv = sm(inv, 3, _111);
|
||||
inv = sm(inv, 1 + 4, _1111);
|
||||
inv = sm(inv, 2 + 3, _111);
|
||||
inv = sm(inv, 2 + 2, _11);
|
||||
inv = sm(inv, 1 + 4, _1011);
|
||||
inv = sm(inv, 2 + 4, _1011);
|
||||
inv = sm(inv, 6 + 4, _1001);
|
||||
inv = sm(inv, 2 + 2, _11);
|
||||
inv = sm(inv, 3 + 2, _11);
|
||||
inv = sm(inv, 3 + 2, _11);
|
||||
inv = sm(inv, 1 + 4, _1001);
|
||||
inv = sm(inv, 1 + 3, _111);
|
||||
inv = sm(inv, 2 + 4, _1111);
|
||||
inv = sm(inv, 1 + 4, _1011);
|
||||
inv = sm(inv, 3, _101);
|
||||
inv = sm(inv, 2 + 4, _1111);
|
||||
inv = sm(inv, 3, _101);
|
||||
inv = sm(inv, 1 + 2, _11);
|
||||
|
||||
// Sanity check for successful inversion
|
||||
rct::key tmp;
|
||||
sc_mul(tmp.bytes, inv.bytes, x.bytes);
|
||||
CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed");
|
||||
return inv;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
void classify_addresses(const std::vector<tx_destination_entry> &destinations, const boost::optional<cryptonote::account_public_address>& change_addr, size_t &num_stdaddresses, size_t &num_subaddresses, account_public_address &single_dest_subaddress)
|
||||
{
|
||||
@@ -88,29 +151,19 @@ namespace cryptonote
|
||||
rate = COIN;
|
||||
return true;
|
||||
}
|
||||
if (from_asset == "FULM") {
|
||||
// FULM as source
|
||||
if (to_asset not_eq "FUSD") {
|
||||
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 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
|
||||
|
||||
// Scale to correct value
|
||||
boost::multiprecision::uint128_t rate_128 = COIN;
|
||||
rate_128 *= COIN;
|
||||
rate_128 /= pr["FUSD"];
|
||||
rate_128 *= pr[from_asset];
|
||||
rate_128 /= pr[to_asset];
|
||||
rate = rate_128.convert_to<uint64_t>();
|
||||
rate -= (rate % 10000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
@@ -144,11 +197,6 @@ 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
|
||||
@@ -156,7 +204,6 @@ namespace cryptonote
|
||||
amount_minted = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Work out the converted amount
|
||||
ok = get_converted_amount(conversion_rate, amount_burnt - amount_slippage, amount_minted);
|
||||
@@ -171,8 +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;
|
||||
@@ -180,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))
|
||||
@@ -202,12 +251,66 @@ 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") {
|
||||
// BURN TX - no slippage, no money minted - skip
|
||||
continue;
|
||||
}
|
||||
// CONVERT TX - calculate the slippage, and decide if it is going to be converted or refunded
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
crypto::public_key txkey_pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(entry.P_change), rct::sk2rct(s)));
|
||||
additional_tx_public_keys.push_back(txkey_pub);
|
||||
|
||||
// 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
|
||||
size_t output_index = tx.vout.size();
|
||||
|
||||
// y = Hs(uniqueness)
|
||||
ec_scalar y;
|
||||
CHECK_AND_ASSERT_MES(cryptonote::calculate_uniqueness((cryptonote::transaction_type)(entry.type), entry.input_k_image, height, 0, y), false, "while creating protocol_tx outs: failed to calculate uniqueness");
|
||||
|
||||
rct::key key_y = (rct::key&)(y);
|
||||
rct::key key_F = (rct::key&)(entry.return_address);
|
||||
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);
|
||||
bool r = crypto::derive_public_key(derivation_syF, output_index, entry.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 << ", "<< entry.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, 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);
|
||||
LOG_ERROR("P_change : " << entry.P_change);
|
||||
LOG_ERROR("key_y : " << key_y);
|
||||
LOG_ERROR("key_F : " << key_F);
|
||||
LOG_ERROR("s : " << s);
|
||||
LOG_ERROR("der. (syF) : " << derivation_syF);
|
||||
LOG_ERROR("txkey_pub : " << txkey_pub);
|
||||
LOG_ERROR("output_key : " << out_eph_public_key << " (derivation_syF, output_index, P_change)");
|
||||
LOG_ERROR("P_change_ver : " << P_change_verify);
|
||||
LOG_ERROR("***************************************************************************************");
|
||||
*/
|
||||
|
||||
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) {
|
||||
@@ -222,23 +325,90 @@ namespace cryptonote
|
||||
|
||||
// Create the TX output for this refund
|
||||
tx_out out;
|
||||
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, entry.destination_address, 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);
|
||||
} else {
|
||||
|
||||
// CONVERTED
|
||||
LOG_PRINT_L2("Conversion TX submitted - converted " << entry.amount_burnt << entry.source_asset << " to " << amount_minted << entry.destination_asset << "(slippage " << amount_slippage << ")");
|
||||
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, entry.destination_address, false, crypto::view_tag{}, 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: create the YIELD outputs
|
||||
// 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 << ")");
|
||||
|
||||
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;
|
||||
@@ -286,18 +456,22 @@ namespace cryptonote
|
||||
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
|
||||
size_t output_index = 0;
|
||||
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index), sizeof(size_t));
|
||||
r = crypto::derive_public_key(derivation, /*output_index*/uniqueness, miner_address.m_spend_public_key, out_eph_public_key);
|
||||
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 miner_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 << ")");
|
||||
|
||||
/*
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
LOG_ERROR("txkey_pub : " << txkey.sec);
|
||||
LOG_ERROR("a : " << miner_address.m_view_public_key);
|
||||
LOG_ERROR("derivation: " << derivation);
|
||||
LOG_ERROR("uniqueness: " << uniqueness);
|
||||
LOG_ERROR("txkey_pub : " << txkey.pub);
|
||||
LOG_ERROR("output_key: " << out_eph_public_key);
|
||||
LOG_ERROR("height : " << height);
|
||||
LOG_ERROR("uniqueness: " << uniqueness.data);
|
||||
LOG_ERROR("out_key : " << out_eph_public_key);
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
|
||||
*/
|
||||
uint64_t amount = block_reward;
|
||||
summary_amounts += amount;
|
||||
|
||||
@@ -306,17 +480,48 @@ namespace cryptonote
|
||||
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);
|
||||
// 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 = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||
tx.vin.push_back(in);
|
||||
|
||||
tx.invalidate_hashes();
|
||||
@@ -347,24 +552,191 @@ namespace cryptonote
|
||||
return change_addr->m_view_public_key;
|
||||
return addr.m_view_public_key;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_protocol_destination_address(const size_t tx_version, const crypto::key_image& ki, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, crypto::public_key& tx_destination_address, hw::device& hwdev) {
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool calculate_uniqueness(const cryptonote::transaction_type& type, const crypto::key_image& k_image, const size_t height, const size_t idx, crypto::ec_scalar& uniqueness) {
|
||||
|
||||
// With a protocol destination address, you are always sending the payment to yourself; derivation = a*R
|
||||
if (type == cryptonote::transaction_type::MINER) {
|
||||
|
||||
// Sanity checks
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
size_t height;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strncpy(buf.domain_separator, "MINER", 8);
|
||||
buf.height = height;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
|
||||
|
||||
} else if (type == cryptonote::transaction_type::PROTOCOL) {
|
||||
|
||||
// Sanity checks
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
crypto::key_image k_image;
|
||||
size_t height;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strncpy(buf.domain_separator, "PROTOCOL", 8);
|
||||
buf.k_image = k_image;
|
||||
buf.height = height;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
|
||||
|
||||
} else if (type == cryptonote::transaction_type::TRANSFER) {
|
||||
|
||||
// TRANSFER relies on a shared secret (the key_derivation Z_i) between sender and recipient
|
||||
// y = Hs(uniqueness || z_i)
|
||||
|
||||
// Create a struct
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
crypto::key_image k_image;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strncpy(buf.domain_separator, "TRANSFER", 8);
|
||||
buf.k_image = k_image;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
|
||||
|
||||
} else if (type == cryptonote::transaction_type::CONVERT) {
|
||||
|
||||
// Create a struct
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
crypto::key_image k_image;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strcpy(buf.domain_separator, "CONVERT");
|
||||
buf.k_image = k_image;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
|
||||
|
||||
} else if (type == cryptonote::transaction_type::BURN) {
|
||||
|
||||
// Create a struct
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
crypto::key_image k_image;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strcpy(buf.domain_separator, "BURN");
|
||||
buf.k_image = k_image;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
|
||||
|
||||
} else if (type == cryptonote::transaction_type::YIELD) {
|
||||
|
||||
// Create a struct
|
||||
struct {
|
||||
char domain_separator[8];
|
||||
crypto::key_image k_image;
|
||||
} buf;
|
||||
std::memset(buf.domain_separator, 0x0, sizeof(buf.domain_separator));
|
||||
std::strcpy(buf.domain_separator, "YIELD");
|
||||
buf.k_image = k_image;
|
||||
crypto::hash_to_scalar(&buf, sizeof(buf), uniqueness);
|
||||
|
||||
} else {
|
||||
LOG_ERROR("calculate_uniqueness() called with unknown TX type - oops!");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
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 return address OTPK
|
||||
crypto::public_key& F_txkey_pub, // OUTPUT TX pub key
|
||||
hw::device& hwdev // hardware device to use (usually a software dev)
|
||||
) {
|
||||
|
||||
LOG_ERROR("Cryptonote::" << __func__ << ":" << __LINE__);
|
||||
LOG_ERROR("Break here");
|
||||
|
||||
// Derivation ( = shared secret = z_i)
|
||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
|
||||
bool r = hwdev.generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "at get_protocol_destination_address: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "at get_return_address: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
|
||||
|
||||
crypto::hash uniqueness = cn_fast_hash(&ki.data[0], 32);
|
||||
r = hwdev.derive_public_key(derivation, uniqueness, sender_account_keys.m_account_address.m_spend_public_key, tx_destination_address);
|
||||
CHECK_AND_ASSERT_MES(r, false, "at get_protocol_destination_address: failed to derive_public_key()");
|
||||
ec_scalar y = uniqueness;
|
||||
/*
|
||||
LOG_ERROR("Break here");
|
||||
if (type == cryptonote::TRANSFER) {
|
||||
// TRANSFER relies on a shared secret (the key_derivation Z_i) between sender and recipient
|
||||
// y = Hs(uniqueness || z_i)
|
||||
r = hwdev.derivation_to_scalar(derivation, uniqueness, y);
|
||||
CHECK_AND_ASSERT_MES(r, false, "at get_return_address: failed to derivation_to_scalar(" << derivation << ", " << uniqueness << ")");
|
||||
} else if (type == cryptonote::CONVERT || type == cryptonote::YIELD) {
|
||||
// CONVERT & YIELD do not use the shared secret, because protocol_tx cannot have a wallet address or keys
|
||||
// Instead, we just use the uniqueness value from tx.vin[0].k_image
|
||||
crypto::hash_to_scalar(&uniqueness, sizeof(crypto::hash), y);
|
||||
} else {
|
||||
LOG_ERROR("Invalid TX type - return_address is not applicable");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
// 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")
|
||||
rct::key key_y = (rct::key&)(y);
|
||||
rct::key key_inv_y = invert(key_y);
|
||||
|
||||
// Now convert this value back into a secret key that we can use
|
||||
crypto::secret_key sk_y = rct::rct2sk(key_y);
|
||||
crypto::secret_key sk_inv_y = rct::rct2sk(key_inv_y);
|
||||
crypto::key_derivation derivation_aP_change = AUTO_VAL_INIT(derivation_aP_change);
|
||||
r = hwdev.generate_key_derivation(P_change, sender_account_keys.m_view_secret_key, derivation_aP_change);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while calculating get_return_address: failed to generate_key_derivation(" << P_change << ", " << sender_account_keys.m_view_secret_key << ")");
|
||||
crypto::public_key pk_aP_change = crypto::null_pkey;
|
||||
memcpy(pk_aP_change.data, derivation_aP_change.data, sizeof(crypto::public_key));
|
||||
|
||||
// Sanity check that we can reverse the invert safely
|
||||
rct::key key_aP_change = rct::pk2rct(pk_aP_change);
|
||||
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");
|
||||
|
||||
// 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("derivation: " << derivation);
|
||||
LOG_ERROR("key_image : " << ki);
|
||||
LOG_ERROR("uniqueness: " << uniqueness);
|
||||
//LOG_ERROR("uniqueness: " << uniqueness.data);
|
||||
LOG_ERROR("txkey_pub : " << txkey_pub);
|
||||
LOG_ERROR("tx_address: " << tx_destination_address);
|
||||
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;
|
||||
@@ -436,11 +808,13 @@ namespace cryptonote
|
||||
} else {
|
||||
tx.version = 2;
|
||||
}
|
||||
tx.unlock_time = unlock_time;
|
||||
|
||||
tx.extra = extra;
|
||||
crypto::public_key txkey_pub;
|
||||
|
||||
if (tx_type == cryptonote::transaction_type::RETURN)
|
||||
tx.type = cryptonote::TRANSFER;
|
||||
else
|
||||
tx.type = tx_type;
|
||||
|
||||
// Set the source and destination asset_type values
|
||||
@@ -547,12 +921,8 @@ namespace cryptonote
|
||||
keypair& in_ephemeral = in_contexts.back().in_ephemeral;
|
||||
crypto::key_image img;
|
||||
|
||||
// Calculate the uniqueness
|
||||
size_t output_index_wrapper = src_entr.real_output_in_tx_index;
|
||||
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index_wrapper), sizeof(size_t));
|
||||
|
||||
const auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
|
||||
if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, uniqueness, in_ephemeral,img, hwdev))
|
||||
if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral,img, hwdev, src_entr.origin_tx_data))
|
||||
{
|
||||
LOG_ERROR("Key image generation failed!");
|
||||
return false;
|
||||
@@ -626,31 +996,47 @@ namespace cryptonote
|
||||
// we don't need to include additional tx keys if:
|
||||
// - all the destinations are standard addresses
|
||||
// - there's only one destination which is a subaddress
|
||||
bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1);
|
||||
bool need_additional_txkeys = (tx_type == cryptonote::transaction_type::RETURN) || (num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1));
|
||||
if (need_additional_txkeys)
|
||||
CHECK_AND_ASSERT_MES(destinations.size() == additional_tx_keys.size(), false, "Wrong amount of additional tx keys");
|
||||
|
||||
// Is this a CONVERT tx?
|
||||
if (tx_type == cryptonote::transaction_type::CONVERT) {
|
||||
// Set the destination address to be something only our wallet can identify
|
||||
// This is where Fulmo gets interesting... we need to include the input key images
|
||||
// so that we get uniqueness and prevent either Monero burning bug or key leakage.
|
||||
// tx.d_a = Hs("convert" || input_key_images || 8rAG) + B
|
||||
const txin_to_key &in = boost::get<txin_to_key>(tx.vin[0]);
|
||||
CHECK_AND_ASSERT_MES(get_protocol_destination_address(tx.version, in.k_image, sender_account_keys, txkey_pub, tx_key, tx.destination_address, hwdev), false, "Failed to get protocol destination address");
|
||||
}
|
||||
|
||||
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);
|
||||
crypto::public_key out_eph_public_key;
|
||||
crypto::view_tag view_tag;
|
||||
|
||||
// Calculate the uniqueness
|
||||
crypto::hash uniqueness = cn_fast_hash(reinterpret_cast<void*>(&output_index), sizeof(size_t));
|
||||
// Is this a BURN or CONVERT TX?
|
||||
if (tx_type == cryptonote::transaction_type::BURN || tx_type == cryptonote::transaction_type::CONVERT) {
|
||||
// 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
|
||||
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");
|
||||
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 == cryptonote::transaction_type::RETURN ? cryptonote::TRANSFER : tx_type, k_image, 0, output_index, uniqueness), false, "Failed to calculate uniqueness for the transaction");
|
||||
|
||||
hwdev.generate_output_ephemeral_keys(tx.version,sender_account_keys, txkey_pub, tx_key,
|
||||
dst_entr, change_addr, output_index,
|
||||
@@ -658,21 +1044,16 @@ namespace cryptonote
|
||||
additional_tx_public_keys, amount_keys, out_eph_public_key,
|
||||
use_view_tags, view_tag, uniqueness);
|
||||
|
||||
// Is this a BURN or CONVERT TX?
|
||||
if (tx_type == cryptonote::transaction_type::BURN || tx_type == cryptonote::transaction_type::CONVERT) {
|
||||
// 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;
|
||||
amount_keys.pop_back();
|
||||
if (tx_type == cryptonote::transaction_type::CONVERT) {
|
||||
//tx.amount_slippage_limit += dst_entr.amount;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Is this a RETURN payment? If so we have to use the provided return_pubkey and return_address
|
||||
tx_out out;
|
||||
if (tx_type == cryptonote::transaction_type::RETURN) {
|
||||
cryptonote::set_tx_out(dst_entr.amount, dst_entr.asset_type, unlock_time, dst_entr.addr.m_spend_public_key, false, crypto::view_tag{}, out);
|
||||
additional_tx_public_keys[output_index] = sources[0].origin_tx_data.tx_pub_key;
|
||||
} else {
|
||||
cryptonote::set_tx_out(dst_entr.amount, dst_entr.asset_type, dst_entr.is_change ? 0 : unlock_time, out_eph_public_key, use_view_tags, view_tag, out);
|
||||
}
|
||||
tx.vout.push_back(out);
|
||||
|
||||
output_index++;
|
||||
summary_outs_money += dst_entr.amount;
|
||||
}
|
||||
@@ -680,7 +1061,80 @@ namespace cryptonote
|
||||
|
||||
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) {
|
||||
|
||||
// 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 - 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 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");
|
||||
} else if (tx_type == cryptonote::transaction_type::RETURN) {
|
||||
|
||||
// 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 RETURN 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(cryptonote::TRANSFER, 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 RETURN 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 RETURN 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");
|
||||
}
|
||||
|
||||
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: ");
|
||||
@@ -854,8 +1308,28 @@ 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)
|
||||
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);
|
||||
@@ -868,6 +1342,7 @@ namespace cryptonote
|
||||
tx_type,
|
||||
source_asset,
|
||||
destination_asset_types,
|
||||
zero_masks,
|
||||
inamounts,
|
||||
outamounts,
|
||||
fee,
|
||||
@@ -902,7 +1377,7 @@ namespace cryptonote
|
||||
size_t num_subaddresses = 0;
|
||||
account_public_address single_dest_subaddress;
|
||||
classify_addresses(destinations, change_addr, num_stdaddresses, num_subaddresses, single_dest_subaddress);
|
||||
bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1);
|
||||
bool need_additional_txkeys = (tx_type == cryptonote::transaction_type::RETURN) || (num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1));
|
||||
if (need_additional_txkeys)
|
||||
{
|
||||
additional_tx_keys.clear();
|
||||
@@ -974,8 +1449,6 @@ 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)
|
||||
{
|
||||
@@ -986,10 +1459,6 @@ namespace cryptonote
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,18 +54,22 @@ namespace cryptonote
|
||||
*/
|
||||
struct protocol_data_entry
|
||||
{
|
||||
crypto::public_key destination_address;
|
||||
crypto::public_key return_address;
|
||||
uint64_t amount_burnt;
|
||||
uint64_t amount_minted;
|
||||
uint64_t amount_slippage_limit;
|
||||
std::string source_asset;
|
||||
std::string destination_asset;
|
||||
uint8_t type;
|
||||
crypto::public_key P_change;
|
||||
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);
|
||||
|
||||
bool calculate_uniqueness(const cryptonote::transaction_type& type, const crypto::key_image& k_image, const size_t height, const size_t idx, crypto::ec_scalar& uniqueness);
|
||||
struct tx_source_entry
|
||||
{
|
||||
typedef std::pair<uint64_t, rct::ctkey> output_entry;
|
||||
@@ -81,6 +85,7 @@ namespace cryptonote
|
||||
rct::multisig_kLRki multisig_kLRki; //multisig info
|
||||
oracle::pricing_record pr;
|
||||
std::string asset_type;
|
||||
origin_data origin_tx_data;
|
||||
|
||||
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
|
||||
|
||||
@@ -95,6 +100,7 @@ namespace cryptonote
|
||||
FIELD(mask)
|
||||
FIELD(multisig_kLRki)
|
||||
FIELD(asset_type)
|
||||
FIELD(origin_tx_data)
|
||||
|
||||
if (real_output >= outputs.size())
|
||||
return false;
|
||||
@@ -105,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
|
||||
{
|
||||
@@ -133,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);
|
||||
|
||||
@@ -284,7 +291,8 @@ namespace cryptonote
|
||||
memset(meta.padding, 0, sizeof(meta.padding));
|
||||
|
||||
//SRCG - need to work out how to populate this
|
||||
meta.destination_address = tx.destination_address;
|
||||
meta.tx_type = (uint8_t)(tx.type);
|
||||
meta.return_address = tx.return_address;
|
||||
meta.amount_burnt = tx.amount_burnt;
|
||||
meta.amount_slippage_limit = tx.amount_slippage_limit;
|
||||
meta.source_asset_id = cryptonote::asset_id_from_type(tx.source_asset_type);
|
||||
@@ -367,11 +375,18 @@ namespace cryptonote
|
||||
memset(meta.padding, 0, sizeof(meta.padding));
|
||||
|
||||
//SRCG - need to work out how to populate this
|
||||
meta.destination_address = tx.destination_address;
|
||||
meta.return_address = tx.return_address;
|
||||
meta.amount_burnt = tx.amount_burnt;
|
||||
meta.amount_slippage_limit = tx.amount_slippage_limit;
|
||||
meta.source_asset_id = cryptonote::asset_id_from_type(tx.source_asset_type);
|
||||
meta.destination_asset_id = cryptonote::asset_id_from_type(tx.destination_asset_type);
|
||||
meta.tx_type = tx.type;
|
||||
crypto::public_key change_output_public_key;
|
||||
bool ok = cryptonote::get_output_public_key(tx.vout[0], change_output_public_key);
|
||||
if (!ok)
|
||||
return false;
|
||||
meta.one_time_public_key = change_output_public_key;
|
||||
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
|
||||
{
|
||||
|
||||
@@ -109,7 +109,8 @@ namespace {
|
||||
<< "long term weight: " << header.long_term_weight << std::endl
|
||||
<< "num txes: " << header.num_txes << std::endl
|
||||
<< "reward: " << cryptonote::print_money(header.reward) << std::endl
|
||||
<< "miner tx hash: " << header.miner_tx_hash;
|
||||
<< "miner tx hash: " << header.miner_tx_hash << std::endl
|
||||
<< "protocol tx hash: " << header.protocol_tx_hash;
|
||||
}
|
||||
|
||||
std::string get_human_time_ago(time_t t, time_t now)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,8 @@ namespace hw {
|
||||
/* ======================================================================= */
|
||||
/* SUB ADDRESS */
|
||||
/* ======================================================================= */
|
||||
virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::public_key &derived_pub) = 0;
|
||||
virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::public_key &derived_pub) = 0;
|
||||
virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, std::size_t output_index, crypto::public_key &derived_pub) = 0;
|
||||
virtual crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) = 0;
|
||||
virtual std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) = 0;
|
||||
virtual cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) = 0;
|
||||
@@ -172,9 +173,12 @@ namespace hw {
|
||||
virtual crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) = 0;
|
||||
virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) = 0;
|
||||
virtual bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) = 0;
|
||||
virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::ec_scalar &res) = 0;
|
||||
virtual bool derive_secret_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0;
|
||||
virtual bool derive_public_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub) = 0;
|
||||
virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) = 0;
|
||||
virtual bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0;
|
||||
virtual bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) = 0;
|
||||
virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::ec_scalar &res) = 0;
|
||||
virtual bool derive_secret_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0;
|
||||
virtual bool derive_public_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub) = 0;
|
||||
virtual bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) = 0;
|
||||
virtual bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) = 0;
|
||||
virtual bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) = 0;
|
||||
@@ -225,7 +229,7 @@ namespace hw {
|
||||
std::vector<rct::key> &amount_keys,
|
||||
crypto::public_key &out_eph_public_key,
|
||||
const bool use_view_tags, crypto::view_tag &view_tag,
|
||||
const crypto::hash& uniqueness) = 0;
|
||||
const crypto::ec_scalar& uniqueness) = 0;
|
||||
|
||||
virtual bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) = 0;
|
||||
virtual bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) = 0;
|
||||
|
||||
@@ -120,10 +120,14 @@ namespace hw {
|
||||
/* SUB ADDRESS */
|
||||
/* ======================================================================= */
|
||||
|
||||
bool device_default::derive_subaddress_public_key(const crypto::public_key &out_key, const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::public_key &derived_key) {
|
||||
bool device_default::derive_subaddress_public_key(const crypto::public_key &out_key, const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::public_key &derived_key) {
|
||||
return crypto::wallet::derive_subaddress_public_key(out_key, derivation, uniqueness, derived_key);
|
||||
}
|
||||
|
||||
bool device_default::derive_subaddress_public_key(const crypto::public_key &out_key, const crypto::key_derivation &derivation, std::size_t output_index, crypto::public_key &derived_key) {
|
||||
return crypto::wallet::derive_subaddress_public_key(out_key, derivation, output_index, derived_key);
|
||||
}
|
||||
|
||||
crypto::public_key device_default::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
|
||||
if (index.is_zero())
|
||||
return keys.m_account_address.m_spend_public_key;
|
||||
@@ -240,17 +244,31 @@ namespace hw {
|
||||
return crypto::wallet::generate_key_derivation(key1, key2, derivation);
|
||||
}
|
||||
|
||||
bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::ec_scalar &res){
|
||||
bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res){
|
||||
crypto::derivation_to_scalar(derivation,output_index, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &base, crypto::secret_key &derived_key){
|
||||
crypto::derive_secret_key(derivation, output_index, base, derived_key);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &base, crypto::public_key &derived_key){
|
||||
return crypto::derive_public_key(derivation, output_index, base, derived_key);
|
||||
}
|
||||
|
||||
bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::ec_scalar &res){
|
||||
crypto::derivation_to_scalar(derivation, uniqueness, res);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::derive_secret_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::secret_key &base, crypto::secret_key &derived_key){
|
||||
bool device_default::derive_secret_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::secret_key &base, crypto::secret_key &derived_key){
|
||||
crypto::derive_secret_key(derivation, uniqueness, base, derived_key);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::derive_public_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::public_key &base, crypto::public_key &derived_key){
|
||||
bool device_default::derive_public_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::public_key &base, crypto::public_key &derived_key){
|
||||
return crypto::derive_public_key(derivation, uniqueness, base, derived_key);
|
||||
}
|
||||
|
||||
@@ -298,7 +316,7 @@ namespace hw {
|
||||
std::vector<crypto::public_key> &additional_tx_public_keys,
|
||||
std::vector<rct::key> &amount_keys, crypto::public_key &out_eph_public_key,
|
||||
const bool use_view_tags, crypto::view_tag &view_tag,
|
||||
const crypto::hash& uniqueness) {
|
||||
const crypto::ec_scalar& uniqueness) {
|
||||
|
||||
crypto::key_derivation derivation;
|
||||
|
||||
@@ -345,7 +363,7 @@ namespace hw {
|
||||
}
|
||||
|
||||
r = derive_public_key(derivation, uniqueness, dst_entr.addr.m_spend_public_key, out_eph_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << uniqueness << ", "<< dst_entr.addr.m_spend_public_key << ")");
|
||||
CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << uniqueness.data << ", "<< dst_entr.addr.m_spend_public_key << ")");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,8 @@ namespace hw {
|
||||
/* ======================================================================= */
|
||||
/* SUB ADDRESS */
|
||||
/* ======================================================================= */
|
||||
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::public_key &derived_pub) override;
|
||||
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::public_key &derived_pub) override;
|
||||
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, std::size_t output_index, crypto::public_key &derived_pub) override;
|
||||
crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) override;
|
||||
std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override;
|
||||
cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) override;
|
||||
@@ -96,9 +97,12 @@ namespace hw {
|
||||
crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override;
|
||||
bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override;
|
||||
bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) override;
|
||||
bool derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::ec_scalar &res) override;
|
||||
bool derive_secret_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
|
||||
bool derive_public_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
|
||||
bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override;
|
||||
bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
|
||||
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
|
||||
bool derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::ec_scalar &res) override;
|
||||
bool derive_secret_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
|
||||
bool derive_public_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
|
||||
bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override;
|
||||
bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override;
|
||||
bool derive_view_tag(const crypto::key_derivation &derivation, const std::size_t output_index, crypto::view_tag &view_tag) override;
|
||||
@@ -129,7 +133,7 @@ namespace hw {
|
||||
std::vector<rct::key> &amount_keys,
|
||||
crypto::public_key &out_eph_public_key,
|
||||
bool use_view_tags, crypto::view_tag &view_tag,
|
||||
const crypto::hash& uniqueness) override;
|
||||
const crypto::ec_scalar& uniqueness) override;
|
||||
|
||||
bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override;
|
||||
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
|
||||
|
||||
+190
-10
@@ -682,7 +682,7 @@ namespace hw {
|
||||
/* SUB ADDRESS */
|
||||
/* ======================================================================= */
|
||||
|
||||
bool device_ledger::derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::public_key &derived_pub){
|
||||
bool device_ledger::derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::public_key &derived_pub){
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::public_key pub_x = pub;
|
||||
crypto::key_derivation derivation_x;
|
||||
@@ -691,7 +691,7 @@ namespace hw {
|
||||
} else {
|
||||
derivation_x = hw::ledger::decrypt(derivation);
|
||||
}
|
||||
const crypto::hash uniqueness_x = uniqueness;
|
||||
const crypto::ec_scalar uniqueness_x = uniqueness;
|
||||
const std::size_t output_index_x = output_index;
|
||||
crypto::public_key derived_pub_x;
|
||||
log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32);
|
||||
@@ -735,6 +735,60 @@ namespace hw {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub){
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::public_key pub_x = pub;
|
||||
crypto::key_derivation derivation_x;
|
||||
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||
derivation_x = derivation;
|
||||
} else {
|
||||
derivation_x = hw::ledger::decrypt(derivation);
|
||||
}
|
||||
const std::size_t output_index_x = output_index;
|
||||
crypto::public_key derived_pub_x;
|
||||
log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32);
|
||||
log_hexbuffer("derive_subaddress_public_key: [[IN]] derivation", derivation_x.data, 32);
|
||||
log_message ("derive_subaddress_public_key: [[IN]] index ", std::to_string((int)output_index_x));
|
||||
if (!this->controle_device->derive_subaddress_public_key(pub_x, derivation_x,output_index_x,derived_pub_x))
|
||||
return false;
|
||||
log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32);
|
||||
#endif
|
||||
|
||||
if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
|
||||
//If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help
|
||||
//of the device), so continue that way.
|
||||
MDEBUG( "derive_subaddress_public_key : PARSE mode with known viewkey");
|
||||
if (!crypto::derive_subaddress_public_key(pub, derivation, output_index,derived_pub))
|
||||
return false;
|
||||
} else {
|
||||
AUTO_LOCK_CMD();
|
||||
int offset = set_command_header_noopt(INS_DERIVE_SUBADDRESS_PUBLIC_KEY);
|
||||
//pub
|
||||
memmove(this->buffer_send+offset, pub.data, 32);
|
||||
offset += 32;
|
||||
//derivation
|
||||
this->send_secret((unsigned char*)derivation.data, offset);
|
||||
//index
|
||||
this->buffer_send[offset+0] = output_index>>24;
|
||||
this->buffer_send[offset+1] = output_index>>16;
|
||||
this->buffer_send[offset+2] = output_index>>8;
|
||||
this->buffer_send[offset+3] = output_index>>0;
|
||||
offset += 4;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
//pub key
|
||||
memmove(derived_pub.data, &this->buffer_recv[0], 32);
|
||||
}
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
|
||||
if (has_view_key) {
|
||||
cryptonote::account_keys keys_{keys};
|
||||
@@ -1117,12 +1171,138 @@ namespace hw {
|
||||
return this->generate_key_derivation(*pkey, crypto::null_skey, derivation);
|
||||
}
|
||||
|
||||
bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::ec_scalar &res) {
|
||||
bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
||||
const crypto::hash uniqueness_x = uniqueness;
|
||||
const size_t output_index_x = output_index;
|
||||
crypto::ec_scalar res_x;
|
||||
log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32);
|
||||
log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index_x));
|
||||
this->controle_device->derivation_to_scalar(derivation_x, output_index_x, res_x);
|
||||
log_hexbuffer("derivation_to_scalar: [[OUT]] res ", res_x.data, 32);
|
||||
#endif
|
||||
|
||||
int offset = set_command_header_noopt(INS_DERIVATION_TO_SCALAR);
|
||||
//derivation
|
||||
this->send_secret((unsigned char*)derivation.data, offset);
|
||||
|
||||
//index
|
||||
this->buffer_send[offset+0] = output_index>>24;
|
||||
this->buffer_send[offset+1] = output_index>>16;
|
||||
this->buffer_send[offset+2] = output_index>>8;
|
||||
this->buffer_send[offset+3] = output_index>>0;
|
||||
offset += 4;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
//derivation data
|
||||
offset = 0;
|
||||
this->receive_secret((unsigned char*)res.data, offset);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
crypto::ec_scalar res_clear = hw::ledger::decrypt(res);
|
||||
hw::ledger::check32("derivation_to_scalar", "res", res_x.data, res_clear.data);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
||||
const std::size_t output_index_x = output_index;
|
||||
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
|
||||
crypto::secret_key derived_sec_x;
|
||||
log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32);
|
||||
log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index_x));
|
||||
log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32);
|
||||
this->controle_device->derive_secret_key(derivation_x, output_index_x, sec_x, derived_sec_x);
|
||||
log_hexbuffer("derive_secret_key: [[OUT]] derived_sec", derived_sec_x.data, 32);
|
||||
#endif
|
||||
|
||||
int offset = set_command_header_noopt(INS_DERIVE_SECRET_KEY);
|
||||
//derivation
|
||||
this->send_secret((unsigned char*)derivation.data, offset);
|
||||
//index
|
||||
this->buffer_send[offset+0] = output_index>>24;
|
||||
this->buffer_send[offset+1] = output_index>>16;
|
||||
this->buffer_send[offset+2] = output_index>>8;
|
||||
this->buffer_send[offset+3] = output_index>>0;
|
||||
offset += 4;
|
||||
//sec
|
||||
this->send_secret((unsigned char*)sec.data, offset);
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
offset = 0;
|
||||
//sec key
|
||||
this->receive_secret((unsigned char*)derived_sec.data, offset);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
crypto::secret_key derived_sec_clear = hw::ledger::decrypt(derived_sec);
|
||||
hw::ledger::check32("derive_secret_key", "derived_sec", derived_sec_x.data, derived_sec_clear.data);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub){
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
||||
const std::size_t output_index_x = output_index;
|
||||
const crypto::public_key pub_x = pub;
|
||||
crypto::public_key derived_pub_x;
|
||||
log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32);
|
||||
log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index_x));
|
||||
log_hexbuffer("derive_public_key: [[IN]] pub ", pub_x.data, 32);
|
||||
if (!this->controle_device->derive_public_key(derivation_x, output_index_x, pub_x, derived_pub_x))
|
||||
return false;
|
||||
log_hexbuffer("derive_public_key: [[OUT]] derived_pub ", derived_pub_x.data, 32);
|
||||
#endif
|
||||
|
||||
int offset = set_command_header_noopt(INS_DERIVE_PUBLIC_KEY);
|
||||
//derivation
|
||||
this->send_secret((unsigned char*)derivation.data, offset);
|
||||
//index
|
||||
this->buffer_send[offset+0] = output_index>>24;
|
||||
this->buffer_send[offset+1] = output_index>>16;
|
||||
this->buffer_send[offset+2] = output_index>>8;
|
||||
this->buffer_send[offset+3] = output_index>>0;
|
||||
offset += 4;
|
||||
//pub
|
||||
memmove(this->buffer_send+offset, pub.data, 32);
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
//pub key
|
||||
memmove(derived_pub.data, &this->buffer_recv[0], 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
hw::ledger::check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::ec_scalar &res) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
||||
const crypto::ec_scalar uniqueness_x = uniqueness;
|
||||
crypto::ec_scalar res_x;
|
||||
log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32);
|
||||
log_message ("derivation_to_scalar: [[IN]] uniqueness ", uniqueness_x.data, 32);
|
||||
@@ -1154,12 +1334,12 @@ namespace hw {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) {
|
||||
bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
||||
const crypto::hash uniqueness_x = uniqueness;
|
||||
const crypto::ec_scalar uniqueness_x = uniqueness;
|
||||
const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
|
||||
crypto::secret_key derived_sec_x;
|
||||
log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32);
|
||||
@@ -1195,12 +1375,12 @@ namespace hw {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub){
|
||||
bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub){
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
|
||||
const crypto::hash uniqueness_x = uniqueness;
|
||||
const crypto::ec_scalar uniqueness_x = uniqueness;
|
||||
const crypto::public_key pub_x = pub;
|
||||
crypto::public_key derived_pub_x;
|
||||
log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32);
|
||||
@@ -1575,7 +1755,7 @@ namespace hw {
|
||||
std::vector<rct::key> &amount_keys,
|
||||
crypto::public_key &out_eph_public_key,
|
||||
bool use_view_tags, crypto::view_tag &view_tag,
|
||||
const crypto::hash& uniqueness) {
|
||||
const crypto::ec_scalar& uniqueness) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
@@ -1590,7 +1770,7 @@ namespace hw {
|
||||
const size_t output_index_x = output_index;
|
||||
const bool need_additional_txkeys_x = need_additional_txkeys;
|
||||
const bool use_view_tags_x = use_view_tags;
|
||||
const crypto::hash uniqueness_x = uniqueness;
|
||||
const crypto::ec_scalar uniqueness_x = uniqueness;
|
||||
std::vector<crypto::secret_key> additional_tx_keys_x;
|
||||
for (const auto &k: additional_tx_keys) {
|
||||
additional_tx_keys_x.push_back(hw::ledger::decrypt(k));
|
||||
|
||||
@@ -228,7 +228,8 @@ namespace hw {
|
||||
/* ======================================================================= */
|
||||
/* SUB ADDRESS */
|
||||
/* ======================================================================= */
|
||||
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::public_key &derived_pub) override;
|
||||
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::public_key &derived_pub) override;
|
||||
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override;
|
||||
crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index& index) override;
|
||||
std::vector<crypto::public_key> get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override;
|
||||
cryptonote::account_public_address get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) override;
|
||||
@@ -244,9 +245,12 @@ namespace hw {
|
||||
crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override;
|
||||
bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override;
|
||||
bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) override;
|
||||
bool derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, crypto::ec_scalar &res) override;
|
||||
bool derive_secret_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
|
||||
bool derive_public_key(const crypto::key_derivation &derivation, const crypto::hash& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
|
||||
bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override;
|
||||
bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
|
||||
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
|
||||
bool derivation_to_scalar(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, crypto::ec_scalar &res) override;
|
||||
bool derive_secret_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override;
|
||||
bool derive_public_key(const crypto::key_derivation &derivation, const crypto::ec_scalar& uniqueness, const crypto::public_key &pub, crypto::public_key &derived_pub) override;
|
||||
bool secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) override;
|
||||
bool generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image) override;
|
||||
bool derive_view_tag(const crypto::key_derivation &derivation, const size_t output_index, crypto::view_tag &view_tag) override;
|
||||
@@ -276,7 +280,7 @@ namespace hw {
|
||||
std::vector<rct::key> &amount_keys,
|
||||
crypto::public_key &out_eph_public_key,
|
||||
const bool use_view_tags, crypto::view_tag &view_tag,
|
||||
const crypto::hash& uniqueness) override;
|
||||
const crypto::ec_scalar& uniqueness) override;
|
||||
|
||||
bool mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) override;
|
||||
bool mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &rvII) override;
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -98,8 +98,13 @@ namespace multisig
|
||||
// - the 'multisig priv keys' here are those held by the local account
|
||||
// - later, we add in the components held by other participants
|
||||
cryptonote::keypair in_ephemeral;
|
||||
crypto::hash uniqueness = crypto::cn_fast_hash(reinterpret_cast<void*>(&real_output_index), sizeof(size_t));
|
||||
if (!cryptonote::generate_key_image_helper(keys, subaddresses, out_key, tx_public_key, additional_tx_public_keys, real_output_index, uniqueness, in_ephemeral, ki, keys.get_device()))
|
||||
//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 Salvium!!!
|
||||
assert(false);
|
||||
cryptonote::origin_data origin_tx_data;
|
||||
|
||||
if (!cryptonote::generate_key_image_helper(keys, subaddresses, out_key, tx_public_key, additional_tx_public_keys, real_output_index, in_ephemeral, ki, keys.get_device(), origin_tx_data))
|
||||
return false;
|
||||
std::unordered_set<crypto::key_image> used;
|
||||
|
||||
|
||||
@@ -108,8 +108,11 @@ static bool compute_keys_for_sources(
|
||||
cryptonote::keypair tmp_keys;
|
||||
if (src.real_output >= src.outputs.size())
|
||||
return false;
|
||||
size_t real_output_wrapper = src.real_output_in_tx_index;
|
||||
crypto::hash uniqueness = crypto::cn_fast_hash(reinterpret_cast<void*>(&real_output_wrapper), sizeof(size_t));
|
||||
|
||||
// Populate this struct if you want to make use of multisig for Salvium!!!
|
||||
assert(false);
|
||||
cryptonote::origin_data origin_tx_data;
|
||||
|
||||
if (not cryptonote::generate_key_image_helper(
|
||||
account_keys,
|
||||
subaddresses,
|
||||
@@ -117,10 +120,10 @@ static bool compute_keys_for_sources(
|
||||
src.real_out_tx_key,
|
||||
src.real_out_additional_tx_keys,
|
||||
src.real_output_in_tx_index,
|
||||
uniqueness,
|
||||
tmp_keys,
|
||||
tmp_key_image,
|
||||
hwdev
|
||||
hwdev,
|
||||
origin_tx_data
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
@@ -427,7 +430,9 @@ static bool compute_keys_for_destinations(
|
||||
|
||||
for (std::size_t i = 0; i < num_destinations; ++i) {
|
||||
|
||||
crypto::hash uniqueness = crypto::cn_fast_hash(reinterpret_cast<void*>(&i), sizeof(size_t));
|
||||
crypto::ec_scalar uniqueness;
|
||||
assert(false);
|
||||
|
||||
if (not hwdev.generate_output_ephemeral_keys(
|
||||
unsigned_tx.version,
|
||||
account_keys,
|
||||
@@ -509,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;
|
||||
}
|
||||
@@ -531,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;
|
||||
}
|
||||
@@ -861,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;
|
||||
}
|
||||
|
||||
+121
-51
@@ -39,18 +39,44 @@ namespace oracle
|
||||
|
||||
namespace
|
||||
{
|
||||
struct asset_data_serialized
|
||||
{
|
||||
std::string asset_type;
|
||||
uint64_t spot_price;
|
||||
uint64_t ma_price;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(asset_type)
|
||||
KV_SERIALIZE(spot_price)
|
||||
KV_SERIALIZE(ma_price)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct supply_data_serialized
|
||||
{
|
||||
uint64_t SAL;
|
||||
uint64_t VSD;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(SAL)
|
||||
KV_SERIALIZE(VSD)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct pr_serialized
|
||||
{
|
||||
uint64_t pr_version;
|
||||
uint64_t spot;
|
||||
uint64_t moving_average;
|
||||
uint64_t height;
|
||||
supply_data supply;
|
||||
std::vector<asset_data> assets;
|
||||
uint64_t timestamp;
|
||||
std::string signature;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(pr_version)
|
||||
KV_SERIALIZE(spot)
|
||||
KV_SERIALIZE(moving_average)
|
||||
KV_SERIALIZE(height)
|
||||
KV_SERIALIZE(supply)
|
||||
KV_SERIALIZE(assets)
|
||||
KV_SERIALIZE(timestamp)
|
||||
KV_SERIALIZE(signature)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
@@ -59,11 +85,57 @@ namespace oracle
|
||||
|
||||
pricing_record::pricing_record() noexcept
|
||||
: pr_version(0)
|
||||
, spot(0)
|
||||
, moving_average(0)
|
||||
, height(0)
|
||||
, supply()
|
||||
, assets()
|
||||
, timestamp(0)
|
||||
, signature()
|
||||
{
|
||||
std::memset(signature, 0, sizeof(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
|
||||
sal = in.SAL;
|
||||
vsd = in.VSD;
|
||||
return true;
|
||||
}
|
||||
// Report error here?
|
||||
return false;
|
||||
}
|
||||
|
||||
bool supply_data::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const
|
||||
{
|
||||
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)
|
||||
{
|
||||
asset_data_serialized in{};
|
||||
if (in._load(src, hparent))
|
||||
{
|
||||
// Copy everything into the local instance
|
||||
asset_type = in.asset_type;
|
||||
spot_price = in.spot_price;
|
||||
ma_price = in.ma_price;
|
||||
return true;
|
||||
}
|
||||
// Report error here?
|
||||
return false;
|
||||
}
|
||||
|
||||
bool asset_data::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const
|
||||
{
|
||||
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)
|
||||
@@ -73,12 +145,18 @@ namespace oracle
|
||||
{
|
||||
// Copy everything into the local instance
|
||||
pr_version = in.pr_version;
|
||||
spot = in.spot;
|
||||
moving_average = in.moving_average;
|
||||
height = in.height;
|
||||
supply = in.supply;
|
||||
assets = in.assets;
|
||||
timestamp = in.timestamp;
|
||||
for (unsigned int i = 0; i < in.signature.length(); i += 2) {
|
||||
|
||||
// Signature arrives in HEX format, but needs to be used in BINARY format - convert it here
|
||||
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;
|
||||
}
|
||||
@@ -90,42 +168,41 @@ 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,spot,moving_average,timestamp,sig_hex};
|
||||
const pr_serialized out{pr_version, height, supply, assets, timestamp, sig_hex};
|
||||
return out.store(dest, hparent);
|
||||
}
|
||||
|
||||
pricing_record::pricing_record(const pricing_record& orig) noexcept
|
||||
: pr_version(orig.pr_version)
|
||||
, spot(orig.spot)
|
||||
, moving_average(orig.moving_average)
|
||||
, height(orig.height)
|
||||
, supply(orig.supply)
|
||||
, assets(orig.assets)
|
||||
, timestamp(orig.timestamp)
|
||||
, signature(orig.signature)
|
||||
{
|
||||
std::memcpy(signature, orig.signature, sizeof(signature));
|
||||
}
|
||||
|
||||
pricing_record& pricing_record::operator=(const pricing_record& orig) noexcept
|
||||
{
|
||||
pr_version = orig.pr_version;
|
||||
spot = orig.spot;
|
||||
moving_average = orig.moving_average;
|
||||
height = orig.height;
|
||||
supply = orig.supply;
|
||||
assets = orig.assets;
|
||||
timestamp = orig.timestamp;
|
||||
::memcpy(signature, orig.signature, sizeof(signature));
|
||||
signature = orig.signature;
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint64_t pricing_record::operator[](const std::string& asset_type) const
|
||||
{
|
||||
if (asset_type == "FULM") return spot;
|
||||
if (asset_type == "FUSD") {
|
||||
boost::multiprecision::uint128_t exchange_128 = COIN;
|
||||
exchange_128 *= COIN;
|
||||
exchange_128 /= spot;
|
||||
return exchange_128.convert_to<uint64_t>();
|
||||
for (const auto& asset: assets) {
|
||||
if (asset.asset_type != asset_type) continue;
|
||||
return asset.spot_price;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -133,10 +210,11 @@ namespace oracle
|
||||
bool pricing_record::equal(const pricing_record& other) const noexcept
|
||||
{
|
||||
return ((pr_version == other.pr_version) &&
|
||||
(spot == other.spot) &&
|
||||
(moving_average == other.moving_average) &&
|
||||
(height == other.height) &&
|
||||
(supply == other.supply) &&
|
||||
(assets == other.assets) &&
|
||||
(timestamp == other.timestamp) &&
|
||||
(!::memcmp(signature, other.signature, sizeof(signature))));
|
||||
(signature == other.signature));
|
||||
}
|
||||
|
||||
bool pricing_record::empty() const noexcept
|
||||
@@ -147,7 +225,7 @@ namespace oracle
|
||||
|
||||
bool pricing_record::verifySignature(const std::string& public_key) const
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(!public_key.empty(), "Pricing record verification failed. NULL public key. PK Size: " << public_key.size()); // TODO: is this necessary or the one below already covers this case, meannin it will produce empty pubkey?
|
||||
CHECK_AND_ASSERT_THROW_MES(!public_key.empty(), "Pricing record verification failed. NULL public key. PK Size: " << public_key.size());
|
||||
|
||||
// extract the key
|
||||
EVP_PKEY* pubkey;
|
||||
@@ -159,19 +237,21 @@ namespace oracle
|
||||
BIO_free(bio);
|
||||
CHECK_AND_ASSERT_THROW_MES(pubkey != NULL, "Pricing record verification failed. NULL public key.");
|
||||
|
||||
// Convert our internal 64-byte binary representation into 128-byte hex string
|
||||
std::string sig_hex;
|
||||
for (unsigned int i=0; i<64; i++) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setw(2) << std::setfill('0') << (0xff & signature[i]);
|
||||
sig_hex += ss.str();
|
||||
}
|
||||
|
||||
// Build the JSON string, so that we can verify the signature
|
||||
std::ostringstream oss;
|
||||
oss << "{\"pr_version\":" << pr_version;
|
||||
oss << ",\"spot\":" << spot;
|
||||
oss << ",\"moving_average\":" << moving_average;
|
||||
oss << ",\"height\":" << height;
|
||||
oss << ",\"supply\":{\"SAL\":" << supply.sal <<",\"VSD\":" << supply.vsd << "}";
|
||||
oss << ",\"assets\":[";
|
||||
bool first = true;
|
||||
for (const auto& asset: assets) {
|
||||
if (first)
|
||||
first=false;
|
||||
else
|
||||
oss << ",";
|
||||
oss << "{\"asset_type\":\"" << asset.asset_type << "\",\"spot_price\":" << asset.spot_price << ",\"ma_price\":" << asset.ma_price << "}";
|
||||
}
|
||||
oss << "]";
|
||||
oss << ",\"timestamp\":" << timestamp;
|
||||
oss << "}";
|
||||
std::string message = oss.str();
|
||||
@@ -184,7 +264,7 @@ namespace oracle
|
||||
if (ret == 1) {
|
||||
ret = EVP_DigestVerifyUpdate(ctx, message.data(), message.length());
|
||||
if (ret == 1) {
|
||||
ret = EVP_DigestVerifyFinal(ctx, (const unsigned char *)signature, 64);
|
||||
ret = EVP_DigestVerifyFinal(ctx, (const unsigned char *)signature.data(), signature.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,11 +283,6 @@ namespace oracle
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pricing_record::has_missing_rates() const noexcept
|
||||
{
|
||||
return (spot == 0) || (moving_average == 0);
|
||||
}
|
||||
|
||||
// overload for pr validation for block
|
||||
bool pricing_record::valid(cryptonote::network_type nettype, uint32_t hf_version, uint64_t bl_timestamp, uint64_t last_bl_timestamp) const
|
||||
{
|
||||
@@ -219,11 +294,6 @@ namespace oracle
|
||||
if (this->empty())
|
||||
return true;
|
||||
|
||||
if (this->has_missing_rates()) {
|
||||
LOG_ERROR("Pricing record has missing rates.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!verifySignature(get_config(nettype).ORACLE_PUBLIC_KEY)) {
|
||||
LOG_ERROR("Invalid pricing record signature.");
|
||||
return false;
|
||||
|
||||
+60
-34
@@ -42,6 +42,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <serialization/containers.h>
|
||||
|
||||
#include "cryptonote_config.h"
|
||||
#include "crypto/hash.h"
|
||||
@@ -64,17 +65,61 @@ namespace oracle
|
||||
uint64_t timestamp;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
class pricing_record
|
||||
|
||||
struct supply_data {
|
||||
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.sal == b.sal &&
|
||||
a.vsd == b.vsd);
|
||||
}
|
||||
|
||||
public:
|
||||
struct asset_data {
|
||||
std::string asset_type;
|
||||
uint64_t spot_price;
|
||||
uint64_t ma_price;
|
||||
|
||||
//! 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()
|
||||
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
|
||||
{
|
||||
return (a.asset_type == b.asset_type &&
|
||||
a.spot_price == b.spot_price &&
|
||||
a.ma_price == b.ma_price);
|
||||
}
|
||||
|
||||
struct pricing_record
|
||||
{
|
||||
// Fields
|
||||
uint64_t pr_version;
|
||||
uint64_t spot;
|
||||
uint64_t moving_average;
|
||||
uint64_t height;
|
||||
supply_data supply;
|
||||
std::vector<asset_data> assets;
|
||||
uint64_t timestamp;
|
||||
unsigned char signature[64];
|
||||
std::vector<uint8_t> signature;
|
||||
|
||||
// Default c'tor
|
||||
pricing_record() noexcept;
|
||||
@@ -83,15 +128,23 @@ 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;
|
||||
bool has_missing_rates() const noexcept;
|
||||
bool valid(cryptonote::network_type nettype, uint32_t hf_version, uint64_t bl_timestamp, uint64_t last_bl_timestamp) const;
|
||||
|
||||
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
|
||||
@@ -104,31 +157,4 @@ namespace oracle
|
||||
return !a.equal(b);
|
||||
}
|
||||
|
||||
class pricing_record_v1
|
||||
{
|
||||
|
||||
public:
|
||||
uint8_t pr_version;
|
||||
uint64_t price;
|
||||
uint64_t timestamp;
|
||||
|
||||
bool write_to_pr(oracle::pricing_record &pr)
|
||||
{
|
||||
pr.pr_version = 0;
|
||||
pr.spot = 0;
|
||||
pr.moving_average = 0;
|
||||
pr.timestamp = 0;
|
||||
std::memset(pr.signature, 0, sizeof(oracle::pricing_record::signature));
|
||||
return true;
|
||||
};
|
||||
|
||||
bool read_from_pr(oracle::pricing_record &pr)
|
||||
{
|
||||
pr_version = 0;
|
||||
price = 0;
|
||||
timestamp = 0;
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
} // oracle
|
||||
|
||||
@@ -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())
|
||||
|
||||
+37
-17
@@ -120,12 +120,19 @@ 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)
|
||||
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;
|
||||
@@ -146,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)
|
||||
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;
|
||||
@@ -1109,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,
|
||||
@@ -1125,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) {
|
||||
@@ -1191,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");
|
||||
@@ -1229,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");
|
||||
@@ -1272,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,8 +1324,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,
|
||||
const keyV &amount_keys,
|
||||
xmr_amount txnFee,
|
||||
unsigned int mixin,
|
||||
@@ -1325,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,6 +1480,9 @@ 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 {
|
||||
|
||||
@@ -847,6 +847,7 @@ namespace cryptonote
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin;
|
||||
req_bin.outputs = req.outputs;
|
||||
req_bin.get_txid = req.get_txid;
|
||||
req_bin.asset_type = req.asset_type;
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin;
|
||||
if(!m_core.get_outs(req_bin, res_bin))
|
||||
{
|
||||
@@ -1909,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.reserved_offset = reserved_offset;
|
||||
store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
|
||||
@@ -2227,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";
|
||||
@@ -2269,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;
|
||||
@@ -2283,6 +2283,7 @@ namespace cryptonote
|
||||
response.pow_hash = fill_pow_hash ? string_tools::pod_to_hex(get_block_longhash(&(m_core.get_blockchain_storage()), blk, height, 0)) : "";
|
||||
response.long_term_weight = m_core.get_blockchain_storage().get_db().get_block_long_term_weight(height);
|
||||
response.miner_tx_hash = string_tools::pod_to_hex(cryptonote::get_transaction_hash(blk.miner_tx));
|
||||
response.protocol_tx_hash = string_tools::pod_to_hex(cryptonote::get_transaction_hash(blk.protocol_tx));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2627,6 +2628,7 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
res.miner_tx_hash = res.block_header.miner_tx_hash;
|
||||
res.protocol_tx_hash = res.block_header.protocol_tx_hash;
|
||||
for (size_t n = 0; n < blk.tx_hashes.size(); ++n)
|
||||
{
|
||||
res.tx_hashes.push_back(epee::string_tools::pod_to_hex(blk.tx_hashes[n]));
|
||||
@@ -2932,6 +2934,36 @@ namespace cryptonote
|
||||
COMMAND_RPC_GET_CIRCULATING_SUPPLY::supply_entry se(i.first, std::to_string(i.second));
|
||||
res.supply_tally.push_back(se);
|
||||
}
|
||||
res.height = m_core.get_current_blockchain_height();
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
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;
|
||||
}
|
||||
@@ -3453,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.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"
|
||||
@@ -1171,6 +1172,7 @@ namespace cryptonote
|
||||
std::string pow_hash;
|
||||
uint64_t long_term_weight;
|
||||
std::string miner_tx_hash;
|
||||
std::string protocol_tx_hash;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(major_version)
|
||||
@@ -1196,6 +1198,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(pow_hash)
|
||||
KV_SERIALIZE_OPT(long_term_weight, (uint64_t)0)
|
||||
KV_SERIALIZE(miner_tx_hash)
|
||||
KV_SERIALIZE(protocol_tx_hash)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
@@ -1220,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
|
||||
@@ -1325,6 +1372,7 @@ namespace cryptonote
|
||||
{
|
||||
block_header_response block_header;
|
||||
std::string miner_tx_hash;
|
||||
std::string protocol_tx_hash;
|
||||
std::vector<std::string> tx_hashes;
|
||||
std::string blob;
|
||||
std::string json;
|
||||
@@ -1333,6 +1381,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE_PARENT(rpc_access_response_base)
|
||||
KV_SERIALIZE(block_header)
|
||||
KV_SERIALIZE(miner_tx_hash)
|
||||
KV_SERIALIZE(protocol_tx_hash)
|
||||
KV_SERIALIZE(tx_hashes)
|
||||
KV_SERIALIZE(blob)
|
||||
KV_SERIALIZE(json)
|
||||
@@ -1367,10 +1416,12 @@ namespace cryptonote
|
||||
struct response_t
|
||||
{
|
||||
std::string status;
|
||||
uint64_t height;
|
||||
std::vector<supply_entry> supply_tally;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
KV_SERIALIZE(height)
|
||||
KV_SERIALIZE(supply_tally)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
@@ -2552,6 +2603,7 @@ namespace cryptonote
|
||||
else
|
||||
KV_SERIALIZE_N(data.distribution, "distribution")
|
||||
KV_SERIALIZE_N(data.base, "base")
|
||||
KV_SERIALIZE_N(data.num_spendable_global_outs, "num_spendable_global_outs")
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
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, destination_address, tx.destination_address);
|
||||
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.destination_address, destination_address);
|
||||
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");
|
||||
@@ -1104,7 +1108,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::rpc::error& error)
|
||||
GET_FROM_JSON_OBJECT(val, error.error_str, error_str);
|
||||
GET_FROM_JSON_OBJECT(val, error.message, message);
|
||||
}
|
||||
|
||||
/*
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const std::pair<std::string, std::pair<uint64_t, uint64_t>>& pr_entry)
|
||||
{
|
||||
dest.StartObject();
|
||||
@@ -1127,14 +1131,59 @@ void fromJsonValue(const rapidjson::Value& val, std::pair<std::string, std::pair
|
||||
GET_FROM_JSON_OBJECT(val, pr_entry.second.first, spot);
|
||||
GET_FROM_JSON_OBJECT(val, pr_entry.second.second, ma);
|
||||
}
|
||||
*/
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::supply_data& supply_data)
|
||||
{
|
||||
dest.StartObject();
|
||||
|
||||
INSERT_INTO_JSON_OBJECT(dest, sal, supply_data.sal);
|
||||
INSERT_INTO_JSON_OBJECT(dest, vsd, supply_data.vsd);
|
||||
|
||||
dest.EndObject();
|
||||
}
|
||||
|
||||
void fromJsonValue(const rapidjson::Value& val, oracle::supply_data& supply_data)
|
||||
{
|
||||
if (!val.IsObject())
|
||||
{
|
||||
throw WRONG_TYPE("json object");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
dest.StartObject();
|
||||
|
||||
INSERT_INTO_JSON_OBJECT(dest, asset_type, asset_data.asset_type);
|
||||
INSERT_INTO_JSON_OBJECT(dest, spot, asset_data.spot_price);
|
||||
INSERT_INTO_JSON_OBJECT(dest, ma, asset_data.ma_price);
|
||||
|
||||
dest.EndObject();
|
||||
}
|
||||
|
||||
void fromJsonValue(const rapidjson::Value& val, oracle::asset_data& asset_data)
|
||||
{
|
||||
if (!val.IsObject())
|
||||
{
|
||||
throw WRONG_TYPE("json object");
|
||||
}
|
||||
|
||||
GET_FROM_JSON_OBJECT(val, asset_data.asset_type, asset_type);
|
||||
GET_FROM_JSON_OBJECT(val, asset_data.spot_price, spot);
|
||||
GET_FROM_JSON_OBJECT(val, asset_data.ma_price, ma);
|
||||
}
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::pricing_record& pricing_record)
|
||||
{
|
||||
dest.StartObject();
|
||||
|
||||
INSERT_INTO_JSON_OBJECT(dest, pr_version, pricing_record.pr_version);
|
||||
INSERT_INTO_JSON_OBJECT(dest, spot, pricing_record.spot);
|
||||
INSERT_INTO_JSON_OBJECT(dest, moving_average, pricing_record.moving_average);
|
||||
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);
|
||||
|
||||
@@ -1143,16 +1192,23 @@ 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.spot, spot);
|
||||
GET_FROM_JSON_OBJECT(val, pricing_record.moving_average, moving_average);
|
||||
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);
|
||||
GET_FROM_JSON_OBJECT(val, boost::lexical_cast<std::string>(pricing_record.signature), signature);
|
||||
std::string sig_hex;
|
||||
std::ostringstream oss;
|
||||
for (size_t i=0; i<pricing_record.signature.size(); ++i) {
|
||||
oss << std::hex << std::setfill('0') << std::setw(2) << std::uppercase << (int)(pricing_record.signature[i]);
|
||||
}
|
||||
GET_FROM_JSON_OBJECT(val, oss.str(), signature);
|
||||
}
|
||||
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::rpc::BlockHeaderResponse& response)
|
||||
|
||||
@@ -197,8 +197,10 @@ 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);
|
||||
void fromJsonValue(const rapidjson::Value& val, oracle::asset_data& asset_data);
|
||||
void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const oracle::pricing_record& pricing_record);
|
||||
void fromJsonValue(const rapidjson::Value& val, oracle::pricing_record& pricing_record);
|
||||
|
||||
|
||||
@@ -37,39 +37,104 @@
|
||||
#include "oracle/pricing_record.h"
|
||||
#include "cryptonote_config.h"
|
||||
|
||||
// read
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false> &ar, oracle::supply_data &sd, uint8_t version)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!ar.good())
|
||||
return false;
|
||||
ar.serialize_varint(sd.sal);
|
||||
ar.serialize_varint(sd.vsd);
|
||||
if (!ar.good())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// read
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false> &ar, oracle::asset_data &ad, uint8_t version)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!ar.good())
|
||||
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;
|
||||
}
|
||||
|
||||
// read
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false> &ar, oracle::pricing_record &pr, uint8_t version)
|
||||
{
|
||||
// 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;
|
||||
/*
|
||||
if (version < HF_VERSION_SLIPPAGE_YIELD)
|
||||
{
|
||||
// very basic sanity check
|
||||
if (ar.remaining_bytes() < sizeof(oracle::pricing_record_v1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
oracle::pricing_record_v1 pr_v1;
|
||||
ar.serialize_blob(&pr_v1, sizeof(oracle::pricing_record_v1), "");
|
||||
// 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;
|
||||
|
||||
if (!pr_v1.write_to_pr(pr))
|
||||
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);
|
||||
}
|
||||
else
|
||||
ar.end_array();
|
||||
*/
|
||||
{
|
||||
// very basic sanity check
|
||||
if (ar.remaining_bytes() < sizeof(oracle::pricing_record)) {
|
||||
if (!do_serialize_container(ar, pr.assets))
|
||||
return false;
|
||||
}
|
||||
|
||||
ar.serialize_blob(&pr, sizeof(oracle::pricing_record), "");
|
||||
ar.serialize_varint(pr.timestamp);
|
||||
if (!ar.good())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!do_serialize_container(ar, pr.signature))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -77,54 +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();
|
||||
/*
|
||||
if (version < HF_VERSION_SLIPPAGE_YIELD)
|
||||
{
|
||||
oracle::pricing_record_v1 pr_v1;
|
||||
if (!pr_v1.read_from_pr(pr))
|
||||
return false;
|
||||
ar.serialize_blob(&pr_v1, sizeof(oracle::pricing_record_v1), "");
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// read
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false> &ar, oracle::pricing_record_v1 &pr, uint8_t version)
|
||||
{
|
||||
// very basic sanity check
|
||||
if (ar.remaining_bytes() < sizeof(oracle::pricing_record_v1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ar.serialize_blob(&pr, sizeof(oracle::pricing_record_v1), "");
|
||||
if (!ar.good())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// write
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<true> &ar, oracle::pricing_record_v1 &pr, uint8_t version)
|
||||
{
|
||||
ar.begin_string();
|
||||
ar.serialize_blob(&pr, sizeof(oracle::pricing_record_v1), "");
|
||||
if (!ar.good())
|
||||
return false;
|
||||
ar.end_string();
|
||||
return true;
|
||||
}
|
||||
|
||||
BLOB_SERIALIZER(oracle::pricing_record);
|
||||
BLOB_SERIALIZER(oracle::pricing_record_v1);
|
||||
//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)
|
||||
|
||||
+338
-133
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);
|
||||
@@ -302,6 +303,7 @@ namespace cryptonote
|
||||
std::string direction;
|
||||
bool confirmed;
|
||||
uint64_t amount;
|
||||
std::string asset_type;
|
||||
crypto::hash hash;
|
||||
std::string payment_id;
|
||||
uint64_t fee;
|
||||
@@ -352,7 +354,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();
|
||||
}
|
||||
}
|
||||
|
||||
+732
-371
File diff suppressed because it is too large
Load Diff
+45
-15
@@ -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) {}
|
||||
@@ -315,11 +315,11 @@ private:
|
||||
uint64_t amount;
|
||||
uint64_t money_transfered;
|
||||
std::string asset_type;
|
||||
crypto::hash uniqueness;
|
||||
crypto::ec_scalar uniqueness;
|
||||
bool error;
|
||||
boost::optional<cryptonote::subaddress_receive_info> received;
|
||||
|
||||
tx_scan_info_t(): amount(0), asset_type(""), money_transfered(0), uniqueness(crypto::null_hash), error(true) {}
|
||||
tx_scan_info_t(): amount(0), asset_type(""), money_transfered(0), uniqueness(), error(true) {}
|
||||
};
|
||||
|
||||
struct transfer_details
|
||||
@@ -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;
|
||||
@@ -602,7 +618,7 @@ private:
|
||||
};
|
||||
|
||||
typedef std::vector<transfer_details> transfer_container;
|
||||
typedef std::map<std::string, std::vector<size_t>> transfer_details_indices;
|
||||
typedef serializable_unordered_map<std::string, std::vector<size_t>> transfer_details_indices;
|
||||
typedef serializable_unordered_multimap<crypto::hash, payment_details> payment_container;
|
||||
|
||||
struct multisig_sig
|
||||
@@ -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,10 +1110,11 @@ 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_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);
|
||||
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 cryptonote::transaction_type tx_type, 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::transaction_type tx_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);
|
||||
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, const cryptonote::transaction_type tx_type, 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);
|
||||
std::vector<wallet2::pending_tx> create_transactions_return(std::vector<size_t> transfers_indices);
|
||||
bool sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, std::vector<cryptonote::tx_destination_entry> dsts) const;
|
||||
void cold_tx_aux_import(const std::vector<pending_tx>& ptx, const std::vector<std::string>& tx_device_aux);
|
||||
void cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux);
|
||||
@@ -1154,7 +1171,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)
|
||||
@@ -1265,6 +1283,8 @@ private:
|
||||
VERSION_FIELD(1)
|
||||
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)
|
||||
@@ -1390,7 +1410,7 @@ private:
|
||||
void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
|
||||
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
|
||||
void check_tx_key_helper(const cryptonote::transaction &tx, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received) const;
|
||||
bool is_out_to_acc(const cryptonote::account_public_address &address, const crypto::public_key& out_key, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const size_t output_index, const boost::optional<crypto::view_tag> &view_tag_opt, crypto::key_derivation &found_derivation) const;
|
||||
bool is_out_to_acc(const cryptonote::account_public_address &address, const crypto::public_key& out_key, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const size_t output_index, const crypto::ec_scalar& uniqueness, const boost::optional<crypto::view_tag> &view_tag_opt, crypto::key_derivation &found_derivation) const;
|
||||
std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message);
|
||||
std::string get_tx_proof(const cryptonote::transaction &tx, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message) const;
|
||||
bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations);
|
||||
@@ -1680,6 +1700,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:
|
||||
/*!
|
||||
@@ -1733,13 +1754,13 @@ private:
|
||||
std::vector<uint64_t> get_unspent_amounts_vector(bool strict);
|
||||
uint64_t get_dynamic_base_fee_estimate();
|
||||
float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const;
|
||||
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices);
|
||||
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type);
|
||||
void set_spent(size_t idx, uint64_t height);
|
||||
void set_unspent(size_t idx);
|
||||
bool is_spent(const transfer_details &td, bool strict = true) const;
|
||||
bool is_spent(size_t idx, bool strict = true) const;
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, bool rct, std::unordered_set<crypto::public_key> &valid_public_keys_cache);
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets, std::unordered_set<crypto::public_key> &valid_public_keys_cache);
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets, std::unordered_set<crypto::public_key> &valid_public_keys_cache, uint64_t &num_spendable_global_outs, uint64_t &num_outs);
|
||||
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked, std::unordered_set<crypto::public_key> &valid_public_keys_cache) const;
|
||||
bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
|
||||
std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
|
||||
@@ -1762,7 +1783,7 @@ private:
|
||||
void register_devices();
|
||||
hw::device& lookup_device(const std::string & device_descriptor);
|
||||
|
||||
bool get_rct_distribution(const std::string &rct_asset_type, uint64_t &start_height, std::vector<uint64_t> &distribution);
|
||||
bool get_rct_distribution(const bool use_global_outs, const std::string &rct_asset_type, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &num_spendable_global_outs);
|
||||
|
||||
uint64_t get_segregation_fork_height() const;
|
||||
|
||||
@@ -1806,6 +1827,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;
|
||||
@@ -1932,6 +1954,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)
|
||||
@@ -2126,6 +2149,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
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;
|
||||
@@ -1615,7 +1617,7 @@ 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_all(req.below_amount, asset_type, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra, req.account_index, subaddr_indices);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(req.below_amount, cryptonote::transaction_type::TRANSFER, asset_type, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra, req.account_index, subaddr_indices);
|
||||
|
||||
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
|
||||
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
|
||||
@@ -1672,7 +1674,7 @@ 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_single(ki, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra);
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_single(ki, cryptonote::transaction_type::TRANSFER, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra);
|
||||
|
||||
if (ptx_vector.empty())
|
||||
{
|
||||
|
||||
@@ -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