Skip to content

Commit

Permalink
diardi: signing and verification of diardi blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Hayzam committed Aug 6, 2023
1 parent c8b53e3 commit e10df7e
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 72 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Scala

Copyright (c) 2014-2023, The Monero Project

Copyright (c) 2021-2023, Haku Labs MTÜ

Portions Copyright (c) 2012-2013 The Cryptonote developers.

[<img src="https://scalaproject.io/img/card.jpg">](https://scalaproject.io)
Expand Down
2 changes: 2 additions & 0 deletions src/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ list(APPEND crypto_sources CryptonightR_template.S)
endif()

include_directories(${RANDOMX_INCLUDE})
include_directories(${FELIDAE_INCLUDE})

set(crypto_headers)

Expand All @@ -71,6 +72,7 @@ target_link_libraries(cncrypto
PUBLIC
epee
randomx
felidae
${Boost_SYSTEM_LIBRARY}
${SODIUM_LIBRARY}
PRIVATE
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/hash-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,6 @@ void rx_seedheights(const uint64_t height, uint64_t *seed_height, uint64_t *next

void rx_set_main_seedhash(const char *seedhash, size_t max_dataset_init_threads);
void rx_slow_hash(const char *seedhash, const void *data, size_t length, char *result_hash);

void felidae_hash(const void *data, size_t length, char *hash, size_t extra_iterations);
void rx_set_miner_thread(uint32_t value, size_t max_dataset_init_threads);
uint32_t rx_get_miner_thread(void);
5 changes: 5 additions & 0 deletions src/crypto/rx-slow-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <unistd.h>
#include <limits.h>

#include "felidae.h"
#include "randomx.h"
#include "c_threads.h"
#include "hash-ops.h"
Expand Down Expand Up @@ -508,6 +509,10 @@ uint32_t rx_get_miner_thread() {
return miner_thread;
}

void felidae_hash(const void *data, size_t length, char *hash, size_t extra_iterations) {
felidae_calculate_hash(data, length, hash, extra_iterations);
}

void rx_slow_hash_allocate_state() {}

static void rx_destroy_vm(randomx_vm** vm) {
Expand Down
6 changes: 5 additions & 1 deletion src/cryptonote_basic/cryptonote_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -460,15 +460,19 @@ namespace cryptonote
uint8_t major_version;
uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built
uint64_t timestamp;
crypto::hash prev_id;
crypto::hash prev_id;
uint32_t nonce;
crypto::signature signature;

BEGIN_SERIALIZE()
VARINT_FIELD(major_version)
VARINT_FIELD(minor_version)
VARINT_FIELD(timestamp)
FIELD(prev_id)
FIELD(nonce)
if(major_version >= HF_VERSION_DIARDI_V2) {
FIELD(signature)
}
END_SERIALIZE()
};

Expand Down
26 changes: 23 additions & 3 deletions src/cryptonote_basic/cryptonote_format_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,17 @@ namespace cryptonote
//---------------------------------------------------------------
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h, hw::device &hwdev)
{
hwdev.get_transaction_prefix_hash(tx,h);
hwdev.get_transaction_prefix_hash(tx,h);
}

//---------------------------------------------------------------
//---------------------------------------------------------------
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx, hw::device &hwdev)
{
crypto::hash h = null_hash;
get_transaction_prefix_hash(tx, h, hwdev);
return h;
}

bool expand_transaction_1(transaction &tx, bool base_only)
{
if (tx.version >= 2 && !is_coinbase(tx))
Expand Down Expand Up @@ -1482,6 +1482,26 @@ namespace cryptonote
return p;
}
//---------------------------------------------------------------
crypto::hash get_sig_data(uint64_t height)
{
crypto::hash sig_data;
unsigned char input[sizeof(height)];
memcpy(input, &height, sizeof(height));
crypto::felidae_hash(input, sizeof(input), sig_data.data, 1);
return sig_data;
}
//---------------------------------------------------------------
blobdata get_block_hashing_blob_sig_data(const block& b)
{
block_header tmp = static_cast<const block_header&>(b);
memset(&tmp.signature, 0, sizeof(tmp.signature));
blobdata blob = t_serializable_object_to_blob(tmp);
crypto::hash tree_root_hash = get_tx_tree_hash(b);
blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash));
blob.append(tools::get_varint_data(b.tx_hashes.size()+1));
return blob;
}
//---------------------------------------------------------------
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
{
std::vector<uint64_t> res = off;
Expand Down
2 changes: 2 additions & 0 deletions src/cryptonote_basic/cryptonote_format_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ namespace cryptonote
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob = NULL);
bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b);
crypto::hash get_sig_data(uint64_t height);
blobdata get_block_hashing_blob_sig_data(const block& b);
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash);
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b);
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash);
Expand Down
24 changes: 24 additions & 0 deletions src/cryptonote_basic/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ namespace cryptonote
const command_line::arg_descriptor<uint64_t> arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true};
const command_line::arg_descriptor<uint16_t> arg_bg_mining_idle_threshold_percentage = {"bg-mining-idle-threshold", "Specify minimum avg idle percentage over lookback interval", miner::BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE, true};
const command_line::arg_descriptor<uint16_t> arg_bg_mining_miner_target_percentage = {"bg-mining-miner-target", "Specify maximum percentage cpu use by miner(s)", miner::BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE, true};
const command_line::arg_descriptor<std::string> arg_spendkey = {"spendkey", "Specify secret spend key used for Diardi mining", "", true};
}


Expand Down Expand Up @@ -293,10 +294,22 @@ namespace cryptonote
command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds);
command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage);
command_line::add_arg(desc, arg_bg_mining_miner_target_percentage);
command_line::add_arg(desc, arg_spendkey);
}
//-----------------------------------------------------------------------------------------------------
bool miner::init(const boost::program_options::variables_map& vm, network_type nettype)
{
if(command_line::has_arg(vm, arg_spendkey))
{
std::string skey_str = command_line::get_arg(vm, arg_spendkey);
crypto::secret_key spendkey;
epee::string_tools::hex_to_pod(skey_str, spendkey);
crypto::secret_key viewkey;
keccak((uint8_t *)&spendkey, 32, (uint8_t *)&viewkey, 32);
sc_reduce32((uint8_t *)&viewkey);
m_spendkey = spendkey;
m_viewkey = viewkey;
}
if(command_line::has_arg(vm, arg_extra_messages))
{
std::string buff;
Expand Down Expand Up @@ -565,6 +578,17 @@ namespace cryptonote
CRITICAL_REGION_END();
local_template_ver = m_template_no;
nonce = m_starter_nonce + th_local_index;

if(b.major_version >= HF_VERSION_DIARDI_V2) {
if(height % 4 == 0) {
crypto::signature signature;
crypto::hash sig_data = get_sig_data(height);
crypto::public_key m_pspendkey;
crypto::secret_key_to_public_key(m_spendkey, m_pspendkey);
crypto::generate_signature(sig_data, m_pspendkey, m_spendkey, signature);
b.signature = signature;
}
}
}

if(!local_template_ver)//no any set_block_template call
Expand Down
2 changes: 2 additions & 0 deletions src/cryptonote_basic/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ namespace cryptonote
i_miner_handler* m_phandler;
get_block_hash_t m_gbh;
account_public_address m_mine_address;
crypto::secret_key m_spendkey;
crypto::secret_key m_viewkey;
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;
Expand Down
1 change: 1 addition & 0 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
#define HF_VERSION_REJECT_SIGS_IN_COINBASE 12
#define HF_VERSION_ENFORCE_MIN_AGE 12
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 12
#define HF_VERSION_DIARDI_V2 13
#define HF_VERSION_EXACT_COINBASE 13
#define HF_VERSION_CLSAG 13
#define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 13
Expand Down
71 changes: 68 additions & 3 deletions src/cryptonote_core/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1416,6 +1416,65 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
return true;
}
//------------------------------------------------------------------
bool Blockchain::validate_diardi_miner_v2(const block& b) {
LOG_PRINT_L3("Blockchain::" << __func__);
uint8_t version = b.major_version;
uint64_t block_height = (b.miner_tx.vin.size() < 1 || b.miner_tx.vin[0].type() != typeid(txin_gen)) ? m_db->height() : boost::get<txin_gen>(b.miner_tx.vin[0]).height;
bool isDiardiBlock = (version >= 13 && block_height % 4 == 0);

if (!isDiardiBlock) {
return true;
}

std::list<std::string> diardi_miners_list = diardi_addresses_v2(m_nettype);

std::string tM;
std::string dM;
std::string vM;

cryptonote::address_parse_info temp_miner_address;
cryptonote::address_parse_info diardi_miner_address;

for(auto const& sM : diardi_miners_list) {
cryptonote::get_account_address_from_str(temp_miner_address, m_nettype, tM);
cryptonote::get_account_address_from_str(diardi_miner_address, m_nettype, sM);

if (temp_miner_address.address == diardi_miner_address.address) {
if(temp_miner_address.address.m_view_public_key == diardi_miner_address.address.m_view_public_key) {
crypto::hash sig_data = get_sig_data(block_height);
crypto::signature signature = b.signature;
crypto::public_key o_pspendkey = diardi_miner_address.address.m_spend_public_key;

vM = sM;

if (!crypto::check_signature(sig_data, o_pspendkey, signature)) {
LOG_PRINT_L1("Diardi: Miner Signature incorrect");
return false;
}

cryptonote::block oDb;
bool oOb = false;
bool getOldBlock = get_block_by_hash(m_db->get_block_hash_from_height((block_height -4)), oDb, &oOb);

if(!getOldBlock) {
LOG_PRINT_L1("Diardi: Could not get old block");
return false;
}

if(check_last_diardi_miner(this, vM, m_nettype)) {
LOG_PRINT_L1("Diardi: Miner already mined a block < 4 blocks ago");
return false;
}

return true;
}
}
}

LOG_PRINT_L1("Diardi: Miner not in list");
return false;
}
//------------------------------------------------------------------
// This function validates the miner transaction reward
bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_block_weight, uint64_t fee, uint64_t& base_reward, uint64_t already_generated_coins, bool &partial_block_reward, uint8_t version)
{
Expand Down Expand Up @@ -1798,7 +1857,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
//make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
uint8_t hf_version = b.major_version;
size_t max_outs = hf_version >= 4 ? 1 : 11;
bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version, m_nettype);
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
Expand All @@ -1807,7 +1866,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
#endif
for (size_t try_count = 0; try_count != 10; ++try_count)
{
r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version, m_nettype);

CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
size_t coinbase_weight = get_transaction_weight(b.miner_tx);
Expand Down Expand Up @@ -4663,7 +4722,6 @@ bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc)
{
try
{

LOG_PRINT_L3("Blockchain::" << __func__);
crypto::hash id = get_block_hash(bl);
CRITICAL_REGION_LOCAL(m_tx_pool);//to avoid deadlock lets lock tx_pool for whole add/reorganize process
Expand All @@ -4677,6 +4735,13 @@ bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc)
return false;
}

if(!validate_diardi_miner_v2(bl)) {
LOG_PRINT_L1("Diardi validation failed for block with id <" << id << ">");
bvc.m_added_to_main_chain = false;
m_blocks_txs_check.clear();
return true;
}

//check that block refers to chain tail
if(!(bl.prev_id == get_tail_id()))
{
Expand Down
8 changes: 8 additions & 0 deletions src/cryptonote_core/blockchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -1609,5 +1609,13 @@ namespace cryptonote
* @param already_generated_coins total coins mined by the network so far
*/
void send_miner_notifications(uint64_t height, const crypto::hash &seed_hash, const crypto::hash &prev_id, uint64_t already_generated_coins);

/**
* @brief check if the diardi miner v2 block is valid
* @param b
* @return true if valid, otherwise false
*/

bool validate_diardi_miner_v2(const block &b);
};
} // namespace cryptonote
Loading

0 comments on commit e10df7e

Please sign in to comment.