{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
module Convex.ThreatModel.MutualExclusion (
mutualExclusionAttack,
) where
import Convex.ThreatModel
mutualExclusionAttack :: ThreatModel ()
mutualExclusionAttack :: ThreatModel ()
mutualExclusionAttack = String -> ThreatModel () -> ThreatModel ()
forall a. String -> ThreatModel a -> ThreatModel a
Named String
"Mutual Exclusion Attack" (ThreatModel () -> ThreatModel ())
-> ThreatModel () -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$ do
[Output]
outputs <- ThreatModel [Output]
getTxOutputs
let scriptOutputs :: [Output]
scriptOutputs = (Output -> Bool) -> [Output] -> [Output]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Output -> Bool) -> Output -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AddressAny -> Bool
isKeyAddressAny (AddressAny -> Bool) -> (Output -> AddressAny) -> Output -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Output -> AddressAny
forall t. IsInputOrOutput t => t -> AddressAny
addressOf) [Output]
outputs
ThreatModel () -> ThreatModel ()
forall a. ThreatModel a -> ThreatModel a
threatPrecondition (ThreatModel () -> ThreatModel ())
-> ThreatModel () -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$ Bool -> ThreatModel ()
ensure (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Output] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Output]
scriptOutputs)
Output
target <- [Output] -> ThreatModel Output
forall a. Show a => [a] -> ThreatModel a
pickAny [Output]
scriptOutputs
let targetAddr :: AddressAny
targetAddr = Output -> AddressAny
forall t. IsInputOrOutput t => t -> AddressAny
addressOf Output
target
targetValue :: Value
targetValue = Output -> Value
forall t. IsInputOrOutput t => t -> Value
valueOf Output
target
targetRefScript :: ReferenceScript Era
targetRefScript = Output -> ReferenceScript Era
forall t. IsInputOrOutput t => t -> ReferenceScript Era
refScriptOf Output
target
let targetDatum :: TxOutDatum CtxTx Era
targetDatum = case TxOut CtxTx Era -> TxOutDatum CtxTx Era
forall ctx. TxOut ctx Era -> TxOutDatum ctx Era
datumOfTxOut (Output -> TxOut CtxTx Era
outputTxOut Output
target) of
TxOutDatum CtxTx Era
TxOutDatumNone -> TxOutDatum CtxTx Era
forall ctx era. TxOutDatum ctx era
TxOutDatumNone
TxOutDatumHash AlonzoEraOnwards Era
s Hash ScriptData
h -> AlonzoEraOnwards Era -> Hash ScriptData -> TxOutDatum CtxTx Era
forall era ctx.
AlonzoEraOnwards era -> Hash ScriptData -> TxOutDatum ctx era
TxOutDatumHash AlonzoEraOnwards Era
s Hash ScriptData
h
TxOutDatumInline BabbageEraOnwards Era
s HashableScriptData
d -> BabbageEraOnwards Era -> HashableScriptData -> TxOutDatum CtxTx Era
forall era ctx.
BabbageEraOnwards era -> HashableScriptData -> TxOutDatum ctx era
TxOutDatumInline BabbageEraOnwards Era
s HashableScriptData
d
TxOutSupplementalDatum AlonzoEraOnwards Era
s HashableScriptData
d -> AlonzoEraOnwards Era -> HashableScriptData -> TxOutDatum CtxTx Era
forall era.
AlonzoEraOnwards era -> HashableScriptData -> TxOutDatum CtxTx era
TxOutSupplementalDatum AlonzoEraOnwards Era
s HashableScriptData
d
String -> ThreatModel ()
counterexampleTM (String -> ThreatModel ()) -> String -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
paragraph
[ String
"The transaction contains a script output at index"
, TxIx -> String
forall a. Show a => a -> String
show (Output -> TxIx
outputIx Output
target)
, String
"going to"
, Doc -> String
forall a. Show a => a -> String
show (Doc -> String) -> Doc -> String
forall a b. (a -> b) -> a -> b
$ AddressAny -> Doc
prettyAddress AddressAny
targetAddr
, String
"."
]
String -> ThreatModel ()
counterexampleTM (String -> ThreatModel ()) -> String -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
paragraph
[ String
"Testing if this output can be duplicated - adding another output with"
, String
"IDENTICAL address, value, and datum."
]
String -> ThreatModel ()
counterexampleTM (String -> ThreatModel ()) -> String -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
paragraph
[ String
"If this validates, the script has a Mutual Exclusion vulnerability."
, String
"Multiple script inputs could cross-match outputs when using list.find"
, String
"to locate 'their' continuation, since duplicate outputs would match"
, String
"the same criteria."
]
String -> ThreatModel ()
counterexampleTM (String -> ThreatModel ()) -> String -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
paragraph
[ String
"An attacker could exploit this to:"
, String
"1) Have multiple inputs claim the same output as 'theirs'"
, String
"2) Break the 1:1 correspondence between inputs and outputs"
, String
"3) Redirect funds by manipulating input-output matching"
]
TxModifier -> ThreatModel ()
shouldNotValidate (TxModifier -> ThreatModel ()) -> TxModifier -> ThreatModel ()
forall a b. (a -> b) -> a -> b
$ AddressAny
-> Value
-> TxOutDatum CtxTx Era
-> ReferenceScript Era
-> TxModifier
addOutput AddressAny
targetAddr Value
targetValue TxOutDatum CtxTx Era
targetDatum ReferenceScript Era
targetRefScript