forked from such-gitea/wownero
cleanup old bp
This commit is contained in:
@@ -241,8 +241,15 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
rct::key commitment;
|
||||||
|
if (tx.version > 1)
|
||||||
|
{
|
||||||
|
commitment = tx.rct_signatures.outPk[i].mask;
|
||||||
|
if (rct::is_rct_bp_plus_legacy(tx.rct_signatures.type))
|
||||||
|
commitment = rct::scalarmult8(commitment);
|
||||||
|
}
|
||||||
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, tx.unlock_time,
|
||||||
tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL);
|
tx.version > 1 ? &commitment : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
add_tx_amount_output_indices(tx_id, amount_output_indices);
|
add_tx_amount_output_indices(tx_id, amount_output_indices);
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ namespace boost
|
|||||||
a & x.type;
|
a & x.type;
|
||||||
if (x.type == rct::RCTTypeNull)
|
if (x.type == rct::RCTTypeNull)
|
||||||
return;
|
return;
|
||||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
|
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeBulletproofPlus_FullCommit)
|
||||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||||
@@ -369,7 +369,7 @@ namespace boost
|
|||||||
a & x.type;
|
a & x.type;
|
||||||
if (x.type == rct::RCTTypeNull)
|
if (x.type == rct::RCTTypeNull)
|
||||||
return;
|
return;
|
||||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus)
|
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG && x.type != rct::RCTTypeBulletproofPlus && x.type != rct::RCTTypeBulletproofPlus_FullCommit)
|
||||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||||
@@ -389,7 +389,7 @@ namespace boost
|
|||||||
a & x.p.MGs;
|
a & x.p.MGs;
|
||||||
if (ver >= 1u)
|
if (ver >= 1u)
|
||||||
a & x.p.CLSAGs;
|
a & x.p.CLSAGs;
|
||||||
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus)
|
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeSimpleBulletproof || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus || x.type == rct::RCTTypeBulletproofPlus_FullCommit)
|
||||||
a & x.p.pseudoOuts;
|
a & x.p.pseudoOuts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ namespace cryptonote
|
|||||||
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
|
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
|
||||||
{
|
{
|
||||||
const rct::rctSig &rv = tx.rct_signatures;
|
const rct::rctSig &rv = tx.rct_signatures;
|
||||||
const bool plus = rv.type == rct::RCTTypeBulletproofPlus;
|
const bool plus = rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeBulletproofPlus_FullCommit;
|
||||||
const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
|
const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
|
||||||
const size_t n_outputs = tx.vout.size();
|
const size_t n_outputs = tx.vout.size();
|
||||||
if (n_padded_outputs <= 2)
|
if (n_padded_outputs <= 2)
|
||||||
@@ -167,7 +167,7 @@ namespace cryptonote
|
|||||||
if (!base_only)
|
if (!base_only)
|
||||||
{
|
{
|
||||||
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
|
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
|
||||||
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
|
const bool bulletproof_plus = rct::is_rct_bulletproof_plus_any(rv.type);
|
||||||
if (bulletproof_plus)
|
if (bulletproof_plus)
|
||||||
{
|
{
|
||||||
if (rv.p.bulletproofs_plus.size() != 1)
|
if (rv.p.bulletproofs_plus.size() != 1)
|
||||||
@@ -188,11 +188,13 @@ namespace cryptonote
|
|||||||
}
|
}
|
||||||
const size_t n_amounts = tx.vout.size();
|
const size_t n_amounts = tx.vout.size();
|
||||||
CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
|
CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
|
||||||
rv.p.bulletproofs_plus[0].V.resize(n_amounts);
|
rv.p.bulletproofs_plus[0].V.resize(n_amounts);
|
||||||
for (size_t i = 0; i < n_amounts; ++i)
|
const bool bulletproof_plus_legacy = rct::is_rct_bp_plus_legacy(rv.type);
|
||||||
rv.p.bulletproofs_plus[0].V[i] = rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT);
|
for (size_t i = 0; i < n_amounts; ++i) {
|
||||||
|
rv.p.bulletproofs_plus[0].V[i] = bulletproof_plus_legacy ? rv.outPk[i].mask : rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (bulletproof)
|
if (rct::is_rct_new_bulletproof(rv.type))
|
||||||
{
|
{
|
||||||
if (rv.p.bulletproofs.size() != 1)
|
if (rv.p.bulletproofs.size() != 1)
|
||||||
{
|
{
|
||||||
@@ -205,7 +207,7 @@ namespace cryptonote
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6);
|
const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6);
|
||||||
if (max_outputs < tx.vout.size())
|
if (max_outputs < tx.vout.size() && rv.type == rct::RCTTypeBulletproof)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx));
|
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx));
|
||||||
return false;
|
return false;
|
||||||
@@ -216,6 +218,24 @@ namespace cryptonote
|
|||||||
for (size_t i = 0; i < n_amounts; ++i)
|
for (size_t i = 0; i < n_amounts; ++i)
|
||||||
rv.p.bulletproofs[0].V[i] = rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT);
|
rv.p.bulletproofs[0].V[i] = rct::scalarmultKey(rv.outPk[i].mask, rct::INV_EIGHT);
|
||||||
}
|
}
|
||||||
|
else if (bulletproof)
|
||||||
|
{
|
||||||
|
if (rct::n_bulletproof_v1_amounts(rv.p.bulletproofs) != tx.vout.size())
|
||||||
|
{
|
||||||
|
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size_t idx = 0;
|
||||||
|
for (size_t n = 0; n < rv.outPk.size(); ++n)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_MES(rv.p.bulletproofs[n].L.size() >= 6, false, "Bad bulletproofs L size");
|
||||||
|
const size_t n_amounts = rct::n_bulletproof_v1_amounts(rv.p.bulletproofs[n]);
|
||||||
|
CHECK_AND_ASSERT_MES(idx + n_amounts <= rv.outPk.size(), false, "Internal error filling out V");
|
||||||
|
rv.p.bulletproofs[n].V.resize(n_amounts);
|
||||||
|
for (size_t i = 0; i < n_amounts; ++i)
|
||||||
|
rv.p.bulletproofs[n].V[i] = rv.outPk[idx++].mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -449,9 +469,14 @@ namespace cryptonote
|
|||||||
return blob_size;
|
return blob_size;
|
||||||
const rct::rctSig &rv = tx.rct_signatures;
|
const rct::rctSig &rv = tx.rct_signatures;
|
||||||
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
|
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
|
||||||
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
|
const bool bulletproof_plus = rct::is_rct_bulletproof_plus_any(rv.type);
|
||||||
if (!bulletproof && !bulletproof_plus)
|
if (!bulletproof && !bulletproof_plus)
|
||||||
return blob_size;
|
return blob_size;
|
||||||
|
const size_t n_outputs = tx.vout.size();
|
||||||
|
if (n_outputs <= 2)
|
||||||
|
return blob_size;
|
||||||
|
if (rct::is_rct_old_bulletproof(rv.type))
|
||||||
|
return blob_size;
|
||||||
const size_t n_padded_outputs = bulletproof_plus ? rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus) : rct::n_bulletproof_max_amounts(rv.p.bulletproofs);
|
const size_t n_padded_outputs = bulletproof_plus ? rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus) : rct::n_bulletproof_max_amounts(rv.p.bulletproofs);
|
||||||
uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs);
|
uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs);
|
||||||
CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow");
|
CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow");
|
||||||
@@ -462,7 +487,7 @@ namespace cryptonote
|
|||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
|
CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
|
||||||
CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
|
CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
|
||||||
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus,
|
CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit,
|
||||||
std::numeric_limits<uint64_t>::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight");
|
std::numeric_limits<uint64_t>::max(), "Unsupported rct_signatures type in get_pruned_transaction_weight");
|
||||||
CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
|
CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
|
||||||
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
|
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
|
||||||
@@ -481,7 +506,7 @@ namespace cryptonote
|
|||||||
while ((n_padded_outputs = (1u << nrl)) < tx.vout.size())
|
while ((n_padded_outputs = (1u << nrl)) < tx.vout.size())
|
||||||
++nrl;
|
++nrl;
|
||||||
nrl += 6;
|
nrl += 6;
|
||||||
extra = 32 * ((rct::is_rct_bulletproof_plus(tx.rct_signatures.type) ? 6 : 9) + 2 * nrl) + 2;
|
extra = 32 * ((rct::is_rct_bulletproof_plus_any(tx.rct_signatures.type) ? 6 : 9) + 2 * nrl) + 2;
|
||||||
weight += extra;
|
weight += extra;
|
||||||
|
|
||||||
// calculate deterministic CLSAG/MLSAG data size
|
// calculate deterministic CLSAG/MLSAG data size
|
||||||
|
|||||||
@@ -203,6 +203,7 @@
|
|||||||
#define HF_VERSION_BLOCK_HEADER_MINER_SIG 18
|
#define HF_VERSION_BLOCK_HEADER_MINER_SIG 18
|
||||||
#define HF_VERSION_VIEW_TAGS 20
|
#define HF_VERSION_VIEW_TAGS 20
|
||||||
#define HF_VERSION_2021_SCALING 20
|
#define HF_VERSION_2021_SCALING 20
|
||||||
|
#define HF_VERSION_BP_PLUS_FULL_COMMIT 21
|
||||||
|
|
||||||
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
||||||
#define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2
|
#define CRYPTONOTE_SCALING_2021_FEE_ROUNDING_PLACES 2
|
||||||
|
|||||||
@@ -3133,7 +3133,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v10, allow bulletproofs v2
|
// from v13, allow bulletproofs v2
|
||||||
if (hf_version < HF_VERSION_SMALLER_BP) {
|
if (hf_version < HF_VERSION_SMALLER_BP) {
|
||||||
if (tx.version >= 2) {
|
if (tx.version >= 2) {
|
||||||
if (tx.rct_signatures.type == rct::RCTTypeBulletproof2)
|
if (tx.rct_signatures.type == rct::RCTTypeBulletproof2)
|
||||||
@@ -3145,7 +3145,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v11, allow only bulletproofs v2
|
// from v14, allow only bulletproofs v2
|
||||||
if (hf_version > HF_VERSION_SMALLER_BP) {
|
if (hf_version > HF_VERSION_SMALLER_BP) {
|
||||||
if (tx.version >= 2) {
|
if (tx.version >= 2) {
|
||||||
if (tx.rct_signatures.type == rct::RCTTypeBulletproof)
|
if (tx.rct_signatures.type == rct::RCTTypeBulletproof)
|
||||||
@@ -3157,7 +3157,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v13, allow CLSAGs
|
// from v16, allow CLSAGs
|
||||||
if (hf_version < HF_VERSION_CLSAG) {
|
if (hf_version < HF_VERSION_CLSAG) {
|
||||||
if (tx.version >= 2) {
|
if (tx.version >= 2) {
|
||||||
if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
|
if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
|
||||||
@@ -3169,7 +3169,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v14, allow only CLSAGs
|
// from v17, allow only CLSAGs
|
||||||
if (hf_version > HF_VERSION_CLSAG) {
|
if (hf_version > HF_VERSION_CLSAG) {
|
||||||
if (tx.version >= 2) {
|
if (tx.version >= 2) {
|
||||||
if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2)
|
if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2)
|
||||||
@@ -3181,11 +3181,25 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v15, allow bulletproofs plus
|
|
||||||
|
// from v12, forbid old bulletproofs
|
||||||
|
if (hf_version > 11) {
|
||||||
|
if (tx.version >= 2) {
|
||||||
|
const bool old_bulletproof = rct::is_rct_old_bulletproof(tx.rct_signatures.type);
|
||||||
|
if (old_bulletproof)
|
||||||
|
{
|
||||||
|
MERROR_VER("Old Bulletproofs are not allowed after v11");
|
||||||
|
tvc.m_invalid_output = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from v18, allow bulletproofs plus
|
||||||
if (hf_version < HF_VERSION_BULLETPROOF_PLUS) {
|
if (hf_version < HF_VERSION_BULLETPROOF_PLUS) {
|
||||||
if (tx.version >= 2) {
|
if (tx.version >= 2) {
|
||||||
const bool bulletproof_plus = rct::is_rct_bulletproof_plus(tx.rct_signatures.type);
|
const bool bulletproof_plus_legacy = rct::is_rct_bp_plus_legacy(tx.rct_signatures.type);
|
||||||
if (bulletproof_plus || !tx.rct_signatures.p.bulletproofs_plus.empty())
|
if (bulletproof_plus_legacy || !tx.rct_signatures.p.bulletproofs_plus.empty())
|
||||||
{
|
{
|
||||||
MERROR_VER("Bulletproofs plus are not allowed before v" << std::to_string(HF_VERSION_BULLETPROOF_PLUS));
|
MERROR_VER("Bulletproofs plus are not allowed before v" << std::to_string(HF_VERSION_BULLETPROOF_PLUS));
|
||||||
tvc.m_invalid_output = true;
|
tvc.m_invalid_output = true;
|
||||||
@@ -3194,7 +3208,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v16, forbid bulletproofs
|
// from v19, forbid bulletproofs
|
||||||
if (hf_version > HF_VERSION_BULLETPROOF_PLUS) {
|
if (hf_version > HF_VERSION_BULLETPROOF_PLUS) {
|
||||||
if (tx.version >= 2) {
|
if (tx.version >= 2) {
|
||||||
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
|
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
|
||||||
@@ -3207,13 +3221,33 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from v15, require view tags on outputs
|
// from v20, require view tags on outputs
|
||||||
if (!check_output_types(tx, hf_version))
|
if (!check_output_types(tx, hf_version))
|
||||||
{
|
{
|
||||||
tvc.m_invalid_output = true;
|
tvc.m_invalid_output = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from v21, allow bulletproofs plus full commit
|
||||||
|
if (hf_version < HF_VERSION_BP_PLUS_FULL_COMMIT) {
|
||||||
|
if (tx.version >= 2) {
|
||||||
|
const bool bulletproof_plus_full_commit = rct::is_rct_bp_plus_full(tx.rct_signatures.type);
|
||||||
|
if (bulletproof_plus_full_commit)
|
||||||
|
{
|
||||||
|
MERROR_VER("Bulletproofs plus full commit are not allowed before v" << std::to_string(HF_VERSION_BP_PLUS_FULL_COMMIT));
|
||||||
|
tvc.m_invalid_output = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// from v22, forbid bulletproof plus legacy
|
||||||
|
if (hf_version > HF_VERSION_BP_PLUS_FULL_COMMIT && rct::is_rct_bp_plus_legacy(tx.rct_signatures.type)) {
|
||||||
|
MERROR_VER("Bulletproof Plus legacy range proofs are not allowed after v" << (HF_VERSION_BP_PLUS_FULL_COMMIT + 1));
|
||||||
|
tvc.m_invalid_output = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
@@ -3239,7 +3273,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
|||||||
rv.message = rct::hash2rct(tx_prefix_hash);
|
rv.message = rct::hash2rct(tx_prefix_hash);
|
||||||
|
|
||||||
// mixRing - full and simple store it in opposite ways
|
// mixRing - full and simple store it in opposite ways
|
||||||
if (rv.type == rct::RCTTypeFull)
|
if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
|
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
|
||||||
rv.mixRing.resize(pubkeys[0].size());
|
rv.mixRing.resize(pubkeys[0].size());
|
||||||
@@ -3254,7 +3288,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus)
|
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeSimpleBulletproof || rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
|
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
|
||||||
rv.mixRing.resize(pubkeys.size());
|
rv.mixRing.resize(pubkeys.size());
|
||||||
@@ -3273,7 +3307,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// II
|
// II
|
||||||
if (rv.type == rct::RCTTypeFull)
|
if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
|
||||||
{
|
{
|
||||||
if (!tx.pruned)
|
if (!tx.pruned)
|
||||||
{
|
{
|
||||||
@@ -3283,7 +3317,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
|||||||
rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
rv.p.MGs[0].II[n] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2)
|
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeSimpleBulletproof)
|
||||||
{
|
{
|
||||||
if (!tx.pruned)
|
if (!tx.pruned)
|
||||||
{
|
{
|
||||||
@@ -3295,7 +3329,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus)
|
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
if (!tx.pruned)
|
if (!tx.pruned)
|
||||||
{
|
{
|
||||||
@@ -3548,11 +3582,9 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Warn that new RCT types are present, and thus the cache is not being used effectively
|
// Warn that new RCT types are present, and thus the cache is not being used effectively
|
||||||
static constexpr const std::uint8_t RCT_CACHE_TYPE = rct::RCTTypeBulletproofPlus;
|
const std::uint8_t rct_cache_type = (hf_version >= HF_VERSION_BP_PLUS_FULL_COMMIT) ? static_cast<std::uint8_t>(rct::RCTTypeBulletproofPlus_FullCommit) : static_cast<std::uint8_t>(rct::RCTTypeBulletproofPlus);
|
||||||
if (tx.rct_signatures.type > RCT_CACHE_TYPE)
|
if (static_cast<std::uint8_t>(tx.rct_signatures.type) > rct_cache_type)
|
||||||
{
|
MWARNING("RCT cache is not caching new verification results. Please update rct_cache_type.");
|
||||||
MWARNING("RCT cache is not caching new verification results. Please update RCT_CACHE_TYPE!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tx.version == 1)
|
if (tx.version == 1)
|
||||||
{
|
{
|
||||||
@@ -3587,12 +3619,14 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case rct::RCTTypeSimple:
|
case rct::RCTTypeSimple:
|
||||||
|
case rct::RCTTypeSimpleBulletproof:
|
||||||
case rct::RCTTypeBulletproof:
|
case rct::RCTTypeBulletproof:
|
||||||
case rct::RCTTypeBulletproof2:
|
case rct::RCTTypeBulletproof2:
|
||||||
case rct::RCTTypeCLSAG:
|
case rct::RCTTypeCLSAG:
|
||||||
case rct::RCTTypeBulletproofPlus:
|
case rct::RCTTypeBulletproofPlus:
|
||||||
|
case rct::RCTTypeBulletproofPlus_FullCommit:
|
||||||
{
|
{
|
||||||
if (!ver_rct_non_semantics_simple_cached(tx, pubkeys, m_rct_ver_cache, RCT_CACHE_TYPE))
|
if (!ver_rct_non_semantics_simple_cached(tx, pubkeys, m_rct_ver_cache, rct_cache_type))
|
||||||
{
|
{
|
||||||
MERROR_VER("Failed to check ringct signatures!");
|
MERROR_VER("Failed to check ringct signatures!");
|
||||||
return false;
|
return false;
|
||||||
@@ -3600,6 +3634,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rct::RCTTypeFull:
|
case rct::RCTTypeFull:
|
||||||
|
case rct::RCTTypeFullBulletproof:
|
||||||
{
|
{
|
||||||
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
|
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -603,7 +603,9 @@ namespace cryptonote
|
|||||||
crypto::hash tx_prefix_hash;
|
crypto::hash tx_prefix_hash;
|
||||||
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
|
get_transaction_prefix_hash(tx, tx_prefix_hash, hwdev);
|
||||||
rct::ctkeyV outSk;
|
rct::ctkeyV outSk;
|
||||||
if (use_simple_rct)
|
if (rct_config.range_proof_type != rct::RangeProofPaddedBulletproof && use_simple_rct)
|
||||||
|
tx.rct_signatures = rct::genRctSimple_old(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, rct_config, hwdev);
|
||||||
|
else if (use_simple_rct && rct_config.range_proof_type == rct::RangeProofPaddedBulletproof)
|
||||||
tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, rct_config, hwdev);
|
tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk, rct_config, hwdev);
|
||||||
else
|
else
|
||||||
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk, rct_config, hwdev); // same index assumption
|
tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk, rct_config, hwdev); // same index assumption
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ bool ver_rct_non_semantics_simple_cached
|
|||||||
// mixring. Future versions of the protocol may differ in this regard, but if this assumptions
|
// mixring. Future versions of the protocol may differ in this regard, but if this assumptions
|
||||||
// holds true in the future, enable the verification hash by modifying the `untested_tx`
|
// holds true in the future, enable the verification hash by modifying the `untested_tx`
|
||||||
// condition below.
|
// condition below.
|
||||||
const bool untested_tx = tx.version > 2 || tx.rct_signatures.type > rct::RCTTypeBulletproofPlus;
|
const bool untested_tx = (tx.version > 2) || (static_cast<std::uint8_t>(tx.rct_signatures.type) > rct_type_to_cache);
|
||||||
VER_ASSERT(!untested_tx, "Unknown TX type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
|
VER_ASSERT(!untested_tx, "Unknown TX type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
|
||||||
|
|
||||||
// Don't cache older (or newer) rctSig types
|
// Don't cache older (or newer) rctSig types
|
||||||
@@ -302,6 +302,7 @@ bool ver_mixed_rct_semantics(std::vector<const rct::rctSig*> rvv)
|
|||||||
is_batchable_rv = true;
|
is_batchable_rv = true;
|
||||||
break;
|
break;
|
||||||
case rct::RCTTypeBulletproofPlus:
|
case rct::RCTTypeBulletproofPlus:
|
||||||
|
case rct::RCTTypeBulletproofPlus_FullCommit:
|
||||||
if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus))
|
if (!is_canonical_bulletproof_plus_layout(rv.p.bulletproofs_plus))
|
||||||
{
|
{
|
||||||
MERROR("Bulletproof_plus does not have canonical form");
|
MERROR("Bulletproof_plus does not have canonical form");
|
||||||
|
|||||||
@@ -2193,7 +2193,7 @@ skip:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
|
const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1;
|
||||||
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
|
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP +1);
|
||||||
bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
|
bool sync_pruned_blocks = m_sync_pruned_blocks && first_block_height >= bp_fork_height && m_core.get_blockchain_pruning_seed();
|
||||||
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
|
span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_remote_address, sync_pruned_blocks, m_core.get_blockchain_pruning_seed(), context.m_pruning_seed, context.m_remote_blockchain_height, context.m_needed_objects);
|
||||||
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
|
MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second);
|
||||||
|
|||||||
@@ -1929,7 +1929,7 @@ namespace hw {
|
|||||||
|
|
||||||
// ====== Aout, Bout, AKout, C, v, k ======
|
// ====== Aout, Bout, AKout, C, v, k ======
|
||||||
kv_offset = data_offset;
|
kv_offset = data_offset;
|
||||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) {
|
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus || type==rct::RCTTypeBulletproofPlus_FullCommit) {
|
||||||
C_offset = kv_offset+ (8)*outputs_size;
|
C_offset = kv_offset+ (8)*outputs_size;
|
||||||
} else {
|
} else {
|
||||||
C_offset = kv_offset+ (32+32)*outputs_size;
|
C_offset = kv_offset+ (32+32)*outputs_size;
|
||||||
@@ -1946,7 +1946,7 @@ namespace hw {
|
|||||||
offset = set_command_header(INS_VALIDATE, 0x02, i+1);
|
offset = set_command_header(INS_VALIDATE, 0x02, i+1);
|
||||||
//options
|
//options
|
||||||
this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ;
|
this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ;
|
||||||
this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus)?0x02:0x00;
|
this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus || type==rct::RCTTypeBulletproofPlus_FullCommit)?0x02:0x00;
|
||||||
offset += 1;
|
offset += 1;
|
||||||
//is_subaddress
|
//is_subaddress
|
||||||
this->buffer_send[offset] = outKeys.is_subaddress;
|
this->buffer_send[offset] = outKeys.is_subaddress;
|
||||||
@@ -1967,7 +1967,7 @@ namespace hw {
|
|||||||
memmove(this->buffer_send+offset, data+C_offset,32);
|
memmove(this->buffer_send+offset, data+C_offset,32);
|
||||||
offset += 32;
|
offset += 32;
|
||||||
C_offset += 32;
|
C_offset += 32;
|
||||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus) {
|
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG || type==rct::RCTTypeBulletproofPlus || type==rct::RCTTypeBulletproofPlus_FullCommit) {
|
||||||
//k
|
//k
|
||||||
memset(this->buffer_send+offset, 0, 32);
|
memset(this->buffer_send+offset, 0, 32);
|
||||||
offset += 32;
|
offset += 32;
|
||||||
|
|||||||
@@ -312,12 +312,12 @@ namespace tx {
|
|||||||
|
|
||||||
bool is_bulletproof() const {
|
bool is_bulletproof() const {
|
||||||
auto tp = get_rv_type();
|
auto tp = get_rv_type();
|
||||||
return rct::is_rct_bulletproof(tp) || rct::is_rct_bulletproof_plus(tp);
|
return rct::is_rct_bulletproof(tp) || rct::is_rct_bulletproof_plus_any(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_bulletproof_plus() const {
|
bool is_bulletproof_plus() const {
|
||||||
auto tp = get_rv_type();
|
auto tp = get_rv_type();
|
||||||
return rct::is_rct_bulletproof_plus(tp);
|
return rct::is_rct_bulletproof_plus_any(tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_clsag() const {
|
bool is_clsag() const {
|
||||||
|
|||||||
@@ -546,6 +546,7 @@ static void make_new_range_proofs(const int bp_version,
|
|||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
static bool try_reconstruct_range_proofs(const int bp_version,
|
static bool try_reconstruct_range_proofs(const int bp_version,
|
||||||
|
const uint8_t sig_type,
|
||||||
const rct::rctSigPrunable& original_sigs,
|
const rct::rctSigPrunable& original_sigs,
|
||||||
const std::size_t num_destinations,
|
const std::size_t num_destinations,
|
||||||
const rct::ctkeyV& output_public_keys,
|
const rct::ctkeyV& output_public_keys,
|
||||||
@@ -559,8 +560,13 @@ static bool try_reconstruct_range_proofs(const int bp_version,
|
|||||||
|
|
||||||
new_range_proofs = original_range_proofs;
|
new_range_proofs = original_range_proofs;
|
||||||
new_range_proofs[0].V.resize(num_destinations);
|
new_range_proofs[0].V.resize(num_destinations);
|
||||||
for (std::size_t i = 0; i < num_destinations; ++i)
|
const bool is_full = (bp_version == 4) && (sig_type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
new_range_proofs[0].V[i] = rct::scalarmultKey(output_public_keys[i].mask, rct::INV_EIGHT);
|
for (std::size_t i = 0; i < num_destinations; ++i) {
|
||||||
|
if (bp_version == 4)
|
||||||
|
new_range_proofs[0].V[i] = is_full ? rct::scalarmultKey(output_public_keys[i].mask, rct::INV_EIGHT) : output_public_keys[i].mask;
|
||||||
|
else
|
||||||
|
new_range_proofs[0].V[i] = rct::scalarmultKey(output_public_keys[i].mask, rct::INV_EIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -612,7 +618,7 @@ static bool set_tx_rct_signatures(
|
|||||||
if (rct_config.bp_version == 3)
|
if (rct_config.bp_version == 3)
|
||||||
rv.type = rct::RCTTypeCLSAG;
|
rv.type = rct::RCTTypeCLSAG;
|
||||||
else if (rct_config.bp_version == 4)
|
else if (rct_config.bp_version == 4)
|
||||||
rv.type = rct::RCTTypeBulletproofPlus;
|
rv.type = (unsigned_tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit) ? rct::RCTTypeBulletproofPlus_FullCommit : rct::RCTTypeBulletproofPlus;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
rv.txnFee = fee;
|
rv.txnFee = fee;
|
||||||
@@ -643,6 +649,7 @@ static bool set_tx_rct_signatures(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (not try_reconstruct_range_proofs(rct_config.bp_version,
|
if (not try_reconstruct_range_proofs(rct_config.bp_version,
|
||||||
|
rv.type,
|
||||||
unsigned_tx.rct_signatures.p,
|
unsigned_tx.rct_signatures.p,
|
||||||
num_destinations,
|
num_destinations,
|
||||||
rv.outPk,
|
rv.outPk,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ set(ringct_basic_sources
|
|||||||
rctCryptoOps.c
|
rctCryptoOps.c
|
||||||
multiexp.cc
|
multiexp.cc
|
||||||
bulletproofs.cc
|
bulletproofs.cc
|
||||||
|
legacy_bp/bulletproofs_old.cc
|
||||||
bulletproofs_plus.cc)
|
bulletproofs_plus.cc)
|
||||||
|
|
||||||
monero_find_all_headers(ringct_basic_private_headers "${CMAKE_CURRENT_SOURCE_DIR}")
|
monero_find_all_headers(ringct_basic_private_headers "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
@@ -51,12 +52,14 @@ target_link_libraries(ringct_basic
|
|||||||
|
|
||||||
set(ringct_sources
|
set(ringct_sources
|
||||||
rctSigs.cpp
|
rctSigs.cpp
|
||||||
|
legacy_bp/rctSigs_old.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(ringct_headers)
|
set(ringct_headers)
|
||||||
|
|
||||||
set(ringct_private_headers
|
set(ringct_private_headers
|
||||||
rctSigs.h
|
rctSigs.h
|
||||||
|
legacy_bp/rctSigs_old.h
|
||||||
)
|
)
|
||||||
|
|
||||||
monero_private_headers(ringct
|
monero_private_headers(ringct
|
||||||
|
|||||||
@@ -42,9 +42,16 @@ Bulletproof bulletproof_PROVE(const rct::key &v, const rct::key &gamma);
|
|||||||
Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma);
|
Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma);
|
||||||
Bulletproof bulletproof_PROVE(const rct::keyV &v, const rct::keyV &gamma);
|
Bulletproof bulletproof_PROVE(const rct::keyV &v, const rct::keyV &gamma);
|
||||||
Bulletproof bulletproof_PROVE(const std::vector<uint64_t> &v, const rct::keyV &gamma);
|
Bulletproof bulletproof_PROVE(const std::vector<uint64_t> &v, const rct::keyV &gamma);
|
||||||
|
Bulletproof bulletproof_PROVE_old(const rct::key &v, const rct::key &gamma);
|
||||||
|
Bulletproof bulletproof_PROVE_old(uint64_t v, const rct::key &gamma);
|
||||||
|
Bulletproof bulletproof_PROVE_old(const rct::keyV &v, const rct::keyV &gamma);
|
||||||
|
Bulletproof bulletproof_PROVE_old(const std::vector<uint64_t> &v, const rct::keyV &gamma);
|
||||||
bool bulletproof_VERIFY(const Bulletproof &proof);
|
bool bulletproof_VERIFY(const Bulletproof &proof);
|
||||||
bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs);
|
bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs);
|
||||||
bool bulletproof_VERIFY(const std::vector<Bulletproof> &proofs);
|
bool bulletproof_VERIFY(const std::vector<Bulletproof> &proofs);
|
||||||
|
bool bulletproof_VERIFY_old(const Bulletproof &proof);
|
||||||
|
bool bulletproof_VERIFY_old(const std::vector<const Bulletproof*> &proofs);
|
||||||
|
bool bulletproof_VERIFY_old(const std::vector<Bulletproof> &proofs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1165
src/ringct/legacy_bp/bulletproofs_old.cc
Normal file
1165
src/ringct/legacy_bp/bulletproofs_old.cc
Normal file
File diff suppressed because it is too large
Load Diff
137
src/ringct/legacy_bp/rctSigs_old.cpp
Normal file
137
src/ringct/legacy_bp/rctSigs_old.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include "misc_log_ex.h"
|
||||||
|
#include "misc_language.h"
|
||||||
|
#include "common/perf_timer.h"
|
||||||
|
#include "common/threadpool.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
#include "ringct/rctSigs.h"
|
||||||
|
#include "ringct/bulletproofs.h"
|
||||||
|
#include "ringct/bulletproofs_plus.h"
|
||||||
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
|
#include "cryptonote_config.h"
|
||||||
|
#include "rctSigs_old.h"
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
namespace rct {
|
||||||
|
|
||||||
|
Bulletproof proveRangeBulletproof_old(key &C, key &mask, uint64_t amount)
|
||||||
|
{
|
||||||
|
mask = rct::skGen();
|
||||||
|
Bulletproof proof = bulletproof_PROVE_old(amount, mask);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element");
|
||||||
|
C = proof.V[0];
|
||||||
|
return proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bulletproof proveRangeBulletproof_old(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts)
|
||||||
|
{
|
||||||
|
masks = rct::skvGen(amounts.size());
|
||||||
|
Bulletproof proof = bulletproof_PROVE_old(amounts, masks);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(proof.V.size() == amounts.size(), "V does not have the expected size");
|
||||||
|
C = proof.V;
|
||||||
|
return proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verBulletproof_old(const Bulletproof &proof)
|
||||||
|
{
|
||||||
|
try { return bulletproof_VERIFY_old(proof); }
|
||||||
|
catch (...) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verBulletproof_old(const std::vector<const Bulletproof*> &proofs)
|
||||||
|
{
|
||||||
|
try { return bulletproof_VERIFY_old(proofs); }
|
||||||
|
catch (...) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
xmr_amount populateFromBlockchainSimple(ctkeyV & mixRing, const ctkey & inPk, int mixin);
|
||||||
|
|
||||||
|
rctSig genRctSimple_old(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
|
||||||
|
const bool bulletproof = rct_config.range_proof_type != RangeProofBorromean;
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts");
|
||||||
|
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(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) {
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(index[n] < mixRing[n].size(), "Bad index into mixRing");
|
||||||
|
}
|
||||||
|
|
||||||
|
rctSig rv;
|
||||||
|
rv.type = bulletproof ? RCTTypeSimpleBulletproof : RCTTypeSimple;
|
||||||
|
rv.message = message;
|
||||||
|
rv.outPk.resize(destinations.size());
|
||||||
|
if (bulletproof)
|
||||||
|
rv.p.bulletproofs.resize(destinations.size());
|
||||||
|
else
|
||||||
|
rv.p.rangeSigs.resize(destinations.size());
|
||||||
|
rv.ecdhInfo.resize(destinations.size());
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
keyV masks(destinations.size()); //sk mask..
|
||||||
|
outSk.resize(destinations.size());
|
||||||
|
key sumout = zero();
|
||||||
|
for (i = 0; i < destinations.size(); i++) {
|
||||||
|
|
||||||
|
//add destination to sig
|
||||||
|
rv.outPk[i].dest = copy(destinations[i]);
|
||||||
|
//compute range proof
|
||||||
|
if (bulletproof)
|
||||||
|
rv.p.bulletproofs[i] = proveRangeBulletproof_old(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
|
||||||
|
else
|
||||||
|
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]);
|
||||||
|
#ifdef DBG
|
||||||
|
if (bulletproof)
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(verBulletproof_old(rv.p.bulletproofs[i]), "verBulletproof failed on newly created proof");
|
||||||
|
else
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sc_add(sumout.bytes, outSk[i].mask.bytes, sumout.bytes);
|
||||||
|
|
||||||
|
//mask amount and mask
|
||||||
|
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||||
|
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
|
||||||
|
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeSimpleBulletproof);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv.txnFee = txnFee;
|
||||||
|
rv.mixRing = mixRing;
|
||||||
|
keyV &pseudoOuts = bulletproof ? rv.p.pseudoOuts : rv.pseudoOuts;
|
||||||
|
pseudoOuts.resize(inamounts.size());
|
||||||
|
rv.p.MGs.resize(inamounts.size());
|
||||||
|
key sumpouts = zero(); //sum pseudoOut masks
|
||||||
|
keyV a(inamounts.size());
|
||||||
|
for (i = 0 ; i < inamounts.size() - 1; i++) {
|
||||||
|
skGen(a[i]);
|
||||||
|
sc_add(sumpouts.bytes, a[i].bytes, sumpouts.bytes);
|
||||||
|
genC(pseudoOuts[i], a[i], inamounts[i]);
|
||||||
|
}
|
||||||
|
rv.mixRing = mixRing;
|
||||||
|
sc_sub(a[i].bytes, sumout.bytes, sumpouts.bytes);
|
||||||
|
genC(pseudoOuts[i], a[i], inamounts[i]);
|
||||||
|
DP(pseudoOuts[i]);
|
||||||
|
|
||||||
|
key full_message = get_pre_mlsag_hash(rv,hwdev);
|
||||||
|
for (i = 0 ; i < inamounts.size(); i++) {
|
||||||
|
rv.p.MGs[i] = proveRctMGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], index[i], hwdev);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rctSig genRctSimple_old(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const vector<xmr_amount> &inamounts, const vector<xmr_amount> &outamounts, const keyV &amount_keys, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev) {
|
||||||
|
std::vector<unsigned int> index;
|
||||||
|
index.resize(inPk.size());
|
||||||
|
ctkeyM mixRing;
|
||||||
|
ctkeyV outSk;
|
||||||
|
mixRing.resize(inPk.size());
|
||||||
|
for (size_t i = 0; i < inPk.size(); ++i) {
|
||||||
|
mixRing[i].resize(mixin+1);
|
||||||
|
index[i] = populateFromBlockchainSimple(mixRing[i], inPk[i], mixin);
|
||||||
|
}
|
||||||
|
return genRctSimple_old(message, inSk, destinations, inamounts, outamounts, txnFee, mixRing, amount_keys, index, outSk, rct_config, hwdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rct
|
||||||
20
src/ringct/legacy_bp/rctSigs_old.h
Normal file
20
src/ringct/legacy_bp/rctSigs_old.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "ringct/rctSigs.h"
|
||||||
|
#include "ringct/bulletproofs.h"
|
||||||
|
|
||||||
|
namespace hw { class device; }
|
||||||
|
|
||||||
|
namespace rct {
|
||||||
|
|
||||||
|
Bulletproof proveRangeBulletproof_old(key &C, key &mask, uint64_t amount);
|
||||||
|
Bulletproof proveRangeBulletproof_old(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts);
|
||||||
|
|
||||||
|
bool verBulletproof_old(const Bulletproof &proof);
|
||||||
|
bool verBulletproof_old(const std::vector<const Bulletproof*> &proofs);
|
||||||
|
|
||||||
|
rctSig genRctSimple_old(const key &message, const ctkeyV & inSk, const keyV & destinations, const std::vector<xmr_amount> &inamounts, const std::vector<xmr_amount> &outamounts, xmr_amount txnFee, const ctkeyM & mixRing, const keyV &amount_keys, const std::vector<unsigned int> & index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev);
|
||||||
|
rctSig genRctSimple_old(const key &message, const ctkeyV & inSk, const ctkeyV & inPk, const keyV & destinations, const std::vector<xmr_amount> &inamounts, const std::vector<xmr_amount> &outamounts, const keyV & amount_keys, xmr_amount txnFee, unsigned int mixin, const RCTConfig &rct_config, hw::device &hwdev);
|
||||||
|
|
||||||
|
} // namespace rct
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
#include "bulletproofs_plus.h"
|
#include "bulletproofs_plus.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
|
#include "legacy_bp/rctSigs_old.h"
|
||||||
|
|
||||||
using namespace crypto;
|
using namespace crypto;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -616,7 +617,7 @@ namespace rct {
|
|||||||
hashes.push_back(hash2rct(h));
|
hashes.push_back(hash2rct(h));
|
||||||
|
|
||||||
keyV kv;
|
keyV kv;
|
||||||
if (rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG)
|
if (rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeSimpleBulletproof || rv.type == RCTTypeFullBulletproof || rv.type == RCTTypeCLSAG)
|
||||||
{
|
{
|
||||||
kv.reserve((6*2+9) * rv.p.bulletproofs.size());
|
kv.reserve((6*2+9) * rv.p.bulletproofs.size());
|
||||||
for (const auto &p: rv.p.bulletproofs)
|
for (const auto &p: rv.p.bulletproofs)
|
||||||
@@ -638,7 +639,7 @@ namespace rct {
|
|||||||
kv.push_back(p.t);
|
kv.push_back(p.t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rv.type == RCTTypeBulletproofPlus)
|
else if (rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
kv.reserve((6*2+6) * rv.p.bulletproofs_plus.size());
|
kv.reserve((6*2+6) * rv.p.bulletproofs_plus.size());
|
||||||
for (const auto &p: rv.p.bulletproofs_plus)
|
for (const auto &p: rv.p.bulletproofs_plus)
|
||||||
@@ -1044,6 +1045,7 @@ namespace rct {
|
|||||||
// Note: For txn fees, the last index in the amounts vector should contain that
|
// Note: For txn fees, the last index in the amounts vector should contain that
|
||||||
// Thus the amounts vector will be "one" longer than the destinations vectort
|
// Thus the amounts vector will be "one" longer than the destinations vectort
|
||||||
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
|
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk, const RCTConfig &rct_config, hw::device &hwdev) {
|
||||||
|
const bool bulletproof = rct_config.range_proof_type != RangeProofBorromean;
|
||||||
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations");
|
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "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(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
|
||||||
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
|
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
|
||||||
@@ -1053,10 +1055,11 @@ namespace rct {
|
|||||||
CHECK_AND_ASSERT_THROW_MES(inSk.size() < 2, "genRct is not suitable for 2+ rings");
|
CHECK_AND_ASSERT_THROW_MES(inSk.size() < 2, "genRct is not suitable for 2+ rings");
|
||||||
|
|
||||||
rctSig rv;
|
rctSig rv;
|
||||||
rv.type = RCTTypeFull;
|
rv.type = bulletproof ? RCTTypeFullBulletproof : RCTTypeFull;
|
||||||
rv.message = message;
|
rv.message = message;
|
||||||
rv.outPk.resize(destinations.size());
|
rv.outPk.resize(destinations.size());
|
||||||
rv.p.rangeSigs.resize(destinations.size());
|
if (!bulletproof)
|
||||||
|
rv.p.rangeSigs.resize(destinations.size());
|
||||||
rv.ecdhInfo.resize(destinations.size());
|
rv.ecdhInfo.resize(destinations.size());
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@@ -1066,14 +1069,49 @@ namespace rct {
|
|||||||
//add destination to sig
|
//add destination to sig
|
||||||
rv.outPk[i].dest = copy(destinations[i]);
|
rv.outPk[i].dest = copy(destinations[i]);
|
||||||
//compute range proof
|
//compute range proof
|
||||||
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
|
if (!bulletproof)
|
||||||
|
{
|
||||||
|
rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]);
|
||||||
|
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
|
CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv.p.bulletproofs.clear();
|
||||||
|
if (bulletproof)
|
||||||
|
{
|
||||||
|
std::vector<uint64_t> proof_amounts;
|
||||||
|
size_t amounts_proved = 0;
|
||||||
|
while (amounts_proved < amounts.size())
|
||||||
|
{
|
||||||
|
size_t batch_size = 1;
|
||||||
|
if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof)
|
||||||
|
while (batch_size * 2 + amounts_proved <= amounts.size())
|
||||||
|
batch_size *= 2;
|
||||||
|
rct::keyV C, masks;
|
||||||
|
std::vector<uint64_t> batch_amounts(batch_size);
|
||||||
|
for (i = 0; i < batch_size; ++i)
|
||||||
|
batch_amounts[i] = amounts[i + amounts_proved];
|
||||||
|
rv.p.bulletproofs.push_back(proveRangeBulletproof_old(C, masks, batch_amounts));
|
||||||
|
#ifdef DBG
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(verBulletproof_old(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||||
|
#endif
|
||||||
|
for (i = 0; i < batch_size; ++i)
|
||||||
|
{
|
||||||
|
rv.outPk[i + amounts_proved].mask = C[i];
|
||||||
|
outSk[i + amounts_proved].mask = masks[i];
|
||||||
|
}
|
||||||
|
amounts_proved += batch_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < outSk.size(); ++i)
|
||||||
|
{
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||||
rv.ecdhInfo[i].amount = d2h(amounts[i]);
|
rv.ecdhInfo[i].amount = d2h(amounts[i]);
|
||||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
//set txn fee
|
//set txn fee
|
||||||
@@ -1121,7 +1159,7 @@ namespace rct {
|
|||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case 4:
|
case 4:
|
||||||
rv.type = RCTTypeBulletproofPlus;
|
rv.type = (rv.type == rct::RCTTypeBulletproofPlus_FullCommit) ? rct::RCTTypeBulletproofPlus_FullCommit : rct::RCTTypeBulletproofPlus;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
rv.type = RCTTypeCLSAG;
|
rv.type = RCTTypeCLSAG;
|
||||||
@@ -1165,7 +1203,9 @@ namespace rct {
|
|||||||
rv.p.bulletproofs_plus.clear();
|
rv.p.bulletproofs_plus.clear();
|
||||||
if (bulletproof_or_plus)
|
if (bulletproof_or_plus)
|
||||||
{
|
{
|
||||||
const bool plus = is_rct_bulletproof_plus(rv.type);
|
const bool bp_plus_full = is_rct_bp_plus_full(rv.type);
|
||||||
|
const bool bulletproof_plus = is_rct_bulletproof_plus_any(rv.type);
|
||||||
|
const bool bulletproof_plus_legacy = rct::is_rct_bp_plus_legacy(rv.type);
|
||||||
size_t n_amounts = outamounts.size();
|
size_t n_amounts = outamounts.size();
|
||||||
size_t amounts_proved = 0;
|
size_t amounts_proved = 0;
|
||||||
if (rct_config.range_proof_type == RangeProofPaddedBulletproof)
|
if (rct_config.range_proof_type == RangeProofPaddedBulletproof)
|
||||||
@@ -1174,7 +1214,7 @@ namespace rct {
|
|||||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||||
{
|
{
|
||||||
// use a fake bulletproof for speed
|
// use a fake bulletproof for speed
|
||||||
if (plus)
|
if (bulletproof_plus)
|
||||||
rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(outamounts, C, masks));
|
rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(outamounts, C, masks));
|
||||||
else
|
else
|
||||||
rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks));
|
rv.p.bulletproofs.push_back(make_dummy_bulletproof(outamounts, C, masks));
|
||||||
@@ -1182,12 +1222,12 @@ namespace rct {
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
|
const epee::span<const key> keys{&amount_keys[0], amount_keys.size()};
|
||||||
if (plus)
|
if (bulletproof_plus)
|
||||||
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, outamounts, keys, hwdev));
|
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, outamounts, keys, hwdev));
|
||||||
else
|
else
|
||||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
|
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts, keys, hwdev));
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
if (plus)
|
if (bulletproof_plus)
|
||||||
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof");
|
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof");
|
||||||
else
|
else
|
||||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||||
@@ -1195,15 +1235,20 @@ namespace rct {
|
|||||||
}
|
}
|
||||||
for (i = 0; i < outamounts.size(); ++i)
|
for (i = 0; i < outamounts.size(); ++i)
|
||||||
{
|
{
|
||||||
|
if (bp_plus_full)
|
||||||
rv.outPk[i].mask = rct::scalarmult8(C[i]);
|
rv.outPk[i].mask = rct::scalarmult8(C[i]);
|
||||||
outSk[i].mask = masks[i];
|
else if (bulletproof_plus_legacy)
|
||||||
|
rv.outPk[i].mask = C[i];
|
||||||
|
else
|
||||||
|
rv.outPk[i].mask = rct::scalarmult8(C[i]);
|
||||||
|
outSk[i].mask = masks[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else while (amounts_proved < n_amounts)
|
else while (amounts_proved < n_amounts)
|
||||||
{
|
{
|
||||||
size_t batch_size = 1;
|
size_t batch_size = 1;
|
||||||
if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof)
|
if (rct_config.range_proof_type == RangeProofMultiOutputBulletproof)
|
||||||
while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= (plus ? BULLETPROOF_PLUS_MAX_OUTPUTS : BULLETPROOF_MAX_OUTPUTS))
|
while (batch_size * 2 + amounts_proved <= n_amounts && batch_size * 2 <= (bulletproof_plus ? BULLETPROOF_PLUS_MAX_OUTPUTS : BULLETPROOF_MAX_OUTPUTS))
|
||||||
batch_size *= 2;
|
batch_size *= 2;
|
||||||
rct::keyV C, masks;
|
rct::keyV C, masks;
|
||||||
std::vector<uint64_t> batch_amounts(batch_size);
|
std::vector<uint64_t> batch_amounts(batch_size);
|
||||||
@@ -1212,7 +1257,7 @@ namespace rct {
|
|||||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||||
{
|
{
|
||||||
// use a fake bulletproof for speed
|
// use a fake bulletproof for speed
|
||||||
if (plus)
|
if (bulletproof_plus)
|
||||||
rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(batch_amounts, C, masks));
|
rv.p.bulletproofs_plus.push_back(make_dummy_bulletproof_plus(batch_amounts, C, masks));
|
||||||
else
|
else
|
||||||
rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks));
|
rv.p.bulletproofs.push_back(make_dummy_bulletproof(batch_amounts, C, masks));
|
||||||
@@ -1220,12 +1265,12 @@ namespace rct {
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
|
const epee::span<const key> keys{&amount_keys[amounts_proved], batch_size};
|
||||||
if (plus)
|
if (bulletproof_plus)
|
||||||
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, batch_amounts, keys, hwdev));
|
rv.p.bulletproofs_plus.push_back(proveRangeBulletproofPlus(C, masks, batch_amounts, keys, hwdev));
|
||||||
else
|
else
|
||||||
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
|
rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, batch_amounts, keys, hwdev));
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
if (plus)
|
if (bulletproof_plus)
|
||||||
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof");
|
CHECK_AND_ASSERT_THROW_MES(verBulletproofPlus(rv.p.bulletproofs_plus.back()), "verBulletproofPlus failed on newly created proof");
|
||||||
else
|
else
|
||||||
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof");
|
||||||
@@ -1233,7 +1278,12 @@ namespace rct {
|
|||||||
}
|
}
|
||||||
for (i = 0; i < batch_size; ++i)
|
for (i = 0; i < batch_size; ++i)
|
||||||
{
|
{
|
||||||
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
|
if (bp_plus_full)
|
||||||
|
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
|
||||||
|
else if (bulletproof_plus_legacy)
|
||||||
|
rv.outPk[i + amounts_proved].mask = C[i];
|
||||||
|
else
|
||||||
|
rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]);
|
||||||
outSk[i + amounts_proved].mask = masks[i];
|
outSk[i + amounts_proved].mask = masks[i];
|
||||||
}
|
}
|
||||||
amounts_proved += batch_size;
|
amounts_proved += batch_size;
|
||||||
@@ -1248,7 +1298,7 @@ namespace rct {
|
|||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
rv.ecdhInfo[i].mask = copy(outSk[i].mask);
|
||||||
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
|
rv.ecdhInfo[i].amount = d2h(outamounts[i]);
|
||||||
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
hwdev.ecdhEncode(rv.ecdhInfo[i], amount_keys[i], rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
//set txn fee
|
//set txn fee
|
||||||
@@ -1317,10 +1367,13 @@ namespace rct {
|
|||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
bool verRct(const rctSig & rv, bool semantics) {
|
bool verRct(const rctSig & rv, bool semantics) {
|
||||||
PERF_TIMER(verRct);
|
PERF_TIMER(verRct);
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig");
|
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||||
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeFullBulletproof, false, "verRct called on non-full rctSig");
|
||||||
if (semantics)
|
if (semantics)
|
||||||
{
|
{
|
||||||
|
if (rv.type == RCTTypeBulletproof)
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
|
||||||
|
else
|
||||||
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
|
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
|
||||||
CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "full rctSig has not one MG");
|
CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "full rctSig has not one MG");
|
||||||
}
|
}
|
||||||
@@ -1335,10 +1388,23 @@ namespace rct {
|
|||||||
if (semantics) {
|
if (semantics) {
|
||||||
tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
|
tools::threadpool& tpool = tools::threadpool::getInstanceForCompute();
|
||||||
tools::threadpool::waiter waiter(tpool);
|
tools::threadpool::waiter waiter(tpool);
|
||||||
std::deque<bool> results(rv.outPk.size(), false);
|
std::deque<bool> results(bulletproof ? rv.p.bulletproofs.size() : rv.outPk.size(), false);
|
||||||
DP("range proofs verified?");
|
DP("range proofs verified?");
|
||||||
for (size_t i = 0; i < rv.outPk.size(); i++)
|
if (rct::is_rct_new_bulletproof(rv.type))
|
||||||
tpool.submit(&waiter, [&, i] { results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); });
|
{
|
||||||
|
for (size_t i = 0; i < rv.p.bulletproofs.size(); i++)
|
||||||
|
tpool.submit(&waiter, [&, i] { results[i] = verBulletproof(rv.p.bulletproofs[i]); });
|
||||||
|
}
|
||||||
|
else if (bulletproof)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < rv.p.bulletproofs.size(); i++)
|
||||||
|
tpool.submit(&waiter, [&, i] { results[i] = verBulletproof_old(rv.p.bulletproofs[i]); });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < rv.outPk.size(); i++)
|
||||||
|
tpool.submit(&waiter, [&, i] { results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]); });
|
||||||
|
}
|
||||||
if (!waiter.wait())
|
if (!waiter.wait())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1394,10 +1460,10 @@ namespace rct {
|
|||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL");
|
CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL");
|
||||||
const rctSig &rv = *rvp;
|
const rctSig &rv = *rvp;
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus,
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeSimpleBulletproof || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit,
|
||||||
false, "verRctSemanticsSimple called on non simple rctSig");
|
false, "verRctSemanticsSimple called on non simple rctSig");
|
||||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||||
const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type);
|
const bool bulletproof_plus = is_rct_bulletproof_plus_any(rv.type);
|
||||||
if (bulletproof || bulletproof_plus)
|
if (bulletproof || bulletproof_plus)
|
||||||
{
|
{
|
||||||
if (bulletproof_plus)
|
if (bulletproof_plus)
|
||||||
@@ -1434,12 +1500,16 @@ namespace rct {
|
|||||||
const rctSig &rv = *rvp;
|
const rctSig &rv = *rvp;
|
||||||
|
|
||||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||||
const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type);
|
const bool bulletproof_plus = is_rct_bulletproof_plus_any(rv.type);
|
||||||
|
const bool bulletproof_plus_legacy = rct::is_rct_bp_plus_legacy(rv.type);
|
||||||
const keyV &pseudoOuts = bulletproof || bulletproof_plus ? rv.p.pseudoOuts : rv.pseudoOuts;
|
const keyV &pseudoOuts = bulletproof || bulletproof_plus ? rv.p.pseudoOuts : rv.pseudoOuts;
|
||||||
|
|
||||||
rct::keyV masks(rv.outPk.size());
|
rct::keyV masks(rv.outPk.size());
|
||||||
for (size_t i = 0; i < rv.outPk.size(); i++) {
|
for (size_t i = 0; i < rv.outPk.size(); i++) {
|
||||||
masks[i] = rv.outPk[i].mask;
|
if (bulletproof_plus_legacy)
|
||||||
|
masks[i] = rct::scalarmult8(rv.outPk[i].mask);
|
||||||
|
else
|
||||||
|
masks[i] = rv.outPk[i].mask;
|
||||||
}
|
}
|
||||||
key sumOutpks = addKeys(masks);
|
key sumOutpks = addKeys(masks);
|
||||||
DP(sumOutpks);
|
DP(sumOutpks);
|
||||||
@@ -1523,10 +1593,10 @@ namespace rct {
|
|||||||
{
|
{
|
||||||
PERF_TIMER(verRctNonSemanticsSimple);
|
PERF_TIMER(verRctNonSemanticsSimple);
|
||||||
|
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus,
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeSimpleBulletproof || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit,
|
||||||
false, "verRctNonSemanticsSimple called on non simple rctSig");
|
false, "verRctNonSemanticsSimple called on non simple rctSig");
|
||||||
const bool bulletproof = is_rct_bulletproof(rv.type);
|
const bool bulletproof = is_rct_bulletproof(rv.type);
|
||||||
const bool bulletproof_plus = is_rct_bulletproof_plus(rv.type);
|
const bool bulletproof_plus = is_rct_bulletproof_plus_any(rv.type);
|
||||||
// semantics check is early, and mixRing/MGs aren't resolved yet
|
// semantics check is early, and mixRing/MGs aren't resolved yet
|
||||||
if (bulletproof || bulletproof_plus)
|
if (bulletproof || bulletproof_plus)
|
||||||
CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.p.pseudoOuts and mixRing");
|
CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.p.pseudoOuts and mixRing");
|
||||||
@@ -1589,16 +1659,18 @@ namespace rct {
|
|||||||
// uses the attached ecdh info to find the amounts represented by each output commitment
|
// uses the attached ecdh info to find the amounts represented by each output commitment
|
||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev) {
|
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeFullBulletproof, false, "decodeRct called on non-full rctSig");
|
||||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
||||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit);
|
||||||
mask = ecdh_info.mask;
|
mask = ecdh_info.mask;
|
||||||
key amount = ecdh_info.amount;
|
key amount = ecdh_info.amount;
|
||||||
key C = rv.outPk[i].mask;
|
key C = rv.outPk[i].mask;
|
||||||
|
if (is_rct_bp_plus_legacy(rv.type))
|
||||||
|
C = scalarmult8(C);
|
||||||
DP("C");
|
DP("C");
|
||||||
DP(C);
|
DP(C);
|
||||||
key Ctmp;
|
key Ctmp;
|
||||||
@@ -1619,17 +1691,19 @@ namespace rct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) {
|
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask, hw::device &hwdev) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus,
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof || rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeSimpleBulletproof || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit,
|
||||||
false, "decodeRct called on non simple rctSig");
|
false, "decodeRct called on non simple rctSig");
|
||||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
ecdhTuple ecdh_info = rv.ecdhInfo[i];
|
||||||
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus);
|
hwdev.ecdhDecode(ecdh_info, sk, rv.type == RCTTypeBulletproof2 || rv.type == RCTTypeCLSAG || rv.type == RCTTypeBulletproofPlus || rv.type == RCTTypeBulletproofPlus_FullCommit);
|
||||||
mask = ecdh_info.mask;
|
mask = ecdh_info.mask;
|
||||||
key amount = ecdh_info.amount;
|
key amount = ecdh_info.amount;
|
||||||
key C = rv.outPk[i].mask;
|
key C = rv.outPk[i].mask;
|
||||||
|
if (is_rct_bp_plus_legacy(rv.type))
|
||||||
|
C = scalarmult8(C);
|
||||||
DP("C");
|
DP("C");
|
||||||
DP(C);
|
DP(C);
|
||||||
key Ctmp;
|
key Ctmp;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include "rctTypes.h"
|
#include "rctTypes.h"
|
||||||
#include "rctOps.h"
|
#include "rctOps.h"
|
||||||
|
#include "legacy_bp/rctSigs_old.h"
|
||||||
|
|
||||||
//Define this flag when debugging to get additional info on the console
|
//Define this flag when debugging to get additional info on the console
|
||||||
#ifdef DBG
|
#ifdef DBG
|
||||||
|
|||||||
@@ -193,10 +193,12 @@ namespace rct {
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case RCTTypeSimple:
|
case RCTTypeSimple:
|
||||||
|
case RCTTypeSimpleBulletproof:
|
||||||
case RCTTypeBulletproof:
|
case RCTTypeBulletproof:
|
||||||
case RCTTypeBulletproof2:
|
case RCTTypeBulletproof2:
|
||||||
case RCTTypeCLSAG:
|
case RCTTypeCLSAG:
|
||||||
case RCTTypeBulletproofPlus:
|
case RCTTypeBulletproofPlus:
|
||||||
|
case RCTTypeBulletproofPlus_FullCommit:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -207,6 +209,8 @@ namespace rct {
|
|||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case RCTTypeSimpleBulletproof:
|
||||||
|
case RCTTypeFullBulletproof:
|
||||||
case RCTTypeBulletproof:
|
case RCTTypeBulletproof:
|
||||||
case RCTTypeBulletproof2:
|
case RCTTypeBulletproof2:
|
||||||
case RCTTypeCLSAG:
|
case RCTTypeCLSAG:
|
||||||
@@ -216,17 +220,23 @@ namespace rct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_rct_bulletproof_plus(int type)
|
bool is_rct_old_bulletproof(int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case RCTTypeBulletproofPlus:
|
case RCTTypeSimpleBulletproof:
|
||||||
|
case RCTTypeFullBulletproof:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_rct_new_bulletproof(int type)
|
||||||
|
{
|
||||||
|
return is_rct_bulletproof(type) && !is_rct_old_bulletproof(type);
|
||||||
|
}
|
||||||
|
|
||||||
bool is_rct_borromean(int type)
|
bool is_rct_borromean(int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
@@ -239,12 +249,67 @@ namespace rct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_rct_bp_plus_legacy(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RCTTypeBulletproofPlus:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_rct_bp_plus_full(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RCTTypeBulletproofPlus_FullCommit:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_rct_bulletproof_plus_any(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RCTTypeBulletproofPlus:
|
||||||
|
case RCTTypeBulletproofPlus_FullCommit:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t n_bulletproof_v1_amounts(const Bulletproof &proof)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size");
|
||||||
|
CHECK_AND_ASSERT_MES(proof.L.size() <= 31, 0, "Insane bulletproof L size");
|
||||||
|
return 1 << (proof.L.size() - 6);
|
||||||
|
}
|
||||||
|
size_t n_bulletproof_v1_amounts(const std::vector<Bulletproof> &proofs)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (const Bulletproof &proof: proofs)
|
||||||
|
{
|
||||||
|
size_t n2 = n_bulletproof_v1_amounts(proof);
|
||||||
|
CHECK_AND_ASSERT_MES(n2 < std::numeric_limits<uint32_t>::max() - n, 0, "Invalid number of bulletproofs");
|
||||||
|
if (n2 == 0)
|
||||||
|
return 0;
|
||||||
|
n += n2;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_rct_clsag(int type)
|
bool is_rct_clsag(int type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case RCTTypeCLSAG:
|
case RCTTypeCLSAG:
|
||||||
case RCTTypeBulletproofPlus:
|
case RCTTypeBulletproofPlus:
|
||||||
|
case RCTTypeBulletproofPlus_FullCommit:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -279,8 +279,10 @@ namespace rct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
size_t n_bulletproof_amounts(const Bulletproof &proof);
|
size_t n_bulletproof_amounts(const Bulletproof &proof);
|
||||||
|
size_t n_bulletproof_v1_amounts(const Bulletproof &proof);
|
||||||
size_t n_bulletproof_max_amounts(const Bulletproof &proof);
|
size_t n_bulletproof_max_amounts(const Bulletproof &proof);
|
||||||
size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs);
|
size_t n_bulletproof_amounts(const std::vector<Bulletproof> &proofs);
|
||||||
|
size_t n_bulletproof_v1_amounts(const std::vector<Bulletproof> &proofs);
|
||||||
size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs);
|
size_t n_bulletproof_max_amounts(const std::vector<Bulletproof> &proofs);
|
||||||
|
|
||||||
size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof);
|
size_t n_bulletproof_plus_amounts(const BulletproofPlus &proof);
|
||||||
@@ -299,10 +301,13 @@ namespace rct {
|
|||||||
RCTTypeNull = 0,
|
RCTTypeNull = 0,
|
||||||
RCTTypeFull = 1,
|
RCTTypeFull = 1,
|
||||||
RCTTypeSimple = 2,
|
RCTTypeSimple = 2,
|
||||||
RCTTypeBulletproof = 3,
|
RCTTypeFullBulletproof = 3,
|
||||||
RCTTypeBulletproof2 = 4,
|
RCTTypeSimpleBulletproof = 4,
|
||||||
RCTTypeCLSAG = 5,
|
RCTTypeBulletproof = 5,
|
||||||
RCTTypeBulletproofPlus = 6,
|
RCTTypeBulletproof2 = 6,
|
||||||
|
RCTTypeCLSAG = 7,
|
||||||
|
RCTTypeBulletproofPlus = 8,
|
||||||
|
RCTTypeBulletproofPlus_FullCommit = 9,
|
||||||
};
|
};
|
||||||
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
|
enum RangeProofType { RangeProofBorromean, RangeProofBulletproof, RangeProofMultiOutputBulletproof, RangeProofPaddedBulletproof };
|
||||||
struct RCTConfig {
|
struct RCTConfig {
|
||||||
@@ -335,7 +340,7 @@ namespace rct {
|
|||||||
FIELD(type)
|
FIELD(type)
|
||||||
if (type == RCTTypeNull)
|
if (type == RCTTypeNull)
|
||||||
return ar.good();
|
return ar.good();
|
||||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
|
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeFullBulletproof && type != RCTTypeSimpleBulletproof && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeBulletproofPlus_FullCommit)
|
||||||
return false;
|
return false;
|
||||||
VARINT_FIELD(txnFee)
|
VARINT_FIELD(txnFee)
|
||||||
// inputs/outputs not saved, only here for serialization help
|
// inputs/outputs not saved, only here for serialization help
|
||||||
@@ -364,7 +369,7 @@ namespace rct {
|
|||||||
return false;
|
return false;
|
||||||
for (size_t i = 0; i < outputs; ++i)
|
for (size_t i = 0; i < outputs; ++i)
|
||||||
{
|
{
|
||||||
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
|
if (type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
// Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the
|
// Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the
|
||||||
// first 8 bytes of ecdhInfo[i].amount
|
// first 8 bytes of ecdhInfo[i].amount
|
||||||
@@ -433,9 +438,24 @@ namespace rct {
|
|||||||
return false;
|
return false;
|
||||||
if (type == RCTTypeNull)
|
if (type == RCTTypeNull)
|
||||||
return ar.good();
|
return ar.good();
|
||||||
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus)
|
if (type != RCTTypeFull && type != RCTTypeSimple && type != RCTTypeBulletproof && type != RCTTypeBulletproof2 && type != RCTTypeFullBulletproof && type != RCTTypeSimpleBulletproof && type != RCTTypeCLSAG && type != RCTTypeBulletproofPlus && type != RCTTypeBulletproofPlus_FullCommit)
|
||||||
return false;
|
return false;
|
||||||
if (type == RCTTypeBulletproofPlus)
|
if (type == RCTTypeSimpleBulletproof || type == RCTTypeFullBulletproof)
|
||||||
|
{
|
||||||
|
ar.tag("bp");
|
||||||
|
ar.begin_array();
|
||||||
|
PREPARE_CUSTOM_VECTOR_SERIALIZATION(outputs, bulletproofs);
|
||||||
|
if (bulletproofs.size() != outputs)
|
||||||
|
return false;
|
||||||
|
for (size_t i = 0; i < outputs; ++i)
|
||||||
|
{
|
||||||
|
FIELDS(bulletproofs[i])
|
||||||
|
if (outputs - i > 1)
|
||||||
|
ar.delimit_array();
|
||||||
|
}
|
||||||
|
ar.end_array();
|
||||||
|
}
|
||||||
|
else if (type == RCTTypeBulletproofPlus || type == RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
uint32_t nbp = bulletproofs_plus.size();
|
uint32_t nbp = bulletproofs_plus.size();
|
||||||
VARINT_FIELD(nbp)
|
VARINT_FIELD(nbp)
|
||||||
@@ -492,7 +512,7 @@ namespace rct {
|
|||||||
ar.end_array();
|
ar.end_array();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
|
if (type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
ar.tag("CLSAGs");
|
ar.tag("CLSAGs");
|
||||||
ar.begin_array();
|
ar.begin_array();
|
||||||
@@ -538,7 +558,7 @@ namespace rct {
|
|||||||
ar.begin_array();
|
ar.begin_array();
|
||||||
// we keep a byte for size of MGs, because we don't know whether this is
|
// we keep a byte for size of MGs, because we don't know whether this is
|
||||||
// a simple or full rct signature, and it's starting to annoy the hell out of me
|
// a simple or full rct signature, and it's starting to annoy the hell out of me
|
||||||
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? inputs : 1;
|
size_t mg_elements = (type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeSimpleBulletproof) ? inputs : 1;
|
||||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
|
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_elements, MGs);
|
||||||
if (MGs.size() != mg_elements)
|
if (MGs.size() != mg_elements)
|
||||||
return false;
|
return false;
|
||||||
@@ -556,7 +576,7 @@ namespace rct {
|
|||||||
for (size_t j = 0; j < mixin + 1; ++j)
|
for (size_t j = 0; j < mixin + 1; ++j)
|
||||||
{
|
{
|
||||||
ar.begin_array();
|
ar.begin_array();
|
||||||
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2) ? 1 : inputs) + 1;
|
size_t mg_ss2_elements = ((type == RCTTypeSimple || type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeSimpleBulletproof) ? 1 : inputs) + 1;
|
||||||
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
|
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mg_ss2_elements, MGs[i].ss[j]);
|
||||||
if (MGs[i].ss[j].size() != mg_ss2_elements)
|
if (MGs[i].ss[j].size() != mg_ss2_elements)
|
||||||
return false;
|
return false;
|
||||||
@@ -583,7 +603,7 @@ namespace rct {
|
|||||||
}
|
}
|
||||||
ar.end_array();
|
ar.end_array();
|
||||||
}
|
}
|
||||||
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus)
|
if (type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeSimpleBulletproof || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
ar.tag("pseudoOuts");
|
ar.tag("pseudoOuts");
|
||||||
ar.begin_array();
|
ar.begin_array();
|
||||||
@@ -615,12 +635,12 @@ namespace rct {
|
|||||||
|
|
||||||
keyV& get_pseudo_outs()
|
keyV& get_pseudo_outs()
|
||||||
{
|
{
|
||||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
|
return type == RCTTypeBulletproof || type == RCTTypeSimpleBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeBulletproofPlus_FullCommit ? p.pseudoOuts : pseudoOuts;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyV const& get_pseudo_outs() const
|
keyV const& get_pseudo_outs() const
|
||||||
{
|
{
|
||||||
return type == RCTTypeBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus ? p.pseudoOuts : pseudoOuts;
|
return type == RCTTypeBulletproof || type == RCTTypeSimpleBulletproof || type == RCTTypeBulletproof2 || type == RCTTypeCLSAG || type == RCTTypeBulletproofPlus || type == RCTTypeBulletproofPlus_FullCommit ? p.pseudoOuts : pseudoOuts;
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_SERIALIZE_OBJECT()
|
BEGIN_SERIALIZE_OBJECT()
|
||||||
@@ -732,9 +752,13 @@ namespace rct {
|
|||||||
|
|
||||||
bool is_rct_simple(int type);
|
bool is_rct_simple(int type);
|
||||||
bool is_rct_bulletproof(int type);
|
bool is_rct_bulletproof(int type);
|
||||||
bool is_rct_bulletproof_plus(int type);
|
bool is_rct_old_bulletproof(int type);
|
||||||
|
bool is_rct_new_bulletproof(int type);
|
||||||
bool is_rct_borromean(int type);
|
bool is_rct_borromean(int type);
|
||||||
bool is_rct_clsag(int type);
|
bool is_rct_clsag(int type);
|
||||||
|
bool is_rct_bp_plus_legacy(int type);
|
||||||
|
bool is_rct_bp_plus_full(int type);
|
||||||
|
bool is_rct_bulletproof_plus_any(int type);
|
||||||
|
|
||||||
static inline const rct::key &pk2rct(const crypto::public_key &pk) { return (const rct::key&)pk; }
|
static inline const rct::key &pk2rct(const crypto::public_key &pk) { return (const rct::key&)pk; }
|
||||||
static inline const rct::key &sk2rct(const crypto::secret_key &sk) { return (const rct::key&)sk; }
|
static inline const rct::key &sk2rct(const crypto::secret_key &sk) { return (const rct::key&)sk; }
|
||||||
|
|||||||
@@ -1939,6 +1939,7 @@ uint64_t WalletImpl::estimateTransactionFee(const std::vector<std::pair<std::str
|
|||||||
m_wallet->use_fork_rules(8, 0),
|
m_wallet->use_fork_rules(8, 0),
|
||||||
m_wallet->use_fork_rules(HF_VERSION_CLSAG, 0),
|
m_wallet->use_fork_rules(HF_VERSION_CLSAG, 0),
|
||||||
m_wallet->use_fork_rules(HF_VERSION_BULLETPROOF_PLUS, 0),
|
m_wallet->use_fork_rules(HF_VERSION_BULLETPROOF_PLUS, 0),
|
||||||
|
m_wallet->use_fork_rules(HF_VERSION_BP_PLUS_FULL_COMMIT, 0),
|
||||||
m_wallet->use_fork_rules(HF_VERSION_VIEW_TAGS, 0),
|
m_wallet->use_fork_rules(HF_VERSION_VIEW_TAGS, 0),
|
||||||
m_wallet->get_base_fee(priority),
|
m_wallet->get_base_fee(priority),
|
||||||
m_wallet->get_fee_quantization_mask());
|
m_wallet->get_fee_quantization_mask());
|
||||||
|
|||||||
@@ -789,7 +789,7 @@ void drop_from_short_history(std::list<crypto::hash> &short_chain_history, size_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags)
|
size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool bulletproof_plus_full_commit, bool use_view_tags)
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
@@ -813,12 +813,12 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra
|
|||||||
size += 1;
|
size += 1;
|
||||||
|
|
||||||
// rangeSigs
|
// rangeSigs
|
||||||
if (bulletproof || bulletproof_plus)
|
if (bulletproof || bulletproof_plus || bulletproof_plus_full_commit)
|
||||||
{
|
{
|
||||||
size_t log_padded_outputs = 0;
|
size_t log_padded_outputs = 0;
|
||||||
while ((1<<log_padded_outputs) < n_outputs)
|
while ((1<<log_padded_outputs) < n_outputs)
|
||||||
++log_padded_outputs;
|
++log_padded_outputs;
|
||||||
size += (2 * (6 + log_padded_outputs) + (bulletproof_plus ? 6 : (4 + 5))) * 32 + 3;
|
size += (2 * (6 + log_padded_outputs) + (bulletproof_plus_full_commit ? 6 : bulletproof_plus ? 6 : (4 + 5))) * 32 + 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
size += (2*64*32+32+64*32) * n_outputs;
|
size += (2*64*32+32+64*32) * n_outputs;
|
||||||
@@ -844,29 +844,29 @@ size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs, size_t extra
|
|||||||
// txnFee
|
// txnFee
|
||||||
size += 4;
|
size += 4;
|
||||||
|
|
||||||
LOG_PRINT_L2("estimated " << (bulletproof_plus ? "bulletproof plus" : bulletproof ? "bulletproof" : "borromean") << " rct tx size for " << n_inputs << " inputs with ring size " << (mixin+1) << " and " << n_outputs << " outputs: " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)");
|
LOG_PRINT_L2("estimated " << (bulletproof_plus_full_commit ? "bulletproof plus full commit" : bulletproof_plus ? "bulletproof plus" : bulletproof ? "bulletproof" : "borromean") << " rct tx size for " << n_inputs << " inputs with ring size " << (mixin+1) << " and " << n_outputs << " outputs: " << size << " (" << ((32 * n_inputs/*+1*/) + 2 * 32 * (mixin+1) * n_inputs + 32 * n_outputs) << " saved)");
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags)
|
size_t estimate_tx_size(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool bulletproof_plus_full_commit, bool use_view_tags)
|
||||||
{
|
{
|
||||||
if (use_rct)
|
if (use_rct)
|
||||||
return estimate_rct_tx_size(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
return estimate_rct_tx_size(n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
else
|
else
|
||||||
return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size + (use_view_tags ? (n_outputs * sizeof(crypto::view_tag)) : 0);
|
return n_inputs * (mixin+1) * APPROXIMATE_INPUT_BYTES + extra_size + (use_view_tags ? (n_outputs * sizeof(crypto::view_tag)) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags)
|
uint64_t estimate_tx_weight(bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool bulletproof_plus_full_commit, bool use_view_tags)
|
||||||
{
|
{
|
||||||
size_t size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
size_t size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
if (use_rct && (bulletproof || bulletproof_plus) && n_outputs > 2)
|
if (use_rct && (bulletproof || bulletproof_plus || bulletproof_plus_full_commit) && n_outputs > 2)
|
||||||
{
|
{
|
||||||
const uint64_t bp_base = (32 * ((bulletproof_plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
|
const uint64_t bp_base = (32 * ((bulletproof_plus_full_commit ? 6 : bulletproof_plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
|
||||||
size_t log_padded_outputs = 2;
|
size_t log_padded_outputs = 2;
|
||||||
while ((1<<log_padded_outputs) < n_outputs)
|
while ((1<<log_padded_outputs) < n_outputs)
|
||||||
++log_padded_outputs;
|
++log_padded_outputs;
|
||||||
uint64_t nlr = 2 * (6 + log_padded_outputs);
|
uint64_t nlr = 2 * (6 + log_padded_outputs);
|
||||||
const uint64_t bp_size = 32 * ((bulletproof_plus ? 6 : 9) + nlr);
|
const uint64_t bp_size = 32 * ((bulletproof_plus_full_commit ? 6 : bulletproof_plus ? 6 : 9) + nlr);
|
||||||
const uint64_t bp_clawback = (bp_base * (1<<log_padded_outputs) - bp_size) * 4 / 5;
|
const uint64_t bp_clawback = (bp_base * (1<<log_padded_outputs) - bp_size) * 4 / 5;
|
||||||
MDEBUG("clawback on size " << size << ": " << bp_clawback);
|
MDEBUG("clawback on size " << size << ": " << bp_clawback);
|
||||||
size += bp_clawback;
|
size += bp_clawback;
|
||||||
@@ -884,6 +884,11 @@ uint8_t get_bulletproof_plus_fork()
|
|||||||
return HF_VERSION_BULLETPROOF_PLUS;
|
return HF_VERSION_BULLETPROOF_PLUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t get_bulletproof_plus_full_commit_fork()
|
||||||
|
{
|
||||||
|
return HF_VERSION_BP_PLUS_FULL_COMMIT;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t get_clsag_fork()
|
uint8_t get_clsag_fork()
|
||||||
{
|
{
|
||||||
return HF_VERSION_CLSAG;
|
return HF_VERSION_CLSAG;
|
||||||
@@ -2195,12 +2200,15 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &
|
|||||||
switch (rv.type)
|
switch (rv.type)
|
||||||
{
|
{
|
||||||
case rct::RCTTypeSimple:
|
case rct::RCTTypeSimple:
|
||||||
|
case rct::RCTTypeSimpleBulletproof:
|
||||||
case rct::RCTTypeBulletproof:
|
case rct::RCTTypeBulletproof:
|
||||||
case rct::RCTTypeBulletproof2:
|
case rct::RCTTypeBulletproof2:
|
||||||
case rct::RCTTypeCLSAG:
|
case rct::RCTTypeCLSAG:
|
||||||
case rct::RCTTypeBulletproofPlus:
|
case rct::RCTTypeBulletproofPlus:
|
||||||
|
case rct::RCTTypeBulletproofPlus_FullCommit:
|
||||||
return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
return rct::decodeRctSimple(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||||
case rct::RCTTypeFull:
|
case rct::RCTTypeFull:
|
||||||
|
case rct::RCTTypeFullBulletproof:
|
||||||
return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask, hwdev);
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unsupported rct type: " << rv.type);
|
LOG_ERROR("Unsupported rct type: " << rv.type);
|
||||||
@@ -8523,16 +8531,16 @@ bool wallet2::sign_multisig_tx_from_file(const std::string &filename, std::vecto
|
|||||||
return sign_multisig_tx_to_file(exported_txs, filename, txids);
|
return sign_multisig_tx_to_file(exported_txs, filename, txids);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask)
|
uint64_t wallet2::estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool bulletproof_plus_full_commit, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask)
|
||||||
{
|
{
|
||||||
if (use_per_byte_fee)
|
if (use_per_byte_fee)
|
||||||
{
|
{
|
||||||
const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t estimated_tx_weight = estimate_tx_weight(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_quantization_mask);
|
return calculate_fee_from_weight(base_fee, estimated_tx_weight, fee_quantization_mask);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t estimated_tx_size = estimate_tx_size(use_rct, n_inputs, mixin, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
return calculate_fee(base_fee, estimated_tx_size);
|
return calculate_fee(base_fee, estimated_tx_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11167,6 +11175,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
const bool use_rct = use_fork_rules(4, 0);
|
const bool use_rct = use_fork_rules(4, 0);
|
||||||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
||||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
||||||
|
const bool bulletproof_plus_full_commit = use_fork_rules(get_bulletproof_plus_full_commit_fork(), 0);
|
||||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
||||||
const rct::RCTConfig rct_config {
|
const rct::RCTConfig rct_config {
|
||||||
rct::RangeProofPaddedBulletproof,
|
rct::RangeProofPaddedBulletproof,
|
||||||
@@ -11215,7 +11224,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
// early out if we know we can't make it anyway
|
// early out if we know we can't make it anyway
|
||||||
// we could also check for being within FEE_PER_KB, but if the fee calculation
|
// we could also check for being within FEE_PER_KB, but if the fee calculation
|
||||||
// ever changes, this might be missed, so let this go through
|
// ever changes, this might be missed, so let this go through
|
||||||
const uint64_t min_fee = (base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags));
|
const uint64_t min_fee = (base_fee * estimate_tx_size(use_rct, 1, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags));
|
||||||
total_needed_money = needed_money + (subtract_fee_from_outputs.size() ? 0 : min_fee);
|
total_needed_money = needed_money + (subtract_fee_from_outputs.size() ? 0 : min_fee);
|
||||||
uint64_t balance_subtotal = 0;
|
uint64_t balance_subtotal = 0;
|
||||||
uint64_t unlocked_balance_subtotal = 0;
|
uint64_t unlocked_balance_subtotal = 0;
|
||||||
@@ -11234,8 +11243,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
LOG_PRINT_L2("Candidate subaddress index for spending: " << i);
|
LOG_PRINT_L2("Candidate subaddress index for spending: " << i);
|
||||||
|
|
||||||
// determine threshold for fractional amount
|
// determine threshold for fractional amount
|
||||||
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
||||||
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
||||||
const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||||
@@ -11329,7 +11338,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
{
|
{
|
||||||
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
// this is used to build a tx that's 1 or 2 inputs, and 2 outputs, which
|
||||||
// will get us a known fee.
|
// will get us a known fee.
|
||||||
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
|
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags, base_fee, fee_quantization_mask);
|
||||||
total_needed_money = needed_money + (subtract_fee_from_outputs.size() ? 0 : estimated_fee);
|
total_needed_money = needed_money + (subtract_fee_from_outputs.size() ? 0 : estimated_fee);
|
||||||
preferred_inputs = pick_preferred_rct_inputs(total_needed_money, subaddr_account, subaddr_indices);
|
preferred_inputs = pick_preferred_rct_inputs(total_needed_money, subaddr_account, subaddr_indices);
|
||||||
if (!preferred_inputs.empty())
|
if (!preferred_inputs.empty())
|
||||||
@@ -11442,7 +11451,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags) < TX_WEIGHT_TARGET(upper_transaction_weight_limit))
|
while (!dsts.empty() && dsts[0].amount <= available_amount && estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags) < TX_WEIGHT_TARGET(upper_transaction_weight_limit))
|
||||||
{
|
{
|
||||||
// we can fully pay that destination
|
// we can fully pay that destination
|
||||||
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
LOG_PRINT_L2("We can fully pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
||||||
@@ -11462,7 +11471,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!out_slots_exhausted && available_amount > 0 && !dsts.empty() &&
|
if (!out_slots_exhausted && available_amount > 0 && !dsts.empty() &&
|
||||||
estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) {
|
estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags) < TX_WEIGHT_TARGET(upper_transaction_weight_limit)) {
|
||||||
// we can partially fill that destination
|
// we can partially fill that destination
|
||||||
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
LOG_PRINT_L2("We can partially pay " << get_account_address_as_str(m_nettype, dsts[0].is_subaddress, dsts[0].addr) <<
|
||||||
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
|
" for " << print_money(available_amount) << "/" << print_money(dsts[0].amount));
|
||||||
@@ -11501,7 +11510,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
try_tx = dsts.empty() || (estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit));
|
try_tx = dsts.empty() || (estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit));
|
||||||
THROW_WALLET_EXCEPTION_IF(try_tx && tx.dsts.empty(), error::tx_too_big, estimated_rct_tx_weight, upper_transaction_weight_limit);
|
THROW_WALLET_EXCEPTION_IF(try_tx && tx.dsts.empty(), error::tx_too_big, estimated_rct_tx_weight, upper_transaction_weight_limit);
|
||||||
}
|
}
|
||||||
@@ -11512,7 +11521,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
|||||||
pending_tx test_ptx;
|
pending_tx test_ptx;
|
||||||
|
|
||||||
const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers);
|
const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers);
|
||||||
needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
|
needed_fee = estimate_fee(use_per_byte_fee, use_rct ,tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags, base_fee, fee_quantization_mask);
|
||||||
|
|
||||||
auto try_carving_from_partial_payment = [&](uint64_t needed_fee, uint64_t available_for_fee)
|
auto try_carving_from_partial_payment = [&](uint64_t needed_fee, uint64_t available_for_fee)
|
||||||
{
|
{
|
||||||
@@ -11820,11 +11829,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
|||||||
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
|
const bool use_per_byte_fee = use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
|
||||||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
||||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
||||||
|
const bool bulletproof_plus_full_commit = use_fork_rules(get_bulletproof_plus_full_commit_fork(), 0);
|
||||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
||||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||||
const uint64_t base_fee = get_base_fee(priority);
|
const uint64_t base_fee = get_base_fee(priority);
|
||||||
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t tx_weight_one_ring = estimate_tx_weight(use_rct, 1, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t tx_weight_two_rings = estimate_tx_weight(use_rct, 2, fake_outs_count, 2, 0, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
||||||
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
||||||
const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
const uint64_t fractional_threshold = (base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||||
@@ -11933,6 +11943,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0);
|
const bool use_rct = fake_outs_count > 0 && use_fork_rules(4, 0);
|
||||||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
||||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
||||||
|
const bool bulletproof_plus_full_commit = use_fork_rules(get_bulletproof_plus_full_commit_fork(), 0);
|
||||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
||||||
const rct::RCTConfig rct_config {
|
const rct::RCTConfig rct_config {
|
||||||
rct::RangeProofPaddedBulletproof,
|
rct::RangeProofPaddedBulletproof,
|
||||||
@@ -11965,7 +11976,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
uint64_t fee_dust_threshold;
|
uint64_t fee_dust_threshold;
|
||||||
if (use_fork_rules(HF_VERSION_PER_BYTE_FEE))
|
if (use_fork_rules(HF_VERSION_PER_BYTE_FEE))
|
||||||
{
|
{
|
||||||
const uint64_t estimated_tx_weight_with_one_extra_output = estimate_tx_weight(use_rct, tx.selected_transfers.size() + 1, fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const uint64_t estimated_tx_weight_with_one_extra_output = estimate_tx_weight(use_rct, tx.selected_transfers.size() + 1, fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_quantization_mask);
|
fee_dust_threshold = calculate_fee_from_weight(base_fee, estimated_tx_weight_with_one_extra_output, fee_quantization_mask);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -11996,7 +12007,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
// here, check if we need to sent tx and start a new one
|
// here, check if we need to sent tx and start a new one
|
||||||
LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
|
LOG_PRINT_L2("Considering whether to create a tx now, " << tx.selected_transfers.size() << " inputs, tx limit "
|
||||||
<< upper_transaction_weight_limit);
|
<< upper_transaction_weight_limit);
|
||||||
const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags);
|
const size_t estimated_rct_tx_weight = estimate_tx_weight(use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size() + 2, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit));
|
bool try_tx = (unused_dust_indices.empty() && unused_transfers_indices.empty()) || ( estimated_rct_tx_weight >= TX_WEIGHT_TARGET(upper_transaction_weight_limit));
|
||||||
|
|
||||||
if (try_tx) {
|
if (try_tx) {
|
||||||
@@ -12004,7 +12015,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
|||||||
pending_tx test_ptx;
|
pending_tx test_ptx;
|
||||||
|
|
||||||
const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers);
|
const size_t num_outputs = get_num_outputs(tx.dsts, m_transfers, tx.selected_transfers);
|
||||||
needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
|
needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, num_outputs, extra.size(), bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags, base_fee, fee_quantization_mask);
|
||||||
|
|
||||||
// add N - 1 outputs for correct initial fee estimation
|
// add N - 1 outputs for correct initial fee estimation
|
||||||
for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i)
|
for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i)
|
||||||
@@ -12853,8 +12864,10 @@ void wallet2::check_tx_key_helper(const cryptonote::transaction &tx, const crypt
|
|||||||
crypto::secret_key scalar1;
|
crypto::secret_key scalar1;
|
||||||
crypto::derivation_to_scalar(found_derivation, n, scalar1);
|
crypto::derivation_to_scalar(found_derivation, n, scalar1);
|
||||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
||||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
const rct::key C = tx.rct_signatures.outPk[n].mask;
|
rct::key C = tx.rct_signatures.outPk[n].mask;
|
||||||
|
if (rct::is_rct_bp_plus_legacy(tx.rct_signatures.type))
|
||||||
|
C = rct::scalarmult8(C);
|
||||||
rct::key Ctmp;
|
rct::key Ctmp;
|
||||||
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask");
|
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.mask.bytes) != 0, error::wallet_internal_error, "Bad ECDH input mask");
|
||||||
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.amount.bytes) != 0, error::wallet_internal_error, "Bad ECDH input amount");
|
THROW_WALLET_EXCEPTION_IF(sc_check(ecdh_info.amount.bytes) != 0, error::wallet_internal_error, "Bad ECDH input amount");
|
||||||
@@ -13543,7 +13556,7 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr
|
|||||||
crypto::secret_key shared_secret;
|
crypto::secret_key shared_secret;
|
||||||
crypto::derivation_to_scalar(derivation, proof.index_in_tx, shared_secret);
|
crypto::derivation_to_scalar(derivation, proof.index_in_tx, shared_secret);
|
||||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[proof.index_in_tx];
|
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[proof.index_in_tx];
|
||||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
rct::ecdhDecode(ecdh_info, rct::sk2rct(shared_secret), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
amount = rct::h2d(ecdh_info.amount);
|
amount = rct::h2d(ecdh_info.amount);
|
||||||
}
|
}
|
||||||
total += amount;
|
total += amount;
|
||||||
@@ -16199,10 +16212,11 @@ std::pair<size_t, uint64_t> wallet2::estimate_tx_size_and_weight(bool use_rct, i
|
|||||||
|
|
||||||
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
const bool bulletproof = use_fork_rules(get_bulletproof_fork(), 0);
|
||||||
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
const bool bulletproof_plus = use_fork_rules(get_bulletproof_plus_fork(), 0);
|
||||||
|
const bool bulletproof_plus_full_commit = use_fork_rules(get_bulletproof_plus_full_commit_fork(), 0);
|
||||||
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
const bool clsag = use_fork_rules(get_clsag_fork(), 0);
|
||||||
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
const bool use_view_tags = use_fork_rules(get_view_tag_fork(), 0);
|
||||||
size_t size = estimate_tx_size(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
size_t size = estimate_tx_size(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
uint64_t weight = estimate_tx_weight(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, use_view_tags);
|
uint64_t weight = estimate_tx_weight(use_rct, n_inputs, ring_size - 1, n_outputs, extra_size, bulletproof, clsag, bulletproof_plus, bulletproof_plus_full_commit, use_view_tags);
|
||||||
return std::make_pair(size, weight);
|
return std::make_pair(size, weight);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1665,7 +1665,7 @@ private:
|
|||||||
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(const std::vector<std::pair<double, double>> &fee_levels);
|
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(const std::vector<std::pair<double, double>> &fee_levels);
|
||||||
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(uint64_t min_tx_weight, uint64_t max_tx_weight, const std::vector<uint64_t> &fees);
|
std::vector<std::pair<uint64_t, uint64_t>> estimate_backlog(uint64_t min_tx_weight, uint64_t max_tx_weight, const std::vector<uint64_t> &fees);
|
||||||
|
|
||||||
static uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask);
|
static uint64_t estimate_fee(bool use_per_byte_fee, bool use_rct, int n_inputs, int mixin, int n_outputs, size_t extra_size, bool bulletproof, bool clsag, bool bulletproof_plus, bool bulletproof_plus_full_commit, bool use_view_tags, uint64_t base_fee, uint64_t fee_quantization_mask);
|
||||||
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm = -1);
|
uint64_t get_fee_multiplier(uint32_t priority, int fee_algorithm = -1);
|
||||||
uint64_t get_base_fee(uint32_t priority);
|
uint64_t get_base_fee(uint32_t priority);
|
||||||
uint64_t get_base_fee();
|
uint64_t get_base_fee();
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ bool gen_bpp_tx_validation_base::check_bpp(const cryptonote::transaction &tx, si
|
|||||||
{
|
{
|
||||||
DEFINE_TESTS_ERROR_CONTEXT(context);
|
DEFINE_TESTS_ERROR_CONTEXT(context);
|
||||||
CHECK_TEST_CONDITION(tx.version >= 2);
|
CHECK_TEST_CONDITION(tx.version >= 2);
|
||||||
CHECK_TEST_CONDITION(rct::is_rct_bulletproof_plus(tx.rct_signatures.type));
|
CHECK_TEST_CONDITION(rct::is_rct_bulletproof_plus_any(tx.rct_signatures.type));
|
||||||
size_t n_sizes = 0, n_amounts = 0;
|
size_t n_sizes = 0, n_amounts = 0;
|
||||||
for (size_t n = 0; n < tx_idx; ++n)
|
for (size_t n = 0; n < tx_idx; ++n)
|
||||||
{
|
{
|
||||||
@@ -312,7 +312,7 @@ bool gen_bpp_tx_invalid_not_enough_proofs::generate(std::vector<test_event_entry
|
|||||||
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
|
const uint64_t amounts_paid[] = {5000, 5000, (uint64_t)-1};
|
||||||
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
||||||
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
||||||
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
||||||
tx.rct_signatures.p.bulletproofs_plus.pop_back();
|
tx.rct_signatures.p.bulletproofs_plus.pop_back();
|
||||||
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
||||||
@@ -327,7 +327,7 @@ bool gen_bpp_tx_invalid_empty_proofs::generate(std::vector<test_event_entry>& ev
|
|||||||
const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1};
|
const uint64_t amounts_paid[] = {50000, 50000, (uint64_t)-1};
|
||||||
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
||||||
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
||||||
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
tx.rct_signatures.p.bulletproofs_plus.clear();
|
tx.rct_signatures.p.bulletproofs_plus.clear();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -340,7 +340,7 @@ bool gen_bpp_tx_invalid_too_many_proofs::generate(std::vector<test_event_entry>&
|
|||||||
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
|
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
|
||||||
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
||||||
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
||||||
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
||||||
tx.rct_signatures.p.bulletproofs_plus.push_back(tx.rct_signatures.p.bulletproofs_plus.back());
|
tx.rct_signatures.p.bulletproofs_plus.push_back(tx.rct_signatures.p.bulletproofs_plus.back());
|
||||||
return true;
|
return true;
|
||||||
@@ -354,7 +354,7 @@ bool gen_bpp_tx_invalid_wrong_amount::generate(std::vector<test_event_entry>& ev
|
|||||||
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
|
const uint64_t amounts_paid[] = {10000, (uint64_t)-1};
|
||||||
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
const rct::RCTConfig rct_config[] = { { rct::RangeProofBulletproof, 4 } };
|
||||||
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
return generate_with(events, mixin, 1, amounts_paid, false, rct_config, HF_VERSION_BULLETPROOF_PLUS, NULL, [&](cryptonote::transaction &tx, size_t idx){
|
||||||
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
CHECK_TEST_CONDITION(tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
CHECK_TEST_CONDITION(!tx.rct_signatures.p.bulletproofs_plus.empty());
|
||||||
tx.rct_signatures.p.bulletproofs_plus.back() = rct::bulletproof_plus_PROVE(1000, rct::skGen());
|
tx.rct_signatures.p.bulletproofs_plus.back() = rct::bulletproof_plus_PROVE(1000, rct::skGen());
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -434,8 +434,10 @@ bool gen_multisig_tx_validation_base::generate_with(std::vector<test_event_entry
|
|||||||
crypto::secret_key scalar1;
|
crypto::secret_key scalar1;
|
||||||
crypto::derivation_to_scalar(derivation, n, scalar1);
|
crypto::derivation_to_scalar(derivation, n, scalar1);
|
||||||
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
rct::ecdhTuple ecdh_info = tx.rct_signatures.ecdhInfo[n];
|
||||||
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus);
|
rct::ecdhDecode(ecdh_info, rct::sk2rct(scalar1), tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus_FullCommit);
|
||||||
rct::key C = tx.rct_signatures.outPk[n].mask;
|
rct::key C = tx.rct_signatures.outPk[n].mask;
|
||||||
|
if (rct::is_rct_bp_plus_legacy(tx.rct_signatures.type))
|
||||||
|
C = rct::scalarmult8(C);
|
||||||
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
|
rct::addKeys2(Ctmp, ecdh_info.mask, ecdh_info.amount, rct::H);
|
||||||
CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount");
|
CHECK_AND_ASSERT_MES(rct::equalKeys(C, Ctmp), false, "Failed to decode amount");
|
||||||
amount += rct::h2d(ecdh_info.amount);
|
amount += rct::h2d(ecdh_info.amount);
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ static void expand_tsx(cryptonote::transaction &tx)
|
|||||||
rv.p.MGs[n].II[0] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
rv.p.MGs[n].II[0] = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus)
|
else if (rv.type == rct::RCTTypeCLSAG || rv.type == rct::RCTTypeBulletproofPlus || rv.type == rct::RCTTypeBulletproofPlus_FullCommit)
|
||||||
{
|
{
|
||||||
if (!tx.pruned)
|
if (!tx.pruned)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user