Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Cooked.Tweak.Common
Contents
Description
This module defines Tweaks
which are the fundamental building blocks of
our "domain specific language" for attacks. They are essentially skeleton
modifications aware of the mockchain state.
Synopsis
- runTweakInChain :: MonadPlus m => Tweak m a -> TxSkel -> m (a, TxSkel)
- runTweakInChain' :: MonadBlockChainWithoutValidation m => Tweak m a -> TxSkel -> m [(a, TxSkel)]
- type Tweak m = StateT TxSkel (ListT m)
- data UntypedTweak m where
- UntypedTweak :: Tweak m a -> UntypedTweak m
- class (MonadPlus m, MonadBlockChainWithoutValidation m) => MonadTweak m where
- failingTweak :: MonadTweak m => m a
- doNothingTweak :: MonadTweak m => m ()
- viewTweak :: (MonadTweak m, Is k A_Getter) => Optic' k is TxSkel a -> m a
- viewAllTweak :: (MonadTweak m, Is k A_Fold) => Optic' k is TxSkel a -> m [a]
- setTweak :: (MonadTweak m, Is k A_Setter) => Optic' k is TxSkel a -> a -> m ()
- overTweak :: (MonadTweak m, Is k A_Setter) => Optic' k is TxSkel a -> (a -> a) -> m ()
- overMaybeTweak :: (MonadTweak m, Is k A_Traversal) => Optic' k is TxSkel a -> (a -> Maybe a) -> m [a]
- overMaybeSelectingTweak :: forall a m k is. (MonadTweak m, Is k A_Traversal) => Optic' k is TxSkel a -> (a -> Maybe a) -> (Integer -> Bool) -> m [a]
- selectP :: (a -> Bool) -> Prism' a a
- combineModsTweak :: (Eq is, Is k A_Traversal, MonadTweak m) => ([is] -> [[is]]) -> Optic' k (WithIx is) TxSkel x -> (is -> x -> m [(x, l)]) -> m [l]
- iviewTweak :: (MonadTweak m, Is k A_Getter) => Optic' k (WithIx is) TxSkel a -> m (is, a)
Documentation
runTweakInChain :: MonadPlus m => Tweak m a -> TxSkel -> m (a, TxSkel) Source #
This is the function that gives a meaning to Tweak
s: A Tweak
is a
computation that, depending on the state of the chain, looks at a transaction
and returns zero or more modified transactions, together with some additional
values.
Our intuition (and also the language of the comments pertaining to Tweak
s)
is that a Tweak
t
- fails if
runTweakInChain t skel
ismzero
. - returns the value in the first component of the pair returned by this
function (which is also the value it returns in the monad
Tweak m
). - modifies a
TxSkel
. Since it can use every method ofMonadBlockChainWithoutValidateTxSkel
to do so, this also includes stateful lookups or even things like waiting for a certain amount of time before submitting the transaction.
If you're using tweaks in a MonadModalBlockChain
together with mechanisms
like withTweak
, somewhere
, or everywhere
, you should never have areason
to use this function.
runTweakInChain' :: MonadBlockChainWithoutValidation m => Tweak m a -> TxSkel -> m [(a, TxSkel)] Source #
Like runTweakInChain
, but for when you want to explicitly apply a tweak
to a transaction skeleton and get all results as a list.
If you're trying to apply a tweak to a transaction directly before it's
modified, consider using MonadModalBlockChain
and idioms like withTweak
,
somewhere
, or everywhere
.
data UntypedTweak m where Source #
This is a wrapper type used in the implementation of the Staged monad. You
will probably never use it while you're building Tweak
s.
Constructors
UntypedTweak :: Tweak m a -> UntypedTweak m |
Instances
User API
class (MonadPlus m, MonadBlockChainWithoutValidation m) => MonadTweak m where Source #
failingTweak :: MonadTweak m => m a Source #
The never-applicable tweak.
doNothingTweak :: MonadTweak m => m () Source #
The tweak that always applies and leaves the transaction unchanged.
viewTweak :: (MonadTweak m, Is k A_Getter) => Optic' k is TxSkel a -> m a Source #
The "tweak" that obtains some value from the TxSkel
. This does *not*
modify the transaction.
viewAllTweak :: (MonadTweak m, Is k A_Fold) => Optic' k is TxSkel a -> m [a] Source #
Like the viewTweak
, but returns a list of all foci
setTweak :: (MonadTweak m, Is k A_Setter) => Optic' k is TxSkel a -> a -> m () Source #
The tweak that sets a certain value in the TxSkel
.
overTweak :: (MonadTweak m, Is k A_Setter) => Optic' k is TxSkel a -> (a -> a) -> m () Source #
The tweak that modifies a certain value in the TxSkel
.
overMaybeTweak :: (MonadTweak m, Is k A_Traversal) => Optic' k is TxSkel a -> (a -> Maybe a) -> m [a] Source #
Like overTweak
, but only modifies foci on which the argument function
returns Just
the new focus. Returns a list of the foci that were modified,
as they were before the tweak, and in the order in which they occurred on
the original transaction.
overMaybeSelectingTweak :: forall a m k is. (MonadTweak m, Is k A_Traversal) => Optic' k is TxSkel a -> (a -> Maybe a) -> (Integer -> Bool) -> m [a] Source #
Sometimes overMaybeTweak
modifies too many foci. This might be the case
if there are several identical foci, but you only want to modify some of
them. This is where this Tweak
becomes useful: The (Integer -> Bool)
argument can be used to select which of the modifiable foci should be
actually modified.
selectP :: (a -> Bool) -> Prism' a a Source #
overMaybeTweak
requires a modification that can fail (targeting Maybe
).
Sometimes, it can prove more convenient to explicitly state which property
the foci shoud satisfy to be eligible for a modification that cannot fail
instead. selectP
provides a prism to make such a selection. The intended
use case is 'overTweak (optic % selectP prop) mod' where optic
gives the
candidate foci, prop
is the predicate to be satisfied by the foci, and
mod
is the modification to be applied to the selected foci.
combineModsTweak :: (Eq is, Is k A_Traversal, MonadTweak m) => ([is] -> [[is]]) -> Optic' k (WithIx is) TxSkel x -> (is -> x -> m [(x, l)]) -> m [l] Source #
When constructing a tweak from an optic and a modification of foci, there are in principle two options for optics with many foci: (a) apply the modification to all foci and return one modified transaction (b) generate a number of transactions that contain different combinations of modified and un-modified foci.
While most of the other "optic -> tweak" functions in this module take take the route (a), this function enables strategy (b).
Explanation of the arguments and return value
- Each of the foci of the
Optic k (WithIx is) TxSkel x
argument is something in the transaction that we might want to modify. - The
is -> x -> m [(x, l)]
argument computes a list of possible modifications for each focus, depending on its index. For each modified focus, it also returns a "label" of typel
, which somehow describes the modification that was made. - The
[is] -> [[is]]
argument determines which combinations of (un-) modified foci will be present on the modified transactions: The input is a list of all of the indices of foci, and for each element[i_1,...,i_n]
of the output list, all possible modified transactions that have a modification applied to the foci with indicesi_1,...,i_n
are generated. - The return value of type
[l]
is the list of labels of all modified foci, in the order in which their indices occurred. Later tweaks may use this list to decide what to do.
Example 1
Assume the optic has three foci, let's denote them by a, b, c :: x
, with
indices 1, 2, 3 :: Integer
respectively. Also assume that the is -> x -> m
[(x, l)]
argument returns lists of 2, 3, and 5 elements on a
, b
, and
c
, respectively. Let's call those elements a1, a2
and b1, b2, b3
and
c1, c2, c3, c4, c5
.
If the [ix] -> [[ix]]
argument is map (:[])
, you will try every
modification on a separate transaction, since
map (:[]) [1, 2, 3] = [[1], [2], [3]] .
Thus, there'll be 2+3+5=10 modified transactions in our examples. Namely, for each element of the list
[a1, a2, b1, b2, b3, c1, c2, c3, c4, c5]
you'll get one modified transaction that includes that value in place of the original focus.
Example 2
In the setting of the first example, if you want to try combining all
possible modifications of one focus with all possible modifications of all
other foci, choose tail . subsequences
for the @[ix] -> [[ix]] argument. We
have
tail (subsequences [1, 2, 3]) == [ [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3] ]
This will correspond to the following 71 modified transactions, represented by the list of modified foci they contain:
[ -- one modified focus (the 10 cases from Example 1) [a1], [a2], ... [c4], [c5], -- two modifications of different foci (2*3 + 2*5 + 3*5 = 31 cases) [a1, b1], [a1, b2], ... [b3, c4], [b3, c5], -- three modified foci, one from each focus (2*3*5 = 30 cases) [a1, b1, c1], [a1, b1, c2], ... [a1, b3, c4], [a1, b3, c5] ]
So you see that tweaks constructed like this can branch quite wildly. Use with caution!
iviewTweak :: (MonadTweak m, Is k A_Getter) => Optic' k (WithIx is) TxSkel a -> m (is, a) Source #
Like viewTweak
, only for indexed optics.