aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_basic')
-rw-r--r--src/cryptonote_basic/account.cpp5
-rw-r--r--src/cryptonote_basic/account.h1
-rw-r--r--src/cryptonote_basic/cryptonote_boost_serialization.h32
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp68
4 files changed, 85 insertions, 21 deletions
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index 36ff41684..9927351a9 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -253,11 +253,6 @@ DISABLE_VS_WARNINGS(4244 4345)
return crypto::secret_key_to_public_key(view_secret_key, m_keys.m_account_address.m_view_public_key);
}
//-----------------------------------------------------------------
- void account_base::finalize_multisig(const crypto::public_key &spend_public_key)
- {
- m_keys.m_account_address.m_spend_public_key = spend_public_key;
- }
- //-----------------------------------------------------------------
const account_keys& account_base::get_keys() const
{
return m_keys;
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
index 5288b9b04..96b024c3c 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -82,7 +82,6 @@ namespace cryptonote
void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey);
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);
- void finalize_multisig(const crypto::public_key &spend_public_key);
const account_keys& get_keys() const;
std::string get_public_address_str(network_type nettype) const;
std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const;
diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h
index c6b81b094..24d452083 100644
--- a/src/cryptonote_basic/cryptonote_boost_serialization.h
+++ b/src/cryptonote_basic/cryptonote_boost_serialization.h
@@ -228,6 +228,20 @@ namespace boost
}
template <class Archive>
+ inline void serialize(Archive &a, rct::BulletproofPlus &x, const boost::serialization::version_type ver)
+ {
+ a & x.V;
+ a & x.A;
+ a & x.A1;
+ a & x.B;
+ a & x.r1;
+ a & x.s1;
+ a & x.d1;
+ a & x.L;
+ a & x.R;
+ }
+
+ template <class Archive>
inline void serialize(Archive &a, rct::boroSig &x, const boost::serialization::version_type ver)
{
a & x.s0;
@@ -305,7 +319,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
return;
- if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG)
+ 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)
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.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@@ -321,7 +335,11 @@ namespace boost
{
a & x.rangeSigs;
if (x.rangeSigs.empty())
+ {
a & x.bulletproofs;
+ if (ver >= 2u)
+ a & x.bulletproofs_plus;
+ }
a & x.MGs;
if (ver >= 1u)
a & x.CLSAGs;
@@ -335,7 +353,7 @@ namespace boost
a & x.type;
if (x.type == rct::RCTTypeNull)
return;
- if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeCLSAG)
+ 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)
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.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
@@ -347,11 +365,15 @@ namespace boost
//--------------
a & x.p.rangeSigs;
if (x.p.rangeSigs.empty())
+ {
a & x.p.bulletproofs;
+ if (ver >= 2u)
+ a & x.p.bulletproofs_plus;
+ }
a & x.p.MGs;
if (ver >= 1u)
a & x.p.CLSAGs;
- if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG)
+ if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeCLSAG || x.type == rct::RCTTypeBulletproofPlus)
a & x.p.pseudoOuts;
}
@@ -392,6 +414,6 @@ namespace boost
}
}
-BOOST_CLASS_VERSION(rct::rctSigPrunable, 1)
-BOOST_CLASS_VERSION(rct::rctSig, 1)
+BOOST_CLASS_VERSION(rct::rctSigPrunable, 2)
+BOOST_CLASS_VERSION(rct::rctSig, 2)
BOOST_CLASS_VERSION(rct::multisig_out, 1)
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 17adcdc35..cedc6f546 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -105,7 +105,9 @@ namespace cryptonote
uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
{
- const uint64_t bp_base = 368;
+ const rct::rctSig &rv = tx.rct_signatures;
+ const bool plus = rv.type == rct::RCTTypeBulletproofPlus;
+ 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();
if (n_padded_outputs <= 2)
return 0;
@@ -113,7 +115,7 @@ namespace cryptonote
while ((1u << nlr) < n_padded_outputs)
++nlr;
nlr += 6;
- const size_t bp_size = 32 * (9 + 2 * nlr);
+ const size_t bp_size = 32 * ((plus ? 6 : 9) + 2 * nlr);
CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(BULLETPROOF_MAX_OUTPUTS) + " per transaction");
CHECK_AND_ASSERT_THROW_MES_L1(bp_base * n_padded_outputs >= bp_size, "Invalid bulletproof clawback: bp_base " + std::to_string(bp_base) + ", n_padded_outputs "
+ std::to_string(n_padded_outputs) + ", bp_size " + std::to_string(bp_size));
@@ -164,7 +166,32 @@ namespace cryptonote
if (!base_only)
{
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
- if (bulletproof)
+ const bool bulletproof_plus = rct::is_rct_bulletproof_plus(rv.type);
+ if (bulletproof_plus)
+ {
+ if (rv.p.bulletproofs_plus.size() != 1)
+ {
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs_plus size in tx " << get_transaction_hash(tx));
+ return false;
+ }
+ if (rv.p.bulletproofs_plus[0].L.size() < 6)
+ {
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs_plus L size in tx " << get_transaction_hash(tx));
+ return false;
+ }
+ const size_t max_outputs = rct::n_bulletproof_plus_max_amounts(rv.p.bulletproofs_plus[0]);
+ if (max_outputs < tx.vout.size())
+ {
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs_plus max outputs in tx " << get_transaction_hash(tx));
+ return false;
+ }
+ const size_t n_amounts = tx.vout.size();
+ CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
+ rv.p.bulletproofs_plus[0].V.resize(n_amounts);
+ for (size_t i = 0; i < n_amounts; ++i)
+ rv.p.bulletproofs_plus[0].V[i] = rv.outPk[i].mask;
+ }
+ else if (bulletproof)
{
if (rv.p.bulletproofs.size() != 1)
{
@@ -306,7 +333,26 @@ namespace cryptonote
{
// derive secret key with subaddress - step 1: original CN derivation
crypto::secret_key scalar_step1;
- hwdev.derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b
+ crypto::secret_key spend_skey = crypto::null_skey;
+
+ if (ack.m_multisig_keys.empty())
+ {
+ // if not multisig, use normal spend skey
+ spend_skey = ack.m_spend_secret_key;
+ }
+ else
+ {
+ // if multisig, use sum of multisig privkeys (local account's share of aggregate spend key)
+ for (const auto &multisig_key : ack.m_multisig_keys)
+ {
+ sc_add((unsigned char*)spend_skey.data,
+ (const unsigned char*)multisig_key.data,
+ (const unsigned char*)spend_skey.data);
+ }
+ }
+
+ // computes Hs(a*R || idx) + b
+ hwdev.derive_secret_key(recv_derivation, real_output_index, spend_skey, scalar_step1);
// step 2: add Hs(a || index_major || index_minor)
crypto::secret_key subaddr_sk;
@@ -400,9 +446,11 @@ namespace cryptonote
if (tx.version < 2)
return blob_size;
const rct::rctSig &rv = tx.rct_signatures;
- if (!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);
+ if (!bulletproof && !bulletproof_plus)
return blob_size;
- const size_t n_padded_outputs = 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);
CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow");
return blob_size + bp_clawback;
@@ -412,8 +460,8 @@ 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.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,
- std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support older range proof types");
+ CHECK_AND_ASSERT_MES(tx.rct_signatures.type == rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG || tx.rct_signatures.type == rct::RCTTypeBulletproofPlus,
+ 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[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
@@ -431,12 +479,12 @@ namespace cryptonote
while ((n_padded_outputs = (1u << nrl)) < tx.vout.size())
++nrl;
nrl += 6;
- extra = 32 * (9 + 2 * nrl) + 2;
+ extra = 32 * ((rct::is_rct_bulletproof_plus(tx.rct_signatures.type) ? 6 : 9) + 2 * nrl) + 2;
weight += extra;
// calculate deterministic CLSAG/MLSAG data size
const size_t ring_size = boost::get<cryptonote::txin_to_key>(tx.vin[0]).key_offsets.size();
- if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
+ if (rct::is_rct_clsag(tx.rct_signatures.type))
extra = tx.vin.size() * (ring_size + 2) * 32;
else
extra = tx.vin.size() * (ring_size * (1 + 1) * 32 + 32 /* cc */);