Thank you all for the insightful feedback, on list, in private and on various social media platforms. I have extended the generalized proposal which extends BIP9. This basically introduces an extra workflow state if activationtime > starttime and < timeout - 1 month. It allows extra business logic to be added, such as requiring mandatory signalling. Please find the draft here: https://gist.github.com/shaolinfry/70d0582db7de958b7d5b6422cfef4e22
 BIP: bip-uaversionbits-strong Title: Version bits extension with mandatory activation Author: Shaolin Fry  Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-???? Status: Draft Type: Informational Created: 2017-03-09 License: BSD-3-Clause CC0-1.0 
==Abstract== This document specifies an extension to BIP9 that introduces an additional activation parameter to deploy backward-compatible changes (further called "soft forks") to be activated by a deadline. ==Motivation== BIP9 introduced a mechanism for doing parallel soft forking deployments based on repurposing the block nVersion field. Activation is dependent on near unanimous hashrate signalling which may be impractical and is also subject to veto by a small minority of non-signalling hashrate. This specification provides an way for full nodes to coordinate syncronized activation based on a median past time using the BIP9 state machine. Hashrate may optionally trigger activation before the user defined activation sequence triggers. ==Specification== This specification adds a new per-chain deployment parameter to the existing BIP9 specification as follows: # The '''activationtime''' specifies a minimum median time past of a block at which the deployment should transition to the locked-in state. This specification adds a new workflow state, '''PRE_LOCK_IN''' to the BIP9 state machine if the deployment '''activationtime''' is greater than zero when the workflow will be '''DEFINED''' -> '''STARTED''' -> '''PRE_LOCK_IN''' -> '''LOCKED_IN''' -> '''ACTIVE'''. The '''PRE_LOCK_IN''' phase allows optional per deployment processing, e.g. mandatory signalling. ===Selection guidelines=== The following guidelines are suggested for selecting these parameters for a soft fork: # '''activationtime''' should be set to some date in the future and must be less than the BIP9 '''timeout'''. It is recommended to have an activation time of 1 year minus 30 days (28944000 seconds). The '''activationtime''' cannot be less than 30 days before the '''timeout'''. ===State transitions=== The state transition workflow is exactly the same as in BIP9 except when '''activationtime''' is greater than zero. Then the workflow will be '''DEFINED''' -> '''STARTED''' -> '''PRE_LOCK_IN''' -> '''LOCKED_IN''' -> '''ACTIVE'''. When in the STARTED state if the median time past is greater than or equal to the '''activationtime''' then the state will transition to PRE_LOCK_IN on the next retarget after '''activationtime'''. case STARTED: // Transition to THRESHOLD_PRE_LOCK_IN if mandatory activation is set if ((nActivationTime != 0) && pindexPrev->GetMedianTimePast() >= nActivationTime) { stateNext = THRESHOLD_PRE_LOCK_IN; break; } // BIP9 specification follows if (GetMedianTimePast(block.parent) >= timeout) { return FAILED; } int count = 0; walk = block; for (i = 0; i < 2016; i++) { walk = walk.parent; if (walk.nVersion & 0xE0000000 == 0x20000000 && (walk.nVersion >> bit) & 1 == 1) { count++; } } if (count >= threshold) { return LOCKED_IN; } return STARTED; === Reference implementation === https://github.com/bitcoin/bitcoin/compare/master...shaolinfry:bip-uaversionbits-strong ==== Optional mandatory signalling ====
 /** * Return true if nVersion BIP9 deployment is signalling during * mandatory periods. */ bool IsMandatorySignalling(int32_t nVersion, Consensus::DeploymentPos pos, const CBlockIndex* pindexPrev, const Consensus::Params& params) { // Check the deployment is in the correct state for this check to apply. if (!((VersionBitsState(pindexPrev, params, pos, versionbitscache) == THRESHOLD_PRE_LOCK_IN) || (VersionBitsState(pindexPrev, params, pos, versionbitscache) == THRESHOLD_LOCKED_IN))) return true; // return signalling state return (((nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (nVersion & VersionBitsMask(params, pos)) != 0); } // segwit signalling is mandatory during PRE_LOCK_IN and LOCKED_IN phase if (!IsMandatorySignalling(block.nVersion, Consensus::DEPLOYMENT_EXAMPLE, pindexPrev, consensusParams)) return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", block.nVersion), strprintf("rejected nVersion=0x%08x block, must upgrade", block.nVersion)); 
==Deployments== A living list of deployment proposals can be found [[bip-0009/assignments.mediawiki|here]]. ==Copyright== This document is placed in the public domain.