Skip to content

Commit

Permalink
Merge #2094
Browse files Browse the repository at this point in the history
2094: More API module splitting r=intricate a=dcoutts

Split almost all the remaining things out of Cardano.Api.Typed
so they are lots of smaller modules. This nearly completes the
split of the original monolithic module. The only remaining part
is the IPC with the node, which will be replaces shortly.

Co-authored-by: Duncan Coutts <[email protected]>
  • Loading branch information
iohk-bors[bot] and dcoutts authored Nov 16, 2020
2 parents d6e988d + a643c2a commit f7d57e3
Show file tree
Hide file tree
Showing 20 changed files with 2,553 additions and 2,009 deletions.
11 changes: 10 additions & 1 deletion cardano-api/cardano-api.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ library
Cardano.Api.Byron
Cardano.Api.Crypto.Ed25519Bip32
Cardano.Api.LocalChainSync
Cardano.Api.MetaData
Cardano.Api.Protocol
Cardano.Api.Protocol.Byron
Cardano.Api.Protocol.Cardano
Expand All @@ -36,20 +35,30 @@ library
Cardano.Api.TxSubmit.Types

-- Splitting up the big Typed module:
Cardano.Api.Address
Cardano.Api.Certificate
Cardano.Api.Eras
Cardano.Api.Error
Cardano.Api.Fees
Cardano.Api.Hash
Cardano.Api.HasTypeProxy
Cardano.Api.Key
Cardano.Api.KeysByron
Cardano.Api.KeysShelley
Cardano.Api.KeysPraos
Cardano.Api.NetworkId
Cardano.Api.OperationalCertificate
Cardano.Api.ProtocolParameters
Cardano.Api.Script
Cardano.Api.SerialiseBech32
Cardano.Api.SerialiseCBOR
Cardano.Api.SerialiseJSON
Cardano.Api.SerialiseRaw
Cardano.Api.SerialiseTextEnvelope
Cardano.Api.StakePoolMetadata
Cardano.Api.Tx
Cardano.Api.TxBody
Cardano.Api.TxMetadata
Cardano.Api.Utils
Cardano.Api.Value

Expand Down
16 changes: 15 additions & 1 deletion cardano-api/src/Cardano/API.hs
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,23 @@ module Cardano.API (
-- * Transaction metadata
-- | Embedding additional structured data within transactions.
TxMetadata(TxMetadata),
TxMetadataValue,

-- ** Constructing metadata
TxMetadataValue(..),
makeTransactionMetadata,

-- ** Validating metadata
validateTxMetadata,
TxMetadataRangeError (..),

-- ** Converstion to\/from JSON
TxMetadataJsonSchema (..),
metadataFromJson,
metadataToJson,
metadataValueToJsonNoSchema,
TxMetadataJsonError (..),
TxMetadataJsonSchemaError (..),

-- * Registering stake address and delegating
-- | Certificates that are embedded in transactions for registering and
-- unregistering stake address, and for setting the stake pool delegation
Expand Down
324 changes: 324 additions & 0 deletions cardano-api/src/Cardano/Api/Address.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,324 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}

-- | Cardano addresses: payment and stake addresses.
--
module Cardano.Api.Address (
-- * Payment addresses
-- | Constructing and inspecting normal payment addresses
Address(..),
-- * Byron addresses
makeByronAddress,
ByronKey,
-- * Shelley addresses
makeShelleyAddress,
PaymentCredential(..),
StakeAddressReference(..),
PaymentKey,
PaymentExtendedKey,

-- * Stake addresses
-- | Constructing and inspecting stake addresses
StakeAddress(..),
StakeCredential(..),
makeStakeAddress,
StakeKey,
StakeExtendedKey,

-- * Internal conversion functions
toShelleyAddr,
toShelleyStakeAddr,
toShelleyStakeCredential,

-- * Serialising addresses
SerialiseAddress(..),

-- * Data family instances
AsType(..)
) where

import Prelude

import Data.Text (Text)
import qualified Data.Text.Encoding as Text
import qualified Data.ByteString.Base58 as Base58

import Control.Applicative

import qualified Cardano.Binary as CBOR

import qualified Cardano.Chain.Common as Byron

import Ouroboros.Consensus.Shelley.Eras (StandardShelley)
import qualified Shelley.Spec.Ledger.Address as Shelley
import qualified Shelley.Spec.Ledger.BaseTypes as Shelley
import qualified Shelley.Spec.Ledger.Credential as Shelley

import Cardano.Api.Eras
import Cardano.Api.Hash
import Cardano.Api.HasTypeProxy
import Cardano.Api.Key
import Cardano.Api.KeysByron
import Cardano.Api.KeysPraos
import Cardano.Api.KeysShelley
import Cardano.Api.NetworkId
import Cardano.Api.Script
import Cardano.Api.SerialiseBech32
import Cardano.Api.SerialiseRaw


