Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incremental decommit e2e scenario #1208

Merged
merged 5 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions hydra-cluster/src/CardanoClient.hs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,17 @@ waitForPayment networkId socket amount addr =
selectPayment (UTxO utxo) =
Map.filter ((== amount) . selectLovelace . txOutValue) utxo

-- | Wait for transaction outputs with matching lovelace value and addresses of
-- the whole given UTxO
waitForUTxO ::
NetworkId ->
SocketPath ->
RunningNode ->
UTxO ->
IO ()
waitForUTxO networkId nodeSocket utxo =
waitForUTxO node utxo =
forM_ (snd <$> UTxO.pairs utxo) forEachUTxO
where
RunningNode{networkId, nodeSocket} = node

forEachUTxO :: TxOut CtxUTxO -> IO ()
forEachUTxO = \case
TxOut (ShelleyAddressInEra addr@ShelleyAddress{}) value _ _ -> do
Expand Down
43 changes: 43 additions & 0 deletions hydra-cluster/src/Hydra/Cluster/Scenarios.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import CardanoClient (
queryTip,
queryUTxOFor,
submitTx,
waitForUTxO,
)
import CardanoNode (NodeLog, RunningNode (..))
import Control.Concurrent.Async (mapConcurrently_)
Expand Down Expand Up @@ -81,6 +82,8 @@ import HydraNode (
withHydraCluster,
withHydraNode,
)
import Network.HTTP.Client.Conduit (Request (requestBody))
import Network.HTTP.Conduit (RequestBody (RequestBodyLBS), parseUrlThrow)
import Network.HTTP.Conduit qualified as L
import Network.HTTP.Req (
HttpException (VanillaHttpException),
Expand All @@ -95,6 +98,7 @@ import Network.HTTP.Req (
runReq,
(/:),
)
import Network.HTTP.Simple (httpLbs)
import PlutusLedgerApi.Test.Examples qualified as Plutus
import System.Directory (removeDirectoryRecursive)
import System.FilePath ((</>))
Expand Down Expand Up @@ -624,6 +628,45 @@ initWithWrongKeys workDir tracer node@RunningNode{nodeSocket} hydraScriptsTxId =

participants `shouldMatchList` expectedParticipants

-- | Open a a single participant head with some UTxO and decommit parts of it.
canDecommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO ()
canDecommit tracer workDir node hydraScriptsTxId =
(`finally` returnFundsToFaucet tracer node Alice) $ do
refuelIfNeeded tracer node Alice 25_000_000
-- Start hydra-node on chain tip
tip <- queryTip networkId nodeSocket
let contestationPeriod = UnsafeContestationPeriod 100
aliceChainConfig <-
chainConfigFor Alice workDir nodeSocket [] contestationPeriod
<&> \config -> config{networkId, startChainFrom = Just tip}
withHydraNode hydraTracer aliceChainConfig workDir 1 aliceSk [] [1] hydraScriptsTxId $ \n1@HydraClient{hydraNodeId} -> do
-- Initialize & open head
send n1 $ input "Init" []
headId <- waitMatch 10 n1 $ headIsInitializingWith (Set.fromList [alice])

(walletVk, walletSk) <- generate genKeyPair

firstUTxO <- seedFromFaucet node walletVk 2_000_000 (contramap FromFaucet tracer)
decommitUTxO <- seedFromFaucet node walletVk 1_000_000 (contramap FromFaucet tracer)

let commitUTxO = firstUTxO <> decommitUTxO

requestCommitTx n1 commitUTxO <&> signTx walletSk >>= submitTx node

waitFor hydraTracer 10 [n1] $
output "HeadIsOpen" ["utxo" .= commitUTxO, "headId" .= headId]

request <- parseUrlThrow ("POST http://localhost:" <> show (4000 + hydraNodeId) <> "/decommit")
let decommitRequest = request{requestBody = RequestBodyLBS $ Aeson.encode decommitUTxO}
-- TODO: check that we get the expected response
res <- httpLbs decommitRequest

failAfter 10 $ waitForUTxO node decommitUTxO
where
hydraTracer = contramap FromHydraNode tracer

RunningNode{networkId, nodeSocket} = node

-- * Utilities

-- | Refuel given 'Actor' with given 'Lovelace' if current marked UTxO is below that amount.
Expand Down
2 changes: 1 addition & 1 deletion hydra-cluster/test/Test/DirectChainSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ spec = around (showLogsOnFailure "DirectChainSpec") $ do
}
aliceChain `observesInTime` OnFanoutTx headId
failAfter 5 $
waitForUTxO networkId nodeSocket someUTxO
waitForUTxO node someUTxO

