-
Notifications
You must be signed in to change notification settings - Fork 135
ReducedData Temporary Softfork #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 29.x-knots
Are you sure you want to change the base?
Changes from all commits
96440ed
0649862
8fbae96
4d39592
2cd2c26
a282204
28b8a59
5965fd7
2d52966
0a3de04
e58a2dd
a4bf597
d492ab5
66f88cf
0c1e17d
d87bd14
6073e11
b251fc6
b2e1e5a
d6b6fa4
db3665e
d8e8129
d290220
2b8b339
0a11dfe
6f6c89e
5366187
1da8414
27caa3a
7bd0376
a734c94
5d22a09
2082d6c
3fb8ee2
fbe877e
6c8bccf
c78685f
8a21fcb
29d8e6f
00d4b2b
b534afc
2b9e3bc
fdff989
17beb82
66769ef
a719bb0
93d3816
3ff937c
bdb42cb
5005fc4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,8 +77,8 @@ void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& opti | |
|
|
||
| for (const std::string& strDeployment : args.GetArgs("-vbparams")) { | ||
| std::vector<std::string> vDeploymentParams = SplitString(strDeployment, ':'); | ||
| if (vDeploymentParams.size() < 3 || 4 < vDeploymentParams.size()) { | ||
| throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end[:min_activation_height]"); | ||
| if (vDeploymentParams.size() < 3 || 5 < vDeploymentParams.size()) { | ||
| throw std::runtime_error("Version bits parameters malformed, expecting deployment:start:end[:min_activation_height[:active_duration]]"); | ||
| } | ||
| CChainParams::VersionBitsParameters vbparams{}; | ||
| if (!ParseInt64(vDeploymentParams[1], &vbparams.start_time)) { | ||
|
|
@@ -94,12 +94,19 @@ void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& opti | |
| } else { | ||
| vbparams.min_activation_height = 0; | ||
| } | ||
| if (vDeploymentParams.size() >= 5) { | ||
| if (!ParseInt32(vDeploymentParams[4], &vbparams.active_duration)) { | ||
| throw std::runtime_error(strprintf("Invalid active_duration (%s)", vDeploymentParams[4])); | ||
| } | ||
| } else { | ||
| vbparams.active_duration = 0; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| bool found = false; | ||
| for (int j=0; j < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { | ||
| if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) { | ||
| options.version_bits_parameters[Consensus::DeploymentPos(j)] = vbparams; | ||
| found = true; | ||
| LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, min_activation_height=%d\n", vDeploymentParams[0], vbparams.start_time, vbparams.timeout, vbparams.min_activation_height); | ||
| LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, min_activation_height=%d, active_duration=%d\n", vDeploymentParams[0], vbparams.start_time, vbparams.timeout, vbparams.min_activation_height, vbparams.active_duration); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,6 +74,7 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const | |
| return "Knots:" + CLIENT_BUILD.substr(pos + 6) + "/"; | ||
| }(); | ||
| ua += ua_knots; | ||
| ua += "UASF-ReducedData:0.1/"; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes sense if you're going to have an activation client, but not so much for a merge into mainline Knots. |
||
| } | ||
| return ua; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,7 @@ constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_ | |
| enum DeploymentPos : uint16_t { | ||
| DEPLOYMENT_TESTDUMMY, | ||
| DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342) | ||
| DEPLOYMENT_REDUCED_DATA, // Temporary deployment of UASF-ReducedData | ||
| // NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp | ||
| MAX_VERSION_BITS_DEPLOYMENTS | ||
| }; | ||
|
|
@@ -52,6 +53,9 @@ struct BIP9Deployment { | |
| * boundary. | ||
| */ | ||
| int min_activation_height{0}; | ||
| /** For temporary softforks: number of blocks the deployment remains active after activation. | ||
| * 0 means permanent (never expires). */ | ||
| int active_duration{0}; | ||
|
|
||
| /** Constant for nTimeout very far in the future. */ | ||
| static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max(); | ||
|
|
@@ -94,6 +98,9 @@ struct Params { | |
| * Note that segwit v0 script rules are enforced on all blocks except the | ||
| * BIP 16 exception blocks. */ | ||
| int SegwitHeight; | ||
| /** Block heights during which Reduced Data is active */ | ||
| int ReducedDataHeightBegin{std::numeric_limits<int>::max()}; | ||
| int ReducedDataHeightEnd{std::numeric_limits<int>::max()}; | ||
|
Comment on lines
+101
to
+103
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the purpose of this with the MASF variant? |
||
| /** Don't warn about unknown BIP 9 activations below this height. | ||
| * This prevents us from warning about the CSV and segwit activations. */ | ||
| int MinBIP9WarningHeight; | ||
|
|
@@ -149,6 +156,20 @@ struct Params { | |
| } // no default case, so the compiler can warn about missing cases | ||
| return std::numeric_limits<int>::max(); | ||
| } | ||
|
|
||
| int DeploymentHeightEnd(BuriedDeployment dep) const | ||
| { | ||
| switch (dep) { | ||
| case DEPLOYMENT_HEIGHTINCB: | ||
| case DEPLOYMENT_CLTV: | ||
| case DEPLOYMENT_DERSIG: | ||
| case DEPLOYMENT_CSV: | ||
| case DEPLOYMENT_SEGWIT: | ||
| // These are forever | ||
| break; | ||
| } // no default case, so the compiler can warn about missing cases | ||
| return std::numeric_limits<int>::max(); | ||
| } | ||
|
Comment on lines
+159
to
+172
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, seems useless/wrong with your MASF concept. |
||
| }; | ||
|
|
||
| } // namespace Consensus | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -161,14 +161,24 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i | |
| return nSigOps; | ||
| } | ||
|
|
||
| bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee) | ||
| bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee, const CheckTxInputsRules rules) | ||
| { | ||
| // are the actual inputs available? | ||
| if (!inputs.HaveInputs(tx)) { | ||
| return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent", | ||
| strprintf("%s: inputs missing/spent", __func__)); | ||
| } | ||
|
|
||
| // NOTE: CheckTransaction is arguably the more logical place to do this, but it's context-independent, so this is probably the next best place for now | ||
| if (rules.test(CheckTxInputsRules::OutputSizeLimit)) { | ||
| for (const auto& txout : tx.vout) { | ||
| if (txout.scriptPubKey.empty()) continue; | ||
| if (txout.scriptPubKey.size() > ((txout.scriptPubKey[0] == OP_RETURN) ? MAX_OUTPUT_DATA_SIZE : MAX_OUTPUT_SCRIPT_SIZE)) { | ||
| return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-vout-script-toolarge"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: wherever it says
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically these are structured from parent to child, and toolarge is a logical single element. |
||
| } | ||
| } | ||
| } | ||
|
|
||
| CAmount nValueIn = 0; | ||
| for (unsigned int i = 0; i < tx.vin.size(); ++i) { | ||
| const COutPoint &prevout = tx.vin[i].prevout; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,10 @@ const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_B | |
| /*.name =*/ "taproot", | ||
| /*.gbt_force =*/ true, | ||
| }, | ||
| { | ||
| /*.name =*/ "reduced_data", | ||
| /*.gbt_force =*/ true, | ||
| }, | ||
| }; | ||
|
|
||
| std::string DeploymentName(Consensus::BuriedDeployment dep) | ||
|
|
@@ -50,5 +54,6 @@ std::optional<Consensus::BuriedDeployment> GetBuriedDeployment(const std::string | |
| } else if (name == "csv") { | ||
| return Consensus::BuriedDeployment::DEPLOYMENT_CSV; | ||
| } | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: unnecessary whitespace change |
||
| return std::nullopt; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,26 +14,50 @@ | |
| inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache& versionbitscache) | ||
| { | ||
| assert(Consensus::ValidDeployment(dep)); | ||
| return (pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1) >= params.DeploymentHeight(dep); | ||
| const auto next_block_height = (pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1); | ||
| return next_block_height >= params.DeploymentHeight(dep) && next_block_height <= params.DeploymentHeightEnd(dep); | ||
| } | ||
|
|
||
| inline bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos dep, VersionBitsCache& versionbitscache) | ||
| { | ||
| assert(Consensus::ValidDeployment(dep)); | ||
| return ThresholdState::ACTIVE == versionbitscache.State(pindexPrev, params, dep); | ||
| if (ThresholdState::ACTIVE != versionbitscache.State(pindexPrev, params, dep)) { | ||
| return false; | ||
| } | ||
| // Check if temporary deployment has expired | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic is missing in some of the other functions here |
||
| const auto& deployment = params.vDeployments[dep]; | ||
| if (deployment.active_duration > 0) { | ||
| const int activation_height = versionbitscache.StateSinceHeight(pindexPrev, params, dep); | ||
| const int next_block_height = (pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1); | ||
| if (next_block_height > activation_height + deployment.active_duration) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: nodes with different activation heights will disagree on the expiry block, which introduces chain split risk.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nodes disagreeing on consensus rules would be a chain split risk regardless. But why would they disagree? |
||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /** Determine if a deployment is active for this block */ | ||
| inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache& versionbitscache) | ||
| { | ||
| assert(Consensus::ValidDeployment(dep)); | ||
| return index.nHeight >= params.DeploymentHeight(dep); | ||
| return index.nHeight >= params.DeploymentHeight(dep) && index.nHeight <= params.DeploymentHeightEnd(dep); | ||
| } | ||
|
|
||
| inline bool DeploymentActiveAt(const CBlockIndex& index, const Consensus::Params& params, Consensus::DeploymentPos dep, VersionBitsCache& versionbitscache) | ||
| { | ||
| assert(Consensus::ValidDeployment(dep)); | ||
| return DeploymentActiveAfter(index.pprev, params, dep, versionbitscache); | ||
| if (ThresholdState::ACTIVE != versionbitscache.State(index.pprev, params, dep)) { | ||
| return false; | ||
| } | ||
| // Check if temporary deployment has expired | ||
| const auto& deployment = params.vDeployments[dep]; | ||
| if (deployment.active_duration > 0) { | ||
| const int activation_height = versionbitscache.StateSinceHeight(index.pprev, params, dep); | ||
| if (index.nHeight > activation_height + deployment.active_duration) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| /** Determine if a deployment is enabled (can ever be active) */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -714,7 +714,8 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) | |
| argsman.AddArg("-datacarriercost", strprintf("Treat extra data in transactions as at least N vbytes per actual byte (default: %s)", DEFAULT_WEIGHT_PER_DATA_BYTE / 4.0), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); | ||
| argsman.AddArg("-datacarrierfullcount", strprintf("Apply datacarriersize limit to all known datacarrier methods (default: %u)", DEFAULT_DATACARRIER_FULLCOUNT), ArgsManager::ALLOW_ANY | (DEFAULT_DATACARRIER_FULLCOUNT ? uint32_t{ArgsManager::DEBUG_ONLY} : 0), OptionsCategory::NODE_RELAY); | ||
| argsman.AddArg("-datacarriersize", | ||
| strprintf("Maximum size of data in data carrier transactions we relay and mine, in bytes (default: %u)", | ||
| strprintf("Maximum size of data in data carrier transactions we relay and mine, in bytes (maximum %s, default: %u)", | ||
| MAX_OUTPUT_DATA_SIZE, | ||
| MAX_OP_RETURN_RELAY), | ||
| ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); | ||
| argsman.AddArg("-maxscriptsize", strprintf("Maximum size of scripts (including the entire witness stack) we relay and mine, in bytes (default: %s)", DEFAULT_SCRIPT_SIZE_POLICY_LIMIT), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); | ||
|
|
@@ -966,7 +967,7 @@ namespace { // Variables internal to initialization process only | |
|
|
||
| int nMaxConnections; | ||
| int available_fds; | ||
| ServiceFlags g_local_services = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS); | ||
| ServiceFlags g_local_services = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS | NODE_UASF_REDUCED_DATA); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By broadcasting the UASF flag by default, doesn't that risk network partition before sufficient adoption?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should only be used for the 8 outgoing connections. Incoming connections from old nodes are accepted. |
||
| int64_t peer_connect_timeout; | ||
| std::set<BlockFilterType> g_enabled_filter_types; | ||
|
|
||
|
|
@@ -2135,6 +2136,27 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) | |
| return; | ||
| } | ||
|
|
||
| constexpr uint256 bad_block_hash{"0000000000000000000000000000000000000000000000000000000000000000"}; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a placeholder? Specify an actual bad block or remove.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, this code only makes sense for the (now removed) reactive activation. Instead, this PR should implement detecting that it's on an invalid chain at startup and rewinding.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will remove. |
||
| BlockValidationState state; | ||
| CBlockIndex* pblockindex; | ||
| { | ||
| LOCK(chainman.GetMutex()); | ||
| pblockindex = chainman.m_blockman.LookupBlockIndex(bad_block_hash); | ||
| if (pblockindex && !pblockindex->IsValid(BLOCK_VALID_UNKNOWN)) { | ||
| // Already marked invalid | ||
| pblockindex = nullptr; | ||
| } | ||
| } | ||
| if (pblockindex) { | ||
| if (!chainman.ActiveChainstate().InvalidateBlock(state, pblockindex)) { | ||
| state.Error("InvalidateBlock failed (is your node too pruned?)"); | ||
| } | ||
| if (state.IsValid()) { | ||
| chainman.ActiveChainstate().ActivateBestChain(state); | ||
| } | ||
| Assert(state.IsValid()); | ||
| } | ||
|
|
||
| // Start indexes initial sync | ||
| if (!StartIndexBackgroundSync(node)) { | ||
| bilingual_str err_str = _("Failed to start indexes, shutting down.."); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would prefer if you split up "Convert DEPLOYMENT_REDUCED_DATA to temporary BIP9 MASF" into 3 commits: