BIN-2024-0002 | Heretical Deployments |
---|---|
Revision | 001 (2024-01-17) |
Author | Anthony Towns <aj@erisian.com.au> |
Layer | Consensus (deployment activation for signet) |
Status | Active |
License | BSD-3-Clause |
Deploying an experimental soft fork for testing on a global signet has different requirements to deploying a soft fork 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 headerstart_time
-- used to control when signalling can begintimeout
-- 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 27-bit BINANA number of the soft fork as follows:binana_id = ((year % 32) << 22) | ((number % 16384) << 8) | (revision % 256)
signal_activate = 0x6000_0000 | binana_id
signal_abandon = 0x4000_0000 | binana_id
A state machine similar to BIP9 is used to coordinate activation based on these parameters, with the state updating every 432 blocks (3 days)
-
The following states are defined:
DEFINED
- inactive, initial state, waiting forstart_time
STARTED
- inactive, waiting for signal ortimeout
LOCKED_IN
- inactive, will be active next periodACTIVE
- active, waiting forsignal_abandon
or timeoutDEACTIVATING
- active, but will be abandoned next periodABANDONED
- inactive, terminal state
-
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 reachedSTARTED -> 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)
The following notes are specific to developers and users working with the Bitcoin Inquisition node software.
As a proposer of a new soft fork, the idea is that you set deployment parameters like this:
consensus.vDeployments[Consensus::DEPLOYMENT_CHECKTEMPLATEVERIFY] = SetupDeployment{
.binana_year = 2024,
.binana_id = 000,
.binana_revision = 000,
.start = 1654041600, // 2022-06-01
.timeout = 1969660800, // 2032-06-01
};
The start
time and binana_revision
should be updated each time the proposal is updated in any way that renders the proposal not fully compatible with prior revisions. 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 proposal text should usually be updated before code is committed and merged.
With 256 values for binana_revision
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 consensus 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 binana_revision
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 beLOCKED_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
.