it "can restart head to point in the past and replay on-chain events" $ \tracer -> do
withTempDir "direct-chain" $ \tmp -> do
Expand Down
26 changes: 8 additions & 18 deletions hydra-cluster/test/Test/EndToEndSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,7 @@ import Hydra.Cluster.Fixture (
carolSk,
carolVk,
)
import Hydra.Cluster.Scenarios (
EndToEndLog (..),
canCloseWithLongContestationPeriod,
canSubmitTransactionThroughAPI,
headIsInitializingWith,
initWithWrongKeys,
refuelIfNeeded,
restartedNodeCanAbort,
restartedNodeCanObserveCommitTx,
singlePartyCannotCommitExternallyWalletUtxo,
singlePartyCommitsExternalScriptWithInlineDatum,
singlePartyCommitsFromExternalScript,
singlePartyHeadFullLifeCycle,
testPreventResumeReconfiguredPeer,
threeNodesNoErrorsOnOpen,
)
import Hydra.Cluster.Scenarios (EndToEndLog (..), canCloseWithLongContestationPeriod, canDecommit, canSubmitTransactionThroughAPI, headIsInitializingWith, initWithWrongKeys, refuelIfNeeded, restartedNodeCanAbort, restartedNodeCanObserveCommitTx, singlePartyCannotCommitExternallyWalletUtxo, singlePartyCommitsExternalScriptWithInlineDatum, singlePartyCommitsFromExternalScript, singlePartyHeadFullLifeCycle, testPreventResumeReconfiguredPeer, threeNodesNoErrorsOnOpen)
import Hydra.Cluster.Util (chainConfigFor, keysFor)
import Hydra.ContestationPeriod (ContestationPeriod (UnsafeContestationPeriod))
import Hydra.Crypto (generateSigningKey)
Expand Down Expand Up @@ -150,6 +135,11 @@ spec = around (showLogsOnFailure "EndToEndSpec") $
withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node ->
publishHydraScriptsAs node Faucet
>>= canSubmitTransactionThroughAPI tracer tmpDir node
it "can decommit utxo" $ \tracer -> do
withClusterTempDir "can-decommit-utxo" $ \tmpDir -> do
withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node ->
publishHydraScriptsAs node Faucet
>>= canDecommit tracer tmpDir node

describe "three hydra nodes scenario" $ do
it "does not error when all nodes open the head concurrently" $ \tracer ->
Expand Down Expand Up @@ -557,7 +547,7 @@ timedTx tmpDir tracer node@RunningNode{networkId, nodeSocket} hydraScriptsTxId =
confirmedTransactions ^.. values `shouldBe` [toJSON $ txId tx]

initAndClose :: FilePath -> Tracer IO EndToEndLog -> Int -> TxId -> RunningNode -> IO ()
initAndClose tmpDir tracer clusterIx hydraScriptsTxId node@RunningNode{nodeSocket, networkId} = do
initAndClose tmpDir tracer clusterIx hydraScriptsTxId node@RunningNode{nodeSocket} = do
aliceKeys@(aliceCardanoVk, _) <- generate genKeyPair
bobKeys@(bobCardanoVk, _) <- generate genKeyPair
carolKeys@(carolCardanoVk, _) <- generate genKeyPair
Expand Down Expand Up @@ -675,7 +665,7 @@ initAndClose tmpDir tracer clusterIx hydraScriptsTxId node@RunningNode{nodeSocke
Error err ->
failure $ "newUTxO isn't valid JSON?: " <> err
Data.Aeson.Success u ->
failAfter 5 $ waitForUTxO networkId nodeSocket u
failAfter 5 $ waitForUTxO node u

--
-- Fixtures
Expand Down
Loading