Compare commits

..

9 Commits

Author SHA1 Message Date
Some Random Crypto Guy 29e435bd39 added belt and braces to prevent CONVERT TXs from being attempted; integrated spend authority proof support into wallet; bumped version number 2024-12-16 14:07:37 +00:00
Some Random Crypto Guy 4abde92c1a bumped RC version 2024-12-16 09:18:47 +00:00
Some Random Crypto Guy dd23331df9 switched to single spend authority proof - the dummy proofs don't work as intended, so dropping them 2024-12-16 09:16:34 +00:00
Some Random Crypto Guy 7d2025bc19 interim checkin 2024-12-16 07:48:16 +00:00
Some Random Crypto Guy a01422a5e0 partial working serialisation 2024-12-15 22:28:14 +00:00
Some Random Crypto Guy e68f7f46ed fixed check on miner-staker split 2024-12-15 11:50:14 +00:00
Some Random Crypto Guy b87c243da1 fixed unit tests; fixed core tests; fixed performance tests; added fix to prevent change in block reward split (thanks Akil); added prelim code for spend authority proof - not complete / working 2024-12-15 11:09:46 +00:00
Some Random Crypto Guy 49fd907073 Merge branch 'main' into develop 2024-12-12 21:08:33 +00:00
Some Random Crypto Guy 8f5111aeda Merge branch 'main' into develop 2024-11-05 12:39:42 +00:00
13 changed files with 37 additions and 142 deletions
+1 -1
View File
@@ -109,7 +109,7 @@ jobs:
with:
name: ${{ matrix.toolchain.name }}
path: |
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-*
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-cli*
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salviumd*
- name: zip daemon & cli
run: |
+1 -1
View File
@@ -1,4 +1,4 @@
# Salvium Zero v0.7.2
# Salvium Zero v0.7.0-rc3
Copyright (c) 2023-2024, Salvium
Portions Copyright (c) 2014-2023, The Monero Project
Binary file not shown.
-2
View File
@@ -220,8 +220,6 @@
#define HF_VERSION_FULL_PROOFS 3
#define HF_VERSION_ENFORCE_FULL_PROOFS 4
#define HF_VERSION_REQUIRE_VIEW_TAGS 255
#define HF_VERSION_ENABLE_CONVERT 255
#define HF_VERSION_ENABLE_ORACLE 255
+25 -31
View File
@@ -1498,7 +1498,6 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
case HF_VERSION_BULLETPROOF_PLUS:
case HF_VERSION_ENABLE_N_OUTS:
case HF_VERSION_FULL_PROOFS:
case HF_VERSION_ENFORCE_FULL_PROOFS:
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;
@@ -1559,19 +1558,16 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
if (o.target.type() == typeid(txout_to_key)) {
txout_to_key out = boost::get<txout_to_key>(o.target);
CHECK_AND_ASSERT_MES(out.unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
CHECK_AND_ASSERT_MES(outputs.count(out.key) == 0, false, "Output duplicated in protocol_tx");
outputs[out.key] = std::make_tuple(out.asset_type, o.amount, out.unlock_time);
} else if (o.target.type() == typeid(txout_to_tagged_key)) {
txout_to_tagged_key out = boost::get<txout_to_tagged_key>(o.target);
CHECK_AND_ASSERT_MES(out.unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
CHECK_AND_ASSERT_MES(outputs.count(out.key) == 0, false, "Output duplicated in protocol_tx");
outputs[out.key] = std::make_tuple(out.asset_type, o.amount, out.unlock_time);
} else {
MERROR("Block at height: " << height << " attempting to add protocol transaction with invalid type " << o.target.type().name());
return false;
}
}
CHECK_AND_ASSERT_MES(outputs.size() == b.protocol_tx.vout.size(), false, "Mismatch between vout and outputs for protocol_tx - aborting");
// Maintain a count of outputs that we have verified
std::vector<crypto::public_key> outputs_verified;
@@ -3493,9 +3489,9 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
}
*/
// from v4, forbid invalid pubkeys
if (hf_version >= 1) {
if (hf_version >= 4) {
for (const auto &o: tx.vout) {
crypto::public_key output_public_key;
if (!get_output_public_key(o, output_public_key)) {
@@ -3508,7 +3504,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
}
/*
// from v8, allow bulletproofs
if (hf_version < 8) {
if (tx.version >= 2) {
@@ -3607,9 +3603,10 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
}
*/
// from v1, forbid bulletproofs
if (hf_version >= HF_VERSION_BULLETPROOF_PLUS) {
// from v16, forbid bulletproofs
if (hf_version > HF_VERSION_BULLETPROOF_PLUS) {
if (tx.version >= 2) {
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
if (bulletproof)
@@ -3620,19 +3617,11 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
}
*/
// from v4, only allow bulletproofs plus _with_ full proofs on RCT transactions
if (hf_version >= HF_VERSION_ENFORCE_FULL_PROOFS) {
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) {
if (hf_version >= HF_VERSION_FULL_PROOFS) {
if (tx.type == cryptonote::transaction_type::TRANSFER) {
if (tx.rct_signatures.type != rct::RCTTypeFullProofs) {
MERROR_VER("FullProofs required after v" + std::to_string(HF_VERSION_FULL_PROOFS));
tvc.m_invalid_output = true;
return false;
}
} else {
if (tx.rct_signatures.type != rct::RCTTypeNull) {
MERROR_VER("NULL RCT required for coinbase TXs after v" + std::to_string(HF_VERSION_FULL_PROOFS));
MERROR_VER("FullProofs required for TRANSFER TXs after v" + std::to_string(HF_VERSION_FULL_PROOFS));
tvc.m_invalid_output = true;
return false;
}
@@ -4051,17 +4040,6 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
// obviously, the original and simple rct APIs use a mixRing that's indexes
// in opposite orders, because it'd be too simple otherwise...
const rct::rctSig &rv = tx.rct_signatures;
// Check that after full proofs are enabled, the RCT version is set to enforce full proofs
if (hf_version >= HF_VERSION_ENFORCE_FULL_PROOFS)
{
if (rv.type != rct::RCTTypeNull && rv.type != rct::RCTTypeFullProofs)
{
MERROR_VER("Unsupported rct type (full proofs are required): " << rv.type);
return false;
}
}
switch (rv.type)
{
case rct::RCTTypeNull: {
@@ -4152,6 +4130,22 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
MERROR_VER("Unsupported rct type: " << rv.type);
return false;
}
// for bulletproofs, check they're only multi-output after v8
if (rct::is_rct_bulletproof(rv.type))
{
if (hf_version < 8)
{
for (const rct::Bulletproof &proof: rv.p.bulletproofs)
{
if (proof.V.size() > 1)
{
MERROR_VER("Multi output bulletproofs are invalid before v8");
return false;
}
}
}
}
}
return true;
}
-10
View File
@@ -923,16 +923,6 @@ namespace cryptonote
if (tx_info[n].tx->version < 2)
continue;
const rct::rctSig &rv = tx_info[n].tx->rct_signatures;
const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version();
if (hf_version >= HF_VERSION_ENFORCE_FULL_PROOFS) {
if (rv.type != rct::RCTTypeNull && rv.type != rct::RCTTypeFullProofs) {
MERROR_VER("Invalid RCT type provided");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
return false;
}
}
switch (rv.type) {
case rct::RCTTypeNull:
// coinbase should not come here, so we reject for all other types
@@ -590,7 +590,6 @@ namespace cryptonote
case HF_VERSION_BULLETPROOF_PLUS:
case HF_VERSION_ENABLE_N_OUTS:
case HF_VERSION_FULL_PROOFS:
case HF_VERSION_ENFORCE_FULL_PROOFS:
// 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;
+1 -7
View File
@@ -36,13 +36,7 @@ const hardfork_t mainnet_hard_forks[] = {
{ 1, 1, 0, 1341378000 },
// version 2 starts from block 89800, which is on or around the 4th of November, 2024. Fork time finalised on 2024-10-21. No fork voting occurs for the v2 fork.
{ 2, 89800, 0, 1729518000 },
// version 3 starts from block 121100, which is on or around the 19th of December, 2024. Fork time finalised on 2024-12-18. No fork voting occurs for the v3 fork.
{ 3, 121100, 0, 1734516900 },
// version 4 starts from block 121100, which is on or around the 20th of December, 2024. Fork time finalised on 2024-12-19. No fork voting occurs for the v4 fork.
{ 4, 121800, 0, 1734607000 },
{ 2, 89800, 0, 1729518000 },
};
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
+6 -80
View File
@@ -543,9 +543,6 @@ static bool compute_keys_for_destinations(
if (destinations[i].is_change) {
found_change = true;
change_index = output_index; // Store the change_index - we will need this
// Calculate the change spend key (x_change)
}
output_index++;
}
@@ -669,8 +666,6 @@ static void make_new_range_proofs(const int bp_version,
sigs.bulletproofs.push_back(rct::bulletproof_PROVE(output_amounts, output_amount_masks));
else if (bp_version == 4)
sigs.bulletproofs_plus.push_back(rct::bulletproof_plus_PROVE(output_amounts, output_amount_masks));
else if (bp_version == 5)
sigs.bulletproofs_plus.push_back(rct::bulletproof_plus_PROVE(output_amounts, output_amount_masks));
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
@@ -706,12 +701,6 @@ static bool try_reconstruct_range_proofs(const int bp_version,
return false;
return rct::bulletproof_plus_VERIFY(reconstructed_sigs.bulletproofs_plus);
}
else if (bp_version == 5)
{
if (not try_reconstruct_range_proofs(original_sigs.bulletproofs_plus, reconstructed_sigs.bulletproofs_plus))
return false;
return rct::bulletproof_plus_VERIFY(reconstructed_sigs.bulletproofs_plus);
}
return false;
}
@@ -829,10 +818,7 @@ static bool set_tx_rct_signatures(
const bool reconstruction,
cryptonote::transaction& unsigned_tx,
std::vector<CLSAG_context_t>& CLSAG_contexts,
rct::keyV& cached_w,
const uint8_t change_index,
const rct::key& x_change,
const rct::key& hs_yF
rct::keyV& cached_w
)
{
if (rct_config.bp_version != 3 &&
@@ -933,38 +919,15 @@ static bool set_tx_rct_signatures(
sc_sub(difference.bytes, sumpouts.bytes, sumouts.bytes);
rct::genC(rv.p_r, difference, 0);
if (rv.type == rct::RCTTypeFullProofs) {
rv.pr_proof = rct::PRProof_Gen(difference);
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(rct::PRProof_Ver(rv.p_r, rv.pr_proof), "PRProof_Ver() failed on recently created proof");
#endif
rv.pr_proof = PRProof_Gen(difference);
}
/*
// Check if spend authority proof is needed (only for TRANSFER TXs)
if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) {
rv.sa_proof = rct::SAProof_Gen(output_public_keys[change_index], x_change, hs_yF);
#ifdef DBG
CHECK_AND_ASSERT_THROW_MES(rct::SAProof_Ver(rv.sa_proof, output_public_keys[change_index], hs_yF), "SAProof_Ver() failed on recently created proof");
#endif
}
*/
}
// check balance if reconstructing the tx
else {
rv.p.pseudoOuts = unsigned_tx.rct_signatures.p.pseudoOuts;
if (rv.type == rct::RCTTypeFullProofs) {
if (!rct::PRProof_Ver(unsigned_tx.rct_signatures.p_r, unsigned_tx.rct_signatures.pr_proof))
return false;
rv.p_r = unsigned_tx.rct_signatures.p_r;
rv.pr_proof = unsigned_tx.rct_signatures.pr_proof;
/*
if (!rct::SAProof_Ver(unsigned_tx.rct_signatures.sa_proof, output_public_keys[change_index], hs_yF))
return false;
rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction
*/
} else {
rv.p_r = unsigned_tx.rct_signatures.p_r;
}
rv.pr_proof = unsigned_tx.rct_signatures.pr_proof; // should verify this during reconstruction
rv.sa_proof = unsigned_tx.rct_signatures.sa_proof; // should verify this during reconstruction
rv.p_r = unsigned_tx.rct_signatures.p_r;
if (num_sources != rv.p.pseudoOuts.size())
return false;
rct::key balance_accumulator = rct::scalarmultH(rct::d2h(fee));
@@ -1209,8 +1172,6 @@ bool tx_builder_ringct_t::init(
// Check that the change element was found
if (!found_change)
return false;
//
// add inputs to tx
set_tx_inputs(sources, unsigned_tx);
@@ -1225,8 +1186,6 @@ bool tx_builder_ringct_t::init(
if (not set_tx_outputs_result)
return false;
rct::key hs_yF;
rct::key x_change;
if (hf_version >= HF_VERSION_ENABLE_N_OUTS && unsigned_tx.type == cryptonote::transaction_type::TRANSFER) {
// Get the output public key for the change output
@@ -1262,7 +1221,6 @@ bool tx_builder_ringct_t::init(
rct::key key_F = rct::scalarmultKey(key_aP_change, key_inv_y);
rct::key key_verify = rct::scalarmultKey(key_F, key_y);
CHECK_AND_ASSERT_MES(key_verify == key_aP_change, false, "at get_return_address: failed to verify invert() function with smK() approach");
hs_yF = rct::hash_to_scalar(key_verify);
// Push the F point into the TX vector of F points
if (not reconstruction)
@@ -1283,38 +1241,6 @@ bool tx_builder_ringct_t::init(
unsigned_tx.return_address_change_mask.push_back(eci_data);
}
if (hf_version >= HF_VERSION_FULL_PROOFS) {
// Get the secret spend key for the change element
crypto::secret_key spend_skey = crypto::null_skey;
for (const auto &multisig_key : account_keys.m_multisig_keys) {
sc_add((unsigned char*)spend_skey.data,
(const unsigned char*)multisig_key.data,
(const unsigned char*)spend_skey.data);
}
// Calculate z_i (the shared secret between sender and ourselves for the original TX)
crypto::public_key txkey_pub = crypto::null_pkey; // R
const std::vector<crypto::public_key> in_additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(unsigned_tx);
if (in_additional_tx_pub_keys.size() != 0) {
CHECK_AND_ASSERT_MES(in_additional_tx_pub_keys.size() == unsigned_tx.vout.size(), false, "incorrect number of additional TX pubkeys in origin TX for return_payment");
txkey_pub = in_additional_tx_pub_keys[change_index];
} else {
txkey_pub = cryptonote::get_tx_pub_key_from_extra(unsigned_tx);
}
// Obtain a separate key_derivation for the P_change output
// (using the TX public key and the sender's private view key)
hw::device &hwdev = account_keys.get_device();
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
CHECK_AND_ASSERT_MES(hwdev.generate_key_derivation(txkey_pub, account_keys.m_view_secret_key, derivation), false, "Failed to generate key_derivation for P_change");
// Calculate the secret spend key "x_change" for the P_change output
crypto::secret_key s_change = crypto::null_skey;
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(derivation, change_index, spend_skey, s_change), false, "Failed to derive secret key for P_change");
x_change = rct::sk2rct(s_change);
}
} else if (unsigned_tx.type == cryptonote::transaction_type::TRANSFER || unsigned_tx.type == cryptonote::transaction_type::STAKE) {
// Get the tx public key
@@ -1327,7 +1253,7 @@ bool tx_builder_ringct_t::init(
// prepare input signatures
if (not set_tx_rct_signatures(fee, sources, destination_amounts, input_secret_keys, output_public_keys, output_amount_secret_keys,
rct_config, reconstruction, unsigned_tx, CLSAG_contexts, cached_w, change_index, x_change, hs_yF))
rct_config, reconstruction, unsigned_tx, CLSAG_contexts, cached_w))
return false;
initialized = true;
-2
View File
@@ -1383,7 +1383,6 @@ namespace rct {
#endif
}
/*
// Check if spend authority proof is needed (only for TRANSFER TXs)
if (tx_type == cryptonote::transaction_type::TRANSFER && rv.type == rct::RCTTypeFullProofs) {
rv.sa_proof = SAProof_Gen(destinations[change_index], x_change, key_yF);
@@ -1391,7 +1390,6 @@ namespace rct {
CHECK_AND_ASSERT_THROW_MES(SAProof_Ver(rv.sa_proof, destinations[change_index], key_yF), "SAProof_Ver() failed on recently created proof");
#endif
}
*/
key full_message = get_pre_mlsag_hash(rv,hwdev);
+1 -1
View File
@@ -88,7 +88,7 @@ namespace rct {
zk_proof PRProof_Gen(const rct::key &difference);
bool PRProof_Ver(const rct::key &C, const zk_proof &proof);
zk_proof SAProof_Gen(const key &P, const key &x_change, const key &key_yF);
zk_proof SAProof_Gen(const keyV &P, const key &x_change, const key &key_yF);
bool SAProof_Ver(const zk_proof &proof, const key &P, const key &key_yF);
//proveRange and verRange
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
#define DEF_SALVIUM_VERSION "0.7.2"
#define DEF_SALVIUM_VERSION "0.7.0-rc3"
#define DEF_MONERO_VERSION_TAG "release"
#define DEF_MONERO_VERSION "0.18.3.3"
#define DEF_MONERO_RELEASE_NAME "Zero"
+1 -5
View File
@@ -2856,7 +2856,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
update_multisig_rescan_info(*m_multisig_rescan_k, *m_multisig_rescan_info, m_transfers.size() - 1);
}
/*
// Verify the spend authority proof
if (!verify_spend_authority_proof(tx, o, tx_scan_info[o])) {
// Freeze the output
@@ -2864,7 +2863,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_ERROR("Please review the transaction and verify that the sender is someone you trust before thawing this payment.");
td.m_frozen = true;
}
*/
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (!ignore_callbacks && 0 != m_callback)
@@ -2982,8 +2980,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
THROW_WALLET_EXCEPTION_IF(td.get_public_key() != tx_scan_info[o].in_ephemeral.pub, error::wallet_internal_error, "Inconsistent public keys");
THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status");
/*
// Verify the spend authority proof
if (!verify_spend_authority_proof(tx, o, tx_scan_info[o])) {
// Freeze the output
@@ -2991,7 +2988,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_ERROR("Please review the transaction and verify that the sender is someone you trust before thawing this payment.");
td.m_frozen = true;
}
*/
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (!ignore_callbacks && 0 != m_callback)