Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
Node-Cryptonote-Util
====================

Dependencies
------------
Adding merged mining with ringCT support to DigitalNote to be used with crpytonote-universal-pool. Note: this compiles but does not work with cryptnote-universal-pool yet, not sure sure where the mistakes are.

* Boost (http://www.boost.org/)
I referenced DigitalNote fork changes (https://github.com/xdn-project/digitalnote/commit/7a321b7a85d41263f33c35c6c69d9a1256d677db and https://github.com/xdn-project/digitalnote/commit/6f53611c3e635e31f33ec0b7ab8dc90263edc214) in coordination with the ringCT upgrades (https://github.com/zone117x/node-cryptonote-util/commit/b3d5e4305238d7cfc6fa860f289851e4d08be771) but in the form of the XDN block structure as per Jan 9, 2017 updates https://github.com/xdn-project/digitalnote/commit/6f53611c3e635e31f33ec0b7ab8dc90263edc214. I attempted to create a new class called "parent_block_transaction" to act as the ringCT carrier, I also updated all references to the major version (which is now 4) and the transaction version (which is now 2). The code seems to line up correctly but I am not sure what I am doing wrong...below is the current readout when I run init.js with this code:

/root/xdnclone/node_modules/cryptonote-util/node_modules/bindings/bindings.js:83
throw e
^
Error: /root/xdnclone/node_modules/cryptonote-util/build/Release/cryptonote.node: undefined symbol: _ZTVN10cryptonote24parent_block_transactionE
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at bindings (/root/xdnclone/node_modules/cryptonote-util/node_modules/bindings/bindings.js:76:44)
at Object.<anonymous> (/root/xdnclone/node_modules/cryptonote-util/index.js:1:99)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)

I do not know anything about node js so I don't know if there is a mistake in my implementation of ringct support for merge-mined blocks, or if there is something that now needs to be updated with cryptonote-universal-pool.
6 changes: 4 additions & 2 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#pragma once

#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
#define CURRENT_TRANSACTION_VERSION 1
#define CURRENT_BLOCK_MAJOR_VERSION 1
#define CURRENT_TRANSACTION_VERSION 2
#define CURRENT_BLOCK_MAJOR_VERSION 4
#define CURRENT_BLOCK_MINOR_VERSION 0

#define BLOCK_MAJOR_VERSION_1 1
#define BLOCK_MAJOR_VERSION_2 2
#define BLOCK_MAJOR_VERSION_3 3
#define BLOCK_MAJOR_VERSION_4 4

#define COIN ((uint64_t)100000000) // pow(10, 8)
#define DEFAULT_FEE ((uint64_t)1000000) // pow(10, 6)
Expand Down
83 changes: 78 additions & 5 deletions src/cryptonote_core/cryptonote_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@
#include "crypto/hash.h"
#include "misc_language.h"
#include "tx_extra.h"
#include "ringct/rctTypes.h"


namespace cryptonote
{
struct block;
class transaction;
class parent_block_transaction;
struct tx_extra_merge_mining_tag;

// Implemented in cryptonote_format_utils.cpp
bool get_transaction_hash(const transaction& t, crypto::hash& res);
bool get_parent_block_transaction_hash(const parent_block_transaction& t, crypto::hash& res);
bool get_mm_tag_from_extra(const std::vector<uint8_t>& tx, tx_extra_merge_mining_tag& mm_tag);

const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash);
Expand Down Expand Up @@ -185,6 +188,76 @@ namespace cryptonote
transaction_prefix(){}
};

class parent_block_transaction : public transaction_prefix
{
public:
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
rct::rctSig rct_signatures;

parent_block_transaction();
virtual ~parent_block_transaction();
void set_null();

BEGIN_SERIALIZE_OBJECT()
FIELDS(*static_cast<transaction_prefix *>(this))

if (version < 2)
{
ar.tag("signatures");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures);
bool signatures_not_expected = signatures.empty();
if (!signatures_not_expected && vin.size() != signatures.size())
return false;

for (size_t i = 0; i < vin.size(); ++i)
{
size_t signature_size = get_signature_size(vin[i]);
if (signatures_not_expected)
{
if (0 == signature_size)
continue;
else
return false;
}

PREPARE_CUSTOM_VECTOR_SERIALIZATION(signature_size, signatures[i]);
if (signature_size != signatures[i].size())
return false;

FIELDS(signatures[i]);

if (vin.size() - i > 1)
ar.delimit_array();
}
ar.end_array();
}
else
{
ar.tag("rct_signatures");
if (!vin.empty())
{
ar.begin_object();
bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
if (!r || !ar.stream().good()) return false;
ar.end_object();
if (rct_signatures.type != rct::RCTTypeNull)
{
ar.tag("rctsig_prunable");
ar.begin_object();
r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(),
vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
if (!r || !ar.stream().good()) return false;
ar.end_object();
}
}
}
END_SERIALIZE()

private:
static size_t get_signature_size(const txin_v& tx_in);
};

