From cd9d169a8fb997f3a60909247cec87e827b0cb5b Mon Sep 17 00:00:00 2001 From: Jianping Wu Date: Tue, 5 Mar 2019 13:18:08 -0800 Subject: [PATCH] WIP: fixed build with cnutils. --- build-aux/m4/ax_boost_date_time.m4 | 113 ++++++++++++++ configure.ac | 3 +- src/Makefile.am | 3 + src/cn_utils/cryptonote_config.h | 138 +++++++++++++++++- .../cryptonote_core/cryptonote_basic_impl.cpp | 6 +- .../cryptonote_format_utils.cpp | 24 +++ .../cryptonote_core/cryptonote_format_utils.h | 2 + src/cn_utils/cryptonote_core/tx_extra.h | 16 +- src/rpc/blockchain.cpp | 19 +-- src/rpc/mining.cpp | 137 ++++------------- src/util.cpp | 22 +++ src/util.h | 2 + 12 files changed, 348 insertions(+), 137 deletions(-) create mode 100644 build-aux/m4/ax_boost_date_time.m4 diff --git a/build-aux/m4/ax_boost_date_time.m4 b/build-aux/m4/ax_boost_date_time.m4 new file mode 100644 index 000000000..3fba4beaa --- /dev/null +++ b/build-aux/m4/ax_boost_date_time.m4 @@ -0,0 +1,113 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_boost_date_time.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_BOOST_DATE_TIME +# +# DESCRIPTION +# +# Test for Date_Time library from the Boost C++ libraries. The macro +# requires a preceding call to AX_BOOST_BASE. Further documentation is +# available at . +# +# This macro calls: +# +# AC_SUBST(BOOST_DATE_TIME_LIB) +# +# And sets: +# +# HAVE_BOOST_DATE_TIME +# +# LICENSE +# +# Copyright (c) 2008 Thomas Porschberg +# Copyright (c) 2008 Michael Tindal +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 22 + +AC_DEFUN([AX_BOOST_DATE_TIME], +[ + AC_ARG_WITH([boost-date-time], + AS_HELP_STRING([--with-boost-date-time@<:@=special-lib@:>@], + [use the Date_Time library from boost - it is possible to specify a certain library for the linker + e.g. --with-boost-date-time=boost_date_time-gcc-mt-d-1_33_1 ]), + [ + if test "$withval" = "no"; then + want_boost="no" + elif test "$withval" = "yes"; then + want_boost="yes" + ax_boost_user_date_time_lib="" + else + want_boost="yes" + ax_boost_user_date_time_lib="$withval" + fi + ], + [want_boost="yes"] + ) + + if test "x$want_boost" = "xyes"; then + AC_REQUIRE([AC_PROG_CC]) + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS + + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS + + AC_CACHE_CHECK(whether the Boost::Date_Time library is available, + ax_cv_boost_date_time, + [AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], + [[using namespace boost::gregorian; date d(2002,Jan,10); + return 0; + ]])], + ax_cv_boost_date_time=yes, ax_cv_boost_date_time=no) + AC_LANG_POP([C++]) + ]) + if test "x$ax_cv_boost_date_time" = "xyes"; then + AC_DEFINE(HAVE_BOOST_DATE_TIME,,[define if the Boost::Date_Time library is available]) + BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` + if test "x$ax_boost_user_date_time_lib" = "x"; then + for libextension in `ls $BOOSTLIBDIR/libboost_date_time*.so* $BOOSTLIBDIR/libboost_date_time*.dylib* $BOOSTLIBDIR/libboost_date_time*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_date_time.*\)\.so.*$;\1;' -e 's;^lib\(boost_date_time.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_date_time.*\)\.a*$;\1;'` ; do + ax_lib=${libextension} + AC_CHECK_LIB($ax_lib, exit, + [BOOST_DATE_TIME_LIB="-l$ax_lib"; AC_SUBST(BOOST_DATE_TIME_LIB) link_date_time="yes"; break], + [link_date_time="no"]) + done + if test "x$link_date_time" != "xyes"; then + for libextension in `ls $BOOSTLIBDIR/boost_date_time*.dll* $BOOSTLIBDIR/boost_date_time*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_date_time.*\)\.dll.*$;\1;' -e 's;^\(boost_date_time.*\)\.a.*$;\1;'` ; do + ax_lib=${libextension} + AC_CHECK_LIB($ax_lib, exit, + [BOOST_DATE_TIME_LIB="-l$ax_lib"; AC_SUBST(BOOST_DATE_TIME_LIB) link_date_time="yes"; break], + [link_date_time="no"]) + done + fi + + else + for ax_lib in $ax_boost_user_date_time_lib boost_date_time-$ax_boost_user_date_time_lib; do + AC_CHECK_LIB($ax_lib, main, + [BOOST_DATE_TIME_LIB="-l$ax_lib"; AC_SUBST(BOOST_DATE_TIME_LIB) link_date_time="yes"; break], + [link_date_time="no"]) + done + + fi + if test "x$ax_lib" = "x"; then + AC_MSG_ERROR(Could not find a version of the library!) + fi + if test "x$link_date_time" != "xyes"; then + AC_MSG_ERROR(Could not link against $ax_lib !) + fi + fi + + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + fi +]) diff --git a/configure.ac b/configure.ac index a30975254..473234f7f 100644 --- a/configure.ac +++ b/configure.ac @@ -785,6 +785,7 @@ AX_BOOST_FILESYSTEM AX_BOOST_PROGRAM_OPTIONS AX_BOOST_THREAD AX_BOOST_CHRONO +AX_BOOST_DATE_TIME dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic dnl counter implementations. In 1.63 and later the std::atomic approach is default. @@ -851,7 +852,7 @@ fi if test x$use_boost = xyes; then -BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB" +BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB $BOOST_DATE_TIME_LIB" dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums diff --git a/src/Makefile.am b/src/Makefile.am index 207cade95..096af4da1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -374,7 +374,10 @@ libbitcoin_cnutils_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/cn_utils -I$(srcdir)/ libbitcoin_cnutils_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_cnutils_a_SOURCES = \ cn_utils/cnutils.cpp \ + cn_utils/cryptonote_core/cryptonote_basic_impl.cpp \ cn_utils/cryptonote_core/cryptonote_format_utils.cpp \ + cn_utils/cryptonote_core/difficulty.cpp \ + cn_utils/crypto/random.c \ cn_utils/crypto/tree-hash.c \ cn_utils/crypto/crypto.cpp \ cn_utils/crypto/crypto-ops.c \ diff --git a/src/cn_utils/cryptonote_config.h b/src/cn_utils/cryptonote_config.h index 31cb03229..f88ba44c2 100644 --- a/src/cn_utils/cryptonote_config.h +++ b/src/cn_utils/cryptonote_config.h @@ -1,16 +1,140 @@ +// Copyright (c) 2014, 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 +#include +#include + +#define CRYPTONOTE_MAX_BLOCK_NUMBER 500000000 +#define CRYPTONOTE_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used! +#define CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE 196608 //size of block (bytes) that is the maximum that miners will produce +#define CRYPTONOTE_MAX_TX_SIZE 1000000000 #define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0 -#define CURRENT_TRANSACTION_VERSION 2 +#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60 +#define CURRENT_TRANSACTION_VERSION 1 #define CURRENT_BLOCK_MAJOR_VERSION 1 #define CURRENT_BLOCK_MINOR_VERSION 0 +#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2 -#define BLOCK_MAJOR_VERSION_1 1 -#define BLOCK_MAJOR_VERSION_2 3 - -#define COIN ((uint64_t)100000000) // pow(10, 8) -#define DEFAULT_FEE ((uint64_t)1000000) // pow(10, 6) +#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60 +// MONEY_SUPPLY - total number coins to be generated +#define MONEY_SUPPLY ((uint64_t)(-1)) +#define EMISSION_SPEED_FACTOR (20) -#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60 +#define CRYPTONOTE_REWARD_BLOCKS_WINDOW 100 +#define CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE 20000 //size of block (bytes) after which reward for block calculated using block size +#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600 #define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12 +// COIN - number of smallest units in one coin +#define COIN ((uint64_t)1000000000000) // pow(10, 12) +#define DEFAULT_FEE ((uint64_t)100000000000) // 5 * pow(10, 11) + + +#define ORPHANED_BLOCKS_MAX_COUNT 100 + + +#define DIFFICULTY_TARGET 60 // seconds +#define DIFFICULTY_WINDOW 720 // blocks +#define DIFFICULTY_LAG 15 // !!! +#define DIFFICULTY_CUT 60 // timestamps to cut after sorting +#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG + + +#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS DIFFICULTY_TARGET * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS +#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS 1 + + +#define DIFFICULTY_BLOCKS_ESTIMATE_TIMESPAN DIFFICULTY_TARGET //just alias + + +#define BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT 10000 //by default, blocks ids count in synchronizing +#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 200 //by default, blocks count in blocks downloading +#define CRYPTONOTE_PROTOCOL_HOP_RELAX_COUNT 3 //value of hop, after which we use only announce of new block + +#define CRYPTONOTE_MEMPOOL_TX_LIVETIME 86400 //seconds, one day +#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week + +#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT 1000 + +#define P2P_LOCAL_WHITE_PEERLIST_LIMIT 1000 +#define P2P_LOCAL_GRAY_PEERLIST_LIMIT 5000 + +#define P2P_DEFAULT_CONNECTIONS_COUNT 12 +#define P2P_DEFAULT_HANDSHAKE_INTERVAL 60 //secondes +#define P2P_DEFAULT_PACKET_MAX_SIZE 50000000 //50000000 bytes maximum packet size +#define P2P_DEFAULT_PEERS_IN_HANDSHAKE 250 +#define P2P_DEFAULT_CONNECTION_TIMEOUT 5000 //5 seconds +#define P2P_DEFAULT_PING_CONNECTION_TIMEOUT 2000 //2 seconds +#define P2P_DEFAULT_INVOKE_TIMEOUT 60*2*1000 //2 minutes +#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds +#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70 + +#define ALLOW_DEBUG_COMMANDS + +#define CRYPTONOTE_NAME "bitmonero" +#define CRYPTONOTE_POOLDATA_FILENAME "poolstate.bin" +#define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "blockchain.bin" +#define CRYPTONOTE_BLOCKCHAINDATA_TEMP_FILENAME "blockchain.bin.tmp" +#define P2P_NET_DATA_FILENAME "p2pstate.bin" +#define MINER_CONFIG_FILE_NAME "miner_conf.json" + +#define THREAD_STACK_SIZE 5 * 1024 * 1024 + +// New constants are intended to go here +namespace config +{ + uint64_t const DEFAULT_FEE_ATOMIC_XMR_PER_KB = 500; // Just a placeholder! Change me! + uint8_t const FEE_CALCULATION_MAX_RETRIES = 10; + uint64_t const DEFAULT_DUST_THRESHOLD = 5000000000; // 5 * 10^9 + std::string const P2P_REMOTE_DEBUG_TRUSTED_PUB_KEY = "0000000000000000000000000000000000000000000000000000000000000000"; + + uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18; + uint16_t const P2P_DEFAULT_PORT = 18080; + uint16_t const RPC_DEFAULT_PORT = 18081; + boost::uuids::uuid const NETWORK_ID = { { + 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10 + } }; // Bender's nightmare + std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"; + uint32_t const GENESIS_NONCE = 10000; + + namespace testnet + { + uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 53; + uint16_t const P2P_DEFAULT_PORT = 28080; + uint16_t const RPC_DEFAULT_PORT = 28081; + boost::uuids::uuid const NETWORK_ID = { { + 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x11 + } }; // Bender's daydream + std::string const GENESIS_TX = "013c01ff0001ffffffffffff0f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd0880712101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b"; + uint32_t const GENESIS_NONCE = 10001; + } +} \ No newline at end of file diff --git a/src/cn_utils/cryptonote_core/cryptonote_basic_impl.cpp b/src/cn_utils/cryptonote_core/cryptonote_basic_impl.cpp index 876b966d6..31a9d6d35 100644 --- a/src/cn_utils/cryptonote_core/cryptonote_basic_impl.cpp +++ b/src/cn_utils/cryptonote_core/cryptonote_basic_impl.cpp @@ -80,7 +80,7 @@ namespace cryptonote { //----------------------------------------------------------------------- std::string get_account_address_as_str(const account_public_address& adr) { - return tools::base58::encode_addr(CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(adr)); + return tools::base58::encode_addr(config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(adr)); } //----------------------------------------------------------------------- bool is_coinbase(const transaction& tx) @@ -106,9 +106,9 @@ namespace cryptonote { return false; } - if (CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX != prefix) + if (config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX != prefix) { - LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX); + LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX); return false; } diff --git a/src/cn_utils/cryptonote_core/cryptonote_format_utils.cpp b/src/cn_utils/cryptonote_core/cryptonote_format_utils.cpp index 41eac6b43..68ba17f83 100644 --- a/src/cn_utils/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cn_utils/cryptonote_core/cryptonote_format_utils.cpp @@ -316,6 +316,26 @@ namespace cryptonote return true; } //--------------------------------------------------------------- + bool append_keva_block_to_extra(std::vector& tx_extra, const tx_extra_keva_block& keva_block) + { + blobdata blob; + if (!t_serializable_object_to_blob(keva_block, blob)) + return false; + + tx_extra.push_back(TX_EXTRA_KEVA_BLOCK_TAG); + std::copy(reinterpret_cast(blob.data()), reinterpret_cast(blob.data() + blob.size()), std::back_inserter(tx_extra)); + return true; + } + //--------------------------------------------------------------- + bool get_keva_block_from_extra(const std::vector& tx_extra, tx_extra_keva_block& keva_block) + { + std::vector tx_extra_fields; + if (!parse_tx_extra(tx_extra, tx_extra_fields)) + return false; + + return find_tx_extra_field_by_type(tx_extra_fields, keva_block); + } + //--------------------------------------------------------------- bool construct_tx(const account_keys& sender_account_keys, const std::vector& sources, const std::vector& destinations, std::vector extra, transaction& tx, uint64_t unlock_time) { tx.vin.clear(); @@ -724,6 +744,7 @@ namespace cryptonote return get_object_hash(blob, res); } //--------------------------------------------------------------- + #if 0 bool generate_genesis_block(block& bl) { //genesis block @@ -773,6 +794,7 @@ namespace cryptonote h = genesis_block_hash; return true; } + #endif //--------------------------------------------------------------- bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height) { @@ -899,6 +921,7 @@ namespace cryptonote return check_hash(proof_of_work, current_diffic); } //--------------------------------------------------------------- + #if 0 bool check_proof_of_work_v2(const block& bl, difficulty_type current_diffic, crypto::hash& proof_of_work) { @@ -937,4 +960,5 @@ namespace cryptonote { } //--------------------------------------------------------------- +#endif } diff --git a/src/cn_utils/cryptonote_core/cryptonote_format_utils.h b/src/cn_utils/cryptonote_core/cryptonote_format_utils.h index b9e5dc59c..7eb9eb21c 100644 --- a/src/cn_utils/cryptonote_core/cryptonote_format_utils.h +++ b/src/cn_utils/cryptonote_core/cryptonote_format_utils.h @@ -64,6 +64,8 @@ namespace cryptonote bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); bool append_mm_tag_to_extra(std::vector& tx_extra, const tx_extra_merge_mining_tag& mm_tag); bool get_mm_tag_from_extra(const std::vector& tx_extra, tx_extra_merge_mining_tag& mm_tag); + bool append_keva_block_to_extra(std::vector& tx_extra, const tx_extra_keva_block& keva_block); + bool get_keva_block_from_extra(const std::vector& tx_extra, tx_extra_keva_block& keva_block); bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector& outs, uint64_t& money_transfered); bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector& outs, uint64_t& money_transfered); diff --git a/src/cn_utils/cryptonote_core/tx_extra.h b/src/cn_utils/cryptonote_core/tx_extra.h index bf06e98fd..4293d2afd 100644 --- a/src/cn_utils/cryptonote_core/tx_extra.h +++ b/src/cn_utils/cryptonote_core/tx_extra.h @@ -13,8 +13,7 @@ #define TX_EXTRA_NONCE 0x02 #define TX_EXTRA_MERGE_MINING_TAG 0x03 -#define TX_EXTRA_KEVA_BLOCKHASH_TAG 0xc1 -#define TX_EXTRA_KEVA_TX_LIST_TAG 0xc2 +#define TX_EXTRA_KEVA_BLOCK_TAG 0xa1 #define TX_EXTRA_NONCE_PAYMENT_ID 0x00 @@ -134,14 +133,25 @@ namespace cryptonote } }; + struct tx_extra_keva_block + { + std::string keva_block; + + BEGIN_SERIALIZE() + FIELD(keva_block) + 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_field; + typedef boost::variant 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); +VARIANT_TAG(binary_archive, cryptonote::tx_extra_keva_block, TX_EXTRA_KEVA_BLOCK_TAG); + diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f345f7018..79ca48bb1 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -62,24 +62,7 @@ double GetDifficulty(const CChain& chain, const CBlockIndex* blockindex) blockindex = chain.Tip(); } - int nShift = (blockindex->nBits >> 24) & 0xff; - - // Difficulty 1 is: 0x2100ffff - double dDiff = - (double)0x00ffff / (double)(blockindex->nBits & 0x00ffffff); - - while (nShift < 33) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > 33) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; + return ConvertNBitsToDiff(blockindex->nBits); } double GetDifficulty(const CBlockIndex* blockindex) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index d9efaed0a..69c4ca5fe 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -785,6 +785,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) std::string strMode = "template"; #if 0 + // TODO: IMPORTANT!!!! uncomment the following!!! if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Kevacoin is not connected!"); @@ -825,50 +826,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) UpdateTime(pblock, consensusParams, pindexPrev); pblock->nNonce = 0; - UniValue transactions(UniValue::VARR); - std::map setTxIndex; - int i = 0; - for (const auto& it : pblock->vtx) { - const CTransaction& tx = *it; - uint256 txHash = tx.GetHash(); - setTxIndex[txHash] = i++; - - if (tx.IsCoinBase()) - continue; - - UniValue entry(UniValue::VOBJ); - - entry.push_back(Pair("data", EncodeHexTx(tx))); - entry.push_back(Pair("txid", txHash.GetHex())); - entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex())); - - UniValue deps(UniValue::VARR); - for (const CTxIn &in : tx.vin) - { - if (setTxIndex.count(in.prevout.hash)) - deps.push_back(setTxIndex[in.prevout.hash]); - } - entry.push_back(Pair("depends", deps)); - - int index_in_template = i - 1; - entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template])); - int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template]; - entry.push_back(Pair("sigops", nTxSigOps)); - entry.push_back(Pair("weight", GetTransactionWeight(tx))); - - transactions.push_back(entry); - } - - UniValue aux(UniValue::VOBJ); - aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()))); - - arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits); - - UniValue aMutable(UniValue::VARR); - aMutable.push_back("time"); - aMutable.push_back("transactions"); - aMutable.push_back("prevblock"); - + std::set setClientRules; UniValue aRules(UniValue::VARR); UniValue vbavailable(UniValue::VOBJ); for (int j = 0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { @@ -887,6 +845,12 @@ UniValue getblocktemplate(const JSONRPCRequest& request) { const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit)); + if (setClientRules.find(vbinfo.name) == setClientRules.end()) { + if (!vbinfo.gbt_force) { + // If the client doesn't support this, don't indicate it in the [default] version + pblock->nVersion &= ~VersionBitsMask(consensusParams, pos); + } + } break; } case THRESHOLD_ACTIVE: @@ -894,52 +858,30 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // Add to rules only const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; aRules.push_back(gbt_vb_name(pos)); + if (setClientRules.find(vbinfo.name) == setClientRules.end()) { + // Not supported by the client; make sure it's safe to proceed + if (!vbinfo.gbt_force) { + // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name)); + } + } break; } } } - // Update witness commitment after adding the transactions. - pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, consensusParams); + // Generate the merkle root as all the transactions (including coinbase) are known. BlockMerkleRoot(*pblock); uint256 blockHash = pblock->GetHash(); -#if 0 - result.push_back(Pair("version", pblock->nVersion)); - result.push_back(Pair("rules", aRules)); - result.push_back(Pair("vbavailable", vbavailable)); - result.push_back(Pair("vbrequired", int(0))); - - result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); - result.push_back(Pair("transactions", transactions)); - result.push_back(Pair("coinbaseaux", aux)); - result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue)); - result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast))); - result.push_back(Pair("target", hashTarget.GetHex())); - result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1)); - result.push_back(Pair("mutable", aMutable)); - result.push_back(Pair("noncerange", "00000000ffffffff")); - int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST; - int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE; - result.push_back(Pair("sigoplimit", nSigOpLimit)); - result.push_back(Pair("sizelimit", nSizeLimit)); - result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT)); - result.push_back(Pair("curtime", pblock->GetBlockTime())); - result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); - result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); - - if (!pblocktemplate->vchCoinbaseCommitment.empty() && fSupportsSegwit) { - result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end()))); - } -#endif - cryptonote::block cn_block; // block_header // const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0; cn_block.major_version = 8; // cn variant 2 cn_block.minor_version = 0; cn_block.timestamp = pblock->GetBlockTime(); - memcpy(&(cn_block.prev_id), pblock->hashPrevBlock.begin(), sizeof(pblock->hashPrevBlock)); + // The prev_id is used to store kevacoin block hash, as a proof of work. + memcpy(&(cn_block.prev_id), blockHash.begin(), blockHash.size()); cn_block.nonce = 0; // block @@ -982,43 +924,28 @@ UniValue getblocktemplate(const JSONRPCRequest& request) throw JSONRPCError(RPC_INTERNAL_ERROR, "Internal error: Failed to calculate offset"); } - // No transactions other than base one. + // No transactions other than coinbase. cn_block.tx_hashes.clear(); - // Copy kevacoin block hash to the extra field, as a proof that the work has - // been done for the block. - // Copy all the txs to extra so that later we can use them to - // reconstruct the block. - const uint32_t blockHashSize = blockHash.size(); - const uint32_t txTotalSize = 1 + blockHashSize + 1 + 4 + pblock->vtx.size() * sizeof(CTransaction); - cn_block.miner_tx.extra.resize(cn_block.miner_tx.extra.size() + txTotalSize, 0); - size_t lastOffset = cn_block.miner_tx.extra.size(); - uint8_t miningTag = TX_EXTRA_KEVA_BLOCKHASH_TAG; - memcpy(cn_block.miner_tx.extra.data() + lastOffset, &miningTag, 1); - lastOffset ++; - memcpy(cn_block.miner_tx.extra.data() + lastOffset, blockHash.begin(), blockHashSize); - lastOffset += blockHashSize; - uint8_t kevaTxsTag = TX_EXTRA_KEVA_TX_LIST_TAG; - memcpy(cn_block.miner_tx.extra.data() + lastOffset, &kevaTxsTag, 1); - lastOffset ++; - uint32_t txsSize = ; - // This is not right! Need to serialize the transactions. - // Maybe using SerializationOp of CBlock to serialize the all block instead? - memcpy(cn_block.miner_tx.extra.data() + lastOffset, pblock->vtx.data(), pblock->vtx.size() * sizeof(CTransaction)); + // Copy keva block to extra so that we can use it in submitblock. + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + stream << *pblock; + std::string kevaBlockData = HexStr(stream.begin(), stream.end()); + cryptonote::tx_extra_keva_block extra_keva_block; + extra_keva_block.keva_block = kevaBlockData; + cryptonote::append_keva_block_to_extra(cn_block.miner_tx.extra, extra_keva_block); UniValue result(UniValue::VOBJ); - cryptonote::blobdata hashing_blob; - cryptonote::get_block_hashing_blob(cn_block, hashing_blob); - - //res.prev_hash = epee::string_tools::pod_to_hex(cn_block.prev_id); - //res.blocktemplate_blob = epee::string_tools::buff_to_hex_nodelimer(block_blob); - //res.blockhashing_blob = epee::string_tools::buff_to_hex_nodelimer(hashing_blob); - + const double difficulty = ConvertNBitsToDiff(pblock->nBits); result.push_back(Pair("blocktemplate_blob", pblock->hashPrevBlock.GetHex())); - result.push_back(Pair("difficulty", pblock->hashPrevBlock.GetHex())); + result.push_back(Pair("difficulty", std::to_string(difficulty))); result.push_back(Pair("height", std::to_string(height))); result.push_back(Pair("reserved_offset", std::to_string(reserved_offset))); + // Kevacoin specific entries. Not used for now and may be useful in the future. + result.push_back(Pair("rules", aRules)); + result.push_back(Pair("vbavailable", vbavailable)); + return result; } diff --git a/src/util.cpp b/src/util.cpp index a3a4eb824..266265084 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -961,3 +961,25 @@ int64_t GetStartupTime() { return nStartupTime; } + +double ConvertNBitsToDiff(uint32_t nBits) +{ + int nShift = (nBits >> 24) & 0xff; + + // Difficulty 1 is: 0x2100ffff + double dDiff = + (double)0x00ffff / (double)(nBits & 0x00ffffff); + + while (nShift < 33) + { + dDiff *= 256.0; + nShift++; + } + while (nShift > 33) + { + dDiff /= 256.0; + nShift--; + } + + return dDiff; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h index 4ce441915..d85fcd698 100644 --- a/src/util.h +++ b/src/util.h @@ -349,4 +349,6 @@ std::unique_ptr MakeUnique(Args&&... args) return std::unique_ptr(new T(std::forward(args)...)); } +double ConvertNBitsToDiff(uint32_t nBits); + #endif // BITCOIN_UTIL_H