Added SAL support
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cryptonote_basic.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "serialization/keyvalue_serialization.h"
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
struct account_keys
|
||||
{
|
||||
account_public_address m_account_address;
|
||||
crypto::secret_key m_spend_secret_key;
|
||||
crypto::secret_key m_view_secret_key;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(m_account_address)
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_secret_key)
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_secret_key)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
class account_base
|
||||
{
|
||||
public:
|
||||
account_base();
|
||||
void generate();
|
||||
const account_keys& get_keys() const;
|
||||
std::string get_public_address_str();
|
||||
|
||||
uint64_t get_createtime() const { return m_creation_timestamp; }
|
||||
void set_createtime(uint64_t val) { m_creation_timestamp = val; }
|
||||
|
||||
bool load(const std::string& file_path);
|
||||
bool store(const std::string& file_path);
|
||||
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive &a, const unsigned int /*ver*/)
|
||||
{
|
||||
a & m_keys;
|
||||
a & m_creation_timestamp;
|
||||
}
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(m_keys)
|
||||
KV_SERIALIZE(m_creation_timestamp)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
||||
private:
|
||||
void set_null();
|
||||
account_keys m_keys;
|
||||
uint64_t m_creation_timestamp;
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cryptonote_basic.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
|
||||
namespace cryptonote {
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
template<class t_array>
|
||||
struct array_hasher: std::unary_function<t_array&, std::size_t>
|
||||
{
|
||||
std::size_t operator()(const t_array& val) const
|
||||
{
|
||||
return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct public_address_outer_blob
|
||||
{
|
||||
uint8_t m_ver;
|
||||
account_public_address m_address;
|
||||
uint8_t check_sum;
|
||||
};
|
||||
#pragma pack (pop)
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Cryptonote helper functions */
|
||||
/************************************************************************/
|
||||
size_t get_max_block_size();
|
||||
size_t get_max_tx_size();
|
||||
bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward);
|
||||
uint8_t get_account_address_checksum(const public_address_outer_blob& bl);
|
||||
std::string get_account_address_as_str(const account_public_address& adr);
|
||||
bool get_account_address_from_str(account_public_address& adr, const std::string& str);
|
||||
bool is_coinbase(const transaction& tx);
|
||||
|
||||
bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b);
|
||||
bool operator ==(const cryptonote::block& a, const cryptonote::block& b);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::ostream &print256(std::ostream &o, const T &v) {
|
||||
return o << "<" << epee::string_tools::pod_to_hex(v) << ">";
|
||||
}
|
||||
|
||||
bool parse_hash256(const std::string str_hash, crypto::hash& hash);
|
||||
|
||||
namespace crypto {
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); }
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); }
|
||||
}
|
||||
@@ -0,0 +1,434 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "include_base_utils.h"
|
||||
using namespace epee;
|
||||
|
||||
#include "cryptonote_format_utils.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include "cryptonote_config.h"
|
||||
#include "miner.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "serialization/binary_utils.h"
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h)
|
||||
{
|
||||
std::ostringstream s;
|
||||
if (tx.blob_type == BLOB_TYPE_CRYPTONOTE_RYO) s << "ryo-currency";
|
||||
binary_archive<true> a(s);
|
||||
::serialization::serialize(a, const_cast<transaction_prefix&>(tx));
|
||||
crypto::cn_fast_hash(s.str().data(), s.str().size(), h);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx)
|
||||
{
|
||||
crypto::hash h = null_hash;
|
||||
get_transaction_prefix_hash(tx, h);
|
||||
return h;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tx_blob;
|
||||
binary_archive<false> ba(ss);
|
||||
bool r = ::serialization::serialize(ba, tx);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tx_blob;
|
||||
binary_archive<false> ba(ss);
|
||||
bool r = ::serialization::serialize(ba, tx);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
||||
//TODO: validate tx
|
||||
|
||||
crypto::cn_fast_hash(tx_blob.data(), tx_blob.size(), tx_hash);
|
||||
get_transaction_prefix_hash(tx, tx_prefix_hash);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields)
|
||||
{
|
||||
tx_extra_fields.clear();
|
||||
|
||||
if(tx_extra.empty())
|
||||
return true;
|
||||
|
||||
std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
|
||||
std::istringstream iss(extra_str);
|
||||
binary_archive<false> ar(iss);
|
||||
|
||||
bool eof = false;
|
||||
while (!eof)
|
||||
{
|
||||
tx_extra_field field;
|
||||
bool r = ::do_serialize(ar, field);
|
||||
CHECK_AND_NO_ASSERT_MES(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
|
||||
tx_extra_fields.push_back(field);
|
||||
|
||||
std::ios_base::iostate state = iss.rdstate();
|
||||
eof = (EOF == iss.peek());
|
||||
iss.clear(state);
|
||||
}
|
||||
CHECK_AND_NO_ASSERT_MES(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra)
|
||||
{
|
||||
std::vector<tx_extra_field> tx_extra_fields;
|
||||
parse_tx_extra(tx_extra, tx_extra_fields);
|
||||
|
||||
tx_extra_pub_key pub_key_field;
|
||||
if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field))
|
||||
return null_pkey;
|
||||
|
||||
return pub_key_field.pub_key;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx)
|
||||
{
|
||||
return get_tx_pub_key_from_extra(tx.extra);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key)
|
||||
{
|
||||
tx.extra.resize(tx.extra.size() + 1 + sizeof(crypto::public_key));
|
||||
tx.extra[tx.extra.size() - 1 - sizeof(crypto::public_key)] = TX_EXTRA_TAG_PUBKEY;
|
||||
*reinterpret_cast<crypto::public_key*>(&tx.extra[tx.extra.size() - sizeof(crypto::public_key)]) = tx_pub_key;
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max");
|
||||
size_t start_pos = tx_extra.size();
|
||||
tx_extra.resize(tx_extra.size() + 2 + extra_nonce.size());
|
||||
//write tag
|
||||
tx_extra[start_pos] = TX_EXTRA_NONCE;
|
||||
//write len
|
||||
++start_pos;
|
||||
tx_extra[start_pos] = static_cast<uint8_t>(extra_nonce.size());
|
||||
//write data
|
||||
++start_pos;
|
||||
memcpy(&tx_extra[start_pos], extra_nonce.data(), extra_nonce.size());
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool append_mm_tag_to_extra(std::vector<uint8_t>& tx_extra, const tx_extra_merge_mining_tag& mm_tag)
|
||||
{
|
||||
blobdata blob;
|
||||
if (!t_serializable_object_to_blob(mm_tag, blob))
|
||||
return false;
|
||||
|
||||
tx_extra.push_back(TX_EXTRA_MERGE_MINING_TAG);
|
||||
std::copy(reinterpret_cast<const uint8_t*>(blob.data()), reinterpret_cast<const uint8_t*>(blob.data() + blob.size()), std::back_inserter(tx_extra));
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_mm_tag_from_extra(const std::vector<uint8_t>& tx_extra, tx_extra_merge_mining_tag& mm_tag)
|
||||
{
|
||||
std::vector<tx_extra_field> tx_extra_fields;
|
||||
if (!parse_tx_extra(tx_extra, tx_extra_fields))
|
||||
return false;
|
||||
|
||||
return find_tx_extra_field_by_type(tx_extra_fields, mm_tag);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id)
|
||||
{
|
||||
extra_nonce.clear();
|
||||
extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID);
|
||||
const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id);
|
||||
std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce));
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id)
|
||||
{
|
||||
if(sizeof(crypto::hash) + 1 != extra_nonce.size())
|
||||
return false;
|
||||
if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0])
|
||||
return false;
|
||||
payment_id = *reinterpret_cast<const crypto::hash*>(extra_nonce.data() + 1);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::string short_hash_str(const crypto::hash& h)
|
||||
{
|
||||
std::string res = string_tools::pod_to_hex(h);
|
||||
CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion");
|
||||
auto erased_pos = res.erase(8, 48);
|
||||
res.insert(8, "....");
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void get_blob_hash(const blobdata& blob, crypto::hash& res)
|
||||
{
|
||||
cn_fast_hash(blob.data(), blob.size(), res);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_blob_hash(const blobdata& blob)
|
||||
{
|
||||
crypto::hash h = null_hash;
|
||||
get_blob_hash(blob, h);
|
||||
return h;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_transaction_hash(const transaction& t)
|
||||
{
|
||||
crypto::hash h = null_hash;
|
||||
size_t blob_size = 0;
|
||||
get_object_hash(t, h, blob_size);
|
||||
return h;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res)
|
||||
{
|
||||
size_t blob_size = 0;
|
||||
return get_object_hash(t, res, blob_size);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
|
||||
{
|
||||
// v1 transactions hash the entire blob
|
||||
if (t.version == 1 && t.blob_type != BLOB_TYPE_CRYPTONOTE2 && t.blob_type != BLOB_TYPE_CRYPTONOTE3)
|
||||
{
|
||||
size_t ignored_blob_size, &blob_size_ref = blob_size ? *blob_size : ignored_blob_size;
|
||||
return get_object_hash(t, res, blob_size_ref);
|
||||
}
|
||||
|
||||
// v2 transactions hash different parts together, than hash the set of those hashes
|
||||
crypto::hash hashes[3];
|
||||
|
||||
// prefix
|
||||
get_transaction_prefix_hash(t, hashes[0]);
|
||||
|
||||
transaction &tt = const_cast<transaction&>(t);
|
||||
|
||||
// base rct
|
||||
{
|
||||
std::stringstream ss;
|
||||
binary_archive<true> ba(ss);
|
||||
const size_t inputs = t.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM ? t.vin_salvium.size() : (t.blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR ? t.vin_zephyr.size() : t.vin.size());
|
||||
const size_t outputs = t.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM ? t.vout_salvium.size() : (t.blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR ? t.vout_zephyr.size() : (t.blob_type != BLOB_TYPE_CRYPTONOTE_XHV ? t.vout.size() : t.vout_xhv.size()));
|
||||
bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base");
|
||||
cryptonote::get_blob_hash(ss.str(), hashes[1]);
|
||||
}
|
||||
|
||||
// prunable rct
|
||||
if (t.rct_signatures.type == rct::RCTTypeNull)
|
||||
{
|
||||
hashes[2] = cryptonote::null_hash;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
binary_archive<true> ba(ss);
|
||||
const size_t inputs = t.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM ? t.vin_salvium.size() : (t.blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR ? t.vin_zephyr.size() : t.vin.size());
|
||||
const size_t outputs = t.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM ? t.vout_salvium.size() : (t.blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR ? t.vout_zephyr.size() : (t.blob_type != BLOB_TYPE_CRYPTONOTE_XHV ? t.vout.size() : t.vout_xhv.size()));
|
||||
size_t mixin;
|
||||
if (t.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM) {
|
||||
mixin = t.vin_salvium.empty() ? 0 : t.vin_salvium[0].type() == typeid(txin_salvium_key) ? boost::get<txin_salvium_key>(t.vin_salvium[0]).key_offsets.size() - 1 : 0;
|
||||
} else if (t.blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR) {
|
||||
mixin = t.vin_zephyr.empty() ? 0 : t.vin_zephyr[0].type() == typeid(txin_zephyr_key) ? boost::get<txin_zephyr_key>(t.vin_zephyr[0]).key_offsets.size() - 1 : 0;
|
||||
} else if (t.blob_type == BLOB_TYPE_CRYPTONOTE_XHV) {
|
||||
mixin = t.vin.empty() ? 0 :
|
||||
t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 :
|
||||
t.vin[0].type() == typeid(txin_offshore) ? boost::get<txin_offshore>(t.vin[0]).key_offsets.size() - 1 :
|
||||
t.vin[0].type() == typeid(txin_onshore) ? boost::get<txin_onshore>(t.vin[0]).key_offsets.size() - 1 :
|
||||
t.vin[0].type() == typeid(txin_xasset) ? boost::get<txin_xasset>(t.vin[0]).key_offsets.size() - 1 :
|
||||
t.vin[0].type() == typeid(txin_haven_key) ? boost::get<txin_haven_key>(t.vin[0]).key_offsets.size() - 1 :
|
||||
0;
|
||||
} else {
|
||||
mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
|
||||
}
|
||||
bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
|
||||
cryptonote::get_blob_hash(ss.str(), hashes[2]);
|
||||
}
|
||||
|
||||
// the tx hash is the hash of the 3 hashes
|
||||
res = cn_fast_hash(hashes, sizeof(hashes));
|
||||
|
||||
// we still need the size
|
||||
if (blob_size)
|
||||
*blob_size = get_object_blobsize(t);
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
|
||||
{
|
||||
return get_transaction_hash(t, res, &blob_size);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_block_hashing_blob(const block& b, blobdata& blob)
|
||||
{
|
||||
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_XTNC || b.blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || b.blob_type == BLOB_TYPE_CRYPTONOTE_TUBE || b.blob_type == BLOB_TYPE_CRYPTONOTE_XTA) {
|
||||
blob = t_serializable_object_to_blob(b.major_version);
|
||||
blob.append(reinterpret_cast<const char*>(&b.minor_version), sizeof(b.minor_version));
|
||||
blob.append(reinterpret_cast<const char*>(&b.timestamp), sizeof(b.timestamp));
|
||||
blob.append(reinterpret_cast<const char*>(&b.prev_id), sizeof(b.prev_id));
|
||||
}
|
||||
else {
|
||||
blob = t_serializable_object_to_blob(static_cast<const block_header&>(b));
|
||||
}
|
||||
crypto::hash tree_root_hash = get_tx_tree_hash(b);
|
||||
blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash));
|
||||
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM) {
|
||||
blob.append(tools::get_varint_data(b.tx_hashes.size()+2));
|
||||
} else {
|
||||
blob.append(tools::get_varint_data(b.tx_hashes.size()+1));
|
||||
}
|
||||
if (b.blob_type == BLOB_TYPE_CRYPTONOTE3) {
|
||||
blob.append(reinterpret_cast<const char*>(&b.uncle), sizeof(b.uncle));
|
||||
}
|
||||
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO || b.blob_type == BLOB_TYPE_CRYPTONOTE_TUBE || b.blob_type == BLOB_TYPE_CRYPTONOTE_XTA) {
|
||||
blob.append(reinterpret_cast<const char*>(&b.nonce8), sizeof(b.nonce8));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_bytecoin_block_hashing_blob(const block& b, blobdata& blob)
|
||||
{
|
||||
auto sbb = make_serializable_bytecoin_block(b, true, true);
|
||||
return t_serializable_object_to_blob(sbb, blob);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_block_hash(const block& b, crypto::hash& res)
|
||||
{
|
||||
blobdata blob;
|
||||
if (!get_block_hashing_blob(b, blob))
|
||||
return false;
|
||||
|
||||
if (b.blob_type == BLOB_TYPE_FORKNOTE2)
|
||||
{
|
||||
blobdata parent_blob;
|
||||
auto sbb = make_serializable_bytecoin_block(b, true, false);
|
||||
if (!t_serializable_object_to_blob(sbb, parent_blob))
|
||||
return false;
|
||||
|
||||
blob.append(parent_blob);
|
||||
}
|
||||
|
||||
return get_object_hash(blob, res);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_block_hash(const block& b)
|
||||
{
|
||||
crypto::hash p = null_hash;
|
||||
get_block_hash(b, p);
|
||||
return p;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_block_header_hash(const block& b, crypto::hash& res)
|
||||
{
|
||||
blobdata blob;
|
||||
if (!get_block_hashing_blob(b, blob))
|
||||
return false;
|
||||
|
||||
return get_object_hash(blob, res);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off)
|
||||
{
|
||||
std::vector<uint64_t> res = off;
|
||||
for(size_t i = 1; i < res.size(); i++)
|
||||
res[i] += res[i-1];
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
std::vector<uint64_t> absolute_output_offsets_to_relative(const std::vector<uint64_t>& off)
|
||||
{
|
||||
std::vector<uint64_t> res = off;
|
||||
if(!off.size())
|
||||
return res;
|
||||
std::sort(res.begin(), res.end());//just to be sure, actually it is already should be sorted
|
||||
for(size_t i = res.size()-1; i != 0; i--)
|
||||
res[i] -= res[i-1];
|
||||
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_bytecoin_block_longhash(const block& b, crypto::hash& res)
|
||||
{
|
||||
blobdata bd;
|
||||
if(!get_bytecoin_block_hashing_blob(b, bd))
|
||||
return false;
|
||||
crypto::cn_slow_hash(bd.data(), bd.size(), res);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << b_blob;
|
||||
binary_archive<false> ba(ss);
|
||||
bool r = ::serialization::serialize(ba, b);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob 1");
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata block_to_blob(const block& b)
|
||||
{
|
||||
return t_serializable_object_to_blob(b);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool block_to_blob(const block& b, blobdata& b_blob)
|
||||
{
|
||||
return t_serializable_object_to_blob(b, b_blob);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata tx_to_blob(const transaction& tx)
|
||||
{
|
||||
return t_serializable_object_to_blob(tx);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool tx_to_blob(const transaction& tx, blobdata& b_blob)
|
||||
{
|
||||
return t_serializable_object_to_blob(tx, b_blob);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h)
|
||||
{
|
||||
tree_hash(tx_hashes.data(), tx_hashes.size(), h);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes)
|
||||
{
|
||||
crypto::hash h = null_hash;
|
||||
get_tx_tree_hash(tx_hashes, h);
|
||||
return h;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_tx_tree_hash(const block& b)
|
||||
{
|
||||
std::vector<crypto::hash> txs_ids;
|
||||
crypto::hash h = null_hash;
|
||||
size_t bl_sz = 0;
|
||||
get_transaction_hash(b.miner_tx, h, bl_sz);
|
||||
if (b.blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM) {
|
||||
txs_ids.push_back(h);
|
||||
h = null_hash;
|
||||
bl_sz = 0;
|
||||
get_transaction_hash(b.protocol_tx, h, bl_sz);
|
||||
}
|
||||
txs_ids.push_back(h);
|
||||
BOOST_FOREACH(auto& th, b.tx_hashes)
|
||||
txs_ids.push_back(th);
|
||||
return get_tx_tree_hash(txs_ids);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "difficulty.h"
|
||||
#include "account.h"
|
||||
#include "include_base_utils.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
|
||||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
|
||||
struct tx_source_entry
|
||||
{
|
||||
typedef std::pair<uint64_t, crypto::public_key> output_entry;
|
||||
|
||||
std::vector<output_entry> outputs; //index + key
|
||||
size_t real_output; //index in outputs vector of real output_entry
|
||||
crypto::public_key real_out_tx_key; //incoming real tx public key
|
||||
size_t real_output_in_tx_index; //index in transaction outputs vector
|
||||
uint64_t amount; //money
|
||||
};
|
||||
|
||||
struct tx_destination_entry
|
||||
{
|
||||
uint64_t amount; //money
|
||||
account_public_address addr; //destination address
|
||||
|
||||
tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { }
|
||||
tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { }
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
//bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
|
||||
|
||||
template<typename T>
|
||||
bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field)
|
||||
{
|
||||
auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [](const tx_extra_field& f) { return typeid(T) == f.type(); });
|
||||
if(tx_extra_fields.end() == it)
|
||||
return false;
|
||||
|
||||
field = boost::get<T>(*it);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra);
|
||||
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx);
|
||||
bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key);
|
||||
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce);
|
||||
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id);
|
||||
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
|
||||
bool append_mm_tag_to_extra(std::vector<uint8_t>& tx_extra, const tx_extra_merge_mining_tag& mm_tag);
|
||||
bool get_mm_tag_from_extra(const std::vector<uint8_t>& tx_extra, tx_extra_merge_mining_tag& mm_tag);
|
||||
void get_blob_hash(const blobdata& blob, crypto::hash& res);
|
||||
crypto::hash get_blob_hash(const blobdata& blob);
|
||||
std::string short_hash_str(const crypto::hash& h);
|
||||
|
||||
crypto::hash get_transaction_hash(const transaction& t);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||
bool get_block_hashing_blob(const block& b, blobdata& blob);
|
||||
bool get_bytecoin_block_hashing_blob(const block& b, blobdata& blob);
|
||||
bool get_block_hash(const block& b, crypto::hash& res);
|
||||
crypto::hash get_block_hash(const block& b);
|
||||
bool get_block_header_hash(const block& b, crypto::hash& res);
|
||||
bool get_bytecoin_block_longhash(const block& blk, crypto::hash& res);
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
|
||||
std::map<std::string, uint64_t> get_outs_money_amount(const transaction& tx);
|
||||
bool check_outs_valid(const transaction& tx);
|
||||
|
||||
std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off);
|
||||
std::vector<uint64_t> absolute_output_offsets_to_relative(const std::vector<uint64_t>& off);
|
||||
//---------------------------------------------------------------
|
||||
template<class t_object>
|
||||
bool t_serializable_object_to_blob(const t_object& to, blobdata& b_blob)
|
||||
{
|
||||
std::stringstream ss;
|
||||
binary_archive<true> ba(ss);
|
||||
bool r = ::serialization::serialize(ba, const_cast<t_object&>(to));
|
||||
b_blob = ss.str();
|
||||
return r;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class t_object>
|
||||
blobdata t_serializable_object_to_blob(const t_object& to)
|
||||
{
|
||||
blobdata b;
|
||||
t_serializable_object_to_blob(to, b);
|
||||
return b;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class t_object>
|
||||
bool get_object_hash(const t_object& o, crypto::hash& res)
|
||||
{
|
||||
get_blob_hash(t_serializable_object_to_blob(o), res);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class t_object>
|
||||
size_t get_object_blobsize(const t_object& o)
|
||||
{
|
||||
blobdata b = t_serializable_object_to_blob(o);
|
||||
return b.size();
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
template<class t_object>
|
||||
bool get_object_hash(const t_object& o, crypto::hash& res, size_t& blob_size)
|
||||
{
|
||||
blobdata bl = t_serializable_object_to_blob(o);
|
||||
blob_size = bl.size();
|
||||
get_blob_hash(bl, res);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold
|
||||
template<typename chunk_handler_t, typename dust_handler_t>
|
||||
void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler)
|
||||
{
|
||||
if (0 == amount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_dust_handled = false;
|
||||
uint64_t dust = 0;
|
||||
uint64_t order = 1;
|
||||
while (0 != amount)
|
||||
{
|
||||
uint64_t chunk = (amount % 10) * order;
|
||||
amount /= 10;
|
||||
order *= 10;
|
||||
|
||||
if (dust + chunk <= dust_threshold)
|
||||
{
|
||||
dust += chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!is_dust_handled && 0 != dust)
|
||||
{
|
||||
dust_handler(dust);
|
||||
is_dust_handled = true;
|
||||
}
|
||||
if (0 != chunk)
|
||||
{
|
||||
chunk_handler(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_dust_handled && 0 != dust)
|
||||
{
|
||||
dust_handler(dust);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
blobdata block_to_blob(const block& b);
|
||||
bool block_to_blob(const block& b, blobdata& b_blob);
|
||||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h);
|
||||
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
|
||||
crypto::hash get_tx_tree_hash(const block& b);
|
||||
|
||||
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
|
||||
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
|
||||
specific_type& variable_name = boost::get<specific_type>(variant_var);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "crypto/hash.h"
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
typedef std::uint64_t difficulty_type;
|
||||
|
||||
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
|
||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties);
|
||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/atomic.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <atomic>
|
||||
#include "cryptonote_basic.h"
|
||||
#include "difficulty.h"
|
||||
#include "math_helper.h"
|
||||
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
|
||||
struct i_miner_handler
|
||||
{
|
||||
virtual bool handle_block_found(block& b) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce) = 0;
|
||||
protected:
|
||||
~i_miner_handler(){};
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
class miner
|
||||
{
|
||||
public:
|
||||
miner(i_miner_handler* phandler);
|
||||
~miner();
|
||||
bool init(const boost::program_options::variables_map& vm);
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
|
||||
bool on_block_chain_update();
|
||||
bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs);
|
||||
uint64_t get_speed();
|
||||
void send_stop_signal();
|
||||
bool stop();
|
||||
bool is_mining();
|
||||
bool on_idle();
|
||||
void on_synchronized();
|
||||
//synchronous analog (for fast calls)
|
||||
static bool find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height);
|
||||
void pause();
|
||||
void resume();
|
||||
void do_print_hashrate(bool do_hr);
|
||||
|
||||
private:
|
||||
bool worker_thread();
|
||||
bool request_block_template();
|
||||
void merge_hr();
|
||||
|
||||
struct miner_config
|
||||
{
|
||||
uint64_t current_extra_message_index;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(current_extra_message_index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
volatile uint32_t m_stop;
|
||||
::critical_section m_template_lock;
|
||||
block m_template;
|
||||
std::atomic<uint32_t> m_template_no;
|
||||
std::atomic<uint32_t> m_starter_nonce;
|
||||
difficulty_type m_diffic;
|
||||
uint64_t m_height;
|
||||
volatile uint32_t m_thread_index;
|
||||
volatile uint32_t m_threads_total;
|
||||
std::atomic<int32_t> m_pausers_count;
|
||||
::critical_section m_miners_count_lock;
|
||||
|
||||
std::list<boost::thread> m_threads;
|
||||
::critical_section m_threads_lock;
|
||||
i_miner_handler* m_phandler;
|
||||
account_public_address m_mine_address;
|
||||
math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||
math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||
std::vector<blobdata> m_extra_messages;
|
||||
miner_config m_config;
|
||||
std::string m_config_folder_path;
|
||||
std::atomic<uint64_t> m_last_hr_merge_time;
|
||||
std::atomic<uint64_t> m_hashes;
|
||||
std::atomic<uint64_t> m_current_hash_rate;
|
||||
critical_section m_last_hash_rates_lock;
|
||||
std::list<uint64_t> m_last_hash_rates;
|
||||
bool m_do_print_hashrate;
|
||||
bool m_do_mining;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#define TX_EXTRA_PADDING_MAX_COUNT 255
|
||||
#define TX_EXTRA_NONCE_MAX_COUNT 255
|
||||
#define TX_EXTRA_OFFSHORE_MAX_COUNT 255
|
||||
#define TX_EXTRA_MEMO_MAX_COUNT 255
|
||||
|
||||
#define TX_EXTRA_TAG_PADDING 0x00
|
||||
#define TX_EXTRA_TAG_PUBKEY 0x01
|
||||
#define TX_EXTRA_NONCE 0x02
|
||||
#define TX_EXTRA_MERGE_MINING_TAG 0x03
|
||||
#define TX_EXTRA_TAG_ADDITIONAL_PUBKEYS 0x04
|
||||
#define TX_EXTRA_TAG_OFFSHORE 0x17
|
||||
#define TX_EXTRA_TAG_MEMO 0x18
|
||||
#define TX_EXTRA_TAG_SERVICE_NODE_REGISTER 0x70
|
||||
#define TX_EXTRA_TAG_SERVICE_NODE_DEREGISTER 0x71
|
||||
#define TX_EXTRA_TAG_SERVICE_NODE_WINNER 0x72
|
||||
#define TX_EXTRA_TAG_SERVICE_NODE_CONTRIBUTOR 0x73
|
||||
#define TX_EXTRA_TAG_SERVICE_NODE_PUBKEY 0x74
|
||||
#define TX_EXTRA_TAG_TX_SECRET_KEY 0x75
|
||||
#define TX_EXTRA_TAG_TX_KEY_IMAGE_PROOFS 0x76
|
||||
#define TX_EXTRA_TAG_TX_KEY_IMAGE_UNLOCK 0x77
|
||||
#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG 0xDE
|
||||
|
||||
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
|
||||
#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
struct tx_extra_padding
|
||||
{
|
||||
size_t size;
|
||||
|
||||
// load
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false>& ar)
|
||||
{
|
||||
// size - 1 - because of variant tag
|
||||
for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size)
|
||||
{
|
||||
std::ios_base::iostate state = ar.stream().rdstate();
|
||||
bool eof = EOF == ar.stream().peek();
|
||||
ar.stream().clear(state);
|
||||
|
||||
if (eof)
|
||||
break;
|
||||
|
||||
uint8_t zero;
|
||||
if (!::do_serialize(ar, zero))
|
||||
return false;
|
||||
|
||||
if (0 != zero)
|
||||
return false;
|
||||
}
|
||||
|
||||
return size <= TX_EXTRA_PADDING_MAX_COUNT;
|
||||
}
|
||||
|
||||
// store
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<true>& ar)
|
||||
{
|
||||
if(TX_EXTRA_PADDING_MAX_COUNT < size)
|
||||
return false;
|
||||
|
||||
// i = 1 - because of variant tag
|
||||
for (size_t i = 1; i < size; ++i)
|
||||
{
|
||||
uint8_t zero = 0;
|
||||
if (!::do_serialize(ar, zero))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct tx_extra_pub_key
|
||||
{
|
||||
crypto::public_key pub_key;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(pub_key)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_nonce
|
||||
{
|
||||
std::string nonce;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(nonce)
|
||||
if(TX_EXTRA_NONCE_MAX_COUNT < nonce.size()) return false;
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_merge_mining_tag
|
||||
{
|
||||
struct serialize_helper
|
||||
{
|
||||
tx_extra_merge_mining_tag& mm_tag;
|
||||
|
||||
serialize_helper(tx_extra_merge_mining_tag& mm_tag_) : mm_tag(mm_tag_)
|
||||
{
|
||||
}
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
VARINT_FIELD_N("depth", mm_tag.depth)
|
||||
FIELD_N("merkle_root", mm_tag.merkle_root)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
size_t depth;
|
||||
crypto::hash merkle_root;
|
||||
|
||||
// load
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<false>& ar)
|
||||
{
|
||||
std::string field;
|
||||
if(!::do_serialize(ar, field))
|
||||
return false;
|
||||
|
||||
std::istringstream iss(field);
|
||||
binary_archive<false> iar(iss);
|
||||
serialize_helper helper(*this);
|
||||
return ::serialization::serialize(iar, helper);
|
||||
}
|
||||
|
||||
// store
|
||||
template <template <bool> class Archive>
|
||||
bool do_serialize(Archive<true>& ar)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
binary_archive<true> oar(oss);
|
||||
serialize_helper helper(*this);
|
||||
if(!::do_serialize(oar, helper))
|
||||
return false;
|
||||
|
||||
std::string field = oss.str();
|
||||
return ::serialization::serialize(ar, field);
|
||||
}
|
||||
};
|
||||
|
||||
// per-output additional tx pubkey for multi-destination transfers involving at least one subaddress
|
||||
struct tx_extra_additional_pub_keys
|
||||
{
|
||||
std::vector<crypto::public_key> data;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(data)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_mysterious_minergate
|
||||
{
|
||||
std::string data;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(data)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_offshore
|
||||
{
|
||||
std::string data;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(data)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_memo
|
||||
{
|
||||
// Actual memo data as string
|
||||
std::string data;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(data)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_service_node_winner
|
||||
{
|
||||
crypto::public_key m_service_node_key;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(m_service_node_key)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_service_node_pubkey
|
||||
{
|
||||
crypto::public_key m_service_node_key;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(m_service_node_key)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
||||
struct tx_extra_service_node_register
|
||||
{
|
||||
std::vector<crypto::public_key> m_public_spend_keys;
|
||||
std::vector<crypto::public_key> m_public_view_keys;
|
||||
uint64_t m_portions_for_operator;
|
||||
std::vector<uint64_t> m_portions;
|
||||
uint64_t m_expiration_timestamp;
|
||||
crypto::signature m_service_node_signature;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(m_public_spend_keys)
|
||||
FIELD(m_public_view_keys)
|
||||
FIELD(m_portions_for_operator)
|
||||
FIELD(m_portions)
|
||||
FIELD(m_expiration_timestamp)
|
||||
FIELD(m_service_node_signature)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_service_node_contributor
|
||||
{
|
||||
crypto::public_key m_spend_public_key;
|
||||
crypto::public_key m_view_public_key;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(m_spend_public_key)
|
||||
FIELD(m_view_public_key)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_service_node_deregister
|
||||
{
|
||||
struct vote
|
||||
{
|
||||
crypto::signature signature;
|
||||
uint32_t voters_quorum_index;
|
||||
};
|
||||
|
||||
uint64_t block_height;
|
||||
uint32_t service_node_index;
|
||||
std::vector<vote> votes;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(block_height)
|
||||
FIELD(service_node_index)
|
||||
FIELD(votes)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_tx_secret_key
|
||||
{
|
||||
crypto::secret_key key;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(key)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_tx_key_image_proofs
|
||||
{
|
||||
struct proof
|
||||
{
|
||||
crypto::key_image key_image;
|
||||
crypto::signature signature;
|
||||
};
|
||||
|
||||
std::vector<proof> proofs;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(proofs)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
struct tx_extra_tx_key_image_unlock
|
||||
{
|
||||
crypto::key_image key_image;
|
||||
crypto::signature signature;
|
||||
uint32_t nonce;
|
||||
|
||||
BEGIN_SERIALIZE()
|
||||
FIELD(key_image)
|
||||
FIELD(signature)
|
||||
FIELD(nonce)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
// tx_extra_field format, except tx_extra_padding and tx_extra_pub_key:
|
||||
// varint tag;
|
||||
// varint size;
|
||||
// varint data[];
|
||||
typedef boost::variant<tx_extra_padding,
|
||||
tx_extra_pub_key,
|
||||
tx_extra_nonce,
|
||||
tx_extra_merge_mining_tag,
|
||||
tx_extra_additional_pub_keys,
|
||||
tx_extra_mysterious_minergate,
|
||||
tx_extra_offshore,
|
||||
tx_extra_memo,
|
||||
tx_extra_service_node_pubkey,
|
||||
tx_extra_service_node_register,
|
||||
tx_extra_service_node_contributor,
|
||||
tx_extra_service_node_winner,
|
||||
tx_extra_service_node_deregister,
|
||||
tx_extra_tx_secret_key,
|
||||
tx_extra_tx_key_image_proofs,
|
||||
tx_extra_tx_key_image_unlock
|
||||
> tx_extra_field;
|
||||
}
|
||||
|
||||
BLOB_SERIALIZER(cryptonote::tx_extra_service_node_deregister::vote);
|
||||
BLOB_SERIALIZER(cryptonote::tx_extra_tx_key_image_proofs::proof);
|
||||
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_additional_pub_keys, TX_EXTRA_TAG_ADDITIONAL_PUBKEYS);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_mysterious_minergate, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_offshore, TX_EXTRA_TAG_OFFSHORE);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_memo, TX_EXTRA_TAG_MEMO);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_service_node_register, TX_EXTRA_TAG_SERVICE_NODE_REGISTER);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_service_node_deregister, TX_EXTRA_TAG_SERVICE_NODE_DEREGISTER);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_service_node_contributor, TX_EXTRA_TAG_SERVICE_NODE_CONTRIBUTOR);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_service_node_winner, TX_EXTRA_TAG_SERVICE_NODE_WINNER);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_service_node_pubkey, TX_EXTRA_TAG_SERVICE_NODE_PUBKEY);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_tx_secret_key, TX_EXTRA_TAG_TX_SECRET_KEY);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_tx_key_image_proofs, TX_EXTRA_TAG_TX_KEY_IMAGE_PROOFS);
|
||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_tx_key_image_unlock, TX_EXTRA_TAG_TX_KEY_IMAGE_UNLOCK);
|
||||
Reference in New Issue
Block a user