This encapsulates the "-vbparams" option, which is only meant for regtest, directly on CRegTestParams.
This is a refactor and doesn't change functionality.
Related to https://github.com/bitcoin/bitcoin/pull/8994
This encapsulates the "-vbparams" option, which is only meant for regtest, directly on CRegTestParams.
This is a refactor and doesn't change functionality.
Related to https://github.com/bitcoin/bitcoin/pull/8994
to ease review, might be good to split this into a moveonly commit and then a subsequent one with changes if thats possible?
Why move the version bits information to a separate file? This introduces a circular dependency between chainparams and versionbitsinfo,
to ease review, might be good to split this into a moveonly commit and then a subsequent one with changes if thats possible?
Sure, but I would like to wait for some concept acks first.
Why move the version bits information to a separate file? This introduces a circular dependency between chainparams and versionbitsinfo,
No, it does not. After this, versionbits depends onchainparams, which depends on versionbitsinfo, which depends on consensus/params. The separation is precisely to avoid a circular dependency between chainparams and versionbits.
No, it does not. After this, versionbits depends onchainparams, which depends on versionbitsinfo, which depends on consensus/params. The separation is precisely to avoid a circular dependency between chainparams and versionbits.
My apologies! I confused chainparams and consensus/params when reading this.
Needs rebase due to merge of #13341
Rebased and separated MOVEONLY commit.
14 | 15 | #include <assert.h> 16 | 17 | -#include <chainparamsseeds.h> 18 | +#include <boost/algorithm/string/classification.hpp> 19 | +#include <boost/algorithm/string/split.hpp>
NB: it's still used in init.cpp, only for mempool replacement
13 | +#include <versionbitsinfo.h> 14 | 15 | #include <assert.h> 16 | 17 | -#include <chainparamsseeds.h> 18 | +#include <boost/algorithm/string/classification.hpp>
NB: it's still used in init.cpp, only for mempool replacement
54 | @@ -55,6 +55,9 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName) 55 | InitSignatureCache(); 56 | InitScriptExecutionCache(); 57 | fCheckBlockIndex = true; 58 | + // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests. 59 | + // TODO: fix the code to support SegWit blocks. 60 | + gArgs.ForceSetArg("-vbparams", "segwit:0:999999999999");
nit: would be nice to keep using Consensus::BIP9Deployment::NO_TIMEOUT
utACK with ultra minor nit
rebased
Fixed nit in #13311 (review)
395 | + } 396 | + } 397 | + } 398 | +} 399 | + 400 | static std::unique_ptr<CChainParams> globalChainParams;
Could change this to unique_ptr<const CChainParams> to better ensure that params aren't changed after initialisation? (Means CreateChainParams() return value also needs to change, but that seems to work fine)
429 | -void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout) 430 | +void SelectParams(const std::string& network) 431 | { 432 | - globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout); 433 | + SelectBaseParams(network); 434 | + globalChainParams = CreateChainParams(network, gArgs);
Why not reference gArgs directly in CreateChainParams() when using REGTEST? This is the only place that actually calls CreateChainParams with the args parameter and the only place that calls it with chain==REGTEST. That way you don't need to have two different ways of calling CreateChainParams.
I can remove the new way of calling CreateChainParams, but the idea was that some unittests could create their own custom ArgsManager instead of using gArgs. This would only serve for testing functions that explicitly take a CChainParams instead of relaying on Params().
I guess one can mutate gArgs to a given value for a given test and then back to its original value afterwards. Or as you say, make this change afterwards when it's going to be used.
275 | @@ -280,7 +276,7 @@ class CTestNetParams : public CChainParams { 276 | */ 277 | class CRegTestParams : public CChainParams { 278 | public: 279 | - CRegTestParams() { 280 | + CRegTestParams(ArgsManager& args) {
Is it necessary to pass in an entire ArgsManager object? It seems only the -vbparams value is used. What about just passing in the vbparams value?
Better to just pass the needed arg IMO, and only couple these classes if preferable based on the eventual use. https://martinfowler.com/bliki/Yagni.html
Could make this const ArgsManager& args
utACK 7067657731404c28ff87e46ec390992500ca13be
Concept ACK.
358 | + void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout) 359 | + { 360 | + consensus.vDeployments[d].nStartTime = nStartTime; 361 | + consensus.vDeployments[d].nTimeout = nTimeout; 362 | + } 363 | + void UpdateVersionBitsParametersFromArgs(ArgsManager& args);
const ArgsManager& here as well
412 | return std::unique_ptr<CChainParams>(new CMainParams()); 413 | else if (chain == CBaseChainParams::TESTNET) 414 | return std::unique_ptr<CChainParams>(new CTestNetParams()); 415 | else if (chain == CBaseChainParams::REGTEST) 416 | - return std::unique_ptr<CChainParams>(new CRegTestParams()); 417 | + return std::unique_ptr<CChainParams>(new CRegTestParams(args));
I still think dropping the args param and referencing gArgs here directly makes more sense. Otherwise, could make args be const here too.
Yes, that makes sense.
By doing just that and dropping the ArgsManager& args argument from std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain, ArgsManager& args) we can remove std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain) as you also have pointed out here: #13311 (review).
utACK ca040b5b76ddeeace6da4f8111169ffd6234414a
365 | 366 | -static std::unique_ptr<CChainParams> globalChainParams; 367 | +void CRegTestParams::UpdateVersionBitsParametersFromArgs(ArgsManager& args) 368 | +{ 369 | + // Allow overriding version bits parameters for testing 370 | + if (args.IsArgSet("-vbparams")) {
This function can exit early if the -vbparams arg is not set.
void CRegTestParams::UpdateVersionBitsParametersFromArgs(ArgsManager& args)
{
if (!args.IsArgSet("-vbparams")) return;
for (const std::string& strDeployment : args.GetArgs("-vbparams")) {
...
}
}
107 | @@ -107,7 +108,9 @@ class CChainParams 108 | * @returns a CChainParams* of the chosen chain. 109 | * @throws a std::runtime_error if the chain is not supported. 110 | */ 111 | -std::unique_ptr<CChainParams> CreateChainParams(const std::string& chain); 112 | +std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain); 113 | +/** Extended version taking custom args (only useful for regtest). */ 114 | +std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain, ArgsManager& args);
I tend to agree with @ajtowns that we can do without std::unique_ptr<const CChainParams> CreateChainParams(const std::string& chain, ArgsManager& args).
If you want to keep it then maybe you can remove its declaration from chainparams.h. There is no need to expose it; it only uses internal linkage at the moment.
Hopefully fixed all pending nits in the last commit to be squashed, please remind me if I left anything out. Also sorry about the wait, back from vacation.
Looks good to me, fwiw
<!--e57a25ab6845829454e8d69fc972939a-->Note to reviewers: This pull request conflicts with the following ones:
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.
utACK 18d5f26
402 | return std::unique_ptr<CChainParams>(new CMainParams()); 403 | else if (chain == CBaseChainParams::TESTNET) 404 | return std::unique_ptr<CChainParams>(new CTestNetParams()); 405 | else if (chain == CBaseChainParams::REGTEST) 406 | - return std::unique_ptr<CChainParams>(new CRegTestParams()); 407 | + return std::unique_ptr<CChainParams>(new CRegTestParams(gArgs));
Any reason to not use gArgs global in CRegTestParams constructor?
The class only uses the global for initialisation; I think it makes sense to supply it as a parameter for initialisation rather than making the entire class dependent on the global. YMMV, FWIW, etc.
utACK 18d5f26, with a little question.
Any reason to use the global instead of a parameter? I think it's more encapsulated this way, but I tend to be alergic to globals ib general. If people prefer a global I guess I will have to change it.
On Sun, 16 Sep 2018, 23:21 João Barbosa, notifications@github.com wrote:
@promag commented on this pull request.
utACK 18d5f26 https://github.com/bitcoin/bitcoin/commit/18d5f2621f2ade428e631d34b95e23c8be862ec8, with a little question.
In src/chainparams.cpp https://github.com/bitcoin/bitcoin/pull/13311#discussion_r217928196:
{ if (chain == CBaseChainParams::MAIN) return std::unique_ptr<CChainParams>(new CMainParams()); else if (chain == CBaseChainParams::TESTNET) return std::unique_ptr<CChainParams>(new CTestNetParams()); else if (chain == CBaseChainParams::REGTEST)
return std::unique_ptr<CChainParams>(new CRegTestParams());
return std::unique_ptr<CChainParams>(new CRegTestParams(gArgs));Any reason to not use gArgs global in CRegTestParams constructor?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/bitcoin/bitcoin/pull/13311#pullrequestreview-155758424, or mute the thread https://github.com/notifications/unsubscribe-auth/AA9jStqUTYlVdHuFThL_C3Io272IQd7eks5ubsDAgaJpZM4UKcd3 .
utACK 18d5f2621f2ade428e631d34b95e23c8be862ec8
58 | @@ -58,6 +59,9 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName) 59 | InitSignatureCache(); 60 | InitScriptExecutionCache(); 61 | fCheckBlockIndex = true; 62 | + // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests. 63 | + // TODO: fix the code to support SegWit blocks. 64 | + gArgs.ForceSetArg("-vbparams", strprintf("segwit:0:%d", (int64_t)Consensus::BIP9Deployment::NO_TIMEOUT));
2018-09-18 16:46:43 clang-tidy(pr=13311): src/test/test_bitcoin.cpp:64:61: warning: redundant cast to the same type [google-readability-casting]
If I remove that casting, I get:
test/qt_test_test_bitcoin_qt-test_bitcoin.o: In function `tinyformat::detail::FormatArg::FormatArg<long>(long const&)':
/home/jt/code/bitcoin/src/./tinyformat.h:508: undefined reference to `Consensus::BIP9Deployment::NO_TIMEOUT'
Cool! A false positive then. Thanks for investigating.
373 | + if (!ParseInt64(vDeploymentParams[2], &nTimeout)) { 374 | + throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2])); 375 | + } 376 | + bool found = false; 377 | + for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { 378 | + if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) {
2018-09-18 16:46:43 clang-tidy(pr=13311): src/chainparams.cpp:377:17: warning: do not use 'compare' to test equality of strings; use the string equality operator instead [misc-string-compare]
267 | @@ -270,7 +268,7 @@ class CTestNetParams : public CChainParams { 268 | */ 269 | class CRegTestParams : public CChainParams { 270 | public: 271 | - CRegTestParams() { 272 | + CRegTestParams(const ArgsManager& args) {
2018-09-18 16:46:43 clang-tidy(pr=13311): src/chainparams.cpp:271:5: warning: single-argument constructors must be marked explicit to avoid unintentional implicit conversions [google-explicit-constructor]
Fixed 2 of the 3 clang warnings.
362 | + 363 | + for (const std::string& strDeployment : args.GetArgs("-vbparams")) { 364 | + std::vector<std::string> vDeploymentParams; 365 | + boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":")); 366 | + if (vDeploymentParams.size() != 3) { 367 | + throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end");
I don't like that this introduces more exceptions in code that can normally hit them by a mere typo. I'd prefer if we used exceptions only in exceptional circumstances, since it is not easy to follow the control flow with exceptions.
Note that the our other command line parsing is done with functions that return bool instead of void and append the error to a passed in string reference.
I see that the caller needs to throw, but that isn't reason enough to "poison" unrelated code.
I think there's absolutely no problem in initialization exceptions that will prevent the binary from starting, this one should be cached (depending on binary) on bitcoin-cli.cpp, bitcoin-tx.cpp or bitcoind.cpp, when SelectParams is called, just like https://github.com/bitcoin/bitcoin/blob/master/src/chainparamsbase.cpp#L42
utACK bd74fb9e4c271bd901dfbb5ad1929b44fcadd735
372 | + } 373 | + if (!ParseInt64(vDeploymentParams[2], &nTimeout)) { 374 | + throw std::runtime_error(strprintf("Invalid nTimeout (%s)", vDeploymentParams[2])); 375 | + } 376 | + bool found = false; 377 | + for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) {
2018-09-22 22:20:08 cpplint(pr=13311): src/chainparams.cpp:376: Missing spaces around < [whitespace/operators] [3]
Fixed latest style nit.
utACK 6fa901f.
re-utACK 6fa901f