Skip to content

Commit 21bf0bf

Browse files
Merge pull request #1301 from Concordium/p7-to-p8-update
Introduce the P7 to P8 update.
2 parents f265d3f + 6579594 commit 21bf0bf

File tree

3 files changed

+130
-3
lines changed

3 files changed

+130
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased changes
44

5+
- Add P7 -> P8 update.
56
- Automatically suspend validators from the consensus that missed too many
67
rounds in the previous payday.
78
- Add support for suspend/resume to validator configuration updates.

concordium-consensus/src/Concordium/ProtocolUpdate/P7.hs

+9-3
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,33 @@ module Concordium.ProtocolUpdate.P7 (
88
updateNextProtocolVersion,
99
) where
1010

11-
import Control.Monad.State
11+
import Control.Monad.State hiding (get)
1212
import qualified Data.HashMap.Strict as HM
1313
import Data.Serialize
1414

1515
import qualified Concordium.Crypto.SHA256 as SHA256
1616
import Concordium.Types
1717
import Concordium.Types.Updates
1818

19+
import qualified Concordium.Genesis.Data.P8 as P8
1920
import Concordium.GlobalState.BlockState
2021
import qualified Concordium.GlobalState.Persistent.BlockState as PBS
2122
import Concordium.GlobalState.Types
2223
import qualified Concordium.GlobalState.Types as GSTypes
2324
import Concordium.KonsensusV1.TreeState.Implementation
2425
import Concordium.KonsensusV1.TreeState.Types
26+
import qualified Concordium.ProtocolUpdate.P7.ProtocolP8 as ProtocolP8
2527
import qualified Concordium.ProtocolUpdate.P7.Reboot as Reboot
2628

2729
-- | Updates that are supported from protocol version P7.
28-
data Update = Reboot
30+
data Update
31+
= Reboot
32+
| ProtocolP8 P8.ProtocolUpdateData
2933
deriving (Show)
3034

3135
-- | Hash map for resolving updates from their specification hash.
3236
updates :: HM.HashMap SHA256.Hash (Get Update)
33-
updates = HM.fromList [(Reboot.updateHash, return Reboot)]
37+
updates = HM.fromList [(Reboot.updateHash, return Reboot), (ProtocolP8.updateHash, ProtocolP8 <$> get)]
3438

3539
-- | Determine if a 'ProtocolUpdate' corresponds to a supported update type.
3640
checkUpdate :: ProtocolUpdate -> Either String Update
@@ -53,9 +57,11 @@ updateRegenesis ::
5357
BlockPointer (MPV m) ->
5458
m (PVInit m)
5559
updateRegenesis Reboot = Reboot.updateRegenesis
60+
updateRegenesis (ProtocolP8 protocolUpdateData) = ProtocolP8.updateRegenesis protocolUpdateData
5661

