Minimal BIP9 implementation #7575

pull sipa wants to merge 6 commits into bitcoin:master from sipa:bip9 changing 17 files +864 −20
  1. sipa commented at 10:18 pm on February 21, 2016: member

    This is an alternative to #6816 and #7566, implementing BIP9 with minimal code changes, including mining logic, softfork warning logic, and some unit tests.

    It adds support for a begin time before version bits are counted, which is not in BIP9 currently, though it is compatible.

    The last commit demonstrates how to add a simple softfork.

  2. btcdrak commented at 2:30 am on February 22, 2016: contributor
    Could you add deployment status to the getblockchaininfo RPC?
  3. dcousens commented at 3:51 am on February 22, 2016: contributor

    @sipa any reason not to just extend #7566?

    once-over utACK 50278bb, concept ACK

  4. btcdrak commented at 4:13 am on February 22, 2016: contributor
    Concept ACK, I prefer this BIP9 implementation.
  5. sipa commented at 4:19 am on February 22, 2016: member
    @dcousens I wrote most of this before I saw #7566, which would need some refactoring anyway to support the warning logic. I did use the params structure from there.
  6. jonasschnelli added the label Consensus on Feb 22, 2016
  7. jonasschnelli commented at 4:18 pm on February 22, 2016: contributor
    There are some versionbits_test.cpp formatting/syntax issues (https://travis-ci.org/bitcoin/bitcoin/jobs/110833452#L1736)
  8. sipa force-pushed on Feb 24, 2016
  9. sipa commented at 9:43 pm on February 24, 2016: member
    Fixed tests.
  10. in src/main.cpp: in 99f66325e8 outdated
    2093+        if (softforkcheck[i]->IsSetFor(pindexPrev, params)) {
    2094+            nVersion |= softforkcheck[i]->Mask(params);
    2095+        }
    2096+    }
    2097+
    2098+    if (nVersion == 0) {
    


    jtimon commented at 7:53 pm on February 25, 2016:
    Why not simply start using the versionbit prefix without voting for any concrete bit instead?

    sipa commented at 8:02 pm on February 25, 2016:

    Why not simply start using the versionbit prefix without voting for any concrete bit instead?

    That would mean that versionbits on itself is a change, and lack of adoption of versionbits by miners would then cause the warning logic to trigger on new nodes.

    Using this logc here, versionbits gets rolled out simultaneously with the first fork that uses it.


    jtimon commented at 9:23 pm on February 25, 2016:

    I mean, if we are going to wait to deploy the first SF to merge it, I think it makes even more sense that we never return Consensus::VERSIONBITS_LAST_OLD_BLOCK_VERSION here.

    That would mean that versionbits on itself is a change, and lack of adoption of versionbits by miners would then cause the warning logic to trigger on new nodes.

    Just like changing the version to 8 without doing anything else would be. But it doesn’t affect functionality. The new nodes would only get warnings if the miners, apart from adopting this change were adopting or implementing other change to vote on concrete bits (if they only set nVersion to Consensus::VERSIONBITS_TOP_BITS), no warnings should be raised (unless an unknown SF has been deployed using versionbits, in which case is good that they get the warnings).


    sipa commented at 9:42 pm on February 25, 2016:

    Assume the start date for the first bip9 softfork is april 1st, but we release code with bip9 and that softfork on march 1st.

    That means that it’s likely that during march no new-style nVersion will be mined. That also means that anyone who does run upgraded code will get warnings, because the nVersion they expect (0x20000000) differs from the one they see (4).


    jtimon commented at 10:04 pm on February 25, 2016:

    Ok, I get it, it’s the old nodes seeing the “empty versionbits” version which would get (unnecessarily?) be told to upgrade and it doesn’t matter whether we introduce a SF with BIP9 or not because the start date will be after the miners start using the new code to produce their new versions.

    But I think I still disagree, though. If in march 15th 95% of the miners are ready to deploy a softfork scheduled for april 1st, I believe old nodes should actually receive the upgrade warning already, even if the message is not accurate.

    EDIT: anyway, this disagreement is minor in the sense that it cannot greatly affect the implementation, the difference will be about 3-lines. So don’t hurry to answer this.

    EDIT: nah, 95% of miner will use BIP9 later, never mind, question answered.

  11. in src/main.cpp: in 99f66325e8 outdated
    2497@@ -2451,20 +2498,14 @@ void static UpdateTip(CBlockIndex *pindexNew) {
    2498     static bool fWarned = false;
    2499     if (!IsInitialBlockDownload() && !fWarned)
    


    jtimon commented at 7:55 pm on February 25, 2016:
    “Unrelated” question: I know this is not changed in this PR, but why don’t we want these warnings on initial block download? Would it be a problem to make these checks in ConnectBlock() rather than UpdateTip() ?
  12. in src/main.cpp: in 99f66325e8 outdated
    2512-        {
    2513+        if (warningcheck.IsLockedIn(pindex, chainParams.GetConsensus())) {
    2514             // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
    2515-            strMiscWarning = _("Warning: This version is obsolete; upgrade required!");
    2516+            if (warningcheck.IsActiveFor(pindex, chainParams.GetConsensus())) {
    2517+                strMiscWarning = _("Warning: unknown softfork has activated");
    


    jtimon commented at 7:56 pm on February 25, 2016:
    Minor nit: Is it really worth it to notify this twice (once when is locked in and 2016 blocks later when it’s activated)?

    sipa commented at 8:00 pm on February 25, 2016:
    Well, one is before you’re forked off and the other is after. The warning texts here could certainly be more descriptive.

    jtimon commented at 9:16 pm on February 25, 2016:
    But unless there’s a reorg, nothing is going to stop the locked in deployment from being activated. I guess more messages don’t hurt, even if we need to repeat the check (states are cached anyway).
  13. in src/consensus/versionbits.h: in 99f66325e8 outdated
    42+
    43+private:
    44+    // A map that gives the state for blocks whose height is a multiple of Period().
    45+    // The map is indexed by the block's parent, however, so all keys in the map
    46+    // will either be NULL or a block with (height + 1) % Period() == 0.
    47+    std::map<const CBlockIndex*, State> cache;
    


    jtimon commented at 8:31 pm on February 25, 2016:

    This is the main difference between your implementation and mine. You have a separate Cache for each deployment while I have a single cache with containing the states of all the deployments. While mine should be more efficient (at least storage-wise), your code is more reusable (as shown in the way you implement the warnings checks). Another goal for caching the states together is to simplify things in case libconsensus exposes (C API) the cache in the future to support concurrent calls.

    EDIT, the biggest difference is my CVersionBitsState::usedBitsMaskCache see the comment in the state machine.

  14. in src/consensus/versionbits.h: in 99f66325e8 outdated
    29+    virtual int Period(const Params& params) =0;
    30+    virtual int Threshold(const Params& params) =0;
    31+
    32+    enum State {
    33+        UNDEFINED,
    34+        DEFINED,
    


    jtimon commented at 8:33 pm on February 25, 2016:
    Bike-shedding: I’m doing s/UNDEFINED/DEFINED s/DEFINED/STARTED isntead, which I think it’s more clear: If it’s in the chainparams is defined, it just hasn’t started yet. Undefined/unkown deployments are those which you don’t have in your chainparams.

    sipa commented at 8:36 pm on February 25, 2016:
    Makes sense.

    sipa commented at 3:26 am on March 1, 2016:
  15. in src/consensus/versionbits.cpp: in 99f66325e8 outdated
    49+        switch (state) {
    50+            case UNDEFINED: {
    51+                if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
    52+                    stateNext = FAILED;
    53+                } else if (pindexPrev->GetMedianTimePast() >= nTimeDefined) {
    54+                    stateNext = DEFINED;
    


    jtimon commented at 10:52 pm on February 25, 2016:
    Important concern: Shouldn’t this check that the same bit is not currently being used by other deployment defined in chainparams for the same bit (and already started or locked in) before advancing to the next state?
  16. in src/consensus/versionbits.cpp: in 99f66325e8 outdated
    46+        pindexPrev = vToCompute.back();
    47+        vToCompute.pop_back();
    48+
    49+        switch (state) {
    50+            case UNDEFINED: {
    51+                if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
    


    jtimon commented at 10:58 pm on February 25, 2016:
    This check is redundant with the similar one in the DEFINED state (assuming the check is done before counting upgrade confirmations). You could also remove the break, so that a deployment changing from UNDEFINED to DEFINED has the chance of moving to FAILED or LOCKED_IN in the same round.

    sipa commented at 0:22 am on February 26, 2016:
    I think the semantics are simpler without the possibility of going from undefined to lockedin in one transition.

    jtimon commented at 4:12 pm on February 26, 2016:
    fair enough, we’re talking about saving 3-4 lines to libconsensus or leave them as self-documentation. If I forget to copy you on this, please, remind me.
  17. in src/main.cpp: in 99f66325e8 outdated
    2080@@ -2080,6 +2081,47 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
    2081     }
    2082 }
    2083 
    2084+Consensus::VersionBitsConditionChecker checkCSV(Consensus::DEPLOYMENT_CSV);
    


    jtimon commented at 11:34 pm on February 25, 2016:

    These variables could be both static and be in consensus/versionbits.cpp instead of main.cpp by moving ComputeBlockVersion() to versionbits as well (of course, without cs_main).

    WarningBitsConditionChecker could be encapsulated behind a function there too. In a very far future in which Bitcoin Core only uses libconsensus through its C API, that GetVersionBitsWarnings(const CBlockIndex* pindexPrev, const Consensus::Params&) function seems much closer from being “exposable” in libconsensus than class Consensus::AbstractThresholdConditionChecker.

    I know that ComputeBlockVersion() and GetVersionBitsWarnings() are not strictly consensus code, but they heavily depend on consensus code, and I think it would be a wasted opportunity not to have this functionality as encapsulated as possible from birth.


    sipa commented at 0:20 am on February 26, 2016:
    The reason I didn’t put them in versionbits is exactly because the lock is in main. Post c++11 we can move locks to libconsensus, and the versionbits cache can have its own lock.

    jtimon commented at 4:25 pm on February 26, 2016:

    I don’t think we want locks in libconsensus, not even post c++11. This reminds me of a previous conversation we had about concurrency and the cache. It seems a renounced to supporting concurrent calls without locks in libconsensus for the wrong reason. When you previously said " no need to have locks in the internal cache, the caller can get cs_main", it seems you meant something different than what I understood. I will go back to having a C API interface for the cache.

    In this PR, can’t the caller of GetFlags (), ComputeBlockVersion() and GetVersionBitsWarnings() take the lock (assuming you move this code behind those 3 functions to encapsulate the static vars)?


    sipa commented at 3:34 am on March 1, 2016:
    I’ll try another implementation that does that. Separating the cache and the logic probably makes sense.
  18. in src/main.cpp: in 99f66325e8 outdated
    2217@@ -2176,6 +2218,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
    2218         flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
    2219     }
    2220 
    2221+    // Start enforcing CHECKSEQUENCEVERIFY using versionbits logic.
    


    jtimon commented at 0:23 am on February 26, 2016:

    please, please, please libconsensus refactor nit:

    Could you replace these lines with

    0flags |= Consensus::GetFlags(pindex, chainparams.GetConsensus());
    

    ? (is it pindex->pprev or just pindex here?)

    Then the function defined in consensus/versionbits.cpp can be extended for new deployments while avoiding new consensus code in main.

    That implies, again, that checkCSV (and thus softforkcheck) would need to move to consensus/versionbits.cpp.


    sdaftuar commented at 6:03 pm on March 3, 2016:
    I don’t have a strong opinion here, but I don’t know that it really makes sense to call a generic GetFlags() function, as I believe we will need to have a separate one of those to deploy BIP68 (which doesn’t use a script flags variable, but uses a locktimeflags variable instead)

    jtimon commented at 0:32 am on March 4, 2016:
    I meant by unifying the consensus flags (currently only script and nSequence_and_nLockTime), see https://github.com/jtimon/bitcoin/commit/b77f1f21eda2329d99d7f2c3242be228db58b131 . EDIT: Anyway, if the last commit is an example that will be merged indepdently, this doesn’t apply here.
  19. sipa force-pushed on Mar 3, 2016
  20. sipa commented at 4:51 am on March 3, 2016: member

    Updated to correspond to latest BIP9 (see https://github.com/bitcoin/bips/pull/344, https://github.com/bitcoin/bips/pull/345, https://github.com/bitcoin/bips/pull/346), and fixed the tests.

    I also have an alternate version that factors out the cache, see https://github.com/sipa/bitcoin/commit/218d2fdcbfb207ed75f4f5a6fc7a1b5de6d791b8).

  21. sipa force-pushed on Mar 3, 2016
  22. sipa commented at 11:49 pm on March 3, 2016: member
    1. Moved the versionbits logic out of consensus, and make it not depend on it is
    2. Added (very basic) reporting of BIP9 deployment status through RPC
    3. Switched the window size from 2016 to 144 for regtest
    4. Factored the cache out of the versionbits logic classes

    Should be ready for review.

  23. jtimon commented at 0:50 am on March 4, 2016: contributor
    utACK 7662816 EDIT: To be clear, I didn’t meant to rename consensus/versionbits.o to versionbits.o, I was just talking about the “consensus package” in the makefile (because otherwise the whole package would depend on chain.o and its dependencies). I’m sorry for the misunderstanding and I understand if you don’t want to change it back again.
  24. in src/main.cpp: in 766281655b outdated
    2522+        if (state == THRESHOLD_ACTIVE || THRESHOLD_LOCKED_IN) {
    2523+            if (state == THRESHOLD_ACTIVE) {
    2524+                strMiscWarning = _("Warning: unknown softfork has activated");
    2525+                CAlert::Notify(strMiscWarning, true);
    2526+            } else {
    2527+                LogPrintf("Warning: An unknown softfork is about to activate");
    


    btcdrak commented at 6:19 am on March 4, 2016:
    missing a trailing \n
  25. sipa force-pushed on Mar 4, 2016
  26. sipa commented at 8:10 pm on March 4, 2016: member

    Fixed a few bugs:

    • typo in the warning logic which made it trigger all the time
    • newline at the end of unknown softfork warning log message
    • bip9_softforks was not being added to the getblockchaininfo output
  27. in src/consensus/params.h: in 8cbed80c31 outdated
    42@@ -22,6 +43,14 @@ struct Params {
    43     /** Block height and hash at which BIP34 becomes active */
    44     int BIP34Height;
    45     uint256 BIP34Hash;
    46+    /**
    47+     * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period,
    48+     * (nPowTargetTimespan / nPowTargetSpacing) wich is also used for BIP9 deployments.
    


    paveljanik commented at 8:17 pm on March 4, 2016:
    wich -> which

    sipa commented at 10:19 pm on March 4, 2016:
    Fixed.
  28. in src/test/versionbits_tests.cpp: in 8cbed80c31 outdated
    86+    }
    87+
    88+    VersionBitsTester& TestStarted() {
    89+        for (int i = 0; i < CHECKERS; i++) {
    90+            if ((insecure_rand() & ((1 << i) - 1)) == 0) {
    91+                BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for DEFINED", num));
    


    sdaftuar commented at 9:01 pm on March 4, 2016:
    should be strprintf("Test %i for STARTED", num)

    sipa commented at 10:19 pm on March 4, 2016:
    Fixed.
  29. in src/test/versionbits_tests.cpp: in 8cbed80c31 outdated
    129+BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup)
    130+
    131+BOOST_AUTO_TEST_CASE(versionbits_test)
    132+{
    133+    for (int i = 0; i < 64; i++) {
    134+        // UNDEFINED -> FAILED
    


    sdaftuar commented at 9:10 pm on March 4, 2016:
    Perhaps this comment and the ones below should be updated? UNDEFINED is not a state.

    sipa commented at 10:19 pm on March 4, 2016:
    Fixed.
  30. sipa force-pushed on Mar 4, 2016
  31. btcdrak commented at 10:19 pm on March 4, 2016: contributor
    Would it be possible to emit debug logs for the softfork state changes?
  32. sipa commented at 0:12 am on March 5, 2016: member
    @btcdrak That would require breaking some layering, as the consensus logic never sees the transitions, and the threshold logic is used for both consensus and warnings.
  33. btcdrak commented at 0:13 am on March 5, 2016: contributor
    @sipa no problem, I drop the idea.
  34. btcdrak commented at 0:24 am on March 5, 2016: contributor

    Tested ACK a7f15a6

    Part of my tests involved porting the softforks activation from #7561 and converting the RPC tests to check both enforcement and RPC bip9 status. Work done in https://github.com/bitcoin/bitcoin/compare/master...btcdrak:vb_68_112_113_1

  35. in src/main.cpp: in cf71c5360a outdated
    2115+    int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
    2116+    int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; }
    2117+
    2118+    bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
    2119+    {
    2120+        return (pindex->nVersion & ~ComputeBlockVersion(pindex->pprev, params)) != 0;
    


    sdaftuar commented at 6:00 pm on March 5, 2016:

    Won’t this have potential false alerts, if let’s say half the blocks in a period are signaling some unknown bit i, while the other half are signaling some other unknown bit j?

    Anyway it occurred to me that it might be nice to record which bits are being set that are unknown and write that to the debug log when we warn an unknown softfork is about to activate (as a useful debugging/investigation aid), but I can see that is a little tricky.


    sipa commented at 6:03 pm on March 5, 2016:
    That’s quite doable actually: have a ‘warning’ tracker per bit.

    sdaftuar commented at 2:04 pm on March 7, 2016:

    Oh it also occurs to me that we probably shouldn’t count a block towards the warning unless its top bits match the 001 versionbits prefix? Otherwise we could see warnings if we deploy versionbits+some soft fork, but miners are slow to pick it up and continue using old version numbers.

    Anyway I like the idea of a warning tracker per bit…

  36. in src/main.cpp: in cf71c5360a outdated
    2080@@ -2080,6 +2081,50 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
    2081     }
    2082 }
    2083 
    2084+// Protected by cs_main
    2085+static VersionBitsCache versionbitscache;
    2086+
    2087+int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
    


    sdaftuar commented at 6:16 pm on March 5, 2016:

    I think it’d be nice if we had test coverage for this function. I believe that as it stands, if this code were busted, then I’m not sure any tests would necessarily fail?

    So far the best idea I have is that when we deploy a new soft fork, we write a unit test that exercises this function and verifies the right bit will be set at the right time (using a fake mainnet chain like the one you built in the versionbits unit test).

    I think we should also have regtest RPC tests which exercise proposed soft forks as well, but I can’t think of any way to write such tests to adequately test mainnet parameters…


    sipa commented at 6:23 pm on March 5, 2016:
    Perhaps it would be useful to have a ’test’ softfork that is disabled (end time before genesis, for example) everywhere but regtest, and enables some very easy to test condition (e.g. coinbase must have exactly one output)?

    jtimon commented at 2:44 pm on March 6, 2016:
    A testing deployment sounds like a good idea.

    sdaftuar commented at 3:54 pm on March 11, 2016:

    @sipa I tried implementing a unit test for ComputeBlockVersion() using a dummy deployment; not sure adding a dummy softfork for testing is something we want to do, but if you’re interested the code for that is here:

    https://github.com/sdaftuar/bitcoin/commit/b8ec634651fbc5a41afc47a768de4357983d3b4f

    If you think this is worth including in some form, feel free to grab it, or I am happy to separately PR this unit test later.


    sipa commented at 3:51 am on March 15, 2016:
    Cherry-picked.
  37. in src/main.cpp: in cf71c5360a outdated
    2096+        }
    2097+    }
    2098+
    2099+    if (nVersion == 0) {
    2100+        // Pre-versionbits
    2101+        return VERSIONBITS_LAST_OLD_BLOCK_VERSION;
    


    morcos commented at 3:11 pm on March 8, 2016:
    I’m not really sure the intention here. This will also happen after version bits is rolled out but between any active soft fork deployments. Is there a reason not to just always | VERSIONBITS_TOP_BITS and forget about version 4 blocks.
  38. morcos commented at 10:07 pm on March 8, 2016: member

    @sipa see https://github.com/sipa/bitcoin/pull/58 for suggestions on how to rework the warning logic. It separates it into two different things.

    • Something similar to the old warnings which just runs in the steady state and lets you know when blocks are happening that aren’t what you expect and triggers an alert if this is over 50%. This could apply to unknown BIP 9 softforks or any other change to the use of nVersion.
    • Something actually detects activation of unknown BIP 9 soft forks. This runs even during IBD. I think this is important so old code doesn’t miss the transient signaling of a new soft fork if it happened to not be online, or so that if someone accidentally downloads old code and syncs it, they can detect they are missing something.
  39. gmaxwell commented at 10:21 pm on March 8, 2016: contributor
    I think we want tracking during IBD for another reason: I think we’ll want to disable mining (return error on GBT) after an unknown BIP9 fork locks in unless explicitly overridden (ignorebip9fork=height:bit in config); otherwise there is a rule-reversion-risk, where long after a fork locks some non-trivial portion of hashpower happens to downgrade to older code that doesn’t support the existing locked forks.
  40. in src/test/versionbits_tests.cpp: in cf71c5360a outdated
    178+                           .Mine(3999, TestTime(30001), 0).TestLockedIn()
    179+                           .Mine(4000, TestTime(30002), 0).TestActive()
    180+                           .Mine(14333, TestTime(30003), 0).TestActive()
    181+                           .Mine(24000, TestTime(40000), 0).TestActive();
    182+    }
    183+}
    


    sdaftuar commented at 2:49 pm on March 10, 2016:

    I wrote up a couple additional tests to try sanity checking the mainnet deployments:

     0diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
     1index 9de8461..c384f92 100644
     2--- a/src/test/versionbits_tests.cpp
     3+++ b/src/test/versionbits_tests.cpp
     4@@ -6,6 +6,7 @@
     5 #include "random.h"
     6 #include "versionbits.h"
     7 #include "test/test_bitcoin.h"
     8+#include "chainparams.h"
     9
    10 #include <boost/test/unit_test.hpp>
    11
    12@@ -180,6 +181,28 @@ BOOST_AUTO_TEST_CASE(versionbits_test)
    13                            .Mine(14333, TestTime(30003), 0).TestActive()
    14                            .Mine(24000, TestTime(40000), 0).TestActive();
    15     }
    16+
    17+    // Sanity checks of version bit deployments
    18+    const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
    19+    for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
    20+        uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i);
    21+        // Make sure that no deployment tries to set an invalid bit.
    22+        BOOST_CHECK(bitmask < (uint32_t)VERSIONBITS_TOP_BITS);
    23+
    24+        // Verify that the deployment windows of different deployment using the
    25+        // same bit are disjoint.
    26+        // This test may need modification at such time as a new deployment
    27+        // is proposed that reuses the bit of an activated soft fork, before the
    28+        // end time of that soft fork.  (Alternatively, the end time of that
    29+        // activated soft fork could be later changed to be earlier to avoid
    30+        // overlap.)
    31+        for (int j=i+1; j<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; j++) {
    32+            if (VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)j) == bitmask) {
    33+                BOOST_CHECK(mainnetParams.vDeployments[j].nStartTime > mainnetParams.vDeployments[i].nTimeout ||
    34+                        mainnetParams.vDeployments[i].nStartTime > mainnetParams.vDeployments[j].nTimeout);
    35+            }
    36+        }
    37+    }
    38 }
    39
    40 BOOST_AUTO_TEST_SUITE_END()
    

    Perhaps worth including something like that here?


    sipa commented at 3:42 am on March 15, 2016:
    Sure! Make a commit somewhere?

    sdaftuar commented at 1:05 pm on March 15, 2016:

    https://github.com/sdaftuar/bitcoin/commit/471d10583b197556ff7d9ae4c30a258a8f3061ff

    Actually, I rebased this, with a minor change to use VERSIONBITS_TOP_MASK rather than VERSIONBITS_TOP_BITS when checking the bitmask: https://github.com/sdaftuar/bitcoin/commit/6b7ec42549d75292719ca7f77a087c4f471de92f

    Edit: Ok I think this is what I intend: https://github.com/sdaftuar/bitcoin/commit/0e492acd62fa792f23e5400e810c7b8b1b13d7b9

  41. in src/main.cpp: in cf71c5360a outdated
    2080@@ -2080,6 +2081,50 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
    2081     }
    2082 }
    2083 
    2084+// Protected by cs_main
    2085+static VersionBitsCache versionbitscache;
    


    sdaftuar commented at 2:52 pm on March 10, 2016:
    I think we should probably clear out these caches in UnloadBlockIndex(). In particular, I think that if we don’t, then the miner_tests will pollute the versionbitscache with cached information that might be invalid in later tests (because the CBlockIndex pointers could be reused, potentially resulting in incorrect state calculations).

    sipa commented at 3:38 am on March 15, 2016:
    Done.
  42. sipa force-pushed on Mar 15, 2016
  43. sipa commented at 3:42 am on March 15, 2016: member
    @gmaxwell The code now will only do checks after IBD, but it will detect unknown softforks that activated in the past.
  44. btcdrak commented at 8:55 am on March 15, 2016: contributor
    @sipa Now that there is a “TESTDUMMY” softfork, can I suggest removing Add CHECKSEQUENCEVERIFY softfork through BIP9 sipa@2b4bb57 and we add it through #7648 separately (which has been rebase to this branch now).
  45. BIP9 Implementation
    Inspired by former implementations by Eric Lombrozo and Rusty Russell, and
    based on code by Jorge Timon.
    6851107b3a
  46. Versionbits tests 732e774c06
  47. Softfork status report in RPC d23f6c6a0d
  48. Add testing of ComputeBlockVersion 532cbb22b5
  49. Test versionbits deployments 7870debceb
  50. in src/main.cpp: in 293e928bf3 outdated
    2534+            LogPrintf("%s: %d of last 100 blocks have unexpected version\n", __func__, nUpgraded);
    2535+        if (nUpgraded > 100/2 && !fWarned)
    2536         {
    2537             // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
    2538-            strMiscWarning = _("Warning: This version is obsolete; upgrade required!");
    2539+            strMiscWarning = _("Warning: unknown block versions being mined on the network!");
    


    morcos commented at 12:56 pm on March 15, 2016:
    I’d prefer if this warning was a little bit stronger. Perhaps you could change it to: "Warning: Unknown block versions being mined! It's possible unknown rules are in effect" or something to that effect?
  51. in src/main.cpp: in 293e928bf3 outdated
    2514+                if (state == THRESHOLD_ACTIVE) {
    2515+                    strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
    2516+                    CAlert::Notify(strMiscWarning, true);
    2517+                    fWarned = true;
    2518+                } else {
    2519+                    LogPrintf("%s: unknown new rules are about to activate (versionbit %i)\n", bit);
    


    sdaftuar commented at 1:32 pm on March 15, 2016:
    Is this missing a __func__?
  52. in src/main.cpp: in 293e928bf3 outdated
    2518+                } else {
    2519+                    LogPrintf("%s: unknown new rules are about to activate (versionbit %i)\n", bit);
    2520+                }
    2521+            }
    2522+        }
    2523+        int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus());
    


    sdaftuar commented at 1:42 pm on March 15, 2016:

    (Sorry if this is a repost, I think github ate my first attempt to comment)

    I think we should move this line into the for loop below; otherwise we’d generate a warning after a known soft-fork activates.

  53. sipa force-pushed on Mar 15, 2016
  54. sipa commented at 3:55 pm on March 15, 2016: member
    All comments addressed, I think.
  55. btcdrak commented at 6:05 pm on March 15, 2016: contributor
    Tested ACK 532cbb2
  56. sdaftuar commented at 8:10 pm on March 15, 2016: member

    ACK

    If anyone is interested I also tested the warning logic with an RPC test (https://github.com/sdaftuar/bitcoin/commit/4c2e8ba2282e0948aa8680ab5e8283e5f8ef12f5)

  57. RPC test for BIP9 warning logic 8c74cedef5
  58. sipa commented at 2:10 pm on March 16, 2016: member
    Included @sdaftuar’s warning logic RPC test.
  59. in src/rpc/blockchain.cpp: in 8c74cedef5
    603@@ -604,6 +604,20 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
    604     return rv;
    605 }
    606 
    607+static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
    


    jtimon commented at 3:20 pm on March 16, 2016:
    Shouldn’t this loop throught all the deployments defined in Consensus::Params and be called from somewhere? Style: why is not indented?

    sipa commented at 3:24 pm on March 16, 2016:

    It’s called once for every deployment below, similar to how SoftForkMajorityDesc is. There just are no deployments just yet.

    Making this function iterate through all deployments would require putting knowledge of the names of all deployments in the consensus params, and would make it inevitable that the test deployment is listed.


    sipa commented at 3:28 pm on March 16, 2016:
    Style: what do you mean by not indented?

    jtimon commented at 3:29 pm on March 16, 2016:

    Mhmm, I can only find one instance of the string “BIP9SoftForkDesc” in the changes.

    re itarate with knowledge of the names, what’s wrong with

    0for (int i = 0; i < MAX_VERSION_BITS_DEPLOYMENTS; ++i)
    

    ?


    sipa commented at 3:36 pm on March 16, 2016:

    You don’t know what string name to give to the Object entry inside “bip9_softforks”.

    Yes you can’t find any calls to it yet, because there are no BIP9 softforks defined. Future deployments using BIP9 are supposed to be added below, just like ISM softforks were supposed to be added below to “softforks”.


    jtimon commented at 3:39 pm on March 16, 2016:

    Style, oh, never mind: https://github.com/bitcoin/bitcoin/blob/master/src/.clang-format#L27

    I see, I didn’t thought about the name.

  60. jtimon commented at 3:26 pm on March 16, 2016: contributor
    re-utACK 8c74cedef53ab791ed333f25794f8b9d2e9f51aa modulo last nit.
  61. morcos commented at 7:06 pm on March 16, 2016: member
    Code review ACK
  62. btcdrak commented at 8:18 pm on March 16, 2016: contributor
    Tested ACK 8c74ced
  63. morcos commented at 9:14 pm on March 16, 2016: member

    @sipa I realize you might still be changing this, but in the event that you’re not, I backported it to 0.11 along with the soft fork for BIP 68,112,113 here: https://github.com/bitcoin/bitcoin/compare/0.11...morcos:backportBIP9SoftFork?expand=1

    The RPC tests are annoying to backport, so I left 2 of them out, but tested using the recent RPC test bip68-112-113.py against the 0.11 binary.

  64. sipa commented at 11:35 pm on March 16, 2016: member
    @morcos I’m fine with the current state.
  65. jonasschnelli commented at 7:07 pm on March 17, 2016: contributor
    utACK
  66. laanwj merged this on Mar 18, 2016
  67. laanwj closed this on Mar 18, 2016

  68. laanwj referenced this in commit 73b7eb501e on Mar 18, 2016
  69. in src/consensus/params.h: in 8c74cedef5
     6@@ -7,8 +7,29 @@
     7 #define BITCOIN_CONSENSUS_PARAMS_H
     8 
     9 #include "uint256.h"
    10+#include <map>
    11+#include <string>
    12 
    13 namespace Consensus {
    14+
    15+enum DeploymentPos
    


    petertodd commented at 2:41 pm on March 24, 2016:

    Why is this called “DeploymentPos”? It’s not a bit position; the actual bit positions have another layer of indirection in the BIP9Deployment structure: https://github.com/sipa/bitcoin/blob/8c74cedef53ab791ed333f25794f8b9d2e9f51aa/src/consensus/params.h#L26

    We should change this to DeploymentId


    laanwj commented at 4:02 pm on March 24, 2016:
    ‘position’ is a very ambigious, yes. It’s almost never a good choice. Made a similar comment here on another pull: #7541 (review) Agree ‘Id’ seems be a better fit here.

    petertodd commented at 8:04 pm on March 24, 2016:
    Alright, I’ll do a pull-req to fix that - but next week after the long weekend!

    jtimon commented at 8:20 am on March 26, 2016:
    It is the position in Consensus::Params::vDeployments. Id could have been another option, but O disagree there’s anything to fix here. Seems too late for bike-shedding this.

    MarcoFalke commented at 11:41 am on March 26, 2016:
    Adding a comment for doxygen would also help if the purpose is not immediately clear from the code alone.

    laanwj commented at 1:03 pm on March 26, 2016:
    I had the same confusion as @petertodd when initially reading the code, so for new developers it must be worse. I do think at least a comment should be added.

    jtimon commented at 1:20 pm on March 26, 2016:
    ACK on adding documentation.
  70. zkbot referenced this in commit e6850571dd on Feb 7, 2018
  71. DrahtBot locked this on Aug 16, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-09-29 01:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me