forked from lthn/blockchain
merge from zarcanum
This commit is contained in:
commit
432e1c2d2b
15 changed files with 399 additions and 265 deletions
|
|
@ -714,26 +714,30 @@ bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const trans
|
|||
purge_transaction_visitor(blockchain_storage& bcs, key_images_container& spent_keys, bool strict_check):
|
||||
m_bcs(bcs),
|
||||
m_spent_keys(spent_keys),
|
||||
m_strict_check(strict_check){}
|
||||
|
||||
bool operator()(const txin_to_key& inp) const
|
||||
m_strict_check(strict_check)
|
||||
{}
|
||||
bool process_input(const crypto::key_image& k_image, const std::vector<txout_ref_v>& key_offsets, uint64_t amount) const
|
||||
{
|
||||
bool r = m_spent_keys.erase_validate(inp.k_image);
|
||||
CHECK_AND_ASSERT_MES( !(!r && m_strict_check), false, "purge_transaction_keyimages_from_blockchain: key image " << inp.k_image << " was not found");
|
||||
bool r = m_spent_keys.erase_validate(k_image);
|
||||
CHECK_AND_ASSERT_MES(r || !m_strict_check, false, "purge_transaction_keyimages_from_blockchain: key image " << k_image << " was not found");
|
||||
|
||||
if(inp.key_offsets.size() == 1)
|
||||
if(key_offsets.size() == 1)
|
||||
{
|
||||
//direct spend detected
|
||||
if(!m_bcs.update_spent_tx_flags_for_input(inp.amount, inp.key_offsets[0], false))
|
||||
if(!m_bcs.update_spent_tx_flags_for_input(amount, key_offsets[0], false))
|
||||
{
|
||||
//internal error
|
||||
LOG_PRINT_L0("Failed to update_spent_tx_flags_for_input");
|
||||
LOG_ERROR("update_spent_tx_flags_for_input failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool operator()(const txin_to_key& inp) const
|
||||
{
|
||||
return process_input(inp.k_image, inp.key_offsets, inp.amount);
|
||||
}
|
||||
bool operator()(const txin_gen& inp) const
|
||||
{
|
||||
return true;
|
||||
|
|
@ -742,19 +746,18 @@ bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const trans
|
|||
{
|
||||
if (!m_bcs.update_spent_tx_flags_for_input(inp.multisig_out_id, 0))
|
||||
{
|
||||
LOG_PRINT_L0("update_spent_tx_flags_for_input failed for multisig id " << inp.multisig_out_id << " amount: " << inp.amount);
|
||||
LOG_ERROR("update_spent_tx_flags_for_input failed for multisig id " << inp.multisig_out_id << " amount: " << inp.amount);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator()(const txin_htlc& inp) const
|
||||
{
|
||||
return this->operator()(static_cast<const txin_to_key&>(inp));
|
||||
return process_input(inp.k_image, inp.key_offsets, inp.amount);
|
||||
}
|
||||
bool operator()(const txin_zc_input& inp) const
|
||||
{
|
||||
// TODO: #@#@
|
||||
return false;
|
||||
return process_input(inp.k_image, inp.key_offsets, 0 /* amount */);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1646,15 +1649,9 @@ bool blockchain_storage::purge_altblock_keyimages_from_big_heap(const block& b,
|
|||
transaction& tx = *tx_ptr;
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
if (tx.vin[n].type() == typeid(txin_to_key) || tx.vin[n].type() == typeid(txin_htlc))
|
||||
{
|
||||
purge_keyimage_from_big_heap(get_to_key_input_from_txin_v(tx.vin[n]).k_image, block_id);
|
||||
}
|
||||
else if (tx.vin[n].type() == typeid(txin_zc_input))
|
||||
{
|
||||
const txin_zc_input& zcin = boost::get<txin_zc_input>(tx.vin[n]);
|
||||
purge_keyimage_from_big_heap(zcin.k_image, block_id);
|
||||
}
|
||||
crypto::key_image ki = AUTO_VAL_INIT(ki);
|
||||
if (get_key_image_from_txin_v(tx.vin[n], ki))
|
||||
purge_keyimage_from_big_heap(ki, block_id);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -4842,7 +4839,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
uint64_t source_max_unlock_time_for_pos_coinbase_dummy = AUTO_VAL_INIT(source_max_unlock_time_for_pos_coinbase_dummy);
|
||||
if (!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase_dummy, scan_contex))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")");
|
||||
LOG_PRINT_L0("Failed to get output keys for htlc input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -5400,7 +5397,7 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 2, false, "incorrect: miner_tx.vin.size() = " << b.miner_tx.vin.size());
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "incorrect input 0 type: " << b.miner_tx.vin[0].type().name());
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin[1].type() == typeid(txin_to_key) || b.miner_tx.vin[1].type() == typeid(txin_zc_input), false, "incorrect input 1 type: " << b.miner_tx.vin[1].type().name());
|
||||
const crypto::key_image& stake_key_image = get_key_image_txin_v(b.miner_tx.vin[1]);
|
||||
const crypto::key_image& stake_key_image = get_key_image_from_txin_v(b.miner_tx.vin[1]);
|
||||
//check keyimage if it's main chain candidate
|
||||
if (!for_altchain)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
|
||||
#define WALLET_MAX_ALLOWED_OUTPUT_AMOUNT ((uint64_t)0xffffffffffffffffLL)
|
||||
#define CURRENCY_MINER_TX_MAX_OUTS CURRENCY_TX_MAX_ALLOWED_OUTS
|
||||
#define CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP 3
|
||||
|
||||
#define DIFFICULTY_STARTER 1
|
||||
#define DIFFICULTY_POS_TARGET 120 // seconds
|
||||
|
|
|
|||
|
|
@ -207,16 +207,7 @@ namespace currency
|
|||
if (tx_version > TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
// randomly split into CURRENCY_TX_MIN_ALLOWED_OUTS outputs
|
||||
// TODO: consider refactoring
|
||||
uint64_t amount_remaining = block_reward;
|
||||
for(size_t i = 1; i < CURRENCY_TX_MIN_ALLOWED_OUTS; ++i) // starting from 1 for one less iteration
|
||||
{
|
||||
uint64_t amount = crypto::rand<uint64_t>() % amount_remaining;
|
||||
amount_remaining -= amount;
|
||||
out_amounts.push_back(amount);
|
||||
}
|
||||
out_amounts.push_back(amount_remaining);
|
||||
// std::shuffle(out_amounts.begin(), out_amounts.end(), crypto::uniform_random_bit_generator());
|
||||
decompose_amount_randomly(block_reward, [&](uint64_t a){ out_amounts.push_back(a); }, CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1618,7 +1609,7 @@ namespace currency
|
|||
CHECK_AND_ASSERT_MES(tx.vin[input_index].type() == typeid(txin_zc_input), false, "Unexpected type of input #" << input_index);
|
||||
|
||||
txin_zc_input& in = boost::get<txin_zc_input>(tx.vin[input_index]);
|
||||
tx.signatures.emplace_back();
|
||||
tx.signatures.emplace_back(ZC_sig());
|
||||
ZC_sig& sig = boost::get<ZC_sig>(tx.signatures.back());
|
||||
|
||||
if (watch_only_mode)
|
||||
|
|
@ -1839,6 +1830,7 @@ namespace currency
|
|||
size_t current_index = 0;
|
||||
inputs_mapping.resize(sources.size());
|
||||
size_t input_starter_index = tx.vin.size();
|
||||
bool has_zc_inputs = false;
|
||||
//fill inputs NLSAG and Zarcanum
|
||||
for (const tx_source_entry& src_entr : sources)
|
||||
{
|
||||
|
|
@ -1928,6 +1920,7 @@ namespace currency
|
|||
//potentially this approach might help to support htlc and multisig without making to complicated code
|
||||
if (src_entr.is_zarcanum())
|
||||
{
|
||||
has_zc_inputs = true;
|
||||
txin_zc_input zc_in = AUTO_VAL_INIT(zc_in);
|
||||
zc_in.k_image = img;
|
||||
zc_in.key_offsets = std::move(key_offsets);
|
||||
|
|
@ -2055,8 +2048,11 @@ namespace currency
|
|||
r = add_tx_fee_amount_to_extra(tx, summary_inputs_money - summary_outs_money);
|
||||
CHECK_AND_ASSERT_MES(r, false, "add_tx_fee_amount_to_extra failed");
|
||||
|
||||
r = generate_tx_balance_proof(tx, blinding_masks_sum);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed");
|
||||
if (!has_zc_inputs)
|
||||
{
|
||||
r = generate_tx_balance_proof(tx, blinding_masks_sum);
|
||||
CHECK_AND_ASSERT_MES(r, false, "generate_tx_balance_proof failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & TX_FLAG_SIGNATURE_MODE_SEPARATE)
|
||||
|
|
@ -2319,9 +2315,12 @@ namespace currency
|
|||
{
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key) || in.type() == typeid(txin_multisig) || in.type() == typeid(txin_htlc), false, "wrong variant type: "
|
||||
<< in.type().name()
|
||||
<< ", in transaction id=" << get_transaction_hash(tx));
|
||||
CHECK_AND_ASSERT_MES(
|
||||
in.type() == typeid(txin_to_key) ||
|
||||
in.type() == typeid(txin_multisig) ||
|
||||
in.type() == typeid(txin_htlc) ||
|
||||
in.type() == typeid(txin_zc_input),
|
||||
false, "wrong input type: " << in.type().name() << ", in transaction " << get_transaction_hash(tx));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2386,7 +2385,6 @@ namespace currency
|
|||
{
|
||||
for(const auto& vo : tx.vout)
|
||||
{
|
||||
|
||||
VARIANT_SWITCH_BEGIN(vo);
|
||||
VARIANT_CASE_CONST(tx_out_bare, out)
|
||||
{
|
||||
|
|
@ -2404,16 +2402,21 @@ namespace currency
|
|||
VARIANT_CASE_CONST(txout_multisig, ms)
|
||||
if (!(ms.keys.size() > 0 && ms.minimum_sigs > 0 && ms.minimum_sigs <= ms.keys.size()))
|
||||
{
|
||||
LOG_ERROR("wrong multisig in transaction id=" << get_transaction_hash(tx));
|
||||
LOG_ERROR("wrong multisig output in transaction " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
VARIANT_CASE_OTHER()
|
||||
LOG_ERROR("wrong variant type: " << out.target.type().name() << ", expected " << typeid(txout_to_key).name()
|
||||
<< ", in transaction id=" << get_transaction_hash(tx));
|
||||
LOG_ERROR("wrong output type: " << out.target.type().name() << " in transaction " << get_transaction_hash(tx));
|
||||
return false;
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@
|
||||
if (!check_key(o.amount_commitment))
|
||||
return false;
|
||||
if (!check_key(o.concealing_point))
|
||||
return false;
|
||||
if (!check_key(o.stealth_address))
|
||||
return false;
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
return true;
|
||||
|
|
@ -2427,7 +2430,7 @@ namespace currency
|
|||
bool check_inputs_overflow(const transaction& tx)
|
||||
{
|
||||
uint64_t money = 0;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
uint64_t this_amount = 0;
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
|
|
@ -2445,9 +2448,13 @@ namespace currency
|
|||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_htlc, htlc_in, false);
|
||||
this_amount = htlc_in.amount;
|
||||
}
|
||||
else if (in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
// ignore inputs with hidden amounts
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Unknow type in in: " << in.type().name());
|
||||
LOG_ERROR("wrong input type: " << in.type().name());
|
||||
return false;
|
||||
}
|
||||
if (money > this_amount + money)
|
||||
|
|
@ -2460,15 +2467,15 @@ namespace currency
|
|||
bool check_outs_overflow(const transaction& tx)
|
||||
{
|
||||
uint64_t money = 0;
|
||||
BOOST_FOREACH(const auto& o, tx.vout)
|
||||
for(const auto& o : tx.vout)
|
||||
{
|
||||
VARIANT_SWITCH_BEGIN(o);
|
||||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
if (money > o.amount + money)
|
||||
return false;
|
||||
money += o.amount;
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@
|
||||
// VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
// ignore inputs with hidden amounts
|
||||
VARIANT_SWITCH_END();
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -710,12 +710,56 @@ namespace currency
|
|||
{
|
||||
decompose_amount_into_digits(amount, dust_threshold, chunk_handler, dust_handler, max_output_allowed, CURRENCY_TX_MAX_ALLOWED_OUTS, 0);
|
||||
}
|
||||
|
||||
// num_digits_to_keep -- how many digits to keep in chunks, 0 means all digits
|
||||
// Ex.: num_digits_to_keep == 3, number_of_outputs == 2 then 1.0 may be decomposed into 0.183 + 0.817
|
||||
// num_digits_to_keep == 0, number_of_outputs == 2 then 1.0 may be decomposed into 0.183374827362 + 0.816625172638
|
||||
template<typename chunk_handler_t>
|
||||
void decompose_amount_randomly(uint64_t amount, chunk_handler_t chunk_cb, size_t number_of_outputs = CURRENCY_TX_MIN_ALLOWED_OUTS, size_t num_digits_to_keep = CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP)
|
||||
{
|
||||
if (amount < number_of_outputs)
|
||||
return;
|
||||
|
||||
uint64_t boundary = 1000;
|
||||
if (num_digits_to_keep != CURRENCY_TX_OUTS_RND_SPLIT_DIGITS_TO_KEEP)
|
||||
{
|
||||
boundary = 1;
|
||||
for(size_t i = 0; i < num_digits_to_keep; ++i)
|
||||
boundary *= 10;
|
||||
}
|
||||
|
||||
auto trim_digits_and_add_variance = [boundary, num_digits_to_keep](uint64_t& v){
|
||||
if (num_digits_to_keep != 0 && v > 1)
|
||||
{
|
||||
uint64_t multiplier = 1;
|
||||
while(v >= boundary)
|
||||
{
|
||||
v /= 10;
|
||||
multiplier *= 10;
|
||||
}
|
||||
v = v / 2 + crypto::rand<uint64_t>() % (v + 1);
|
||||
v *= multiplier;
|
||||
}
|
||||
};
|
||||
|
||||
uint64_t amount_remaining = amount;
|
||||
for(size_t i = 1; i < number_of_outputs && amount_remaining > 1; ++i) // starting from 1 for one less iteration
|
||||
{
|
||||
uint64_t chunk_amount = amount_remaining / (number_of_outputs - i + 1);
|
||||
trim_digits_and_add_variance(chunk_amount);
|
||||
amount_remaining -= chunk_amount;
|
||||
chunk_cb(chunk_amount);
|
||||
}
|
||||
chunk_cb(amount_remaining);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
/*
|
||||
inline size_t get_input_expected_signatures_count(const txin_v& tx_in)
|
||||
{
|
||||
struct txin_signature_size_visitor : public boost::static_visitor<size_t>
|
||||
{
|
||||
size_t operator()(const txin_gen& /*txin*/) const { return 0; }
|
||||
size_t operator()(const txin_gen& txin) const { return 0; }
|
||||
size_t operator()(const txin_to_key& txin) const { return txin.key_offsets.size(); }
|
||||
size_t operator()(const txin_multisig& txin) const { return txin.sigs_count; }
|
||||
size_t operator()(const txin_htlc& txin) const { return 1; }
|
||||
|
|
@ -723,6 +767,22 @@ namespace currency
|
|||
};
|
||||
|
||||
return boost::apply_visitor(txin_signature_size_visitor(), tx_in);
|
||||
}*/
|
||||
//---------------------------------------------------------------
|
||||
inline size_t get_input_expected_signature_size(const txin_v& tx_in, bool last_input_in_separately_signed_tx)
|
||||
{
|
||||
struct txin_signature_size_visitor : public boost::static_visitor<size_t>
|
||||
{
|
||||
txin_signature_size_visitor(size_t add) : a(add) {}
|
||||
size_t a;
|
||||
size_t operator()(const txin_gen& /*txin*/) const { return 0; }
|
||||
size_t operator()(const txin_to_key& txin) const { return tools::get_varint_packed_size(txin.key_offsets.size() + a) + sizeof(crypto::signature) * (txin.key_offsets.size() + a); }
|
||||
size_t operator()(const txin_multisig& txin) const { return tools::get_varint_packed_size(txin.sigs_count + a) + sizeof(crypto::signature) * (txin.sigs_count + a); }
|
||||
size_t operator()(const txin_htlc& txin) const { return tools::get_varint_packed_size(1 + a) + sizeof(crypto::signature) * (1 + a); }
|
||||
size_t operator()(const txin_zc_input& txin) const { return 97 + tools::get_varint_packed_size(txin.key_offsets.size()) + txin.key_offsets.size() * 32; }
|
||||
};
|
||||
|
||||
return boost::apply_visitor(txin_signature_size_visitor(last_input_in_separately_signed_tx ? 1 : 0), tx_in);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class txin_t>
|
||||
|
|
|
|||
|
|
@ -192,26 +192,51 @@ namespace currency
|
|||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
const crypto::key_image & get_key_image_txin_v(const txin_v& in_v)
|
||||
const bool get_key_image_from_txin_v(const txin_v& in_v, crypto::key_image& result) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
if (in_v.type() == typeid(txin_to_key))
|
||||
{
|
||||
result = boost::get<txin_to_key>(in_v).k_image;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in_v.type() == typeid(txin_htlc))
|
||||
{
|
||||
result = boost::get<txin_htlc>(in_v).k_image;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (in_v.type() == typeid(txin_zc_input))
|
||||
{
|
||||
result = boost::get<txin_zc_input>(in_v).k_image;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
// should never go here, just precaution
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
inline
|
||||
const crypto::key_image& get_key_image_from_txin_v(const txin_v& in_v)
|
||||
{
|
||||
if (in_v.type() == typeid(txin_to_key))
|
||||
{
|
||||
return boost::get<txin_to_key>(in_v).k_image;
|
||||
}
|
||||
else if (in_v.type() == typeid(txin_htlc))
|
||||
{
|
||||
|
||||
if (in_v.type() == typeid(txin_htlc))
|
||||
return boost::get<txin_htlc>(in_v).k_image;
|
||||
}
|
||||
else if (in_v.type() == typeid(txin_zc_input))
|
||||
{
|
||||
return boost::get<txin_zc_input>(in_v).k_image;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MES_AND_THROW("[get_to_key_input_from_txin_v] Wrong type " << in_v.type().name());
|
||||
}
|
||||
}
|
||||
|
||||
if (in_v.type() == typeid(txin_zc_input))
|
||||
return boost::get<txin_zc_input>(in_v).k_image;
|
||||
|
||||
ASSERT_MES_AND_THROW("[get_key_image_from_txin_v] Wrong type: " << in_v.type().name());
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
//, txin_htlc, txin_zc_input
|
||||
inline bool compare_variant_by_types(const txin_multisig& left, const txin_multisig& right)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -232,12 +232,8 @@ namespace currency
|
|||
|
||||
for (size_t i = 0; i != t.vin.size(); i++)
|
||||
{
|
||||
size_t sig_count = get_input_expected_signatures_count(t.vin[i]);
|
||||
if (separately_signed_tx && i == t.vin.size() - 1)
|
||||
++sig_count; // count in one more signature for the last input in a complete separately signed tx
|
||||
tx_blob_size += tools::get_varint_packed_size(sig_count); // size of transaction::signatures[i]
|
||||
tx_blob_size += sizeof(crypto::signature) * sig_count; // size of signatures' data itself
|
||||
//tx_blob_size += sizeof(binary_archive<true>::variant_tag_type); //tools::get_varint_packed_size(variant_serialization_traits<binary_archive<true>, currency::NLSAG_sig>::get_tag()); // sizeof variant tag
|
||||
size_t sig_size = get_input_expected_signature_size(t.vin[i], separately_signed_tx && i == t.vin.size() - 1);
|
||||
tx_blob_size += sig_size;
|
||||
}
|
||||
|
||||
// 2. attachments (try to find extra_attachment_info in tx prefix and count it in if succeed)
|
||||
|
|
@ -273,12 +269,12 @@ namespace currency
|
|||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key) || in.type() == typeid(txin_htlc) || in.type() == typeid(txin_zc_input))
|
||||
{
|
||||
|
||||
if (!ki.insert(get_key_image_txin_v(in)).second)
|
||||
if (!ki.insert(get_key_image_from_txin_v(in)).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,13 @@ namespace currency
|
|||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core)
|
||||
{
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
// defaults
|
||||
tvc.m_added_to_pool = false;
|
||||
tvc.m_verification_failed = true;
|
||||
|
||||
if (!kept_by_block && !from_core && m_blockchain.is_in_checkpoint_zone())
|
||||
{
|
||||
// BCS is in CP zone, tx verification is impossible until it gets synchronized
|
||||
|
|
@ -104,21 +110,13 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!m_blockchain.validate_tx_for_hardfork_specific_terms(tx, id))
|
||||
{
|
||||
//
|
||||
LOG_ERROR("Transaction " << id <<" doesn't fit current hardfork");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = m_blockchain.validate_tx_for_hardfork_specific_terms(tx, id);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Transaction " << id <<" doesn't fit current hardfork");
|
||||
|
||||
TIME_MEASURE_START_PD(tx_processing_time);
|
||||
TIME_MEASURE_START_PD(check_inputs_types_supported_time);
|
||||
if(!check_inputs_types_supported(tx))
|
||||
{
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = check_inputs_types_supported(tx);
|
||||
CHECK_AND_ASSERT_MES(r, false, "tx " << id << " has wrong inputs types");
|
||||
TIME_MEASURE_FINISH_PD(check_inputs_types_supported_time);
|
||||
|
||||
TIME_MEASURE_START_PD(expiration_validate_time);
|
||||
|
|
@ -134,33 +132,26 @@ namespace currency
|
|||
}
|
||||
TIME_MEASURE_FINISH_PD(expiration_validate_time);
|
||||
|
||||
|
||||
TIME_MEASURE_START_PD(validate_amount_time);
|
||||
uint64_t inputs_amount = 0;
|
||||
if(!get_inputs_money_amount(tx, inputs_amount))
|
||||
{
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(tx.vout.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, "transaction has too many outs = " << tx.vout.size());
|
||||
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(tx.vout.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS, false, tvc.m_verification_failed = true, "transaction has too many outs = " << tx.vout.size());
|
||||
uint64_t tx_fee = 0;
|
||||
r = get_tx_fee(tx, tx_fee);
|
||||
CHECK_AND_ASSERT_MES(r, false, "get_tx_fee failed");
|
||||
|
||||
uint64_t outputs_amount = get_outs_money_amount(tx);
|
||||
|
||||
if(outputs_amount > inputs_amount)
|
||||
{
|
||||
LOG_PRINT_L0("transaction use more money then it has: use " << outputs_amount << ", have " << inputs_amount);
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
// @#@# consider removing the following
|
||||
//if (!check_tx_balance(tx)) // TODO (performance): check_tx_balance calls get_tx_fee as well, consider refactoring -- sowle
|
||||
//{
|
||||
// LOG_PRINT_L0("balance check failed for tx " << id);
|
||||
// tvc.m_verification_failed = true;
|
||||
// return false;
|
||||
//}
|
||||
TIME_MEASURE_FINISH_PD(validate_amount_time);
|
||||
|
||||
TIME_MEASURE_START_PD(validate_alias_time);
|
||||
if (!from_core && !validate_alias_info(tx, kept_by_block))
|
||||
{
|
||||
LOG_PRINT_RED_L0("validate_alias_info failed");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = from_core || validate_alias_info(tx, kept_by_block);
|
||||
CHECK_AND_ASSERT_MES(r, false, "validate_alias_info failed");
|
||||
TIME_MEASURE_FINISH_PD(validate_alias_time);
|
||||
|
||||
TIME_MEASURE_START_PD(check_keyimages_ws_ms_time);
|
||||
|
|
@ -168,15 +159,10 @@ namespace currency
|
|||
if(!from_core && !kept_by_block)
|
||||
{
|
||||
crypto::key_image spent_ki = AUTO_VAL_INIT(spent_ki);
|
||||
if(have_tx_keyimges_as_spent(tx, &spent_ki))
|
||||
{
|
||||
LOG_ERROR("Transaction " << id << " uses already spent key image " << spent_ki);
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
r = !have_tx_keyimges_as_spent(tx, &spent_ki);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Transaction " << id << " uses already spent key image " << spent_ki);
|
||||
|
||||
//transaction spam protection, soft rule
|
||||
uint64_t tx_fee = inputs_amount - outputs_amount;
|
||||
if (tx_fee < m_blockchain.get_core_runtime_config().tx_pool_min_fee)
|
||||
{
|
||||
if (is_valid_contract_finalization_tx(tx))
|
||||
|
|
@ -188,7 +174,7 @@ namespace currency
|
|||
else
|
||||
{
|
||||
// this tx has no fee
|
||||
LOG_PRINT_RED_L0("Transaction with id= " << id << " has too small fee: " << tx_fee << ", expected fee: " << m_blockchain.get_core_runtime_config().tx_pool_min_fee);
|
||||
LOG_PRINT_RED_L0("Transaction " << id << " has too small fee: " << print_money_brief(tx_fee) << ", minimum fee: " << print_money_brief(m_blockchain.get_core_runtime_config().tx_pool_min_fee));
|
||||
tvc.m_verification_failed = false;
|
||||
tvc.m_should_be_relayed = false;
|
||||
tvc.m_added_to_pool = false;
|
||||
|
|
@ -211,13 +197,13 @@ namespace currency
|
|||
bool ch_inp_res = m_blockchain.check_tx_inputs(tx, id, max_used_block_height, max_used_block_id);
|
||||
if (!ch_inp_res && !kept_by_block && !from_core)
|
||||
{
|
||||
LOG_PRINT_L0("tx used wrong inputs, rejected");
|
||||
LOG_PRINT_L0("check_tx_inputs failed, tx rejected");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(check_inputs_time);
|
||||
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, inputs_amount - outputs_amount, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0);
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0);
|
||||
|
||||
TIME_MEASURE_FINISH_PD(tx_processing_time);
|
||||
tvc.m_added_to_pool = true;
|
||||
|
|
@ -479,10 +465,10 @@ namespace currency
|
|||
should_be_spent_before_height -= CONFLICT_KEY_IMAGE_SPENT_DEPTH_TO_REMOVE_TX_FROM_POOL;
|
||||
for (auto& in : tx_entry.tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image ki = AUTO_VAL_INIT(ki);
|
||||
if (get_key_image_from_txin_v(in, ki))
|
||||
{
|
||||
// if at least one key image is spent deep enought -- remove such tx
|
||||
const crypto::key_image& ki = boost::get<txin_to_key>(in).k_image;
|
||||
if (m_blockchain.have_tx_keyimg_as_spent(ki, should_be_spent_before_height))
|
||||
{
|
||||
LOG_PRINT_L0("tx " << h << " is about to be removed from tx pool, reason: ki was spent in the blockchain before height " << should_be_spent_before_height << ", tx age: " << misc_utils::get_time_interval_string(tx_age));
|
||||
|
|
@ -709,16 +695,15 @@ namespace currency
|
|||
{
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, true);//should never fail
|
||||
if (have_tx_keyimg_as_spent(tokey_in.k_image))
|
||||
if (have_tx_keyimg_as_spent(k_image))
|
||||
{
|
||||
if (p_spent_ki)
|
||||
*p_spent_ki = tokey_in.k_image;
|
||||
*p_spent_ki = k_image;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -729,13 +714,13 @@ namespace currency
|
|||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
const txin_to_key& tokey_in = boost::get<txin_to_key>(in);
|
||||
auto& id_set = m_key_images[tokey_in.k_image];
|
||||
auto& id_set = m_key_images[k_image];
|
||||
size_t sz_before = id_set.size();
|
||||
id_set.insert(tx_id);
|
||||
LOG_PRINT_L2("tx pool: key image added: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << sz_before << " -> " << id_set.size());
|
||||
LOG_PRINT_L2("tx pool: key image added: " << k_image << ", from tx " << tx_id << ", counter: " << sz_before << " -> " << id_set.size());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -789,11 +774,10 @@ namespace currency
|
|||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
const txin_to_key& tokey_in = boost::get<txin_to_key>(in);
|
||||
|
||||
auto it_map = epee::misc_utils::it_get_or_insert_value_initialized(m_key_images, tokey_in.k_image);
|
||||
auto it_map = epee::misc_utils::it_get_or_insert_value_initialized(m_key_images, k_image);
|
||||
auto& id_set = it_map->second;
|
||||
size_t count_before = id_set.size();
|
||||
auto it_set = id_set.find(tx_id);
|
||||
|
|
@ -804,22 +788,22 @@ namespace currency
|
|||
if (id_set.size() == 0)
|
||||
m_key_images.erase(it_map);
|
||||
|
||||
LOG_PRINT_L2("tx pool: key image removed: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << count_before << " -> " << count_after);
|
||||
LOG_PRINT_L2("tx pool: key image removed: " << k_image << ", from tx " << tx_id << ", counter: " << count_before << " -> " << count_after);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::get_key_images_from_tx_pool(key_image_cache& key_images) const
|
||||
{
|
||||
|
||||
{
|
||||
m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry)
|
||||
{
|
||||
for (auto& in : tx_entry.tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(in, k_image))
|
||||
{
|
||||
key_images[boost::get<txin_to_key>(in).k_image].insert(h);
|
||||
key_images[k_image].insert(h);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -923,10 +907,10 @@ namespace currency
|
|||
LOCAL_READONLY_TRANSACTION();
|
||||
for(size_t i = 0; i!= tx.vin.size(); i++)
|
||||
{
|
||||
if (tx.vin[i].type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(tx.vin[i], k_image))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false);
|
||||
if (k_images.count(itk.k_image))
|
||||
if (k_images.count(k_image))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -935,13 +919,13 @@ namespace currency
|
|||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::append_key_images(std::unordered_set<crypto::key_image>& k_images, const transaction& tx)
|
||||
{
|
||||
for(size_t i = 0; i!= tx.vin.size(); i++)
|
||||
for(size_t i = 0; i != tx.vin.size(); i++)
|
||||
{
|
||||
if (tx.vin[i].type() == typeid(txin_to_key))
|
||||
crypto::key_image k_image = AUTO_VAL_INIT(k_image);
|
||||
if (get_key_image_from_txin_v(tx.vin[i], k_image))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false);
|
||||
auto i_res = k_images.insert(itk.k_image);
|
||||
CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << itk.k_image);
|
||||
auto i_res = k_images.insert(k_image);
|
||||
CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << k_image);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -1334,10 +1318,6 @@ namespace currency
|
|||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
if (o.target.type() == typeid(txout_multisig))
|
||||
result.push_back(ms_out_info({ get_multisig_out_id(tx, idx), idx, false }));
|
||||
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@
|
||||
VARIANT_CASE_THROW_ON_OTHER();
|
||||
VARIANT_SWITCH_END();
|
||||
++idx;
|
||||
}
|
||||
|
|
@ -1358,8 +1338,6 @@ namespace currency
|
|||
VARIANT_CASE_CONST(tx_out_bare, o)
|
||||
if (o.target.type() == typeid(txout_multisig) && get_multisig_out_id(tx, idx) == multisig_id)
|
||||
return true;
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o)
|
||||
//@#@
|
||||
VARIANT_SWITCH_END();
|
||||
++idx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace currency
|
|||
bool check_tx_inputs_keyimages_diff(const transaction& tx)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4889,16 +4889,24 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency
|
|||
API_RETURN_CODE_INTERNAL_ERROR);
|
||||
}
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
auto interted_it = src.outputs.insert(it_to_insert, real_oe);
|
||||
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx);
|
||||
src.real_output = interted_it - src.outputs.begin();
|
||||
src.real_output_in_tx_index = td.m_internal_output_index;
|
||||
print_source_entry(src);
|
||||
}
|
||||
VARIANT_CASE_CONST(tx_out_zarcanum, o);
|
||||
//@#@
|
||||
real_oe.amount_commitment = o.amount_commitment;
|
||||
real_oe.concealing_point = o.concealing_point;
|
||||
real_oe.stealth_address = o.stealth_address;
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(td.m_opt_blinding_mask, "m_opt_blinding_mask is null, transfer index: " << J << ", amount: " << print_money_brief(td.amount()));
|
||||
src.real_out_amount_blinding_mask = *td.m_opt_blinding_mask;
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
auto interted_it = src.outputs.insert(it_to_insert, real_oe);
|
||||
src.real_out_tx_key = get_tx_pub_key_from_extra(td.m_ptx_wallet_info->m_tx);
|
||||
src.real_output = interted_it - src.outputs.begin();
|
||||
src.real_output_in_tx_index = td.m_internal_output_index;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "source entry [" << i << "], td_idx: " << J << ", ";
|
||||
print_source_entry(ss, src);
|
||||
WLT_LOG_L1(ss.str());
|
||||
|
||||
++i;
|
||||
}
|
||||
|
|
@ -4990,7 +4998,7 @@ assets_selection_context wallet2::get_needed_money(uint64_t fee, const std::vect
|
|||
{
|
||||
assets_selection_context amounts_map;
|
||||
amounts_map[currency::null_hash].needed_amount = fee;
|
||||
BOOST_FOREACH(auto& dt, dsts)
|
||||
for(auto& dt : dsts)
|
||||
{
|
||||
if(dt.asset_id == currency::ffff_hash)
|
||||
continue; //this destination for emmition only
|
||||
|
|
@ -5592,11 +5600,16 @@ uint64_t wallet2::get_tx_expiration_median() const
|
|||
return res.expiration_median;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::print_source_entry(const currency::tx_source_entry& src) const
|
||||
void wallet2::print_source_entry(std::stringstream& output, const currency::tx_source_entry& src) const
|
||||
{
|
||||
std::ostringstream indexes;
|
||||
std::for_each(src.outputs.begin(), src.outputs.end(), [&](const currency::tx_source_entry::output_entry& s_e) { indexes << s_e.out_reference << " "; });
|
||||
WLT_LOG_L0("amount=" << currency::print_money(src.amount) << ", real_output=" << src.real_output << ", real_output_in_tx_index=" << src.real_output_in_tx_index << ", indexes: " << indexes.str());
|
||||
std::stringstream ss;
|
||||
for(auto& el : src.outputs)
|
||||
ss << el.out_reference << " ";
|
||||
|
||||
output << "amount: " << print_money_brief(src.amount) << (src.is_zarcanum() ? " (hidden)" : "")
|
||||
<< ", real_output: " << src.real_output
|
||||
<< ", real_output_in_tx_index: " << src.real_output_in_tx_index
|
||||
<< ", indexes: " << ss.str();
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const
|
||||
|
|
@ -5617,11 +5630,22 @@ void wallet2::prepare_tx_destinations(const assets_selection_context& needed_mon
|
|||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
const tx_dust_policy& dust_policy,
|
||||
const std::vector<currency::tx_destination_entry>& dsts,
|
||||
std::vector<currency::tx_destination_entry>& final_detinations)
|
||||
std::vector<currency::tx_destination_entry>& final_destinations)
|
||||
{
|
||||
for (auto& el: needed_money_map)
|
||||
{
|
||||
prepare_tx_destinations(el.second.needed_amount, el.second.found_amount, destination_split_strategy_id, dust_policy, dsts, final_detinations, el.first);
|
||||
prepare_tx_destinations(el.second.needed_amount, el.second.found_amount, destination_split_strategy_id, dust_policy, dsts, final_destinations, el.first);
|
||||
}
|
||||
|
||||
if (is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM) && final_destinations.size() < CURRENCY_TX_MIN_ALLOWED_OUTS)
|
||||
{
|
||||
// if there's not ehough destinations items (i.e. outputs), split the last one
|
||||
tx_destination_entry de = final_destinations.back();
|
||||
final_destinations.pop_back();
|
||||
size_t items_to_be_added = CURRENCY_TX_MIN_ALLOWED_OUTS - final_destinations.size();
|
||||
decompose_amount_randomly(de.amount, [&](uint64_t amount){ de.amount = amount; final_destinations.push_back(de); }, items_to_be_added);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(final_destinations.size() == CURRENCY_TX_MIN_ALLOWED_OUTS,
|
||||
"can't get necessary number of outputs using decompose_amount_randomly(), got " << final_destinations.size() << " while mininum is " << CURRENCY_TX_MIN_ALLOWED_OUTS);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -988,7 +988,7 @@ private:
|
|||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
const tx_dust_policy& dust_policy,
|
||||
const std::vector<currency::tx_destination_entry>& dsts,
|
||||
std::vector<currency::tx_destination_entry>& final_detinations);
|
||||
std::vector<currency::tx_destination_entry>& final_destinations);
|
||||
void prepare_tx_destinations(uint64_t needed_money,
|
||||
uint64_t found_money,
|
||||
detail::split_strategy_id_t destination_split_strategy_id,
|
||||
|
|
@ -1033,7 +1033,8 @@ private:
|
|||
|
||||
|
||||
void fill_transfer_details(const currency::transaction& tx, const tools::money_transfer2_details& td, tools::wallet_public::wallet_transfer_info_details& res_td) const;
|
||||
void print_source_entry(const currency::tx_source_entry& src) const;
|
||||
void print_source_entry(std::stringstream& output, const currency::tx_source_entry& src) const;
|
||||
|
||||
|
||||
void init_log_prefix();
|
||||
void load_keys2ki(bool create_if_not_exist, bool& need_to_resync);
|
||||
|
|
|
|||
|
|
@ -422,22 +422,6 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
|||
|
||||
build_stake_modifier(rsp.sm, m_blockchain);
|
||||
|
||||
//rsp.pos_basic_difficulty = m_core.get_blockchain_storage().get_next_diff_conditional(true).convert_to<std::string>();
|
||||
//rsp.starter_timestamp = m_core.get_blockchain_storage().get_last_timestamps_check_window_median();
|
||||
//uint64_t i_last_pos_block = get_last_block_of_type(true, m_blockchain);
|
||||
//uint64_t last_pos_block_timestamp = 0;
|
||||
//if(i_last_pos_block)
|
||||
// last_pos_block_timestamp = m_blockchain[i_last_pos_block]->b.timestamp;
|
||||
//else
|
||||
// last_pos_block_timestamp = m_blockchain.back()->b.timestamp - DIFFICULTY_POS_TARGET/2;
|
||||
//uint64_t starter_timestamp = last_pos_block_timestamp + DIFFICULTY_POS_TARGET;
|
||||
//uint64_t median_timestamp = get_timestamps_median(m_blockchain);
|
||||
//if (starter_timestamp < median_timestamp)
|
||||
// starter_timestamp = median_timestamp;
|
||||
//if (basic_diff < 10)
|
||||
// starter_timestamp -= 90;
|
||||
//starter_timestamp = POS_SCAN_STEP - (starter_timestamp%POS_SCAN_STEP) + starter_timestamp;
|
||||
|
||||
uint64_t median_timestamp = get_timestamps_median(m_blockchain);
|
||||
rsp.starter_timestamp = median_timestamp; // the core uses median timestamp as starter timestamp, here we mimic this behaviour -- sowle
|
||||
|
||||
|
|
@ -552,28 +536,7 @@ bool test_generator::find_kernel(const std::list<currency::account_base>& accs,
|
|||
crypto::hash& found_kh)
|
||||
{
|
||||
bool r = false;
|
||||
// TODO: consiger removing this function completely in order to unify pos mining code -- sowle
|
||||
|
||||
/*
|
||||
uint64_t i_last_pos_block = get_last_block_of_type(true, blck_chain);
|
||||
uint64_t last_pos_block_timestamp = 0;
|
||||
if(i_last_pos_block)
|
||||
last_pos_block_timestamp = blck_chain[i_last_pos_block]->b.timestamp;
|
||||
else
|
||||
last_pos_block_timestamp = blck_chain.back()->b.timestamp - DIFFICULTY_POS_TARGET/2;
|
||||
uint64_t starter_timestamp = last_pos_block_timestamp + DIFFICULTY_POS_TARGET;
|
||||
uint64_t median_timestamp = get_timestamps_median(blck_chain);
|
||||
if (starter_timestamp < median_timestamp)
|
||||
starter_timestamp = median_timestamp;
|
||||
wide_difficulty_type basic_diff = get_difficulty_for_next_block(blck_chain, false);
|
||||
if (basic_diff < 10)
|
||||
starter_timestamp -= 90;
|
||||
starter_timestamp = POS_SCAN_STEP - (starter_timestamp%POS_SCAN_STEP) + starter_timestamp;
|
||||
*/
|
||||
|
||||
//for (uint64_t ts = starter_timestamp; ts < starter_timestamp + POS_SCAN_WINDOW/2; ts += POS_SCAN_STEP)
|
||||
|
||||
uint64_t last_block_ts = !blck_chain.empty() ? blck_chain.back()->b.timestamp : test_core_time::get_time();
|
||||
uint64_t last_block_ts = !blck_chain.empty() ? blck_chain.back()->b.timestamp : test_core_time::get_time();
|
||||
|
||||
//lets try to find block
|
||||
for (size_t wallet_index = 0, size = wallets.size(); wallet_index < size; ++wallet_index)
|
||||
|
|
@ -618,61 +581,8 @@ bool test_generator::find_kernel(const std::list<currency::account_base>& accs,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
uint64_t h = 0;
|
||||
uint64_t out_i = 0;
|
||||
const transaction * pts = nullptr;
|
||||
crypto::public_key source_tx_pub_key = null_pkey;
|
||||
crypto::public_key out_key = null_pkey;
|
||||
r = get_output_details_by_global_index(blck_chain,
|
||||
indexes,
|
||||
pos_entries[i].amount,
|
||||
pos_entries[i].g_index,
|
||||
h,
|
||||
pts,
|
||||
out_i,
|
||||
source_tx_pub_key,
|
||||
out_key);
|
||||
CHECK_AND_ASSERT_THROW_MES(r,"Failed to get_output_details_by_global_index()");
|
||||
sk.block_timestamp = ts;
|
||||
sk.kimage = pos_entries[i].keyimage;
|
||||
//build_stake_modifier(sk.stake_modifier, blck_chain);
|
||||
sk.stake_modifier = stake_modifier_type();
|
||||
uint64_t last_pos_i = get_last_block_of_type(true, blck_chain);
|
||||
uint64_t last_pow_i = get_last_block_of_type(false, blck_chain);
|
||||
if (last_pos_i)
|
||||
{
|
||||
sk.stake_modifier.last_pos_kernel_id = blck_chain[last_pos_i]->ks_hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = string_tools::parse_tpod_from_hex_string(POS_STARTER_KERNEL_HASH, sk.stake_modifier.last_pos_kernel_id);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse POS_STARTER_KERNEL_HASH");
|
||||
}
|
||||
sk.stake_modifier.last_pow_id = get_block_hash(blck_chain[last_pow_i]->b);
|
||||
|
||||
|
||||
crypto::hash kernel_hash = crypto::cn_fast_hash(&sk, sizeof(sk));
|
||||
wide_difficulty_type this_coin_diff = basic_diff / pos_entries[i].amount;
|
||||
if (check_hash(kernel_hash, this_coin_diff))
|
||||
{
|
||||
//found kernel
|
||||
LOG_PRINT_GREEN("Found kernel: amount=" << print_money(pos_entries[i].amount)
|
||||
<< ", index=" << pos_entries[i].g_index
|
||||
<< ", key_image" << pos_entries[i].keyimage
|
||||
<< ", diff: " << this_coin_diff, LOG_LEVEL_0);
|
||||
pe = pos_entries[i];
|
||||
found_wallet_index = i;
|
||||
found_kh = kernel_hash;
|
||||
found_timestamp = ts;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t
|
|||
crc.pos_minimum_heigh = 1;
|
||||
c.get_blockchain_storage().set_core_runtime_config(crc);
|
||||
|
||||
m_checkpoints.add_checkpoint(12, "2a6e13df811eccce121c0de4dbdcc640de1d37c8459c2c8ea02af39717779836");
|
||||
m_checkpoints.add_checkpoint(12, "8cce274f3ade893fa407a5215b90c595d2ecb036e76ad934b3410da4e8bc7c2c");
|
||||
c.set_checkpoints(currency::checkpoints(m_checkpoints));
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1631,7 +1631,7 @@ multisig_and_checkpoints::multisig_and_checkpoints()
|
|||
bool multisig_and_checkpoints::set_cp(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
checkpoints.add_checkpoint(15, "e2a1b0d51c4de81a79caafb28ba3c2f2ef3f53f7a728932b4d7e2a81a3fc2cc0");
|
||||
checkpoints.add_checkpoint(15, "10521273decd310d17be7216c4bd1c0bb55d9adf70e068943d216878276dbe5a");
|
||||
c.set_checkpoints(std::move(checkpoints));
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
/*
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "currency_core/currency_format_utils.h"
|
||||
|
||||
using namespace currency;
|
||||
|
|
@ -123,4 +123,81 @@ TEST_neg(0_0_);
|
|||
TEST_neg(_0_0);
|
||||
TEST_neg(0_0_0);
|
||||
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t get_nonzero_digits_count(uint64_t x)
|
||||
{
|
||||
size_t result = 0;
|
||||
while(x != 0)
|
||||
{
|
||||
if (x % 10 != 0)
|
||||
++result;
|
||||
x /= 10;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void foo(uint64_t amount, size_t outputs_count, size_t num_digits_to_keep)
|
||||
{
|
||||
std::vector<uint64_t> vec;
|
||||
decompose_amount_randomly(amount, [&](uint64_t a){ vec.push_back(a); }, outputs_count, num_digits_to_keep);
|
||||
//std::cout << amount << " -> (" << vec.size() << ") ";
|
||||
ASSERT_EQ(vec.size(), outputs_count);
|
||||
for(size_t i = 0; i + 1 < outputs_count; ++i)
|
||||
{
|
||||
//std::cout << vec[i] << ",";
|
||||
ASSERT_LE(get_nonzero_digits_count(vec[i]), num_digits_to_keep);
|
||||
}
|
||||
//std::cout << vec.back() << ENDL;
|
||||
ASSERT_LE(get_nonzero_digits_count(vec.back()), num_digits_to_keep);
|
||||
}
|
||||
|
||||
TEST(decompose_amount_randomly, 1)
|
||||
{
|
||||
std::vector<uint64_t> vec;
|
||||
for(size_t i = 0; i < 1000; ++i)
|
||||
{
|
||||
vec.clear();
|
||||
decompose_amount_randomly(0, [&](uint64_t a){ vec.push_back(a); }, 2, 3);
|
||||
ASSERT_EQ(vec.size(), 0);
|
||||
|
||||
vec.clear();
|
||||
decompose_amount_randomly(1, [&](uint64_t a){ vec.push_back(a); }, 2, 3);
|
||||
ASSERT_EQ(vec.size(), 0);
|
||||
|
||||
vec.clear();
|
||||
decompose_amount_randomly(2, [&](uint64_t a){ vec.push_back(a); }, 2, 3);
|
||||
ASSERT_EQ(vec.size(), 2);
|
||||
ASSERT_EQ(vec[0], 1);
|
||||
ASSERT_EQ(vec[1], 1);
|
||||
|
||||
vec.clear();
|
||||
decompose_amount_randomly(4, [&](uint64_t a){ vec.push_back(a); }, 2, 1);
|
||||
ASSERT_EQ(vec.size(), 2);
|
||||
ASSERT_LE(vec[0], 3);
|
||||
ASSERT_GE(vec[0], 1);
|
||||
ASSERT_LE(vec[1], 3);
|
||||
ASSERT_GE(vec[1], 1);
|
||||
|
||||
vec.clear();
|
||||
decompose_amount_randomly(3, [&](uint64_t a){ vec.push_back(a); }, 3, 1);
|
||||
ASSERT_EQ(vec.size(), 3);
|
||||
ASSERT_EQ(vec[0], 1);
|
||||
ASSERT_EQ(vec[1], 1);
|
||||
ASSERT_EQ(vec[2], 1);
|
||||
|
||||
foo(1000, 2, 3);
|
||||
foo(1000, 2, 2);
|
||||
foo(1000, 2, 1);
|
||||
|
||||
foo(10000, 4, 2);
|
||||
foo(10010, 4, 3);
|
||||
foo(17283, 4, 4);
|
||||
|
||||
foo(100000, 4, 5);
|
||||
foo(100000, 4, 5);
|
||||
|
||||
foo(1000000000000, 2, 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
// Copyright (c) 2022 Zano Project
|
||||
// Copyright (c) 2012-2014 The Boolberry developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -13,6 +14,8 @@
|
|||
#include "currency_core/difficulty.h"
|
||||
#include "common/difficulty_boost_serialization.h"
|
||||
|
||||
using namespace currency;
|
||||
|
||||
TEST(block_pack_unpack, basic_struct_packing)
|
||||
{
|
||||
currency::block b = AUTO_VAL_INIT(b);
|
||||
|
|
@ -68,4 +71,59 @@ TEST(boost_multiprecision_serizlization, basic_struct_packing)
|
|||
ASSERT_EQ(v_origial, v_unserialized);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(tx_signatures_packing, 1)
|
||||
{
|
||||
std::vector<signature_v> sigs;
|
||||
|
||||
sigs.clear();
|
||||
ASSERT_EQ(1, get_object_blobsize(sigs));
|
||||
|
||||
// v(x) = tools::get_varint_packed_size(x)
|
||||
|
||||
{
|
||||
// empty NLSAG
|
||||
// v(0) + (1 + v(0) + 0 * 2 * 32) = 3
|
||||
sigs.clear();
|
||||
sigs.emplace_back(std::move(NLSAG_sig()));
|
||||
ASSERT_EQ(3, get_object_blobsize(sigs));
|
||||
}
|
||||
|
||||
{
|
||||
// 128 empty NLSAGs
|
||||
// v(128) + 128 * (1 + v(0) + 0 * 2 * 32) = 258
|
||||
sigs.clear();
|
||||
for(size_t i = 0; i < 128; ++i)
|
||||
sigs.emplace_back(std::move(NLSAG_sig()));
|
||||
ASSERT_EQ(258, get_object_blobsize(sigs));
|
||||
}
|
||||
|
||||
{
|
||||
// empty ZC_sig
|
||||
// v(0) + (1 + 32 + 32 + (1 + 10*32) + 32) = 99
|
||||
sigs.clear();
|
||||
sigs.emplace_back(std::move(ZC_sig()));
|
||||
ASSERT_EQ(99, get_object_blobsize(sigs));
|
||||
}
|
||||
|
||||
{
|
||||
// 128 empty ZC_sigs
|
||||
// v(128) + 128 * (1 + 32 + 32 + (v(0) + 0*32) + 32) = 12546
|
||||
sigs.clear();
|
||||
for(size_t i = 0; i < 128; ++i)
|
||||
sigs.emplace_back(std::move(ZC_sig()));
|
||||
ASSERT_EQ(12546, get_object_blobsize(sigs));
|
||||
}
|
||||
|
||||
{
|
||||
// 128 10-ring ZC_sigs
|
||||
// v(128) + 128 * (1 + 32 + 32 + (v(10) + 10*32) + 32) = 53506 (97 + (v(10) + 10*32))
|
||||
ZC_sig zc = AUTO_VAL_INIT(zc);
|
||||
zc.clsags_gg.r.resize(10);
|
||||
sigs.clear();
|
||||
for(size_t i = 0; i < 128; ++i)
|
||||
sigs.emplace_back(zc);
|
||||
ASSERT_EQ(53506, get_object_blobsize(sigs));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue