From 4d3b091eb269a6cc275aba669b86079639dd9676 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Mon, 1 Oct 2018 12:12:15 -0700 Subject: [PATCH 01/13] CVE-2018-17144 fix https://bitcoincore.org/en/2018/09/20/notice/ --- src/consensus/tx_verify.cpp | 16 +++++++--------- src/consensus/tx_verify.h | 2 +- src/validation.cpp | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index 9878a29ab..1380f7ac8 100755 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -157,7 +157,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i return nSigOps; } -bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs) +bool CheckTransaction(const CTransaction& tx, CValidationState &state) { // Basic checks that don't depend on any context if (tx.vin.empty()) @@ -181,14 +181,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge"); } - // Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock - if (fCheckDuplicateInputs) { - std::set vInOutPoints; - for (const auto& txin : tx.vin) - { - if (!vInOutPoints.insert(txin.prevout).second) - return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate"); - } + // Check for duplicate inputs - note that this check is slow (no longer skipped due to CVE-2018-17144) + std::set vInOutPoints; + for (const auto& txin : tx.vin) + { + if (!vInOutPoints.insert(txin.prevout).second) + return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate"); } if (tx.IsCoinBase()) diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h index d1f401a52..50122660b 100755 --- a/src/consensus/tx_verify.h +++ b/src/consensus/tx_verify.h @@ -17,7 +17,7 @@ class CValidationState; /** Transaction validation functions */ /** Context-independent validity checks */ -bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true); +bool CheckTransaction(const CTransaction& tx, CValidationState& state); namespace Consensus { /** diff --git a/src/validation.cpp b/src/validation.cpp index 1c37b036b..521f55ce6 100755 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2824,7 +2824,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P // Check transactions for (const auto& tx : block.vtx) - if (!CheckTransaction(*tx, state, false)) + if (!CheckTransaction(*tx, state)) return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(), strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage())); From 1ee6c75b74b17cb569abd4c887fab25bca4a081d Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Mon, 1 Oct 2018 15:57:35 -0700 Subject: [PATCH 02/13] checkpoint block 3,000,000 --- src/chainparams.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ab28ea850..45f2c9498 100755 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -102,10 +102,10 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1554098766; // April 1st, 2019 // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000011f1db4843f05806"); + consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000050b6f9f1c2494ad8"); // 3,000,000 // By default assume that the signatures in ancestors of this block are valid. - consensus.defaultAssumeValid = uint256S("0x4a8cb5ca397b7c92c270ccfa9139ffb93f7c5b9515e52486c635c7a1dee9d221"); // 2000000 + consensus.defaultAssumeValid = uint256S("0x5ad3a302e3b1c681f0177411384ea03ee595a80a530c23a61f22839fae948e7f"); // 3,000,000 // Difficulty adjustments consensus.nPowTargetSpacing = 40; // 40s block time @@ -191,15 +191,16 @@ public: {1796633, uint256S("0xc2da8b936a7f2c0de02aa0c6c45f3d971ebad78655255a945b0e60b62f27d445")}, {2094558, uint256S("0x946616c88286f32bfac15868456d87a86f8611e1f9b56594b81e46831ce43f81")}, {2532181, uint256S("0xcacd5149aaed1088ae1db997a741210b0525e941356104120f182f3159931c79")}, + {3000000, uint256S("0x5ad3a302e3b1c681f0177411384ea03ee595a80a530c23a61f22839fae948e7f")}, } }; chainTxData = ChainTxData{ - // Data as of block cacd5149aaed1088ae1db997a741210b0525e941356104120f182f3159931c79 (height 2532181). - 1515282818, // * UNIX timestamp of last known number of transactions - 3223208, // * total number of transactions between genesis and that timestamp + // Data as of block 5ad3a302e3b1c681f0177411384ea03ee595a80a530c23a61f22839fae948e7f (height 3,000,000). + 1538389345, // * UNIX timestamp of last known number of transactions + 4563023, // * total number of transactions between genesis and that timestamp // (the tx=... number in the SetBestChain debug.log lines) - 0.04 // * estimated number of transactions per second after that timestamp + 0.03 // * estimated number of transactions per second after that timestamp }; } @@ -237,10 +238,10 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1530446401; // July 1, 2018 FLO future date // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000000000000083540886d"); + consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000003dd47d3172"); // 230,000 // By default assume that the signatures in ancestors of this block are valid. - consensus.defaultAssumeValid = uint256S("0x4be79531ee8b0f410f0d8c8d785083acb4e14e5d54b0820502bc60f98a629b19"); //flo testnet block 20,000 + consensus.defaultAssumeValid = uint256S("0xc2e6451240a580c3bfa5ddbfad1b001f8655e7c51d5c32c123e16f69c2d2b539"); // 230,000 // Difficulty adjustments consensus.nPowTargetSpacing = 40; // 40s block time @@ -303,14 +304,15 @@ public: checkpointData = (CCheckpointData) { { {2056, uint256S("0xd3334db071731beaa651f10624c2fea1a5e8c6f9e50f0e602f86262938374148")}, + {230000, uint256S("0xc2e6451240a580c3bfa5ddbfad1b001f8655e7c51d5c32c123e16f69c2d2b539")}, } }; chainTxData = ChainTxData{ - // flo: Data as of block 4be79531ee8b0f410f0d8c8d785083acb4e14e5d54b0820502bc60f98a629b19 (height 20000) - 1515699893, // * UNIX timestamp of last known number of transactions - 34572, // * total number of transactions between genesis and that timestamp - 0.001454897737891917 // * estimated number of transactions per second after that timestamp + // flo: Data as of block c2e6451240a580c3bfa5ddbfad1b001f8655e7c51d5c32c123e16f69c2d2b539 (height 230,000) + 1538135261, // * UNIX timestamp of last known number of transactions + 265211, // * total number of transactions between genesis and that timestamp + 0.01 // * estimated number of transactions per second after that timestamp }; } From 998ac47e9a5fd1b769af2b94579e3ca0d2f4ecb0 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Mon, 1 Oct 2018 15:59:32 -0700 Subject: [PATCH 03/13] version bump --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 8f75e88bb..26b5d5b0f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,10 +2,10 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 15) -define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_REVISION, 1) +define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2017) +define(_COPYRIGHT_YEAR, 2018) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[FLO Core]]) AC_INIT([FLO Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/floblockchain/flo/issues],[flo],[https://flo.cash/]) From 2fe045194caf8137878128ebf01461b9a99e7fb4 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Thu, 20 Sep 2018 12:13:25 -0500 Subject: [PATCH 04/13] nlr --- src/chainparams.cpp | 3 + src/chainparams.h | 2 + src/init.cpp | 1 + src/rpc/blockchain.cpp | 2 +- src/validation.cpp | 36 +++++- src/validation.h | 2 +- test/functional/nlr.py | 105 ++++++++++++++++++ .../test_framework/test_framework.py | 6 + 8 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 test/functional/nlr.py diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 45f2c9498..35139a011 100755 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -139,6 +139,7 @@ public: pchMessageStart[3] = 0xf1; nDefaultPort = 7312; nPruneAfterHeight = 100000; + nNlrLimit = 100; // 100 * ~40s = ~66 minutes genesis = CreateGenesisBlock(1371488396, 1000112548, 0x1e0ffff0, 1, 100 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); @@ -275,6 +276,7 @@ public: pchMessageStart[3] = 0xf2; nDefaultPort = 17312; nPruneAfterHeight = 100000; + nNlrLimit = 50; // 50 * ~40s = ~33 minutes genesis = CreateGenesisBlock(1371387277, 1000580675, 0x1e0ffff0, 1, 100 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); @@ -389,6 +391,7 @@ public: pchMessageStart[3] = 0xda; nDefaultPort = 17412; nPruneAfterHeight = 1000; + nNlrLimit = 10; genesis = CreateGenesisBlock(1371387277, 0, 0x207fffff, 1, 100 * COIN); consensus.hashGenesisBlock = genesis.GetHash(); diff --git a/src/chainparams.h b/src/chainparams.h index a7b1c62a1..f4df46532 100755 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -63,6 +63,7 @@ public: const Consensus::Params& GetConsensus() const { return consensus; } const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } int GetDefaultPort() const { return nDefaultPort; } + int NoLargeReorgLimit() const { return nNlrLimit; } const CBlock& GenesisBlock() const { return genesis; } /** Default value for -checkmempool and -checkblockindex argument */ @@ -87,6 +88,7 @@ protected: CMessageHeader::MessageStartChars pchMessageStart; int nDefaultPort; uint64_t nPruneAfterHeight; + int nNlrLimit; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; std::string strNetworkID; diff --git a/src/init.cpp b/src/init.cpp index da71ebb5a..f52086286 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -401,6 +401,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER)); strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER)); strUsage += HelpMessageOpt("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT)); + strUsage += HelpMessageOpt("-nlrlimit=", strprintf(_("Set the limit to be considered a large reorg, -nlrlimit=0 to disable NLR mode (default: %u)"), defaultChainParams->NoLargeReorgLimit())); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 046769454..b8cd8e532 100755 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1457,7 +1457,7 @@ UniValue reconsiderblock(const JSONRPCRequest& request) } CValidationState state; - ActivateBestChain(state, Params()); + ActivateBestChain(state, Params(), std::shared_ptr(), true); if (!state.IsValid()) { throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); diff --git a/src/validation.cpp b/src/validation.cpp index 521f55ce6..5da8e7444 100755 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2313,12 +2313,42 @@ static void PruneBlockIndexCandidates() { * Try to make some progress towards making pindexMostWork the active block. * pblock is either nullptr or a pointer to a CBlock corresponding to pindexMostWork. */ -static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) +static bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr& pblock, bool& fInvalidFound, ConnectTrace& connectTrace, bool reconsider) { AssertLockHeld(cs_main); const CBlockIndex *pindexOldTip = chainActive.Tip(); const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork); + int nNlrLimit = gArgs.GetArg("-nlrlimit", Params().NoLargeReorgLimit()); + if (nNlrLimit != 0 && !reconsider && !IsInitialBlockDownload() && pindexFork != nullptr + && chainActive.Tip()->nHeight - pindexFork->nHeight >= nNlrLimit) { + LogPrintf("%s: NLR triggered! current height=%d current hash=%s | fork height=%d fork hash=%s\n", __func__, + pindexOldTip->nHeight, pindexOldTip->GetBlockHash().ToString(), pindexMostWork->nHeight, + pindexMostWork->GetBlockHash().ToString()); + CBlockIndex *pindexWalk = pindexMostWork; + + // mark invalid_child from tip of fork to second block of fork + while (pindexWalk->nHeight != pindexFork->nHeight+2) { + pindexWalk = pindexWalk->pprev; + pindexWalk->nStatus |= BLOCK_FAILED_CHILD; + setDirtyBlockIndex.insert(pindexWalk); + setBlockIndexCandidates.erase(pindexWalk); + } + + // mark invalid first block of fork + pindexWalk = pindexWalk->pprev; + pindexWalk->nStatus |= BLOCK_FAILED_VALID; + setDirtyBlockIndex.insert(pindexWalk); + setBlockIndexCandidates.erase(pindexWalk); + + // sanity check + assert(pindexWalk->pprev == pindexFork); + + fInvalidFound = true; + InvalidChainFound(pindexMostWork); + return true; + } + // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; DisconnectedBlockTransactions disconnectpool; @@ -2420,7 +2450,7 @@ static void NotifyHeaderTip() { * or an activated best chain. pblock is either nullptr or a pointer to a block * that is already loaded (to avoid loading it again from disk). */ -bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr pblock) { +bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, std::shared_ptr pblock, bool reconsider) { // Note that while we're often called here from ProcessNewBlock, this is // far from a guarantee. Things in the P2P/RPC will often end up calling // us in the middle of ProcessNewBlock - do not assume pblock is set @@ -2451,7 +2481,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, bool fInvalidFound = false; std::shared_ptr nullBlockPtr; - if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace)) + if (!ActivateBestChainStep(state, chainparams, pindexMostWork, pblock && pblock->GetHash() == pindexMostWork->GetBlockHash() ? pblock : nullBlockPtr, fInvalidFound, connectTrace, reconsider)) return false; if (fInvalidFound) { diff --git a/src/validation.h b/src/validation.h index 0e120cd56..ac7067e96 100755 --- a/src/validation.h +++ b/src/validation.h @@ -273,7 +273,7 @@ bool IsInitialBlockDownload(); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ -bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr pblock = std::shared_ptr()); +bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr pblock = std::shared_ptr(), bool reconsider=false); CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */ diff --git a/test/functional/nlr.py b/test/functional/nlr.py new file mode 100644 index 000000000..bbc891c6b --- /dev/null +++ b/test/functional/nlr.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) Flo Developers 2013-2018 +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test the getchaintips RPC. + +- introduce a network split +- work on chains of different lengths +- join the network together again +- verify that getchaintips now returns two chain tips. +""" + +import time + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal + +class GetChainTipsTest (BitcoinTestFramework): + def __init__(self): + super().__init__() + self.num_nodes = 4 + self.extra_args = [['-nlrlimit=0'], ['-nlrlimit=10'], ['-nlrlimit=10'], ['-nlrlimit=10']] + self.setup_clean_chain = False + + def run_test (self): + + tips = self.nodes[0].getchaintips () + assert_equal (len (tips), 1) + assert_equal (tips[0]['branchlen'], 0) + assert_equal (tips[0]['height'], 200) + assert_equal (tips[0]['status'], 'active') + + # Split the network and build two chains of different lengths. + self.split_network() + self.nodes[0].generate(10) + self.nodes[2].generate(20) + self.sync_all([self.nodes[:2], self.nodes[2:]]) + + tips = self.nodes[1].getchaintips () + assert_equal (len (tips), 1) + shortTip = tips[0] + assert_equal(shortTip['branchlen'], 0) + assert_equal(shortTip['height'], 210) + assert_equal(tips[0]['status'], 'active') + + tips = self.nodes[3].getchaintips () + assert_equal (len (tips), 1) + longTip = tips[0] + assert_equal (longTip['branchlen'], 0) + assert_equal (longTip['height'], 220) + assert_equal (tips[0]['status'], 'active') + + # Join the network halves and check that we now have two tips + # (at least at the nodes that previously had the short chain). + print("pre join") + self.join_network_no_sync () + time.sleep(10) + print("post join") + + print("node 0") + print(self.nodes[0].getchaintips()) + print("node 1") + print(self.nodes[1].getchaintips()) + print("node 2") + print(self.nodes[2].getchaintips()) + + print("reconsider") + self.nodes[1].reconsiderblock(self.nodes[2].getbestblockhash()) + self.sync_all() + + print("node 0") + print(self.nodes[0].getchaintips ()) + print("node 1") + print(self.nodes[1].getchaintips ()) + print("node 2") + print(self.nodes[2].getchaintips ()) + self.nodes[2].generate(20) + + self.sync_all() + self.nodes[1].generate(20) + + self.sync_all() + + print("node 0") + print(self.nodes[0].getchaintips ()) + print("node 1") + print(self.nodes[1].getchaintips ()) + print("node 2") + print(self.nodes[2].getchaintips ()) + + # tips = self.nodes[1].getchaintips () + # assert_equal (len (tips), 2) + # assert_equal (tips[0], longTip) + # + # assert_equal (tips[1]['branchlen'], 10) + # assert_equal (tips[1]['status'], 'valid-fork') + # tips[1]['branchlen'] = 0 + # tips[1]['status'] = 'active' + # assert_equal (tips[1], shortTip) + + assert_equal(1, 3) + +if __name__ == '__main__': + GetChainTipsTest().main() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 3fd7685ce..3cbe5fd17 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -310,6 +310,12 @@ class BitcoinTestFramework(object): connect_nodes_bi(self.nodes, 1, 2) self.sync_all() + def join_network_no_sync(self): + """ + Join the (previously split) network halves together. Do not wait sync. + """ + connect_nodes_bi(self.nodes, 1, 2) + def sync_all(self, node_groups=None): if not node_groups: node_groups = [self.nodes] From a33e124e82bebd541295d958af23f79efd4774c9 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Mon, 8 Oct 2018 12:56:17 -0700 Subject: [PATCH 05/13] version bump --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 26b5d5b0f..41376ff33 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 15) define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_BUILD, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2018) define(_COPYRIGHT_HOLDERS,[The %s developers]) From 0b8b8f16c6213fc0c7b8ff481dba1a1bfc16202d Mon Sep 17 00:00:00 2001 From: Sky Young Date: Tue, 29 Jan 2019 10:10:35 -0700 Subject: [PATCH 06/13] Increase Maximum utxo chain to 1250 --- src/validation.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/validation.h b/src/validation.h index ac7067e96..28d386163 100755 --- a/src/validation.h +++ b/src/validation.h @@ -59,13 +59,13 @@ static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN; //! -maxtxfee will warn if called with a higher fee than this amount (in satoshis) static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB; /** Default for -limitancestorcount, max number of in-mempool ancestors */ -static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25; +static const unsigned int DEFAULT_ANCESTOR_LIMIT = 1250; /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ -static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101; +static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 5050; /** Default for -limitdescendantcount, max number of in-mempool descendants */ -static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25; +static const unsigned int DEFAULT_DESCENDANT_LIMIT = 1250; /** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */ -static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101; +static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 5050; /** Default for -mempoolexpiry, expiration time for mempool transactions in hours */ static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336; /** Maximum kilobytes for transactions to store for processing during reorg */ From 3da8e842385d87a93ced60173f7d55dffd0fddda Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Tue, 29 Jan 2019 11:24:31 -0800 Subject: [PATCH 07/13] bump version and copyright year --- configure.ac | 6 +++--- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 2 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 41376ff33..bd2ffc489 100644 --- a/configure.ac +++ b/configure.ac @@ -2,10 +2,10 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 15) -define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_REVISION, 2) +define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) -define(_COPYRIGHT_YEAR, 2018) +define(_COPYRIGHT_YEAR, 2019) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[FLO Core]]) AC_INIT([FLO Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/floblockchain/flo/issues],[flo],[https://flo.cash/]) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index caec8ae04..5b6becfa5 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "flo-linux-0.15" +name: "flo-linux-0.15.2.0" enable_cache: true suites: - "trusty" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 6a076b1d2..7ec964363 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "flo-osx-0.15" +name: "flo-osx-0.15.2.0" enable_cache: true suites: - "trusty" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 32af3b3eb..5adbde3e8 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "flo-win-0.15" +name: "flo-win-0.15.2.0" enable_cache: true suites: - "trusty" From 818b91b454342007ea36ba6fd2ab79a32203745a Mon Sep 17 00:00:00 2001 From: Sky Young Date: Mon, 4 Feb 2019 11:24:11 -0700 Subject: [PATCH 08/13] Set Ancestor/Descendant Size limit to 1.75MB Rational for 1.75MB limit: https://github.com/floblockchain/flo/pull/8#issuecomment-458666055 Comment documenting testing of values: https://github.com/floblockchain/flo/pull/8#issuecomment-460356226 --- src/validation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/validation.h b/src/validation.h index 28d386163..cae0b7833 100755 --- a/src/validation.h +++ b/src/validation.h @@ -61,11 +61,11 @@ static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB; /** Default for -limitancestorcount, max number of in-mempool ancestors */ static const unsigned int DEFAULT_ANCESTOR_LIMIT = 1250; /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ -static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 5050; +static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 1750; /** Default for -limitdescendantcount, max number of in-mempool descendants */ static const unsigned int DEFAULT_DESCENDANT_LIMIT = 1250; /** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */ -static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 5050; +static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 1750; /** Default for -mempoolexpiry, expiration time for mempool transactions in hours */ static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336; /** Maximum kilobytes for transactions to store for processing during reorg */ From ffa312c126c2aa2686cf5f6e212ec6bc30f32a8d Mon Sep 17 00:00:00 2001 From: Sky Young Date: Tue, 29 Jan 2019 10:35:17 -0700 Subject: [PATCH 09/13] Remove prepended `text:` from floData sent from UI --- src/qt/sendcoinsdialog.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index b3235bbba..177c514e6 100755 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -266,8 +266,6 @@ void SendCoinsDialog::on_sendButton_clicked() // prepare transaction for getting txFee earlier std::string floData = ui->floData->text().toStdString(); - if (!floData.empty()) - floData = "text:" + floData; WalletModelTransaction currentTransaction(recipients, floData); WalletModel::SendCoinsReturn prepareStatus; From cbaf28e4dd697c5dc1c444ca0cb37914ff1e4402 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Tue, 29 Jan 2019 11:05:49 -0800 Subject: [PATCH 10/13] sign floData for all transactions --- src/script/sign.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index f5b947053..7da6a2d97 100755 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -28,13 +28,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector& vchSig, if (sigversion == SIGVERSION_WITNESS_V0 && !key.IsCompressed()) return false; - int tempHashType = nHashType; - if (sigversion != SIGVERSION_WITNESS_V0) { - // Compatibility with v0.10.4 requires not signing the flo data - // Once v0.10.4 is sufficiently fazed out this should be removed - tempHashType |= SIGHASH_OMIT_FLO_DATA; - } - uint256 hash = SignatureHash(scriptCode, *txTo, nIn, tempHashType, amount, sigversion); + uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); if (!key.Sign(hash, vchSig)) return false; vchSig.push_back((unsigned char)nHashType); From cba88b4c54bf17c97d10d90b03f86156087a3271 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 23 Sep 2017 10:36:23 +0200 Subject: [PATCH 11/13] net: Improve and document SOCKS code Make the SOCKS code more consistent, and document the constants used. --- src/netbase.cpp | 125 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 36 deletions(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index 2a97d5988..0b3014c12 100755 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -185,6 +185,48 @@ struct timeval MillisToTimeval(int64_t nTimeout) return timeout; } +/** SOCKS version */ +enum SOCKSVersion: uint8_t { + SOCKS4 = 0x04, + SOCKS5 = 0x05 +}; + +/** Values defined for METHOD in RFC1928 */ +enum SOCKS5Method: uint8_t { + NOAUTH = 0x00, //! No authentication required + GSSAPI = 0x01, //! GSSAPI + USER_PASS = 0x02, //! Username/password + NO_ACCEPTABLE = 0xff, //! No acceptable methods +}; + +/** Values defined for CMD in RFC1928 */ +enum SOCKS5Command: uint8_t { + CONNECT = 0x01, + BIND = 0x02, + UDP_ASSOCIATE = 0x03 +}; + +/** Values defined for REP in RFC1928 */ +enum SOCKS5Reply: uint8_t { + SUCCEEDED = 0x00, //! Succeeded + GENFAILURE = 0x01, //! General failure + NOTALLOWED = 0x02, //! Connection not allowed by ruleset + NETUNREACHABLE = 0x03, //! Network unreachable + HOSTUNREACHABLE = 0x04, //! Network unreachable + CONNREFUSED = 0x05, //! Connection refused + TTLEXPIRED = 0x06, //! TTL expired + CMDUNSUPPORTED = 0x07, //! Command not supported + ATYPEUNSUPPORTED = 0x08, //! Address type not supported +}; + +/** Values defined for ATYPE in RFC1928 */ +enum SOCKS5Atyp: uint8_t { + IPV4 = 0x01, + DOMAINNAME = 0x03, + IPV6 = 0x04, +}; + +/** Status codes that can be returned by InterruptibleRecv */ enum class IntrRecvError { OK, Timeout, @@ -204,7 +246,7 @@ enum class IntrRecvError { * * @note This function requires that hSocket is in non-blocking mode. */ -static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, const SOCKET& hSocket) +static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket) { int64_t curTime = GetTimeMillis(); int64_t endTime = curTime + timeout; @@ -212,7 +254,7 @@ static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, cons // to break off in case of an interruption. const int64_t maxWait = 1000; while (len > 0 && curTime < endTime) { - ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first + ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first if (ret > 0) { len -= ret; data += ret; @@ -243,24 +285,35 @@ static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, cons return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout; } +/** Credentials for proxy authentication */ struct ProxyCredentials { std::string username; std::string password; }; -std::string Socks5ErrorString(int err) +/** Convert SOCKS5 reply to a an error message */ +std::string Socks5ErrorString(uint8_t err) { switch(err) { - case 0x01: return "general failure"; - case 0x02: return "connection not allowed"; - case 0x03: return "network unreachable"; - case 0x04: return "host unreachable"; - case 0x05: return "connection refused"; - case 0x06: return "TTL expired"; - case 0x07: return "protocol error"; - case 0x08: return "address type not supported"; - default: return "unknown"; + case SOCKS5Reply::GENFAILURE: + return "general failure"; + case SOCKS5Reply::NOTALLOWED: + return "connection not allowed"; + case SOCKS5Reply::NETUNREACHABLE: + return "network unreachable"; + case SOCKS5Reply::HOSTUNREACHABLE: + return "host unreachable"; + case SOCKS5Reply::CONNREFUSED: + return "connection refused"; + case SOCKS5Reply::TTLEXPIRED: + return "TTL expired"; + case SOCKS5Reply::CMDUNSUPPORTED: + return "protocol error"; + case SOCKS5Reply::ATYPEUNSUPPORTED: + return "address type not supported"; + default: + return "unknown"; } } @@ -275,34 +328,34 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials } // Accepted authentication methods std::vector vSocks5Init; - vSocks5Init.push_back(0x05); + vSocks5Init.push_back(SOCKSVersion::SOCKS5); if (auth) { - vSocks5Init.push_back(0x02); // # METHODS - vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED - vSocks5Init.push_back(0x02); // X'02' USERNAME/PASSWORD (RFC1929) + vSocks5Init.push_back(0x02); // Number of methods + vSocks5Init.push_back(SOCKS5Method::NOAUTH); + vSocks5Init.push_back(SOCKS5Method::USER_PASS); } else { - vSocks5Init.push_back(0x01); // # METHODS - vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED + vSocks5Init.push_back(0x01); // Number of methods + vSocks5Init.push_back(SOCKS5Method::NOAUTH); } ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL); if (ret != (ssize_t)vSocks5Init.size()) { CloseSocket(hSocket); return error("Error sending to proxy"); } - char pchRet1[2]; + uint8_t pchRet1[2]; if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port); return false; } - if (pchRet1[0] != 0x05) { + if (pchRet1[0] != SOCKSVersion::SOCKS5) { CloseSocket(hSocket); return error("Proxy failed to initialize"); } - if (pchRet1[1] == 0x02 && auth) { + if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) { // Perform username/password authentication (as described in RFC1929) std::vector vAuth; - vAuth.push_back(0x01); + vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation if (auth->username.size() > 255 || auth->password.size() > 255) return error("Proxy username or password too long"); vAuth.push_back(auth->username.size()); @@ -315,7 +368,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials return error("Error sending authentication to proxy"); } LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); - char pchRetA[2]; + uint8_t pchRetA[2]; if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); return error("Error reading proxy authentication response"); @@ -324,17 +377,17 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Proxy authentication unsuccessful"); } - } else if (pchRet1[1] == 0x00) { + } else if (pchRet1[1] == SOCKS5Method::NOAUTH) { // Perform no authentication } else { CloseSocket(hSocket); return error("Proxy requested wrong authentication method %02x", pchRet1[1]); } std::vector vSocks5; - vSocks5.push_back(0x05); // VER protocol version - vSocks5.push_back(0x01); // CMD CONNECT - vSocks5.push_back(0x00); // RSV Reserved - vSocks5.push_back(0x03); // ATYP DOMAINNAME + vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version + vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT + vSocks5.push_back(0x00); // RSV Reserved must be 0 + vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end()); vSocks5.push_back((port >> 8) & 0xFF); @@ -344,7 +397,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error sending to proxy"); } - char pchRet2[4]; + uint8_t pchRet2[4]; if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); if (recvr == IntrRecvError::Timeout) { @@ -356,26 +409,26 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials return error("Error while reading proxy response"); } } - if (pchRet2[0] != 0x05) { + if (pchRet2[0] != SOCKSVersion::SOCKS5) { CloseSocket(hSocket); return error("Proxy failed to accept request"); } - if (pchRet2[1] != 0x00) { + if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) { // Failures to connect to a peer that are not proxy errors CloseSocket(hSocket); LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1])); return false; } - if (pchRet2[2] != 0x00) { + if (pchRet2[2] != 0x00) { // Reserved field must be 0 CloseSocket(hSocket); return error("Error: malformed proxy response"); } - char pchRet3[256]; + uint8_t pchRet3[256]; switch (pchRet2[3]) { - case 0x01: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break; - case 0x04: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break; - case 0x03: + case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break; + case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break; + case SOCKS5Atyp::DOMAINNAME: { recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); if (recvr != IntrRecvError::OK) { From 72120bff0d535a2b6233cb8ae4687a7479997361 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Mon, 11 Nov 2019 13:28:55 -0800 Subject: [PATCH 12/13] 0.15.2.1 --- configure.ac | 2 +- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 2 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index bd2ffc489..c54341357 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 15) define(_CLIENT_VERSION_REVISION, 2) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_BUILD, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2019) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 5b6becfa5..07ee45750 100644 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -1,5 +1,5 @@ --- -name: "flo-linux-0.15.2.0" +name: "flo-linux-0.15.2.1" enable_cache: true suites: - "trusty" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 7ec964363..f89008089 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -1,5 +1,5 @@ --- -name: "flo-osx-0.15.2.0" +name: "flo-osx-0.15.2.1" enable_cache: true suites: - "trusty" diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index 5adbde3e8..3e80e49e4 100644 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -1,5 +1,5 @@ --- -name: "flo-win-0.15.2.0" +name: "flo-win-0.15.2.1" enable_cache: true suites: - "trusty" From 8708d4bc17b6493f92d972cb3f04305212b44cd1 Mon Sep 17 00:00:00 2001 From: Chris Chrysostom Date: Tue, 4 Feb 2020 17:37:00 -0700 Subject: [PATCH 13/13] Regtest ports (#18) * Ignore IntelliJ files * Regtest RPC Port to 17413 --- .gitignore | 5 +++++ src/chainparamsbase.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 59a463c0f..ca055a86e 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,8 @@ test/cache/* libbitcoinconsensus.pc contrib/devtools/split-debug.sh + +#IntelliJ +*.iml +.idea/ + diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 665ec1008..decf0e7e9 100755 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -58,7 +58,7 @@ class CBaseRegTestParams : public CBaseChainParams public: CBaseRegTestParams() { - nRPCPort = 17313; + nRPCPort = 17413; strDataDir = "regtest"; } };