class transaction: public transaction_prefix
{
public:
Expand Down Expand Up @@ -365,7 +438,7 @@ namespace cryptonote
uint32_t nonce;
size_t number_of_transactions;
std::vector<crypto::hash> miner_tx_branch;
transaction miner_tx;
parent_block_transaction miner_tx;
std::vector<crypto::hash> blockchain_branch;
};

Expand All @@ -392,7 +465,7 @@ namespace cryptonote
if (hashing_serialization)
{
crypto::hash miner_tx_hash;
if (!get_transaction_hash(b.miner_tx, miner_tx_hash))
if (!get_parent_block_transaction_hash(b.miner_tx, miner_tx_hash)) //if (!get_transaction_hash(b.miner_tx, miner_tx_hash))
return false;

crypto::hash merkle_root;
Expand Down Expand Up @@ -456,7 +529,7 @@ namespace cryptonote

BEGIN_SERIALIZE()
VARINT_FIELD(major_version)
if(major_version > BLOCK_MAJOR_VERSION_2) return false;
if(major_version > BLOCK_MAJOR_VERSION_4) return false;
VARINT_FIELD(minor_version)
if (BLOCK_MAJOR_VERSION_1 == major_version)
{
Expand All @@ -479,7 +552,7 @@ namespace cryptonote

BEGIN_SERIALIZE_OBJECT()
FIELDS(*static_cast<block_header *>(this))
if (BLOCK_MAJOR_VERSION_2 <= major_version)
if (BLOCK_MAJOR_VERSION_4 <= major_version)
{
auto sbb = make_serializable_bytecoin_block(*this, false, false);
FIELD_N("parent_block", sbb);
Expand Down Expand Up @@ -571,7 +644,7 @@ namespace cryptonote
BEGIN_SERIALIZE()
//block header
VARINT_FIELD(b.major_version)
if(b.major_version > BLOCK_MAJOR_VERSION_2) return false;
if(b.major_version > BLOCK_MAJOR_VERSION_4) return false;
VARINT_FIELD(b.minor_version)
VARINT_FIELD(b.timestamp)
FIELD(b.prev_id)
Expand Down
66 changes: 61 additions & 5 deletions src/cryptonote_core/cryptonote_format_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,58 @@ namespace cryptonote
{
return get_object_hash(t, res, blob_size);
}
//---------------------------------------------------------------
bool get_parent_block_transaction_hash(const parent_block_transaction& t, crypto::hash& res)
{
// v1 transactions hash the entire blob
if (t.version == 1) {
return get_object_hash(t, res);
}
// 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]);

parent_block_transaction &tt = const_cast<parent_block_transaction&>(t);

// base rct
{
std::stringstream ss;
binary_archive<true> ba(ss);
const size_t inputs = t.vin.size();
const size_t outputs = t.vout.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.vin.size();
const size_t outputs = t.vout.size();
const size_t 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_block_hashing_blob(const block& b, blobdata& blob)
{
Expand Down Expand Up @@ -864,7 +916,7 @@ namespace cryptonote
//---------------------------------------------------------------
bool check_proof_of_work_v1(const block& bl, difficulty_type current_diffic, crypto::hash& proof_of_work)
{
if (BLOCK_MAJOR_VERSION_1 != bl.major_version)
if (BLOCK_MAJOR_VERSION_2 < bl.major_version)
return false;

proof_of_work = get_block_longhash(bl, 0);
Expand All @@ -873,8 +925,8 @@ namespace cryptonote
//---------------------------------------------------------------
bool check_proof_of_work_v2(const block& bl, difficulty_type current_diffic, crypto::hash& proof_of_work)
{
if (BLOCK_MAJOR_VERSION_2 != bl.major_version)
return false;
if (BLOCK_MAJOR_VERSION_3 > bl.major_version)
return false;

if (!get_bytecoin_block_longhash(bl, proof_of_work))
return false;
Expand Down Expand Up @@ -911,8 +963,12 @@ namespace cryptonote
{
switch (bl.major_version)
{
case BLOCK_MAJOR_VERSION_1: return check_proof_of_work_v1(bl, current_diffic, proof_of_work);
case BLOCK_MAJOR_VERSION_2: return check_proof_of_work_v2(bl, current_diffic, proof_of_work);
case BLOCK_MAJOR_VERSION_1:
case BLOCK_MAJOR_VERSION_2:
return check_proof_of_work_v1(bl, current_diffic, proof_of_work);
case BLOCK_MAJOR_VERSION_3:
case BLOCK_MAJOR_VERSION_4:
return check_proof_of_work_v2(bl, current_diffic, proof_of_work);
}

CHECK_AND_ASSERT_MES(false, false, "unknown block major version: " << bl.major_version << "." << bl.minor_version);
Expand Down
3 changes: 2 additions & 1 deletion src/cryptonote_core/cryptonote_format_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ namespace cryptonote
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_parent_block_transaction_hash(const parent_block_transaction& t, crypto::hash& res);
bool get_block_hashing_blob(const block& b, blobdata& blob);
bool get_bytecoin_block_hashing_blob(const block& b, blobdata& blob);
blobdata get_block_hashing_blob(const bb_block& b);
bool get_block_hash(const block& b, crypto::hash& res, uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_2);
bool get_block_hash(const block& b, crypto::hash& res, uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_4);
crypto::hash get_block_hash(const block& b);
bool get_block_header_hash(const block& b, crypto::hash& res);
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
Expand Down
52 changes: 26 additions & 26 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,32 +49,32 @@ static bool fillExtra(cryptonote::block& block1, const cryptonote::block& block2
}

static bool mergeBlocks(const cryptonote::block& block1, cryptonote::block& block2, const std::vector<crypto::hash>& branch2) {
block2.timestamp = block1.timestamp;
block2.parent_block.major_version = block1.major_version;
block2.parent_block.minor_version = block1.minor_version;
block2.parent_block.prev_id = block1.prev_id;
block2.parent_block.nonce = block1.nonce;
block2.parent_block.miner_tx = block1.miner_tx;
block2.parent_block.number_of_transactions = block1.tx_hashes.size() + 1;
block2.parent_block.miner_tx_branch.resize(crypto::tree_depth(block1.tx_hashes.size() + 1));
std::vector<crypto::hash> transactionHashes;
transactionHashes.push_back(cryptonote::get_transaction_hash(block1.miner_tx));
std::copy(block1.tx_hashes.begin(), block1.tx_hashes.end(), std::back_inserter(transactionHashes));
tree_branch(transactionHashes.data(), transactionHashes.size(), block2.parent_block.miner_tx_branch.data());
block2.parent_block.blockchain_branch = branch2;
return true;
block2.timestamp = block1.timestamp;
block2.parent_block.major_version = block1.major_version;
block2.parent_block.minor_version = block1.minor_version;
block2.parent_block.prev_id = block1.prev_id;
block2.parent_block.nonce = block1.nonce;
//block2.parent_block.miner_tx = block1.miner_tx; //this needs work
block2.parent_block.number_of_transactions = block1.tx_hashes.size() + 1;
block2.parent_block.miner_tx_branch.resize(crypto::tree_depth(block1.tx_hashes.size() + 1));
std::vector<crypto::hash> transactionHashes;
transactionHashes.push_back(cryptonote::get_transaction_hash(block1.miner_tx));
std::copy(block1.tx_hashes.begin(), block1.tx_hashes.end(), std::back_inserter(transactionHashes));
tree_branch(transactionHashes.data(), transactionHashes.size(), block2.parent_block.miner_tx_branch.data());
block2.parent_block.blockchain_branch = branch2;
return true;
}

static bool construct_parent_block(const cryptonote::block& b, cryptonote::block& parent_block) {
parent_block.major_version = 1;
parent_block.minor_version = 0;
parent_block.timestamp = b.timestamp;
parent_block.prev_id = b.prev_id;
parent_block.nonce = b.parent_block.nonce;
parent_block.miner_tx.version = CURRENT_TRANSACTION_VERSION;
parent_block.miner_tx.unlock_time = 0;

return fillExtra(parent_block, b);
parent_block.major_version = 4;
parent_block.minor_version = 0;
parent_block.timestamp = b.timestamp;
parent_block.prev_id = b.prev_id;
parent_block.nonce = b.parent_block.nonce;
parent_block.miner_tx.version = CURRENT_TRANSACTION_VERSION;
parent_block.miner_tx.unlock_time = 0;

return fillExtra(parent_block, b);
}

Handle<Value> convert_blob(const Arguments& args) {
Expand All @@ -84,7 +84,7 @@ Handle<Value> convert_blob(const Arguments& args) {
return except("You must provide one argument.");

Local<Object> target = args[0]->ToObject();
uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_2;
uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_4;
if (args.Length() >= 2) {
mergedMiningBlockVersion = static_cast<uint64_t>(args[1]->ToNumber()->NumberValue());
}
Expand Down Expand Up @@ -123,7 +123,7 @@ Handle<Value> get_block_id(const Arguments& args) {
return except("You must provide one argument.");

Local<Object> target = args[0]->ToObject();
uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_2;
uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_4;
if (args.Length() >= 2) {
mergedMiningBlockVersion = static_cast<uint64_t>(args[1]->ToNumber()->NumberValue());
}
Expand Down Expand Up @@ -155,7 +155,7 @@ Handle<Value> construct_block_blob(const Arguments& args) {
Local<Object> block_template_buf = args[0]->ToObject();
Local<Object> nonce_buf = args[1]->ToObject();

uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_2;
uint64_t mergedMiningBlockVersion = BLOCK_MAJOR_VERSION_4;
if (args.Length() >= 3) {
mergedMiningBlockVersion = static_cast<uint64_t>(args[2]->ToNumber()->NumberValue());
}
Expand Down