Compare commits

..

2 Commits

Author SHA1 Message Date
Some Random Crypto Guy e2bc467618 fixed key image calculation for return_payment outputs 2025-08-05 21:11:22 +01:00
Some Random Crypto Guy cb3f1905ed updated SPARC code to support one-way payment channels, ready for Salvium Two smart contracts 2025-08-05 12:27:20 +01:00
39 changed files with 339 additions and 611 deletions
+5 -5
View File
@@ -1,4 +1,4 @@
# Salvium One v1.0.0
# Salvium Zero v0.9.9
Copyright (c) 2023-2024, Salvium
Portions Copyright (c) 2014-2023, The Monero Project
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
```bash
cd salvium
git checkout v1.0.0
git checkout v0.9.9
make
```
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/salvium/salvium
cd salvium
git checkout v1.0.0
git checkout v0.9.9
```
* Build:
@@ -370,10 +370,10 @@ application.
cd salvium
```
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v1.0.0'. If you don't care about the version and just want binaries from master, skip this step:
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.9.9'. If you don't care about the version and just want binaries from master, skip this step:
```bash
git checkout v1.0.0
git checkout v0.9.9
```
* If you are on a 64-bit system, run:
+1 -1
View File
@@ -238,7 +238,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
LOG_PRINT_L1("Failed to get output unlock time, aborting transaction addition");
throw std::runtime_error("Unexpected error getting output unlock_time, aborting");
}
if (miner_tx && tx.version >= 2)
if (miner_tx && tx.version == 2)
{
cryptonote::tx_out vout = tx.vout[i];
// TODO: avoid multiple expensive zeroCommitVartime call here + get_outs_by_last_locked_block + ver_non_input_consensus
+1 -1
View File
@@ -208,8 +208,8 @@ typedef struct yield_tx_info {
} yield_tx_info;
typedef struct yield_tx_info_carrot {
uint64_t block_height;
uint8_t version;
uint64_t block_height;
crypto::hash tx_hash;
uint64_t locked_coins;
crypto::public_key return_address;
-51
View File
@@ -315,55 +315,6 @@ crypto::secret_key carrot_and_legacy_account::generate(
return retval;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::set_keys(const cryptonote::account_keys& keys, bool copy_spend_secret_keys)
{
// CN keys
m_keys.m_account_address = keys.m_account_address;
if (copy_spend_secret_keys) m_keys.m_spend_secret_key = keys.m_spend_secret_key;
m_keys.m_view_secret_key = keys.m_view_secret_key;
if (copy_spend_secret_keys) m_keys.m_multisig_keys = keys.m_multisig_keys;
m_keys.m_device = keys.m_device;
m_keys.m_encryption_iv = keys.m_encryption_iv;
// Carrot keys
if (copy_spend_secret_keys) m_keys.s_master = keys.s_master;
if (copy_spend_secret_keys) m_keys.k_prove_spend = keys.k_prove_spend;
m_keys.s_view_balance = keys.s_view_balance;
m_keys.k_view_incoming = keys.k_view_incoming;
m_keys.k_generate_image = keys.k_generate_image;
m_keys.s_generate_address = keys.s_generate_address;
m_keys.m_carrot_account_address = keys.m_carrot_account_address;
m_keys.m_carrot_main_address = keys.m_carrot_main_address;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::create_from_svb_key(const cryptonote::account_public_address& address, const crypto::secret_key& svb_key)
{
// top level keys
m_keys.s_master = crypto::null_skey;
make_carrot_provespend_key(m_keys.s_master, m_keys.k_prove_spend);
m_keys.s_view_balance = svb_key;
// view balance keys
make_carrot_viewincoming_key(m_keys.s_view_balance, m_keys.k_view_incoming);
make_carrot_generateimage_key(m_keys.s_view_balance, m_keys.k_generate_image);
make_carrot_generateaddress_secret(m_keys.s_view_balance, m_keys.s_generate_address);
// carrot account address - use the provided address spend pubkey
m_keys.m_carrot_account_address = address;
k_view_incoming_dev.view_key_scalar_mult_ed25519(m_keys.m_carrot_account_address.m_spend_public_key,
m_keys.m_carrot_account_address.m_view_public_key
);
// carrot main wallet address
m_keys.m_carrot_main_address = address;
k_view_incoming_dev.view_key_scalar_mult_ed25519(crypto::get_G(),
m_keys.m_carrot_main_address.m_view_public_key
);
this->default_derive_type = AddressDeriveType::Carrot;
generate_subaddress_map();
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_derive_type)
{
// top level keys
@@ -382,7 +333,6 @@ void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_
m_keys.m_carrot_account_address.m_spend_public_key,
m_keys.m_carrot_account_address.m_view_public_key
);
m_keys.m_carrot_account_address.m_is_carrot = true;
// carrot main wallet address
m_keys.m_carrot_main_address.m_spend_public_key = m_keys.m_carrot_account_address.m_spend_public_key;
@@ -390,7 +340,6 @@ void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_
crypto::get_G(),
m_keys.m_carrot_main_address.m_view_public_key
);
m_keys.m_carrot_main_address.m_is_carrot = true;
this->default_derive_type = default_derive_type;
generate_subaddress_map();
-54
View File
@@ -52,16 +52,6 @@ namespace carrot
crypto::secret_key x;
crypto::secret_key y;
return_output_info_t() {
// Default constructor for serialization
input_context = input_context_t();
K_o = crypto::public_key();
K_change = crypto::public_key();
key_image = crypto::key_image();
x = crypto::secret_key();
y = crypto::secret_key();
}
return_output_info_t(
const input_context_t &input_context,
const crypto::public_key &K_o,
@@ -75,15 +65,6 @@ namespace carrot
key_image(key_image),
x(x),
y(y) {}
BEGIN_SERIALIZE_OBJECT()
FIELD(input_context)
FIELD(K_o)
FIELD(K_change)
FIELD(key_image)
FIELD(x)
FIELD(y)
END_SERIALIZE()
};
@@ -101,8 +82,6 @@ namespace carrot
s_generate_address_dev(get_keys().s_generate_address)
{}
void set_keys(const cryptonote::account_keys& keys, bool copy_spend_secret_keys);
carrot_and_legacy_account(const carrot_and_legacy_account &k) = delete;
carrot_and_legacy_account(carrot_and_legacy_account&&) = delete;
@@ -153,7 +132,6 @@ namespace carrot
const AddressDeriveType default_derive_type = AddressDeriveType::Carrot
);
void create_from_svb_key(const cryptonote::account_public_address& address, const crypto::secret_key& svb_key);
void set_carrot_keys(const AddressDeriveType default_derive_type = AddressDeriveType::Carrot);
void insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map);
void insert_return_output_info(
@@ -168,35 +146,3 @@ namespace carrot
std::unordered_map<crypto::public_key, return_output_info_t> return_output_map;
};
}
namespace boost
{
namespace serialization
{
template <class Archive>
inline typename std::enable_if<!Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
{
}
template <class Archive>
inline typename std::enable_if<Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
{
x.input_context = carrot::input_context_t();
x.K_o = crypto::public_key();
x.K_change = crypto::public_key();
x.key_image = crypto::key_image();
x.x = crypto::secret_key();
x.y = crypto::secret_key();
}
template <class Archive>
inline void serialize(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
{
a & x.input_context;
a & x.K_o;
a & x.K_change;
a & x.key_image;
a & x.x;
a & x.y;
}
}
}
+2 -1
View File
@@ -70,10 +70,11 @@ static constexpr const unsigned char CARROT_DOMAIN_SEP_SUBADDRESS_SCALAR[] = "Ca
static constexpr const unsigned int CARROT_MIN_TX_OUTPUTS = 2;
static constexpr const unsigned int CARROT_MAX_TX_OUTPUTS = 8;
static constexpr const unsigned int CARROT_MIN_TX_INPUTS = 1;
static constexpr const unsigned int CARROT_MAX_TX_INPUTS = 64;
static constexpr const unsigned int CARROT_MAX_TX_INPUTS = 128;
// SPARC addressing protocol domain separators
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_PUBKEY_ENCRYPTION_MASK[] = "SPARC return pubkey encryption mask";
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_ADDRESS_SCALAR[] = "SPARC return address scalar";
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_INDEX_SCALAR[] = "SPARC return index scalar";
} //namespace carrot
+34 -12
View File
@@ -211,6 +211,17 @@ void make_sparc_return_privkey(const unsigned char s_sender_receiver_unctx[32],
derive_scalar(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_privkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_sparc_return_index(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const crypto::public_key &onetime_address,
const uint64_t idx,
crypto::secret_key &return_index_out)
{
// k_return = H_32(s_sr || input_context || Ko)
const auto transcript = sp::make_fixed_transcript<SPARC_DOMAIN_SEP_RETURN_INDEX_SCALAR>(input_context, onetime_address, idx);
derive_scalar(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_index_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const crypto::public_key &onetime_address,
@@ -222,22 +233,33 @@ void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_recei
}
//-------------------------------------------------------------------------------------------------------------------
void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
encrypted_return_pubkey_t &return_pubkey_out)
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
const uint64_t idx,
encrypted_return_pubkey_t &return_enc_pubkey_out)
{
// K_return = k_return G ^ m_return
// K_return = k_return G + k_idx T
crypto::secret_key k_return;
crypto::public_key return_pub;
encrypted_return_pubkey_t K_return;
encrypted_return_pubkey_t m_return;
crypto::secret_key k_idx = crypto::null_skey;
encrypted_return_pubkey_t return_pub;
s_view_balance_dev->make_internal_return_privkey(input_context, onetime_address, k_return);
crypto::secret_key_to_public_key(k_return, return_pub);
static_assert(sizeof(K_return.bytes) == sizeof(return_pub.data), "Size mismatch");
memcpy(K_return.bytes, return_pub.data, sizeof(encrypted_return_pubkey_t));
make_sparc_return_index(to_bytes(onetime_address), input_context, onetime_address, idx, k_idx);
rct::key K_return;
rct::addKeys2(K_return,
rct::sk2rct(k_return),
rct::sk2rct(k_idx),
rct::pk2rct(crypto::get_T()));
//K_return = rct::scalarmult8(K_return);
if (!rct::isInMainSubgroup(K_return))
throw std::runtime_error("K_return is not in main subgroup");
static_assert(sizeof(K_return.bytes) == sizeof(return_pub.bytes), "Size mismatch");
memcpy(return_pub.bytes, K_return.bytes, sizeof(encrypted_return_pubkey_t));
// return_enc = return_pub ^ m_return
encrypted_return_pubkey_t m_return;
make_sparc_return_pubkey_encryption_mask(s_sender_receiver_unctx, input_context, onetime_address, m_return);
return_pubkey_out = K_return ^ m_return;
return_enc_pubkey_out = return_pub ^ m_return;
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
+20 -4
View File
@@ -138,6 +138,20 @@ void make_sparc_return_privkey(const unsigned char s_sender_receiver_unctx[32],
const crypto::public_key &onetime_address,
crypto::secret_key &return_privkey_out);
/**
* brief: make_sparc_return_index - return k_idx, given non-secret data
* k_idx = H_32(s_sr || input_context || Ko || idx)
* param: s_sender_receiver_unctx - s_sr
* param: input_context - input_context
* param: onetime_address - Ko
* param: idx
* outparam: return_index_out - k_idx
*/
void make_sparc_return_index(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const crypto::public_key &onetime_address,
const uint64_t idx,
crypto::secret_key &return_index_out);
/**
* brief: make_sparc_return_pubkey_encryption_mask - used for hiding return pubkey
* m_return = H_32(s_sr || input_context || Ko)
* param: s_sender_receiver_unctx - s_sr
@@ -156,13 +170,15 @@ void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_recei
* param: input_context - input_context
* param: s_view_balance_dev - s_vb
* param: onetime_address - Ko
* param: idx
* outparam: return_pubkey_mask_out - K_return
*/
void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
encrypted_return_pubkey_t &return_pubkey_out);
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
const uint64_t idx,
encrypted_return_pubkey_t &return_pubkey_out);
/**
* brief: make_carrot_input_context_coinbase - input context for a sender-receiver secret (coinbase txs)
* input_context = "C" || IntToBytes256(block_index)
+8 -8
View File
@@ -216,7 +216,7 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
// construct normal enotes
for (size_t i = 0; i < normal_payment_proposals.size(); ++i)
{
auto &output_entry = sortable_data.emplace_back();
auto &output_entry = tools::add_element(sortable_data);
output_entry.second = {false, i};
encrypted_payment_id_t encrypted_payment_id;
@@ -270,7 +270,7 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
{
const CarrotPaymentProposalSelfSendV1 &selfsend_payment_proposal = selfsend_payment_proposals.at(i);
auto &output_entry = sortable_data.emplace_back();
auto &output_entry = tools::add_element(sortable_data);
output_entry.second = {true, i};
if (s_view_balance_dev != nullptr)
@@ -361,11 +361,11 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
component_out_of_order, "this set contains duplicate onetime addresses");
// assert all K_o lie in prime order subgroup
// for (const RCTOutputEnoteProposal &output_enote_proposal : output_enote_proposals_out)
// {
// CARROT_CHECK_AND_THROW(rct::isInMainSubgroup(rct::pk2rct(output_enote_proposal.enote.onetime_address)),
// invalid_point, "this set contains an invalid onetime address");
// }
for (const RCTOutputEnoteProposal &output_enote_proposal : output_enote_proposals_out)
{
CARROT_CHECK_AND_THROW(rct::isInMainSubgroup(rct::pk2rct(output_enote_proposal.enote.onetime_address)),
invalid_point, "this set contains an invalid onetime address");
}
// assert unique and non-trivial k_a
memcmp_set<crypto::secret_key> amount_blinding_factors;
@@ -416,7 +416,7 @@ void get_coinbase_output_enotes(const std::vector<CarrotPaymentProposalV1> &norm
{
get_coinbase_output_proposal_v1(normal_payment_proposals[i],
block_index,
output_coinbase_enotes_out.emplace_back());
tools::add_element(output_coinbase_enotes_out));
}
// assert uniqueness and non-trivial-ness of D_e
+5 -4
View File
@@ -208,10 +208,11 @@ static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_re
// 4. construct the return pubkey
if (s_view_balance_dev != nullptr)
make_sparc_return_pubkey(s_sender_receiver_unctx.data,
input_context,
s_view_balance_dev,
onetime_address_out,
return_pubkey_out);
input_context,
s_view_balance_dev,
onetime_address_out,
0/*idx*/,
return_pubkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
+22 -6
View File
@@ -34,6 +34,11 @@
//local headers
#include "destination.h"
#include "enote_utils.h"
extern "C"
{
#include "crypto/crypto-ops.h"
}
#include "crypto/generators.h"
#include "ringct/rctOps.h"
#include "scan_unsafe.h"
@@ -508,20 +513,31 @@ bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
const carrot::input_context_t input_context = carrot::make_carrot_input_context(enote.tx_first_key_image);
account.s_view_balance_dev.make_internal_return_privkey(input_context, output_key, k_return);
// compute K_return = k_return * G
crypto::public_key K_return;
crypto::secret_key_to_public_key(k_return, K_return);
// make k_idx
crypto::secret_key k_idx = crypto::null_skey;
uint64_t idx = 0;
make_sparc_return_index(to_bytes(output_key), input_context, output_key, idx, k_idx);
// compute K_return = k_return * G + k_idx * T
rct::key K_return;
rct::addKeys2(K_return,
rct::sk2rct(k_return),
rct::sk2rct(k_idx),
rct::pk2rct(crypto::get_T()));
//K_return = rct::scalarmult8(K_return);
// compute K_r = K_return + K_o
crypto::public_key K_r = rct::rct2pk(rct::addKeys(rct::pk2rct(K_return), rct::pk2rct(enote.onetime_address)));
crypto::public_key K_r = rct::rct2pk(rct::addKeys(K_return, rct::pk2rct(enote.onetime_address)));
// calculate the key image for the return output
crypto::secret_key sum_g;
sc_add(to_bytes(sum_g), to_bytes(sender_extension_g_out), to_bytes(k_return));
crypto::secret_key sum_t;
sc_add(to_bytes(sum_t), to_bytes(sender_extension_t_out), to_bytes(k_idx));
crypto::key_image key_image = account.derive_key_image(
account.get_keys().m_carrot_account_address.m_spend_public_key,
sum_g,
sender_extension_t_out,
sum_t,
K_r
);
@@ -529,7 +545,7 @@ bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
account.try_searching_for_opening_for_onetime_address(
account.get_keys().m_carrot_account_address.m_spend_public_key,
sum_g,
sender_extension_t_out,
sum_t,
x,
y
);
+3 -2
View File
@@ -33,6 +33,7 @@
#include "carrot_core/enote_utils.h"
#include "carrot_core/exceptions.h"
#include "carrot_core/payment_proposal.h"
#include "common/container_helpers.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "cryptonote_config.h"
@@ -257,7 +258,7 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
}});
//a_enc
rct::ecdhTuple &ecdh_tuple = tx.rct_signatures.ecdhInfo.emplace_back();
rct::ecdhTuple &ecdh_tuple = tools::add_element(tx.rct_signatures.ecdhInfo);
memcpy(ecdh_tuple.amount.bytes, enote.amount_enc.bytes, sizeof(ecdh_tuple.amount));
//C_a
@@ -420,7 +421,7 @@ cryptonote::transaction store_carrot_to_coinbase_transaction_v1(
cryptonote::transaction tx;
tx.type = tx_type;
tx.pruned = false;
tx.version = TRANSACTION_VERSION_CARROT;
tx.version = 2;
tx.unlock_time = CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
tx.vin.reserve(1);
tx.vout.reserve(nouts);
+18 -12
View File
@@ -318,27 +318,33 @@ std::vector<std::size_t> get_input_counts_in_preferred_order()
// 1 or 2 randomly, then
// other ascending powers of 2, then
// other ascending positive numbers
//! @TODO: MRL discussion about 2 vs 1 default input count when 1 input can pay. If we default
// to 1, then that may reveal more information about the amount, and reveals that one can't pay
// with 1 output when using 2. Vice versa, if we default to 2, then that means that one only
// owns 1 output when using 1. It may be the most advantageous to randomly switch between
// preferring 1 vs 2. See: https://lavalle.pl/planning/node437.html. Con to this approach: if we
// default to 1 over 2 always then there's scenarios where we net save tx fees and proving time.
//static_assert(CARROT_MAX_TX_INPUTS == FCMP_PLUS_PLUS_MAX_INPUTS, "inconsistent input count max limit");
static_assert(CARROT_MIN_TX_INPUTS == 1 && CARROT_MAX_TX_INPUTS == 64,
// preferring 1 vs 2. See: https://lavalle.pl/planning/node437.html. Con to this approach: if we
// default to 1 over 2 always then there's scenarios where we net save tx fees and proving time.
//static_assert(CARROT_MAX_TX_INPUTS == FCMP_PLUS_PLUS_MAX_INPUTS, "inconsistent input count max limit");
static_assert(CARROT_MIN_TX_INPUTS == 1 && CARROT_MAX_TX_INPUTS == 128,
"refactor this function for different input count limits");
const bool random_bit = 0 == (crypto::rand<uint8_t>() & 0x01);
if (random_bit)
return {2, 1, 4, 8, 16, 32, 64, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
return {2, 1, 4, 8, 16, 32, 64, 128, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
else
return {1, 2, 4, 8, 16, 32, 64, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
return {1, 2, 4, 8, 16, 32, 64, 128, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
}
//-------------------------------------------------------------------------------------------------------------------
select_inputs_func_t make_single_transfer_input_selector(
+9 -10
View File
@@ -331,6 +331,15 @@ void make_carrot_transaction_proposal_v1_transfer(
selfsend_payment_proposals.back().proposal.amount =
boost::numeric_cast<rct::xmr_amount>(implicit_change_amount);
// remove the self send payment we have made to ourself now that we have our change payment.
if (tx_type == cryptonote::transaction_type::STAKE ||
tx_type == cryptonote::transaction_type::BURN)
{
selfsend_payment_proposals.back().proposal.enote_ephemeral_pubkey =
selfsend_payment_proposals.front().proposal.enote_ephemeral_pubkey;
selfsend_payment_proposals.erase(selfsend_payment_proposals.begin());
}
// deduct an even fee amount from all subtractable outputs
const size_t num_subtractble_normal = subtractable_normal_payment_proposals.size();
const size_t num_subtractable_selfsend = subtractable_selfsend_payment_proposals.size();
@@ -394,16 +403,6 @@ void make_carrot_transaction_proposal_v1_transfer(
CHECK_AND_ASSERT_THROW_MES(fee_remainder == 0,
"make unsigned transaction transfer subtractable: bug: fee remainder at end of carve function");
// remove the self send payment we have made to ourself now that we have our change payment.
if (tx_type == cryptonote::transaction_type::STAKE ||
tx_type == cryptonote::transaction_type::BURN)
{
selfsend_payment_proposals.back().proposal.enote_ephemeral_pubkey =
selfsend_payment_proposals.front().proposal.enote_ephemeral_pubkey;
selfsend_payment_proposals.erase(selfsend_payment_proposals.begin());
}
}; //end carve_fees_and_balance
// make unsigned transaction with fee carving callback
+7
View File
@@ -138,6 +138,13 @@ bool keys_match_internal_values(const std::unordered_map<KeyT, ValueT> &map, Pre
return true;
}
/// convenience wrapper for getting the last element after emplacing back
template <typename ContainerT>
typename ContainerT::value_type& add_element(ContainerT &container)
{
container.emplace_back();
return container.back();
}
/// convenience erasor for unordered maps: std::erase_if(std::unordered_map) is C++20
template <typename KeyT, typename ValueT, typename PredT>
void for_all_in_map_erase_if(std::unordered_map<KeyT, ValueT> &map_inout, PredT predicate)
-3
View File
@@ -151,8 +151,6 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_base::forget_spend_key()
{
m_keys.m_spend_secret_key = crypto::secret_key();
m_keys.s_master = m_keys.m_spend_secret_key;
m_keys.k_prove_spend = m_keys.m_spend_secret_key;
m_keys.m_multisig_keys.clear();
}
//-----------------------------------------------------------------
@@ -165,7 +163,6 @@ DISABLE_VS_WARNINGS(4244 4345)
"Unexpected derived public spend key");
m_keys.m_spend_secret_key = spend_secret_key;
m_keys.s_master = m_keys.m_spend_secret_key;
}
//-----------------------------------------------------------------
crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
@@ -73,11 +73,6 @@ namespace boost
a & reinterpret_cast<char (&)[sizeof(crypto::key_image)]>(x);
}
template <class Archive>
inline void serialize(Archive &a, carrot::input_context_t &x, const boost::serialization::version_type ver)
{
a & reinterpret_cast<char (&)[sizeof(carrot::input_context_t)]>(x);
}
template <class Archive>
inline void serialize(Archive &a, crypto::view_tag &x, const boost::serialization::version_type ver)
{
a & reinterpret_cast<char (&)[sizeof(crypto::view_tag)]>(x);
@@ -1381,31 +1381,17 @@ namespace cryptonote
for (const auto &o: tx.vout)
{
if (hf_version >= HF_VERSION_ENFORCE_CARROT)
if (hf_version >= HF_VERSION_CARROT)
{
// from v10, require outputs be carrot outputs
// from v11, require outputs be carrot outputs
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx));
} else if (hf_version >= HF_VERSION_CARROT) {
if (tx.type != cryptonote::transaction_type::PROTOCOL) {
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx));
} else {
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key) ||
o.target.type() == typeid(txout_to_tagged_key) ||
o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_key or txout_to_tagged_key or txout_to_carrot_v1 in protocol transaction");
// require all outputs in a tx be of the same type
CHECK_AND_ASSERT_MES(o.target.type() == tx.vout[0].target.type(), false, "non-matching variant types: "
<< o.target.type().name() << " and " << tx.vout[0].target.type().name() << ", "
<< "expected matching variant types in protocol transaction");
}
}
else {
} else {
// require outputs be of type txout_to_key OR txout_to_tagged_key
// to allow grace period before requiring all to be txout_to_tagged_key
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_to_tagged_key), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_key or txout_to_tagged_key in transaction");
// require all outputs in a tx be of the same type
CHECK_AND_ASSERT_MES(o.target.type() == tx.vout[0].target.type(), false, "non-matching variant types: "
<< o.target.type().name() << " and " << tx.vout[0].target.type().name() << ", "
+17 -18
View File
@@ -244,14 +244,13 @@
#define HF_VERSION_AUDIT2 8
#define HF_VERSION_AUDIT2_PAUSE 9
#define HF_VERSION_CARROT 10
#define HF_VERSION_ENFORCE_CARROT 11
#define HF_VERSION_REQUIRE_VIEW_TAGS 255
#define HF_VERSION_ENABLE_CONVERT 255
#define HF_VERSION_ENABLE_ORACLE 255
#define HF_VERSION_SLIPPAGE_YIELD 255
#define TESTNET_VERSION 15
#define TESTNET_VERSION 14
#define STAGENET_VERSION 1
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
@@ -432,22 +431,22 @@ namespace config
// treasury payout {tx-key, output-key, anchor_enc, vie_tag} tuples
const std::map<uint64_t, std::tuple<std::string, std::string, std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_DATA = {
{1100, {"0d82afb3ae9c5de25a06da49e24e64d37ba05d6144f9f6153cea325c61407106","81440913c1484891d25010986806a62d1fae1b2fe045e3ac1396413638d594f1","40864bbf80397c05516368a1397eb5c3","220bda"}},
{1120, {"a032f2de4d3b5d880d3a636d9786a4a2f586bee360c323bc7521f987a2ada51b","cf8e5eeb5d37996d86c9c4c88fabaabc1ec77bab9cd5ce610a61b49f1e079ce2","9877a989e0216f76a8cdf0a568e57d45","017549"}},
{1140, {"51da7a4c34aa20a800ada615a931fbba5fd1b9f7df78f0f911097ad9d99dc230","dd784a5bf1adf9c01cb44946ca094ed4d38f8d9cccf8edfdab397db3b7631dbf","97314be452f184b54f16a558ee8a7dbe","357ac3"}},
{1160, {"a0cf49118c62cea834fabae83e12f26939ce170f308adadacf7275226e5cdf6d","7ec9cb2dfac8dfa45bab1bab2b1e31a4291a9e3d939e9c193740cc191d1b720d","4e950acc71ffd4f3835ec79202dc46fd","e7da3a"}},
{1180, {"5193e35f6cd3ff8408a442be5eaf4aa1871419ecb0c485546e9d995c4c9c2730","39fb9792b88290b3377036a150a6681334ebe5cb201e2005d2c1d7b212b3df4d","cb458163806a277c7b3513df0d5b0028","1939b5"}},
{1200, {"a2c71a7381bc48576f4cb4313cb6264d2a6e82cd2ddcbbd5460bce1db8d5021e","d0c46f29f4bbdd5538d64a438c0ab93cb0586e67fbfc7d1671f0c9809d6a7fac","af38cc2ddccb9229728ef704e360e15a","8a8dc1"}},
{1220, {"8358105081510e907c98da59636eef777460513d827aba400efbb81d82aead4c","b2b8e2f9bb13e7527d0ee1bc3ebf0ca5057139ee4f9302251455b9f27dca3b16","dc226161830e952b2533fe34b1dd3c48","fb7c67"}},
{1240, {"90b0bc153b97a93eefd59af9b47d26c0c91aadda6203de91a15f2f76fc949074","06e6a11b8742ee78beafe89f894fb9078a514ee6dd4e099182ac982ead37eacc","4fbfd0f3c2b8d514f2c675b37b9f0b6f","3308ad"}},
{1260, {"cd10148b3175804b17e3c68a6a5556364d585dee89953904b32f005a5f6d8f14","d9d6f64119776e9c97fe2fb540cdb5f40bea0c40127fda0f1f2b831cb7fa7d2b","9c21b83d29324e2d91774a623219ae28","1d647c"}},
{1280, {"5963697782de7db5111d12c853f3fec0dd53f597d80cc376c7945f1d4afa224b","cc5e5b1273c10016dc855ec1d9bfa0bcf4736a748125f5341717ad9d080fbba0","19dd1f9a0cac118564e2ccb9f36be53a","7ab2c2"}},
{1300, {"cf1d4d2d21b7b3f1a54889e0688a4654687e28a302a2ac3ad046ac2ad323f97a","5b5926da5e9199f190e86073ebd09ccb867faf1e9887c9e52a47c194915b2575","5775fa47af3c7226f2ec3017470410c9","2b03b3"}},
{1320, {"b565ec8842f3e6c22c7a23eb23f0e5684b462d2261681dff7b2ce71ab02ff170","4f94cf4d811574c9fcc27888cc972ebc6c01ae97146b9882d397b77c9232d1fd","9d142686627c918a26b6c6853b911143","685b18"}},
{1340, {"50d1b1bcacf36ba14b23b3827e36a02a7610dd3199a9f1b9d0a23ebcbd1c2d54","38818e41cf0ce7d54391978801c58087ddd5fe517dadb5e61d840f27a7a81a52","55328f4bff5120d44c5d76fc5a9dfdbd","d17be2"}},
{1360, {"7657bf97a9be9beac5f999a1e2c1226613849c41c12df5d7185d4d6613a27328","63d96a47f29fab0e727d13905cc843df40ccb76b14dc48857d0dd9ec0873e8c5","ab4f7ffa6431452f0fac7eec33e89e3e","5acd14"}},
{1380, {"845e4cbe9b9d2462fae2225da698d6a4e18340f06b312545ee9cfda8127abd41","cc65f1f22f863b31f3c4a53ac3987186c2a699f387a2bf08d8dfed54037912c6","bda3aa3bdd2b42e8183c1013e4350c98","d4a418"}},
{1400, {"4b11413fcba49df61537427ff35fdd47ee12a8467751236ff22681bbea343d2c","32d22bba59559489f422298ae653ef55ec8c87e8705daf4c89da7187c8574cbd","8868e1c1d788ce4560beb4afbe77aa5a","5a35d9"}}
{1100, {"310fe378b82e2475a87c83eef07c57d92fa0731d5c499258e774852158276968","f17c5a62efcc96710f2a173538fe5e79b190b44ab6facc01a619f0e227ac18d1","eb613855f58d093ae9d527e8ab69b46a","6c74f9"}},
{1120, {"adb74cea72d46ebe5a45e5886189e71c493308686f076ccfc053cb9b4f55b656","b40e958589238cc48a5a7f03f1f28406a13b2f724efe831cfec43c06bb0fcb60","77a51cc3a6c3c53d631cadad72f57c1d","e5fec0"}},
{1140, {"c5e9a67c695ddcab05b980de0c8cc7d9d5b9c09af58047843bfd7d29a038f671","6c3253bd837b899b87aedc97114feb9c10c2d255ce59b7ba5b470817a37d16df","fcf6e1907ea30dbafd510e33a37cc2dc","fa5c45"}},
{1160, {"e95c8b7fc3d0e7e34d544e97d3b526e94f70acb7d85cb0053b3cb830e863ac38","3a5ae93e922985ea1a126ff8fd35f6cbf39fa556525e15a049765510eb1360e1","7ea6d62add9387a28f3dbed5dbac120b","c26ac2"}},
{1180, {"9d453235a25e470df2d7ceaa8f8d4216a8939a0a93bc0c43f1b902cb461ee82d","2e990ed2de4d745389d88aa9868634ce430f09d2c0cb5ebc2ee8b9bcc23e221a","807e07241a48b97acb537241822a97b8","eb37c0"}},
{1200, {"92dbd7da158d4bcb4f002dcc505ed4c49ac4e4782724b506a5977119c80c4869","4505a9be31c2ac6ad5faa2ea8332b85b1a3efee84d0456740d208b8188ad842a","8870c1f88de25b5443d8323759f386d9","443c65"}},
{1220, {"1e4d5c44a112c3ac89ab2c7065bb2c8c094779b3a5d696652198f7dd05f88b77","01f56bf134652852688e30dd9559bdb5fe2edd046bed99dbea23b655d2475b89","da088fc1e1c2f2d0e348f06f2079e8ed","d7c7bf"}},
{1240, {"91ba144c930a65996b2d7c3b296217c692225756392b580a323838e48b357452","f2d5f4f2aaa599a52c557270cbc5cde138b753a98297d975b74a7223a9b80b13","0dc3a42cb1f36768a09c316790936356","172c22"}},
{1260, {"1d626ede8d2e34e888384655b30942a25be272a3ea58d49835265e6933a91a52","05666de1b136236f0682e128c0c3ae84578a6a4b233a578dd676e581a582fe19","c81ccf7f93e01e7872543907de8d17d0","21dd94"}},
{1280, {"85b10b5ae72ab59281f47be4edede17b7a017dc7ddd839813e3a12c0b2a39874","d34d259e2fee2b0c977242c473cf83997920c1e64ff7a9c364b2bf4abba4d5cc","43de6ce100ca3eeb6734fc44cc9f7dbc","574e2f"}},
{1300, {"c699ca0dcbe538e6be9e997acb50a4c13557d1e8cf3a105ab47406cb68300656","50c5e0fa60907c2c2b66748562193b7f5bfcba269eb398c5c975c9e125933942","05aeb41f8863152a7e0e36f216ecbb12","e413dd"}},
{1320, {"76bb126d6e0e5d3d7ee7ccabd194a248cbe006ae7d57f89c31c6826f8e7b4851","e1f2277b378630d92bc03003e3d206899404afde342fcb3a9b1790f798c8b5a4","26274ad1bbf5d483f2c747754b898873","a2df70"}},
{1340, {"5738dc94686bfffe1789b695785f270f6f616b1a52e071e975cf915063233b1a","982b4848ed74f2a5d899f778b182c35f40535579349435b466ff98c3fce678e7","67bd9b9a434b9028564a065a30ae34fa","36ceec"}},
{1360, {"473b6f6941d6eafaef007d3d932763b6e39c1428d3ba76dfff452ddc67f93b48","76e3b1280b959672d86c357e6f5fcd8a74e61a0a948a0541a0eb384060705bac","74b5ad8847471e3d8723ad3e101b8a13","5e5671"}},
{1380, {"6dae9a14e24b96caf8f7acb0edad936a4ecaa194a61b3785a2b1d08cbca0a158","26ca204c10481ed2447447e3893e0c46c9f01df16c3f3a671cf9e6054176ee5d","7c04e4ed28bfac12a0050bdae44f9979","4c23ad"}},
{1400, {"a5837480d8e17ddb9b29baaf5671545d59d18b546de0d7092768882cff94d125","dc76eb3892b3721da947fc71de8ab30ef32651f1b6bb1a45eb7b80882217a5ac","bb490940a3cdf4a17fd0bec0b578531f","84d899"}}
};
}
+35 -93
View File
@@ -1348,11 +1348,6 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
CHECK_AND_ASSERT_MES(b.miner_tx.version > 1, false, "Invalid coinbase transaction version");
if (hf_version >= HF_VERSION_CARROT) {
CHECK_AND_ASSERT_MES(b.miner_tx.version == TRANSACTION_VERSION_CARROT, false, "miner transaction has wrong version");
CHECK_AND_ASSERT_MES(b.miner_tx.type == cryptonote::transaction_type::MINER, false, "miner transaction has wrong type");
}
// for v2 txes (ringct), we only accept empty rct signatures for miner transactions,
if (hf_version >= HF_VERSION_REJECT_SIGS_IN_COINBASE && b.miner_tx.version >= 2)
{
@@ -1403,16 +1398,6 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh
CHECK_AND_ASSERT_MES(b.protocol_tx.vin[0].type() == typeid(txin_gen), false, "coinbase protocol transaction in the block has the wrong type");
CHECK_AND_ASSERT_MES(b.protocol_tx.version > 1, false, "Invalid coinbase protocol transaction version");
if (hf_version >= HF_VERSION_CARROT) {
CHECK_AND_ASSERT_MES(b.protocol_tx.version == TRANSACTION_VERSION_CARROT || 2, false, "protocol transaction has wrong version");
CHECK_AND_ASSERT_MES(b.protocol_tx.type == cryptonote::transaction_type::PROTOCOL, false, "protocol transaction has wrong type");
}
if (hf_version >= HF_VERSION_ENFORCE_CARROT) {
CHECK_AND_ASSERT_MES(b.protocol_tx.version == TRANSACTION_VERSION_CARROT, false, "protocol transaction has wrong version");
CHECK_AND_ASSERT_MES(b.protocol_tx.type == cryptonote::transaction_type::PROTOCOL, false, "protocol transaction has wrong type");
}
// for v2 txes (ringct), we only accept empty rct signatures for protocol transactions,
if (hf_version >= HF_VERSION_REJECT_SIGS_IN_COINBASE && b.protocol_tx.version >= 2)
{
@@ -1521,7 +1506,6 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
case HF_VERSION_AUDIT2:
case HF_VERSION_AUDIT2_PAUSE:
case HF_VERSION_CARROT:
case HF_VERSION_ENFORCE_CARROT:
if (b.miner_tx.amount_burnt > 0) {
CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt");
money_in_use += b.miner_tx.amount_burnt;
@@ -1589,7 +1573,7 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
LOG_PRINT_L1("Block at height: " << height << " - no yield payouts due - skipping");
} else {
// Iterate over the cached data for block yield, calculating the yield payouts due
if (get_ideal_hard_fork_version(matured_height) >= HF_VERSION_CARROT) {
if (hf_version >= HF_VERSION_CARROT) {
if (!calculate_yield_payouts(matured_height, carrot_yield_payouts)) {
LOG_ERROR("Block at height: " << height << " - Failed to obtain carrot yield payout information - aborting");
return false;
@@ -1637,7 +1621,7 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
);
if (hf_version >= HF_VERSION_CARROT) {
// TODO: add other verifications for carrot yield payouts
size_t output_idx = 0;
for (auto it = carrot_yield_payouts.begin(); it != carrot_yield_payouts.end(); it++, output_idx++) {
// Verify the output key
@@ -1645,16 +1629,6 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
cryptonote::get_output_public_key(b.protocol_tx.vout[output_idx], out_key);
CHECK_AND_ASSERT_MES(out_key == it->first.return_address, false, "Incorrect output key detected in protocol_tx");
// Verify the return pubkey
if (b.protocol_tx.vout.size() > 1) {
const auto additional_pubkeys = cryptonote::get_additional_tx_pub_keys_from_extra(b.protocol_tx.extra);
CHECK_AND_ASSERT_MES(additional_pubkeys.size() > output_idx, false, "Missing return pubkey detected in protocol_tx");
CHECK_AND_ASSERT_MES(additional_pubkeys[output_idx] == it->first.return_pubkey, false, "Incorrect return pubkey detected in protocol_tx");
} else {
const auto main_pubkey = cryptonote::get_tx_pub_key_from_extra(b.protocol_tx.extra);
CHECK_AND_ASSERT_MES(main_pubkey == it->first.return_pubkey, false, "Incorrect return pubkey detected in protocol_tx");
}
// Verify the output amount
uint64_t expected_amount = it->second;
CHECK_AND_ASSERT_MES(b.protocol_tx.vout[output_idx].amount == expected_amount, false, "Incorrect output amount detected in protocol_tx. expected_amount: " << expected_amount);
@@ -1662,21 +1636,11 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
// Verify the output asset type
std::string out_asset_type;
cryptonote::get_output_asset_type(b.protocol_tx.vout[output_idx], out_asset_type);
CHECK_AND_ASSERT_MES(out_asset_type == "SAL1", false, "Incorrect output asset_type (!= SAL1) detected in protocol_tx");
// Verify the view tag
CHECK_AND_ASSERT_MES(
boost::get<cryptonote::txout_to_carrot_v1>(
b.protocol_tx.vout[output_idx].target
).view_tag == it->first.return_view_tag, false, "Incorrect view tag detected in protocol_tx"
);
// Verify the anchor encrypted
CHECK_AND_ASSERT_MES(
boost::get<cryptonote::txout_to_carrot_v1>(
b.protocol_tx.vout[output_idx].target
).encrypted_janus_anchor == it->first.return_anchor_enc, false, "Incorrect anchor detected in protocol_tx"
);
uint8_t hf_yield = m_hardfork->get_ideal_version(it->first.block_height);
if (hf_yield >= HF_VERSION_SALVIUM_ONE_PROOFS)
CHECK_AND_ASSERT_MES(out_asset_type == "SAL1", false, "Incorrect output asset_type (!= SAL1) detected in protocol_tx");
else
CHECK_AND_ASSERT_MES(out_asset_type == "SAL", false, "Incorrect output asset_type (!= SAL) detected in protocol_tx");
}
return true;
@@ -1987,14 +1951,11 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
cryptonote::yield_block_info ybi_matured;
bool ok = get_ybi_entry(start_height, ybi_matured);
if (ok && ybi_matured.locked_coins_this_block > 0) {
// Work out what the asset_type should be based on height of submission
uint8_t hf_submitted = m_hardfork->get_ideal_version(start_height);
// Iterate over the cached data for block yield, calculating the yield payouts due
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
std::vector<std::pair<yield_tx_info_carrot, uint64_t>> carrot_yield_payouts;
if (hf_submitted >= HF_VERSION_CARROT) {
std::vector<std::pair<yield_tx_info_carrot, uint64_t>> carrot_yield_payouts;
if (b.major_version >= HF_VERSION_CARROT) {
if (!calculate_yield_payouts(start_height, carrot_yield_payouts)) {
LOG_ERROR("Failed to obtain yield payout information - aborting");
return false;
@@ -2006,8 +1967,11 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
}
}
// Work out what the asset_type should be based on height of submission
uint8_t hf_submitted = m_hardfork->get_ideal_version(start_height);
// Create the protocol_metadata entries here
if (!carrot_yield_payouts.empty()) {
if (b.major_version >= HF_VERSION_CARROT) {
for (const auto& yield_entry: carrot_yield_payouts) {
cryptonote::protocol_data_entry entry;
entry.amount_burnt = yield_entry.second;
@@ -2026,7 +1990,6 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
entry.origin_height = start_height;
entry.return_view_tag = yield_entry.first.return_view_tag;
entry.return_anchor_enc = yield_entry.first.return_anchor_enc;
entry.is_carrot = true;
protocol_entries.push_back(entry);
}
} else {
@@ -2047,7 +2010,6 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
entry.P_change = yield_entry.first.P_change;
entry.return_pubkey = yield_entry.first.return_pubkey;
entry.origin_height = start_height;
entry.is_carrot = false;
protocol_entries.push_back(entry);
}
}
@@ -3723,7 +3685,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
*/
if (hf_version >= HF_VERSION_CARROT) {
// from v10, force the new SalviumOne RCT data
// from v11, force the new SalviumOne RCT data
if (tx.type == cryptonote::transaction_type::TRANSFER || tx.type == cryptonote::transaction_type::STAKE || tx.type == cryptonote::transaction_type::BURN || tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::AUDIT) {
if (tx.rct_signatures.type != rct::RCTTypeSalviumOne) {
MERROR_VER("SalviumOne data required after v" + std::to_string(HF_VERSION_CARROT));
@@ -3798,7 +3760,7 @@ bool Blockchain::check_tx_type_and_version(const transaction& tx, tx_verificatio
}
// Check for v1 TXs - genesis block protocol_tx exception required!
if (tx.version == 1) {
if (tx.version == 1 && epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(tx)) == "4f78ff511e860acd03138737a71505eb62eb78b620e180e58c8e13ed0e1e3e19") {
MERROR("v1 TXs are not permitted");
tvc.m_version_mismatch = true;
return false;
@@ -3831,32 +3793,6 @@ bool Blockchain::check_tx_type_and_version(const transaction& tx, tx_verificatio
}
}
if (tx.type == cryptonote::transaction_type::AUDIT) {
// Make sure we are supposed to accept AUDIT txs at this point
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(m_nettype).AUDIT_HARD_FORKS;
CHECK_AND_ASSERT_MES(audit_hard_forks.find(hf_version) != audit_hard_forks.end(), false, "trying to audit outside an audit fork");
std::string expected_asset_type = audit_hard_forks.at(hf_version).second.first;
CHECK_AND_ASSERT_MES(tx.source_asset_type == expected_asset_type, false, "trying to spend " << tx.source_asset_type << " coins in an AUDIT TX");
} else {
if (hf_version >= HF_VERSION_SALVIUM_ONE_PROOFS) {
CHECK_AND_ASSERT_MES(tx.source_asset_type == "SAL1", false, "trying to spend " << tx.source_asset_type << " coins in a non-AUDIT TX");
} else {
CHECK_AND_ASSERT_MES(tx.source_asset_type == "SAL", false, "trying to spend " << tx.source_asset_type << " coins in a non-AUDIT TX");
}
}
if (tx.type == cryptonote::transaction_type::BURN) {
CHECK_AND_ASSERT_MES(tx.destination_asset_type == "BURN", false, "incorrect burn tx destination type:" << tx.destination_asset_type);
} else {
if (tx.source_asset_type != tx.destination_asset_type) {
MERROR_VER("Tx " << get_transaction_hash(tx) << " has mismatched asset types: " << tx.source_asset_type << " != " << tx.destination_asset_type);
tvc.m_verifivation_failed = true;
return false;
}
}
// Check for invalid TX types
if (tx.type == cryptonote::transaction_type::UNSET || tx.type > cryptonote::transaction_type::MAX) {
MERROR("TX type `" + std::to_string(tx.type) + "' is not supported");
@@ -4120,6 +4056,20 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
}
if (tx.type == cryptonote::transaction_type::AUDIT) {
// Make sure we are supposed to accept AUDIT txs at this point
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(m_nettype).AUDIT_HARD_FORKS;
CHECK_AND_ASSERT_MES(audit_hard_forks.find(hf_version) != audit_hard_forks.end(), false, "trying to audit outside an audit fork");
std::string expected_asset_type = audit_hard_forks.at(hf_version).second.first;
CHECK_AND_ASSERT_MES(tx.source_asset_type == expected_asset_type, false, "trying to spend " << tx.source_asset_type << " coins in an AUDIT TX");
} else {
if (hf_version >= HF_VERSION_SALVIUM_ONE_PROOFS) {
CHECK_AND_ASSERT_MES(tx.source_asset_type == "SAL1", false, "trying to spend " << tx.source_asset_type << " coins in a non-AUDIT TX");
} else {
CHECK_AND_ASSERT_MES(tx.source_asset_type == "SAL", false, "trying to spend " << tx.source_asset_type << " coins in a non-AUDIT TX");
}
}
std::vector<std::vector<rct::ctkey>> pubkeys(tx.vin.size());
std::vector < uint64_t > results;
results.resize(tx.vin.size(), 0);
@@ -4723,7 +4673,7 @@ bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vecto
if (!yield_entries.size()) {
// Report error and abort
LOG_ERROR("calculate_yield_payouts() called for carrot, but no yield TXs found at height " << start_height << " - aborting");
LOG_ERROR("calculate_yield_payouts() called, but no yield TXs found at height " << start_height << " - aborting");
return false;
}
@@ -4759,14 +4709,10 @@ bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vecto
// Iterate over the yield_container, adding each proportion of the yield
for (auto& entry: yield_container) {
boost::multiprecision::int128_t locked_coins_128 = entry.first.locked_coins;
boost::multiprecision::int128_t yield_128 = (slippage_128 * locked_coins_128) / locked_total_128;
uint64_t yield_u64 = boost::numeric_cast<uint64_t>(yield_128);
if (entry.second + yield_u64 < entry.second) {
throw std::overflow_error("uint64_t addition overflow");
}
entry.second += yield_u64;
entry.second += yield_128.convert_to<uint64_t>();
}
}
@@ -4825,14 +4771,10 @@ bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vecto
// Iterate over the yield_container, adding each proportion of the yield
for (auto& entry: yield_container) {
boost::multiprecision::int128_t locked_coins_128 = entry.first.locked_coins;
boost::multiprecision::int128_t yield_128 = (slippage_128 * locked_coins_128) / locked_total_128;
uint64_t yield_u64 = boost::numeric_cast<uint64_t>(yield_128);
if (entry.second + yield_u64 < entry.second) {
throw std::overflow_error("uint64_t addition overflow");
}
entry.second += yield_u64;
entry.second += yield_128.convert_to<uint64_t>();
}
}
+1 -1
View File
@@ -1022,7 +1022,7 @@ namespace cryptonote
}
if (!rvv.empty())
{
LOG_PRINT_L1("Verifying transactions one at a time");
LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
ret = false;
for (size_t n = 0; n < tx_info.size(); ++n)
{
+11 -39
View File
@@ -346,27 +346,14 @@ namespace cryptonote
// Clear the TX contents
tx.set_null();
tx.version = 2;
bool carrot_found = false;
bool noncarrot_found = false;
tx.type = cryptonote::transaction_type::PROTOCOL;
// Scan the protocol_data to make sure all or none are Carrot
for (auto const& entry: protocol_data) {
if (entry.is_carrot) carrot_found = true;
else noncarrot_found = true;
}
if (carrot_found && noncarrot_found) {
LOG_ERROR("Cannot mix Carrot and non-Carrot outputs in the same protocol transaction");
return false;
}
if (carrot_found || hard_fork_version >= HF_VERSION_ENFORCE_CARROT)
{
// Force the TX type to 2
tx.version = 2;
// Ensure the TX version is correct
tx.version = TRANSACTION_VERSION_CARROT;
const bool do_carrot = hard_fork_version >= HF_VERSION_CARROT;
if (do_carrot)
{
try
{
// Create a vector of enotes
@@ -386,6 +373,7 @@ namespace cryptonote
memcpy(e.enote_ephemeral_pubkey.data, entry.return_pubkey.data, sizeof(crypto::public_key));
enotes.push_back(e);
}
tx = store_carrot_to_coinbase_transaction_v1(enotes, std::string{}, cryptonote::transaction_type::PROTOCOL, height);
tx.amount_burnt = 0;
tx.invalidate_hashes();
@@ -408,29 +396,14 @@ namespace cryptonote
std::vector<crypto::public_key> additional_tx_public_keys;
for (auto const& entry: protocol_data) {
if (entry.type == cryptonote::transaction_type::STAKE) {
// PAYOUT
LOG_PRINT_L2("Yield TX payout submitted " << entry.amount_burnt << entry.source_asset);
if (entry.is_carrot) {
tx_out out;
out.amount = entry.amount_burnt;
out.target = txout_to_carrot_v1 {
.key = entry.return_address,
.asset_type = entry.destination_asset,
.view_tag = entry.return_view_tag,
.encrypted_janus_anchor = entry.return_anchor_enc,
};
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
} else {
// Create the TX output for this refund
tx_out out;
cryptonote::set_tx_out(entry.amount_burnt, entry.destination_asset, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
}
// Create the TX output for this refund
tx_out out;
cryptonote::set_tx_out(entry.amount_burnt, entry.destination_asset, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
} else if (entry.type == cryptonote::transaction_type::AUDIT) {
// PAYOUT
LOG_PRINT_L2("Audit TX payout submitted " << entry.amount_burnt << entry.source_asset);
@@ -594,7 +567,6 @@ namespace cryptonote
case HF_VERSION_AUDIT2:
case HF_VERSION_AUDIT2_PAUSE:
case HF_VERSION_CARROT:
case HF_VERSION_ENFORCE_CARROT:
// SRCG: subtract 20% that will be rewarded to staking users
CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero");
tx.amount_burnt = amount / 5;
@@ -71,7 +71,6 @@ namespace cryptonote
carrot::view_tag_t return_view_tag;
carrot::encrypted_janus_anchor_t return_anchor_enc;
uint64_t origin_height;
bool is_carrot;
};
//---------------------------------------------------------------
-3
View File
@@ -92,9 +92,6 @@ const hardfork_t testnet_hard_forks[] = {
// version 10 Carrot - including treasury mint - starts from block 1100
{10, 1100, 0, 1739780005 },
// version 11 Carrot and CryptoNote starts from block 1200
{11, 1200, 0, 1756811153 },
};
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
+3 -3
View File
@@ -733,9 +733,9 @@ namespace nodetool
std::set<std::string> full_addrs;
if (m_nettype == cryptonote::TESTNET)
{
full_addrs.insert("165.22.6.67:29080");
full_addrs.insert("165.22.15.162:29080");
full_addrs.insert("162.243.163.207:29080");
full_addrs.insert("72.5.43.63:29080");
full_addrs.insert("195.85.114.217:29080");
full_addrs.insert("206.188.197.72:29080");
}
else if (m_nettype == cryptonote::STAGENET)
{
-3
View File
@@ -38,7 +38,6 @@
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "mx25519.h"
#include "carrot_core/core_types.h"
// read
template <template <bool> class Archive>
@@ -86,7 +85,6 @@ BLOB_SERIALIZER(crypto::public_key);
BLOB_SERIALIZER(crypto::secret_key);
BLOB_SERIALIZER(crypto::key_derivation);
BLOB_SERIALIZER(crypto::key_image);
BLOB_SERIALIZER(carrot::input_context_t);
BLOB_SERIALIZER(crypto::signature);
BLOB_SERIALIZER(crypto::view_tag);
BLOB_SERIALIZER(crypto::ec_point);
@@ -97,7 +95,6 @@ VARIANT_TAG(debug_archive, crypto::public_key, "public_key");
VARIANT_TAG(debug_archive, crypto::secret_key, "secret_key");
VARIANT_TAG(debug_archive, crypto::key_derivation, "key_derivation");
VARIANT_TAG(debug_archive, crypto::key_image, "key_image");
VARIANT_TAG(debug_archive, carrot::input_context_t, "input_context");
VARIANT_TAG(debug_archive, crypto::signature, "signature");
VARIANT_TAG(debug_archive, crypto::view_tag, "view_tag");
VARIANT_TAG(debug_archive, crypto::ec_point, "ec_point");
+11 -80
View File
@@ -192,7 +192,6 @@ namespace
const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to <arg>"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_device = {"generate-from-device", sw::tr("Generate new wallet from device and save it to <arg>"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_svb_key = {"generate-from-svb-key", sw::tr("Generate full view-only wallet from view key"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_spend_key = {"generate-from-spend-key", sw::tr("Generate deterministic wallet from spend key"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_keys = {"generate-from-keys", sw::tr("Generate wallet from private keys"), ""};
const command_line::arg_descriptor<std::string> arg_generate_from_multisig_keys = {"generate-from-multisig-keys", sw::tr("Generate a master wallet from multisig wallet keys"), ""};
@@ -4425,12 +4424,12 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
bool welcome = false;
if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_device.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_svb_key.empty()) + (!m_generate_from_spend_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1)
if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_device.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_spend_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1)
{
fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-svb-key=\"wallet_name\", --generate-from-spend-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\", --generate-from-json=\"jsonfilename\" and --generate-from-device=\"wallet_name\"");
fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-spend-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\", --generate-from-json=\"jsonfilename\" and --generate-from-device=\"wallet_name\"");
return false;
}
else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_device.empty() && m_generate_from_view_key.empty() && m_generate_from_svb_key.empty() && m_generate_from_spend_key.empty() && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty())
else if (m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_device.empty() && m_generate_from_view_key.empty() && m_generate_from_spend_key.empty() && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty())
{
if(!ask_wallet_create_if_needed()) return false;
}
@@ -4585,69 +4584,6 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
password = *r;
welcome = true;
}
else if (!m_generate_from_svb_key.empty())
{
m_wallet_file = m_generate_from_svb_key;
// parse address
std::string address_string = input_line("Standard address");
if (std::cin.eof())
return false;
if (address_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
cryptonote::address_parse_info info;
if(!get_account_address_from_str(info, nettype, address_string))
{
fail_msg_writer() << tr("failed to parse address");
return false;
}
if (info.is_subaddress)
{
fail_msg_writer() << tr("This address is a subaddress which cannot be used here.");
return false;
}
if (!info.is_carrot)
{
fail_msg_writer() << tr("This address is not a Carrot address, and cannot be used here.");
return false;
}
// parse view secret key
epee::wipeable_string viewkey_string = input_secure_line("Secret view key");
if (std::cin.eof())
return false;
if (viewkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
}
crypto::secret_key viewkey;
if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey))))
{
fail_msg_writer() << tr("failed to parse view key secret key");
return false;
}
// Create all of the necessary keys for Carrot view-only wallet
/*
// check the view key matches the given address
crypto::public_key pkey;
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
fail_msg_writer() << tr("failed to verify view key secret key");
return false;
}
if (info.address.m_view_public_key != pkey) {
fail_msg_writer() << tr("view key does not match standard address");
return false;
}
*/
auto r = new_wallet(vm, info.address, boost::none, viewkey);
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
password = *r;
welcome = true;
}
else if (!m_generate_from_spend_key.empty())
{
m_wallet_file = m_generate_from_spend_key;
@@ -5113,7 +5049,6 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_generate_new = command_line::get_arg(vm, arg_generate_new_wallet);
m_generate_from_device = command_line::get_arg(vm, arg_generate_from_device);
m_generate_from_view_key = command_line::get_arg(vm, arg_generate_from_view_key);
m_generate_from_svb_key = command_line::get_arg(vm, arg_generate_from_svb_key);
m_generate_from_spend_key = command_line::get_arg(vm, arg_generate_from_spend_key);
m_generate_from_keys = command_line::get_arg(vm, arg_generate_from_keys);
m_generate_from_multisig_keys = command_line::get_arg(vm, arg_generate_from_multisig_keys);
@@ -5129,7 +5064,6 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_subaddress_lookahead = command_line::get_arg(vm, arg_subaddress_lookahead);
m_use_english_language_names = command_line::get_arg(vm, arg_use_english_language_names);
m_restoring = !m_generate_from_view_key.empty() ||
!m_generate_from_svb_key.empty() ||
!m_generate_from_spend_key.empty() ||
!m_generate_from_keys.empty() ||
!m_generate_from_multisig_keys.empty() ||
@@ -5353,9 +5287,8 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
}
//----------------------------------------------------------------------------------------------------
boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
const cryptonote::account_public_address& address,
const boost::optional<crypto::secret_key>& spendkey,
const crypto::secret_key& viewkey)
const cryptonote::account_public_address& address, const boost::optional<crypto::secret_key>& spendkey,
const crypto::secret_key& viewkey)
{
std::pair<std::unique_ptr<tools::wallet2>, tools::password_container> rc;
try { rc = tools::wallet2::make_new(vm, false, password_prompter); }
@@ -7772,6 +7705,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector<std::string> &args_)
{
CHECK_IF_BACKGROUND_SYNCING("cannot sweep");
std::string asset_type = (args_.size() > 1) ? args_.back() : (m_wallet->get_current_hard_fork() >= HF_VERSION_SALVIUM_ONE_PROOFS) ? "SAL1" : "SAL";
auto print_usage = [this, account, below]()
{
if (below)
@@ -7904,8 +7838,6 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
}
}
std::string asset_type = (m_wallet->get_current_hard_fork() >= HF_VERSION_SALVIUM_ONE_PROOFS) ? "SAL1" : "SAL";
std::vector<uint8_t> extra;
bool payment_id_seen = false;
if (local_args.size() >= 2)
@@ -7997,8 +7929,8 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
prompt << tr("WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy.\n");
}
// if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
// return true;
if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return true;
if (ptx_vector.size() > 1) {
prompt << boost::format(tr("Sweeping %s in %llu transactions for a total fee of %s. Is this okay?")) %
@@ -11144,7 +11076,7 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
description += " ";
description += args[i];
}
m_wallet->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : NULL, description, info.is_subaddress, info.is_carrot);
m_wallet->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : NULL, description, info.is_subaddress);
}
else
{
@@ -11168,9 +11100,9 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
success_msg_writer() << tr("Index: ") << i;
std::string address;
if (row.m_has_payment_id)
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), row.m_address, row.m_payment_id, row.m_is_carrot);
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), row.m_address, row.m_payment_id);
else
address = get_account_address_as_str(m_wallet->nettype(), row.m_is_subaddress, row.m_address, row.m_is_carrot);
address = get_account_address_as_str(m_wallet->nettype(), row.m_is_subaddress, row.m_address);
success_msg_writer() << tr("Address: ") << address;
success_msg_writer() << tr("Description: ") << row.m_description << "\n";
}
@@ -11896,7 +11828,6 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_generate_new_wallet);
command_line::add_arg(desc_params, arg_generate_from_device);
command_line::add_arg(desc_params, arg_generate_from_view_key);
command_line::add_arg(desc_params, arg_generate_from_svb_key);
command_line::add_arg(desc_params, arg_generate_from_spend_key);
command_line::add_arg(desc_params, arg_generate_from_keys);
command_line::add_arg(desc_params, arg_generate_from_multisig_keys);
+2 -6
View File
@@ -101,11 +101,8 @@ namespace cryptonote
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const crypto::secret_key& recovery_key,
bool recover, bool two_random, const std::string &old_language);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm,
const cryptonote::account_public_address& address,
const boost::optional<crypto::secret_key>& spendkey,
const crypto::secret_key& viewkey
);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const cryptonote::account_public_address& address,
const boost::optional<crypto::secret_key>& spendkey, const crypto::secret_key& viewkey);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm,
const epee::wipeable_string &multisig_keys, const epee::wipeable_string &seed_pass, const std::string &old_language);
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm);
@@ -433,7 +430,6 @@ namespace cryptonote
std::string m_generate_new;
std::string m_generate_from_device;
std::string m_generate_from_view_key;
std::string m_generate_from_svb_key;
std::string m_generate_from_spend_key;
std::string m_generate_from_keys;
std::string m_generate_from_multisig_keys;
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
#define DEF_SALVIUM_VERSION "1.0.0-rc4"
#define DEF_SALVIUM_VERSION "0.9.9-rc4"
#define DEF_MONERO_VERSION_TAG "release"
#define DEF_MONERO_VERSION "0.18.3.4"
#define DEF_MONERO_RELEASE_NAME "One"
+2 -2
View File
@@ -62,7 +62,7 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa
return false;
}
bool r = m_wallet->m_wallet->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : NULL,description,info.is_subaddress,info.is_carrot);
bool r = m_wallet->m_wallet->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : NULL,description,info.is_subaddress);
if (r)
refresh();
else
@@ -81,7 +81,7 @@ bool AddressBookImpl::setDescription(std::size_t index, const std::string &descr
tools::wallet2::address_book_row entry = ab[index];
entry.m_description = description;
bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, entry.m_has_payment_id ? &entry.m_payment_id : nullptr, entry.m_description, entry.m_is_subaddress,entry.m_is_carrot);
bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, entry.m_has_payment_id ? &entry.m_payment_id : nullptr, entry.m_description, entry.m_is_subaddress);
if (r)
refresh();
else
+10 -12
View File
@@ -36,6 +36,7 @@
#include "carrot_core/lazy_amount_commitment.h"
#include "carrot_core/scan.h"
#include "carrot_impl/format_utils.h"
#include "common/container_helpers.h"
#include "crypto/generators.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "ringct/rctOps.h"
@@ -132,9 +133,6 @@ static bool try_load_pre_carrot_enote(const bool is_coinbase,
enote_out.amount_commitment = rct::Z;
}
// Check for protocol_tx outputs
enote_out.is_protocol_tx_output = (tx.type == cryptonote::transaction_type::PROTOCOL);
return true;
}
//-------------------------------------------------------------------------------------------------------------------
@@ -171,8 +169,8 @@ static std::optional<enote_view_incoming_scan_info_t> view_incoming_scan_pre_car
crypto::ec_scalar amount_key;
if (!hwdev.derivation_to_scalar(receive_info->derivation,
enote.is_protocol_tx_output ? 0 : enote.local_output_index,
amount_key))
enote.local_output_index,
amount_key))
return std::nullopt;
// a
@@ -211,16 +209,16 @@ static std::optional<enote_view_incoming_scan_info_t> view_incoming_scan_pre_car
// derive k^g_o
crypto::secret_key sender_extension_g;
if (!hwdev.derivation_to_scalar(receive_info->derivation,
enote.is_protocol_tx_output ? 0 : enote.local_output_index,
sender_extension_g))
enote.local_output_index,
sender_extension_g))
return std::nullopt;
// K^j_s'
crypto::public_key address_spend_pubkey;
if (!hwdev.derive_subaddress_public_key(enote.onetime_address,
receive_info->derivation,
enote.is_protocol_tx_output ? 0 : enote.local_output_index,
address_spend_pubkey))
receive_info->derivation,
enote.local_output_index,
address_spend_pubkey))
return std::nullopt;
//pid
@@ -489,14 +487,14 @@ void perform_ecdh_derivations(const epee::span<const crypto::public_key> main_tx
{
hwdev.generate_key_derivation(main_tx_ephemeral_pubkey,
k_view_incoming,
main_derivations_out.emplace_back());
tools::add_element(main_derivations_out));
}
for (const crypto::public_key &additional_tx_ephemeral_pubkey : additional_tx_ephemeral_pubkeys)
{
hwdev.generate_key_derivation(additional_tx_ephemeral_pubkey,
k_view_incoming,
additional_derivations_out.emplace_back());
tools::add_element(additional_derivations_out));
}
}
}
-2
View File
@@ -100,8 +100,6 @@ struct PreCarrotEnote
bool short_amount;
rct::key amount_commitment;
rct::ecdhTuple amount;
bool is_protocol_tx_output;
};
using MoneroEnoteVariant = std::variant<PreCarrotEnote,
+4 -1
View File
@@ -541,6 +541,9 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
const std::set<uint32_t> &subaddr_indices,
const wallet2::unique_index_container &subtract_fee_from_outputs)
{
wallet2::transfer_container transfers;
w.get_transfers(transfers);
const bool use_per_byte_fee = w.use_fork_rules(HF_VERSION_PER_BYTE_FEE, 0);
CHECK_AND_ASSERT_THROW_MES(use_per_byte_fee,
"make_carrot_transaction_proposals_wallet2_transfer: not using per-byte base fee");
@@ -739,7 +742,7 @@ std::vector<carrot::CarrotTransactionProposalV1> make_carrot_transaction_proposa
subaddr_account,
subaddr_indices,
only_below ? only_below : MONEY_SUPPLY,
1, // ignore_below
0,
top_block_index))
continue;
+42 -79
View File
@@ -2621,7 +2621,7 @@ void wallet2::process_new_scanned_transaction(
continue;
// update m_transfers view-incoming scan info, and default values
transfer_details& td = m_transfers.emplace_back();
transfer_details& td = tools::add_element(m_transfers);
td.m_block_height = height;
td.m_internal_output_index = local_output_index;
td.m_global_output_index = o_indices.at(local_output_index);
@@ -2704,37 +2704,6 @@ void wallet2::process_new_scanned_transaction(
// update m_transfer_indices
m_transfers_indices[enote_scan_info->asset_type].insert(m_transfers.size()-1);
// Check for STAKE / AUDIT TX payouts
if (tx.type == cryptonote::transaction_type::PROTOCOL && td.m_td_origin_idx != std::numeric_limits<uint64_t>::max()) {
// Attempt to get the origin TX
THROW_WALLET_EXCEPTION_IF(td.m_td_origin_idx >= get_num_transfer_details(),
error::wallet_internal_error,
"cannot locate return_payment TX origin in m_transfers");
const transfer_details &td_origin = m_transfers[td.m_td_origin_idx];
THROW_WALLET_EXCEPTION_IF(td_origin.m_tx.type != cryptonote::transaction_type::AUDIT && td_origin.m_tx.type != cryptonote::transaction_type::STAKE,
error::wallet_internal_error,
"incorrect TX type for protocol_tx origin in m_transfers");
// Get the output key for the change entry
crypto::public_key pk_locked_coins = crypto::null_pkey;
THROW_WALLET_EXCEPTION_IF(!get_output_public_key(td_origin.m_tx.vout[td_origin.m_internal_output_index], pk_locked_coins),
error::wallet_internal_error,
"Failed to get output public key for locked coins");
// At this point, we need to clear the "locked coins" count, because otherwise we will be counting yield stakes twice in our balance
if (!m_locked_coins.erase(pk_locked_coins)) {
LOG_ERROR("Failed to remove protocol_tx entry from m_locked_coins - possible duplicate output key detected");
}
}
// Check for STAKE / AUDIT TXs
if (tx.type == cryptonote::transaction_type::AUDIT || tx.type == cryptonote::transaction_type::STAKE) {
// Add a "locked coins" entry so users don't freak out when they STAKE/AUDITOA
m_locked_coins.insert({onetime_address, {0, tx.amount_burnt, tx.source_asset_type}});
}
// update multisig info
if (m_multisig)
{
@@ -2880,8 +2849,21 @@ void wallet2::process_new_scanned_transaction(
// save the change output key in our subaddress_map, so we can receive money to it later
// from protocol or return txs
for (const auto &entry: tx_amounts_individual_outs[i->first]) {
const crypto::public_key &onetime_address = std::get<1>(entry);
carrot::AddressDeriveType derive_type;
if (use_fork_rules(HF_VERSION_CARROT, 0)) {
derive_type = carrot::AddressDeriveType::Carrot;
} else {
derive_type = carrot::AddressDeriveType::PreCarrot;
}
const carrot::subaddress_index_extended subaddr_ext = {i->first.major, i->first.minor, derive_type, true};
// save to m_subaddresses as well, so that we can populate account subaddress map
// when we open the wallet first time.
if (derive_type == carrot::AddressDeriveType::PreCarrot)
m_subaddresses_extended[onetime_address] = subaddr_ext;
// update m_salvium_txs
m_salvium_txs.insert({std::get<1>(entry), m_transfers.size()-1});
m_salvium_txs.insert({onetime_address, m_transfers.size()-1});
}
// delete change output from amounts
@@ -3131,7 +3113,8 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b,
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
LOG_PRINT_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
} else {
}else
{
if (!(height % 128))
LOG_PRINT_L2( "Skipped block by timestamp, height: " << height << ", block time " << b.timestamp << ", account time " << m_account.get_createtime());
}
@@ -3399,6 +3382,19 @@ void wallet2::process_parsed_blocks(const uint64_t start_height, const std::vect
size_t i = 0;
size_t tx_output_idx = 0;
while (i < blocks.size()) {
/*
if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase)
tx_scan_job(par_blk.block.miner_tx, tx_output_idx);
tx_output_idx += par_blk.block.miner_tx.vout.size();
if (!skip_scan_for_this_block && m_refresh_type != RefreshNoCoinbase)
tx_scan_job(par_blk.block.protocol_tx, tx_output_idx);
tx_output_idx += par_blk.block.protocol_tx.vout.size();
for (const cryptonote::transaction &tx : par_blk.txes)
{
if (!skip_scan_for_this_block)
tx_scan_job(tx, tx_output_idx);
tx_output_idx += tx.vout.size();
*/
tools::threadpool::waiter scan_blocks_waiter(tpool);
for (size_t j = 0; j < 10; ++j)
{
@@ -3472,23 +3468,6 @@ void wallet2::process_parsed_blocks(const uint64_t start_height, const std::vect
tx_output_idx += n_block_outputs;
++current_index;
}
// save accumulated return subaddresses to m_subaddresses_extended, so that we can re-insert
// them into account after we restart the wallet.
m_subaddresses_extended.clear();
for (const auto& subaddr: m_account.get_subaddress_map_ref()) {
if (subaddr.second.derive_type == carrot::AddressDeriveType::PreCarrot &&
subaddr.second.is_return_spend_key == true
) {
m_subaddresses_extended.insert({subaddr.first, subaddr.second});
}
}
// save accumulated return output info to wallet
m_return_output_info.clear();
for (const auto& output_info: m_account.get_return_output_map_ref()) {
m_return_output_info.insert({output_info.first, output_info.second});
}
}
//----------------------------------------------------------------------------------------------------
void wallet2::refresh(bool trusted_daemon)
@@ -4052,7 +4031,7 @@ void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height,
}
bool wallet2::add_address_book_row(const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress, bool is_carrot)
bool wallet2::add_address_book_row(const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress)
{
wallet2::address_book_row a;
a.m_address = address;
@@ -4060,7 +4039,6 @@ bool wallet2::add_address_book_row(const cryptonote::account_public_address &add
a.m_payment_id = payment_id ? *payment_id : crypto::null_hash8;
a.m_description = description;
a.m_is_subaddress = is_subaddress;
a.m_is_carrot = is_carrot;
auto old_size = m_address_book.size();
m_address_book.push_back(a);
@@ -4069,7 +4047,7 @@ bool wallet2::add_address_book_row(const cryptonote::account_public_address &add
return false;
}
bool wallet2::set_address_book_row(size_t row_id, const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress, bool is_carrot)
bool wallet2::set_address_book_row(size_t row_id, const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress)
{
wallet2::address_book_row a;
a.m_address = address;
@@ -4077,7 +4055,6 @@ bool wallet2::set_address_book_row(size_t row_id, const cryptonote::account_publ
a.m_payment_id = payment_id ? *payment_id : crypto::null_hash8;
a.m_description = description;
a.m_is_subaddress = is_subaddress;
a.m_is_carrot = is_carrot;
const auto size = m_address_book.size();
if (row_id >= size)
@@ -5845,7 +5822,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
*/
void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
const cryptonote::account_public_address &account_public_address,
const crypto::secret_key& viewkey, bool create_address_file)
const crypto::secret_key& viewkey, bool create_address_file)
{
clear();
prepare_file_names(wallet_);
@@ -5857,11 +5834,7 @@ void wallet2::generate(const std::string& wallet_, const epee::wipeable_string&
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
}
if (account_public_address.m_is_carrot) {
m_account.create_from_svb_key(account_public_address, viewkey);
} else {
m_account.create_from_viewkey(account_public_address, viewkey);
}
m_account.create_from_viewkey(account_public_address, viewkey);
init_type(hw::device::device_type::SOFTWARE);
m_watch_only = true;
m_account_public_address = account_public_address;
@@ -6623,21 +6596,17 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
if (get_num_subaddress_accounts() == 0)
add_subaddress_account(tr("Primary account"));
// populate account subaddress list
m_account.insert_subaddresses(m_subaddresses_extended);
if (!m_subaddresses.empty())
{
// if we have subaddresses, we need to insert them into the account
for (const auto &subaddress : m_subaddresses)
m_account.insert_subaddresses(
// we assume none of these subaddresses are return tx subaddresses
// TODO: we assume none of these subaddresses are return tx subaddresses
{{subaddress.first, {{subaddress.second.major, subaddress.second.minor}, carrot::AddressDeriveType::PreCarrot, false}}}
);
}
m_account.insert_subaddresses(m_subaddresses_extended);
// populate account return output info
m_account.insert_return_output_info(m_return_output_info);
try
{
@@ -6844,8 +6813,9 @@ void wallet2::process_background_cache_on_open()
background_w2->m_custom_background_key = m_custom_background_key;
// TODO: uncommet this block
background_w2->m_account.set_keys(m_account.get_keys(), false);
background_w2->m_account.forget_spend_key();
// carrot::carrot_and_legacy_account account = m_account;
// account.forget_spend_key();
// background_w2->m_account = account;
// Load background cache from file
background_w2->clear();
@@ -7457,14 +7427,6 @@ bool wallet2::is_transfer_unlocked(const transfer_details& td)
uint64_t unlock_time = 0;
if (!cryptonote::get_output_unlock_time(td.m_tx.vout[td.m_internal_output_index], unlock_time))
return false;
if (unlock_time == 0) {
if (td.m_tx.type == cryptonote::transaction_type::MINER || td.m_tx.type == cryptonote::transaction_type::PROTOCOL) {
unlock_time = CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
} else {
unlock_time = CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE;
}
}
return is_transfer_unlocked(unlock_time, td.m_block_height);
}
//----------------------------------------------------------------------------------------------------
@@ -11614,8 +11576,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
const auto tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep_all(*this, below, address, is_subaddress, outputs, priority, extra, tx_type, subaddr_account, subaddr_indices);
std::vector<pending_tx> ptx_vector;
ptx_vector.reserve(tx_proposals.size());
for (const auto &tx_proposal : tx_proposals)
ptx_vector.push_back(tools::wallet::finalize_all_proofs_from_transfer_details_as_pending_tx(tx_proposal, *this));
// TODO: use CLSAGS here..
// for (const auto &tx_proposal : tx_proposals)
// ptx_vector.push_back(tools::wallet::finalize_all_proofs_from_transfer_details_as_pending_tx(tx_proposal, *this));
return ptx_vector;
}
+3 -12
View File
@@ -859,7 +859,6 @@ private:
std::string m_description;
bool m_is_subaddress;
bool m_has_payment_id;
bool m_is_carrot;
BEGIN_SERIALIZE_OBJECT()
VERSION_FIELD(0)
@@ -868,7 +867,6 @@ private:
FIELD(m_description)
FIELD(m_is_subaddress)
FIELD(m_has_payment_id)
FIELD(m_is_carrot)
END_SERIALIZE()
};
@@ -1019,7 +1017,6 @@ private:
* \param account_public_address The account's public address
* \param viewkey view secret key
* \param create_address_file Whether to create an address file
* \param is_carrot Whether viewkey is k_v (CN) or s_vb (Carrot)
*/
void generate(const std::string& wallet, const epee::wipeable_string& password,
const cryptonote::account_public_address &account_public_address,
@@ -1420,7 +1417,6 @@ private:
return;
a & m_subaddresses.parent();
a & m_subaddresses_extended.parent();
a & m_return_output_info.parent();
std::unordered_map<cryptonote::subaddress_index, crypto::public_key> dummy_subaddresses_inv;
a & dummy_subaddresses_inv;
a & m_subaddress_labels;
@@ -1488,7 +1484,6 @@ private:
FIELD(m_scanned_pool_txs[1])
FIELD(m_subaddresses)
FIELD(m_subaddresses_extended)
FIELD(m_return_output_info)
FIELD(m_subaddress_labels)
FIELD(m_additional_tx_keys)
FIELD(m_attributes)
@@ -1649,8 +1644,8 @@ private:
* \brief GUI Address book get/store
*/
std::vector<address_book_row> get_address_book() const { return m_address_book; }
bool add_address_book_row(const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress, bool is_carrot);
bool set_address_book_row(size_t row_id, const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress, bool is_carrot);
bool add_address_book_row(const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress);
bool set_address_book_row(size_t row_id, const cryptonote::account_public_address &address, const crypto::hash8 *payment_id, const std::string &description, bool is_subaddress);
bool delete_address_book_row(std::size_t row_id);
uint64_t get_num_rct_outputs();
@@ -2152,7 +2147,6 @@ private:
cryptonote::account_public_address m_account_public_address;
serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index> m_subaddresses;
serializable_unordered_map<crypto::public_key, carrot::subaddress_index_extended> m_subaddresses_extended;
serializable_unordered_map<crypto::public_key, carrot::return_output_info_t> m_return_output_info;
std::vector<std::vector<std::string>> m_subaddress_labels;
serializable_unordered_map<crypto::hash, std::string> m_tx_notes;
serializable_unordered_map<std::string, std::string> m_attributes;
@@ -2293,7 +2287,7 @@ BOOST_CLASS_VERSION(tools::wallet2::payment_details, 5)
BOOST_CLASS_VERSION(tools::wallet2::pool_payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 8)
BOOST_CLASS_VERSION(tools::wallet2::confirmed_transfer_details, 6)
BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 19)
BOOST_CLASS_VERSION(tools::wallet2::address_book_row, 18)
BOOST_CLASS_VERSION(tools::wallet2::reserve_proof_entry, 0)
BOOST_CLASS_VERSION(tools::wallet2::unsigned_tx_set, 1)
BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 1)
@@ -2671,9 +2665,6 @@ namespace boost
a & x.m_has_payment_id;
if (x.m_has_payment_id)
a & x.m_payment_id;
if (ver < 19)
return;
a & x.m_is_carrot;
}
template <class Archive>
+4 -5
View File
@@ -3313,9 +3313,9 @@ namespace tools
const auto &entry = ab[idx];
std::string address;
if (entry.m_has_payment_id)
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.m_address, entry.m_payment_id, entry.m_is_carrot);
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.m_address, entry.m_payment_id);
else
address = get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address, entry.m_is_carrot);
address = get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address);
res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, address, entry.m_description});
}
}
@@ -3355,7 +3355,7 @@ namespace tools
er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + req.address;
return false;
}
if (!m_wallet->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : NULL, req.description, info.is_subaddress, info.is_carrot))
if (!m_wallet->add_address_book_row(info.address, info.has_payment_id ? &info.payment_id : NULL, req.description, info.is_subaddress))
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = "Failed to add address book entry";
@@ -3414,13 +3414,12 @@ namespace tools
entry.m_is_subaddress = info.is_subaddress;
if (info.has_payment_id)
entry.m_payment_id = info.payment_id;
entry.m_is_carrot = info.is_carrot;
}
if (req.set_description)
entry.m_description = req.description;
if (!m_wallet->set_address_book_row(req.index, entry.m_address, req.set_address && entry.m_has_payment_id ? &entry.m_payment_id : NULL, entry.m_description, entry.m_is_subaddress, entry.m_is_carrot))
if (!m_wallet->set_address_book_row(req.index, entry.m_address, req.set_address && entry.m_has_payment_id ? &entry.m_payment_id : NULL, entry.m_description, entry.m_is_subaddress))
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = "Failed to edit address book entry";
+51 -50
View File
@@ -38,6 +38,7 @@
#include "carrot_impl/tx_proposal_utils.h"
#include "carrot_impl/input_selection.h"
#include "carrot_mock_helpers.h"
#include "common/container_helpers.h"
#include "crypto/generators.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/subaddress_index.h"
@@ -62,7 +63,7 @@ static void unittest_scan_enote_set_multi_account(const std::vector<CarrotEnoteV
res.reserve(accounts.size());
for (const auto *account : accounts)
mock_scan_enote_set(enotes, encrypted_payment_id, *account, res.emplace_back());
mock_scan_enote_set(enotes, encrypted_payment_id, *account, tools::add_element(res));
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
@@ -356,7 +357,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_1)
acc1.generate();
// 1 normal payment
CarrotPaymentProposalV1 &normal_payment_proposal = tx_proposal.per_account_payments[0].second.emplace_back().first;
CarrotPaymentProposalV1 &normal_payment_proposal = tools::add_element( tx_proposal.per_account_payments[0].second).first;
normal_payment_proposal = CarrotPaymentProposalV1{
.destination = acc0.cryptonote_address(),
.amount = crypto::rand_idx((rct::xmr_amount) 1ull << 63),
@@ -395,21 +396,21 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_2)
tx_proposal.self_sender_index = 2;
// 1 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -444,7 +445,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_3)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -453,7 +454,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_3)
acc0.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 2 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -462,7 +463,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_3)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -497,7 +498,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_4)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -506,7 +507,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_4)
acc0.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 2 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -515,14 +516,14 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_4)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 main address selfsend
tx_proposal.explicit_selfsend_proposals.emplace_back().first.proposal = CarrotPaymentProposalSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals).first.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.carrot_account_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.enote_type = CarrotEnoteType::PAYMENT,
@@ -530,7 +531,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_4)
};
// 1 subaddress selfsend
tx_proposal.explicit_selfsend_proposals.emplace_back().first = CarrotPaymentProposalVerifiableSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals).first = CarrotPaymentProposalVerifiableSelfSendV1{
.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.subaddress({{4, 19}}).address_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
@@ -561,7 +562,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_5)
acc1.generate(AddressDeriveType::PreCarrot);
// 1 normal payment
CarrotPaymentProposalV1 &normal_payment_proposal = tx_proposal.per_account_payments[0].second.emplace_back().first;
CarrotPaymentProposalV1 &normal_payment_proposal = tools::add_element( tx_proposal.per_account_payments[0].second).first;
normal_payment_proposal = CarrotPaymentProposalV1{
.destination = acc0.cryptonote_address(),
.amount = crypto::rand_idx((rct::xmr_amount) 1ull << 63),
@@ -600,21 +601,21 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_6)
tx_proposal.self_sender_index = 2;
// 1 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -649,7 +650,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_7)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -658,7 +659,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_7)
acc0.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 2 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -667,7 +668,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_7)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -702,7 +703,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_8)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -711,7 +712,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_8)
acc0.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 2 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -720,14 +721,14 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_8)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 main address selfsend
tx_proposal.explicit_selfsend_proposals.emplace_back().first.proposal = CarrotPaymentProposalSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals).first.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.carrot_account_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.enote_type = CarrotEnoteType::PAYMENT,
@@ -735,7 +736,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_8)
};
// 1 subaddress selfsend
tx_proposal.explicit_selfsend_proposals.emplace_back().first = CarrotPaymentProposalVerifiableSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals).first = CarrotPaymentProposalVerifiableSelfSendV1{
.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.subaddress({{4, 19}}).address_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
@@ -767,7 +768,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_9)
acc1.generate();
// 1 normal payment (subtractable)
CarrotPaymentProposalV1 &normal_payment_proposal = tx_proposal.per_account_payments[0].second.emplace_back().first;
CarrotPaymentProposalV1 &normal_payment_proposal = tools::add_element( tx_proposal.per_account_payments[0].second).first;
normal_payment_proposal = CarrotPaymentProposalV1{
.destination = acc0.cryptonote_address(),
.amount = crypto::rand_idx((rct::xmr_amount) 1ull << 63),
@@ -808,21 +809,21 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_10)
tx_proposal.self_sender_index = 2;
// 1 subaddress payment (subtractable)
acc0.second.emplace_back().first = CarrotPaymentProposalV1{ = {CarrotPaymentProposalV1{
tools::add_element(acc0.second) = {CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
}, true};
// 1 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second) = {CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -858,7 +859,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_11)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment
acc0.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc0.second).first = CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -868,7 +869,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_11)
acc0.second.back().second = true; //set copy as subtractable
// 2 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -878,7 +879,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_11)
acc1.second.back().second = true; //set copy as subtractable
// 1 integrated address payment
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second).first = CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -914,7 +915,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_12)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment (1 subtractable)
acc0.second.emplace_back().first = CarrotPaymentProposalV1{ = {CarrotPaymentProposalV1{
tools::add_element(acc0.second) = {CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -924,7 +925,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_12)
acc0.second.back().second = false; //set not subtractable, first already is
// 2 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -933,14 +934,14 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_12)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment (subtractable)
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second) = {CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
}, true};
// 1 main address selfsend
tx_proposal.explicit_selfsend_proposals.emplace_back().first.proposal = CarrotPaymentProposalSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals).first.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.carrot_account_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.enote_type = CarrotEnoteType::PAYMENT,
@@ -948,7 +949,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_12)
};
// 1 subaddress selfsend (subtractable)
tx_proposal.explicit_selfsend_proposals.emplace_back().first = CarrotPaymentProposalVerifiableSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals) = {CarrotPaymentProposalVerifiableSelfSendV1{
.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.subaddress({{4, 19}}).address_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
@@ -980,7 +981,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_13)
acc1.generate(AddressDeriveType::PreCarrot);
// 1 normal payment (subtractable)
CarrotPaymentProposalV1 &normal_payment_proposal = tx_proposal.per_account_payments[0].second.emplace_back().first;
CarrotPaymentProposalV1 &normal_payment_proposal = tools::add_element( tx_proposal.per_account_payments[0].second).first;
normal_payment_proposal = CarrotPaymentProposalV1{
.destination = acc0.cryptonote_address(),
.amount = crypto::rand_idx((rct::xmr_amount) 1ull << 63),
@@ -1021,21 +1022,21 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_14)
tx_proposal.self_sender_index = 2;
// 1 subaddress payment (subtractable)
acc0.second.emplace_back().first = CarrotPaymentProposalV1{ = {CarrotPaymentProposalV1{
tools::add_element(acc0.second) = {CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
}, true};
// 1 main address payment
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second).first = CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
};
// 1 integrated address payment (subtractable)
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second) = {CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -1071,7 +1072,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_15)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment (subtractable)
acc0.second.emplace_back().first = CarrotPaymentProposalV1{ = {CarrotPaymentProposalV1{
tools::add_element(acc0.second) = {CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -1080,7 +1081,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_15)
acc0.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 2 main address payment (subtractable)
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second) = {CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -1089,7 +1090,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_15)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment (subtractable)
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second) = {CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -1125,7 +1126,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_16)
tx_proposal.self_sender_index = 2;
// 2 subaddress payment (subtractable)
acc0.second.emplace_back().first = CarrotPaymentProposalV1{ = {CarrotPaymentProposalV1{
tools::add_element(acc0.second) = {CarrotPaymentProposalV1{
.destination = acc0.first.subaddress({{2, 3}}),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -1134,7 +1135,7 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_16)
acc0.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 2 main address payment (subtractable)
acc1.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc1.second) = {CarrotPaymentProposalV1{
.destination = acc1.first.cryptonote_address(),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
@@ -1143,22 +1144,22 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_16)
acc1.second.back().first.randomness = gen_janus_anchor(); //mangle anchor_norm
// 1 integrated address payment (subtractable)
acc3.second.emplace_back().first = CarrotPaymentProposalV1{
tools::add_element(acc3.second) = {CarrotPaymentProposalV1{
.destination = acc3.first.cryptonote_address(gen_payment_id()),
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.randomness = gen_janus_anchor()
}, true};
// 1 main address selfsend (subtractable)
tx_proposal.explicit_selfsend_proposals.emplace_back() = {CarrotPaymentProposalSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals) = {{CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.carrot_account_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
.enote_type = CarrotEnoteType::PAYMENT,
// no internal messages for legacy self-sends
}, true};
}}, true};
// 1 subaddress selfsend (subtractable)
tx_proposal.explicit_selfsend_proposals.emplace_back() = {CarrotPaymentProposalVerifiableSelfSendV1{
tools::add_element(tx_proposal.explicit_selfsend_proposals) = {CarrotPaymentProposalVerifiableSelfSendV1{
.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = acc2.first.subaddress({{4, 19}}).address_spend_pubkey,
.amount = crypto::rand_idx<rct::xmr_amount>(1000000),
+2 -2
View File
@@ -157,7 +157,7 @@ TEST(x25519, scmul_key_convergence)
for (unsigned char j = 0; j < 8; ++j)
{
// add 2^i + j (sometimes with duplicates, which is okay)
mx25519_privkey &s = scalars.emplace_back();
mx25519_privkey &s = tools::add_element(scalars);
memset(s.data, 0, sizeof(mx25519_privkey));
const int msb_byte_index = i >> 3;
const int msb_bit_index = i & 7;
@@ -169,7 +169,7 @@ TEST(x25519, scmul_key_convergence)
scalars.push_back(hex2pod<mx25519_privkey>("ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f"));
// add random
const rct::key a = rct::skGen();
memcpy(scalars.emplace_back().data, &a, sizeof(mx25519_privkey));
memcpy(tools::add_element(scalars).data, &a, sizeof(mx25519_privkey));
std::vector<std::pair<rct::key, mx25519_pubkey>> points;
// add base point