{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
module Singular.Registry.TxBuilder.Internal.Identity
(
mkCageScript
, mkRequestScript
, scriptFromBytes
, scriptHashBytes
, computeScriptHash
, cagePolicyIdFromCfg
, cageAddrFromCfg
, requestAddrFromCfg
, onChainTokenId
, mkRequestDatum
, mkRequestDatumWith
, toPlcData
, toLedgerData
, mkInlineDatum
, extractCageDatum
, txInToRef
, addrKeyHashBytes
, addrFromKeyHashBytes
, addrWitnessKeyHash
, extractOwnerBytes
, emptyRoot
, policyIdFromPin
, addrFromBytes
) where
import Cardano.Crypto.Hash (hashFromBytes, hashToBytes)
import Cardano.Ledger.Address (Addr (..), decodeAddrEither)
import Cardano.Ledger.Alonzo.Scripts
( fromPlutusScript
, mkPlutusScript
)
import Cardano.Ledger.Api.Scripts.Data
( Data (..)
, Datum (..)
, binaryDataToData
, dataToBinaryData
)
import Cardano.Ledger.Api.Tx.Out
( TxOut
, datumTxOutL
)
import Cardano.Ledger.BaseTypes
( Network
, TxIx (..)
)
import Cardano.Ledger.Core
( Script
, extractHash
, hashScript
)
import Cardano.Ledger.Credential
( Credential (..)
, StakeReference (..)
)
import Cardano.Ledger.Hashes (ScriptHash (..))
import Cardano.Ledger.Keys
( KeyHash (..)
, KeyRole (..)
)
import Cardano.Ledger.Mary.Value (PolicyID (..))
import Cardano.Ledger.Plutus.Language
( Language (PlutusV3)
, Plutus (..)
, PlutusBinary (..)
)
import Cardano.Ledger.TxIn (TxId (..), TxIn (..))
import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.ByteString.Short qualified as SBS
import Data.Coerce (coerce)
import Lens.Micro ((^.))
import PlutusCore.Data qualified as PLC
import PlutusTx.Builtins.Internal
( BuiltinByteString (..)
, BuiltinData (..)
)
import PlutusTx.IsData.Class
( FromData (..)
, ToData (..)
)
import Singular.Registry.Blueprint.Params (applyRequestParams)
import Singular.Registry.Config (CageConfig (..))
import Singular.Registry.Ledger
( AssetName (..)
, ConwayEra
, TokenId (..)
)
import Singular.Registry.Types
( CageDatum (..)
, Edge
, OnChainRequest (..)
, OnChainTokenId (..)
, OnChainTxOutRef (..)
)
emptyRoot :: ByteString
emptyRoot :: ByteString
emptyRoot = Int -> Word8 -> ByteString
BS.replicate Int
32 Word8
0
mkCageScript
:: CageConfig
-> Script ConwayEra
mkCageScript :: CageConfig -> Script ConwayEra
mkCageScript CageConfig
cfg =
[Char] -> ShortByteString -> Script ConwayEra
scriptFromBytes
[Char]
"mkCageScript"
(CageConfig -> ShortByteString
cageScriptBytes CageConfig
cfg)
mkRequestScript
:: CageConfig
-> TokenId
-> Script ConwayEra
mkRequestScript :: CageConfig -> TokenId -> Script ConwayEra
mkRequestScript CageConfig
cfg TokenId
tid =
[Char] -> ShortByteString -> Script ConwayEra
scriptFromBytes
[Char]
"mkRequestScript"
(CageConfig -> TokenId -> ShortByteString
requestScriptBytesFromCfg CageConfig
cfg TokenId
tid)
scriptFromBytes
:: String
-> SBS.ShortByteString
-> Script ConwayEra
scriptFromBytes :: [Char] -> ShortByteString -> Script ConwayEra
scriptFromBytes [Char]
label ShortByteString
sbs =
let plutus :: Plutus 'PlutusV3
plutus =
forall (l :: Language). PlutusBinary -> Plutus l
Plutus @PlutusV3 (PlutusBinary -> Plutus 'PlutusV3)
-> PlutusBinary -> Plutus 'PlutusV3
forall a b. (a -> b) -> a -> b
$
ShortByteString -> PlutusBinary
PlutusBinary ShortByteString
sbs
in case Plutus 'PlutusV3 -> Maybe (PlutusScript ConwayEra)
forall era (l :: Language) (m :: * -> *).
(AlonzoEraScript era, PlutusLanguage l, MonadFail m) =>
Plutus l -> m (PlutusScript era)
forall (l :: Language) (m :: * -> *).
(PlutusLanguage l, MonadFail m) =>
Plutus l -> m (PlutusScript ConwayEra)
mkPlutusScript Plutus 'PlutusV3
plutus of
Just PlutusScript ConwayEra
ps -> PlutusScript ConwayEra -> Script ConwayEra
forall era. AlonzoEraScript era => PlutusScript era -> Script era
fromPlutusScript PlutusScript ConwayEra
ps
Maybe (PlutusScript ConwayEra)
Nothing ->
[Char] -> AlonzoScript ConwayEra
forall a. HasCallStack => [Char] -> a
error
( [Char]
label
[Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
": invalid PlutusV3 \
\script"
)
computeScriptHash
:: SBS.ShortByteString
-> ScriptHash
computeScriptHash :: ShortByteString -> ScriptHash
computeScriptHash ShortByteString
sbs =
let plutus :: Plutus 'PlutusV3
plutus =
forall (l :: Language). PlutusBinary -> Plutus l
Plutus @PlutusV3 (PlutusBinary -> Plutus 'PlutusV3)
-> PlutusBinary -> Plutus 'PlutusV3
forall a b. (a -> b) -> a -> b
$
ShortByteString -> PlutusBinary
PlutusBinary ShortByteString
sbs
in case forall era (l :: Language) (m :: * -> *).
(AlonzoEraScript era, PlutusLanguage l, MonadFail m) =>
Plutus l -> m (PlutusScript era)
mkPlutusScript @ConwayEra Plutus 'PlutusV3
plutus of
Just PlutusScript ConwayEra
ps ->
forall era. EraScript era => Script era -> ScriptHash
hashScript @ConwayEra (Script ConwayEra -> ScriptHash) -> Script ConwayEra -> ScriptHash
forall a b. (a -> b) -> a -> b
$
PlutusScript ConwayEra -> Script ConwayEra
forall era. AlonzoEraScript era => PlutusScript era -> Script era
fromPlutusScript PlutusScript ConwayEra
ps
Maybe (PlutusScript ConwayEra)
Nothing ->
[Char] -> ScriptHash
forall a. HasCallStack => [Char] -> a
error
[Char]
"computeScriptHash: invalid \
\PlutusV3 script"
cagePolicyIdFromCfg :: CageConfig -> PolicyID
cagePolicyIdFromCfg :: CageConfig -> PolicyID
cagePolicyIdFromCfg =
ScriptHash -> PolicyID
PolicyID (ScriptHash -> PolicyID)
-> (CageConfig -> ScriptHash) -> CageConfig -> PolicyID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CageConfig -> ScriptHash
cfgScriptHash
cageAddrFromCfg
:: CageConfig
-> Network
-> Addr
cageAddrFromCfg :: CageConfig -> Network -> Addr
cageAddrFromCfg CageConfig
cfg Network
net =
Network -> Credential Payment -> StakeReference -> Addr
Addr
Network
net
(ScriptHash -> Credential Payment
forall (kr :: KeyRole). ScriptHash -> Credential kr
ScriptHashObj (ScriptHash -> Credential Payment)
-> ScriptHash -> Credential Payment
forall a b. (a -> b) -> a -> b
$ CageConfig -> ScriptHash
cfgScriptHash CageConfig
cfg)
StakeReference
StakeRefNull
requestAddrFromCfg
:: CageConfig
-> TokenId
-> Network
-> Addr
requestAddrFromCfg :: CageConfig -> TokenId -> Network -> Addr
requestAddrFromCfg CageConfig
cfg TokenId
tid Network
net =
Network -> Credential Payment -> StakeReference -> Addr
Addr
Network
net
( ScriptHash -> Credential Payment
forall (kr :: KeyRole). ScriptHash -> Credential kr
ScriptHashObj (ScriptHash -> Credential Payment)
-> ScriptHash -> Credential Payment
forall a b. (a -> b) -> a -> b
$
ShortByteString -> ScriptHash
computeScriptHash
(CageConfig -> TokenId -> ShortByteString
requestScriptBytesFromCfg CageConfig
cfg TokenId
tid)
)
StakeReference
StakeRefNull
onChainTokenId :: TokenId -> OnChainTokenId
onChainTokenId :: TokenId -> OnChainTokenId
onChainTokenId TokenId
tid =
BuiltinByteString -> OnChainTokenId
OnChainTokenId (BuiltinByteString -> OnChainTokenId)
-> BuiltinByteString -> OnChainTokenId
forall a b. (a -> b) -> a -> b
$
ByteString -> BuiltinByteString
BuiltinByteString (ByteString -> BuiltinByteString)
-> ByteString -> BuiltinByteString
forall a b. (a -> b) -> a -> b
$
ShortByteString -> ByteString
SBS.fromShort (ShortByteString -> ByteString) -> ShortByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
let AssetName ShortByteString
sbs = TokenId -> AssetName
unTokenId TokenId
tid
in ShortByteString
sbs
requestScriptBytesFromCfg
:: CageConfig
-> TokenId
-> SBS.ShortByteString
requestScriptBytesFromCfg :: CageConfig -> TokenId -> ShortByteString
requestScriptBytesFromCfg CageConfig
cfg TokenId
tid =
ByteString -> OnChainTokenId -> ShortByteString -> ShortByteString
applyRequestParams
(ScriptHash -> ByteString
scriptHashBytes (ScriptHash -> ByteString) -> ScriptHash -> ByteString
forall a b. (a -> b) -> a -> b
$ CageConfig -> ScriptHash
cfgScriptHash CageConfig
cfg)
(TokenId -> OnChainTokenId
onChainTokenId TokenId
tid)
(CageConfig -> ShortByteString
requestScriptBytes CageConfig
cfg)
scriptHashBytes :: ScriptHash -> ByteString
scriptHashBytes :: ScriptHash -> ByteString
scriptHashBytes (ScriptHash Hash ADDRHASH EraIndependentScript
h) =
Hash ADDRHASH EraIndependentScript -> ByteString
forall h a. Hash h a -> ByteString
hashToBytes Hash ADDRHASH EraIndependentScript
h
mkRequestDatum
:: TokenId
-> Addr
-> ByteString
-> Edge
-> Integer
-> Integer
-> PLC.Data
mkRequestDatum :: TokenId
-> Addr -> ByteString -> Integer -> Integer -> Integer -> Data
mkRequestDatum TokenId
tid Addr
addr ByteString
key Integer
edge Integer
deposit Integer
submittedAt =
TokenId
-> Addr
-> ByteString
-> Integer
-> Integer
-> Integer
-> (ByteString, Maybe Data)
-> Data
mkRequestDatumWith
TokenId
tid
Addr
addr
ByteString
key
Integer
edge
Integer
deposit
Integer
submittedAt
(ByteString
BS.empty, Maybe Data
forall a. Maybe a
Nothing)
mkRequestDatumWith
:: TokenId
-> Addr
-> ByteString
-> Edge
-> Integer
-> Integer
-> (ByteString, Maybe PLC.Data)
-> PLC.Data
mkRequestDatumWith :: TokenId
-> Addr
-> ByteString
-> Integer
-> Integer
-> Integer
-> (ByteString, Maybe Data)
-> Data
mkRequestDatumWith TokenId
tid Addr
addr ByteString
key Integer
edge Integer
deposit Integer
submittedAt (ByteString, Maybe Data)
destination =
let datum :: OnChainRequest
datum =
OnChainRequest
{ requestToken :: OnChainTokenId
requestToken = TokenId -> OnChainTokenId
onChainTokenId TokenId
tid
, requestOwner :: BuiltinByteString
requestOwner =
ByteString -> BuiltinByteString
BuiltinByteString
(Addr -> ByteString
addrKeyHashBytes Addr
addr)
, requestKey :: ByteString
requestKey = ByteString
key
, requestEdge :: Integer
requestEdge = Integer
edge
, requestDeposit :: Integer
requestDeposit = Integer
deposit
, requestSubmittedAt :: Integer
requestSubmittedAt = Integer
submittedAt
, requestDestination :: (ByteString, Maybe Data)
requestDestination = (ByteString, Maybe Data)
destination
}
in CageDatum -> Data
forall a. ToData a => a -> Data
toPlcData (OnChainRequest -> CageDatum
RequestDatum OnChainRequest
datum)
toPlcData :: (ToData a) => a -> PLC.Data
toPlcData :: forall a. ToData a => a -> Data
toPlcData a
x =
let BuiltinData Data
d = a -> BuiltinData
forall a. ToData a => a -> BuiltinData
toBuiltinData a
x in Data
d
toLedgerData
:: (ToData a) => a -> Data ConwayEra
toLedgerData :: forall a. ToData a => a -> Data ConwayEra
toLedgerData = Data -> Data ConwayEra
forall era. Era era => Data -> Data era
Data (Data -> Data ConwayEra) -> (a -> Data) -> a -> Data ConwayEra
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Data
forall a. ToData a => a -> Data
toPlcData
mkInlineDatum :: PLC.Data -> Datum ConwayEra
mkInlineDatum :: Data -> Datum ConwayEra
mkInlineDatum Data
d =
BinaryData ConwayEra -> Datum ConwayEra
forall era. BinaryData era -> Datum era
Datum (BinaryData ConwayEra -> Datum ConwayEra)
-> BinaryData ConwayEra -> Datum ConwayEra
forall a b. (a -> b) -> a -> b
$
Data ConwayEra -> BinaryData ConwayEra
forall era. Data era -> BinaryData era
dataToBinaryData
(Data -> Data ConwayEra
forall era. Era era => Data -> Data era
Data Data
d :: Data ConwayEra)
txInToRef :: TxIn -> OnChainTxOutRef
txInToRef :: TxIn -> OnChainTxOutRef
txInToRef (TxIn (TxId SafeHash EraIndependentTxBody
h) (TxIx Word16
ix)) =
OnChainTxOutRef
{ txOutRefId :: BuiltinByteString
txOutRefId =
ByteString -> BuiltinByteString
BuiltinByteString
(Hash HASH EraIndependentTxBody -> ByteString
forall h a. Hash h a -> ByteString
hashToBytes (SafeHash EraIndependentTxBody -> Hash HASH EraIndependentTxBody
forall i. SafeHash i -> Hash HASH i
extractHash SafeHash EraIndependentTxBody
h))
, txOutRefIdx :: Integer
txOutRefIdx = Word16 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
ix
}
addrKeyHashBytes :: Addr -> ByteString
addrKeyHashBytes :: Addr -> ByteString
addrKeyHashBytes
(Addr Network
_ (KeyHashObj (KeyHash Hash ADDRHASH (VerKeyDSIGN DSIGN)
h)) StakeReference
_) =
Hash ADDRHASH (VerKeyDSIGN DSIGN) -> ByteString
forall h a. Hash h a -> ByteString
hashToBytes Hash ADDRHASH (VerKeyDSIGN DSIGN)
h
addrKeyHashBytes Addr
_ = ByteString
BS.empty
addrFromKeyHashBytes
:: Network
-> ByteString
-> Addr
addrFromKeyHashBytes :: Network -> ByteString -> Addr
addrFromKeyHashBytes Network
net ByteString
bs =
case ByteString -> Maybe (Hash ADDRHASH (VerKeyDSIGN DSIGN))
forall h a. HashAlgorithm h => ByteString -> Maybe (Hash h a)
hashFromBytes ByteString
bs of
Just Hash ADDRHASH (VerKeyDSIGN DSIGN)
h ->
Network -> Credential Payment -> StakeReference -> Addr
Addr
Network
net
(KeyHash Payment -> Credential Payment
forall (kr :: KeyRole). KeyHash kr -> Credential kr
KeyHashObj (Hash ADDRHASH (VerKeyDSIGN DSIGN) -> KeyHash Payment
forall (r :: KeyRole).
Hash ADDRHASH (VerKeyDSIGN DSIGN) -> KeyHash r
KeyHash Hash ADDRHASH (VerKeyDSIGN DSIGN)
h))
StakeReference
StakeRefNull
Maybe (Hash ADDRHASH (VerKeyDSIGN DSIGN))
Nothing ->
[Char] -> Addr
forall a. HasCallStack => [Char] -> a
error
[Char]
"addrFromKeyHashBytes: \
\invalid hash"
addrWitnessKeyHash
:: ByteString -> KeyHash Guard
addrWitnessKeyHash :: ByteString -> KeyHash Guard
addrWitnessKeyHash ByteString
bs =
case ByteString -> Maybe (Hash ADDRHASH (VerKeyDSIGN DSIGN))
forall h a. HashAlgorithm h => ByteString -> Maybe (Hash h a)
hashFromBytes ByteString
bs of
Just Hash ADDRHASH (VerKeyDSIGN DSIGN)
h ->
KeyHash Payment -> KeyHash Guard
forall a b. Coercible a b => a -> b
coerce
(Hash ADDRHASH (VerKeyDSIGN DSIGN) -> KeyHash Payment
forall (r :: KeyRole).
Hash ADDRHASH (VerKeyDSIGN DSIGN) -> KeyHash r
KeyHash Hash ADDRHASH (VerKeyDSIGN DSIGN)
h :: KeyHash Payment)
Maybe (Hash ADDRHASH (VerKeyDSIGN DSIGN))
Nothing ->
[Char] -> KeyHash Guard
forall a. HasCallStack => [Char] -> a
error
[Char]
"addrWitnessKeyHash: \
\invalid hash"
extractCageDatum
:: TxOut ConwayEra -> Maybe CageDatum
TxOut ConwayEra
txOut =
case TxOut ConwayEra
BabbageTxOut ConwayEra
txOut BabbageTxOut ConwayEra
-> Getting
(Datum ConwayEra) (BabbageTxOut ConwayEra) (Datum ConwayEra)
-> Datum ConwayEra
forall s a. s -> Getting a s a -> a
^. (Datum ConwayEra -> Const (Datum ConwayEra) (Datum ConwayEra))
-> TxOut ConwayEra -> Const (Datum ConwayEra) (TxOut ConwayEra)
Getting
(Datum ConwayEra) (BabbageTxOut ConwayEra) (Datum ConwayEra)
forall era. BabbageEraTxOut era => Lens' (TxOut era) (Datum era)
Lens' (TxOut ConwayEra) (Datum ConwayEra)
datumTxOutL of
Datum BinaryData ConwayEra
bd ->
let Data Data
plcData =
BinaryData ConwayEra -> Data ConwayEra
forall era. Era era => BinaryData era -> Data era
binaryDataToData BinaryData ConwayEra
bd
in BuiltinData -> Maybe CageDatum
forall a. FromData a => BuiltinData -> Maybe a
fromBuiltinData (Data -> BuiltinData
BuiltinData Data
plcData)
Datum ConwayEra
_ -> Maybe CageDatum
forall a. Maybe a
Nothing
extractOwnerBytes
:: TxOut ConwayEra -> ByteString
TxOut ConwayEra
out =
case TxOut ConwayEra -> Maybe CageDatum
extractCageDatum TxOut ConwayEra
out of
Just (RequestDatum OnChainRequest
req) ->
let OnChainRequest
{ requestOwner :: OnChainRequest -> BuiltinByteString
requestOwner =
BuiltinByteString ByteString
bs
} = OnChainRequest
req
in ByteString
bs
Maybe CageDatum
_ ->
[Char] -> ByteString
forall a. HasCallStack => [Char] -> a
error
[Char]
"extractOwnerBytes: \
\not a request"
policyIdFromPin :: SBS.ShortByteString -> PolicyID
policyIdFromPin :: ShortByteString -> PolicyID
policyIdFromPin ShortByteString
pin = case ByteString -> Maybe (Hash ADDRHASH EraIndependentScript)
forall h a. HashAlgorithm h => ByteString -> Maybe (Hash h a)
hashFromBytes (ShortByteString -> ByteString
SBS.fromShort ShortByteString
pin) of
Just Hash ADDRHASH EraIndependentScript
h -> ScriptHash -> PolicyID
PolicyID (Hash ADDRHASH EraIndependentScript -> ScriptHash
ScriptHash Hash ADDRHASH EraIndependentScript
h)
Maybe (Hash ADDRHASH EraIndependentScript)
Nothing ->
[Char] -> PolicyID
forall a. HasCallStack => [Char] -> a
error
( [Char]
"policyIdFromPin: a pin is not a 28-byte script hash: "
[Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> ShortByteString -> [Char]
forall a. Show a => a -> [Char]
show ShortByteString
pin
)
addrFromBytes :: ByteString -> Maybe Addr
addrFromBytes :: ByteString -> Maybe Addr
addrFromBytes ByteString
bs = case ByteString -> Either [Char] Addr
decodeAddrEither ByteString
bs of
Right Addr
a -> Addr -> Maybe Addr
forall a. a -> Maybe a
Just Addr
a
Left [Char]
_ -> Maybe Addr
forall a. Maybe a
Nothing