Skip to content

Commit

Permalink
50% of elaborator for Shelley
Browse files Browse the repository at this point in the history
  • Loading branch information
danbornside committed Apr 8, 2021
1 parent 911fc35 commit da00183
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 17 deletions.
@@ -1,4 +1,5 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DefaultSignatures #-}
Expand Down Expand Up @@ -41,7 +42,6 @@ import Shelley.Spec.Ledger.API.Protocol (PraosCrypto)
import Shelley.Spec.Ledger.BaseTypes (Globals (..))
import Shelley.Spec.Ledger.BaseTypes (ShelleyBase)
import Shelley.Spec.Ledger.BlockChain
-- import Shelley.Spec.Ledger.TxBody
import Shelley.Spec.Ledger.LedgerState (NewEpochState)
import qualified Shelley.Spec.Ledger.LedgerState as LedgerState
import Shelley.Spec.Ledger.PParams (PParams' (..))
Expand All @@ -53,6 +53,12 @@ import Data.Proxy
import Numeric.Natural
import Data.Set (Set)
import Data.Bifunctor
-- import Data.Default.Class
-- import qualified Data.Map as Map
-- import qualified Cardano.Ledger.Crypto as CC
-- import qualified Cardano.Crypto.Hash.Class as CC
-- import Control.Monad.State (evalStateT)
-- import Data.Functor.Identity
-- import Data.Kind (Type)
-- import Control.Monad.State (StateT)
-- import Data.Map (Map)
Expand All @@ -63,8 +69,11 @@ import Data.Bifunctor


newtype ModelTxId = ModelTxId Integer
deriving (Eq, Ord, Show)
newtype ModelAddress = ModelAddress String
deriving (Eq, Ord, Show)
newtype ModelValue = ModelValue Integer
deriving (Eq, Ord, Show)

data ModelTxIn = ModelTxIn ModelTxId Natural
data ModelTxOut = ModelTxOut ModelAddress ModelValue
Expand All @@ -87,14 +96,11 @@ class TraceApplyBlock era where
:: proxy era
-> [ModelTxOut]
-> [ModelBlock]
-> BaseM era
-> BaseM (Core.EraRule "TICK" era)
( State (Core.EraRule "TICK" era)
, [ApplyBlockData era]
)

-- instance PraosCrypto crypto => TraceApplyBlock (ShelleyEra crypto) where
-- toEra _ utxos blocks = _


data ApplyBlockData era where
ApplyTick :: Signal (Core.EraRule "TICK" era) -> ApplyBlockData era
Expand Down
Expand Up @@ -35,6 +35,7 @@ module Shelley.Spec.Ledger.LedgerState
DPState (..),
DState (..),
EpochState (..),
esLStateLens,
UpecState (..),
PulsingRewUpdate (..),
FutureGenDeleg (..),
Expand Down Expand Up @@ -84,6 +85,7 @@ module Shelley.Spec.Ledger.LedgerState
pulseOther,
--
NewEpochState (..),
nesEsLens,
getGKeys,
updateNES,
circulation,
Expand Down Expand Up @@ -482,6 +484,13 @@ type TransEpoch (c :: Type -> Constraint) era =
c (Core.PParams era)
)

esLStateLens :: Functor f
=> (LedgerState era -> f (LedgerState era))
-> EpochState era -> f (EpochState era)
esLStateLens a2b s = (\b -> s {esLState = b}) <$> a2b (esLState s)
{-# INLINE esLStateLens #-}


deriving stock instance
TransEpoch Show era =>
Show (EpochState era)
Expand Down Expand Up @@ -637,6 +646,13 @@ data NewEpochState era = NewEpochState
}
deriving (Generic)

