|
| 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