5762
-- | Determine the protocol version the update will update to.
5863
updateNextProtocolVersion ::
5964
Update ->
6065
SomeProtocolVersion
6166
updateNextProtocolVersion Reboot{} = SomeProtocolVersion SP7
67+
updateNextProtocolVersion ProtocolP8{} = SomeProtocolVersion SP8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
{-# LANGUAGE DataKinds #-}
2+
{-# LANGUAGE OverloadedStrings #-}
3+
{-# LANGUAGE TypeFamilies #-}
4+
5+
-- | This module implements the P7.ProtocolP8 protocol update.
6+
-- This protocol update is valid at protocol version P7, and updates
7+
-- to protocol version P8.
8+
--
9+
-- This produces a new 'RegenesisDataP8' using the 'GDP8RegenesisFromP7' constructor,
10+
-- as follows:
11+
--
12+
-- * 'genesisCore':
13+
--
14+
-- * 'genesisTime' is the timestamp of the last finalized block of the previous chain.
15+
-- * 'genesisEpochDuration' is taken from the previous genesis.
16+
-- * 'genesisSignatureThreshold' is taken from the previous genesis.
17+
--
18+
-- * 'genesisFirstGenesis' is either:
19+
--
20+
-- * the hash of the genesis block of the previous chain, if it is a 'GDP7Initial'; or
21+
-- * the 'genesisFirstGenesis' value of the genesis block of the previous chain, if it
22+
-- is a 'GDP7Regenesis'.
23+
--
24+
-- * 'genesisPreviousGenesis' is the hash of the previous genesis block.
25+
--
26+
-- * 'genesisTerminalBlock' is the hash of the last finalized block of the previous chain.
27+
--
28+
-- * 'genesisStateHash' is the state hash of the last finalized block of the previous chain.
29+
--
30+
-- * 'genesisMigration' is derived from the data provided to the protocol update, which is the
31+
-- validator score parameters
32+
--
33+
-- The block state is taken from the last finalized block of the previous chain. It is updated
34+
-- as part of the state migration, which makes the following changes:
35+
--
36+
-- * The seed state is migrated as follows:
37+
--
38+
-- * The current epoch is reset to zero.
39+
-- * The current and updated leadership election nonce are set to the hash of
40+
-- @"Regenesis" <> encode oldUpdatedNonce@.
41+
-- * The trigger block time is kept the same, meaning that the epoch will transition as soon
42+
-- as possible.
43+
-- * The epoch transition triggered flag is set.
44+
-- * The shutdown triggered flag is cleared.
45+
--
46+
-- * The old current epoch is subtracted from the next payday epoch.
47+
--
48+
-- * The protocol update queue is emptied during the migration.
49+
--
50+
-- Note that, the initial epoch of the new chain is not considered
51+
-- a new epoch for the purposes of block rewards and baker/finalization committee determination.
52+
-- In particular, the timing of the next payday will be the same as if the protocol update
53+
-- had not happened. (For instance, if it would have happened at the start of the next epoch
54+
-- prior to the protocol update, after the update it will happen at the start of epoch 1.
55+
-- The trigger block time in epoch 0 of the new consensus is the same as the trigger block
56+
-- time in the final epoch of the old consensus.)
57+
-- Furthermore, the bakers from the final epoch of the previous chain are also the bakers for the
58+
-- initial epoch of the new chain.
59+
module Concordium.ProtocolUpdate.P7.ProtocolP8 where
60+
61+
import Control.Monad.State
62+
import Lens.Micro.Platform
63+
64+
import qualified Concordium.Crypto.SHA256 as SHA256
65+
import qualified Concordium.Genesis.Data as GenesisData
66+
import qualified Concordium.Genesis.Data.BaseV1 as BaseV1
67+
import qualified Concordium.Genesis.Data.P8 as P8
68+
import Concordium.GlobalState.BlockState
69+
import qualified Concordium.GlobalState.Persistent.BlockState as PBS
70+
import Concordium.GlobalState.Types
71+
import qualified Concordium.GlobalState.Types as GSTypes
72+
import qualified Concordium.KonsensusV1.TreeState.Implementation as TreeState
73+
import Concordium.KonsensusV1.TreeState.Types
74+
import Concordium.KonsensusV1.Types
75+
import Concordium.Types.HashableTo (getHash)
76+
import Concordium.Types.ProtocolVersion
77+
78+
-- | The hash that identifies a update from P7 to P8 protocol.
79+
-- This is the hash of the published specification document.
80+
updateHash :: SHA256.Hash
81+
updateHash = read "f12e20b6936a6b1b736e95715e1654b92adb4226ef7601b4183895bee563f9da"
82+
83+
-- | Construct the genesis data for a P7.ProtocolP8 update.
84+
-- This takes the terminal block of the old chain which is used as the basis for constructing
85+
-- the new genesis block.
86+
updateRegenesis ::
87+
( MPV m ~ 'P7,
88+
BlockStateStorage m,
89+
MonadState (TreeState.SkovData (MPV m)) m,
90+
GSTypes.BlockState m ~ PBS.HashedPersistentBlockState (MPV m)
91+
) =>
92+
P8.ProtocolUpdateData ->
93+
-- | The terminal block of the old chain.
94+
BlockPointer 'P7 ->
95+
m (PVInit m)
96+
updateRegenesis protocolUpdateData terminalBlock = do
97+
-- Genesis time is the timestamp of the terminal block
98+
let regenesisTime = blockTimestamp terminalBlock
99+
-- Core parameters are derived from the old genesis, apart from genesis time which is set for
100+
-- the time of the terminal block.
101+
gMetadata <- use TreeState.genesisMetadata
102+
BaseV1.CoreGenesisParametersV1{..} <- gmParameters <$> use TreeState.genesisMetadata
103+
let core =
104+
BaseV1.CoreGenesisParametersV1
105+
{ BaseV1.genesisTime = regenesisTime,
106+
..
107+
}
108+
-- genesisFirstGenesis is the block hash of the previous genesis, if it is initial,
109+
-- or the genesisFirstGenesis of the previous genesis otherwise.
110+
let genesisFirstGenesis = gmFirstGenesisHash gMetadata
111+
genesisPreviousGenesis = gmCurrentGenesisHash gMetadata
112+
genesisTerminalBlock = getHash terminalBlock
113+
let regenesisBlockState = bpState terminalBlock
114+
genesisStateHash <- getStateHash regenesisBlockState
115+
let genesisMigration =
116+
P8.StateMigrationData
117+
{ migrationProtocolUpdateData = protocolUpdateData
118+
}
119+
let newGenesis = GenesisData.RGDP8 $ P8.GDP8RegenesisFromP7{genesisRegenesis = BaseV1.RegenesisDataV1{genesisCore = core, ..}, ..}
120+
return (PVInit newGenesis (GenesisData.StateMigrationParametersP7ToP8 genesisMigration) (bmHeight $ bpInfo terminalBlock))

0 commit comments

Comments
 (0)