{-# OPTIONS_GHC -Wno-orphans #-}
module Cooked.Attack.DoubleSat
( DoubleSatDelta,
DoubleSatLbl (..),
doubleSatAttack,
)
where
import Cooked.MockChain.BlockChain
import Cooked.Pretty
import Cooked.Skeleton
import Cooked.Tweak
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
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 ::
(MonadTweak m, Eq is, Is k A_Traversal, IsTxSkelOutAllowedOwner owner) =>
([is] -> [[is]]) ->
Optic' k (WithIx is) TxSkel a ->
(is -> a -> m [(a, DoubleSatDelta)]) ->
owner ->
m ()
doubleSatAttack :: forall (m :: * -> *) is k owner a.
(MonadTweak m, Eq is, Is k A_Traversal,
IsTxSkelOutAllowedOwner owner) =>
([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel a
-> (is -> a -> m [(a, DoubleSatDelta)])
-> owner
-> m ()
doubleSatAttack [is] -> [[is]]
groupings Optic' k (WithIx is) TxSkel a
optic is -> a -> m [(a, DoubleSatDelta)]
change owner
target = do
[DoubleSatDelta]
deltas <- ([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel a
-> (is -> a -> m [(a, DoubleSatDelta)])
-> m [DoubleSatDelta]
forall is k (m :: * -> *) x l.
(Eq is, Is k A_Traversal, MonadTweak m) =>
([is] -> [[is]])
-> Optic' k (WithIx is) TxSkel x
-> (is -> x -> m [(x, l)])
-> m [l]
combineModsTweak [is] -> [[is]]
groupings Optic' k (WithIx is) TxSkel a
optic is -> a -> m [(a, DoubleSatDelta)]
change
let delta :: DoubleSatDelta
delta = [DoubleSatDelta] -> DoubleSatDelta
joinDoubleSatDeltas [DoubleSatDelta]
deltas
DoubleSatDelta -> m ()
forall (m :: * -> *). MonadTweak m => DoubleSatDelta -> m ()
addDoubleSatDeltaTweak DoubleSatDelta
delta
Value
addedValue <- DoubleSatDelta -> m Value
forall (m :: * -> *). MonadTweak m => DoubleSatDelta -> m Value
deltaBalance DoubleSatDelta
delta
if Value
addedValue Value -> Value -> Bool
`Api.gt` Value
forall a. Monoid a => a
mempty
then TxSkelOut -> m ()
forall (m :: * -> *). MonadTweak m => TxSkelOut -> m ()
addOutputTweak (TxSkelOut -> m ()) -> TxSkelOut -> m ()
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 m ()
forall (m :: * -> *) a. MonadTweak m => m a
failingTweak
DoubleSatLbl -> m ()
forall (m :: * -> *) x. (MonadTweak m, LabelConstrs x) => x -> m ()
addLabelTweak DoubleSatLbl
DoubleSatLbl
where
deltaBalance :: (MonadTweak m) => DoubleSatDelta -> m Api.Value
deltaBalance :: forall (m :: * -> *). MonadTweak m => DoubleSatDelta -> m 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)
-> m [(TxOutRef, TxSkelOut)] -> m Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m [(TxOutRef, TxSkelOut)]
forall (m :: * -> *).
MonadBlockChainWithoutValidation m =>
m [(TxOutRef, TxSkelOut)]
allUtxos
Value -> m Value
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Value -> m Value) -> Value -> m 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 :: (MonadTweak m) => DoubleSatDelta -> m ()
addDoubleSatDeltaTweak :: forall (m :: * -> *). MonadTweak m => DoubleSatDelta -> m ()
addDoubleSatDeltaTweak (Map TxOutRef TxSkelRedeemer
ins, [TxSkelOut]
outs, TxSkelMints
mints) =
((TxOutRef, TxSkelRedeemer) -> m ())
-> [(TxOutRef, TxSkelRedeemer)] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((TxOutRef -> TxSkelRedeemer -> m ())
-> (TxOutRef, TxSkelRedeemer) -> m ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry TxOutRef -> TxSkelRedeemer -> m ()
forall (m :: * -> *).
MonadTweak m =>
TxOutRef -> TxSkelRedeemer -> m ()
addInputTweak) (Map TxOutRef TxSkelRedeemer -> [(TxOutRef, TxSkelRedeemer)]
forall k a. Map k a -> [(k, a)]
Map.toList Map TxOutRef TxSkelRedeemer
ins)
m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (TxSkelOut -> m ()) -> [TxSkelOut] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ TxSkelOut -> m ()
forall (m :: * -> *). MonadTweak m => TxSkelOut -> m ()
addOutputTweak [TxSkelOut]
outs
m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Mint] -> m ()
forall (m :: * -> *). MonadTweak m => [Mint] -> m ()
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"