Refactor versionbits deployments to avoid potential uninitialized variables #21401

pull achow101 wants to merge 16 commits into bitcoin:master from achow101:encap-vbits-params changing 17 files +555 −340
  1. achow101 commented at 11:44 PM on March 9, 2021: member

    Currently versionbits deployments are stored in a simple C array in Params. Setting the actual values needs to be done externally. Since the memory is allocated and initialized when Params is initialized, it is possible to have a deployment with uninitialized (or otherwise garbage and invalid) values set for its parameters if something is forgotten when they are being set.

    Instead of this two step approach (create deployment object, then set its members), I think it is better to have a constructor where those parameters are passed in and set when the deployment is initialized. This PR does that. In order for this to work though, vDeployments cannot be a simple C array. It is instead changed to be a std::map<DeploymentPos, VBitsDeployment>. This maps the deployment enum to the VBitsDeployment object itself; this is essentially how we were using vDeployments previously. Additionally, by also changing VersionBitsDeploymentInfo to a map as well, we are able to remove MAX_VERSION_BITS_DEPLOYMENT and all of the places where we were iterating the deployments no longer need to cast an int to DeploymentPos.

    An additional concern is that the members of VBitsDeployment are not const and could thus be accidentally changed during runtime. To prevent this, this PR makes all members of VBitsDeployment const.

    Lastly, to make VBitsDeployment actually fully describe a deployment, this PR moves the number of blocks in a period into the struct. In order to ensure that this variable matches up with the retarget period, a unit test is added.

    Built on top of #21392 and #21380 for the refactors and other changes they make to VBitsDeployment.

  2. in src/chainparams.cpp:330 in c2549d0326 outdated
     337 | -        consensus.m_deployments[Consensus::DEPLOYMENT_TAPROOT].threshold = 1916; // 95% of 2016
     338 | -        consensus.m_deployments[Consensus::DEPLOYMENT_TAPROOT].m_min_activation_height = 0; // No minimum activation height
     339 | +        consensus.m_deployments.emplace(Consensus::DEPLOYMENT_TESTDUMMY, Consensus::VBitsDeployment(28, false /* active */));
     340 | +
     341 | +        // Deployment of Taproot (BIPs 340-342)
     342 | +        consensus.m_deployments.emplace(Consensus::DEPLOYMENT_TAPROOT, Consensus::VBitsDeployment(2, true /* active */));
    


    ajtowns commented at 12:17 AM on March 10, 2021:

    We usually do these comments as /* active= */ false I think

  3. ajtowns commented at 12:56 AM on March 10, 2021: contributor

    globalChainParams / Params() is already const during runtime, so that should already prevent changing any of the fields in vDeployments. Ah, a different approach that might be worth considering:

    class CChainParams
    {
    protected:
        CChainParams(const Consensus::Params& cons) : consensus{cons} { } // or std::move, whatever
    public:
        const Consensus::Params consensus;
        ...
    };
    
    class CRegTestParams : public CChainParams
    {
    public:
        CRegTestParams(const ArgsManager& args) : CChainParams{getConsensus(args)}
        { ... }
        
        static Consensus::Params getConsensus(const ArgsManager& args)
        {
            Consensus::Params consensus{};
            consensus.foo = bar; ...
            // parse -segwitheight and -vbparams here as well
        }
    };
    

    and have default initializers for everything in Consensus::Params?

    Not keen on the map -- the possibility that deployments.at(DEPLOYMENT_FOO) might throw doesn't seem that great to me; and if you're just using deployments[DEPLOYMENT_FOO] and relying on it getting default initialised to something sane, might as well give VBitsDeployment a default initiaizer and just use the array?

  4. DrahtBot added the label Build system on Mar 10, 2021
  5. DrahtBot added the label Consensus on Mar 10, 2021
  6. DrahtBot added the label Docs on Mar 10, 2021
  7. DrahtBot added the label Mining on Mar 10, 2021
  8. DrahtBot added the label RPC/REST/ZMQ on Mar 10, 2021
  9. DrahtBot added the label Validation on Mar 10, 2021
  10. achow101 commented at 2:33 AM on March 10, 2021: member

    Ah, a different approach that might be worth considering:

    That doesn't seem that much different from what we already do now.

    Not keen on the map -- the possibility that deployments.at(DEPLOYMENT_FOO) might throw doesn't seem that great to me; and if you're just using deployments[DEPLOYMENT_FOO] and relying on it getting default initialised to something sane, might as well give VBitsDeployment a default initiaizer and just use the array?

    It seems better to me to throw (and hard shutdown) than to use some defaults, or worse, uninitialized members. I don't really like the idea of consensus params being initialized with default values that might not actually be what is wanted.

  11. DrahtBot commented at 4:37 AM on March 10, 2021: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #21391 ([Bundle 5/n] Prune g_chainman usage in RPC modules by dongcarl)
    • #21377 (Speedy trial support for versionbits by ajtowns)
    • #20354 (test: Add feature_taproot.py --previous_release by MarcoFalke)
    • #19573 (Replace unused BIP 9 logic with draft BIP 8 by luke-jr)
    • #19461 (multiprocess: Add bitcoin-gui -ipcconnect option by ryanofsky)
    • #19460 (multiprocess: Add bitcoin-wallet -ipcconnect option by ryanofsky)
    • #17783 (util: Fix -norpcwhitelist, -norpcallowip, and similar corner case behavior by ryanofsky)
    • #17581 (refactor: Remove settings merge reverse precedence code by ryanofsky)
    • #17580 (refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags by ryanofsky)
    • #17493 (util: Forbid ambiguous multiple assignments in config file by ryanofsky)
    • #10102 ([experimental] Multiprocess bitcoin by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  12. DrahtBot cross-referenced this on Mar 10, 2021 from issue Genericide BIP9 in variable/type names and comments by luke-jr
  13. DrahtBot cross-referenced this on Mar 10, 2021 from issue BIP 341: Add Speedy Trial activation parameters by achow101
  14. DrahtBot cross-referenced this on Mar 10, 2021 from issue [Bundle 5/n] Prune g_chainman usage in RPC modules by dongcarl
  15. DrahtBot cross-referenced this on Mar 10, 2021 from issue tests: Add fuzzing harness for versionbits by ajtowns
  16. DrahtBot cross-referenced this on Mar 10, 2021 from issue Convert taproot to flag day activation by ajtowns
  17. DrahtBot cross-referenced this on Mar 10, 2021 from issue Speedy trial support for versionbits by ajtowns
  18. DrahtBot cross-referenced this on Mar 10, 2021 from issue fuzz: Add tx_pool fuzz target by MarcoFalke
  19. practicalswift commented at 7:12 AM on March 10, 2021: contributor

    Concept ACK on not using error prone C arrays like maps.

  20. laanwj removed the label Build system on Mar 10, 2021
  21. laanwj removed the label Consensus on Mar 10, 2021
  22. laanwj removed the label Docs on Mar 10, 2021
  23. laanwj removed the label Mining on Mar 10, 2021
  24. laanwj removed the label RPC/REST/ZMQ on Mar 10, 2021
  25. laanwj removed the label Validation on Mar 10, 2021
  26. laanwj added the label Refactoring on Mar 10, 2021
  27. DrahtBot cross-referenced this on Mar 10, 2021 from issue rpc: Properly document return values (submitblock, gettxout, getblocktemplate, scantxoutset) by MarcoFalke
  28. DrahtBot cross-referenced this on Mar 10, 2021 from issue test: Add feature_taproot.py --previous_release by MarcoFalke
  29. DrahtBot cross-referenced this on Mar 10, 2021 from issue multiprocess: Add bitcoin-gui -ipcconnect option by ryanofsky
  30. DrahtBot cross-referenced this on Mar 10, 2021 from issue multiprocess: Add bitcoin-wallet -ipcconnect option by ryanofsky
  31. DrahtBot cross-referenced this on Mar 10, 2021 from issue Introduce deploymentstatus by ajtowns
  32. DrahtBot cross-referenced this on Mar 10, 2021 from issue fuzz: Add fuzzing harness for LoadMempool(...) and DumpMempool(...) by practicalswift
  33. DrahtBot cross-referenced this on Mar 10, 2021 from issue Multiprocess bitcoin by ryanofsky
  34. DrahtBot cross-referenced this on Mar 14, 2021 from issue Implement BIP 8 based Speedy Trial activation by achow101
  35. DrahtBot added the label Needs rebase on Mar 15, 2021
  36. achow101 force-pushed on Mar 15, 2021
  37. achow101 force-pushed on Mar 15, 2021
  38. DrahtBot removed the label Needs rebase on Mar 15, 2021
  39. DrahtBot commented at 4:48 PM on March 15, 2021: contributor

    <!--4a62be1de6b64f3ed646cdc7932c8cf5-->

    🕵️ @harding @sipa have been requested to review this pull request as specified in the REVIEWERS file.

  40. DrahtBot added the label Needs rebase on Mar 15, 2021
  41. [refactor] versionbits: make AbstractThresholdConditionChecker less abstract
    AbstractThresholdConditionChecker is already tightly tied to
    Consensus::BIP9Deployment, so have it reference that directly rather
    than abstracting it. It also does not need most of Consensus::Params,
    so pull out the two relevant fields directly.
    
    Also pull the Condition() implementation and Mask() function into the
    base class, though keeping Condition() virtual to allow it to be replaced.
    
    This simplifies the API substantially, but more importantly makes it
    easier to test independently.
    524b41ffdb
  42. chainparams: make versionbits threshold per-deployment d86a699edf
  43. scripted-diff: Rename AbstractThresholdConditionChecker and BIP9* classes
    -BEGIN VERIFY SCRIPT-
    sed -i -e 's/AbstractThresholdConditionChecker/ThresholdConditionChecker/g' $(git grep -l AbstractThresholdConditionChecker src/)
    sed -i -e 's/BIP9Deployment/VBitsDeployment/g' $(git grep -l BIP9Deployment src/)
    sed -i -e 's/BIP9Stats/VBitsStats/g' $(git grep -l BIP9Stats src/)
    -END VERIFY SCRIPT-
    ae541ab9a7
  44. versionbits: GetStateStatisticsFor
    Document that GetStateStatisticsFor expects a pointer to the previous block;
    which means that the "current period" it's reporting statistics for
    may not yet have any blocks in it. This is consistent with its usage
    from getblockchaininfo.
    
    Also fix a bug where GetStateStatisticsFor would crash if pindexPrev was
    a block in the first retarget period, but not the final block of that
    retarget period. Note that GetStateStatisticsFor would never be called
    in this case, as that would require the first retarget period to be in
    STARTED state, but it is always in DEFINED state.
    c67ead16f5
  45. versionbits: make Mask signed to match CBlockIndex::nVersion
    This avoids undefined behaviour when doing bitwise operations, so long as
    the versions are not negative.
    414640fbaf
  46. achow101 force-pushed on Mar 15, 2021
  47. DrahtBot removed the label Needs rebase on Mar 16, 2021
  48. Migrate versionbits to use height instead of MTP
    Co-authored-by: Anthony Towns <aj@erisian.com.au>
    25ab012cfd
  49. Rename user facing mentions of BIP 9 to versionbits and/or BIP 8
    Co-authored-by: Anthony Towns <aj@erisian.com.au>
    a440de1a77
  50. Add minimum activation height to VBitsDeployments 8269a341f7
  51. tests: test versionbits delayed activation c0efe1896c
  52. Clarify and reduce nRuleChangeActivationThreshold
    As thresholds are now parameterized, nRuleChangeActivationThreshold is
    no longer the threshold used for activating new rule changes. Instead it
    is now only used to warn if there is an unkonwn versionbits deployment.
    To make this clear, rename to m_vbits_min_threshold and update the
    comment describing it.
    
    Additionally, because this is just a minimum used for a warning, reduce
    the threshold to 75% so that future soft forks which may have thresholds
    lower than 95% will still have warnings.
    409a8cba9b
  53. test: add min_activation_height to -vbparams e3f7654fe1
  54. test: BIP 8 delayed activation functional test 3cc72deda8
  55. Change versionbits deployments to maps
    vDeployments is a C array that is used like a map. To make construction
    of deployments and later iteration easier, use a std::map for all things
    containing versionbits deployment data.
    
    Also removes MAX_VERSION_BITS_DEPLOYMENTS as it is no longer needed.
    434b43ca85
  56. Add constructors for VBitsDeployment
    Instead of using the default struct constructor and then filling in the
    parameters later, add constructors to VBitsDeployment where the
    parameters are filled in at initialization.
    de47b3189c
  57. Make parameters in VBitsDeployment const 48771d52c7
  58. Move period into VBitsDeployment 585dd6e774
  59. achow101 force-pushed on Mar 16, 2021
  60. DrahtBot cross-referenced this on Mar 22, 2021 from issue Implement BIP8 lockinontimeout by achow101
  61. DrahtBot cross-referenced this on Apr 8, 2021 from issue Replace unused BIP 9 logic with draft BIP 8 by luke-jr
  62. DrahtBot cross-referenced this on Apr 11, 2021 from issue refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags by ryanofsky
  63. jnewbery commented at 2:36 PM on April 11, 2021: member

    This is built on #21392, which is now closed. Should this PR also be closed?

  64. fanquake added the label Waiting for author on Apr 12, 2021
  65. fanquake marked this as a draft on Apr 12, 2021
  66. MarcoFalke commented at 7:54 AM on April 12, 2021: member

    I'd say it needs rebase after #21377 is merged

  67. DrahtBot cross-referenced this on Apr 12, 2021 from issue util: Fix -norpcwhitelist, -norpcallowip, and similar corner case behavior by ryanofsky
  68. DrahtBot cross-referenced this on Apr 13, 2021 from issue refactor: Remove settings merge reverse precedence code by ryanofsky
  69. DrahtBot cross-referenced this on Apr 13, 2021 from issue util: Forbid ambiguous multiple assignments in config file by ryanofsky
  70. MarcoFalke removed the label Waiting for author on Apr 15, 2021
  71. MarcoFalke added the label Needs rebase on Apr 15, 2021
  72. luke-jr commented at 8:33 PM on May 13, 2021: member

    This seems to be a lot less readable. Is there a good way to get uninitialised warnings without harming readability, perhaps?

  73. achow101 commented at 4:56 AM on May 25, 2021: member

    Closing for now, may revisit in the future, or someone else can take it over.

  74. achow101 closed this on May 25, 2021

  75. ajtowns cross-referenced this on Jan 11, 2022 from issue Add defaults to vDeployments to avoid uninitialized variables by ajtowns
  76. bitcoin 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: 2026-05-20 06:54 UTC