Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add protocol version 7 and genesis data #474

Merged
merged 2 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions concordium-base.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ library
Concordium.Genesis.Data.P4
Concordium.Genesis.Data.P5
Concordium.Genesis.Data.P6
Concordium.Genesis.Data.P7
Concordium.Genesis.Parameters
Concordium.GRPC2
Concordium.ID.Account
Expand Down
2 changes: 1 addition & 1 deletion concordium-grpc-api
3 changes: 3 additions & 0 deletions haskell-bins/genesis/Genesis.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import qualified Concordium.Genesis.Data.P3 as P3
import qualified Concordium.Genesis.Data.P4 as P4
import qualified Concordium.Genesis.Data.P5 as P5
import qualified Concordium.Genesis.Data.P6 as P6
import qualified Concordium.Genesis.Data.P7 as P7
import Concordium.Genesis.Parameters
import Concordium.Types
import Concordium.Types.AnonymityRevokers
Expand Down Expand Up @@ -242,6 +243,8 @@ main =
gd@(GDP5 P5.GDP5Initial{..}) -> printInitial SP5 (genesisBlockHash gd) (CGPV0 genesisCore) genesisInitialState
SP6 -> case gdata of
gd@(GDP6 P6.GDP6Initial{..}) -> printInitial SP6 (genesisBlockHash gd) (CGPV1 genesisCore) genesisInitialState
SP7 -> case gdata of
gd@(GDP7 P7.GDP7Initial{..}) -> printInitial SP7 (genesisBlockHash gd) (CGPV1 genesisCore) genesisInitialState

printInitial :: SProtocolVersion pv -> BlockHash -> VersionedCoreGenesisParameters -> GDBase.GenesisState pv -> IO ()
printInitial spv gh vcgp GDBase.GenesisState{..} = do
Expand Down
5 changes: 4 additions & 1 deletion haskell-src/Concordium/Constants.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ maxPayloadSize SP3 = 100 * 1024 -- 100kB
maxPayloadSize SP4 = maxWasmModuleSizeV1 + 1 + 4 + 4 -- +1 for the payload tag, +4 for the length, +4 for the module version
maxPayloadSize SP5 = maxPayloadSize SP4
maxPayloadSize SP6 = maxPayloadSize SP4
maxPayloadSize SP7 = maxPayloadSize SP4

-- * Web assembly related constants

Expand All @@ -33,7 +34,8 @@ maxParameterLen SP2 = 1024
maxParameterLen SP3 = 1024
maxParameterLen SP4 = 1024
maxParameterLen SP5 = 65535
maxParameterLen SP6 = 65535
maxParameterLen SP6 = maxParameterLen SP5
maxParameterLen SP7 = maxParameterLen SP5

-- | Whether the number of logs and size of return values should be limited.
-- The limits have been removed in P5 and onward.
Expand All @@ -44,6 +46,7 @@ limitLogsAndReturnValues SP3 = True
limitLogsAndReturnValues SP4 = True
limitLogsAndReturnValues SP5 = False
limitLogsAndReturnValues SP6 = False
limitLogsAndReturnValues SP7 = False

-- | Maximum module size of a V0 module.
maxWasmModuleSizeV0 :: Word32
Expand Down
1 change: 1 addition & 0 deletions haskell-src/Concordium/GRPC2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ instance ToProto ProtocolVersion where
toProto P4 = Proto.PROTOCOL_VERSION_4
toProto P5 = Proto.PROTOCOL_VERSION_5
toProto P6 = Proto.PROTOCOL_VERSION_6
toProto P7 = Proto.PROTOCOL_VERSION_7

instance ToProto QueryTypes.NextAccountNonce where
type Output QueryTypes.NextAccountNonce = Proto.NextAccountSequenceNumber
Expand Down
19 changes: 19 additions & 0 deletions haskell-src/Concordium/Genesis/Data.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import qualified Concordium.Genesis.Data.P3 as P3
import qualified Concordium.Genesis.Data.P4 as P4
import qualified Concordium.Genesis.Data.P5 as P5
import qualified Concordium.Genesis.Data.P6 as P6
import qualified Concordium.Genesis.Data.P7 as P7
import Concordium.Types
import Concordium.Types.Parameters

Expand All @@ -63,6 +64,7 @@ newtype instance GenesisData 'P3 = GDP3 {unGDP3 :: P3.GenesisDataP3}
newtype instance GenesisData 'P4 = GDP4 {unGDP4 :: P4.GenesisDataP4}
newtype instance GenesisData 'P5 = GDP5 {unGDP5 :: P5.GenesisDataP5}
newtype instance GenesisData 'P6 = GDP6 {unGDP6 :: P6.GenesisDataP6}
newtype instance GenesisData 'P7 = GDP7 {unGDP7 :: P7.GenesisDataP7}

-- | Data family for regenesis data. This has been chosen to be a data family, as
-- opposed to a type family principally so that it is injective, i.e., so that
Expand All @@ -75,6 +77,7 @@ newtype instance Regenesis 'P3 = RGDP3 {unRGP3 :: P3.RegenesisP3}
newtype instance Regenesis 'P4 = RGDP4 {unRGP4 :: P4.RegenesisP4}
newtype instance Regenesis 'P5 = RGDP5 {unRGP5 :: P5.RegenesisP5}
newtype instance Regenesis 'P6 = RGDP6 {unRGP6 :: P6.RegenesisP6}
newtype instance Regenesis 'P7 = RGDP7 {unRGP7 :: P7.RegenesisP7}

instance (IsProtocolVersion pv, IsConsensusV0 pv) => BasicGenesisData (GenesisData pv) where
gdGenesisTime = case protocolVersion @pv of
Expand Down Expand Up @@ -158,6 +161,7 @@ instance (IsProtocolVersion pv) => Eq (GenesisData pv) where
SP4 -> (==) `on` unGDP4
SP5 -> (==) `on` unGDP5
SP6 -> (==) `on` unGDP6
SP7 -> (==) `on` unGDP7

instance (IsProtocolVersion pv) => Serialize (GenesisData pv) where
get = case protocolVersion @pv of
Expand All @@ -167,6 +171,7 @@ instance (IsProtocolVersion pv) => Serialize (GenesisData pv) where
SP4 -> GDP4 <$> P4.getGenesisDataV6
SP5 -> GDP5 <$> P5.getGenesisDataV7
SP6 -> GDP6 <$> P6.getGenesisDataV8
SP7 -> GDP7 <$> P7.getGenesisDataV9

put = case protocolVersion @pv of
SP1 -> P1.putGenesisDataV3 . unGDP1
Expand All @@ -175,6 +180,7 @@ instance (IsProtocolVersion pv) => Serialize (GenesisData pv) where
SP4 -> P4.putGenesisDataV6 . unGDP4
SP5 -> P5.putGenesisDataV7 . unGDP5
SP6 -> P6.putGenesisDataV8 . unGDP6
SP7 -> P7.putGenesisDataV9 . unGDP7

-- | Deserialize 'GenesisConfiguration' given the hash of the genesis. If
-- 'GenesisData' or 'Regenesis' is decodable (using its Serialize instance) from a given
Expand Down Expand Up @@ -202,6 +208,7 @@ getVersionedGenesisData = case protocolVersion @pv of
SP4 -> GDP4 <$> P4.getVersionedGenesisData
SP5 -> GDP5 <$> P5.getVersionedGenesisData
SP6 -> GDP6 <$> P6.getVersionedGenesisData
SP7 -> GDP7 <$> P7.getVersionedGenesisData

-- | Serialize genesis data with a version tag.
-- Each version tag must be specific to a protocol version, though more than one version tag can
Expand All @@ -225,6 +232,7 @@ putVersionedGenesisData = case protocolVersion @pv of
SP4 -> P4.putVersionedGenesisData . unGDP4
SP5 -> P5.putVersionedGenesisData . unGDP5
SP6 -> P6.putVersionedGenesisData . unGDP6
SP7 -> P7.putVersionedGenesisData . unGDP7

-- | Generate the block hash of a genesis block with the given genesis data.
-- This is based on the presumption that a block hash is computed from a byte string
Expand All @@ -237,6 +245,7 @@ genesisBlockHash = case protocolVersion @pv of
SP4 -> P4.genesisBlockHash . unGDP4
SP5 -> P5.genesisBlockHash . unGDP5
SP6 -> P6.genesisBlockHash . unGDP6
SP7 -> P7.genesisBlockHash . unGDP7

-- | Generate the block hash of a regenesis block with the given regenesis data.
regenesisBlockHash :: forall pv. (IsProtocolVersion pv) => Regenesis pv -> BlockHash
Expand All @@ -247,6 +256,7 @@ regenesisBlockHash = case protocolVersion @pv of
SP4 -> P4.regenesisBlockHash . unRGP4
SP5 -> P5.regenesisBlockHash . unRGP5
SP6 -> P6.regenesisBlockHash . unRGP6
SP7 -> P7.regenesisBlockHash . unRGP7

-- | Hash of the initial genesis of the chain to which the given genesis data belongs.
-- Genesis created as part of a protocol update records the genesis
Expand All @@ -259,6 +269,7 @@ firstGenesisBlockHash = case protocolVersion @pv of
SP4 -> P4.firstGenesisBlockHash . unRGP4
SP5 -> P5.firstGenesisBlockHash . unRGP5
SP6 -> P6.firstGenesisBlockHash . unRGP6
SP7 -> P7.firstGenesisBlockHash . unRGP7

-- | Tag of the genesis variant used for serialization. This tag determines
-- whether the genesis data is, e.g., initial genesis, or regenesis.
Expand All @@ -270,6 +281,7 @@ genesisVariantTag = case protocolVersion @pv of
SP4 -> P4.genesisVariantTag . unGDP4
SP5 -> P5.genesisVariantTag . unGDP5
SP6 -> P6.genesisVariantTag . unGDP6
SP7 -> P7.genesisVariantTag . unGDP7

-- | Tag of the regenesis variant used for serialization. This tag determines
-- whether the genesis data is, e.g., initial genesis, or regenesis and allows
Expand All @@ -283,6 +295,7 @@ regenesisVariantTag = case protocolVersion @pv of
SP4 -> P4.regenesisVariantTag . unRGP4
SP5 -> P5.regenesisVariantTag . unRGP5
SP6 -> P6.regenesisVariantTag . unRGP6
SP7 -> P7.regenesisVariantTag . unRGP7

-- | A dependent pair of a protocol version and genesis data.
data PVGenesisData = forall pv. (IsProtocolVersion pv) => PVGenesisData (GenesisData pv)
Expand All @@ -303,6 +316,7 @@ getPVGenesisData = do
6 -> PVGenesisData . GDP4 <$> P4.getGenesisDataV6
7 -> PVGenesisData . GDP5 <$> P5.getGenesisDataV7
8 -> PVGenesisData . GDP6 <$> P6.getGenesisDataV8
9 -> PVGenesisData . GDP7 <$> P7.getGenesisDataV9
n -> fail $ "Unsupported genesis version: " ++ show n

-- | Deserialize a genesis data version tag and return the associated protocol
Expand All @@ -318,6 +332,7 @@ getPVGenesisDataPV = do
6 -> return $ SomeProtocolVersion SP4
7 -> return $ SomeProtocolVersion SP5
8 -> return $ SomeProtocolVersion SP6
9 -> return $ SomeProtocolVersion SP7
n -> fail $ "Unsupported genesis version: " ++ show n

-- | Serialize genesis data with a version tag. This is a helper function that
Expand Down Expand Up @@ -353,6 +368,8 @@ data StateMigrationParameters (p1 :: ProtocolVersion) (p2 :: ProtocolVersion) wh
StateMigrationParametersP4ToP5 :: StateMigrationParameters 'P4 'P5
-- | The state is migrated from protocol version 'P5' to 'P6'.
StateMigrationParametersP5ToP6 :: P6.StateMigrationData -> StateMigrationParameters 'P5 'P6
-- | The state is migrated from protocol version 'P6' to 'P7'.
StateMigrationParametersP6ToP7 :: StateMigrationParameters 'P6 'P7

-- | Extract the genesis configuration from the genesis data.
genesisConfiguration :: (IsProtocolVersion pv, IsConsensusV0 pv) => GenesisData pv -> GenesisConfiguration
Expand Down Expand Up @@ -382,6 +399,7 @@ genesisCoreParametersV1 ::
BaseV1.CoreGenesisParametersV1
genesisCoreParametersV1 = case protocolVersion @pv of
SP6 -> \(GDP6 genData) -> P6.genesisCore genData
SP7 -> \(GDP7 genData) -> P7.genesisCore genData

-- | Extract the V1 core genesis parameters from the regenesis data.
regenesisCoreParametersV1 ::
Expand All @@ -391,3 +409,4 @@ regenesisCoreParametersV1 ::
BaseV1.CoreGenesisParametersV1
regenesisCoreParametersV1 = case protocolVersion @pv of
SP6 -> \(RGDP6 genData) -> BaseV1.genesisCore $ P6.genesisRegenesis genData
SP7 -> \(RGDP7 genData) -> BaseV1.genesisCore $ P7.genesisRegenesis genData
143 changes: 143 additions & 0 deletions haskell-src/Concordium/Genesis/Data/P7.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}

-- | This module defines the genesis data format for the 'P7' protocol version.
module Concordium.Genesis.Data.P7 where

import Data.Serialize
import Data.Word

import Concordium.Common.Version
import qualified Concordium.Crypto.SHA256 as Hash
import qualified Concordium.Genesis.Data.Base as Base
import qualified Concordium.Genesis.Data.BaseV1 as BaseV1
import Concordium.Types

