-- |
-- Module      :  Network.Polkadot.Extrinsic.Payload
-- Copyright   :  Aleksandr Krupenkin 2016-2024
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  portable
--
-- Extrinsic payload and payload signing methods.
--

module Network.Polkadot.Extrinsic.Payload where

import           Codec.Scale                                (encode)
import           Codec.Scale.Class                          (Encode (..))
import qualified Data.ByteString                            as BS (length)
import           Data.Digest.Blake2                         (blake2_256)
import           Network.JsonRpc.TinyClient                 (JsonRpc)

import           Network.Polkadot.Crypto                    (MultiPair (MultiSignature, multi_sign))
import           Network.Polkadot.Extrinsic.SignedExtension (SignedExtension (..))

-- | A payload that has been signed for an unchecked extrinsics.
--
-- Note that the payload that we sign to produce unchecked extrinsic signature
-- is going to be different than the `Payload` - so the thing the extrinsic
-- actually contains.
type Payload call extra = (call, extra)

-- | Sign extrinsic's payload by multi-pair.
sign_payload :: (MultiPair a, Encode c, SignedExtension e, JsonRpc m)
             => a
             -> Payload c e
             -> m (MultiSignature a)
sign_payload :: forall a c e (m :: * -> *).
(MultiPair a, Encode c, SignedExtension e, JsonRpc m) =>
a -> Payload c e -> m (MultiSignature a)
sign_payload a
pair (c
call, e
extra) = do
    AdditionalSigned e
additional <- e -> m (AdditionalSigned e)
forall a (m :: * -> *).
(SignedExtension a, JsonRpc m) =>
a -> m (AdditionalSigned a)
forall (m :: * -> *). JsonRpc m => e -> m (AdditionalSigned e)
additional_signed e
extra
    let encoded :: ByteString
encoded = (c, e, AdditionalSigned e) -> ByteString
forall a ba. (Encode a, ByteArray ba) => a -> ba
encode (c
call, e
extra, AdditionalSigned e
additional)
        payload :: ByteString
payload | ByteString -> Int
BS.length ByteString
encoded Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
256 = ByteString -> ByteString
blake2_256 ByteString
encoded
                | Bool
otherwise = ByteString
encoded
    MultiSignature a -> m (MultiSignature a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MultiSignature a -> m (MultiSignature a))
-> MultiSignature a -> m (MultiSignature a)
forall a b. (a -> b) -> a -> b
$ a -> ByteString -> MultiSignature a
forall ba. ByteArrayAccess ba => a -> ba -> MultiSignature a
forall a ba.
(MultiPair a, ByteArrayAccess ba) =>
a -> ba -> MultiSignature a
multi_sign a
pair ByteString
payload