nesEsLens :: Functor f
=> (EpochState era -> f (EpochState era))
-> NewEpochState era -> f (NewEpochState era)
nesEsLens a2b s = (\b -> s {nesEs = b}) <$> a2b (nesEs s)
{-# INLINE nesEsLens #-}


deriving stock instance
(TransEpoch Show era) =>
Show (NewEpochState era)
Expand Down
Expand Up @@ -44,6 +44,7 @@ library
test
exposed-modules:
Test.Cardano.Crypto.VRF.Fake
Test.Shelley.Spec.Ledger.ApplyBlock
Test.Shelley.Spec.Ledger.BenchmarkFunctions
Test.Shelley.Spec.Ledger.ConcreteCryptoTypes
Test.Shelley.Spec.Ledger.Example
Expand Down
@@ -0,0 +1,167 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Test.Shelley.Spec.Ledger.ApplyBlock where

import Control.Monad.State
import Data.Functor.Identity
import Data.Proxy
import Data.Traversable
import Numeric.Natural
import qualified Data.Map as Map
import qualified Data.Set as Set

import Control.State.Transition.Extended
import Cardano.Ledger.Shelley (ShelleyEra)
import Shelley.Spec.Ledger.API.Protocol (PraosCrypto)
import Shelley.Spec.Ledger.API.Validation
import Shelley.Spec.Ledger.Address
import Shelley.Spec.Ledger.BaseTypes (Network (..))
import Shelley.Spec.Ledger.BaseTypes (Nonce (..))
-- import Shelley.Spec.Ledger.Coin
import Shelley.Spec.Ledger.TxBody
import Shelley.Spec.Ledger.LedgerState
import qualified Cardano.Crypto.Hash.Class as CC
import Cardano.Crypto.Util (SignableRepresentation)
import qualified Cardano.Crypto.KES.Class as KES
import qualified Cardano.Ledger.Core as Core
import Cardano.Ledger.Crypto (KES, DSIGN)
import qualified Cardano.Ledger.Crypto as CC
import qualified Shelley.Spec.Ledger.UTxO as UTxO
import qualified Cardano.Crypto.DSIGN.Class as DSIGN
import Shelley.Spec.Ledger.Keys
import Shelley.Spec.Ledger.BlockChain
import Shelley.Spec.Ledger.Tx
import Cardano.Ledger.Era
-- import qualified Data.Sequence.Strict as StrictSeq
import Cardano.Slotting.Block

import Test.Shelley.Spec.Ledger.Generator.ScriptClass
import Test.Shelley.Spec.Ledger.Generator.Core
import Test.Shelley.Spec.Ledger.Generator.ShelleyEraGen ()
import Test.Shelley.Spec.Ledger.Generator.Presets
import Test.Shelley.Spec.Ledger.Examples.Federation
import Shelley.Spec.Ledger.OCert

type KeyPair' crypto = (KeyPair 'Payment crypto, KeyPair 'Staking crypto)

data ShellyEraState crypto = ShellyEraState
{ _unusedKeyPairs :: [KeyPair' crypto]
, _keys :: Map.Map ModelAddress (KeyPair' crypto)
, _blockNo :: BlockNo
, _prevHash :: HashHeader crypto
}


getKeyPairFor :: forall m crypto. MonadState (ShellyEraState crypto) m => ModelAddress -> m (KeyPair' crypto)
getKeyPairFor mAddr = do
st <- get
case Map.lookup mAddr (_keys st) of
Just k -> pure k
Nothing -> case _unusedKeyPairs st of
[] -> error "ran out of keys"
(k:ks) -> do
put $ st {_unusedKeyPairs = ks, _keys = Map.insert mAddr k $ _keys st}
pure k


instance
( PraosCrypto crypto
, KES.Signable (KES crypto) ~ SignableRepresentation
, DSIGN.Signable (DSIGN crypto) ~ SignableRepresentation
) => TraceApplyBlock (ShelleyEra crypto) where
toEra _ utxos blocks = do
nes <- reapplySTS @(Core.EraRule "TICK" (ShelleyEra crypto)) (IRC ())
let
initialState :: ShellyEraState crypto
initialState = ShellyEraState (mkKeyPairs <$> [1..]) Map.empty 0 genesisHash'

myGenEnv = genEnv (Proxy :: Proxy (ShelleyEra crypto))


set :: ((a -> Identity b) -> (s -> Identity t)) -> b -> s -> t
set l b s = runIdentity (l (\_ -> Identity b) s)

genesisHash = TxId $ CC.castHash $ CC.hashWith id "TEST GENESIS"
genesisHash' = HashHeader $ CC.castHash $ CC.hashWith id "TEST GENESIS"

getBHeaderHash :: Block (ShelleyEra crypto) -> HashHeader crypto
getBHeaderHash (Block bh _) = bhHash bh

mkGenTxOut
:: forall m. (MonadState (ShellyEraState crypto) m)
=> (ModelTxOut, Natural)
-> m (TxIn crypto, TxOut (ShelleyEra crypto))
mkGenTxOut ((ModelTxOut mAddr (ModelValue mValue)), n) = do
addr <- getKeyPairFor mAddr

pure (TxIn genesisHash n, TxOut (toAddr Testnet addr) (Coin mValue))

mkTx
:: forall m. (MonadState (ShellyEraState crypto) m)
=> ModelTx
-> m (Tx (ShelleyEra crypto))
mkTx mtx@(ModelTx {}) = do

pure $ Tx
(TxBody
{ _inputs = Set.map _ $ _mtxInputs mtx
, _outputs = _
, _certs = _
, _wdrls = _
, _txfee = _
, _ttl = _
, _txUpdate = _
, _mdHash = _
})
mempty
mempty

mkBlock'
:: forall m. (MonadState (ShellyEraState crypto) m)
=> ModelBlock -> m (Block (ShelleyEra crypto))
mkBlock' mBlk = do
txSeq :: [Tx (ShelleyEra era)] <- for (_mbUtxo mBlk) mkTx

st <- get
-- let
let
newBlock = mkBlock
(_prevHash st)
(head . ksStakePools . geKeySpace $ myGenEnv)
txSeq
(_mbSlot mBlk)
(_blockNo st)
NeutralNonce
0
0
(mkOCert (head . ksGenesisDelegates . geKeySpace $ myGenEnv) 0 (KESPeriod 0))
put $ st {_prevHash = getBHeaderHash newBlock }
pure newBlock


flip evalStateT initialState $ do
genesisUtxos <- traverse mkGenTxOut (zip utxos [0..])
let
nes' = set (nesEsLens . esLStateLens) ledgerState nes
ledgerState = genesisState @(ShelleyEra crypto) Map.empty
. UTxO.UTxO
$ Map.fromList genesisUtxos

blocks' :: [[ApplyBlockData (ShelleyEra crypto)]] <- for blocks $ \block -> do
newBlock <- mkBlock' block
pure $
[ ApplyTick $ _mbSlot block
, ApplyBlock newBlock
]

pure $ (nes', concat blocks')
-- mkGenTxOut :: ModelTxOut -> (TxIn crypto, TxOut (ShelleyEra crypto))
-- mkGenTxOut (ModelTxOut ma mv) = _

-- pure (nes, [])

Expand Up @@ -75,7 +75,6 @@ import Data.Ratio ((%))
import Data.Sequence.Strict (StrictSeq)
import qualified Data.Sequence.Strict as StrictSeq
import Data.Set (Set)
import Data.Tuple (swap)
import Data.Word (Word64)
import GHC.Records (HasField, getField)
import Numeric.Natural (Natural)
Expand Down Expand Up @@ -188,6 +187,7 @@ import Test.Shelley.Spec.Ledger.Generator.ScriptClass
exponential,
mkPayScriptHashMap,
mkStakeScriptHashMap,
mkKeyPairs
)
import Test.Shelley.Spec.Ledger.Orphans ()
import Test.Shelley.Spec.Ledger.Utils
Expand Down Expand Up @@ -314,17 +314,6 @@ genWord64 lower upper =
fromIntegral
<$> genNatural (fromIntegral lower) (fromIntegral upper)

mkKeyPairs ::
(DSIGNAlgorithm (DSIGN crypto)) =>
Word64 ->
(KeyPair kr crypto, KeyPair kr' crypto)
mkKeyPairs n =
(mkKeyPair_ (2 * n), mkKeyPair_ (2 * n + 1))
where
mkKeyPair_ n_ =
(uncurry KeyPair . swap)
(mkKeyPair (n_, n_, n_, n_, n_))

-- | Generate a mapping from genesis delegate cold key hash to the issuer keys.
-- Note: we index all possible genesis delegate keys, that is,
-- core nodes and all potential keys.
Expand Down

0 comments on commit da00183

Please sign in to comment.