-
Notifications
You must be signed in to change notification settings - Fork 6
Heretical Deployments
Deploying a soft fork for testing on a global signet has different requirements to deploying one on mainnet.
In particular:
-
the codebase must support triggering soft fork activation on signet at different heights, as custom signets may not activate at the same height or time as the global signet
-
in the event of a proposed soft fork being found to be buggy, and the specification being updated incompatibly when the bug is fixed, activated soft forks must be able to be rolled back so that the new version of the specification can be tested without triggering a hard fork event
-
activations should be able to take place relatively quickly, so that testing is convenient, rather than spending months to allow coordination amongst miners and users
To emphasise this difference, we're calling this deployment method "heretical".
The way heretical deployments are designed is as follows:
-
Four configuration parameters are set:
-
int32_t signal_activate, signal_abandon
-- version numbers used to signal activation/abandonment of the soft fork via the block header -
start_time
-- used to control when signalling can begin -
timeout
-- used to set a fixed timeout at which the soft fork will always be automatically abandoned
-
-
signal_activate
andsignal_abandon
should be derived from the BIP number of the soft fork (asuint16_t
) as follows:signal_activate = 0x6000_0000 | (((int32_t)bip)<<8) | (bip_version & 0xFF)
signal_abandon = 0x4000_0000 | (((int32_t)bip)<<8) | (bip_version & 0xFF)
-
A state machine similar to BIP9 is introduced, with the state updating every 432 blocks (3 days)
-
The following states are defined:
- DEFINED - inactive, initial state, waiting for
start_time
- STARTED - inactive, waiting for signal or
timeout
- LOCKED_IN - inactive, will be active next period
- ACTIVE - active, waiting for
signal_abandon
or timeout - DEACTIVATING - active, but will be abandoned next period
- ABANDONED - inactive, terminal state
- DEFINED - inactive, initial state, waiting for
-
The transitions to activate a fork look like
DEFINED -> STARTED -> LOCKED_IN -> ACTIVE
, withSTARTED
being triggered by median time reachingstart_time
andLOCKED_IN
being triggered by a block being mined withnVersion == signal_activate
. -
The transitions to abandon a fork look like:
-
DEFINED -> ABANDONED
- only if timeout is reached -
STARTED -> ABANDONED
- if timeout is reached ornVersion == signal_abandon
is seen (overrides theSTARTED -> LOCKED_IN
transition if a block withnVersion == signal_activate
occurs in the same period) -
LOCKED_IN or ACTIVE -> DEACTIVATING -> ABANDONED
- if timeout is reached ornVersion == signal_abandon
is observed inLOCKED_IN
orACTIVE
-
(Note: there is no option for a signet to transition a soft fork back to ACTIVE
if a signal_abandon
block is mined. Maybe there should be; and a terminal state should only occur via the timeout
? On the other hand, because signet is permissioned, the miners could always trigger a large reorg of the chain to put it back in an earlier state to undo an unwanted soft fork abandonment)
As a proposer of a new soft fork, the idea is that you set deployment parameters like this:
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{
.bip = 119,
.bip_version = 0,
.start = 1654041600, // 2022-06-01
.timeout = 1969660800, // 2032-06-01
};
The start
time and bip_version
should be updated each time the proposal is updated in a way that's not fully compatible; and the timeout
should normally be set to 10 years after the start time. Note that this means the start
time should almost always be in the past, since the BIP should usually be updated before code is committed and merged.
With 256 values for bip_version
available, this allows for an incompatible update approximately every month over a 10 year period, without causing any ambiguity and allowing clients implementing different versions of the spec to be compatible.
As a miner of a signet, you can support testing a proposed soft fork by doing the following:
- Updating your mining/block-signing nodes to run bitcoin-inquisition rather than bitcoin core
- Mining a block with
nVersion = signal_activate
- Waiting up to 6 days for the state to transition from
STARTED
throughLOCKED_IN
toACTIVE
. Manually mining up to 864 blocks as quickly as possible can reduce this time, of course.
If a soft fork proposal has an incompatible update, bumping bip_version
from A
to B
, you should proceed as follows:
- Mine a block with
nVersion = signal_abandon_A
to signal that you will no longer be supporting the old version of the fork - Mine a block with
nVersion = signal_activate_B
to signal that you will be supporting the new version of the fork. - Continue running the software supporting version
A
while the deployment transitions fromACTIVE
throughDEACTIVATING
until it reachesABANDONED
. These states can be observed by invokingbitcoin-cli -signet getdeploymentinfo
- Once version
A
is inactive, upgrade your mining software to support versionB
. - If both signalling blocks were in the same period, version
B
will already beACTIVE
and ready to use, otherwise it will be LOCKED_IN and ready to use after 432 blocks are mined.
Note that signalling for activation of a new version B
should be done after signalling for abandonment of any prior version that was activated. Not doing so may cause a hard fork event, that is it may cause users running versions of bitcoin that enforce version A
of the soft fork to cease being able to follow the chain once transactions/blocks following the rules in version B
are included in the chain.
(Some consideration should probably be given to how the chain behaves if a bug in the soft fork implementation causes it to be a hard fork compared to bitcoin core's consensus rules)
(The contrib/signet/miner
software currently does not have any special support for doing this signalling)
In order to test a proposed soft fork that has been merged into the bitcoin inquisition codebase, a user needs to:
- switch their software from bitcoin core to bitcoin inquisition
- use a signet whose miners are activating the soft fork (which can be observed by running
bitcoin-cli -signet getdeploymentinfo
after syncing)
In the event that a soft fork is updated from version A
to version B
, users may want to recover any funds they have locked under the version A
rules. In that case, they may observe that miners are deactivating version A
by watching for the DEACTIVATING
state via getdeploymentinfo
, and will have 432 blocks in this state to recover their funds. (This feature relies on the signet miners signalling for abandonment of A
prior to activation of B
, and continuing to run software supporting version A
until it is inactive)
In the event that you wish to disable a particular soft fork, despite it being active on the signet you're following, you can deactivate it by using the -renounce
option; eg bitcoind -renounce=checktemplateverify
.