miner block header signing
This commit is contained in:
parent
2ddaa7835c
commit
48841789cb
|
@ -461,6 +461,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)
|
||||||
|
@ -468,6 +469,8 @@ namespace cryptonote
|
||||||
VARINT_FIELD(timestamp)
|
VARINT_FIELD(timestamp)
|
||||||
FIELD(prev_id)
|
FIELD(prev_id)
|
||||||
FIELD(nonce)
|
FIELD(nonce)
|
||||||
|
if (major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
|
||||||
|
FIELD(signature)
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,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 >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
a & b.signature;
|
||||||
|
}
|
||||||
//------------------
|
//------------------
|
||||||
a & b.miner_tx;
|
a & b.miner_tx;
|
||||||
a & b.tx_hashes;
|
a & b.tx_hashes;
|
||||||
|
|
|
@ -1490,6 +1490,25 @@ namespace cryptonote
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
crypto::hash get_sig_data(const block& b)
|
||||||
|
{
|
||||||
|
crypto::hash sig_data;
|
||||||
|
blobdata blob = get_block_hashing_blob_sig_data(b);
|
||||||
|
crypto::cn_fast_hash(blob.data(), blob.size(), sig_data);
|
||||||
|
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> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
|
||||||
{
|
{
|
||||||
std::vector<uint64_t> res = off;
|
std::vector<uint64_t> res = off;
|
||||||
|
|
|
@ -124,6 +124,8 @@ 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);
|
||||||
|
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, 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);
|
||||||
|
|
|
@ -100,6 +100,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<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_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<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 mining", "", true};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -292,10 +293,22 @@ namespace cryptonote
|
||||||
command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds);
|
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_idle_threshold_percentage);
|
||||||
command_line::add_arg(desc, arg_bg_mining_miner_target_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)
|
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))
|
if(command_line::has_arg(vm, arg_extra_messages))
|
||||||
{
|
{
|
||||||
std::string buff;
|
std::string buff;
|
||||||
|
@ -574,6 +587,28 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
|
|
||||||
b.nonce = nonce;
|
b.nonce = nonce;
|
||||||
|
|
||||||
|
// Miner Block Header Signing
|
||||||
|
if (b.major_version >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
// tx key derivation
|
||||||
|
crypto::key_derivation derivation;
|
||||||
|
cryptonote::keypair in_ephemeral;
|
||||||
|
crypto::secret_key eph_secret_key;
|
||||||
|
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(b.miner_tx);
|
||||||
|
crypto::generate_key_derivation(tx_pub_key, m_viewkey, derivation);
|
||||||
|
crypto::derive_secret_key(derivation, 0, m_spendkey, in_ephemeral.sec);
|
||||||
|
eph_secret_key = in_ephemeral.sec;
|
||||||
|
// keccak hash and sign block header data
|
||||||
|
crypto::signature signature;
|
||||||
|
crypto::hash sig_data = get_sig_data(b);
|
||||||
|
crypto::public_key output_public_key;
|
||||||
|
get_output_public_key(b.miner_tx.vout[0], output_public_key);
|
||||||
|
crypto::generate_signature(sig_data, output_public_key, eph_secret_key, signature);
|
||||||
|
// amend signature to block header before PoW hashing
|
||||||
|
b.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
crypto::hash h;
|
crypto::hash h;
|
||||||
|
|
||||||
if ((b.major_version >= RX_BLOCK_VERSION) && !rx_set)
|
if ((b.major_version >= RX_BLOCK_VERSION) && !rx_set)
|
||||||
|
|
|
@ -136,6 +136,8 @@ namespace cryptonote
|
||||||
i_miner_handler* m_phandler;
|
i_miner_handler* m_phandler;
|
||||||
get_block_hash_t m_gbh;
|
get_block_hash_t m_gbh;
|
||||||
account_public_address m_mine_address;
|
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<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<2> m_update_merge_hr_interval;
|
||||||
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;
|
epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;
|
||||||
|
|
|
@ -1414,6 +1414,35 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||||
// valid output types
|
// valid output types
|
||||||
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 >= HF_VERSION_BLOCK_HEADER_MINER_SIG)
|
||||||
|
{
|
||||||
|
// sanity checks
|
||||||
|
if (b.miner_tx.vout.size() != 1)
|
||||||
|
{
|
||||||
|
MWARNING("Only 1 output in miner transaction allowed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!check_output_types(b.miner_tx, hf_version))
|
||||||
|
{
|
||||||
|
MWARNING("Wrong txout type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// keccak hash block header data and check miner signature
|
||||||
|
// if signature is invalid, reject block
|
||||||
|
crypto::hash sig_data = get_sig_data(b);
|
||||||
|
crypto::signature signature = b.signature;
|
||||||
|
crypto::public_key output_public_key;
|
||||||
|
get_output_public_key(b.miner_tx.vout[0], output_public_key);
|
||||||
|
if (!crypto::check_signature(sig_data, output_public_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");
|
||||||
|
|
|
@ -2257,6 +2257,10 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
b.nonce = req.starting_nonce;
|
b.nonce = req.starting_nonce;
|
||||||
|
if (b.major_version >= HF_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 >= HF_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;
|
||||||
|
|
|
@ -313,6 +313,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);
|
||||||
|
|
||||||
|
@ -332,6 +333,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…
Reference in New Issue