From 4fd36c2876b3fb4418c7a990bf2bd8882218cf9c Mon Sep 17 00:00:00 2001 From: Sasha Bogicevic Date: Wed, 4 Sep 2024 12:21:52 +0200 Subject: [PATCH] PR review changes Signed-off-by: Sasha Bogicevic --- flake.lock | 6 +- hydra-node/src/Hydra/HeadLogic.hs | 5 - hydra-plutus/scripts/mDeposit.plutus | 5 - hydra-plutus/scripts/vDeposit.plutus | 4 +- hydra-plutus/src/Hydra/Contract/Deposit.hs | 16 +-- hydra-tx/exe/Main.hs | 8 +- hydra-tx/exe/Options.hs | 7 +- hydra-tx/src/Hydra/Tx/Deposit.hs | 7 +- hydra-tx/src/Hydra/Tx/Recover.hs | 21 ++-- .../test/Hydra/Tx/Contract/ContractSpec.hs | 4 +- hydra-tx/test/Hydra/Tx/Contract/Recover.hs | 100 ++++++++++++++---- 11 files changed, 119 insertions(+), 64 deletions(-) delete mode 100644 hydra-plutus/scripts/mDeposit.plutus diff --git a/flake.lock b/flake.lock index 7d31afa13bf..d7dc436ab09 100644 --- a/flake.lock +++ b/flake.lock @@ -1413,11 +1413,11 @@ "nixpkgs": "nixpkgs_9" }, "locked": { - "lastModified": 1723044854, - "narHash": "sha256-drzeiMBle5pI1V4ZRwJqS5lU2Ngazeab2pvk10Ara8g=", + "lastModified": 1725260503, + "narHash": "sha256-PV3JrSImQCK048+lE474BJMGP24jMh/9F6uEV+UP0qg=", "owner": "cardano-scaling", "repo": "hydra-formal-specification", - "rev": "56f025e99b93b9d2f988970337148b0e3fbdc6fd", + "rev": "34ea7455d151c239eb12ec5b0b0cb28ab2cc1df7", "type": "github" }, "original": { diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index 74f4cb76aaa..e2da6ce8416 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -323,9 +323,6 @@ 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} @@ -415,8 +412,6 @@ 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) -> diff --git a/hydra-plutus/scripts/mDeposit.plutus b/hydra-plutus/scripts/mDeposit.plutus deleted file mode 100644 index 1b0f25eac77..00000000000 --- a/hydra-plutus/scripts/mDeposit.plutus +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "PlutusScriptV2", - "description": "hydra-mDeposit-0.18.1-42-gfdb9d672a", - "cborHex": "59082059081d01000033233322232332232323232323232323233223322322332323232222253353330043232325333573466e1d2000002100d1300b00a35573c0046aae74004dd50019919192999ab9a3370e90000010998040049aba10011300b00a35573c0046aae74004dd50011991919191911919192999ab9a3370e90000010999109198008018011919192999ab9a3370e9000001099191919191919191919199999999999911111111111091999999999998008068060058050048040038030028020018011980d91919192999ab9a3370e900000109991091980080180118101aba10013016357426ae880044c088084d55cf0011aab9d00137540026ae8402cd5d08051980d8091aba100933301675ca02a6ae84020ccc059d7280a9aba10073574200c6ae84014d5d08021980dbae357420066ae84008ccc059d710009aba1001357426ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba20011301401335573c0046aae74004dd51aba10013232325333573466e1d2000002132122223003005375c6ae8400454ccd5cd19b87480080084c848888c004014c048d5d08008a999ab9a3370e900200109909111180100298049aba100115333573466e1d20060021321222230040053232325333573466e1d2000002132122222223005008300c357420022a666ae68cdc3a400400426424444444600e01060186ae8400454ccd5cd19b87480100084cc8848888888cc018024020c030d5d08009bae357426ae8800454ccd5cd19b87480180084cc8848888888cc008024020dd71aba1001375c6ae84d5d10008a999ab9a3370e90040010999109111111198008048041bae357420026eb4d5d09aba200115333573466e1d200a00211222222200415333573466e1d200c0021122222220031301701635573c0046aae74004dd51aba10011301401335573c0046aae74004dd51aba135744002260220206aae78008d55ce8009baa0013223232325333573466e1d200000213232333322221233330010050040030023232325333573466e1d2000002133221233001003002300c35742002660140166ae84d5d10008980b00a9aab9e00235573a0026ea8d5d0801999805bae500a35742004646464a666ae68cdc3a4000004224440062a666ae68cdc3a4004004264244460020086eb8d5d08008a999ab9a3370e9002001099091118010021aba10011301601535573c0046aae74004dd51aba10013300775c6ae84d5d10009aba200135744002260220206aae78008d55ce8009baa001223232325333573466e1d20020021501615333573466e1d200000213017300535742002260220206aae78008d55ce8009baa00123232325333573466e1d200000213212230020033005357420022a666ae68cdc3a400400426466644424466600200a0080066eb4d5d08011bad357420026eb4d5d09aba2001357440022601e01c6aae78008d55ce8009baa00123232325333573466e1d20000021321223002003375c6ae8400454ccd5cd19b87480080084c8488c00400cdd71aba10011300e00d35573c0046aae74004dd5000899800bae75a4464460046eac004c08088cccd55cf800900f11919a80f1991091980080180118031aab9d001300535573c00260086ae8800cd5d0801007000880989804248103505435002322300237580026034446666aae7c00480608cd405cc010d5d080118019aba200200823232325333573466e1d20000021332212330010030023232325333573466e1d20000021375c6ae840044c024020d55cf0011aab9d00137546ae84004dd69aba1357440022600c00a6aae78008d55ce8009baa0014910350543100232633573800200666464644444a66aa66a66600e00c6a002446666a0024a01040024a0104a0106a002446a00444444444444401042a66a66601000e6e48c048c03cc05800c00484ccd5cd19b8748008004034030402c4028402c40284c98cd5ce2481024c680000422333573466e3c00800401c01888c88c008004c060894cd400454024884d4008894cd4cc02000801c4c0380044c01800c004480044880084880048488c00800c4488004c03c894cd40044c008c00c0308854cd40044008884c018c01c014c038894cd4004402c8854cd4004400c884cd4038cc01c010008c018004c0348894cd400840048854cd400c4010c88854ccd4cc0440140085400c4cd403c008cc02001c0045400c4cd4030008cc01400400cc030894cd40045220100221337146eccd400888cdd2a400066ae80cdd2a400066ae80dd48011bb10073357406ea0004dd88039802000a4c6a0064440026a0044440046a002444006664600200244246466600446004444600600846004444600400846004444600200846a660080080066a006002244446660084a66a002266a00c00e00e442a66a002266a010006012442a64666a6601a00a0062a002266601000666a01600a0180042a002266600c004466a01600a002002444a66a002266a01066a010006004600c01264442a666a6601a00c0042a006266601000466a01600c00a0022a006266a01066a010006004600c002444a6466a0042600293110a99199a998070038018a8008980224c2a002266600e0044600c66a01800e002002466a012600666a012008014600e0042440042442446600200800664446a004446a00644a666a6600e0080042a666ae68cdc380180088050a999ab9a337120060022010201226600e00800426600e00800444a666ae68cdc780100088028a999ab9a337220040022006200824440062444004244400246460020024600446600400400291011c10ea3b87d4afc5714d677b6f2542e24ea2da55771a68b975fc9509290001" -} diff --git a/hydra-plutus/scripts/vDeposit.plutus b/hydra-plutus/scripts/vDeposit.plutus index fd98f5ec4ca..5c8e91d5670 100644 --- a/hydra-plutus/scripts/vDeposit.plutus +++ b/hydra-plutus/scripts/vDeposit.plutus @@ -1,5 +1,5 @@ { "type": "PlutusScriptV2", - "description": "hydra-vDeposit-0.18.1-42-gfdb9d672a", - "cborHex": "590ac5590ac20100003233322232332232323232323232323232323232323322323232323232323232323232323232323232322225335333222353007006322225335006101f2153535355005222222222222005220022233553335002213300b4910344303400333573466e2400401808808c4c07124103443033001301c491034430330013300a49010344303500333573466e3cdc9181199a8078019aa8039111111111110051b92302b3028302f004022021102113500122002225335001101a1335738004032646464a666ae68cdc3a400000422440042a666ae68cdc3a400400426424460020066eb4d5d08008980a80b1aab9e00235573a0026ea8008c8c8c94ccd5cd19b87480000084cc8848cc00400c008c8c8c94ccd5cd19b87480000084c8c8c8c8c8c8c8c8c8c8cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cc064070d5d08059980c80e1aba100a3301901f3574201266604aeb94090d5d0804199812bae50243574200e660320366ae84018ccc094081d69aba10053232325333573466e1d20000021332212330010030023232325333573466e1d20000021332212330010030023301e75a6ae84004c074d5d09aba20011302802935573c0046aae74004dd51aba10013232325333573466e1d20000021332212330010030023301e75a6ae84004c074d5d09aba20011302802935573c0046aae74004dd51aba1357440022604a04c6aae78008d55ce8009baa3574200866032eb8d5d080199981280d00b1aba100233302575c02c6ae84004c078d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae880044c060064d55cf0011aab9d00137546ae84004c034d5d09aba20011301501635573c0046aae74004dd5000880e89809248103505435003223232325333573466e1d200000213233322212333001004003002375c6ae84008dd69aba10013006357426ae88004d5d10008980980a1aab9e00235573a0026ea8004c0148c8c8c94ccd5cd19b87480000084cc8848cc00400c008c034d5d08009bae357426ae880044c04804cd55cf0011aab9d00137540026605044244a666ae68cdc480124000204e2a66a002204e44266a05000466a600c2400266e04011200200112001200123232325333573466e1d2000002101415333573466e1d200200210151300f01035573c0046aae74004dd5000911919192999ab9a3370e9000001089110010a999ab9a3370e90010010990911180180218029aba100115333573466e1d2004002112220011300f01035573c0046aae74004dd5000919118011bac00130252233335573e0024046466a04460086ae84008c00cd5d100100811919192999ab9a3370e90000010990911118018029bae357420022a666ae68cdc3a400400426424444600200a600e6ae8400454ccd5cd19b87480100084c848888c008014c028d5d08008a999ab9a3370e900300109909111180200298029aba10011300c00d35573c0046aae74004dd500091919192999ab9a3370e900000109909111111180280418049aba100115333573466e1d20020021321222222230070083009357420022a666ae68cdc3a400800426644244444446600c01201060126ae84004dd71aba1357440022a666ae68cdc3a400c0042664424444444660040120106eb8d5d08009bae357426ae8800454ccd5cd19b87480200084cc8848888888cc004024020dd71aba1001375a6ae84d5d10008a999ab9a3370e90050010891111110020a999ab9a3370e9006001089111111001898058061aab9e00235573a0026ea80048c8c8c94ccd5cd19b87480000084cc8848cc00400c008c014d5d080098039aba135744002260140166aae78008d55ce8009baa00123232325333573466e1d20000021332212330010030023005357420026eb4d5d09aba20011300900a35573c0046aae74004dd500091919192999ab9a3370e900000109bae35742002260100126aae78008d55ce8009baa0013223232325333573466e1d200000213232333322221233330010050040030023232325333573466e1d2000002133221233001003002300c35742002660140166ae84d5d1000898068071aab9e00235573a0026ea8d5d0801999806bae500c35742004646464a666ae68cdc3a4000004224440062a666ae68cdc3a4004004264244460020086eb8d5d08008a999ab9a3370e9002001099091118010021aba10011300d00e35573c0046aae74004dd51aba10013300775c6ae84d5d10009aba200135744002260100126aae78008d55ce8009baa001223232325333573466e1d2002002112200115333573466e1d20000021321223002003300535742002260100126aae78008d55ce8009baa00123232325333573466e1d200000213212230020033005357420022a666ae68cdc3a400400426466644424466600200a0080066eb4d5d08011bad357420026eb4d5d09aba2001357440022600c00e6aae78008d55ce8009baa00123232325333573466e1d20000021321223002003375c6ae8400454ccd5cd19b87480080084c8488c00400cdd71aba10011300500635573c0046aae74004dd5000919319ab9c0010054901035054310013300175ceb488c88c008dd5800980d111999aab9f001201823233501833221233001003002300635573a002600a6aae78004c010d5d10019aba1002005120011220021220013014225335001100b221337146eccd40088888cdd2a400066ae80d401088cdd2a400066ae80c02c008cd5d019806119a800919ba548000cd5d018068009bb10102223374a900119aba0375000666ae80dd400119aba037500026ec4048004dd880719aba033300b75266016ea48dd400080199aba05333500213374a90001bb100c213374a900219aba0001376201a4266e9520023357406ea4004dd880699aba03300a7520026ec4030c0100048cd40048cdd2a400066ae80dd48009bb100523374a900119aba037520026ec4014894cd400484cdd2a400066ae80c00c004dd8802899ba548008dd8802111911ba6300200130132253350011376400a4426a0044466ae80cdd8180400118038009803001a4c601e44a66a002260046006018442a66a0022004442600c600e00a601c44a66a0022016442a66a002200644266a01c6600e008004600c002601a444a66a0042002442a66a006200864442a666a6602200a0042a006266a01e0046601000e0022a006266a0180046600a002006601844a66a00220064426a0044466e28004c01800d22010035003222001350022220023500122200333230010012212323330022300222230030042300222230020042300222230010042353300400400335003001122223330042533500113350060070072215335001133500800300922153233353300d00500315001133300800333500b00500c002150011333006002233500b00500100122253350011335008335008003002300600932221533353300d00600215003133300800233500b0060050011500313350083350080030023006001222532335002130014988854c8ccd4cc03801c00c540044c011261500113330070022300633500c0070010012335009300333500900400a30070021220021221223300100400332223500222350022235005223500222533353300b00600215333573466e1c014004403854ccd5cd19b89005001100c100d13300b00600213300b006002225333573466e3c008004401454ccd5cd19b91002001100310041222003122200212220012323001001230022330020020011" + "description": "hydra-vDeposit-0.18.1-27-g5d6d4b00e", + "cborHex": "590ae4590ae10100003233322232332232323232323232323232323232323322323232323232323232323232323232323232222533533322253353232325333573466e1d2000002112200215333573466e1d20020021321223001003375a6ae840044c05c060d55cf0011aab9d001375400a20326442a6a6a6aa00444444444444400a440044466aa666a00442660109210344303400333573466e24004d401c88800807807c4c061241034430330013018491034430330013300749010344303500333573466e3cdc9180f99a8058019aa8021111111111110051b9230273024302b3500622200101e01d101d1350012200222533500110191335738004030646464a666ae68cdc3a4000004264646464a666ae68cdc3a4000004264666444246660020080060046eb8d5d08011bad35742002600a6ae84d5d10009aba20011301801935573c0046aae74004dd51aba1002300b23232325333573466e1d20000021332212330010030023013357420026eb8d5d09aba20011301801935573c0046aae74004dd50008980a00a9aab9e00235573a0026ea800cc8c8c94ccd5cd19b87480000084cc8848cc00400c008c8c8c94ccd5cd19b87480000084c8c8c8c8c8c8c8c8c8c8cccccccccccc88888888888848cccccccccccc00403403002c02802402001c01801401000c008cc06006cd5d08059980c00d9aba100a3301801e35742012666048eb9408cd5d08041998123ae50233574200e660300346ae84018ccc09007dd69aba10053232325333573466e1d20000021332212330010030023232325333573466e1d20000021332212330010030023301d75a6ae84004c070d5d09aba20011302702835573c0046aae74004dd51aba10013232325333573466e1d20000021332212330010030023301d75a6ae84004c070d5d09aba20011302702835573c0046aae74004dd51aba1357440022604804a6aae78008d55ce8009baa3574200866030eb8d5d080199981200c80a9aba100233302475c02a6ae84004c074d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae880044c05c060d55cf0011aab9d00137546ae84004c030d5d09aba20011301401535573c0046aae74004dd5000880e09808a481035054350033028221225333573466e240092000102715335001102722133502800233530061200133702008900100089000900091919192999ab9a3370e9000001080a0a999ab9a3370e9001001080a898078081aab9e00235573a0026ea800488c8c8c94ccd5cd19b87480000084488800854ccd5cd19b87480080084c84888c00c010c014d5d08008a999ab9a3370e900200108911000898078081aab9e00235573a0026ea80048c88c008dd60009812911999aab9f0012023233502230043574200460066ae880080408c8c8c94ccd5cd19b87480000084c848888c00c014dd71aba100115333573466e1d20020021321222230010053007357420022a666ae68cdc3a400800426424444600400a60146ae8400454ccd5cd19b87480180084c848888c010014c014d5d0800898060069aab9e00235573a0026ea80048c8c8c94ccd5cd19b87480000084c848888888c014020c024d5d08008a999ab9a3370e900100109909111111180380418049aba100115333573466e1d20040021332212222222330060090083009357420026eb8d5d09aba200115333573466e1d2006002133221222222233002009008375c6ae84004dd71aba1357440022a666ae68cdc3a40100042664424444444660020120106eb8d5d08009bad357426ae8800454ccd5cd19b874802800844888888801054ccd5cd19b874803000844888888800c4c02c030d55cf0011aab9d00137540024646464a666ae68cdc3a4000004266442466002006004600a6ae84004c01cd5d09aba20011300a00b35573c0046aae74004dd500091919192999ab9a3370e900000109991091980080180118029aba1001375a6ae84d5d1000898048051aab9e00235573a0026ea80048c8c8c94ccd5cd19b87480000084dd71aba10011300800935573c0046aae74004dd50009911919192999ab9a3370e900000109919199991110919998008028020018011919192999ab9a3370e900000109991091980080180118061aba10013300a00b357426ae880044c034038d55cf0011aab9d00137546ae8400cccc035d728061aba10023232325333573466e1d20000021122200315333573466e1d200200213212223001004375c6ae8400454ccd5cd19b87480100084c84888c008010d5d0800898068071aab9e00235573a0026ea8d5d080099803bae357426ae88004d5d10009aba20011300800935573c0046aae74004dd5000911919192999ab9a3370e900100108910008a999ab9a3370e9000001099091180100198029aba10011300800935573c0046aae74004dd500091919192999ab9a3370e9000001099091180100198029aba100115333573466e1d2002002132333222122333001005004003375a6ae84008dd69aba1001375a6ae84d5d10009aba20011300600735573c0046aae74004dd500091919192999ab9a3370e900000109909118010019bae357420022a666ae68cdc3a400400426424460020066eb8d5d0800898028031aab9e00235573a0026ea80048c98cd5ce000802a481035054310013300175ceb488c88c008dd5800980d111999aab9f001201823233501833221233001003002300635573a002600a6aae78004c010d5d10019aba1002005120011220021220013014225335001100b221337146eccd40088888cdd2a400066ae80d401088cdd2a400066ae80c02c008cd5d019806119a800919ba548000cd5d018068009bb10102223374a900119aba0375000666ae80dd400119aba037500026ec4048004dd880719aba033300b75266016ea48dd400080199aba05333500213374a90001bb100c213374a900219aba0001376201a4266e9520023357406ea4004dd880699aba03300a7520026ec4030c0100048cd40048cdd2a400066ae80dd48009bb100523374a900119aba037520026ec4014894cd400484cdd2a400066ae80c00c004dd8802899ba548008dd8802111911ba6300200130132253350011376400a4426a0044466ae80cdd8180400118038009803001a4c601e44a66a002260046006018442a66a0022004442600c600e00a601c44a66a0022016442a66a002200644266a01c6600e008004600c002601a444a66a0042002442a66a006200864442a666a6602200a0042a006266a01e0046601000e0022a006266a0180046600a002006601844a66a00220064426a0044466e28004c01800d22010035003222001350022220023500122200333230010012212323330022300222230030042300222230020042300222230010042353300400400335003001122223330042533500113350060070072215335001133500800300922153233353300d00500315001133300800333500b00500c002150011333006002233500b00500100122253350011335008335008003002300600932221533353300d00600215003133300800233500b0060050011500313350083350080030023006001222532335002130014988854c8ccd4cc03801c00c540044c011261500113330070022300633500c0070010012335009300333500900400a30070021220021221223300100400332223500222350022235005223500222533353300b00600215333573466e1c014004403854ccd5cd19b89005001100c100d13300b00600213300b006002225333573466e3c008004401454ccd5cd19b91002001100310041222003122200212220012323001001230022330020020011" } diff --git a/hydra-plutus/src/Hydra/Contract/Deposit.hs b/hydra-plutus/src/Hydra/Contract/Deposit.hs index c74a2884b3c..b3ccb39d85e 100644 --- a/hydra-plutus/src/Hydra/Contract/Deposit.hs +++ b/hydra-plutus/src/Hydra/Contract/Deposit.hs @@ -50,23 +50,27 @@ data DepositRedeemer PlutusTx.unstableMakeIsData ''DepositRedeemer -- | Deposit datum containing HeadId, deadline and a list of deposits. -type DepositDatum = (CurrencySymbol, POSIXTime, [Commit]) +newtype DepositDatum + = DepositDatum (CurrencySymbol, POSIXTime, [Commit]) + +PlutusTx.unstableMakeIsData ''DepositDatum -- | v_deposit validator checks -- --- * Claim redeemer -> no checks are needed +-- * Claim redeemer -> more checks will be added -- -- * Recover redeemer --- * The deadline HAS BEEN reached. --- * The hash of locked outputs are mathing the tx outputs. +-- * The deadline has been reached. +-- * The hash of recovered outputs are matching the deposited outputs. validator :: DepositDatum -> DepositRedeemer -> ScriptContext -> Bool -validator (_headId, dl, deposits) r ctx = +validator depositDatum r ctx = case r of - Claim -> True + Claim -> False Recover m -> afterDeadline && recoverOutputs m where + DepositDatum (_headId, dl, deposits) = depositDatum recoverOutputs m = traceIfFalse $(errorCode IncorrectDepositHash) $ hashOfOutputs m == hashPreSerializedCommits deposits diff --git a/hydra-tx/exe/Main.hs b/hydra-tx/exe/Main.hs index 90d79e573cf..e8c4a3b0319 100644 --- a/hydra-tx/exe/Main.hs +++ b/hydra-tx/exe/Main.hs @@ -6,7 +6,7 @@ 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.Contract.Deposit (DepositDatum (..)) import Hydra.Tx.Deposit (depositTx) import Hydra.Tx.Recover (recoverTx) import Hydra.Tx.Utils (extractInlineDatumFromTxOut) @@ -23,7 +23,7 @@ main = 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 + Recover RecoverOptions{networkId, outFile, recoverTxIn, utxoFilePath, recoverSlotNo} -> do eitherDecodeFileStrict utxoFilePath >>= \case Left err -> die $ "failed to parse provided UTXO file! " <> err Right (utxo :: UTxO) -> do @@ -32,8 +32,8 @@ main = do Just depositedTxOut -> do case extractInlineDatumFromTxOut @DepositDatum depositedTxOut of Nothing -> die "failed to extract DepositDatum from recover UTxO" - Just (_, _, depositted) -> do + Just (DepositDatum (headCS, datumDepositDeadline, deposited)) -> do let recoverTransaction = - recoverTx networkId headId recoverTxIn depositted depositDeadline recoverSlotNo + recoverTx networkId headCS recoverTxIn deposited datumDepositDeadline recoverSlotNo writeFileLBS outFile $ textEnvelopeToJSON Nothing recoverTransaction putStrLn $ "Wrote deposit transaction to " <> outFile diff --git a/hydra-tx/exe/Options.hs b/hydra-tx/exe/Options.hs index 61fa8e5d043..0558ba0d27b 100644 --- a/hydra-tx/exe/Options.hs +++ b/hydra-tx/exe/Options.hs @@ -27,10 +27,8 @@ data DepositOptions = DepositOptions data RecoverOptions = RecoverOptions { recoverTxIn :: TxIn , utxoFilePath :: FilePath - , headId :: HeadId , outFile :: FilePath , networkId :: NetworkId - , depositDeadline :: UTCTime , recoverSlotNo :: SlotNo } deriving stock (Show, Eq) @@ -76,10 +74,8 @@ recoverOptionsParser = RecoverOptions <$> txInParser <*> utxoParser - <*> headIdParser <*> outputFileParser <*> networkIdParser - <*> deadlineParser <*> lowerBoundSlotParser txInParser :: Parser TxIn @@ -192,6 +188,9 @@ lowerBoundSlotParser = <> help ( mconcat [ "Provide a starting slot for the recover transaction. " + , "This value could be obtained by querying the current slot number of the target network." + , "The slot needs to be after the deadline which was set in the deposit transaction " + , "in order for a recover transaction to be valid." ] ) diff --git a/hydra-tx/src/Hydra/Tx/Deposit.hs b/hydra-tx/src/Hydra/Tx/Deposit.hs index 5c9ada65890..4fa155c893b 100644 --- a/hydra-tx/src/Hydra/Tx/Deposit.hs +++ b/hydra-tx/src/Hydra/Tx/Deposit.hs @@ -34,14 +34,13 @@ depositTx networkId headId depositUTxO deadline = depositInputs = (,BuildTxWith $ KeyWitness KeyWitnessForSpending) <$> depositInputsList - depositValue = foldMap (txOutValue . snd) (UTxO.pairs depositUTxO) + depositValue = foldMap txOutValue depositUTxO depositScript = fromPlutusScript @PlutusScriptV2 Deposit.validatorScript - deposits = - mapMaybe Commit.serializeCommit $ UTxO.pairs depositUTxO + deposits = mapMaybe Commit.serializeCommit $ UTxO.pairs depositUTxO - depositPlutusDatum = Deposit.datum (headIdToCurrencySymbol headId, posixFromUTCTime deadline, deposits) + depositPlutusDatum = Deposit.datum $ Deposit.DepositDatum (headIdToCurrencySymbol headId, posixFromUTCTime deadline, deposits) depositDatum = mkTxOutDatumInline depositPlutusDatum diff --git a/hydra-tx/src/Hydra/Tx/Recover.hs b/hydra-tx/src/Hydra/Tx/Recover.hs index fde5d8e45b4..bebe1539ce5 100644 --- a/hydra-tx/src/Hydra/Tx/Recover.hs +++ b/hydra-tx/src/Hydra/Tx/Recover.hs @@ -13,42 +13,39 @@ import Hydra.Ledger.Cardano.Builder ( setValidityLowerBound, unsafeBuildTransaction, ) -import Hydra.Plutus.Extras (posixFromUTCTime) -import Hydra.Tx (HeadId, headIdToCurrencySymbol) +import PlutusLedgerApi.V2 (CurrencySymbol, POSIXTime) -- | Builds a recover transaction to recover locked funds from the v_deposit script. recoverTx :: NetworkId -> - HeadId -> + CurrencySymbol -> -- | Deposit input TxIn -> -- | Already Deposited funds [Commit.Commit] -> -- | Recover deadline - UTCTime -> + POSIXTime -> -- | Lower bound slot number SlotNo -> Tx -recoverTx networkId headId depositedTxIn depositted deadline lowerBoundSlot = +recoverTx networkId headId depositTxIn depositted deadline lowerBoundSlot = unsafeBuildTransaction $ emptyTxBody & addInputs recoverInputs - & addOutputs deposittedOutputs + & addOutputs depositOutputs & setValidityLowerBound lowerBoundSlot where - recoverInputs = (,depositWitness) <$> [depositedTxIn] + recoverInputs = (,depositWitness) <$> [depositTxIn] - redeemer = Deposit.Recover $ fromIntegral $ length deposittedOutputs + redeemer = Deposit.Recover $ fromIntegral $ length depositOutputs depositWitness = BuildTxWith $ ScriptWitness scriptWitnessInCtx $ mkScriptWitness depositScript (mkScriptDatum constructedDatum) (toScriptData redeemer) - constructedDatum = (headIdToCurrencySymbol headId, posixFromUTCTime deadline, depositted) + constructedDatum = (headId, deadline, depositted) - deposittedOutputs = - let deposited = mapMaybe (Commit.deserializeCommit (networkIdToNetwork networkId)) depositted - in fmap (toTxContext . snd) deposited + depositOutputs = toTxContext . snd <$> mapMaybe (Commit.deserializeCommit (networkIdToNetwork networkId)) depositted depositScript = fromPlutusScript @PlutusScriptV2 Deposit.validatorScript diff --git a/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs b/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs index adbd828ee52..36231c84b5a 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs @@ -45,7 +45,7 @@ import Hydra.Tx.Contract.Decrement (genDecrementMutation, healthyDecrementTx) import Hydra.Tx.Contract.Deposit (healthyDepositTx) import Hydra.Tx.Contract.FanOut (genFanoutMutation, healthyFanoutTx) import Hydra.Tx.Contract.Init (genInitMutation, healthyInitTx) -import Hydra.Tx.Contract.Recover (healthyRecoverTx) +import Hydra.Tx.Contract.Recover (genRecoverMutation, healthyRecoverTx) import Hydra.Tx.Crypto (aggregate, sign, toPlutusSignatures) import PlutusLedgerApi.V2 (fromBuiltin, toBuiltin) import Test.Hydra.Tx.Fixture (testNetworkId) @@ -120,6 +120,8 @@ spec = parallel $ do describe "Recover" $ do prop "is healthy" $ propTransactionEvaluates healthyRecoverTx + prop "does not survive random adversarial mutations" $ + propMutation healthyRecoverTx genRecoverMutation describe "CloseInitial" $ do prop "is healthy" $ propTransactionEvaluates healthyCloseInitialTx diff --git a/hydra-tx/test/Hydra/Tx/Contract/Recover.hs b/hydra-tx/test/Hydra/Tx/Contract/Recover.hs index 494b29a55e9..2070a7789d9 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Recover.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Recover.hs @@ -5,43 +5,107 @@ import Hydra.Prelude import Cardano.Api.UTxO qualified as UTxO import Data.Fixed (Milli) +import Data.List qualified as List import Data.Maybe (fromJust) -import Data.Time.Clock.POSIX (posixSecondsToUTCTime) -import Hydra.Contract.Deposit (DepositDatum) -import Hydra.Tx (mkHeadId) +import Data.Time.Clock.POSIX qualified as POSIX +import Hydra.Contract.Deposit (DepositDatum (..), DepositRedeemer (Recover)) +import Hydra.Contract.DepositError (DepositError (..)) +import Hydra.Contract.Error (toErrorCode) +import Hydra.Ledger.Cardano.Evaluate (slotLength, systemStart) +import Hydra.Ledger.Cardano.Time (slotNoToUTCTime) +import Hydra.Plutus.Extras (posixFromUTCTime) import Hydra.Tx.Deposit (depositTx) +import Hydra.Tx.HeadId (mkHeadId) import Hydra.Tx.Recover (recoverTx) import Hydra.Tx.Utils (extractInlineDatumFromTxOut) +import PlutusLedgerApi.V2 (CurrencySymbol, POSIXTime) import Test.Hydra.Tx.Fixture (testNetworkId, testPolicyId) -import Test.Hydra.Tx.Gen (genUTxOAdaOnlyOfSize) +import Test.Hydra.Tx.Gen (genUTxOAdaOnlyOfSize, genValue) +import Test.Hydra.Tx.Mutation ( + Mutation (ChangeInput, ChangeOutput, ChangeValidityLowerBound), + SomeMutation (..), + modifyInlineDatum, + ) +import Test.QuickCheck (elements, oneof, suchThat) healthyRecoverTx :: (Tx, UTxO) healthyRecoverTx = - (tx, utxo) + (tx, lookupUTxO) where tx = recoverTx testNetworkId - headId + headCS depositTxIn deposits - deadline + recoverDeadline recoverSlotNo - headId = mkHeadId testPolicyId + DepositDatum (_, _, deposits) = + fromJust $ extractInlineDatumFromTxOut @DepositDatum depositTxOut - deadline = (posixSecondsToUTCTime . realToFrac <$> (arbitrary :: Gen Milli)) `generateWith` 42 +recoverSlotNo :: SlotNo +recoverSlotNo = SlotNo $ arbitrary `generateWith` 42 - recoverSlotNo = arbitrary `generateWith` 42 +recoverDeadline :: POSIXTime +recoverDeadline = posixFromUTCTime depositDeadline - utxo = utxoFromTx $ depositTx testNetworkId headId depositUTxO deadline +depositDeadline :: UTCTime +depositDeadline = + slotNoToUTCTime systemStart slotLength (recoverSlotNo - SlotNo 1) - depositUTxO = genUTxOAdaOnlyOfSize 1 `generateWith` 42 +depositTransaction :: Tx +depositTransaction = + depositTx testNetworkId (mkHeadId headPolicyId) utxoToDeposit depositDeadline - (depositTxIn, depositTxOut) = - case UTxO.pairs utxo of - [] -> error "empty UTxO" - [(depositTxIn', depositTxOut')] -> (depositTxIn', depositTxOut') - _ -> error "multiple UTxO entries" +utxoToDeposit :: UTxO +utxoToDeposit = genUTxOAdaOnlyOfSize 1 `generateWith` 42 - (_, _, deposits) = fromJust $ extractInlineDatumFromTxOut @DepositDatum depositTxOut +headCS :: CurrencySymbol +headCS = toPlutusCurrencySymbol testPolicyId + +headPolicyId :: PolicyId +headPolicyId = + case fromPlutusCurrencySymbol headCS of + Nothing -> error "failed to create headId from provided CurrencySymbol" + Just policyId -> policyId + +lookupUTxO :: UTxO +lookupUTxO = utxoFromTx depositTransaction + +depositTxIn :: TxIn +depositTxOut :: TxOut CtxUTxO +(depositTxIn, depositTxOut) = List.head $ UTxO.pairs lookupUTxO + +data RecoverMutation + = -- | Move the deposit deadline further so that the recover lower bound is + -- not after the deadline + MutateDepositDeadline + | -- | Change the recover output so that the datum commit hash does not match + MutateRecoverOutput + | -- | Remove the lower bound from the recover transaction + RemoveTxValidityLowerBound + deriving stock (Generic, Show, Enum, Bounded) + +genRecoverMutation :: (Tx, UTxO) -> Gen SomeMutation +genRecoverMutation (tx, utxo) = + oneof + [ SomeMutation (pure $ toErrorCode DepositDeadlineNotReached) MutateDepositDeadline <$> do + -- Could also use depositTxIn/Out directly but this way we can be sure that the depositTxIn/Out are in the UTxO + let (depositIn, depositOut@(TxOut addr val _ rscript)) = List.head $ UTxO.pairs (resolveInputsUTxO utxo tx) + let n = POSIX.posixSecondsToUTCTime $ realToFrac $ (arbitrary :: Gen Milli) `generateWith` 42 + let datum = + txOutDatum $ + flip modifyInlineDatum (toTxContext depositOut) $ \case + DepositDatum (headCS', depositDatumDeadline, commits) -> + DepositDatum (headCS', depositDatumDeadline + posixFromUTCTime n, commits) + let newOutput = toCtxUTxOTxOut $ TxOut addr val datum rscript + pure $ ChangeInput depositIn newOutput (Just $ toScriptData $ Recover 1) + , SomeMutation (pure $ toErrorCode IncorrectDepositHash) MutateRecoverOutput <$> do + let outs = txOuts' tx + (ix :: Int, out) <- elements (zip [0 ..] outs) + value' <- genValue `suchThat` (/= txOutValue out) + pure $ ChangeOutput (fromIntegral ix) (modifyTxOutValue (const value') out) + , SomeMutation (pure $ toErrorCode DepositNoLowerBoundDefined) RemoveTxValidityLowerBound . ChangeValidityLowerBound <$> do + pure TxValidityNoLowerBound + ]