-- ----------------------------------------------------------------------------
-- Address Serialisation
--

-- | Address serialisation uses different serialisation formats for different
-- kinds of addresses, so it needs its own class.
--
-- In particular, Byron addresses are typically formatted in base 58, while
-- Shelley addresses (payment and stake) are formatted using Bech32.
--
class HasTypeProxy addr => SerialiseAddress addr where

serialiseAddress :: addr -> Text

deserialiseAddress :: AsType addr -> Text -> Maybe addr
-- TODO: consider adding data AddressDecodeError


-- ----------------------------------------------------------------------------
-- Payment addresses
--

data Address era where

-- | Byron addresses are valid in both the Byron and Shelley era.
--
ByronAddress
:: Byron.Address
-> Address era

-- | Shelley addresses are only valid in the Shelley era.
--
ShelleyAddress
:: Shelley.Network
-> Shelley.PaymentCredential StandardShelley
-> Shelley.StakeReference StandardShelley
-> Address Shelley

deriving instance Eq (Address era)
deriving instance Ord (Address era)
deriving instance Show (Address era)


instance HasTypeProxy (Address Byron) where
data AsType (Address Byron) = AsByronAddress
proxyToAsType _ = AsByronAddress

instance HasTypeProxy (Address Shelley) where
data AsType (Address Shelley) = AsShelleyAddress
proxyToAsType _ = AsShelleyAddress


instance SerialiseAsRawBytes (Address Byron) where
serialiseToRawBytes (ByronAddress addr) = CBOR.serialize' addr

deserialiseFromRawBytes AsByronAddress bs =
case CBOR.decodeFull' bs of
Left _ -> Nothing
Right addr -> Just (ByronAddress addr)


instance SerialiseAsRawBytes (Address Shelley) where
serialiseToRawBytes (ByronAddress addr) =
Shelley.serialiseAddr
. Shelley.AddrBootstrap
. Shelley.BootstrapAddress
$ addr

serialiseToRawBytes (ShelleyAddress nw pc scr) =
Shelley.serialiseAddr (Shelley.Addr nw pc scr)

deserialiseFromRawBytes AsShelleyAddress bs =
case Shelley.deserialiseAddr bs of
Nothing -> Nothing
Just (Shelley.Addr nw pc scr) ->
Just (ShelleyAddress nw pc scr)

Just (Shelley.AddrBootstrap (Shelley.BootstrapAddress addr)) ->
Just (ByronAddress addr)

instance SerialiseAsBech32 (Address Shelley) where
bech32PrefixFor (ShelleyAddress Shelley.Mainnet _ _) = "addr"
bech32PrefixFor (ShelleyAddress Shelley.Testnet _ _) = "addr_test"
bech32PrefixFor (ByronAddress _) = "addr"

bech32PrefixesPermitted AsShelleyAddress = ["addr", "addr_test"]


instance SerialiseAddress (Address Byron) where
serialiseAddress addr@ByronAddress{} =
Text.decodeLatin1
. Base58.encodeBase58 Base58.bitcoinAlphabet
. serialiseToRawBytes
$ addr

deserialiseAddress AsByronAddress txt = do
bs <- Base58.decodeBase58 Base58.bitcoinAlphabet (Text.encodeUtf8 txt)
deserialiseFromRawBytes AsByronAddress bs

instance SerialiseAddress (Address Shelley) where
serialiseAddress (ByronAddress addr) =
serialiseAddress (ByronAddress addr :: Address Byron)

serialiseAddress addr@ShelleyAddress{} =
serialiseToBech32 addr

deserialiseAddress AsShelleyAddress t =
deserialiseAsShelleyAddress
<|> deserialiseAsByronAddress
where
deserialiseAsShelleyAddress =
either (const Nothing) Just $
deserialiseFromBech32 AsShelleyAddress t

deserialiseAsByronAddress =
castByronToShelleyAddress <$>
deserialiseAddress AsByronAddress t

castByronToShelleyAddress :: Address Byron -> Address Shelley
castByronToShelleyAddress (ByronAddress addr) = ByronAddress addr


makeByronAddress :: NetworkId
-> VerificationKey ByronKey
-> Address era
makeByronAddress nw (ByronVerificationKey vk) =
ByronAddress $
Byron.makeVerKeyAddress
(toByronNetworkMagic nw)
vk


