Compare commits
4 Commits
v1.0.0-rc2
...
v1.0.0-rc3
| Author | SHA1 | Date | |
|---|---|---|---|
| 1667514896 | |||
| 041cd03098 | |||
| 0c4998b091 | |||
| 7f25459169 |
@@ -336,6 +336,34 @@ void carrot_and_legacy_account::set_keys(const cryptonote::account_keys& keys, b
|
||||
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
|
||||
@@ -354,6 +382,7 @@ 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;
|
||||
@@ -361,6 +390,7 @@ 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();
|
||||
|
||||
@@ -153,6 +153,7 @@ 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(
|
||||
|
||||
@@ -1381,17 +1381,31 @@ namespace cryptonote
|
||||
|
||||
for (const auto &o: tx.vout)
|
||||
{
|
||||
if (hf_version >= HF_VERSION_CARROT)
|
||||
if (hf_version >= HF_VERSION_ENFORCE_CARROT)
|
||||
{
|
||||
// from v10, 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 {
|
||||
} 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 {
|
||||
// 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() << ", "
|
||||
|
||||
@@ -244,6 +244,7 @@
|
||||
#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
|
||||
|
||||
@@ -1404,6 +1404,11 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh
|
||||
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");
|
||||
}
|
||||
@@ -1516,6 +1521,7 @@ 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;
|
||||
@@ -1583,7 +1589,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 (hf_version >= HF_VERSION_CARROT) {
|
||||
if (get_ideal_hard_fork_version(matured_height) >= 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;
|
||||
@@ -1981,11 +1987,14 @@ 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 (b.major_version >= HF_VERSION_CARROT) {
|
||||
std::vector<std::pair<yield_tx_info_carrot, uint64_t>> carrot_yield_payouts;
|
||||
if (hf_submitted >= HF_VERSION_CARROT) {
|
||||
if (!calculate_yield_payouts(start_height, carrot_yield_payouts)) {
|
||||
LOG_ERROR("Failed to obtain yield payout information - aborting");
|
||||
return false;
|
||||
@@ -1997,11 +2006,8 @@ 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 (b.major_version >= HF_VERSION_CARROT) {
|
||||
if (!carrot_yield_payouts.empty()) {
|
||||
for (const auto& yield_entry: carrot_yield_payouts) {
|
||||
cryptonote::protocol_data_entry entry;
|
||||
entry.amount_burnt = yield_entry.second;
|
||||
@@ -2020,6 +2026,7 @@ 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 {
|
||||
@@ -2040,6 +2047,7 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -3790,7 +3798,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 && epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(tx)) == "4f78ff511e860acd03138737a71505eb62eb78b620e180e58c8e13ed0e1e3e19") {
|
||||
if (tx.version == 1) {
|
||||
MERROR("v1 TXs are not permitted");
|
||||
tvc.m_version_mismatch = true;
|
||||
return false;
|
||||
@@ -3823,6 +3831,32 @@ 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");
|
||||
@@ -4086,20 +4120,6 @@ 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);
|
||||
@@ -4703,7 +4723,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, but no yield TXs found at height " << start_height << " - aborting");
|
||||
LOG_ERROR("calculate_yield_payouts() called for carrot, but no yield TXs found at height " << start_height << " - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4739,10 +4759,14 @@ 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;
|
||||
entry.second += yield_128.convert_to<uint64_t>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4801,10 +4825,14 @@ 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;
|
||||
entry.second += yield_128.convert_to<uint64_t>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1022,7 +1022,7 @@ namespace cryptonote
|
||||
}
|
||||
if (!rvv.empty())
|
||||
{
|
||||
LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
|
||||
LOG_PRINT_L1("Verifying transactions one at a time");
|
||||
ret = false;
|
||||
for (size_t n = 0; n < tx_info.size(); ++n)
|
||||
{
|
||||
|
||||
@@ -347,10 +347,12 @@ 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;
|
||||
|
||||
const bool do_carrot = hard_fork_version >= HF_VERSION_CARROT;
|
||||
if (do_carrot)
|
||||
const bool force_carrot = hard_fork_version >= HF_VERSION_ENFORCE_CARROT;
|
||||
if (force_carrot)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -371,7 +373,7 @@ namespace cryptonote
|
||||
memcpy(e.enote_ephemeral_pubkey.data, entry.return_pubkey.data, sizeof(crypto::public_key));
|
||||
enotes.push_back(e);
|
||||
}
|
||||
|
||||
carrot_found = true;
|
||||
tx = store_carrot_to_coinbase_transaction_v1(enotes, std::string{}, cryptonote::transaction_type::PROTOCOL, height);
|
||||
tx.amount_burnt = 0;
|
||||
tx.invalidate_hashes();
|
||||
@@ -394,14 +396,31 @@ 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,
|
||||
};
|
||||
|
||||
// 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);
|
||||
additional_tx_public_keys.push_back(entry.return_pubkey);
|
||||
tx.vout.push_back(out);
|
||||
carrot_found = true;
|
||||
} 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);
|
||||
noncarrot_found = true;
|
||||
}
|
||||
} else if (entry.type == cryptonote::transaction_type::AUDIT) {
|
||||
// PAYOUT
|
||||
LOG_PRINT_L2("Audit TX payout submitted " << entry.amount_burnt << entry.source_asset);
|
||||
@@ -411,9 +430,19 @@ namespace cryptonote
|
||||
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);
|
||||
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) {
|
||||
// Ensure the TX version is correct
|
||||
tx.version = TRANSACTION_VERSION_CARROT;
|
||||
}
|
||||
|
||||
// Add in all of the additional TX pubkeys we need to process the payments
|
||||
add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys);
|
||||
|
||||
@@ -565,6 +594,7 @@ 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,6 +71,7 @@ namespace cryptonote
|
||||
carrot::view_tag_t return_view_tag;
|
||||
carrot::encrypted_janus_anchor_t return_anchor_enc;
|
||||
uint64_t origin_height;
|
||||
bool is_carrot;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
@@ -92,6 +92,9 @@ 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);
|
||||
|
||||
@@ -192,6 +192,7 @@ 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"), ""};
|
||||
@@ -4424,12 +4425,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_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_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)
|
||||
{
|
||||
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\"");
|
||||
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\"");
|
||||
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_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_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())
|
||||
{
|
||||
if(!ask_wallet_create_if_needed()) return false;
|
||||
}
|
||||
@@ -4584,6 +4585,69 @@ 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;
|
||||
@@ -5049,6 +5113,7 @@ 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);
|
||||
@@ -5064,6 +5129,7 @@ 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() ||
|
||||
@@ -5287,8 +5353,9 @@ 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); }
|
||||
@@ -11829,6 +11896,7 @@ 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);
|
||||
|
||||
@@ -101,8 +101,11 @@ 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);
|
||||
@@ -430,6 +433,7 @@ 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
@@ -1,5 +1,5 @@
|
||||
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_SALVIUM_VERSION "1.0.0-rc2"
|
||||
#define DEF_SALVIUM_VERSION "1.0.0-rc3"
|
||||
#define DEF_MONERO_VERSION_TAG "release"
|
||||
#define DEF_MONERO_VERSION "0.18.3.4"
|
||||
#define DEF_MONERO_RELEASE_NAME "One"
|
||||
|
||||
@@ -5845,7 +5845,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,7 +5857,11 @@ 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);
|
||||
}
|
||||
|
||||
m_account.create_from_viewkey(account_public_address, viewkey);
|
||||
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);
|
||||
}
|
||||
init_type(hw::device::device_type::SOFTWARE);
|
||||
m_watch_only = true;
|
||||
m_account_public_address = account_public_address;
|
||||
|
||||
@@ -1019,6 +1019,7 @@ 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,
|
||||
|
||||
Reference in New Issue
Block a user