{-# OPTIONS_GHC -Wno-orphans #-}
module Cooked.Attack.DoubleSat
( DoubleSatDelta,
DoubleSatLbl (..),
doubleSatAttack,
)
where
import Control.Monad
import Cooked.MockChain.Read
import Cooked.Pretty.Class
import Cooked.Skeleton
import Cooked.Tweak.Common
import Cooked.Tweak.Inputs
import Cooked.Tweak.Labels
import Cooked.Tweak.Mint
import Cooked.Tweak.Outputs
import Data.Map (Map)
import Data.Map qualified as Map
import Optics.Core
import Plutus.Script.Utils.Value qualified as Script
import PlutusLedgerApi.V1.Value qualified as Api
import PlutusLedgerApi.V3 qualified as Api
import PlutusTx.Numeric qualified as PlutusTx
import Polysemy
import Polysemy.NonDet
type DoubleSatDelta = (Map Api.TxOutRef TxSkelRedeemer, [TxSkelOut], TxSkelMints)
instance {-# OVERLAPPING #-} Semigroup DoubleSatDelta where
(Map TxOutRef TxSkelRedeemer
i, [TxSkelOut]
o, TxSkelMints
m) <> :: DoubleSatDelta -> DoubleSatDelta -> DoubleSatDelta
<> (Map TxOutRef TxSkelRedeemer
i', [TxSkelOut]
o', TxSkelMints
m') =
( Map TxOutRef TxSkelRedeemer
i Map TxOutRef TxSkelRedeemer
-> Map TxOutRef TxSkelRedeemer -> Map TxOutRef TxSkelRedeemer
forall a. Semigroup a => a -> a -> a
<> Map TxOutRef TxSkelRedeemer
i',
[TxSkelOut]
o [TxSkelOut] -> [TxSkelOut] -> [TxSkelOut]
forall a. [a] -> [a] -> [a]
++ [TxSkelOut]
o',
TxSkelMints
m TxSkelMints -> TxSkelMints -> TxSkelMints
forall a. Semigroup a => a -> a -> a
<> TxSkelMints
m'
)
instance {-# OVERLAPPING #-} Monoid DoubleSatDelta where
mempty :: DoubleSatDelta
mempty = (Map TxOutRef TxSkelRedeemer
forall k a. Map k a
Map.empty, [], TxSkelMints
forall a. Monoid a => a
mempty)
doubleSatAttack ::
forall effs is k owner a.
( Members '[Tweak, NonDet, MockChainRead] effs,
Eq is,
Is k A_Traversal,
IsTxSkelOutAllowedOwner owner
) =>
([is] -> [[is]]) ->
Optic' k (WithIx is) TxSkel a ->
(is -> a -> Sem effs [(a, DoubleSatDelta)]) ->
owner ->
Sem effs ()
doubleSatAttack :: forall (effs :: EffectRow) is k owner a.
(Members '[Tweak, NonDet, MockChainRead] effs, Eq is,
Is k A_Traversal, IsTxSkelOutAllowedOwner owner) =>
([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel a
-> (is -> a -> Sem effs [(a, DoubleSatDelta)])
-> owner
-> Sem effs ()
doubleSatAttack [is] -> [[is]]
groupings Optic' k (WithIx is) TxSkel a
optic is -> a -> Sem effs [(a, DoubleSatDelta)]
change owner
target = do
[DoubleSatDelta]
deltas <- ([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel a
-> (is -> a -> Sem effs [(a, DoubleSatDelta)])
-> Sem effs [DoubleSatDelta]
forall is k (effs :: EffectRow) x l.
(Eq is, Is k A_Traversal, Members '[Tweak, NonDet] effs) =>
([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel x
-> (is -> x -> Sem effs [(x, l)])
-> Sem effs [l]
combineModsTweak [is] -> [[is]]
groupings Optic' k (WithIx is) TxSkel a
optic is -> a -> Sem effs [(a, DoubleSatDelta)]
change
let delta :: DoubleSatDelta
delta = [DoubleSatDelta] -> DoubleSatDelta
joinDoubleSatDeltas [DoubleSatDelta]
deltas
DoubleSatDelta -> Sem effs ()
addDoubleSatDeltaTweak DoubleSatDelta
delta
Value
addedValue <- DoubleSatDelta -> Sem effs Value
deltaBalance DoubleSatDelta
delta
if Value
addedValue Value -> Value -> Bool
`Api.gt` Value
forall a. Monoid a => a
mempty
then TxSkelOut -> Sem effs ()
forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelOut -> Sem effs ()
addOutputTweak (TxSkelOut -> Sem effs ()) -> TxSkelOut -> Sem effs ()
forall a b. (a -> b) -> a -> b
$ owner
target owner -> Payable '[ 'IsValue] -> TxSkelOut
forall owner (els :: [PayableKind]).
IsTxSkelOutAllowedOwner owner =>
owner -> Payable els -> TxSkelOut
`receives` Value -> Payable '[ 'IsValue]
forall a1. ToValue a1 => a1 -> Payable '[ 'IsValue]
Value Value
addedValue
else Sem effs ()
forall a. Sem effs a
forall (m :: * -> *) a. MonadPlus m => m a
mzero
DoubleSatLbl -> Sem effs ()
forall lbl (effs :: EffectRow).
(LabelConstrs lbl, Member Tweak effs) =>
lbl -> Sem effs ()
addLabelTweak DoubleSatLbl
DoubleSatLbl
where
deltaBalance :: DoubleSatDelta -> Sem effs Api.Value
deltaBalance :: DoubleSatDelta -> Sem effs Value
deltaBalance (Map TxOutRef TxSkelRedeemer
inputs, [TxSkelOut]
outputs, TxSkelMints
mints) = do
Value
inValue <- ((TxOutRef, TxSkelOut) -> Value)
-> [(TxOutRef, TxSkelOut)] -> Value
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Optic' A_Lens NoIx TxSkelOut Value -> TxSkelOut -> Value
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL (TxSkelOut -> Value)
-> ((TxOutRef, TxSkelOut) -> TxSkelOut)
-> (TxOutRef, TxSkelOut)
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxOutRef, TxSkelOut) -> TxSkelOut
forall a b. (a, b) -> b
snd) ([(TxOutRef, TxSkelOut)] -> Value)
-> ([(TxOutRef, TxSkelOut)] -> [(TxOutRef, TxSkelOut)])
-> [(TxOutRef, TxSkelOut)]
-> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((TxOutRef, TxSkelOut) -> Bool)
-> [(TxOutRef, TxSkelOut)] -> [(TxOutRef, TxSkelOut)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((TxOutRef -> [TxOutRef] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Map TxOutRef TxSkelRedeemer -> [TxOutRef]
forall k a. Map k a -> [k]
Map.keys Map TxOutRef TxSkelRedeemer
inputs) (TxOutRef -> Bool)
-> ((TxOutRef, TxSkelOut) -> TxOutRef)
-> (TxOutRef, TxSkelOut)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TxOutRef, TxSkelOut) -> TxOutRef
forall a b. (a, b) -> a
fst) ([(TxOutRef, TxSkelOut)] -> Value)
-> Sem effs [(TxOutRef, TxSkelOut)] -> Sem effs Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem effs [(TxOutRef, TxSkelOut)]
forall (effs :: EffectRow).
Member MockChainRead effs =>
Sem effs [(TxOutRef, TxSkelOut)]
allUtxos
Value -> Sem effs Value
forall a. a -> Sem effs a
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> Sem effs Value) -> Value -> Sem effs Value
forall a b. (a -> b) -> a -> b
$ Value
inValue Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> Value -> Value
forall a. AdditiveGroup a => a -> a
PlutusTx.negate (Optic' A_Traversal NoIx [TxSkelOut] Value -> [TxSkelOut] -> Value
forall k a (is :: IxList) s.
(Is k A_Fold, Monoid a) =>
Optic' k is s a -> s -> a
foldOf (Traversal [TxSkelOut] [TxSkelOut] TxSkelOut TxSkelOut
forall (t :: * -> *) a b.
Traversable t =>
Traversal (t a) (t b) a b
traversed Traversal [TxSkelOut] [TxSkelOut] TxSkelOut TxSkelOut
-> Optic' A_Lens NoIx TxSkelOut Value
-> Optic' A_Traversal NoIx [TxSkelOut] Value
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic' A_Lens NoIx TxSkelOut Value
txSkelOutValueL) [TxSkelOut]
outputs) Value -> Value -> Value
forall a. Semigroup a => a -> a -> a
<> TxSkelMints -> Value
forall a. ToValue a => a -> Value
Script.toValue TxSkelMints
mints
addDoubleSatDeltaTweak :: DoubleSatDelta -> Sem effs ()
addDoubleSatDeltaTweak :: DoubleSatDelta -> Sem effs ()
addDoubleSatDeltaTweak (Map TxOutRef TxSkelRedeemer
ins, [TxSkelOut]
outs, TxSkelMints
mints) =
((TxOutRef, TxSkelRedeemer) -> Sem effs ())
-> [(TxOutRef, TxSkelRedeemer)] -> Sem effs ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((TxOutRef -> TxSkelRedeemer -> Sem effs ())
-> (TxOutRef, TxSkelRedeemer) -> Sem effs ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry TxOutRef -> TxSkelRedeemer -> Sem effs ()
forall (effs :: EffectRow).
Members '[Tweak, NonDet] effs =>
TxOutRef -> TxSkelRedeemer -> Sem effs ()
addInputTweak) (Map TxOutRef TxSkelRedeemer -> [(TxOutRef, TxSkelRedeemer)]
forall k a. Map k a -> [(k, a)]
Map.toList Map TxOutRef TxSkelRedeemer
ins)
Sem effs () -> Sem effs () -> Sem effs ()
forall a b. Sem effs a -> Sem effs b -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (TxSkelOut -> Sem effs ()) -> [TxSkelOut] -> Sem effs ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ TxSkelOut -> Sem effs ()
forall (effs :: EffectRow).
Member Tweak effs =>
TxSkelOut -> Sem effs ()
addOutputTweak [TxSkelOut]
outs
Sem effs () -> Sem effs () -> Sem effs ()
forall a b. Sem effs a -> Sem effs b -> Sem effs b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Mint] -> Sem effs ()
forall (effs :: EffectRow).
Member Tweak effs =>
[Mint] -> Sem effs ()
addMintsTweak (Optic' An_Iso NoIx TxSkelMints [Mint] -> TxSkelMints -> [Mint]
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' An_Iso NoIx TxSkelMints [Mint]
txSkelMintsListI TxSkelMints
mints)
joinDoubleSatDeltas :: [DoubleSatDelta] -> DoubleSatDelta
joinDoubleSatDeltas :: [DoubleSatDelta] -> DoubleSatDelta
joinDoubleSatDeltas = [DoubleSatDelta] -> DoubleSatDelta
forall a. Monoid a => [a] -> a
mconcat
data DoubleSatLbl = DoubleSatLbl
deriving (DoubleSatLbl -> DoubleSatLbl -> Bool
(DoubleSatLbl -> DoubleSatLbl -> Bool)
-> (DoubleSatLbl -> DoubleSatLbl -> Bool) -> Eq DoubleSatLbl
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DoubleSatLbl -> DoubleSatLbl -> Bool
== :: DoubleSatLbl -> DoubleSatLbl -> Bool
$c/= :: DoubleSatLbl -> DoubleSatLbl -> Bool
/= :: DoubleSatLbl -> DoubleSatLbl -> Bool
Eq, Int -> DoubleSatLbl -> ShowS
[DoubleSatLbl] -> ShowS
DoubleSatLbl -> String
(Int -> DoubleSatLbl -> ShowS)
-> (DoubleSatLbl -> String)
-> ([DoubleSatLbl] -> ShowS)
-> Show DoubleSatLbl
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DoubleSatLbl -> ShowS
showsPrec :: Int -> DoubleSatLbl -> ShowS
$cshow :: DoubleSatLbl -> String
show :: DoubleSatLbl -> String
$cshowList :: [DoubleSatLbl] -> ShowS
showList :: [DoubleSatLbl] -> ShowS
Show, Eq DoubleSatLbl
Eq DoubleSatLbl =>
(DoubleSatLbl -> DoubleSatLbl -> Ordering)
-> (DoubleSatLbl -> DoubleSatLbl -> Bool)
-> (DoubleSatLbl -> DoubleSatLbl -> Bool)
-> (DoubleSatLbl -> DoubleSatLbl -> Bool)
-> (DoubleSatLbl -> DoubleSatLbl -> Bool)
-> (DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl)
-> (DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl)
-> Ord DoubleSatLbl
DoubleSatLbl -> DoubleSatLbl -> Bool
DoubleSatLbl -> DoubleSatLbl -> Ordering
DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: DoubleSatLbl -> DoubleSatLbl -> Ordering
compare :: DoubleSatLbl -> DoubleSatLbl -> Ordering
$c< :: DoubleSatLbl -> DoubleSatLbl -> Bool
< :: DoubleSatLbl -> DoubleSatLbl -> Bool
$c<= :: DoubleSatLbl -> DoubleSatLbl -> Bool
<= :: DoubleSatLbl -> DoubleSatLbl -> Bool
$c> :: DoubleSatLbl -> DoubleSatLbl -> Bool
> :: DoubleSatLbl -> DoubleSatLbl -> Bool
$c>= :: DoubleSatLbl -> DoubleSatLbl -> Bool
>= :: DoubleSatLbl -> DoubleSatLbl -> Bool
$cmax :: DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl
max :: DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl
$cmin :: DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl
min :: DoubleSatLbl -> DoubleSatLbl -> DoubleSatLbl
Ord)
instance PrettyCooked DoubleSatLbl where
prettyCooked :: DoubleSatLbl -> DocCooked
prettyCooked DoubleSatLbl
_ = DocCooked
"DoubleSat"