makeShelleyAddress :: NetworkId
-> PaymentCredential
-> StakeAddressReference
-> Address Shelley
makeShelleyAddress nw pc scr =
ShelleyAddress
(toShelleyNetwork nw)
(toShelleyPaymentCredential pc)
(toShelleyStakeReference scr)


-- ----------------------------------------------------------------------------
-- Stake addresses
--

data StakeAddress where

StakeAddress
:: Shelley.Network
-> Shelley.StakeCredential StandardShelley
-> StakeAddress
deriving (Eq, Ord, Show)

data PaymentCredential
= PaymentCredentialByKey (Hash PaymentKey)
| PaymentCredentialByScript ScriptHash
deriving (Eq, Show)

data StakeCredential
= StakeCredentialByKey (Hash StakeKey)
| StakeCredentialByScript ScriptHash
deriving (Eq, Show)

data StakeAddressReference
= StakeAddressByValue StakeCredential
| StakeAddressByPointer StakeAddressPointer
| NoStakeAddress
deriving (Eq, Show)

--TODO: wrap this type properly and export it
type StakeAddressPointer = Shelley.Ptr


instance HasTypeProxy StakeAddress where
data AsType StakeAddress = AsStakeAddress
proxyToAsType _ = AsStakeAddress


instance SerialiseAsRawBytes StakeAddress where
serialiseToRawBytes (StakeAddress nw sc) =
Shelley.serialiseRewardAcnt (Shelley.RewardAcnt nw sc)

deserialiseFromRawBytes AsStakeAddress bs =
case Shelley.deserialiseRewardAcnt bs of
Nothing -> Nothing
Just (Shelley.RewardAcnt nw sc) -> Just (StakeAddress nw sc)


instance SerialiseAsBech32 StakeAddress where
bech32PrefixFor (StakeAddress Shelley.Mainnet _) = "stake"
bech32PrefixFor (StakeAddress Shelley.Testnet _) = "stake_test"

bech32PrefixesPermitted AsStakeAddress = ["stake", "stake_test"]


instance SerialiseAddress StakeAddress where
serialiseAddress addr@StakeAddress{} =
serialiseToBech32 addr

deserialiseAddress AsStakeAddress t =
either (const Nothing) Just $
deserialiseFromBech32 AsStakeAddress t


makeStakeAddress :: NetworkId
-> StakeCredential
-> StakeAddress
makeStakeAddress nw sc =
StakeAddress
(toShelleyNetwork nw)
(toShelleyStakeCredential sc)


-- ----------------------------------------------------------------------------
-- Internal conversion functions
--

toShelleyAddr :: Address era -> Shelley.Addr StandardShelley
toShelleyAddr (ByronAddress addr) = Shelley.AddrBootstrap
(Shelley.BootstrapAddress addr)
toShelleyAddr (ShelleyAddress nw pc scr) = Shelley.Addr nw pc scr

toShelleyStakeAddr :: StakeAddress -> Shelley.RewardAcnt StandardShelley
toShelleyStakeAddr (StakeAddress nw sc) =
Shelley.RewardAcnt {
Shelley.getRwdNetwork = nw,
Shelley.getRwdCred = sc
}

toShelleyPaymentCredential :: PaymentCredential
-> Shelley.PaymentCredential StandardShelley
toShelleyPaymentCredential (PaymentCredentialByKey (PaymentKeyHash kh)) =
Shelley.KeyHashObj kh
toShelleyPaymentCredential (PaymentCredentialByScript (ScriptHash sh)) =
Shelley.ScriptHashObj sh

toShelleyStakeCredential :: StakeCredential
-> Shelley.StakeCredential StandardShelley
toShelleyStakeCredential (StakeCredentialByKey (StakeKeyHash kh)) =
Shelley.KeyHashObj kh
toShelleyStakeCredential (StakeCredentialByScript (ScriptHash kh)) =
Shelley.ScriptHashObj kh

toShelleyStakeReference :: StakeAddressReference
-> Shelley.StakeReference StandardShelley
toShelleyStakeReference (StakeAddressByValue stakecred) =
Shelley.StakeRefBase (toShelleyStakeCredential stakecred)
toShelleyStakeReference (StakeAddressByPointer ptr) =
Shelley.StakeRefPtr ptr
toShelleyStakeReference NoStakeAddress =
Shelley.StakeRefNull
4 changes: 0 additions & 4 deletions cardano-api/src/Cardano/Api/Byron.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ module Cardano.Api.Byron
TxIx(TxIx),
Lovelace(Lovelace),
SlotNo(SlotNo),
toByronLovelace,
toByronTxId,
toByronTxIn,
toByronTxOut,

-- * Signing transactions
-- | Creating transaction witnesses one by one, or all in one go.
Expand Down
Loading

0 comments on commit f7d57e3

Please sign in to comment.