tweag / cooked-validators

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: can we make a blanket double satisfaction attack?

VictorCMiraldo opened this issue · comments

A common attack to most scripts is to rely on a double satisfaction vulnerability: the combination of consuming two utxos that would cause the script to validate but in some slightly off manner. For example, when auditing a DEX we always try to execute the refunding of an order, but consume two order UTxOs instead and pay the difference to an attacker.

Can we make this into a blanket attack in cooked, just like we have with datum hijacking and token duplication?

I understand your view of the double satisfaction attack like this: It consists in adding an input to an otherwise normal transaction and paying the excess after the transaction to the attacker. Since it's always about fooling (validator) scripts, my idea would be to write an attack of a type like

doubleSatAttack :: 
  ( 
  ... -- some constraints on 'a'  and its 'RedeemerType' and 'DatumType', probably
  ) =>
  (TypedValidator a -> RedeemerType a -> (SpendableOut, DatumType a) -> Maybe MiscConstraint) ->
  Wallet ->
  Attack

Here, the first argument of doubleSatAttack looks at all the SpendsScript constraints in the transaction to be modified (note that its arguments are exactly the arguments of the SpendsScript constructor), and returns Just the additional transaction input if the constraint matches, and Nothing otherwise. The second argument would be the wallet of the attacker.

My high-level question is this: What if there is more than one possible way to try double satisfaction (specified as above or differently)? In that case, wouldn't we like an attack that can return several modifications of the same transaction, so

type Attack = TxSkel -> [TxSkel]

where the empty list signals that the modification has failed? This would open up many possible other attacks (for example: try all permutations of the outputs). I'll ask @mmontin what he thinks about this.

This is a relatively unordered brain dump, but I still think it's worthwhile to record it somewhere. In particular, we're after a justification of the Attack type anyway.

Since we're already talking about generalisations, another reason why type Attack = TxSkel -> Maybe TxSkel might not be appropriate for the double satisfaction attack: The core of that attack is adding a script input to a transaction, so we have to have a way to obtain that input. A doubleSatAttack that always has to be preceded by at least a call to utxosSuchThat would not be useful in combination with the LTL framework. That is: The return value of Attacks has to depend on the state of the blockchain.

Here are a few idea-germs:

  1. Something like type Attack = TxSkel -> Maybe (StagedMockchain TxId) would mean that we swap one validateTxSkel instruction for a whole sub-trace that ends in validateTxSkel. (I'm not sure if StagedMockChain is appropriate here or it we sould make it polymorphic on any m with MonadModalMockChain m.)
  2. As a slight restriction, type Attack = SomeContext -> TxSkel -> Maybe TxSkel, where SomeContext is a suitable type that let's us query (a relevant part of) the state of the blockchain. I don't know what that type should be, though, without breaking the interface of MonadBlockChain.
  3. A riff on @mmontin's "modifications form a monad" idea: Maybe the monad of modifications has methods that allow for queries of the blockchain state.
  4. type Attack = TxSkel -> Maybe (SomeContext -> TxSkel)

With all of these, one problem that I see immediately is "How should conjunction (LtlAnd) work? Furthermore, the question about Maybe remains, lists also seem sensible.