morley-upgradeable-0.3: src/Lorentz/Contracts/UpgradeableCounterSdu/V2.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
{-# OPTIONS_GHC -Wno-orphans #-}
module Lorentz.Contracts.UpgradeableCounterSdu.V2
( CounterSduV
, counterContract
, migration
, counterUpgradeParameters
, counterUpgradeParametersFromV0
, counterRollbackParameters
) where
import Lorentz
import Prelude (Identity)
import Lorentz.Contracts.Upgradeable.Common
import Lorentz.Contracts.Upgradeable.StorageDriven
import Lorentz.Contracts.UpgradeableCounterSdu
import qualified Lorentz.Contracts.UpgradeableCounterSdu.V1 as V1
import Lorentz.UStore
import Lorentz.UStore.Migration
import Util.Named
-- Moved all entrypoints to a dedicated datatype for convenience
data UStoreEntrypoints store = UStoreEntrypoints
{ epInc :: UStoreEntrypoint store ()
, epDec :: UStoreEntrypoint store ()
, epGetCounterValue :: UStoreEntrypoint store (Void_ () Integer)
} deriving stock (Eq, Generic)
data UStoreTemplate = UStoreTemplate
{ -- We want to keep a value of significantly different type comparing to V1
counterValue :: UStoreField ("i" :! Integer, ())
, code :: UStoreEntrypoints UStoreTemplate
} deriving stock (Eq, Generic)
type UStorage = UStore UStoreTemplate
type Interface = UStoreEpInterface UStoreTemplate
instance KnownContractVersion (CounterSduV 2) where
type VerInterface (CounterSduV 2) = Interface
type VerUStoreTemplate (CounterSduV 2) = UStoreTemplate
type VerPermanent (CounterSduV 2) = Permanent
addInt :: Integer -> Entrypoint () UStorage
addInt x = do
drop @()
ustoreGetField #counterValue
getField #i
push x
add
setField #i
ustoreSetField #counterValue
nil; pair
runInc :: Entrypoint () UStorage
runInc = addInt 1
runDec :: Entrypoint () UStorage
runDec = addInt (-1)
runGetCounterValue :: Entrypoint (Void_ () Integer) UStorage
runGetCounterValue = void_ $ do
drop @()
ustoreGetField #counterValue
toField #i
dip drop
counterContract :: UContractRouter (CounterSduV 2)
counterContract = mkSduContract sduFallbackFail
permImpl :: PermanentImpl (CounterSduV 2)
permImpl = mkSmallPermanentImpl
( #cGetCounter /-> void_ $ do
drop @(); ustoreToField #counterValue; toField #i
, #cGetNothing /-> absurd_
)
mkStorage :: UStoreTemplate
mkStorage = UStoreTemplate
{ counterValue = UStoreField (#i .! 0, ())
, code = UStoreEntrypoints
{ epInc = mkUStoreEntrypoint runInc
, epDec = mkUStoreEntrypoint runDec
, epGetCounterValue = mkUStoreEntrypoint runGetCounterValue
}
}
migration :: UStoreMigration (VerUStoreTemplate (CounterSduV 1)) UStoreTemplate
migration = mkUStoreMigration $ do
migrateExtractField #counterValue
int; toNamed #i
unit; swap; pair
migrateAddField #counterValue
migrateRemoveField #epAdd
push (mkSduEntrypoint runInc)
migrateOverwriteField #epInc
push (mkSduEntrypoint runDec)
migrateAddField #epDec
push (mkSduEntrypoint runGetCounterValue)
migrateOverwriteField #epGetCounterValue
migrationFinish
counterUpgradeParameters :: EpwUpgradeParameters Identity (CounterSduV 1) (CounterSduV 2)
counterUpgradeParameters = EpwUpgradeParameters
{ upMigrationScripts = migrationToScriptI migration
, upNewCode = counterContract
, upNewPermCode = permImpl
}
counterUpgradeParametersFromV0 :: EpwUpgradeParameters Identity (CounterSduV 0) (CounterSduV 2)
counterUpgradeParametersFromV0 = EpwUpgradeParameters
{ upMigrationScripts = migrationToScriptI $ fillUStore mkStorage
, upNewCode = counterContract
, upNewPermCode = permImpl
}
rollback :: UStoreMigration UStoreTemplate (VerUStoreTemplate (CounterSduV 1))
rollback = mkUStoreMigration $ do
migrateExtractField #counterValue
toField #i; isNat
assertSome [mt|Rollback is impossible|]
migrateAddField #counterValue
push (mkSduEntrypoint V1.runAdd)
migrateAddField #epAdd
migrateCoerceUnsafe #epInc
migrateRemoveField #epDec
push (mkSduEntrypoint V1.runGetCounterValue)
migrateOverwriteField #epGetCounterValue
migrationFinish
-- Needed for one of our tests
counterRollbackParameters :: EpwUpgradeParameters Identity (CounterSduV 2) (CounterSduV 1)
counterRollbackParameters = EpwUpgradeParameters
{ upMigrationScripts = migrationToScriptI rollback
, upNewCode = V1.counterContract
, upNewPermCode = V1.permImpl
}