Compare commits

..

36 Commits

Author SHA1 Message Date
MoneroOcean 02d48ecc72 Aeon support 2019-10-25 17:22:31 -07:00
MoneroOcean f382894d9c Fixed merged mining block hash calc 2019-04-04 17:50:04 -07:00
MoneroOcean c359843323 Added timestamp patch 2019-04-04 09:50:50 -07:00
MoneroOcean db89485957 Avoid changing Loki blocks 2019-04-03 22:17:09 -07:00
MoneroOcean a9d6ab839f Loki extra parse 2019-04-03 22:16:49 -07:00
MoneroOcean fef5d6e3a5 One more loki fix 2019-04-03 17:35:39 -07:00
MoneroOcean c545b65f01 Moved LOKI hash to last phase of child block creation 2019-04-03 12:01:40 -07:00
MoneroOcean c93a411c64 Restored original compatible version 2019-04-03 11:34:02 -07:00
MoneroOcean 08798aaff0 Restore extra trim 2019-04-03 11:32:30 -07:00
MoneroOcean b660e2c154 Loki hack for mm 2019-04-03 09:23:12 -07:00
MoneroOcean 24bf4d44f9 Loki hack for mm 2019-04-03 09:21:30 -07:00
MoneroOcean 2f116a267b Fixed error 2019-04-03 03:17:46 -07:00
MoneroOcean e4f21ac12a Some more fixes 2019-04-03 03:16:12 -07:00
MoneroOcean 01c0279543 Restored original compatible version 2019-04-03 00:01:42 -07:00
MoneroOcean 47b898375b Remove extra stuff 2019-04-02 23:49:55 -07:00
MoneroOcean 89271f9517 Better error messages 2019-04-02 21:29:46 -07:00
MoneroOcean d71a8a4feb Added extra error messages 2019-04-02 19:36:29 -07:00
MoneroOcean 903dacf470 Fixed MM stuff 2019-04-02 19:14:03 -07:00
MoneroOcean 2f554e2fcd Change block blob to extra nonce 2019-04-01 17:09:47 -07:00
MoneroOcean 83e3280861 Updated version 2019-04-01 11:52:21 -07:00
MoneroOcean 429077e4c7 Name fix 2019-03-31 11:33:21 -07:00
MoneroOcean 46c038018b Added EOL 2019-03-31 00:20:43 -07:00
MoneroOcean 5afa00d329 Simplified and redesigned mm stuff 2019-03-31 00:18:52 -07:00
MoneroOcean 75e5e04509 Moved version 2019-03-18 08:47:34 -07:00
MoneroOcean 1a31a67303 Merge pull request #4 from Doy-lee/LokiSupportPR
Update cryptonote utils for Loki hardfork 11
2019-03-18 16:46:37 +01:00
Doyle ee84d41d34 Update cryptonote utils for Loki hardfork 11, Infinite Staking 2019-03-18 14:20:49 +11:00
campurro 23696c6c63 Clear some bugs + support mining just a v2 coin 2019-03-16 16:17:53 +01:00
campurro 1583dcd07a Some bugfixes & improvements 2019-03-16 15:10:47 +01:00
campurro b234fcb6c6 Initial support for Moneta Verde Multi-PoW merged mining 2019-03-16 13:32:11 +01:00
MoneroOcean 5bda5f949e MSR fixes 2019-01-26 09:19:31 -08:00
MoneroOcean 52bb818185 Updated version 2019-01-26 08:40:49 -08:00
MoneroOcean b5ba759c9f Added new Masari support 2019-01-26 08:39:27 -08:00
Campurro f4818ad461 Add fill_extra function (support for xmr-node-proxy) 2018-11-12 12:01:58 +01:00
Campurro 1ec4fd5b72 Merged mining support 2018-11-09 19:24:17 +01:00
MoneroOcean 35cc401a30 Fixed version 2018-09-15 16:58:14 +02:00
MoneroOcean 473f81f81b Added Loki support 2018-09-10 22:07:41 +02:00
8 changed files with 448 additions and 50 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
Node-CryptoForkNote-Util
====================
Node-CryptoForkNote-Util with Merged Mining support
===================================================
Dependencies
------------
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cryptoforknote-util",
"version": "2.0.0",
"version": "6.0.0",
"main": "cryptoforknote-util",
"author": {
"name": "LucasJones",
+9 -6
View File
@@ -3,9 +3,12 @@
#define CURRENT_TRANSACTION_VERSION 1
enum BLOB_TYPE {
BLOB_TYPE_CRYPTONOTE = 0,
BLOB_TYPE_FORKNOTE1 = 1,
BLOB_TYPE_FORKNOTE2 = 2,
BLOB_TYPE_CRYPTONOTE2 = 3, // Masari
BLOB_TYPE_CRYPTONOTE_RYO = 4, // Ryo
};
BLOB_TYPE_CRYPTONOTE = 0,
BLOB_TYPE_FORKNOTE1 = 1,
BLOB_TYPE_FORKNOTE2 = 2,
BLOB_TYPE_CRYPTONOTE2 = 3, // Masari
BLOB_TYPE_CRYPTONOTE_RYO = 4, // Ryo
BLOB_TYPE_CRYPTONOTE_LOKI = 5, // Loki
BLOB_TYPE_CRYPTONOTE3 = 6, // Masari
BLOB_TYPE_AEON = 7, // Aeon
};
+75 -5
View File
@@ -25,16 +25,20 @@
#include "misc_language.h"
#include "tx_extra.h"
#include "ringct/rctTypes.h"
#include "cryptonote_protocol/blobdatatype.h"
namespace cryptonote
{
struct block;
class transaction;
class transaction_prefix;
struct tx_extra_merge_mining_tag;
// Implemented in cryptonote_format_utils.cpp
bool get_transaction_hash(const transaction& t, crypto::hash& res);
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
void get_blob_hash(const blobdata& blob, 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);
@@ -137,6 +141,15 @@ namespace cryptonote
END_SERIALIZE()
};
enum loki_version
{
loki_version_0 = 0,
loki_version_1,
loki_version_2,
loki_version_3_per_output_unlock_times,
loki_version_4_tx_types,
};
class transaction_prefix
{
@@ -151,12 +164,45 @@ namespace cryptonote
//extra
std::vector<uint8_t> extra;
//
// NOTE: Loki specific
//
std::vector<uint64_t> output_unlock_times;
enum loki_type_t
{
loki_type_standard,
loki_type_deregister,
loki_type_key_image_unlock,
loki_type_count,
};
union
{
bool is_deregister;
uint16_t type;
};
BEGIN_SERIALIZE()
VARINT_FIELD(version)
if (version > loki_version_2 && blob_type == BLOB_TYPE_CRYPTONOTE_LOKI)
{
FIELD(output_unlock_times)
if (version == loki_version_3_per_output_unlock_times)
FIELD(is_deregister)
}
VARINT_FIELD(unlock_time)
FIELD(vin)
FIELD(vout)
if (blob_type == BLOB_TYPE_CRYPTONOTE_LOKI)
{
if (version >= loki_version_3_per_output_unlock_times && vout.size() != output_unlock_times.size()) return false;
}
FIELD(extra)
if (blob_type == BLOB_TYPE_CRYPTONOTE_LOKI && version >= loki_version_4_tx_types)
{
VARINT_FIELD(type)
if (static_cast<uint16_t>(type) >= loki_type_count) return false;
}
END_SERIALIZE()
@@ -177,7 +223,7 @@ namespace cryptonote
BEGIN_SERIALIZE_OBJECT()
FIELDS(*static_cast<transaction_prefix *>(this))
if (version == 1 && blob_type != BLOB_TYPE_CRYPTONOTE2)
if (version == 1 && blob_type != BLOB_TYPE_CRYPTONOTE2 && blob_type != BLOB_TYPE_CRYPTONOTE3)
{
ar.tag("signatures");
ar.begin_array();
@@ -311,8 +357,18 @@ namespace cryptonote
if (hashing_serialization)
{
crypto::hash miner_tx_hash;
if (!get_transaction_hash(b.miner_tx, miner_tx_hash))
return false;
if (b.miner_tx.version < 2) {
if (!get_transaction_hash(b.miner_tx, miner_tx_hash))
return false;
} else {
get_transaction_prefix_hash(static_cast<const transaction_prefix&>(b.miner_tx), miner_tx_hash);
const uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x36, 0x78, 0x9e, 0x7a, 0x1e, 0x28, 0x14, 0x36, 0x46, 0x42, 0x29, 0x82, 0x8f, 0x81, 0x7d, 0x66, 0x12, 0xf7, 0xb4, 0x77, 0xd6, 0x65, 0x91, 0xff, 0x96, 0xa9, 0xe0, 0x64, 0xbc, 0xc9, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
blobdata blobdata((char*)data, sizeof(data));
const unsigned char* p = (unsigned char*)&miner_tx_hash;
for (int i = 0; i != HASH_SIZE; ++ i, ++ p) blobdata[i] = *p;
get_blob_hash(blobdata, miner_tx_hash);
}
crypto::hash merkle_root;
crypto::tree_hash_from_branch(b.miner_tx_branch.data(), b.miner_tx_branch.size(), miner_tx_hash, 0, merkle_root);
@@ -373,14 +429,23 @@ namespace cryptonote
uint8_t minor_version;
uint64_t timestamp;
crypto::hash prev_id;
uint32_t nonce;
uint64_t nonce;
BEGIN_SERIALIZE()
VARINT_FIELD(major_version)
VARINT_FIELD(minor_version)
if (blob_type != BLOB_TYPE_FORKNOTE2) VARINT_FIELD(timestamp)
FIELD(prev_id)
if (blob_type != BLOB_TYPE_FORKNOTE2) FIELD(nonce)
if (blob_type != BLOB_TYPE_FORKNOTE2) {
if (blob_type == BLOB_TYPE_AEON) {
FIELD(nonce)
} else {
uint32_t nonce32;
if (typename Archive<W>::is_saving()) nonce32 = (uint32_t)nonce;
FIELD_N("nonce", nonce32);
if (!typename Archive<W>::is_saving()) nonce = nonce32;
}
}
END_SERIALIZE()
};
@@ -390,6 +455,7 @@ namespace cryptonote
transaction miner_tx;
std::vector<crypto::hash> tx_hashes;
mutable crypto::hash uncle = cryptonote::null_hash;
void set_blob_type(enum BLOB_TYPE bt) { miner_tx.blob_type = blob_type = bt; }
@@ -402,6 +468,10 @@ namespace cryptonote
}
FIELD(miner_tx)
FIELD(tx_hashes)
if (blob_type == BLOB_TYPE_CRYPTONOTE3)
{
FIELD(uncle)
}
END_SERIALIZE()
};
@@ -370,7 +370,7 @@ namespace cryptonote
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)
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);
@@ -433,7 +433,9 @@ namespace cryptonote
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));
if (b.blob_type == BLOB_TYPE_CRYPTONOTE3) {
blob.append(reinterpret_cast<const char*>(&b.uncle), sizeof(b.uncle));
}
return true;
}
//---------------------------------------------------------------
+203 -16
View File
@@ -1,19 +1,55 @@
// 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.
// 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_PADDING_MAX_COUNT 255
#define TX_EXTRA_NONCE_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_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_TAG_PADDING 0x00
#define TX_EXTRA_TAG_PUBKEY 0x01
#define TX_EXTRA_NONCE 0x02
#define TX_EXTRA_MERGE_MINING_TAG 0x03
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01
namespace cryptonote
{
@@ -131,14 +167,165 @@ namespace cryptonote
}
};
// 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_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_field;
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_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;
}
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);
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_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);
+147 -18
View File
@@ -17,6 +17,9 @@ using namespace node;
using namespace v8;
using namespace cryptonote;
// cryptonote::append_mm_tag_to_extra writes byte with TX_EXTRA_MERGE_MINING_TAG (1 here) and VARINT DEPTH (2 here)
const size_t MM_NONCE_SIZE = 1 + 2 + sizeof(crypto::hash);
blobdata uint64be_to_blob(uint64_t num) {
blobdata res = " ";
res[0] = num >> 56 & 0xff;
@@ -29,7 +32,7 @@ blobdata uint64be_to_blob(uint64_t num) {
res[7] = num & 0xff;
return res;
}
static bool fillExtra(cryptonote::block& block1, const cryptonote::block& block2) {
cryptonote::tx_extra_merge_mining_tag mm_tag;
mm_tag.depth = 0;
@@ -41,13 +44,68 @@ static bool fillExtra(cryptonote::block& block1, const cryptonote::block& block2
return true;
}
static bool fillExtraMM(cryptonote::block& block1, const cryptonote::block& block2) {
cryptonote::tx_extra_merge_mining_tag mm_tag;
mm_tag.depth = 0;
if (!cryptonote::get_block_header_hash(block2, mm_tag.merkle_root)) {
fprintf(stderr, "Can't get child block header hash!\n");
return false;
}
std::vector<uint8_t> extra_nonce_replace;
if (!cryptonote::append_mm_tag_to_extra(extra_nonce_replace, mm_tag)) {
fprintf(stderr, "Can't append mm_tag extra!\n");
return false;
}
if (extra_nonce_replace.size() != MM_NONCE_SIZE) {
fprintf(stderr, "Wrong MM_NONCE_SIZE size!\n");
return false;
}
std::vector<uint8_t>& extra = block1.miner_tx.extra;
size_t pos = 0;
while (pos < extra.size() && extra[pos] != TX_EXTRA_NONCE) {
switch (extra[pos]) {
case TX_EXTRA_TAG_PUBKEY: pos += 1 + sizeof(crypto::public_key); break;
default: {
fprintf(stderr, "Not supported extra tag found: %x\n", extra[pos]);
return false;
}
}
}
if (pos + 1 >= extra.size()) {
fprintf(stderr, "Can't find TX_EXTRA_NONCE in extra\n");
return false;
}
const int extra_nonce_size = extra[pos + 1];
const int new_extra_nonce_size = extra_nonce_size - MM_NONCE_SIZE;
if (new_extra_nonce_size < 0) {
fprintf(stderr, "Too small extra size, can't fit MM tag here\n");
return false;
}
extra[pos + 1] = new_extra_nonce_size;
std::copy(extra_nonce_replace.begin(), extra_nonce_replace.end(), extra.begin() + pos + 1 + new_extra_nonce_size + 1);
//extra.resize(pos + 1 + extra_nonce_size + 1);
// get the most recent timestamp (solve duplicated timestamps on child coin)
if (block2.timestamp > block1.timestamp) block1.timestamp = block2.timestamp;
return true;
}
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.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;
@@ -66,11 +124,10 @@ static bool construct_parent_block(const cryptonote::block& b, cryptonote::block
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);
}
NAN_METHOD(convert_blob) {
NAN_METHOD(convert_blob) { // (parentBlockBuffer, cnBlobType)
if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide one argument.");
Local<Object> target = info[0]->ToObject();
@@ -85,17 +142,16 @@ NAN_METHOD(convert_blob) {
blob_type = static_cast<enum BLOB_TYPE>(Nan::To<int>(info[1]).FromMaybe(0));
}
//convert
block b = AUTO_VAL_INIT(b);
b.set_blob_type(blob_type);
if (!parse_and_validate_block_from_blob(input, b)) return THROW_ERROR_EXCEPTION("Failed to parse block");
if (blob_type == BLOB_TYPE_FORKNOTE2) {
block parent_block;
if (!construct_parent_block(b, parent_block)) return THROW_ERROR_EXCEPTION("Failed to construct parent block");
if (!get_block_hashing_blob(parent_block, output)) return THROW_ERROR_EXCEPTION("Failed to create mining block");
if (!construct_parent_block(b, parent_block)) return THROW_ERROR_EXCEPTION("convert_blob: Failed to construct parent block");
if (!get_block_hashing_blob(parent_block, output)) return THROW_ERROR_EXCEPTION("convert_blob: Failed to create mining block");
} else {
if (!get_block_hashing_blob(b, output)) return THROW_ERROR_EXCEPTION("Failed to create mining block");
if (!get_block_hashing_blob(b, output)) return THROW_ERROR_EXCEPTION("convert_blob: Failed to create mining block");
}
v8::Local<v8::Value> returnValue = Nan::CopyBuffer((char*)output.data(), output.size()).ToLocalChecked();
@@ -109,7 +165,6 @@ NAN_METHOD(get_block_id) {
if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("Argument should be a buffer object.");
blobdata input = std::string(Buffer::Data(target), Buffer::Length(target));
blobdata output = "";
enum BLOB_TYPE blob_type = BLOB_TYPE_CRYPTONOTE;
if (info.Length() >= 2) {
@@ -129,18 +184,13 @@ NAN_METHOD(get_block_id) {
info.GetReturnValue().Set(returnValue);
}
NAN_METHOD(construct_block_blob) {
NAN_METHOD(construct_block_blob) { // (parentBlockTemplateBuffer, nonceBuffer, cnBlobType)
if (info.Length() < 2) return THROW_ERROR_EXCEPTION("You must provide two arguments.");
Local<Object> block_template_buf = info[0]->ToObject();
Local<Object> nonce_buf = info[1]->ToObject();
if (!Buffer::HasInstance(block_template_buf) || !Buffer::HasInstance(nonce_buf)) return THROW_ERROR_EXCEPTION("Both arguments should be buffer objects.");
if (Buffer::Length(nonce_buf) != 4) return THROW_ERROR_EXCEPTION("Nonce buffer has invalid size.");
uint32_t nonce = *reinterpret_cast<uint32_t*>(Buffer::Data(nonce_buf));
blobdata block_template_blob = std::string(Buffer::Data(block_template_buf), Buffer::Length(block_template_buf));
blobdata output = "";
enum BLOB_TYPE blob_type = BLOB_TYPE_CRYPTONOTE;
if (info.Length() >= 3) {
@@ -148,6 +198,12 @@ NAN_METHOD(construct_block_blob) {
blob_type = static_cast<enum BLOB_TYPE>(Nan::To<int>(info[2]).FromMaybe(0));
}
if (Buffer::Length(nonce_buf) != (blob_type == BLOB_TYPE_AEON ? 8 : 4)) return THROW_ERROR_EXCEPTION("Nonce buffer has invalid size.");
uint64_t nonce = blob_type == BLOB_TYPE_AEON ? *reinterpret_cast<uint64_t*>(Buffer::Data(nonce_buf)) : *reinterpret_cast<uint32_t*>(Buffer::Data(nonce_buf));
blobdata block_template_blob = std::string(Buffer::Data(block_template_buf), Buffer::Length(block_template_buf));
blobdata output = "";
block b = AUTO_VAL_INIT(b);
b.set_blob_type(blob_type);
if (!parse_and_validate_block_from_blob(block_template_blob, b)) return THROW_ERROR_EXCEPTION("Failed to parse block");
@@ -166,7 +222,6 @@ NAN_METHOD(construct_block_blob) {
info.GetReturnValue().Set(returnValue);
}
NAN_METHOD(address_decode) {
if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide one argument.");
@@ -227,12 +282,86 @@ NAN_METHOD(address_decode_integrated) {
}
}
NAN_METHOD(get_merged_mining_nonce_size) {
Local<Integer> returnValue = Nan::New(static_cast<uint32_t>(MM_NONCE_SIZE));
info.GetReturnValue().Set(returnValue);
}
NAN_METHOD(construct_mm_parent_block_blob) { // (parentBlockTemplate, blob_type, childBlockTemplate)
if (info.Length() < 3) return THROW_ERROR_EXCEPTION("You must provide three arguments (parentBlock, blob_type, childBlock).");
Local<Object> target = info[0]->ToObject();
Local<Object> child_target = info[2]->ToObject();
if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("First argument should be a buffer object.");
if (!info[1]->IsNumber()) return THROW_ERROR_EXCEPTION("Second argument should be a number");
if (!Buffer::HasInstance(child_target)) return THROW_ERROR_EXCEPTION("Third argument should be a buffer object.");
const enum BLOB_TYPE blob_type = static_cast<enum BLOB_TYPE>(Nan::To<int>(info[1]).FromMaybe(0));
blobdata input = std::string(Buffer::Data(target), Buffer::Length(target));
blobdata child_input = std::string(Buffer::Data(child_target), Buffer::Length(child_target));
block b = AUTO_VAL_INIT(b);
b.set_blob_type(blob_type);
if (!parse_and_validate_block_from_blob(input, b)) return THROW_ERROR_EXCEPTION("construct_mm_parent_block_blob: Failed to parse prent block");
if (blob_type == BLOB_TYPE_CRYPTONOTE_LOKI) b.miner_tx.version = cryptonote::loki_version_2;
block b2 = AUTO_VAL_INIT(b2);
b2.set_blob_type(BLOB_TYPE_FORKNOTE2);
if (!parse_and_validate_block_from_blob(child_input, b2)) return THROW_ERROR_EXCEPTION("construct_mm_parent_block_blob: Failed to parse child block");
if (!fillExtraMM(b, b2)) return THROW_ERROR_EXCEPTION("construct_mm_parent_block_blob: Failed to add merged mining tag to parent block extra");
blobdata output = "";
if (!block_to_blob(b, output)) return THROW_ERROR_EXCEPTION("construct_mm_parent_block_blob: Failed to convert child block to blob");
v8::Local<v8::Value> returnValue = Nan::CopyBuffer((char*)output.data(), output.size()).ToLocalChecked();
info.GetReturnValue().Set(returnValue);
}
NAN_METHOD(construct_mm_child_block_blob) { // (shareBuffer, blob_type, childBlockTemplate)
if (info.Length() < 3) return THROW_ERROR_EXCEPTION("You must provide three arguments (shareBuffer, blob_type, block2).");
Local<Object> block_template_buf = info[0]->ToObject();
Local<Object> child_block_template_buf = info[2]->ToObject();
if (!Buffer::HasInstance(block_template_buf)) return THROW_ERROR_EXCEPTION("First argument should be a buffer object.");
if (!info[1]->IsNumber()) return THROW_ERROR_EXCEPTION("Second argument should be a number");
if (!Buffer::HasInstance(child_block_template_buf)) return THROW_ERROR_EXCEPTION("Third argument should be a buffer object.");
const enum BLOB_TYPE blob_type = static_cast<enum BLOB_TYPE>(Nan::To<int>(info[1]).FromMaybe(0));
blobdata block_template_blob = std::string(Buffer::Data(block_template_buf), Buffer::Length(block_template_buf));
blobdata child_block_template_blob = std::string(Buffer::Data(child_block_template_buf), Buffer::Length(child_block_template_buf));
block b = AUTO_VAL_INIT(b);
b.set_blob_type(blob_type);
if (!parse_and_validate_block_from_blob(block_template_blob, b)) return THROW_ERROR_EXCEPTION("construct_mm_child_block_blob: Failed to parse parent block");
block b2 = AUTO_VAL_INIT(b2);
b2.set_blob_type(BLOB_TYPE_FORKNOTE2);
if (!parse_and_validate_block_from_blob(child_block_template_blob, b2)) return THROW_ERROR_EXCEPTION("construct_mm_child_block_blob: Failed to parse child block");
if (!mergeBlocks(b, b2, std::vector<crypto::hash>())) return THROW_ERROR_EXCEPTION("construct_mm_child_block_blob: Failed to postprocess mining block");
blobdata output = "";
if (!block_to_blob(b2, output)) return THROW_ERROR_EXCEPTION("construct_mm_child_block_blob: Failed to convert child block to blob");
v8::Local<v8::Value> returnValue = Nan::CopyBuffer((char*)output.data(), output.size()).ToLocalChecked();
info.GetReturnValue().Set(returnValue);
}
NAN_MODULE_INIT(init) {
Nan::Set(target, Nan::New("construct_block_blob").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(construct_block_blob)).ToLocalChecked());
Nan::Set(target, Nan::New("get_block_id").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(get_block_id)).ToLocalChecked());
Nan::Set(target, Nan::New("convert_blob").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(convert_blob)).ToLocalChecked());
Nan::Set(target, Nan::New("address_decode").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(address_decode)).ToLocalChecked());
Nan::Set(target, Nan::New("address_decode_integrated").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(address_decode_integrated)).ToLocalChecked());
Nan::Set(target, Nan::New("get_merged_mining_nonce_size").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(get_merged_mining_nonce_size)).ToLocalChecked());
Nan::Set(target, Nan::New("construct_mm_parent_block_blob").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(construct_mm_parent_block_blob)).ToLocalChecked());
Nan::Set(target, Nan::New("construct_mm_child_block_blob").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(construct_mm_child_block_blob)).ToLocalChecked());
}
NODE_MODULE(cryptoforknote, init)
+7
View File
@@ -45,6 +45,13 @@ inline bool do_serialize(Archive &ar, T &v)
return ::serializer<Archive, T>::serialize(ar, v);
}
template <class Archive>
inline bool do_serialize(Archive &ar, bool &v)
{
ar.serialize_blob(&v, sizeof(v));
return true;
}
#ifndef __GNUC__
#ifndef constexpr
#define constexpr