Skip to content

Commit e4bcfd8

Browse files
authored
Moving network ID into addresses (#1487)
1 parent d1db6d9 commit e4bcfd8

File tree

19 files changed

+202
-141
lines changed

19 files changed

+202
-141
lines changed

shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/Address.hs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module Shelley.Spec.Ledger.Address
1717
serialiseAddr,
1818
deserialiseAddr,
1919
Addr (..),
20+
getNetwork,
2021
-- internals exported for testing
2122
getAddr,
2223
getKeyHash,
@@ -37,7 +38,6 @@ import Cardano.Binary (DecoderError (..), FromCBOR (..), ToCBOR (..), decodeFull
3738
import qualified Cardano.Chain.Common as Byron
3839
import qualified Cardano.Crypto.Hash.Class as Hash
3940
import Cardano.Prelude (NFData, NoUnexpectedThunks, cborError)
40-
import Control.Monad (unless)
4141
import Data.Binary (Get, Put, Word8)
4242
import qualified Data.Binary as B
4343
import qualified Data.Binary.Get as B
@@ -50,6 +50,7 @@ import Data.String (fromString)
5050
import Data.Typeable (Typeable)
5151
import GHC.Generics (Generic)
5252
import Numeric.Natural (Natural)
53+
import Shelley.Spec.Ledger.BaseTypes (Network (..), networkToWord8, word8ToNetwork)
5354
import Shelley.Spec.Ledger.Credential
5455
( Credential (..),
5556
PaymentCredential,
@@ -76,9 +77,10 @@ mkRwdAcnt key@(KeyHashObj _) = RewardAcnt key
7677

7778
toAddr ::
7879
Crypto crypto =>
80+
Network ->
7981
(KeyPair 'Payment crypto, KeyPair 'Staking crypto) ->
8082
Addr crypto
81-
toAddr (payKey, stakeKey) = Addr (toCred payKey) (StakeRefBase $ toCred stakeKey)
83+
toAddr n (payKey, stakeKey) = Addr n (toCred payKey) (StakeRefBase $ toCred stakeKey)
8284

8385
toCred ::
8486
Crypto crypto =>
@@ -94,12 +96,12 @@ scriptToCred :: Crypto crypto => MultiSig crypto -> Credential kr crypto
9496
scriptToCred = ScriptHashObj . hashMultiSigScript
9597

9698
-- | Create a base address from a pair of multi-sig scripts (pay and stake)
97-
scriptsToAddr :: Crypto crypto => (MultiSig crypto, MultiSig crypto) -> Addr crypto
98-
scriptsToAddr (payScript, stakeScript) =
99-
Addr (scriptToCred payScript) (StakeRefBase $ scriptToCred stakeScript)
99+
scriptsToAddr :: Crypto crypto => Network -> (MultiSig crypto, MultiSig crypto) -> Addr crypto
100+
scriptsToAddr n (payScript, stakeScript) =
101+
Addr n (scriptToCred payScript) (StakeRefBase $ scriptToCred stakeScript)
100102

101103
-- | Serialise an address to the external format.
102-
serialiseAddr :: Crypto crypto => Addr crypto -> ByteString
104+
serialiseAddr :: Addr crypto -> ByteString
103105
serialiseAddr = BSL.toStrict . B.runPut . putAddr
104106

105107
-- | Deserialise an address from the external format. This will fail if the
@@ -111,10 +113,17 @@ deserialiseAddr bs = case B.runGetOrFail getAddr (BSL.fromStrict bs) of
111113

112114
-- | An address for UTxO.
113115
data Addr crypto
114-
= Addr !(PaymentCredential crypto) !(StakeReference crypto)
116+
= Addr !Network !(PaymentCredential crypto) !(StakeReference crypto)
115117
| AddrBootstrap !(Byron.Address)
116118
deriving (Show, Eq, Generic, NFData, Ord)
117119

120+
getNetwork :: Addr crypto -> Network
121+
getNetwork (Addr n _ _) = n
122+
getNetwork (AddrBootstrap byronAddr) =
123+
case Byron.aaNetworkMagic . Byron.attrData . Byron.addrAttributes $ byronAddr of
124+
Byron.NetworkMainOrStage -> Mainnet
125+
Byron.NetworkTestnet _ -> Testnet
126+
118127
instance NoUnexpectedThunks (Addr crypto)
119128

120129
byron :: Int
@@ -132,13 +141,13 @@ stakeCredIsScript = 5
132141
payCredIsScript :: Int
133142
payCredIsScript = 4
134143

135-
putAddr :: forall crypto. Crypto crypto => Addr crypto -> Put
144+
putAddr :: Addr crypto -> Put
136145
putAddr (AddrBootstrap byronAddr) = B.putLazyByteString (serialize byronAddr)
137-
putAddr (Addr pc sr) =
146+
putAddr (Addr network pc sr) =
138147
let setPayCredBit = case pc of
139148
ScriptHashObj _ -> flip setBit payCredIsScript
140149
KeyHashObj _ -> id
141-
netId = networkToWord8 $ networkMagicId ([] @crypto)
150+
netId = networkToWord8 network
142151
in case sr of
143152
StakeRefBase sc -> do
144153
let setStakeCredBit = case sc of
@@ -166,17 +175,12 @@ getAddr = do
166175
else do
167176
_ <- B.getWord8 -- read past the header byte
168177
let addrNetId = header .&. 0x0F -- 0b00001111 is the mask for the network id
169-
netId = networkToWord8 $ networkMagicId ([] @crypto)
170-
unless (addrNetId == netId) $ fail $
171-
concat
172-
[ "Got address with incorrect network Id. \n",
173-
"Expected: ",
174-
show netId,
175-
"\n",
176-
"Got: ",
177-
show addrNetId
178-
]
179-
Addr <$> getPayCred header <*> getStakeReference header
178+
case word8ToNetwork addrNetId of
179+
Just n -> Addr n <$> getPayCred header <*> getStakeReference header
180+
Nothing ->
181+
fail $
182+
concat
183+
["Address with unknown network Id. (", show addrNetId, ")"]
180184

181185
getHash :: forall h a. Hash.HashAlgorithm h => Get (Hash.Hash h a)
182186
getHash = Hash.UnsafeHash <$> B.getByteString (fromIntegral $ Hash.sizeHash ([] @h))

shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/BaseTypes.hs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
{-# LANGUAGE DeriveAnyClass #-}
12
{-# LANGUAGE DeriveGeneric #-}
3+
{-# LANGUAGE DerivingStrategies #-}
24
{-# LANGUAGE DerivingVia #-}
35
{-# LANGUAGE EmptyDataDecls #-}
46
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
@@ -11,6 +13,9 @@ module Shelley.Spec.Ledger.BaseTypes
1113
( FixedPoint,
1214
(==>),
1315
(⭒),
16+
Network (..),
17+
networkToWord8,
18+
word8ToNetwork,
1419
Nonce (..),
1520
Seed (..),
1621
UnitInterval (..),
@@ -57,7 +62,7 @@ import Cardano.Binary
5762
matchSize,
5863
)
5964
import Cardano.Crypto.Hash
60-
import Cardano.Prelude (NoUnexpectedThunks (..), cborError)
65+
import Cardano.Prelude (NFData, NoUnexpectedThunks (..), cborError)
6166
import Cardano.Slotting.EpochInfo
6267
import Control.Monad.Trans.Reader (ReaderT)
6368
import qualified Data.ByteString as BS
@@ -91,7 +96,8 @@ fpEpsilon = (10 :: FixedPoint) ^ (17 :: Integer) / fpPrecision
9196

9297
-- | Type to represent a value in the unit interval [0; 1]
9398
newtype UnitInterval = UnsafeUnitInterval Rational -- TODO: Fixed precision
94-
deriving (Show, Ord, Eq, NoUnexpectedThunks, Generic)
99+
deriving (Show, Ord, Eq, Generic)
100+
deriving newtype (NoUnexpectedThunks)
95101

96102
instance ToCBOR UnitInterval where
97103
toCBOR (UnsafeUnitInterval u) = rationalToCBOR u
@@ -166,7 +172,8 @@ mkNonce = Nonce . coerce . hash @SHA256
166172
-- We do not expose the constructor to `Seed`. Instead, a `Seed` should be
167173
-- created using `mkSeed` for a VRF calculation.
168174
newtype Seed = Seed (Hash SHA256 Seed)
169-
deriving (Eq, Ord, Show, Generic, NoUnexpectedThunks, ToCBOR)
175+
deriving (Eq, Ord, Show, Generic)
176+
deriving newtype (NoUnexpectedThunks, ToCBOR)
170177

171178
(==>) :: Bool -> Bool -> Bool
172179
a ==> b = not a || b
@@ -251,7 +258,8 @@ text64FromCBOR = do
251258
--
252259

253260
newtype Url = Url {urlToText :: Text}
254-
deriving (Eq, Ord, Generic, Show, ToCBOR, NoUnexpectedThunks)
261+
deriving (Eq, Ord, Generic, Show)
262+
deriving newtype (ToCBOR, NoUnexpectedThunks)
255263

256264
textToUrl :: Text -> Maybe Url
257265
textToUrl t = Url <$> text64 t
@@ -260,7 +268,8 @@ instance FromCBOR Url where
260268
fromCBOR = Url <$> text64FromCBOR
261269

262270
newtype DnsName = DnsName {dnsToText :: Text}
263-
deriving (Eq, Ord, Generic, Show, ToCBOR, NoUnexpectedThunks)
271+
deriving (Eq, Ord, Generic, Show)
272+
deriving newtype (ToCBOR, NoUnexpectedThunks)
264273

265274
textToDns :: Text -> Maybe DnsName
266275
textToDns t = DnsName <$> text64 t
@@ -269,7 +278,8 @@ instance FromCBOR DnsName where
269278
fromCBOR = DnsName <$> text64FromCBOR
270279

271280
newtype Port = Port {portToWord16 :: Word16}
272-
deriving (Eq, Ord, Num, Generic, Show, ToCBOR, FromCBOR, NoUnexpectedThunks)
281+
deriving (Eq, Ord, Generic, Show)
282+
deriving newtype (Num, FromCBOR, ToCBOR, NoUnexpectedThunks)
273283

274284
--------------------------------------------------------------------------------
275285
-- Active Slot Coefficent, named f in
@@ -353,10 +363,34 @@ data Globals = Globals
353363
maxLovelaceSupply :: !Word64,
354364
-- | Active Slot Coefficient, named f in
355365
-- "Ouroboros Praos: An adaptively-secure, semi-synchronous proof-of-stake protocol"
356-
activeSlotCoeff :: !ActiveSlotCoeff
366+
activeSlotCoeff :: !ActiveSlotCoeff,
367+
-- | The network ID
368+
networkId :: !Network
357369
}
358370
deriving (Generic)
359371

360372
instance NoUnexpectedThunks Globals
361373

362374
type ShelleyBase = ReaderT Globals Identity
375+
376+
data Network
377+
= Testnet
378+
| Mainnet
379+
deriving (Eq, Ord, Enum, Bounded, Show, Generic, NFData, NoUnexpectedThunks)
380+
381+
networkToWord8 :: Network -> Word8
382+
networkToWord8 = toEnum . fromEnum
383+
384+
word8ToNetwork :: Word8 -> Maybe Network
385+
word8ToNetwork e
386+
| fromEnum e > fromEnum (maxBound :: Network) = Nothing
387+
| fromEnum e < fromEnum (minBound :: Network) = Nothing
388+
| otherwise = Just $ toEnum (fromEnum e)
389+
390+
instance ToCBOR Network where
391+
toCBOR = toCBOR . networkToWord8
392+
393+
instance FromCBOR Network where
394+
fromCBOR = word8ToNetwork <$> fromCBOR >>= \case
395+
Nothing -> cborError $ DecoderErrorCustom "Network" "Unknown network id"
396+
Just n -> pure n

shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/Crypto.hs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import Cardano.Crypto.KES
1010
import Cardano.Crypto.VRF
1111
import Data.Kind (Type)
1212
import Data.Typeable (Typeable)
13-
import Data.Word (Word8)
1413

1514
class
1615
( HashAlgorithm (HASH c),
@@ -28,12 +27,3 @@ class
2827
type DSIGN c :: Type
2928
type KES c :: Type
3029
type VRF c :: Type
31-
networkMagicId :: proxy c -> Network
32-
33-
data Network
34-
= Testnet
35-
| Mainnet
36-
deriving (Eq, Ord, Enum)
37-
38-
networkToWord8 :: Network -> Word8
39-
networkToWord8 = toEnum . fromEnum

shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/EpochBoundary.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ newtype Stake crypto = Stake {unStake :: (Map (Credential 'Staking crypto) Coin)
7676

7777
-- | Extract hash of staking key from base address.
7878
getStakeHK :: Addr crypto -> Maybe (Credential 'Staking crypto)
79-
getStakeHK (Addr _ (StakeRefBase hk)) = Just hk
79+
getStakeHK (Addr _ _ (StakeRefBase hk)) = Just hk
8080
getStakeHK _ = Nothing
8181

8282
aggregateOuts :: UTxO crypto -> Map (Addr crypto) Coin
@@ -98,7 +98,7 @@ baseStake vals =
9898

9999
-- | Extract pointer from pointer address.
100100
getStakePtr :: Addr crypto -> Maybe Ptr
101-
getStakePtr (Addr _ (StakeRefPtr ptr)) = Just ptr
101+
getStakePtr (Addr _ _ (StakeRefPtr ptr)) = Just ptr
102102
getStakePtr _ = Nothing
103103

104104
-- | Calculate stake of pointer addresses in TxOut set.

shelley/chain-and-ledger/executable-spec/src/Shelley/Spec/Ledger/LedgerState.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ witsVKeyNeeded utxo' tx@(Tx txbody _ _ _) _genDelegs =
766766
unspendableKeyHash = KeyHash (coerce (hash 0 :: Hash crypto Int))
767767
insertHK txin hkeys =
768768
case txinLookup txin utxo' of
769-
Just (TxOut (Addr (KeyHashObj pay) _) _) -> Set.insert pay hkeys
769+
Just (TxOut (Addr _ (KeyHashObj pay) _) _) -> Set.insert pay hkeys
770770
Just (TxOut (AddrBootstrap _) _) -> Set.insert unspendableKeyHash hkeys
771771
-- NOTE: Until Byron addresses are supported, we insert an unspendible keyhash
772772
_ -> hkeys

0 commit comments

Comments
 (0)