Skip to content

Commit fbffd68

Browse files
authored
Merge pull request #1408 from input-output-hk/fee-calculation-fix
Fee calculation in presence of random signers
2 parents 980f608 + e292f64 commit fbffd68

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

hydra-cluster/hydra-cluster.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ test-suite tests
159159
, async
160160
, base >=4.7 && <5
161161
, bytestring
162+
, cardano-ledger-api
162163
, containers
163164
, directory
164165
, filepath

hydra-cluster/test/Test/DirectChainSpec.hs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module Test.DirectChainSpec where
55
import Hydra.Prelude
66
import Test.Hydra.Prelude
77

8+
import Cardano.Ledger.Api (bodyTxL, reqSignerHashesTxBodyL)
89
import CardanoClient (
910
QueryPoint (QueryTip),
1011
RunningNode (..),
@@ -17,17 +18,23 @@ import CardanoClient (
1718
import CardanoNode (NodeLog, withCardanoNodeDevnet)
1819
import Control.Concurrent.STM (newEmptyTMVarIO, takeTMVar)
1920
import Control.Concurrent.STM.TMVar (putTMVar)
21+
import Control.Lens ((<>~))
22+
import Data.Set qualified as Set
2023
import Hydra.Cardano.Api (
2124
ChainPoint (..),
2225
CtxUTxO,
2326
Key (SigningKey),
2427
PaymentKey,
2528
TxOut,
2629
UTxO',
30+
fromLedgerTx,
2731
lovelaceToValue,
2832
signTx,
33+
toLedgerKeyHash,
34+
toLedgerTx,
2935
txOutValue,
3036
unFile,
37+
verificationKeyHash,
3138
)
3239
import Hydra.Chain (
3340
Chain (Chain, draftCommitTx, postTx),
@@ -79,7 +86,7 @@ import Hydra.Party (Party)
7986
import Hydra.Snapshot (ConfirmedSnapshot (..), Snapshot (..))
8087
import System.FilePath ((</>))
8188
import System.Process (proc, readCreateProcess)
82-
import Test.QuickCheck (generate)
89+
import Test.QuickCheck (choose, generate)
8390

8491
spec :: Spec
8592
spec = around (showLogsOnFailure "DirectChainSpec") $ do
@@ -240,6 +247,38 @@ spec = around (showLogsOnFailure "DirectChainSpec") $ do
240247
externalCommit node aliceChain aliceExternalSk headId mempty
241248
aliceChain `observesInTime` OnCommitTx headId alice mempty
242249

250+
it "can commit with multiple required signatures" $ \tracer -> do
251+
withTempDir "hydra-cluster" $ \tmp -> do
252+
withCardanoNodeDevnet (contramap FromNode tracer) tmp $ \node@RunningNode{nodeSocket} -> do
253+
hydraScriptsTxId <- publishHydraScriptsAs node Faucet
254+
-- Alice setup
255+
(aliceCardanoVk, _) <- keysFor Alice
256+
seedFromFaucet_ node aliceCardanoVk 100_000_000 (contramap FromFaucet tracer)
257+
aliceChainConfig <- chainConfigFor Alice tmp nodeSocket hydraScriptsTxId [] cperiod
258+
withDirectChainTest (contramap (FromDirectChain "alice") tracer) aliceChainConfig alice $
259+
\aliceChain@DirectChainTest{postTx} -> do
260+
-- Scenario
261+
participants <- loadParticipants [Alice]
262+
let headParameters = HeadParameters cperiod [alice]
263+
postTx $ InitTx{participants, headParameters}
264+
headId <- fst <$> aliceChain `observesInTimeSatisfying` hasInitTxWith headParameters participants
265+
266+
(aliceExternalVk, aliceExternalSk) <- generate genKeyPair
267+
newAliceUTxO <- seedFromFaucet node aliceExternalVk 3_000_000 (contramap FromFaucet tracer)
268+
269+
numberOfKeyWits <- generate $ choose (2, 10)
270+
randomKeys <- generate $ replicateM numberOfKeyWits genKeyPair
271+
272+
let blueprintTx =
273+
fromLedgerTx
274+
( toLedgerTx (txSpendingUTxO newAliceUTxO)
275+
& bodyTxL . reqSignerHashesTxBodyL
276+
<>~ Set.fromList (toLedgerKeyHash . verificationKeyHash . fst <$> randomKeys)
277+
)
278+
279+
externalCommit' node aliceChain (aliceExternalSk : fmap snd randomKeys) headId newAliceUTxO blueprintTx
280+
aliceChain `observesInTime` OnCommitTx headId alice newAliceUTxO
281+
243282
it "can open, close & fanout a Head" $ \tracer -> do
244283
withTempDir "hydra-cluster" $ \tmp -> do
245284
withCardanoNodeDevnet (contramap FromNode tracer) tmp $ \node@RunningNode{nodeSocket, networkId} -> do
@@ -527,10 +566,24 @@ externalCommit ::
527566
IO ()
528567
externalCommit node hydraClient externalSk headId utxoToCommit = do
529568
let blueprintTx = txSpendingUTxO utxoToCommit
569+
externalCommit' node hydraClient [externalSk] headId utxoToCommit blueprintTx
570+
571+
externalCommit' ::
572+
RunningNode ->
573+
DirectChainTest Tx IO ->
574+
[SigningKey PaymentKey] ->
575+
HeadId ->
576+
UTxO' (TxOut CtxUTxO) ->
577+
Tx ->
578+
IO ()
579+
externalCommit' node hydraClient externalSks headId utxoToCommit blueprintTx = do
530580
commitTx <- draftCommitTx headId utxoToCommit blueprintTx
531-
let signedTx = signTx externalSk commitTx
581+
let signedTx = everybodySigns commitTx externalSks
532582
submitTx node signedTx
533583
where
584+
everybodySigns tx' [] = tx'
585+
everybodySigns tx' (sk : sks) = everybodySigns (signTx sk tx') sks
586+
534587
DirectChainTest{draftCommitTx} = hydraClient
535588

536589
-- | Load key files for given 'Actor's (see keysFor) and directly convert them to 'OnChainId'.

hydra-node/src/Hydra/Chain/Direct/Wallet.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import Cardano.Ledger.Api (
3838
ppMaxTxExUnitsL,
3939
rdmrsTxWitsL,
4040
referenceInputsTxBodyL,
41+
reqSignerHashesTxBodyL,
4142
scriptIntegrityHashTxBodyL,
4243
witsTxL,
4344
)
@@ -311,9 +312,8 @@ coverFee_ pparams systemStart epochInfo lookupUTxO walletUTxO partialTx@Babbage.
311312
unbalancedTx
312313
& bodyTxL . outputsTxBodyL %~ (|> feeTxOut)
313314
& bodyTxL . feeTxBodyL .~ Coin 10_000_000
314-
-- XXX: Not hard-code but parameterize to make this flexible enough for
315-
-- later signing and commit transactions with more than one sig
316-
additionalWitnesses = 2
315+
-- We add one additional witness for the fee input
316+
additionalWitnesses = 1 + length (partialTx ^. bodyTxL . reqSignerHashesTxBodyL)
317317

318318
-- Balance tx with a change output and computed fee
319319
change <-

0 commit comments

Comments
 (0)