From ef58867f47026e5c1a22be981b8e01817e8dadf0 Mon Sep 17 00:00:00 2001 From: Skylar Young Date: Thu, 12 Apr 2018 14:17:40 -0700 Subject: [PATCH 1/8] Update Intro UI to have correct chain size & name --- src/qt/intro.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 51aefc494..eadd2141e 100755 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -23,9 +23,9 @@ static const uint64_t GB_BYTES = 1000000000LL; /* Minimum free space (in GB) needed for data directory */ -static const uint64_t BLOCK_CHAIN_SIZE = 20; +static const uint64_t BLOCK_CHAIN_SIZE = 4; /* Minimum free space (in GB) needed for data directory when pruned; Does not include prune target */ -static const uint64_t CHAIN_STATE_SIZE = 3; +static const uint64_t CHAIN_STATE_SIZE = 1; /* Total required space (in GB) depending on user choice (prune, not prune) */ static uint64_t requiredSpace; @@ -127,8 +127,8 @@ Intro::Intro(QWidget *parent) : ui->lblExplanation1->setText(ui->lblExplanation1->text() .arg(tr(PACKAGE_NAME)) .arg(BLOCK_CHAIN_SIZE) - .arg(2009) - .arg(tr("Bitcoin")) + .arg(2013) + .arg(tr("Flo")) ); ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME))); @@ -147,7 +147,7 @@ Intro::Intro(QWidget *parent) : } requiredSpace += CHAIN_STATE_SIZE; ui->sizeWarningLabel->setText( - tr("%1 will download and store a copy of the Bitcoin block chain.").arg(tr(PACKAGE_NAME)) + " " + + tr("%1 will download and store a copy of the Flo block chain.").arg(tr(PACKAGE_NAME)) + " " + storageRequiresMsg.arg(requiredSpace) + " " + tr("The wallet will also be stored in this directory.") ); From 2b919e57970b66d69251b5c58e7a4a337ed46292 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Fri, 27 Apr 2018 16:17:34 -0700 Subject: [PATCH 2/8] Fix TargetTimespan calculation --- src/consensus/params.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index 4acedacab..fec33bfbc 100755 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -70,9 +70,9 @@ struct Params { return nTargetTimespan_Version1; // V2 if (height < nHeight_Difficulty_Version3) - return nInterval_Version2 * nPowTargetSpacing; + return nAveragingInterval_Version2 * nPowTargetSpacing; // V3 - return nInterval_Version3 * nPowTargetSpacing; + return nAveragingInterval_Version3 * nPowTargetSpacing; } int64_t DifficultyAdjustmentInterval(int height) const { From e17497e0948f6360a76c31de1e794cb89e10ff72 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Fri, 27 Apr 2018 16:18:42 -0700 Subject: [PATCH 3/8] Use function to obtain TargetTimespan --- src/pow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pow.cpp b/src/pow.cpp index 84a64c757..2a92e657e 100755 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -85,7 +85,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF if (fShift) bnNew >>= 1; bnNew *= nActualTimespan; - bnNew /= params.AveragingInterval(pindexLast->nHeight+1) * params.nPowTargetSpacing; + bnNew /= params.TargetTimespan(pindexLast->nHeight+1); if (fShift) bnNew <<= 1; From 4d3b091eb269a6cc275aba669b86079639dd9676 Mon Sep 17 00:00:00 2001 From: Jeremiah Buddenhagen Date: Mon, 1 Oct 2018 12:12:15 -0700 Subject: [PATCH 4/8] 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 5/8] 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 6/8] 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 7/8] 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 8/8] 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])