mirror of
https://git.wownero.com/wownero/wownero.git
synced 2024-08-15 01:03:23 +00:00
miner block header signing
This commit is contained in:
parent
eb7d095731
commit
5cf05f27da
13 changed files with 91 additions and 6 deletions
|
@ -446,6 +446,7 @@ namespace cryptonote
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
crypto::hash prev_id;
|
crypto::hash prev_id;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
|
crypto::signature signature;
|
||||||
|
|
||||||
BEGIN_SERIALIZE()
|
BEGIN_SERIALIZE()
|
||||||
VARINT_FIELD(major_version)
|
VARINT_FIELD(major_version)
|
||||||
|
@ -453,6 +454,8 @@ namespace cryptonote
|
||||||
VARINT_FIELD(timestamp)
|
VARINT_FIELD(timestamp)
|
||||||
FIELD(prev_id)
|
FIELD(prev_id)
|
||||||
FIELD(nonce)
|
FIELD(nonce)
|
||||||
|
if (major_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
FIELD(signature)
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,10 @@ namespace boost
|
||||||
a & b.timestamp;
|
a & b.timestamp;
|
||||||
a & b.prev_id;
|
a & b.prev_id;
|
||||||
a & b.nonce;
|
a & b.nonce;
|
||||||
|
if (b.major_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
a & b.signature;
|
||||||
|
}
|
||||||
//------------------
|
//------------------
|
||||||
a & b.miner_tx;
|
a & b.miner_tx;
|
||||||
a & b.tx_hashes;
|
a & b.tx_hashes;
|
||||||
|
|
|
@ -1293,6 +1293,16 @@ namespace cryptonote
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
crypto::hash get_sig_data(const block& b)
|
||||||
|
{
|
||||||
|
crypto::hash sig_data;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << (b.nonce + b.timestamp);
|
||||||
|
std::string d(ss.str());
|
||||||
|
crypto::cn_fast_hash(d.data(), d.size(), sig_data);
|
||||||
|
return sig_data;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------
|
||||||
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
|
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
|
||||||
{
|
{
|
||||||
std::vector<uint64_t> res = off;
|
std::vector<uint64_t> res = off;
|
||||||
|
|
|
@ -121,6 +121,7 @@ namespace cryptonote
|
||||||
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob = NULL);
|
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);
|
bool get_block_hash(const block& b, crypto::hash& res);
|
||||||
crypto::hash get_block_hash(const block& b);
|
crypto::hash get_block_hash(const block& b);
|
||||||
|
crypto::hash get_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, 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);
|
||||||
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, crypto::hash &block_hash);
|
||||||
|
|
|
@ -45,6 +45,8 @@
|
||||||
#include "storages/portable_storage_template_helper.h"
|
#include "storages/portable_storage_template_helper.h"
|
||||||
#include "boost/logic/tribool.hpp"
|
#include "boost/logic/tribool.hpp"
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
|
@ -574,6 +576,27 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
|
|
||||||
b.nonce = nonce;
|
b.nonce = nonce;
|
||||||
|
|
||||||
|
// Miner Block Header Signing
|
||||||
|
if (b.major_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
// read one-time stealth keys from file
|
||||||
|
std::ifstream keys_file("stealth.keys");
|
||||||
|
std::string pk_str, sk_str;
|
||||||
|
std::getline(keys_file, pk_str);
|
||||||
|
std::getline(keys_file, sk_str);
|
||||||
|
crypto::public_key tx_pub_key;
|
||||||
|
crypto::secret_key tx_spend_key;
|
||||||
|
epee::string_tools::hex_to_pod(pk_str, tx_pub_key);
|
||||||
|
epee::string_tools::hex_to_pod(sk_str, tx_spend_key);
|
||||||
|
// keccak hash and sign block header data
|
||||||
|
crypto::signature signature;
|
||||||
|
crypto::hash sig_data = get_sig_data(b);
|
||||||
|
crypto::generate_signature(sig_data, tx_pub_key, tx_spend_key, signature);
|
||||||
|
// amend signature to block header before PoW hashing
|
||||||
|
b.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
crypto::hash h;
|
crypto::hash h;
|
||||||
m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
|
m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#define CURRENT_TRANSACTION_VERSION 2
|
#define CURRENT_TRANSACTION_VERSION 2
|
||||||
#define CURRENT_BLOCK_MAJOR_VERSION 7
|
#define CURRENT_BLOCK_MAJOR_VERSION 7
|
||||||
#define CURRENT_BLOCK_MINOR_VERSION 7
|
#define CURRENT_BLOCK_MINOR_VERSION 7
|
||||||
|
#define BLOCK_HEADER_MINER_SIG 18
|
||||||
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 300*2
|
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 300*2
|
||||||
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2
|
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2
|
||||||
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 4
|
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 4
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/range/adaptor/reversed.hpp>
|
#include <boost/range/adaptor/reversed.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
||||||
|
@ -1381,6 +1383,23 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||||
// a non-overflowing tx amount (dubious necessity on this check)
|
// a non-overflowing tx amount (dubious necessity on this check)
|
||||||
bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version)
|
bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version)
|
||||||
{
|
{
|
||||||
|
// Miner Block Header Signing
|
||||||
|
if (hf_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
// keccak hash block header data and check miner signature
|
||||||
|
// if signature is invalid, reject block
|
||||||
|
crypto::hash sig_data = get_sig_data(b);
|
||||||
|
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(b.miner_tx);
|
||||||
|
crypto::signature signature = b.signature;
|
||||||
|
if (!crypto::check_signature(sig_data, tx_pub_key, signature))
|
||||||
|
{
|
||||||
|
MWARNING("Miner signature is invalid");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG_PRINT_L1("Miner signature is good");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||||
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
|
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
|
||||||
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.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
|
||||||
|
@ -1795,7 +1814,8 @@ 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
|
//make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
|
||||||
uint8_t hf_version = b.major_version;
|
uint8_t hf_version = b.major_version;
|
||||||
size_t max_outs = hf_version >= 4 ? 1 : 11;
|
size_t max_outs = hf_version >= 4 ? 1 : 11;
|
||||||
bool r = construct_miner_tx(this, m_nettype, height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
keypair txkey = keypair::generate(hw::get_device("default"));
|
||||||
|
bool r = construct_miner_tx(this, txkey, m_nettype, height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
|
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);
|
size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
|
||||||
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
||||||
|
@ -1804,8 +1824,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||||
#endif
|
#endif
|
||||||
for (size_t try_count = 0; try_count != 10; ++try_count)
|
for (size_t try_count = 0; try_count != 10; ++try_count)
|
||||||
{
|
{
|
||||||
r = construct_miner_tx(this, m_nettype, height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
r = construct_miner_tx(this, txkey, m_nettype, height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
||||||
|
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
|
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
|
||||||
size_t coinbase_weight = get_transaction_weight(b.miner_tx);
|
size_t coinbase_weight = get_transaction_weight(b.miner_tx);
|
||||||
if (coinbase_weight > cumulative_weight - txs_weight)
|
if (coinbase_weight > cumulative_weight - txs_weight)
|
||||||
|
@ -1848,6 +1867,20 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||||
", cumulative weight " << cumulative_weight << " is now good");
|
", cumulative weight " << cumulative_weight << " is now good");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Miner Block Header Signing
|
||||||
|
if (b.major_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
// save one-time stealth address keys to file
|
||||||
|
std::string pk_str, sk_str;
|
||||||
|
pk_str = epee::string_tools::pod_to_hex(txkey.pub);
|
||||||
|
sk_str = epee::string_tools::pod_to_hex(txkey.sec);
|
||||||
|
std::ofstream keys_file;
|
||||||
|
keys_file.open("stealth.keys");
|
||||||
|
keys_file << pk_str << std::endl << sk_str;
|
||||||
|
keys_file.close();
|
||||||
|
b.signature = {};
|
||||||
|
}
|
||||||
|
|
||||||
if (!from_block)
|
if (!from_block)
|
||||||
cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, seed_height, seed_hash, pool_cookie);
|
cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, seed_height, seed_hash, pool_cookie);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -76,12 +76,11 @@ namespace cryptonote
|
||||||
LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses");
|
LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses");
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
bool construct_miner_tx(const Blockchain *pb, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
|
bool construct_miner_tx(const Blockchain *pb, const keypair& txkey, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
|
||||||
tx.vin.clear();
|
tx.vin.clear();
|
||||||
tx.vout.clear();
|
tx.vout.clear();
|
||||||
tx.extra.clear();
|
tx.extra.clear();
|
||||||
|
|
||||||
keypair txkey = keypair::generate(hw::get_device("default"));
|
|
||||||
add_tx_pub_key_to_extra(tx, txkey.pub);
|
add_tx_pub_key_to_extra(tx, txkey.pub);
|
||||||
if(!extra_nonce.empty())
|
if(!extra_nonce.empty())
|
||||||
if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
|
if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
class Blockchain;
|
class Blockchain;
|
||||||
bool construct_miner_tx(const Blockchain *pb, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
|
bool construct_miner_tx(const Blockchain *pb, const keypair& txkey, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
|
||||||
|
|
||||||
struct tx_source_entry
|
struct tx_source_entry
|
||||||
{
|
{
|
||||||
|
|
|
@ -2087,6 +2087,10 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
b.nonce = req.starting_nonce;
|
b.nonce = req.starting_nonce;
|
||||||
|
if (b.major_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
b.signature = {};
|
||||||
|
}
|
||||||
crypto::hash seed_hash = crypto::null_hash;
|
crypto::hash seed_hash = crypto::null_hash;
|
||||||
if (b.major_version >= RX_BLOCK_VERSION && !epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash))
|
if (b.major_version >= RX_BLOCK_VERSION && !epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash))
|
||||||
{
|
{
|
||||||
|
|
|
@ -895,6 +895,10 @@ namespace rpc
|
||||||
header.minor_version = b.minor_version;
|
header.minor_version = b.minor_version;
|
||||||
header.timestamp = b.timestamp;
|
header.timestamp = b.timestamp;
|
||||||
header.nonce = b.nonce;
|
header.nonce = b.nonce;
|
||||||
|
if (b.major_version >= BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
header.signature = b.signature;
|
||||||
|
}
|
||||||
header.prev_id = b.prev_id;
|
header.prev_id = b.prev_id;
|
||||||
|
|
||||||
header.depth = m_core.get_current_blockchain_height() - header.height - 1;
|
header.depth = m_core.get_current_blockchain_height() - header.height - 1;
|
||||||
|
|
|
@ -164,6 +164,7 @@ namespace rpc
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
crypto::hash prev_id;
|
crypto::hash prev_id;
|
||||||
uint32_t nonce;
|
uint32_t nonce;
|
||||||
|
crypto::signature signature;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
uint64_t depth;
|
uint64_t depth;
|
||||||
crypto::hash hash;
|
crypto::hash hash;
|
||||||
|
|
|
@ -312,6 +312,7 @@ void toJsonValue(rapidjson::Writer<epee::byte_stream>& dest, const cryptonote::b
|
||||||
INSERT_INTO_JSON_OBJECT(dest, timestamp, b.timestamp);
|
INSERT_INTO_JSON_OBJECT(dest, timestamp, b.timestamp);
|
||||||
INSERT_INTO_JSON_OBJECT(dest, prev_id, b.prev_id);
|
INSERT_INTO_JSON_OBJECT(dest, prev_id, b.prev_id);
|
||||||
INSERT_INTO_JSON_OBJECT(dest, nonce, b.nonce);
|
INSERT_INTO_JSON_OBJECT(dest, nonce, b.nonce);
|
||||||
|
INSERT_INTO_JSON_OBJECT(dest, signature, b.signature);
|
||||||
INSERT_INTO_JSON_OBJECT(dest, miner_tx, b.miner_tx);
|
INSERT_INTO_JSON_OBJECT(dest, miner_tx, b.miner_tx);
|
||||||
INSERT_INTO_JSON_OBJECT(dest, tx_hashes, b.tx_hashes);
|
INSERT_INTO_JSON_OBJECT(dest, tx_hashes, b.tx_hashes);
|
||||||
|
|
||||||
|
@ -331,6 +332,7 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::block& b)
|
||||||
GET_FROM_JSON_OBJECT(val, b.timestamp, timestamp);
|
GET_FROM_JSON_OBJECT(val, b.timestamp, timestamp);
|
||||||
GET_FROM_JSON_OBJECT(val, b.prev_id, prev_id);
|
GET_FROM_JSON_OBJECT(val, b.prev_id, prev_id);
|
||||||
GET_FROM_JSON_OBJECT(val, b.nonce, nonce);
|
GET_FROM_JSON_OBJECT(val, b.nonce, nonce);
|
||||||
|
GET_FROM_JSON_OBJECT(val, b.signature, signature);
|
||||||
GET_FROM_JSON_OBJECT(val, b.miner_tx, miner_tx);
|
GET_FROM_JSON_OBJECT(val, b.miner_tx, miner_tx);
|
||||||
GET_FROM_JSON_OBJECT(val, b.tx_hashes, tx_hashes);
|
GET_FROM_JSON_OBJECT(val, b.tx_hashes, tx_hashes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue