Skip to content

Commit

Permalink
Merge pull request #1133 from Concordium/remove-serialization
Browse files Browse the repository at this point in the history
Remove unused state serialization code.
  • Loading branch information
td202 authored Mar 13, 2024
2 parents dddd486 + a7faf4e commit 5e8934d
Show file tree
Hide file tree
Showing 14 changed files with 0 additions and 554 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ module Concordium.GlobalState.Basic.BlockState.Account (
module Concordium.GlobalState.Basic.BlockState.Account,
) where

import Control.Monad
import Data.Coerce
import qualified Data.Map.Strict as Map
import Data.Maybe
import qualified Data.Serialize as S
import GHC.Stack (HasCallStack)
import Lens.Micro.Platform

Expand All @@ -28,12 +25,9 @@ import Concordium.GlobalState.Basic.BlockState.AccountReleaseSchedule
import Concordium.ID.Parameters
import Concordium.ID.Types
import Concordium.Types.HashableTo
import Concordium.Utils.Serialization

import Concordium.Genesis.Data
import Concordium.Types
import Concordium.Types.Accounts
import Concordium.Types.Migration

-- | Type for how a 'PersistingAccountData' value is stored as part of
-- an account. This is stored with its hash.
Expand Down Expand Up @@ -97,100 +91,6 @@ unsafeAccountDelegator = singular accountDelegator
instance HasPersistingAccountData (Account av) where
persistingAccountData = accountPersisting . unhashed

-- | Serialize an account. The serialization format may depend on the protocol version.
--
-- This format allows accounts to be stored in a reduced format by
-- eliding (some) data that can be inferred from context, or is
-- the default value. Note that there can be multiple representations
-- of the same account.
serializeAccount :: (IsAccountVersion av) => GlobalContext -> S.Putter (Account av)
serializeAccount cryptoParams acct@Account{..} = do
S.put flags
when asfExplicitAddress $ S.put _accountAddress
when asfExplicitEncryptionKey $ S.put _accountEncryptionKey
unless asfThresholdIsOne $ S.put (aiThreshold _accountVerificationKeys)
putCredentials
when asfHasRemovedCredentials $ S.put (_accountRemovedCredentials ^. unhashed)
S.put _accountNonce
S.put _accountAmount
when asfExplicitEncryptedAmount $ S.put _accountEncryptedAmount
when asfExplicitReleaseSchedule $ serializeAccountReleaseSchedule _accountReleaseSchedule
when asfHasBakerOrDelegation $ serializeAccountStake _accountStaking
where
PersistingAccountData{..} = acct ^. persistingAccountData
flags = AccountSerializationFlags{..}
initialCredId =
credId
( Map.findWithDefault
(error "Account missing initial credential")
initialCredentialIndex
_accountCredentials
)
asfExplicitAddress = _accountAddress /= addressFromRegIdRaw initialCredId
-- There is an opportunity for improvement here. We do not have to convert
-- the raw key to a structured one. We can check the equality directly on
-- the byte representation (in fact equality is defined on those). However
-- that requires a bit of work to expose the right raw values from
-- cryptographic parameters.
asfExplicitEncryptionKey = unsafeEncryptionKeyFromRaw _accountEncryptionKey /= makeEncryptionKey cryptoParams (unsafeCredIdFromRaw initialCredId)
(asfMultipleCredentials, putCredentials) = case Map.toList _accountCredentials of
[(i, cred)] | i == initialCredentialIndex -> (False, S.put cred)
_ -> (True, putSafeMapOf S.put S.put _accountCredentials)
asfExplicitEncryptedAmount = _accountEncryptedAmount /= initialAccountEncryptedAmount
asfExplicitReleaseSchedule = _accountReleaseSchedule /= emptyAccountReleaseSchedule
asfHasBakerOrDelegation = _accountStaking /= AccountStakeNone
asfThresholdIsOne = aiThreshold _accountVerificationKeys == 1
asfHasRemovedCredentials = _accountRemovedCredentials ^. unhashed /= EmptyRemovedCredentials

-- | Deserialize an account.
-- The serialization format may depend on the protocol version, and maybe migrated from one version
-- to another, using the 'StateMigrationParameters' provided.
deserializeAccount ::
forall oldpv pv.
(IsProtocolVersion oldpv, IsProtocolVersion pv) =>
StateMigrationParameters oldpv pv ->
GlobalContext ->
S.Get (Account (AccountVersionFor pv))
deserializeAccount migration cryptoParams = do
AccountSerializationFlags{..} <- S.get
preAddress <- if asfExplicitAddress then Just <$> S.get else return Nothing
preEncryptionKey <- if asfExplicitEncryptionKey then Just <$> S.get else return Nothing
threshold <- if asfThresholdIsOne then return 1 else S.get
let getCredentials
| asfMultipleCredentials = do
creds <- getSafeMapOf S.get S.get
case Map.lookup initialCredentialIndex creds of
Nothing -> fail $ "Account has no credential with index " ++ show initialCredentialIndex
Just cred -> return (creds, credId cred)
| otherwise = do
cred <- S.get
return (Map.singleton initialCredentialIndex cred, credId cred)
(_accountCredentials, initialCredId) <- getCredentials
_accountRemovedCredentials <- if asfHasRemovedCredentials then makeHashed <$> S.get else return emptyHashedRemovedCredentials
let _accountVerificationKeys = getAccountInformation threshold _accountCredentials
let _accountAddress = fromMaybe (addressFromRegIdRaw initialCredId) preAddress
-- There is an opportunity for improvement here. We do not have to convert
-- the raw credId to a structured one. We can directly construct the
-- However that requires a bit of work to expose the right raw values from
-- cryptographic parameters.
_accountEncryptionKey = fromMaybe (toRawEncryptionKey (makeEncryptionKey cryptoParams (unsafeCredIdFromRaw initialCredId))) preEncryptionKey
_accountNonce <- S.get
_accountAmount <- S.get
_accountEncryptedAmount <-
if asfExplicitEncryptedAmount
then S.get
else return initialAccountEncryptedAmount
_accountReleaseSchedule <-
if asfExplicitReleaseSchedule
then deserializeAccountReleaseSchedule (accountVersion @(AccountVersionFor oldpv))
else return emptyAccountReleaseSchedule
_accountStaking <-
if asfHasBakerOrDelegation
then migrateAccountStake migration <$> deserializeAccountStake
else return AccountStakeNone
let _accountPersisting = makeAccountPersisting PersistingAccountData{..}
return Account{..}

-- | Generate hash inputs from an account for 'AccountV0' and 'AccountV1'.
accountHashInputsV0 :: (IsAccountVersion av, AccountStructureVersionFor av ~ 'AccountStructureV0) => Account av -> AccountHashInputsV0 av
accountHashInputsV0 Account{..} =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
module Concordium.GlobalState.Basic.BlockState.AccountReleaseSchedule where

import Data.Function
import Data.Serialize
import Lens.Micro.Platform

import Concordium.Types
Expand Down Expand Up @@ -146,39 +145,6 @@ nextReleaseTimestamp = case accountVersion @av of
SAccountV1 -> ARSV0.nextReleaseTimestamp . theAccountReleaseSchedule
SAccountV2 -> ARSV1.nextReleaseTimestamp . theAccountReleaseSchedule

-- | Serialize an account release schedule. The serialization format depends on the account version.
serializeAccountReleaseSchedule :: forall av. (IsAccountVersion av) => Putter (AccountReleaseSchedule av)
serializeAccountReleaseSchedule = case accountVersion @av of
SAccountV0 -> put . theAccountReleaseSchedule
SAccountV1 -> put . theAccountReleaseSchedule
SAccountV2 -> put . theAccountReleaseSchedule

-- | Deserialize an account release schedule, possibly upgrading the account version.
--
-- Precondition: @av@ is at least @avold@.
deserializeAccountReleaseSchedule :: forall avold av. (IsAccountVersion av) => SAccountVersion avold -> Get (AccountReleaseSchedule av)
deserializeAccountReleaseSchedule SAccountV0 = AccountReleaseSchedule . convert <$> get
where
convert :: ARSV0.AccountReleaseSchedule -> AccountReleaseSchedule' av
convert = case accountVersion @av of
SAccountV0 -> id
SAccountV1 -> id
SAccountV2 -> ARSV1.fromAccountReleaseScheduleV0
deserializeAccountReleaseSchedule SAccountV1 = AccountReleaseSchedule . convert <$> get
where
convert :: ARSV0.AccountReleaseSchedule -> AccountReleaseSchedule' av
convert = case accountVersion @av of
SAccountV0 -> id
SAccountV1 -> id
SAccountV2 -> ARSV1.fromAccountReleaseScheduleV0
deserializeAccountReleaseSchedule SAccountV2 = AccountReleaseSchedule . convert <$> get
where
convert :: ARSV1.AccountReleaseSchedule -> AccountReleaseSchedule' av
convert = case accountVersion @av of
SAccountV0 -> error "deserializeAccountReleaseSchedule: cannot downgrade account version"
SAccountV1 -> error "deserializeAccountReleaseSchedule: cannot downgrade account version"
SAccountV2 -> id

-- | Get the total locked balance.
totalLockedUpBalance :: forall av. (IsAccountVersion av) => SimpleGetter (AccountReleaseSchedule av) Amount
totalLockedUpBalance = case accountVersion @av of
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ module Concordium.GlobalState.Basic.BlockState.AccountReleaseScheduleV0 (
sumOfReleases,
) where

import Control.Monad
import qualified Data.ByteString as BS
import Data.Foldable
import Data.Function
Expand All @@ -53,7 +52,6 @@ import Concordium.Crypto.SHA256
import Concordium.Types
import Concordium.Types.Accounts.Releases
import Concordium.Types.HashableTo
import Concordium.Utils.Serialization

----------------------------------- Release ------------------------------------

Expand Down Expand Up @@ -121,46 +119,6 @@ toAccountReleaseSummary AccountReleaseSchedule{..} = AccountReleaseSummary{..}
}
releaseSchedule = map makeScheduledRelease sortedAndGroupedByTimestamp

instance Serialize AccountReleaseSchedule where
get = do
vecLength <- getLength
_values <-
Vector.replicateM
vecLength
( getMaybe
( do
l <- getLength
item <- replicateM l get
txh <- get
return (item, txh)
)
)
let (_pendingReleases, _totalLockedUpBalance) =
Vector.ifoldl'
( \acc idx -> \case
Nothing -> acc
Just (rel, _) ->
let f (pending, am) Release{..} =
let pending' = Map.alter (maybe (Just [idx]) (Just . (idx :))) timestamp pending
am' = am + amount
in (pending', am')
in foldl' f acc rel
)
(Map.empty, 0)
_values
return AccountReleaseSchedule{..}
put AccountReleaseSchedule{..} = do
putLength $ Vector.length _values
Vector.mapM_
( putMaybe
( \(rel, txh) -> do
putLength $ length rel
mapM_ put rel
put txh
)
)
_values

-- λ: getHash $ addReleases ([(3,5), (4,10)], th) $ addReleases ([(1,2), (3,4)], th) emptyAccountReleaseSchedule :: Hash
-- 5473ef105c995db8d8dfe75881d8a2018bb12eaeef32032569edfff6814f1b50
-- λ: h1 = hash ((runPut $ put (1 :: Timestamp) >> put (2 :: Amount)) <> hashToByteString (hash (runPut $ put (3 :: Timestamp) >> put (4 :: Amount))))
Expand Down
6 changes: 0 additions & 6 deletions concordium-consensus/src/Concordium/GlobalState/BlockState.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1431,10 +1431,6 @@ class (BlockStateOperations m, FixedSizeSerialization (BlockStateRef m)) => Bloc
-- In particular the 'StateHash' should be supplied if loading a non-genesis block state.
loadBlockState :: Maybe StateHash -> BlockStateRef m -> m (BlockState m)

-- | Serialize the block state to a byte string.
-- This serialization does not include transaction outcomes.
serializeBlockState :: BlockState m -> m BS.ByteString

-- | Retrieve the callback that is needed to read state that is not in
-- memory. This is needed for using V1 contract state.
blockStateLoadCallback :: m LoadCallback
Expand Down Expand Up @@ -1721,7 +1717,6 @@ instance (Monad (t m), MonadTrans t, BlockStateStorage m) => BlockStateStorage (
saveAccounts = lift . saveAccounts
reconstructAccountDifferenceMap bs parentMap = lift . reconstructAccountDifferenceMap bs parentMap
loadBlockState hsh = lift . loadBlockState hsh
serializeBlockState = lift . serializeBlockState
blockStateLoadCallback = lift blockStateLoadCallback
collapseCaches = lift collapseCaches
cacheBlockState = lift . cacheBlockState
Expand All @@ -1735,7 +1730,6 @@ instance (Monad (t m), MonadTrans t, BlockStateStorage m) => BlockStateStorage (
{-# INLINE saveBlockState #-}
{-# INLINE reconstructAccountDifferenceMap #-}
{-# INLINE loadBlockState #-}
{-# INLINE serializeBlockState #-}
{-# INLINE blockStateLoadCallback #-}
{-# INLINE collapseCaches #-}
{-# INLINE cacheBlockState #-}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import Concordium.Types.Accounts.Releases
import Concordium.Types.Execution
import Concordium.Types.HashableTo
import Concordium.Types.Parameters
import Concordium.Utils.Serialization.Put

import qualified Concordium.Crypto.SHA256 as Hash
import Concordium.Genesis.Data
Expand Down Expand Up @@ -506,17 +505,6 @@ makePersistentBakerInfoRef = case accountVersion @av of

-- * Migration

-- | Serialize an account. The serialization format may depend on the protocol version.
--
-- This format allows accounts to be stored in a reduced format by
-- eliding (some) data that can be inferred from context, or is
-- the default value. Note that there can be multiple representations
-- of the same account.
serializeAccount :: (MonadBlobStore m, MonadPut m) => GlobalContext -> PersistentAccount av -> m ()
serializeAccount gc (PAV0 acc) = V0.serializeAccount gc acc
serializeAccount gc (PAV1 acc) = V0.serializeAccount gc acc
serializeAccount gc (PAV2 acc) = V1.serializeAccount gc acc

-- | Migrate a 'PersistentAccount' between protocol versions according to a state migration.
migratePersistentAccount ::
forall oldpv pv t m.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ import Concordium.Types.Accounts.Releases
import Concordium.Types.Execution
import Concordium.Types.HashableTo
import qualified Concordium.Types.Migration as Migration
import Concordium.Utils.Serialization
import Concordium.Utils.Serialization.Put

import Concordium.GlobalState.Account hiding (addIncomingEncryptedAmount, addToSelfEncryptedAmount, replaceUpTo)
import Concordium.GlobalState.BakerInfo (BakerAdd (..), BakerKeyUpdate (..), bakerKeyUpdateToInfo, genesisBakerInfo)
Expand Down Expand Up @@ -1195,61 +1193,6 @@ migratePersistentAccount migration PersistentAccount{..} = do
_accountStake = newAccountStake
}

-- ** Serialization

-- | Serialize an account. The serialization format may depend on the protocol version.
--
-- This format allows accounts to be stored in a reduced format by
-- eliding (some) data that can be inferred from context, or is
-- the default value. Note that there can be multiple representations
-- of the same account.
serializeAccount :: forall m av. (MonadBlobStore m, MonadPut m, IsAccountVersion av, AVStructureV0 av) => GlobalContext -> PersistentAccount av -> m ()
serializeAccount cryptoParams PersistentAccount{..} = do
PersistingAccountData{..} <- refLoad _persistingData
let initialCredId =
credId
( Map.findWithDefault
(error "Account missing initial credential")
initialCredentialIndex
_accountCredentials
)
asfExplicitAddress = _accountAddress /= addressFromRegIdRaw initialCredId
-- There is an opportunity for improvement here. There is no need to go
-- through the deserialized key. The way the encryption key is formed is
-- that the first half is the generator, the second half is the credId.
-- So we could just concatenate them. This requires a bit of scaffolding
-- to get the right component out of cryptoParams, so it is not yet
-- done.
asfExplicitEncryptionKey = _accountEncryptionKey /= toRawEncryptionKey (makeEncryptionKey cryptoParams (unsafeCredIdFromRaw initialCredId))
(asfMultipleCredentials, putCredentials) = case Map.toList _accountCredentials of
[(i, cred)] | i == initialCredentialIndex -> (False, put cred)
_ -> (True, putSafeMapOf put put _accountCredentials)
asfThresholdIsOne = aiThreshold _accountVerificationKeys == 1
asfHasRemovedCredentials = _accountRemovedCredentials ^. unhashed /= EmptyRemovedCredentials
aea <- refLoad _accountEncryptedAmount
(asfExplicitEncryptedAmount, putEA) <-
putAccountEncryptedAmountV0 aea <&> \case
Nothing -> (False, return ())
Just p -> (True, p)
arSched <- loadPersistentAccountReleaseSchedule =<< refLoad _accountReleaseSchedule
let asfExplicitReleaseSchedule = arSched /= ARSV0.emptyAccountReleaseSchedule
asfHasBakerOrDelegation = case _accountStake of
PersistentAccountStakeNone -> False
_ -> True
stake <- loadAccountStake _accountStake
liftPut $ do
put AccountSerializationFlags{..}
when asfExplicitAddress $ put _accountAddress
when asfExplicitEncryptionKey $ put _accountEncryptionKey
unless asfThresholdIsOne $ put (aiThreshold _accountVerificationKeys)
putCredentials
when asfHasRemovedCredentials $ put (_accountRemovedCredentials ^. unhashed)
put _accountNonce
put _accountAmount
putEA
when asfExplicitReleaseSchedule $ put arSched
when asfHasBakerOrDelegation $ serializeAccountStake stake

-- ** Conversion

-- | Converts an account to a transient (i.e. in memory) account. (Used for testing.)
Expand Down
Loading

0 comments on commit 5e8934d

Please sign in to comment.