From 469efc983952fd1d48da70e604449f00b29d5d91 Mon Sep 17 00:00:00 2001 From: drsk Date: Thu, 19 Sep 2024 14:14:15 +0200 Subject: [PATCH] fixes after rebase --- .gitmodules | 2 +- concordium-base | 1 - .../src/Concordium/GlobalState/BakerInfo.hs | 5 +- .../GlobalState/Persistent/BlockState.hs | 17 +-- .../src/Concordium/ProtocolUpdate/P8.hs | 61 ++++++++++ .../Concordium/ProtocolUpdate/P8/Reboot.hs | 110 ++++++++++++++++++ .../src/Concordium/ProtocolUpdate/V1.hs | 6 + .../src/Concordium/Scheduler/Runner.hs | 4 +- concordium-node/src/consensus_ffi/ffi.rs | 5 +- 9 files changed, 196 insertions(+), 15 deletions(-) delete mode 160000 concordium-base create mode 100644 concordium-consensus/src/Concordium/ProtocolUpdate/P8.hs create mode 100644 concordium-consensus/src/Concordium/ProtocolUpdate/P8/Reboot.hs diff --git a/.gitmodules b/.gitmodules index d1b21f6ff5..305883cf05 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = ../noiseexplorer_xx.git [submodule "concordium-base"] path = concordium-base - url = ../concordium-base.git + url = ../concordium-base [submodule "concordium-consensus/haskell-lmdb"] path = concordium-consensus/haskell-lmdb url = ../haskell-lmdb.git diff --git a/concordium-base b/concordium-base deleted file mode 160000 index 60710de451..0000000000 --- a/concordium-base +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 60710de451ad197fe127a5e0a8f50997ea9d594e diff --git a/concordium-consensus/src/Concordium/GlobalState/BakerInfo.hs b/concordium-consensus/src/Concordium/GlobalState/BakerInfo.hs index 830becb444..2f28fb1ff9 100644 --- a/concordium-consensus/src/Concordium/GlobalState/BakerInfo.hs +++ b/concordium-consensus/src/Concordium/GlobalState/BakerInfo.hs @@ -245,7 +245,8 @@ validatorRemove = vuMetadataURL = Nothing, vuTransactionFeeCommission = Nothing, vuBakingRewardCommission = Nothing, - vuFinalizationRewardCommission = Nothing + vuFinalizationRewardCommission = Nothing, + vuSuspend = Nothing } -- | Failure modes when configuring a validator. @@ -276,6 +277,8 @@ data BakerConfigureUpdateChange | BakerConfigureTransactionFeeCommission !AmountFraction | BakerConfigureBakingRewardCommission !AmountFraction | BakerConfigureFinalizationRewardCommission !AmountFraction + | BakerConfigureSuspended + | BakerConfigureResumed deriving (Eq, Show) -- | Parameters for adding a delegator. diff --git a/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs b/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs index bd78cae576..bedfa82e21 100644 --- a/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs +++ b/concordium-consensus/src/Concordium/GlobalState/Persistent/BlockState.hs @@ -1835,7 +1835,7 @@ newUpdateValidator pbs curTimestamp ai vu@ValidatorUpdate{..} = do >>= updateRestakeEarnings >>= updatePoolInfo existingBaker >>= updateCapital existingBaker - >>= updateSuspend (sSupportsValidatorSuspension (accountVersion @(AccountVersionFor pv))) + >>= updateSuspend newAccounts <- Accounts.setAccountAtIndex ai newAcc (bspAccounts newBSP) return newBSP{bspAccounts = newAccounts} (events,) <$> storePBS pbs newBSP @@ -1844,13 +1844,14 @@ newUpdateValidator pbs curTimestamp ai vu@ValidatorUpdate{..} = do -- Only do the given update if specified. ifPresent Nothing _ = return ifPresent (Just v) k = k v - updateSuspend STrue = - case bcuSuspend of - Nothing -> return return - Just b -> do - MTL.tell [if b then BakerConfigureSuspended else BakerConfigureResumed] - return $ setAccountSuspended b - updateSuspend SFalse = return return + updateSuspend = + ifPresent vuSuspend $ \suspend (bsp, acc) -> do + case sSupportsValidatorSuspension (accountVersion @(AccountVersionFor pv)) of + STrue -> do + acc1 <- setAccountSuspended suspend acc + MTL.tell [if suspend then BakerConfigureSuspended else BakerConfigureResumed] + return (bsp, acc1) + SFalse -> return (bsp, acc) updateKeys oldBaker = ifPresent vuKeys $ \keys (bsp, acc) -> do let oldAggrKey = oldBaker ^. BaseAccounts.bakerAggregationVerifyKey bsp1 <- diff --git a/concordium-consensus/src/Concordium/ProtocolUpdate/P8.hs b/concordium-consensus/src/Concordium/ProtocolUpdate/P8.hs new file mode 100644 index 0000000000..f78b3d2c69 --- /dev/null +++ b/concordium-consensus/src/Concordium/ProtocolUpdate/P8.hs @@ -0,0 +1,61 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE TypeFamilies #-} + +module Concordium.ProtocolUpdate.P8 ( + Update (..), + checkUpdate, + updateRegenesis, + updateNextProtocolVersion, +) where + +import Control.Monad.State +import qualified Data.HashMap.Strict as HM +import Data.Serialize + +import qualified Concordium.Crypto.SHA256 as SHA256 +import Concordium.Types +import Concordium.Types.Updates + +import Concordium.GlobalState.BlockState +import qualified Concordium.GlobalState.Persistent.BlockState as PBS +import Concordium.GlobalState.Types +import qualified Concordium.GlobalState.Types as GSTypes +import Concordium.KonsensusV1.TreeState.Implementation +import Concordium.KonsensusV1.TreeState.Types +import qualified Concordium.ProtocolUpdate.P8.Reboot as Reboot + +-- | Updates that are supported from protocol version P7. +data Update = Reboot + deriving (Show) + +-- | Hash map for resolving updates from their specification hash. +updates :: HM.HashMap SHA256.Hash (Get Update) +updates = HM.fromList [(Reboot.updateHash, return Reboot)] + +-- | Determine if a 'ProtocolUpdate' corresponds to a supported update type. +checkUpdate :: ProtocolUpdate -> Either String Update +checkUpdate ProtocolUpdate{..} = case HM.lookup puSpecificationHash updates of + Nothing -> Left "Specification hash does not correspond to a known protocol update." + Just updateGet -> case runGet updateGet puSpecificationAuxiliaryData of + Left err -> Left $! "Could not deserialize auxiliary data: " ++ err + Right update -> return update + +-- | Construct the genesis data for a P7 update. +updateRegenesis :: + ( MPV m ~ 'P8, + BlockStateStorage m, + MonadState (SkovData (MPV m)) m, + GSTypes.BlockState m ~ PBS.HashedPersistentBlockState (MPV m) + ) => + -- | The update taking effect. + Update -> + -- | The terminal block of the old chain. + BlockPointer (MPV m) -> + m (PVInit m) +updateRegenesis Reboot = Reboot.updateRegenesis + +-- | Determine the protocol version the update will update to. +updateNextProtocolVersion :: + Update -> + SomeProtocolVersion +updateNextProtocolVersion Reboot{} = SomeProtocolVersion SP8 diff --git a/concordium-consensus/src/Concordium/ProtocolUpdate/P8/Reboot.hs b/concordium-consensus/src/Concordium/ProtocolUpdate/P8/Reboot.hs new file mode 100644 index 0000000000..a5192cfeb1 --- /dev/null +++ b/concordium-consensus/src/Concordium/ProtocolUpdate/P8/Reboot.hs @@ -0,0 +1,110 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TypeFamilies #-} + +-- | This module implements the P8.Reboot protocol update. +-- This protocol update is valid at protocol version P8, and updates +-- to protocol version P8. +-- This produces a new 'RegenesisDataP8 using the 'GDP8Regenesis' constructor, +-- as follows: +-- +-- * 'genesisCore': +-- +-- * 'genesisTime' is the timestamp of the last finalized block of the previous chain. +-- * 'genesisEpochDuration' is taken from the previous genesis. +-- * 'genesisSignatureThreshold' is taken from the previous genesis. +-- +-- * 'genesisFirstGenesis' is either: +-- +-- * the hash of the genesis block of the previous chain, if it is a 'GDP8Initial'; or +-- * the 'genesisFirstGenesis' value of the genesis block of the previous chain, if it +-- is a 'GDP6Regenesis'. +-- +-- * 'genesisPreviousGenesis' is the hash of the previous genesis block. +-- +-- * 'genesisTerminalBlock' is the hash of the last finalized block of the previous chain. +-- +-- * 'genesisStateHash' is the state hash of the last finalized block of the previous chain. +-- +-- The block state is taken from the last finalized block of the previous chain. It is updated +-- as part of the state migration, which makes the following changes: +-- +-- * The seed state is migrated as follows: +-- +-- * The current epoch is reset to zero. +-- * The current and updated leadership election nonce are set to the hash of +-- @"Regenesis" <> encode oldUpdatedNonce@. +-- * The trigger block time is kept the same, meaning that the epoch will transition as soon +-- as possible. +-- * The epoch transition triggered flag is set. +-- * The shutdown triggered flag is cleared. +-- +-- * The old current epoch is subtracted from the next payday epoch. +-- +-- * The protocol update queue is emptied during the migration. +-- +-- Note that, the initial epoch of the new chain is not considered +-- a new epoch for the purposes of block rewards and baker/finalization committee determination. +-- In particular, the timing of the next payday will be the same as if the protocol update +-- had not happened. (For instance, if it would have happened at the start of the next epoch +-- prior to the protocol update, after the update it will happen at the start of epoch 1. +-- The trigger block time in epoch 0 of the new consensus is the same as the trigger block +-- time in the final epoch of the old consensus.) +-- Furthermore, the bakers from the final epoch of the previous chain are also the bakers for the +-- initial epoch of the new chain. +module Concordium.ProtocolUpdate.P8.Reboot where + +import Control.Monad.State +import Lens.Micro.Platform + +import qualified Concordium.Crypto.SHA256 as SHA256 +import qualified Concordium.Genesis.Data as GenesisData +import qualified Concordium.Genesis.Data.BaseV1 as BaseV1 +import qualified Concordium.Genesis.Data.P8 as P8 +import Concordium.GlobalState.BlockState +import qualified Concordium.GlobalState.Persistent.BlockState as PBS +import Concordium.GlobalState.Types +import qualified Concordium.GlobalState.Types as GSTypes +import Concordium.KonsensusV1.TreeState.Implementation +import Concordium.KonsensusV1.TreeState.Types +import Concordium.KonsensusV1.Types +import Concordium.Types.HashableTo (getHash) +import Concordium.Types.ProtocolVersion + +-- | The hash that identifies the P8.Reboot update. +updateHash :: SHA256.Hash +updateHash = SHA256.hash "P8.Reboot" + +-- | Construct the genesis data for a P8.Reboot update. +-- This takes the terminal block of the old chain which is used as the basis for constructing +-- the new genesis block. +updateRegenesis :: + ( MPV m ~ 'P8, + BlockStateStorage m, + MonadState (SkovData (MPV m)) m, + GSTypes.BlockState m ~ PBS.HashedPersistentBlockState (MPV m) + ) => + -- | The terminal block of the old chain. + BlockPointer 'P8 -> + m (PVInit m) +updateRegenesis terminal = do + -- Genesis time is the timestamp of the terminal block + let regenesisTime = blockTimestamp terminal + -- Core parameters are derived from the old genesis, apart from genesis time which is set for + -- the time of the terminal block. + gMetadata <- use genesisMetadata + BaseV1.CoreGenesisParametersV1{..} <- gmParameters <$> use genesisMetadata + let core = + BaseV1.CoreGenesisParametersV1 + { BaseV1.genesisTime = regenesisTime, + .. + } + -- genesisFirstGenesis is the block hash of the previous genesis, if it is initial, + -- or the genesisFirstGenesis of the previous genesis otherwise. + let genesisFirstGenesis = gmFirstGenesisHash gMetadata + genesisPreviousGenesis = gmCurrentGenesisHash gMetadata + genesisTerminalBlock = getHash terminal + let regenesisBlockState = bpState terminal + genesisStateHash <- getStateHash regenesisBlockState + let newGenesis = GenesisData.RGDP8 $ P8.GDP8Regenesis{genesisRegenesis = BaseV1.RegenesisDataV1{genesisCore = core, ..}} + return (PVInit newGenesis GenesisData.StateMigrationParametersTrivial (bmHeight $ bpInfo terminal)) diff --git a/concordium-consensus/src/Concordium/ProtocolUpdate/V1.hs b/concordium-consensus/src/Concordium/ProtocolUpdate/V1.hs index d18f85fdb5..6972313189 100644 --- a/concordium-consensus/src/Concordium/ProtocolUpdate/V1.hs +++ b/concordium-consensus/src/Concordium/ProtocolUpdate/V1.hs @@ -19,15 +19,18 @@ import Concordium.KonsensusV1.TreeState.Implementation import Concordium.KonsensusV1.TreeState.Types import qualified Concordium.ProtocolUpdate.P6 as P6 import qualified Concordium.ProtocolUpdate.P7 as P7 +import qualified Concordium.ProtocolUpdate.P8 as P8 -- | Type representing currently supported protocol update types. data Update (pv :: ProtocolVersion) where UpdateP6 :: P6.Update -> Update 'P6 UpdateP7 :: P7.Update -> Update 'P7 + UpdateP8 :: P8.Update -> Update 'P8 instance Show (Update pv) where show (UpdateP6 u) = "P6." ++ show u show (UpdateP7 u) = "P7." ++ show u + show (UpdateP8 u) = "P8." ++ show u -- | Determine if a 'ProtocolUpdate' corresponds to a supported update type. checkUpdate :: forall pv. (IsProtocolVersion pv) => ProtocolUpdate -> Either String (Update pv) @@ -41,6 +44,7 @@ checkUpdate = case protocolVersion @pv of -- These ones are supported in V1. SP6 -> fmap UpdateP6 . P6.checkUpdate SP7 -> fmap UpdateP7 . P7.checkUpdate + SP8 -> fmap UpdateP8 . P8.checkUpdate -- | Construct the genesis data for a P1 update. updateRegenesis :: @@ -55,6 +59,7 @@ updateRegenesis :: m (PVInit m) updateRegenesis (UpdateP6 u) = P6.updateRegenesis u updateRegenesis (UpdateP7 u) = P7.updateRegenesis u +updateRegenesis (UpdateP8 u) = P8.updateRegenesis u -- | Determine the next protocol version for the given update. Although the same -- information can be retrieved from 'updateRegenesis', this is more efficient @@ -64,3 +69,4 @@ updateNextProtocolVersion :: SomeProtocolVersion updateNextProtocolVersion (UpdateP6 u) = P6.updateNextProtocolVersion u updateNextProtocolVersion (UpdateP7 u) = P7.updateNextProtocolVersion u +updateNextProtocolVersion (UpdateP8 u) = P8.updateNextProtocolVersion u diff --git a/concordium-consensus/src/Concordium/Scheduler/Runner.hs b/concordium-consensus/src/Concordium/Scheduler/Runner.hs index 3905cc0a42..4d7121768b 100644 --- a/concordium-consensus/src/Concordium/Scheduler/Runner.hs +++ b/concordium-consensus/src/Concordium/Scheduler/Runner.hs @@ -250,7 +250,9 @@ data PayloadJSON -- | The commission the pool owner takes on baking rewards. cbBakingRewardCommission :: !(Maybe AmountFraction), -- | The commission the pool owner takes on finalization rewards. - cbFinalizationRewardCommission :: !(Maybe AmountFraction) + cbFinalizationRewardCommission :: !(Maybe AmountFraction), + -- | Whether to suspend/resume the validator. + cbSuspend :: !(Maybe Bool) } | ConfigureDelegation { -- | The capital delegated to the pool. diff --git a/concordium-node/src/consensus_ffi/ffi.rs b/concordium-node/src/consensus_ffi/ffi.rs index 1faddf7de0..086121b6cc 100644 --- a/concordium-node/src/consensus_ffi/ffi.rs +++ b/concordium-node/src/consensus_ffi/ffi.rs @@ -1977,12 +1977,11 @@ impl ConsensusContainer { pub fn send_finalization(&self, genesis_index: u32, msg: &[u8]) -> ConsensusFfiResponse { wrap_send_data_to_c!(self, genesis_index, msg, receiveFinalizationMessage) - .check_consistent() + .check_consistent() } pub fn send_finalization_record(&self, genesis_index: u32, rec: &[u8]) -> ConsensusFfiResponse { - wrap_send_data_to_c!(self, genesis_index, rec, receiveFinalizationRecord) - .check_consistent() + wrap_send_data_to_c!(self, genesis_index, rec, receiveFinalizationRecord).check_consistent() } /// Send a transaction to consensus. Return whether the operation succeeded