prep for alpha binary release

This commit is contained in:
Some Random Crypto Guy
2024-05-27 11:35:34 +01:00
87 changed files with 4006 additions and 2127 deletions
@@ -37,6 +37,7 @@
#include "misc_log_ex.h"
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <typeinfo>
#include <iomanip>
+86 -589
View File
@@ -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
+34 -18
View File
@@ -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
View File
@@ -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; \
+22 -11
View File
@@ -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;
+9 -9
View File
@@ -157,7 +157,7 @@ endif()
set_property(TARGET blockchain_import
PROPERTY
OUTPUT_NAME "fulmo-blockchain-import")
OUTPUT_NAME "salvium-blockchain-import")
install(TARGETS blockchain_import DESTINATION bin)
monero_add_executable(blockchain_export
@@ -178,7 +178,7 @@ target_link_libraries(blockchain_export
set_property(TARGET blockchain_export
PROPERTY
OUTPUT_NAME "fulmo-blockchain-export")
OUTPUT_NAME "salvium-blockchain-export")
install(TARGETS blockchain_export DESTINATION bin)
monero_add_executable(blockchain_blackball
@@ -200,7 +200,7 @@ target_link_libraries(blockchain_blackball
set_property(TARGET blockchain_blackball
PROPERTY
OUTPUT_NAME "fulmo-blockchain-mark-spent-outputs")
OUTPUT_NAME "salvium-blockchain-mark-spent-outputs")
install(TARGETS blockchain_blackball DESTINATION bin)
@@ -222,7 +222,7 @@ target_link_libraries(blockchain_usage
set_property(TARGET blockchain_usage
PROPERTY
OUTPUT_NAME "fulmo-blockchain-usage")
OUTPUT_NAME "salvium-blockchain-usage")
install(TARGETS blockchain_usage DESTINATION bin)
monero_add_executable(blockchain_ancestry
@@ -243,7 +243,7 @@ target_link_libraries(blockchain_ancestry
set_property(TARGET blockchain_ancestry
PROPERTY
OUTPUT_NAME "fulmo-blockchain-ancestry")
OUTPUT_NAME "salvium-blockchain-ancestry")
install(TARGETS blockchain_ancestry DESTINATION bin)
monero_add_executable(blockchain_depth
@@ -264,7 +264,7 @@ target_link_libraries(blockchain_depth
set_property(TARGET blockchain_depth
PROPERTY
OUTPUT_NAME "fulmo-blockchain-depth")
OUTPUT_NAME "salvium-blockchain-depth")
install(TARGETS blockchain_depth DESTINATION bin)
monero_add_executable(blockchain_stats
@@ -285,7 +285,7 @@ target_link_libraries(blockchain_stats
set_property(TARGET blockchain_stats
PROPERTY
OUTPUT_NAME "fulmo-blockchain-stats")
OUTPUT_NAME "salvium-blockchain-stats")
install(TARGETS blockchain_stats DESTINATION bin)
monero_add_executable(blockchain_prune_known_spent_data
@@ -307,7 +307,7 @@ target_link_libraries(blockchain_prune_known_spent_data
set_property(TARGET blockchain_prune_known_spent_data
PROPERTY
OUTPUT_NAME "fulmo-blockchain-prune-known-spent-data")
OUTPUT_NAME "salvium-blockchain-prune-known-spent-data")
install(TARGETS blockchain_prune_known_spent_data DESTINATION bin)
monero_add_executable(blockchain_prune
@@ -316,7 +316,7 @@ monero_add_executable(blockchain_prune
set_property(TARGET blockchain_prune
PROPERTY
OUTPUT_NAME "fulmo-blockchain-prune")
OUTPUT_NAME "salvium-blockchain-prune")
install(TARGETS blockchain_prune DESTINATION bin)
target_link_libraries(blockchain_prune
@@ -386,7 +386,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -1219,7 +1219,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -88,7 +88,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -90,7 +90,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -487,8 +487,9 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
try
{
cryptonote::yield_block_info ybi; // This just gets discarded because we aren't looking to maintain a cache of YBI data in the import utility
uint64_t long_term_block_weight = core.get_blockchain_storage().get_next_long_term_block_weight(block_weight);
core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs);
core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, ybi);
}
catch (const std::exception& e)
{
@@ -637,7 +638,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -483,7 +483,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -137,7 +137,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -175,7 +175,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
@@ -242,7 +242,7 @@ int main(int argc, char* argv[])
/*
* The default output can be plotted with GnuPlot using these commands:
set key autotitle columnhead
set title "Fulmo Blockchain Growth"
set title "Salvium Blockchain Growth"
set timefmt "%Y-%m-%d"
set xdata time
set xrange ["2014-04-17":*]
@@ -120,7 +120,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
Binary file not shown.
+2 -1
View File
@@ -110,7 +110,8 @@ namespace tools
catch(...)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(file_path, file_path + ".unportable");
data_file.close();
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
if(data_file.fail())
+1
View File
@@ -34,6 +34,7 @@
#include <iostream>
#include <vector>
#include <stdexcept>
#include <cstdint>
namespace tools {
+1 -1
View File
@@ -122,7 +122,7 @@ public:
* @brief Gets a DNS address from OpenAlias format
*
* If the address looks good, but contains one @ symbol, replace that with a .
* e.g. donate@fulmo.network becomes donate.fulmo.network
* e.g. donate@salvium.network becomes donate.salvium.network
*
* @param oa_addr OpenAlias address
*
+1 -1
View File
@@ -102,7 +102,7 @@ namespace tools
std::string get_update_url(const std::string &software, const std::string &subdir, const std::string &buildtag, const std::string &version, bool user)
{
const char *base = user ? "https://downloads.fulmo.network/" : "https://updates.fulmo.network/";
const char *base = user ? "https://downloads.salvium.network/" : "https://updates.salvium.network/";
#ifdef _WIN32
static const char *extension = strncmp(buildtag.c_str(), "source", 6) ? (strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe") : ".tar.bz2";
#elif defined(__APPLE__)
+18
View File
@@ -115,6 +115,24 @@ static int flock_exnb(int fd)
namespace tools
{
void copy_file(const std::string& from, const std::string& to)
{
using boost::filesystem::path;
#if BOOST_VERSION < 107400
// Remove this preprocessor if/else when we are bumping the boost version.
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_option::overwrite_if_exists);
#else
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_options::overwrite_existing);
#endif
}
std::function<void(int)> signal_handler::m_handler;
private_file::private_file() noexcept : m_handle(), m_filename() {}
+2
View File
@@ -67,6 +67,8 @@ namespace tools
}
};
void copy_file(const std::string& from, const std::string& to);
//! A file restricted to process owner AND process. Deletes file on destruction.
class private_file {
std::unique_ptr<std::FILE, close_file> m_handle;
+13 -6
View File
@@ -74,6 +74,13 @@ namespace crypto {
const crypto::public_key null_pkey = crypto::public_key{};
const crypto::secret_key null_skey = crypto::secret_key{};
static inline crypto::key_image get_null_ki() {
crypto::key_image ki;
std::memset(ki.data, 0, sizeof(ki.data));
return ki;
}
const crypto::key_image null_ki = get_null_ki();
static inline unsigned char *operator &(ec_point &point) {
return &reinterpret_cast<unsigned char &>(point);
}
@@ -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
View File
@@ -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; }
}
+9 -1
View File
@@ -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;
+48 -9
View File
@@ -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;
}
}
}
+217 -76
View File
@@ -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
View File
@@ -51,13 +51,12 @@
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60
// MONEY_SUPPLY - total number coins to be generated
#define MONEY_SUPPLY ((uint64_t)(1800000000000000ull))
#define EMISSION_SPEED_FACTOR_PER_MINUTE (19)
#define MONEY_SUPPLY ((uint64_t)(18440000000000000ull)) // 184.4M coins * pow(10, 8)
#define EMISSION_SPEED_FACTOR_PER_MINUTE (20)
#define FINAL_SUBSIDY_PER_MINUTE ((uint64_t)30000000) // 3 * pow(10, 7)
#define BURN_LOCK_PERIOD 0
#define CONVERT_LOCK_PERIOD 0
#define YIELD_LOCK_PERIOD 30*24*30
#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100
#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 60000 //size of block (bytes) after which reward for block calculated using block size
@@ -70,7 +69,7 @@
// COIN - number of smallest units in one coin
#define COIN ((uint64_t)100000000) // pow(10, 8)
#define FEE_PER_KB_OLD ((uint64_t)1000000) // pow(10, 6)
//#define FEE_PER_KB_OLD ((uint64_t)1000000) // pow(10, 6)
#define FEE_PER_KB ((uint64_t)200000) // 2 * pow(10, 5)
#define FEE_PER_BYTE ((uint64_t)30)
#define DYNAMIC_FEE_PER_KB_BASE_FEE ((uint64_t)200000) // 2 * pow(10,5)
@@ -80,7 +79,9 @@
#define ORPHANED_BLOCKS_MAX_COUNT 100
#define PREMINE_AMOUNT ((uint64_t)90000000000000ull) // 5% of supply (9 * pow(10,13))
#define PREMINE_AMOUNT ((uint64_t)2210000000000000ull) // 12% of MONEY_SUPPLY
#define PREMINE_AMOUNT_UPFRONT ((uint64_t)650000000000000ull) // 3.4% of MONEY_SUPPLY
#define PREMINE_AMOUNT_MONTHLY ((uint64_t)65000000000000ull) // 8.6%/24 of MONEY_SUPPLY
#define DIFFICULTY_TARGET_V2 120 // seconds
#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork
@@ -163,7 +164,7 @@
#define RPC_IP_FAILS_BEFORE_BLOCK 3
#define CRYPTONOTE_NAME "fulmo"
#define CRYPTONOTE_NAME "salvium"
#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "data.mdb"
#define CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME "lock.mdb"
#define P2P_NET_DATA_FILENAME "p2pstate.bin"
@@ -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)
{
+333 -57
View File
@@ -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 += "&timestamp=" + 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;
+57 -1
View File
@@ -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
*
+21 -5
View File
@@ -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;
+561 -92
View File
@@ -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;
}
+14 -6
View File
@@ -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)
+17 -2
View File
@@ -139,6 +139,13 @@ namespace cryptonote
{
const bool kept_by_block = (tx_relay == relay_method::block);
if(tx.type == cryptonote::transaction_type::CONVERT && version < HF_VERSION_ENABLE_CONVERT)
{
tvc.m_verifivation_failed = true;
tvc.m_invalid_version = true;
return false;
}
// this should already be called with that lock, but let's make it explicit for clarity
CRITICAL_REGION_LOCAL(m_transactions_lock);
@@ -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;
+2 -1
View File
@@ -51,6 +51,7 @@ namespace cryptonote
TRANSFER = 3,
CONVERT = 4,
BURN = 5,
YIELD = 6
YIELD = 6,
RETURN = 7
};
}
+1 -1
View File
@@ -71,5 +71,5 @@ target_link_libraries(daemon
${Blocks})
set_property(TARGET daemon
PROPERTY
OUTPUT_NAME "fulmod")
OUTPUT_NAME "salviumd")
install(TARGETS daemon DESTINATION bin)
+1 -1
View File
@@ -35,7 +35,7 @@
namespace daemon_args
{
std::string const WINDOWS_SERVICE_NAME = "Fulmo Daemon";
std::string const WINDOWS_SERVICE_NAME = "Salvium Daemon";
const command_line::arg_descriptor<std::string, false, true, 2> arg_config_file = {
"config-file"
+1 -1
View File
@@ -412,7 +412,7 @@ bool t_command_server::apropos(const std::vector<std::string>& args)
std::string t_command_server::get_commands_str()
{
std::stringstream ss;
ss << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
ss << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
ss << "Commands: " << std::endl;
std::string usage = m_command_lookup.get_usage();
boost::replace_all(usage, "\n", "\n ");
+2 -2
View File
@@ -40,7 +40,7 @@
namespace daemonize
{
std::string const t_executor::NAME = "Fulmo Daemon";
std::string const t_executor::NAME = "Salvium Daemon";
void t_executor::init_options(
boost::program_options::options_description & configurable_options
@@ -58,7 +58,7 @@ namespace daemonize
boost::program_options::variables_map const & vm
)
{
LOG_PRINT_L0("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised");
LOG_PRINT_L0("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised");
return t_daemon{vm, public_rpc_port};
}
+6 -4
View File
@@ -241,7 +241,7 @@ int main(int argc, char const * argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Usage: " + std::string{argv[0]} + " [options|settings] [daemon_command...]" << std::endl << std::endl;
std::cout << visible_options << std::endl;
return 0;
@@ -250,7 +250,7 @@ int main(int argc, char const * argv[])
// Monero Version
if (command_line::get_arg(vm, command_line::arg_version))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
return 0;
}
@@ -264,7 +264,9 @@ int main(int argc, char const * argv[])
// OS
if (command_line::get_arg(vm, daemon_args::arg_print_genesis_tx))
{
print_genesis_tx_hex(cryptonote::MAINNET);
const bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
print_genesis_tx_hex(testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET);
return 0;
}
@@ -351,7 +353,7 @@ int main(int argc, char const * argv[])
tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency));
// logging is now set up
MGINFO("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")");
MGINFO("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")");
// If there are positional options, we're running a daemon command
{
+2 -1
View File
@@ -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)
+1 -1
View File
@@ -100,7 +100,7 @@ namespace daemonizer
}
else
{
//LOG_PRINT_L0("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
//LOG_PRINT_L0("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
return executor.run_interactive(vm);
}
}
+1 -1
View File
@@ -181,7 +181,7 @@ namespace daemonizer
}
else // interactive
{
//LOG_PRINT_L0("Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
//LOG_PRINT_L0("Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
if (command_line::has_arg(vm, arg_non_interactive))
return executor.run_non_interactive(vm);
else
+3 -3
View File
@@ -46,7 +46,7 @@ target_link_libraries(cn_deserialize
set_property(TARGET cn_deserialize
PROPERTY
OUTPUT_NAME "monero-utils-deserialize")
OUTPUT_NAME "salvium-utils-deserialize")
set(object_sizes_sources
@@ -67,7 +67,7 @@ target_link_libraries(object_sizes
set_property(TARGET object_sizes
PROPERTY
OUTPUT_NAME "monero-utils-object-sizes")
OUTPUT_NAME "salvium-utils-object-sizes")
set(dns_checks_sources
@@ -89,5 +89,5 @@ target_link_libraries(dns_checks
set_property(TARGET dns_checks
PROPERTY
OUTPUT_NAME "monero-utils-dns-checks")
OUTPUT_NAME "salvium-utils-dns-checks")
+1 -1
View File
@@ -103,7 +103,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
+1 -1
View File
@@ -121,7 +121,7 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
+9 -5
View File
@@ -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;
+24 -6
View File
@@ -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;
}
+9 -5
View File
@@ -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
View File
@@ -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));
+9 -5
View File
@@ -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;
+1 -1
View File
@@ -50,5 +50,5 @@ add_dependencies(gen_multisig
version)
set_property(TARGET gen_multisig
PROPERTY
OUTPUT_NAME "fulmo-gen-trusted-multisig")
OUTPUT_NAME "salvium-gen-trusted-multisig")
install(TARGETS gen_multisig DESTINATION bin)
+1 -1
View File
@@ -45,5 +45,5 @@ add_dependencies(gen_ssl_cert
version)
set_property(TARGET gen_ssl_cert
PROPERTY
OUTPUT_NAME "fulmo-gen-ssl-cert")
OUTPUT_NAME "salvium-gen-ssl-cert")
install(TARGETS gen_ssl_cert DESTINATION bin)
+2 -2
View File
@@ -121,13 +121,13 @@ int main(int argc, char* argv[])
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 0;
}
if (command_line::get_arg(vm, command_line::arg_version))
{
std::cout << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
return 0;
}
+5 -5
View File
@@ -36,26 +36,26 @@ const hardfork_t mainnet_hard_forks[] = {
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 1000, which is on or around the 20th of March, 2016. Fork time finalised on 2015-09-20. No fork voting occurs for the v2 fork.
{ 2, 1000, 0, 1442763710 },
//{ 2, 1000, 0, 1442763710 },
};
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
const uint64_t mainnet_hard_fork_version_1_till = 1000;
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
const hardfork_t testnet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 1000, which is on or around the 23rd of November, 2015. Fork time finalised on 2015-11-20. No fork voting occurs for the v2 fork.
{ 1, 1000, 0, 1445355000 },
//{ 2, 1000, 0, 1445355000 },
};
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = 1000;
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
const hardfork_t stagenet_hard_forks[] = {
// version 1 from the start of the blockchain
{ 1, 1, 0, 1341378000 },
// versions 2-7 in rapid succession from March 13th, 2018
{ 2, 1000, 0, 1521000000 },
//{ 2, 1000, 0, 1521000000 },
};
const size_t num_stagenet_hard_forks = sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]);
+7 -2
View File
@@ -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;
+12 -8
View File
@@ -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
View File
@@ -31,7 +31,7 @@
namespace oracle {
const std::vector<std::string> ASSET_TYPES = {"FULM", "FUSD", "BURN"};
const std::vector<std::string> ASSET_TYPES = {"SAL", "VSD", "BURN"};
class asset_type_counts
{
@@ -39,23 +39,23 @@ namespace oracle {
public:
// Fields
uint64_t FULM;
uint64_t FUSD;
uint64_t SAL;
uint64_t VSD;
uint64_t BURN;
asset_type_counts() noexcept
: FULM(0)
, FUSD(0)
: SAL(0)
, VSD(0)
, BURN(0)
{
}
uint64_t operator[](const std::string asset_type) const noexcept
{
if (asset_type == "FULM") {
return FULM;
} else if (asset_type == "FUSD") {
return FUSD;
if (asset_type == "SAL") {
return SAL;
} else if (asset_type == "VSD") {
return VSD;
} else if (asset_type == "BURN") {
return BURN;
}
@@ -65,10 +65,10 @@ namespace oracle {
void add(const std::string asset_type, const uint64_t val)
{
if (asset_type == "FULM") {
FULM += val;
} else if (asset_type == "FUSD") {
FUSD += val;
if (asset_type == "SAL") {
SAL += val;
} else if (asset_type == "VSD") {
VSD += val;
} else if (asset_type == "BURN") {
BURN += val;
}
+121 -51
View File
@@ -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
View File
@@ -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
+2 -1
View File
@@ -42,6 +42,7 @@
#include <boost/serialization/version.hpp>
#include "net_peerlist_boost_serialization.h"
#include "common/util.h"
namespace nodetool
@@ -200,7 +201,7 @@ namespace nodetool
if (!out)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(path, path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(path, path + ".unportable");
src_file.close();
src_file.open( path , std::ios_base::binary | std::ios_base::in);
if(src_file.fail())
+37 -17
View File
@@ -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);
+2
View File
@@ -135,6 +135,7 @@ namespace rct {
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const std::vector<bool> &zero_masks,
const std::vector<xmr_amount> & inamounts,
const std::vector<xmr_amount> & outamounts,
const keyV &amount_keys,
@@ -150,6 +151,7 @@ namespace rct {
const cryptonote::transaction_type tx_type,
const std::string& in_asset_type,
const std::vector<std::string> & destination_asset_types,
const std::vector<bool> &zero_masks,
const std::vector<xmr_amount> & inamounts,
const std::vector<xmr_amount> & outamounts,
xmr_amount txnFee,
+3
View File
@@ -324,6 +324,7 @@ namespace rct {
std::vector<ecdhTuple> ecdhInfo;
ctkeyV outPk;
xmr_amount txnFee; // contains b
key p_r;
template<bool W, template <bool> class Archive>
bool serialize_rctsig_base(Archive<W> &ar, size_t inputs, size_t outputs)
@@ -390,6 +391,7 @@ namespace rct {
ar.delimit_array();
}
ar.end_array();
FIELD(p_r)
return ar.good();
}
@@ -401,6 +403,7 @@ namespace rct {
FIELD(ecdhInfo)
FIELD(outPk)
VARINT_FIELD(txnFee)
FIELD(p_r)
END_SERIALIZE()
};
struct rctSigPrunable {
+37 -7
View File
@@ -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;
+2
View File
@@ -175,6 +175,7 @@ namespace cryptonote
MAP_JON_RPC_WE("get_version", on_get_version, COMMAND_RPC_GET_VERSION)
MAP_JON_RPC_WE_IF("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM, !m_restricted)
MAP_JON_RPC_WE("get_circulating_supply", on_get_circulating_supply, COMMAND_RPC_GET_CIRCULATING_SUPPLY)
MAP_JON_RPC_WE("get_yield_info", on_get_yield_info, COMMAND_RPC_GET_YIELD_INFO)
MAP_JON_RPC_WE("get_fee_estimate", on_get_base_fee_estimate, COMMAND_RPC_GET_BASE_FEE_ESTIMATE)
MAP_JON_RPC_WE_IF("get_alternate_chains",on_get_alternate_chains, COMMAND_RPC_GET_ALTERNATE_CHAINS, !m_restricted)
MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted)
@@ -253,6 +254,7 @@ namespace cryptonote
bool on_get_version(const COMMAND_RPC_GET_VERSION::request& req, COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_circulating_supply(const COMMAND_RPC_GET_CIRCULATING_SUPPLY::request& req, COMMAND_RPC_GET_CIRCULATING_SUPPLY::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_yield_info(const COMMAND_RPC_GET_YIELD_INFO::request& req, COMMAND_RPC_GET_YIELD_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_base_fee_estimate(const COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request& req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
+52
View File
@@ -33,6 +33,7 @@
#include "string_tools.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "blockchain_db/blockchain_db.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/difficulty.h"
#include "crypto/hash.h"
@@ -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()
};
+2 -8
View File
@@ -234,16 +234,10 @@ namespace cryptonote
block = is_current ? info.block : info.previous_block;
*(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(nonce);
if (block.major_version >= RX_BLOCK_VERSION)
{
const crypto::hash &seed_hash = is_current ? info.seed_hash : info.previous_seed_hash;
crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data);
}
else
{
const int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0;
crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash, cn_variant, cryptonote::get_block_height(block));
}
if (!check_hash(hash, m_diff))
{
MWARNING("Payment too low");
+66 -10
View File
@@ -270,16 +270,18 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::t
dest.StartObject();
INSERT_INTO_JSON_OBJECT(dest, version, tx.version);
INSERT_INTO_JSON_OBJECT(dest, unlock_time, tx.unlock_time);
INSERT_INTO_JSON_OBJECT(dest, inputs, tx.vin);
INSERT_INTO_JSON_OBJECT(dest, outputs, tx.vout);
INSERT_INTO_JSON_OBJECT(dest, extra, tx.extra);
INSERT_INTO_JSON_OBJECT(dest, type, static_cast<uint8_t>(tx.type));
INSERT_INTO_JSON_OBJECT(dest, 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)
+4 -2
View File
@@ -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);
+105 -66
View File
@@ -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);
+1 -1
View File
@@ -61,5 +61,5 @@ target_link_libraries(simplewallet
${EXTRA_LIBRARIES})
set_property(TARGET simplewallet
PROPERTY
OUTPUT_NAME "fulmo-wallet-cli")
OUTPUT_NAME "salvium-wallet-cli")
install(TARGETS simplewallet DESTINATION bin)
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -52,8 +52,8 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.simplewallet"
// Hardcode Fulmo's donation address
constexpr const char FULMO_DONATION_ADDR[] = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
// Hardcode Salvium's donation address
constexpr const char SALVIUM_DONATION_ADDR[] = "888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H";
/*!
* \namespace cryptonote
@@ -180,6 +180,7 @@ namespace cryptonote
bool sweep_below(const std::vector<std::string> &args);
bool sweep_single(const std::vector<std::string> &args);
bool sweep_unmixable(const std::vector<std::string> &args);
bool return_payment(const std::vector<std::string> &args);
bool burn(const std::vector<std::string> &args);
bool convert(const std::vector<std::string> &args);
bool lock_for_yield(const std::vector<std::string> &args);
@@ -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
View File
@@ -1,13 +1,15 @@
#define DEF_FULMO_VERSION_TAG "7f6b8da"
#define DEF_FULMO_VERSION "0.0.1"
#define DEF_SALVIUM_VERSION_TAG "7f6b8da"
#define DEF_SALVIUM_VERSION "0.0.8"
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "0.18.2.2"
#define DEF_MONERO_RELEASE_NAME "Zero"
#define DEF_MONERO_VERSION_FULL DEF_FULMO_VERSION "-" DEF_FULMO_VERSION_TAG ", based on Monero " DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_FULL DEF_SALVIUM_VERSION "-" DEF_SALVIUM_VERSION_TAG ", based on Monero " DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
#include "version.h"
const char* const SALVIUM_VERSION_TAG = DEF_SALVIUM_VERSION_TAG;
const char* const SALVIUM_VERSION = DEF_SALVIUM_VERSION;
const char* const MONERO_VERSION_TAG = DEF_MONERO_VERSION_TAG;
const char* const MONERO_VERSION = DEF_MONERO_VERSION;
const char* const MONERO_RELEASE_NAME = DEF_MONERO_RELEASE_NAME;
+2
View File
@@ -1,5 +1,7 @@
#pragma once
extern const char* const SALVIUM_VERSION_TAG;
extern const char* const SALVIUM_VERSION;
extern const char* const MONERO_VERSION_TAG;
extern const char* const MONERO_VERSION;
extern const char* const MONERO_RELEASE_NAME;
+1 -1
View File
@@ -100,7 +100,7 @@ if(NOT IOS)
${EXTRA_LIBRARIES})
set_property(TARGET wallet_rpc_server
PROPERTY
OUTPUT_NAME "fulmo-wallet-rpc")
OUTPUT_NAME "salvium-wallet-rpc")
install(TARGETS wallet_rpc_server DESTINATION bin)
endif()
+5 -5
View File
@@ -154,20 +154,20 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
}
}
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time)
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time, const uint64_t& tx_origin_idx)
{
std::string tx_hash = epee::string_tools::pod_to_hex(txid);
LOG_PRINT_L3(__FUNCTION__ << ": money received. height: " << height
<< ", tx: " << tx_hash
<< ", amount: " << print_money(amount - burnt)
<< ", burnt: " << print_money(burnt)
<< ", raw_output_value: " << print_money(amount)
<< ", amount: " << print_money(amount)
<< ", burnt: " << print_money(tx.amount_burnt)
<< ", raw_output_value: " << print_money(amount - tx.amount_burnt)
<< ", idx: " << subaddr_index);
// do not signal on received tx if wallet is not syncronized completely
if (m_listener && m_wallet->synchronized()) {
m_listener->moneyReceived(tx_hash, amount - burnt);
m_listener->moneyReceived(tx_hash, amount - tx.amount_burnt);
m_listener->updated();
}
}
+732 -371
View File
File diff suppressed because it is too large Load Diff
+45 -15
View File
@@ -140,7 +140,7 @@ private:
// Full wallet callbacks
virtual void on_new_block(uint64_t height, const cryptonote::block& block) {}
virtual void on_reorg(uint64_t height, uint64_t blocks_detached, size_t transfers_detached) {}
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const std::string& asset_type, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) {}
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const std::string& asset_type, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time, const uint64_t& origin_td_idx) {}
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index) {}
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const std::string& asset_type, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index) {}
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) {}
@@ -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)
{
+3 -3
View File
@@ -148,7 +148,7 @@ namespace wallet_args
if (command_line::get_arg(vm, command_line::arg_help))
{
Print(print) << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
Print(print) << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
Print(print) << wallet_args::tr("This is the command line monero wallet. It needs to connect to a monero\n"
"daemon to work correctly.") << ENDL;
Print(print) << wallet_args::tr("Usage:") << ENDL << " " << usage;
@@ -158,7 +158,7 @@ namespace wallet_args
}
else if (command_line::get_arg(vm, command_line::arg_version))
{
Print(print) << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
Print(print) << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
should_terminate = true;
return true;
}
@@ -209,7 +209,7 @@ namespace wallet_args
if (!command_line::is_arg_defaulted(vm, arg_max_concurrency))
tools::set_max_concurrency(command_line::get_arg(vm, arg_max_concurrency));
Print(print) << "Fulmo '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
Print(print) << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
if (!command_line::is_arg_defaulted(vm, arg_log_level))
MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level));
-8
View File
@@ -153,15 +153,7 @@ bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads
tpool.submit(&waiter, [&, i] {
*(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(local_nonce-i);
const uint8_t major_version = hashing_blob[0];
if (major_version >= RX_BLOCK_VERSION)
{
crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data);
}
else
{
int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0;
crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash[i], cn_variant, height);
}
});
}
waiter.wait();
+10 -8
View File
@@ -451,7 +451,7 @@ namespace tools
if (!m_wallet) return not_open(er);
std::vector<std::string> assets_in_wallet = m_wallet->list_asset_types();
std::string asset_type = req.asset_type.empty() ? "FULM" : boost::algorithm::to_upper_copy(req.asset_type);
std::string asset_type = req.asset_type.empty() ? "SAL" : boost::algorithm::to_upper_copy(req.asset_type);
// verify that the asset is in the list of in-wallet assets
if (std::find(assets_in_wallet.begin(), assets_in_wallet.end(), asset_type) == assets_in_wallet.end()) {
er.message = std::string("Invalid source asset specified: ") + asset_type;
@@ -667,8 +667,8 @@ namespace tools
info.base_address = m_wallet->get_subaddress_as_str(subaddr_index);
//for (const auto& asset: asset_types) {
info.balance = m_wallet->balance(subaddr_index.major, "FULM", req.strict_balances);
info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major, "FULM", req.strict_balances);
info.balance = m_wallet->balance(subaddr_index.major, "SAL", req.strict_balances);
info.unlocked_balance = m_wallet->unlocked_balance(subaddr_index.major, "SAL", req.strict_balances);
//}
info.label = m_wallet->get_subaddress_label(subaddr_index);
info.tag = account_tags.second[subaddr_index.major];
@@ -1102,7 +1102,8 @@ namespace tools
{
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
uint32_t priority = m_wallet->adjust_priority(req.priority);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
const crypto::key_image ki_return = crypto::null_ki;
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, ki_return);
if (ptx_vector.empty())
{
@@ -1156,8 +1157,9 @@ namespace tools
{
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
uint32_t priority = m_wallet->adjust_priority(req.priority);
const crypto::key_image ki_return = crypto::null_ki;
LOG_PRINT_L2("on_transfer_split calling create_transactions_2");
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, static_cast<cryptonote::transaction_type>(req.tx_type), mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, ki_return);
LOG_PRINT_L2("on_transfer_split called create_transactions_2");
if (ptx_vector.empty())
@@ -1587,7 +1589,7 @@ namespace tools
destination.push_back(wallet_rpc::transfer_destination());
destination.back().amount = 0;
destination.back().address = req.address;
std::string asset_type = req.asset_type.empty() ? "FULM" : req.asset_type;
std::string asset_type = req.asset_type.empty() ? "SAL" : req.asset_type;
if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
{
return false;
@@ -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())
{
+3 -1
View File
@@ -35,6 +35,7 @@
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/filesystem/operations.hpp>
#include "common/util.h"
namespace tools
{
@@ -110,7 +111,8 @@ namespace tools
catch(...)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(file_path, file_path + ".unportable");
data_file.close();
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
if(data_file.fail())