Skip to content

Commit

Permalink
Deposit and Recover
Browse files Browse the repository at this point in the history
Signed-off-by: Sasha Bogicevic <[email protected]>
  • Loading branch information
v0d1ch committed Sep 3, 2024
1 parent 0062556 commit c7050c7
Show file tree
Hide file tree
Showing 19 changed files with 637 additions and 3 deletions.
3 changes: 3 additions & 0 deletions hydra-node/bench/tx-cost/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ scriptSizes =
, "| " <> "νCommit" <> " | " <> serialiseToRawBytesHexText commitScriptHash <> " | " <> show commitScriptSize <> " | "
, "| " <> "νHead" <> " | " <> serialiseToRawBytesHexText headScriptHash <> " | " <> show headScriptSize <> " | "
, "| " <> "μHead" <> " | " <> serialiseToRawBytesHexText mintingScriptHash <> "* | " <> show mintingScriptSize <> " | "
, "| " <> "νDeposit" <> " | " <> serialiseToRawBytesHexText depositScriptHash <> " | " <> show depositScriptSize <> " | "
, ""
, "* The minting policy hash is only usable for comparison. As the script is parameterized, the actual script is unique per head."
]
Expand All @@ -148,6 +149,8 @@ scriptSizes =
, commitScriptSize
, headScriptHash
, headScriptSize
, depositScriptHash
, depositScriptSize
} = scriptInfo

costOfInit :: IO Text
Expand Down
5 changes: 5 additions & 0 deletions hydra-node/src/Hydra/HeadLogic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ onOpenNetworkReqTx env ledger st ttl tx =
-- Spec: wait L̂ ◦ tx ≠ ⊥
waitApplyTx $ \newLocalUTxO ->
(cause (ClientEffect $ ServerOutput.TxValid headId tx) <>) $
-- Spec: T̂ ← T̂ ⋃ {tx}
-- L̂ ← L̂ ◦ tx

-- Spec: T̂ ← T̂ ⋃ {tx}
-- L̂ ← L̂ ◦ tx
newState TransactionAppliedToLocalUTxO{tx, newLocalUTxO}
Expand Down Expand Up @@ -412,6 +415,8 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx =
requireReqSn $
-- Spec: wait ŝ = ̅S.s
waitNoSnapshotInFlight $
-- Spec: wait v = v̂

