mirror of https://github.com/voidlizard/hbs2
200 lines
5.5 KiB
Haskell
200 lines
5.5 KiB
Haskell
{-# LANGUAGE AllowAmbiguousTypes #-}
|
|
{-# LANGUAGE TypeOperators #-}
|
|
{-# LANGUAGE UndecidableInstances #-}
|
|
|
|
module RefChanQBLF.Transactions where
|
|
|
|
import Data.String.Conversions (cs)
|
|
import HBS2.Base58
|
|
import HBS2.Data.Types.Refs (HashRef (..))
|
|
import HBS2.Data.Types.SignedBox
|
|
import HBS2.Hash
|
|
import HBS2.Net.Auth.Credentials
|
|
import HBS2.Net.Messaging.Unix (UNIX)
|
|
import HBS2.Peer.Proto
|
|
import HBS2.Prelude.Plated
|
|
|
|
import Codec.Serialise
|
|
import Control.Arrow hiding ((<+>))
|
|
import Data.ByteString.Lazy (ByteString)
|
|
import Data.Hashable (Hashable (..))
|
|
import Data.Word (Word64)
|
|
import System.Random
|
|
|
|
import RefChanQBLF.Common
|
|
|
|
newtype Actor s = Actor {fromActor :: PubKey 'Sign s}
|
|
deriving stock (Generic)
|
|
|
|
deriving stock instance (Eq (PubKey 'Sign s)) => Eq (Actor s)
|
|
deriving newtype instance (Hashable (PubKey 'Sign s)) => Hashable (Actor s)
|
|
|
|
instance (Pretty (AsBase58 (PubKey 'Sign s))) => Pretty (Actor s) where
|
|
pretty (Actor a) = pretty (AsBase58 a)
|
|
|
|
type Account s = PubKey 'Sign s
|
|
|
|
newtype Amount = Amount Integer
|
|
deriving stock (Eq, Show, Ord, Data, Generic)
|
|
deriving newtype (Read, Enum, Num, Integral, Real, Pretty)
|
|
|
|
newtype DAppState = DAppState {fromDAppState :: HashRef}
|
|
deriving stock (Eq, Show, Ord, Data, Generic)
|
|
deriving newtype (Hashable, Pretty)
|
|
|
|
instance Hashed HbSync DAppState where
|
|
hashObject (DAppState (HashRef h)) = h
|
|
|
|
data EmitTx s = EmitTx (Account s) Amount Word64
|
|
deriving stock (Generic)
|
|
|
|
instance (Pretty (AsBase58 (PubKey 'Sign s))) => Pretty (EmitTx s) where
|
|
pretty (EmitTx acc amount n) =
|
|
"Emit"
|
|
<+> "to:"
|
|
<> pretty (AsBase58 acc)
|
|
<+> "amount:"
|
|
<> pretty amount
|
|
<+> "nonce:"
|
|
<> pretty n
|
|
|
|
data MoveTx s = MoveTx (Account s) (Account s) Amount Word64
|
|
deriving stock (Generic)
|
|
|
|
instance (Pretty (AsBase58 (PubKey 'Sign s))) => Pretty (MoveTx s) where
|
|
pretty (MoveTx accfrom accto amount n) =
|
|
"Move"
|
|
<+> "from:"
|
|
<> pretty (AsBase58 accfrom)
|
|
<+> "to:"
|
|
<> pretty (AsBase58 accto)
|
|
<+> "amount:"
|
|
<> pretty amount
|
|
<+> "nonce:"
|
|
<> pretty n
|
|
|
|
data QBLFDemoToken s
|
|
= Emit (SignedBox (EmitTx s) s) -- proof: owner's key
|
|
| Move (SignedBox (MoveTx s) s) -- proof: wallet's key
|
|
deriving stock (Generic)
|
|
|
|
instance
|
|
( Pretty (AsBase58 (PubKey 'Sign s))
|
|
, Signatures s
|
|
, Eq (Signature s)
|
|
, FromStringMaybe (PubKey 'Sign s)
|
|
, Serialise (PubKey 'Sign s)
|
|
, Serialise (Signature s)
|
|
, Hashable (PubKey 'Sign s)
|
|
)
|
|
=> Pretty (QBLFDemoToken s)
|
|
where
|
|
pretty = \case
|
|
Emit box -> pretty (WhiteSignedBox @s box)
|
|
Move box -> pretty (WhiteSignedBox @s box)
|
|
|
|
newtype WhiteSignedBox s a = WhiteSignedBox (SignedBox a s)
|
|
|
|
instance
|
|
( Pretty (AsBase58 (PubKey 'Sign s))
|
|
, Pretty a
|
|
, Serialise a
|
|
)
|
|
=> Pretty (WhiteSignedBox s a)
|
|
where
|
|
pretty (WhiteSignedBox (SignedBox pk bs _sign)) =
|
|
"SignedBox"
|
|
<+> "Hash:"
|
|
<+> pretty ((hashObject @HbSync . serialise) bs)
|
|
<+> "SignedBy:"
|
|
<+> pretty (AsBase58 pk)
|
|
<+> "("
|
|
<> pretty ((PrettyEither . left show . deserialiseOrFail @a . cs) bs)
|
|
<> ")"
|
|
|
|
instance (ForQBLFDemoToken s) => Serialise (Actor s)
|
|
|
|
instance Serialise DAppState
|
|
|
|
instance Serialise Amount
|
|
|
|
instance (ForQBLFDemoToken s) => Serialise (EmitTx s)
|
|
|
|
instance (ForQBLFDemoToken s) => Serialise (MoveTx s)
|
|
|
|
instance (ForQBLFDemoToken s) => Serialise (QBLFDemoToken s)
|
|
|
|
type ForQBLFDemoToken s =
|
|
( Eq (PubKey 'Sign s)
|
|
, Eq (Signature s)
|
|
, Pretty (AsBase58 (PubKey 'Sign s))
|
|
, ForSignedBox s
|
|
, FromStringMaybe (PubKey 'Sign s)
|
|
, Serialise (PubKey 'Sign s)
|
|
, Serialise (Signature s)
|
|
, Hashable (PubKey 'Sign s)
|
|
)
|
|
|
|
deriving stock instance (ForQBLFDemoToken s) => Eq (QBLFDemoToken s)
|
|
|
|
instance (ForQBLFDemoToken s) => Hashable (QBLFDemoToken s) where
|
|
hashWithSalt salt = \case
|
|
Emit box -> hashWithSalt salt box
|
|
Move box -> hashWithSalt salt box
|
|
|
|
newtype QBLFDemoTran e
|
|
= QBLFDemoTran (SignedBox (QBLFDemoToken (Encryption e)) (Encryption e))
|
|
deriving stock (Generic)
|
|
|
|
instance (ForRefChans e) => Serialise (QBLFDemoTran e)
|
|
|
|
deriving newtype instance
|
|
(Eq (PubKey 'Sign (Encryption e)), Eq (Signature (Encryption e)))
|
|
=> Eq (QBLFDemoTran e)
|
|
|
|
deriving newtype instance
|
|
(Eq (Signature (Encryption e)), ForRefChans e)
|
|
=> Hashable (QBLFDemoTran e)
|
|
|
|
instance HasProtocol UNIX (QBLFDemoTran UNIX) where
|
|
type ProtocolId (QBLFDemoTran UNIX) = 0xFFFF0001
|
|
type Encoded UNIX = ByteString
|
|
decode = either (const Nothing) Just . deserialiseOrFail
|
|
encode = serialise
|
|
|
|
makeEmitDemoToken
|
|
:: forall s e m
|
|
. ( MonadIO m
|
|
, ForRefChans e
|
|
, ForQBLFDemoToken s
|
|
, Signatures (Encryption e)
|
|
, s ~ Encryption e
|
|
)
|
|
=> PubKey 'Sign s
|
|
-> PrivKey 'Sign s
|
|
-> Account s
|
|
-> Amount
|
|
-> m (QBLFDemoToken s)
|
|
makeEmitDemoToken pk sk acc amount = do
|
|
nonce <- randomIO
|
|
let box = makeSignedBox @s pk sk (EmitTx acc amount nonce)
|
|
pure (Emit @s box)
|
|
|
|
makeMoveDemoToken
|
|
:: forall s e m
|
|
. ( MonadIO m
|
|
, ForQBLFDemoToken s
|
|
, ForRefChans e
|
|
, Signatures s
|
|
, s ~ Encryption e
|
|
)
|
|
=> PubKey 'Sign s -- from pk
|
|
-> PrivKey 'Sign s -- from sk
|
|
-> Account s
|
|
-> Amount -- amount
|
|
-> m (QBLFDemoToken s)
|
|
makeMoveDemoToken pk sk acc amount = do
|
|
nonce <- randomIO
|
|
let box = makeSignedBox @s pk sk (MoveTx pk acc amount nonce)
|
|
pure (Move @s box)
|