-- | Initial genesis data for the P7 protocol version.
data GenesisDataP7 = GDP7Initial
{ -- | The immutable genesis parameters.
genesisCore :: !BaseV1.CoreGenesisParametersV1,
-- | Serialized initial block state.
genesisInitialState :: !(Base.GenesisState 'P7)
}
deriving (Eq, Show)

-- | The regenesis represents a reset of the protocol with a new genesis block.
-- This does not include the full new state, but only its hash.
--
-- The relationship between the new state and the state of the
-- terminal block of the old chain should be defined by the
-- chain update mechanism used.
--
-- There are two variants, one when migrating from 'P6' to 'P7' and
-- one from 'P7' to 'P7'.
data RegenesisP7
= GDP7Regenesis {genesisRegenesis :: !BaseV1.RegenesisDataV1}
| GDP7RegenesisFromP6
{ genesisRegenesis :: !BaseV1.RegenesisDataV1,
genesisMigration :: ()
}
deriving (Eq, Show)

-- | Deserialize genesis data in the V9 format.
getGenesisDataV9 :: Get GenesisDataP7
getGenesisDataV9 =
getWord8 >>= \case
0 -> do
genesisCore <- get
genesisInitialState <- get
return GDP7Initial{..}
_ -> fail "Unrecognized P7 genesis data type."

getRegenesisData :: Get RegenesisP7
getRegenesisData =
getWord8 >>= \case
1 -> do
genesisRegenesis <- get
return GDP7Regenesis{..}
2 -> do
genesisRegenesis <- get
genesisMigration <- get
return GDP7RegenesisFromP6{..}
_ -> fail "Unrecognized P7 regenesis data type."

-- | Serialize genesis data in the V9 format.
putGenesisDataV9 :: Putter GenesisDataP7
putGenesisDataV9 GDP7Initial{..} = do
putWord8 0
put genesisCore
put genesisInitialState

-- | Deserialize genesis data with a version tag. The expected version tag is 9
-- and this must be distinct from version tags of other genesis data formats.
getVersionedGenesisData :: Get GenesisDataP7
getVersionedGenesisData =
getVersion >>= \case
9 -> getGenesisDataV9
n -> fail $ "Unsupported genesis data version for P7 genesis: " ++ show n

-- | Serialize genesis data with a version tag.
-- This will use the V9 format.
putVersionedGenesisData :: Putter GenesisDataP7
putVersionedGenesisData gd = do
putVersion 9
putGenesisDataV9 gd

-- | Compute the block hash of the genesis block with the given genesis data.
-- Every block hash is derived from a message that begins with the block slot,
-- which is 0 for genesis blocks.
limemloh marked this conversation as resolved.
Show resolved Hide resolved
--
-- NB: For the regenesis variant the serialized state is not included in the
-- block hash, only the state hash is. This makes it possible to optimize the
-- format in the future since it does not have protocol defined meaning. In
-- contrast, for the initial P7 genesis the initial state is hashed as is.
genesisBlockHash :: GenesisDataP7 -> BlockHash
genesisBlockHash GDP7Initial{..} = BlockHash . Hash.hashLazy . runPutLazy $ do
put genesisSlot
put P7
putWord8 0 -- initial variant
put genesisCore
put genesisInitialState

-- | Compute the block hash of the regenesis data as defined by the specified
-- protocol. This becomes the block hash of the genesis block of the new chain
-- after the protocol update.
regenesisBlockHash :: RegenesisP7 -> BlockHash
regenesisBlockHash GDP7Regenesis{genesisRegenesis = BaseV1.RegenesisDataV1{..}} = BlockHash . Hash.hashLazy . runPutLazy $ do
put genesisSlot
put P7
putWord8 1 -- regenesis variant
put genesisCore
put genesisFirstGenesis
put genesisPreviousGenesis
put genesisTerminalBlock
put genesisStateHash
regenesisBlockHash GDP7RegenesisFromP6{genesisRegenesis = BaseV1.RegenesisDataV1{..}, ..} = BlockHash . Hash.hashLazy . runPutLazy $ do
put genesisSlot
put P7
putWord8 2 -- migration from P6 variant
put genesisCore
put genesisFirstGenesis
put genesisPreviousGenesis
put genesisTerminalBlock
put genesisStateHash
put genesisMigration

-- | The hash of the first genesis block in the chain.
firstGenesisBlockHash :: RegenesisP7 -> BlockHash
firstGenesisBlockHash GDP7Regenesis{genesisRegenesis = BaseV1.RegenesisDataV1{..}} = genesisFirstGenesis
firstGenesisBlockHash GDP7RegenesisFromP6{genesisRegenesis = BaseV1.RegenesisDataV1{..}} = genesisFirstGenesis

-- | Tag of the genesis data used for serialization.
genesisVariantTag :: GenesisDataP7 -> Word8
genesisVariantTag GDP7Initial{} = 0

-- | Tag of the regenesis variant used for serialization. This tag determines
-- whether the genesis data is, e.g., initial genesis, or regenesis and allows
-- us to deserialize one or the other from the data without knowing a priori what
-- the data is.
regenesisVariantTag :: RegenesisP7 -> Word8
regenesisVariantTag GDP7Regenesis{} = 1
regenesisVariantTag GDP7RegenesisFromP6{} = 2
Loading