-- Spec: wait v = v̂
waitOnSnapshotVersion $
requireApplicableDecommitTx $ \(activeUTxO, mUtxoToDecommit) ->
Expand Down
2 changes: 2 additions & 0 deletions hydra-plutus/hydra-plutus.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ library
Hydra.Contract
Hydra.Contract.Commit
Hydra.Contract.CommitError
Hydra.Contract.Deposit
Hydra.Contract.DepositError
Hydra.Contract.Error
Hydra.Contract.Hash
Hydra.Contract.Head
Expand Down
5 changes: 5 additions & 0 deletions hydra-plutus/scripts/vDeposit.plutus
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "PlutusScriptV2",
"description": "hydra-vDeposit-0.18.1-42-gfdb9d672a",
"cborHex": "590ac5590ac20100003233322232332232323232323232323232323232323322323232323232323232323232323232323232322225335333222353007006322225335006101f2153535355005222222222222005220022233553335002213300b4910344303400333573466e2400401808808c4c07124103443033001301c491034430330013300a49010344303500333573466e3cdc9181199a8078019aa8039111111111110051b92302b3028302f004022021102113500122002225335001101a1335738004032646464a666ae68cdc3a400000422440042a666ae68cdc3a400400426424460020066eb4d5d08008980a80b1aab9e00235573a0026ea8008c8c8c94ccd5cd19b87480000084cc8848cc00400c008c8c8c94ccd5cd19b87480000084c8c8c8c8c8c8c8c8c8c8cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cc064070d5d08059980c80e1aba100a3301901f3574201266604aeb94090d5d0804199812bae50243574200e660320366ae84018ccc094081d69aba10053232325333573466e1d20000021332212330010030023232325333573466e1d20000021332212330010030023301e75a6ae84004c074d5d09aba20011302802935573c0046aae74004dd51aba10013232325333573466e1d20000021332212330010030023301e75a6ae84004c074d5d09aba20011302802935573c0046aae74004dd51aba1357440022604a04c6aae78008d55ce8009baa3574200866032eb8d5d080199981280d00b1aba100233302575c02c6ae84004c078d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae880044c060064d55cf0011aab9d00137546ae84004c034d5d09aba20011301501635573c0046aae74004dd5000880e89809248103505435003223232325333573466e1d200000213233322212333001004003002375c6ae84008dd69aba10013006357426ae88004d5d10008980980a1aab9e00235573a0026ea8004c0148c8c8c94ccd5cd19b87480000084cc8848cc00400c008c034d5d08009bae357426ae880044c04804cd55cf0011aab9d00137540026605044244a666ae68cdc480124000204e2a66a002204e44266a05000466a600c2400266e04011200200112001200123232325333573466e1d2000002101415333573466e1d200200210151300f01035573c0046aae74004dd5000911919192999ab9a3370e9000001089110010a999ab9a3370e90010010990911180180218029aba100115333573466e1d2004002112220011300f01035573c0046aae74004dd5000919118011bac00130252233335573e0024046466a04460086ae84008c00cd5d100100811919192999ab9a3370e90000010990911118018029bae357420022a666ae68cdc3a400400426424444600200a600e6ae8400454ccd5cd19b87480100084c848888c008014c028d5d08008a999ab9a3370e900300109909111180200298029aba10011300c00d35573c0046aae74004dd500091919192999ab9a3370e900000109909111111180280418049aba100115333573466e1d20020021321222222230070083009357420022a666ae68cdc3a400800426644244444446600c01201060126ae84004dd71aba1357440022a666ae68cdc3a400c0042664424444444660040120106eb8d5d08009bae357426ae8800454ccd5cd19b87480200084cc8848888888cc004024020dd71aba1001375a6ae84d5d10008a999ab9a3370e90050010891111110020a999ab9a3370e9006001089111111001898058061aab9e00235573a0026ea80048c8c8c94ccd5cd19b87480000084cc8848cc00400c008c014d5d080098039aba135744002260140166aae78008d55ce8009baa00123232325333573466e1d20000021332212330010030023005357420026eb4d5d09aba20011300900a35573c0046aae74004dd500091919192999ab9a3370e900000109bae35742002260100126aae78008d55ce8009baa0013223232325333573466e1d200000213232333322221233330010050040030023232325333573466e1d2000002133221233001003002300c35742002660140166ae84d5d1000898068071aab9e00235573a0026ea8d5d0801999806bae500c35742004646464a666ae68cdc3a4000004224440062a666ae68cdc3a4004004264244460020086eb8d5d08008a999ab9a3370e9002001099091118010021aba10011300d00e35573c0046aae74004dd51aba10013300775c6ae84d5d10009aba200135744002260100126aae78008d55ce8009baa001223232325333573466e1d2002002112200115333573466e1d20000021321223002003300535742002260100126aae78008d55ce8009baa00123232325333573466e1d200000213212230020033005357420022a666ae68cdc3a400400426466644424466600200a0080066eb4d5d08011bad357420026eb4d5d09aba2001357440022600c00e6aae78008d55ce8009baa00123232325333573466e1d20000021321223002003375c6ae8400454ccd5cd19b87480080084c8488c00400cdd71aba10011300500635573c0046aae74004dd5000919319ab9c0010054901035054310013300175ceb488c88c008dd5800980d111999aab9f001201823233501833221233001003002300635573a002600a6aae78004c010d5d10019aba1002005120011220021220013014225335001100b221337146eccd40088888cdd2a400066ae80d401088cdd2a400066ae80c02c008cd5d019806119a800919ba548000cd5d018068009bb10102223374a900119aba0375000666ae80dd400119aba037500026ec4048004dd880719aba033300b75266016ea48dd400080199aba05333500213374a90001bb100c213374a900219aba0001376201a4266e9520023357406ea4004dd880699aba03300a7520026ec4030c0100048cd40048cdd2a400066ae80dd48009bb100523374a900119aba037520026ec4014894cd400484cdd2a400066ae80c00c004dd8802899ba548008dd8802111911ba6300200130132253350011376400a4426a0044466ae80cdd8180400118038009803001a4c601e44a66a002260046006018442a66a0022004442600c600e00a601c44a66a0022016442a66a002200644266a01c6600e008004600c002601a444a66a0042002442a66a006200864442a666a6602200a0042a006266a01e0046601000e0022a006266a0180046600a002006601844a66a00220064426a0044466e28004c01800d22010035003222001350022220023500122200333230010012212323330022300222230030042300222230020042300222230010042353300400400335003001122223330042533500113350060070072215335001133500800300922153233353300d00500315001133300800333500b00500c002150011333006002233500b00500100122253350011335008335008003002300600932221533353300d00600215003133300800233500b0060050011500313350083350080030023006001222532335002130014988854c8ccd4cc03801c00c540044c011261500113330070022300633500c0070010012335009300333500900400a30070021220021221223300100400332223500222350022235005223500222533353300b00600215333573466e1c014004403854ccd5cd19b89005001100c100d13300b00600213300b006002225333573466e3c008004401454ccd5cd19b91002001100310041222003122200212220012323001001230022330020020011"
}
5 changes: 5 additions & 0 deletions hydra-plutus/src/Hydra/Contract.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Hydra.Cardano.Api (
pattern PlutusScript,
)
import Hydra.Contract.Commit qualified as Commit
import Hydra.Contract.Deposit qualified as Deposit
import Hydra.Contract.Head qualified as Head
import Hydra.Contract.HeadTokens qualified as HeadTokens
import Hydra.Contract.Initial qualified as Initial
Expand All @@ -30,6 +31,8 @@ data ScriptInfo = ScriptInfo
, commitScriptSize :: Int64
, headScriptHash :: ScriptHash
, headScriptSize :: Int64
, depositScriptHash :: ScriptHash
, depositScriptSize :: Int64
}
deriving stock (Eq, Show, Generic)
deriving anyclass (ToJSON)
Expand All @@ -47,6 +50,8 @@ scriptInfo =
, commitScriptSize = scriptSize Commit.validatorScript
, headScriptHash = plutusScriptHash Head.validatorScript
, headScriptSize = scriptSize Head.validatorScript
, depositScriptHash = plutusScriptHash Deposit.validatorScript
, depositScriptSize = scriptSize Deposit.validatorScript
}
where
plutusScriptHash =
Expand Down
102 changes: 102 additions & 0 deletions hydra-plutus/src/Hydra/Contract/Deposit.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -fno-specialize #-}
{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:conservative-optimisation #-}
{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-}
-- Plutus core version to compile to. In babbage era, that is Cardano protocol
-- version 7 and 8, only plutus-core version 1.0.0 is available.
{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:target-version=1.0.0 #-}

-- | The validator used to deposit and recover locked funds
module Hydra.Contract.Deposit where

import PlutusTx.Prelude

import Hydra.Cardano.Api (PlutusScriptVersion (PlutusScriptV2))
import Hydra.Contract.Commit (Commit)
import Hydra.Contract.DepositError (
DepositError (
DepositDeadlineNotReached,
DepositNoLowerBoundDefined,
IncorrectDepositHash
),
)
import Hydra.Contract.Error (errorCode)
import Hydra.Contract.Head (hashPreSerializedCommits, hashTxOuts)
import Hydra.Plutus.Extras (ValidatorType, scriptValidatorHash, wrapValidator)
import PlutusLedgerApi.V2 (
CurrencySymbol,
Datum (Datum),
Extended (Finite),
Interval (ivFrom),
LowerBound (LowerBound),
POSIXTime,
Redeemer (Redeemer),
ScriptContext (..),
ScriptHash,
SerialisedScript,
serialiseCompiledCode,
txInfoOutputs,
txInfoValidRange,
)
import PlutusTx (CompiledCode, toBuiltinData)
import PlutusTx qualified

data DepositRedeemer
= -- | Claims already deposited funds.
Claim
| -- | Recovers m number of deposited outputs.
Recover Integer

PlutusTx.unstableMakeIsData ''DepositRedeemer

-- | Deposit datum containing HeadId, deadline and a list of deposits.
type DepositDatum = (CurrencySymbol, POSIXTime, [Commit])

-- | v_deposit validator checks
--
-- * Claim redeemer -> no checks are needed
--
-- * Recover redeemer
-- * The deadline HAS BEEN reached.
-- * The hash of locked outputs are mathing the tx outputs.
validator :: DepositDatum -> DepositRedeemer -> ScriptContext -> Bool
validator (_headId, dl, deposits) r ctx =
case r of
Claim -> True
Recover m ->
afterDeadline
&& recoverOutputs m
where
recoverOutputs m =
traceIfFalse $(errorCode IncorrectDepositHash) $
hashOfOutputs m == hashPreSerializedCommits deposits

hashOfOutputs m =
hashTxOuts $ take m (txInfoOutputs txInfo)

afterDeadline =
case ivFrom (txInfoValidRange txInfo) of
LowerBound (Finite t) _ ->
traceIfFalse $(errorCode DepositDeadlineNotReached) $
t > dl
_ -> traceError $(errorCode DepositNoLowerBoundDefined)

ScriptContext{scriptContextTxInfo = txInfo} = ctx

compiledValidator :: CompiledCode ValidatorType
compiledValidator =
$$(PlutusTx.compile [||wrap validator||])
where
wrap = wrapValidator @DepositDatum @DepositRedeemer

validatorScript :: SerialisedScript
validatorScript = serialiseCompiledCode compiledValidator

validatorHash :: ScriptHash
validatorHash = scriptValidatorHash PlutusScriptV2 validatorScript

datum :: DepositDatum -> Datum
datum a = Datum (toBuiltinData a)

redeemer :: DepositRedeemer -> Redeemer
redeemer a = Redeemer (toBuiltinData a)
25 changes: 25 additions & 0 deletions hydra-plutus/src/Hydra/Contract/DepositError.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Hydra.Contract.DepositError (
errorCode,
module Hydra.Contract.DepositError,
) where

import Hydra.Contract.Error (ToErrorCode (..), errorCode)
import Text.Show (Show)

data DepositError
= DepositDeadlineSurpassed
| DepositNoUpperBoundDefined
| DepositNoLowerBoundDefined
| DepositDeadlineNotReached
| IncorrectDepositHash
| DTNotMinted
deriving stock (Show)

instance ToErrorCode DepositError where
toErrorCode = \case
DepositDeadlineSurpassed -> "D01"
DepositNoUpperBoundDefined -> "D02"
DepositNoLowerBoundDefined -> "D03"
DepositDeadlineNotReached -> "D04"
IncorrectDepositHash -> "D05"
DTNotMinted -> "D06"
3 changes: 3 additions & 0 deletions hydra-plutus/test/Hydra/Plutus/GoldenSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Hydra.Cardano.Api (
pattern PlutusScript,
)
import Hydra.Contract.Commit qualified as Commit
import Hydra.Contract.Deposit qualified as Deposit
import Hydra.Contract.Head qualified as Head
import Hydra.Contract.HeadTokens qualified as HeadTokens
import Hydra.Contract.Initial qualified as Initial
Expand All @@ -42,6 +43,8 @@ spec = do
goldenScript "vHead" Head.validatorScript
it "Head minting policy script" $
goldenScript "mHead" (serialiseCompiledCode HeadTokens.unappliedMintingPolicy)
it "Deposit validator script" $
goldenScript "vDeposit" Deposit.validatorScript

-- | Write a golden script on first run and ensure it stays the same on
-- subsequent runs.
Expand Down
39 changes: 39 additions & 0 deletions hydra-tx/exe/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module Main where

import Hydra.Cardano.Api (textEnvelopeToJSON)
import Hydra.Prelude

import Cardano.Api.UTxO (UTxO)
import Cardano.Api.UTxO qualified as UTxO
import Data.Aeson (eitherDecodeFileStrict)
import Hydra.Contract.Deposit (DepositDatum)
import Hydra.Tx.Deposit (depositTx)
import Hydra.Tx.Recover (recoverTx)
import Hydra.Tx.Utils (extractInlineDatumFromTxOut)
import Options

main :: IO ()
main = do
cmd <- parseHydraCommand
case cmd of
Deposit DepositOptions{networkId, headId, outFile, utxoFilePath, depositDeadline} ->
eitherDecodeFileStrict utxoFilePath >>= \case
Left err -> die $ "failed to parse provided UTXO file! " <> err
Right (utxo :: UTxO) -> do
let depositTransaction = depositTx networkId headId utxo depositDeadline
writeFileLBS outFile $ textEnvelopeToJSON Nothing depositTransaction
putStrLn $ "Wrote deposit transaction to " <> outFile
Recover RecoverOptions{networkId, headId, outFile, recoverTxIn, utxoFilePath, depositDeadline, recoverSlotNo} -> do
eitherDecodeFileStrict utxoFilePath >>= \case
Left err -> die $ "failed to parse provided UTXO file! " <> err
Right (utxo :: UTxO) -> do
case UTxO.resolve recoverTxIn utxo of
Nothing -> die "failed to resolve deposited UTxO with provided TxIn"
Just depositedTxOut -> do
case extractInlineDatumFromTxOut @DepositDatum depositedTxOut of
Nothing -> die "failed to extract DepositDatum from recover UTxO"
Just (_, _, depositted) -> do
let recoverTransaction =
recoverTx networkId headId recoverTxIn depositted depositDeadline recoverSlotNo
writeFileLBS outFile $ textEnvelopeToJSON Nothing recoverTransaction
putStrLn $ "Wrote deposit transaction to " <> outFile
Loading

0 comments on commit c7050c7

Please sign in to comment.