diff --git a/CHANGELOG.md b/CHANGELOG.md index aacd4874df4..f2b71ecd885 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,11 @@ changes. ## [0.20.0] - UNRELEASED -- Bump docusaurus version +- **BETA** hydra-node now supports incremental commits in beta mode. We would like to test out this feature + with the community members building on Hydra. This feature means you can commit funds to a Head while it is running. + TODO: Implement missing spec changes. -- **IMPORTANT - Do not release this version** - - Incremental commits - off-chain changes to make the incremental commits possible. - Important to note is that on-chain security is not implemented and hydra-node in this - state is not releasable! - Missing off-chain items to implement as a series of next PR's: - - Revisit types related to observations/posting transactions and make sure the fields are named appropriatelly +- **BREAKING** hydra-node accepts multiple `hydra-scripts-tx-id` as a comma-seperated list, as the outcome of changes in the Hydra scripts publishing. - Tested with `cardano-node 10.1.2` and `cardano-cli 10.1.1.0`. @@ -41,6 +38,8 @@ changes. - Overall this results in transactions still to be submitted once per client, but requires signifanctly less book-keeping on the client-side. +- Bump docusaurus version + - Add blockfrost support to `hydra-chain-observer`, to follow the chain via Blockfrost API. - Fix `bench-e2e single` benchmarks and only use `--output-directory` to keep diff --git a/demo/seed-devnet.sh b/demo/seed-devnet.sh index d6b87456cc5..58b5d94ed37 100755 --- a/demo/seed-devnet.sh +++ b/demo/seed-devnet.sh @@ -98,7 +98,9 @@ function publishReferenceScripts() { hnode publish-scripts \ --testnet-magic ${NETWORK_ID} \ --node-socket ${DEVNET_DIR}/node.socket \ - --cardano-signing-key devnet/credentials/faucet.sk + --cardano-signing-key devnet/credentials/faucet.sk \ + | tr '\n' ',' \ + | head -c -1 } function queryPParams() { diff --git a/docs/benchmarks/profiling.md b/docs/benchmarks/profiling.md index f6a00600b25..fcd1dbe36cc 100644 --- a/docs/benchmarks/profiling.md +++ b/docs/benchmarks/profiling.md @@ -39,7 +39,7 @@ Here, isolate the transaction for `5` parties by altering the function to `maybe ## Compiling a script for profiling -The `collectCom` transaction utilizes the `vCommit` and `vHead` validator scripts. To enable profiling, add the following directive to the modules [`Hydra.Contract.Commit`](/haddock/hydra-plutus/Hydra-Contract-Commit.html) and [`Hydra.Contract.Head`](/haddock/hydra-plutus/Hydra-Contract-Head.html): +The `collectCom` transaction utilizes the `vCommit` and `vHead` validator scripts. To enable profiling, add the following directive to the modules [`Hydra.Contract.Commit`](pathname:///haddock/hydra-plutus/Hydra-Contract-Commit.html) and [`Hydra.Contract.Head`](pathname:///haddock/hydra-plutus/Hydra-Contract-Head.html): ``` {-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:profile-all #-} @@ -48,7 +48,7 @@ The `collectCom` transaction utilizes the `vCommit` and `vHead` validator script ## Acquiring an executable script You can achieve this using -[`prepareTxScripts`](/haddock/hydra-tx/Hydra-Ledger-Cardano-Evaluate.html#v:prepareTxScripts). +[`prepareTxScripts`](pathname:///haddock/hydra-tx/Hydra-Ledger-Cardano-Evaluate.html#v:prepareTxScripts). To acquire and save the fully applied scripts from the transaction onto disk, run: ```haskell diff --git a/docs/docs/dev/architecture/networking.md b/docs/docs/dev/architecture/networking.md index de266b63a42..9d894ab1362 100644 --- a/docs/docs/dev/architecture/networking.md +++ b/docs/docs/dev/architecture/networking.md @@ -74,7 +74,7 @@ See also [this ADR](/adr/27) for a past discussion on making the network compone ### Current network stack -See [haddocks](/haddock/hydra-node/Hydra-Node-Network.html) +See [haddocks](pathname:///haddock/hydra-node/Hydra-Node-Network.html) - Hydra nodes form a network of pairwise connected *peers* using point-to-point (eg, TCP) connections that are expected to remain active at all times: - Nodes use [Ouroboros](https://github.com/input-output-hk/ouroboros-network/) as the underlying network abstraction, which manages connections with peers via a reliable point-to-point stream-based communication framework known as a `Snocket` diff --git a/docs/docs/dev/commit_to_a_Head.md b/docs/docs/dev/commit_to_a_Head.md index 4132b950563..97464e6b266 100644 --- a/docs/docs/dev/commit_to_a_Head.md +++ b/docs/docs/dev/commit_to_a_Head.md @@ -84,7 +84,7 @@ users can request a recover by providing a `TxId` of the deposit transaction which initially locked the funds. ::::info -Users can also request to see pending deposits. See our api [documentation](/api-reference/#operation-publish-/commits). +Users can also request to see pending deposits. See our api [documentation](/api-reference). :::: Any Head participant can request to recover the deposit not only the one which initially deposited the funds. diff --git a/docs/docs/dev/incremental-commits-and-decommits.md b/docs/docs/dev/incremental-commits-and-decommits.md new file mode 100644 index 00000000000..6501e52da60 --- /dev/null +++ b/docs/docs/dev/incremental-commits-and-decommits.md @@ -0,0 +1,121 @@ +# Incremental commits and decommits + +These two new addons to the initial Hydra Head protocol deserve more +explanation so our users are aware of how they work _under the hood_ to bring +more clarity to these processes. + +For now these two new additions run sequentially so we are doing one thing at a +time, at least for now, while we will think about batching certain actions in +the future if the need for that arises. + +It is only possible to either commit or decommit - we don't allow snapshots with both +fields specified for simplicity. This restriction might be lifted later on - once we +are sure this simpler version works nicely. + +## Incremental Commits + +Incremental Commits allow us to take some `UTxO` from L1 and make it available +on L2 for transacting inside of a running Hydra Head. + +The process for incremental commits is pretty much the same as when +_committing_ before the Head is in the `Open` state. In fact we can open a Head +without committing some funds and then _top-up_ our L2 funds by doing incremental +commits. + +The process of incrementally committing a `UTxO` starts by sending a `HTTP` request to +the hydra-node API endpoint: + +```bash + +curl -X POST :/commit --data @commit.json +``` + +:::info + +Note that the commit transaction, which is sent to the hydra-node API, only needs +to specify the transaction inputs present in L1 that we want to make available +on L2. It will ignore any specified outputs and instead the owner of +incremented `UTxO` on L2 is the same one that owned the funds on L1. + +::: + +Hydra node will accept a plain `UTxO` encoded as JSON in the `POST` request +body or a _blueprint_ transaction together with the `UTxO` used to resolve it's +inputs. + +_Blueprint_ transaction is just like a recipe that describes which transaction +inputs should be made available on L2 network ignoring any specified outputs. +It goes together with a `UTxO` used to resolve the transaction inputs. It's +purpose is to prove that one can spend specified transaction inputs. + +Successfull API response includes a _deposit_ transaction that needs to be +signed and submitted by the user in order to kick-off the deposit process. + +This process just locks the specified `UTxO` at a deposit script address which +will then, later on, after confirmed snapshot, be unlocked by the _increment_ +transaction which will actually make this `UTxO` available on L2. + +The deposit transaction contains a deadline - time window in which we expect +the hydra-node to be able to observe this deposit and issue a _increment_ +transaction that will do the heavy lifting and bring the specified input on L2. + +Currently, _contestation period_ value is used to specify a deposit deadline +but this should be made available as a separate argument to hydra-node since it +heavily depends on the network we are running on. + +Once a hydra-node observes a deposit transaction it will record the deposit as +pending into the local state. There can be many pending deposits but the new +Snapshot will include them one by one. + +When this new Snapshot is acknowledged by all parties _increment_ transaction +will be posted by the leader. + +:::info +Note that any node that posts increment transaction will also pay the fees even if +the deposit will not be owned by them on L2. +::: + +Upon observing increment transaction we remove deposit from the local pending deposits +and the process can start again. + +:::note + +Since we can potentially request many deposits, the leader will increment only +one of them. While others are stuck in the pending state any new transaction on +L2 will take next pending deposit and try to include it in a snapshot. + +::: + +## Incremental Decommits + +Incremental decommits allow us to take some L2 `UTxO` and bring it to the L1 +while the Head protocol is running. + +Head participant (or any other user that can send requests to the hydra-node +API endpoint) requests inclusion of some UTxO from L1 by sending a `POST` +`HTTP` request which contains in the request body a decommit transaction +encoded as _TextEnvelope_ JSON value. + +```bash +curl -X POST :/decommit --data @decommit-tx.json +``` + +This transaction needs to be signed by the owner of the funds on L2. + +:::info + +What we call a decommit transaction is the one that user supplies in the API +endpoint. The decrement transaction is the transaction that hydra-node posts +after it checks that decommit transaction applies and the one that actually +makes some UTxO available on L1. + +::: + +Hydra node accepts this transaction and checks if it can be cleanly applied to +the local `UTxO` set. After this check hydra-node will issue a `ReqDec` message +signalling to other parties that we want to produce a new `Snapshot` that +contains the same `UTxO` to decommit. Once a snapshot is signed, hydra-node +posts a _decrement_ transaction that will take specified output and make it +available on L1. + + diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index a66e511c7c1..1a463ce7005 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -19,7 +19,7 @@ const config = { baseUrl: "/head-protocol/", // Note: This gives warnings about the haddocks; but actually they are // present. If you are concerned, please check the links manually! - onBrokenLinks: "warn", + onBrokenLinks: "throw", onBrokenMarkdownLinks: "warn", favicon: "img/hydra.png", organizationName: "Input Output", diff --git a/docs/sidebars.js b/docs/sidebars.js index d9ebee986b5..e584f813d65 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -70,6 +70,7 @@ module.exports = { label: "Specification", }, "dev/protocol", + "dev/incremental-commits-and-decommits", { type: "doc", id: "dev/commit_to_a_Head", diff --git a/flake.lock b/flake.lock index 47d5f3a734a..e5a562527e9 100644 --- a/flake.lock +++ b/flake.lock @@ -73,11 +73,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1727863681, - "narHash": "sha256-lzSItBMYcZ7Q92+u/8XFoFgwslfkUBf8RqsunrIoruQ=", + "lastModified": 1729359954, + "narHash": "sha256-cspIIuH+0LJItTz9wk6mChwEMFP3GDpI+KKg0FWM9bQ=", "owner": "aiken-lang", "repo": "aiken", - "rev": "c7ae161a39c29656938ce1c8d4f674e387980022", + "rev": "a7741ec286bd939784f3183420be845d22de9a25", "type": "github" }, "original": { diff --git a/hydra-cluster/src/Hydra/Cluster/Faucet.hs b/hydra-cluster/src/Hydra/Cluster/Faucet.hs index 82d1699f155..07f5676a545 100644 --- a/hydra-cluster/src/Hydra/Cluster/Faucet.hs +++ b/hydra-cluster/src/Hydra/Cluster/Faucet.hs @@ -21,7 +21,6 @@ import Control.Exception (IOException) import Control.Monad.Class.MonadThrow (Handler (Handler), catches) import Control.Tracer (Tracer, traceWith) import GHC.IO.Exception (IOErrorType (ResourceExhausted), IOException (ioe_type)) -import Hydra.Chain.CardanoClient (queryProtocolParameters) import Hydra.Chain.ScriptRegistry ( publishHydraScripts, ) @@ -150,15 +149,8 @@ createOutputAtAddress :: createOutputAtAddress node@RunningNode{networkId, nodeSocket} atAddress datum val = do (faucetVk, faucetSk) <- keysFor Faucet utxo <- findFaucetUTxO node 0 - pparams <- queryProtocolParameters networkId nodeSocket QueryTip let collateralTxIns = mempty - let output = - mkTxOutAutoBalance - pparams - atAddress - val - datum - ReferenceScriptNone + let output = TxOut atAddress val datum ReferenceScriptNone buildTransaction networkId nodeSocket @@ -205,7 +197,7 @@ retryOnExceptions tracer action = -- -- The key of the given Actor is used to pay for fees in required transactions, -- it is expected to have sufficient funds. -publishHydraScriptsAs :: RunningNode -> Actor -> IO TxId +publishHydraScriptsAs :: RunningNode -> Actor -> IO [TxId] publishHydraScriptsAs RunningNode{networkId, nodeSocket} actor = do (_, sk) <- keysFor actor publishHydraScripts networkId nodeSocket sk diff --git a/hydra-cluster/src/Hydra/Cluster/Options.hs b/hydra-cluster/src/Hydra/Cluster/Options.hs index d039194dee7..0c907392019 100644 --- a/hydra-cluster/src/Hydra/Cluster/Options.hs +++ b/hydra-cluster/src/Hydra/Cluster/Options.hs @@ -1,6 +1,9 @@ +{-# LANGUAGE OverloadedStrings #-} + module Hydra.Cluster.Options where import Data.ByteString.Char8 qualified as BSC +import Data.List qualified as List import Hydra.Cardano.Api (AsType (AsTxId), TxId, deserialiseFromRawBytesHex) import Hydra.Cluster.Fixture (KnownNetwork (..)) import Hydra.Prelude @@ -17,7 +20,7 @@ data Options = Options deriving stock (Show, Eq, Generic) deriving anyclass (ToJSON, FromJSON) -data PublishOrReuse = Publish | Reuse TxId +data PublishOrReuse = Publish | Reuse [TxId] deriving stock (Show, Eq, Generic) deriving anyclass (ToJSON, FromJSON) @@ -73,13 +76,17 @@ parseOptions = <> help "Publish hydra scripts before running the scenario." ) <|> option - (eitherReader $ bimap show Reuse . deserialiseFromRawBytesHex AsTxId . BSC.pack) + (eitherReader $ bimap show Reuse . parseTxIds) ( long "hydra-scripts-tx-id" <> metavar "TXID" <> help "Use the hydra scripts already published in given transaction id. \ \See --publish-hydra-scripts or hydra-node publish-scripts" ) + where + parseTxIds str = + let parsed = fmap (deserialiseFromRawBytesHex AsTxId . BSC.pack) (List.lines str) + in if null (lefts parsed) then Right (rights parsed) else Left ("Invalid TxId" :: String) parseUseMithril = flag diff --git a/hydra-cluster/src/Hydra/Cluster/Scenarios.hs b/hydra-cluster/src/Hydra/Cluster/Scenarios.hs index de3312b4ee8..210d5d6c238 100644 --- a/hydra-cluster/src/Hydra/Cluster/Scenarios.hs +++ b/hydra-cluster/src/Hydra/Cluster/Scenarios.hs @@ -125,13 +125,13 @@ data EndToEndLog | StartingFunds {actor :: String, utxo :: UTxO} | RefueledFunds {actor :: String, refuelingAmount :: Coin, utxo :: UTxO} | RemainingFunds {actor :: String, utxo :: UTxO} - | PublishedHydraScriptsAt {hydraScriptsTxId :: TxId} - | UsingHydraScriptsAt {hydraScriptsTxId :: TxId} + | PublishedHydraScriptsAt {hydraScriptsTxId :: [TxId]} + | UsingHydraScriptsAt {hydraScriptsTxId :: [TxId]} | CreatedKey {keyPath :: FilePath} deriving stock (Eq, Show, Generic) deriving anyclass (ToJSON, FromJSON) -restartedNodeCanObserveCommitTx :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +restartedNodeCanObserveCommitTx :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () restartedNodeCanObserveCommitTx tracer workDir cardanoNode hydraScriptsTxId = do let clients = [Alice, Bob] [(aliceCardanoVk, _), (bobCardanoVk, _)] <- forM clients keysFor @@ -166,7 +166,7 @@ restartedNodeCanObserveCommitTx tracer workDir cardanoNode hydraScriptsTxId = do where RunningNode{nodeSocket, networkId} = cardanoNode -testPreventResumeReconfiguredPeer :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +testPreventResumeReconfiguredPeer :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () testPreventResumeReconfiguredPeer tracer workDir cardanoNode hydraScriptsTxId = do let contestationPeriod = UnsafeContestationPeriod 1 aliceChainConfig <- @@ -210,7 +210,7 @@ testPreventResumeReconfiguredPeer tracer workDir cardanoNode hydraScriptsTxId = failToConnect tr nodes = waitForNodesConnected tr 10 nodes `shouldThrow` anyException -restartedNodeCanAbort :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +restartedNodeCanAbort :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () restartedNodeCanAbort tracer workDir cardanoNode hydraScriptsTxId = do refuelIfNeeded tracer cardanoNode Alice 100_000_000 let contestationPeriod = UnsafeContestationPeriod 2 @@ -243,7 +243,7 @@ singlePartyHeadFullLifeCycle :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () singlePartyHeadFullLifeCycle tracer workDir node hydraScriptsTxId = ( `finally` @@ -302,7 +302,7 @@ singlePartyOpenAHead :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> -- | Continuation called when the head is open (HydraClient -> SigningKey PaymentKey -> IO ()) -> IO () @@ -341,7 +341,7 @@ singlePartyCommitsFromExternal :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () singlePartyCommitsFromExternal tracer workDir node hydraScriptsTxId = ( `finally` @@ -384,7 +384,7 @@ singlePartyCommitsScriptBlueprint :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ do @@ -397,7 +397,7 @@ singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId = send n1 $ input "Init" [] headId <- waitMatch (10 * blockTime) n1 $ headIsInitializingWith (Set.fromList [alice]) - (clientPayload, scriptUTxO) <- prepareScriptPayload + (clientPayload, scriptUTxO) <- prepareScriptPayload 3_000_000 res <- runReq defaultHttpConfig $ @@ -417,7 +417,7 @@ singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId = pure $ v ^? key "utxo" lockedUTxO `shouldBe` Just (toJSON scriptUTxO) -- incrementally commit script to a running Head - (clientPayload', scriptUTxO') <- prepareScriptPayload + (clientPayload', scriptUTxO') <- prepareScriptPayload 2_000_000 res' <- runReq defaultHttpConfig $ @@ -443,12 +443,12 @@ singlePartyCommitsScriptBlueprint tracer workDir node hydraScriptsTxId = waitFor hydraTracer 10 [n1] $ output "GetUTxOResponse" ["headId" .= headId, "utxo" .= (scriptUTxO <> scriptUTxO')] where - prepareScriptPayload = do + prepareScriptPayload lovelaceAmt = do let script = dummyValidatorScript let serializedScript = PlutusScriptSerialised script let scriptAddress = mkScriptAddress networkId serializedScript let datumHash = mkTxOutDatumHash () - (scriptIn, scriptOut) <- createOutputAtAddress node scriptAddress datumHash (lovelaceToValue 0) + (scriptIn, scriptOut) <- createOutputAtAddress node scriptAddress datumHash (lovelaceToValue lovelaceAmt) let scriptUTxO = UTxO.singleton (scriptIn, scriptOut) let scriptWitness = @@ -473,7 +473,7 @@ persistenceCanLoadWithEmptyCommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () persistenceCanLoadWithEmptyCommit tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ do @@ -513,7 +513,7 @@ singlePartyCommitsFromExternalTxBlueprint :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () singlePartyCommitsFromExternalTxBlueprint tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ do @@ -572,7 +572,7 @@ canCloseWithLongContestationPeriod :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () canCloseWithLongContestationPeriod tracer workDir node hydraScriptsTxId = do refuelIfNeeded tracer node Alice 100_000_000 @@ -609,7 +609,7 @@ canSubmitTransactionThroughAPI :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> - TxId -> + [TxId] -> IO () canSubmitTransactionThroughAPI tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ do @@ -658,7 +658,7 @@ canSubmitTransactionThroughAPI tracer workDir node hydraScriptsTxId = -- | Three hydra nodes open a head and we assert that none of them sees errors. -- This was particularly misleading when everyone tries to post the collect -- transaction concurrently. -threeNodesNoErrorsOnOpen :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +threeNodesNoErrorsOnOpen :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () threeNodesNoErrorsOnOpen tracer tmpDir node@RunningNode{nodeSocket} hydraScriptsTxId = do aliceKeys@(aliceCardanoVk, _) <- generate genKeyPair bobKeys@(bobCardanoVk, _) <- generate genKeyPair @@ -702,7 +702,7 @@ threeNodesNoErrorsOnOpen tracer tmpDir node@RunningNode{nodeSocket} hydraScripts -- | Two hydra node setup where Alice is wrongly configured to use Carol's -- cardano keys instead of Bob's which will prevent him to be notified the -- `HeadIsInitializing` but he should still receive some notification. -initWithWrongKeys :: FilePath -> Tracer IO EndToEndLog -> RunningNode -> TxId -> IO () +initWithWrongKeys :: FilePath -> Tracer IO EndToEndLog -> RunningNode -> [TxId] -> IO () initWithWrongKeys workDir tracer node@RunningNode{nodeSocket} hydraScriptsTxId = do (aliceCardanoVk, _) <- keysFor Alice (carolCardanoVk, _) <- keysFor Carol @@ -733,47 +733,94 @@ initWithWrongKeys workDir tracer node@RunningNode{nodeSocket} hydraScriptsTxId = participants `shouldMatchList` expectedParticipants --- | Open a a single participant head and incrementally commit to it. -canCommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +-- | Open a a two participant head and incrementally commit to it. +canCommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () canCommit tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ do - refuelIfNeeded tracer node Alice 30_000_000 - let contestationPeriod = UnsafeContestationPeriod 1 - aliceChainConfig <- - chainConfigFor Alice workDir nodeSocket hydraScriptsTxId [] contestationPeriod - <&> setNetworkId networkId - withHydraNode hydraTracer aliceChainConfig workDir 1 aliceSk [] [1] $ \n1 -> do - send n1 $ input "Init" [] - headId <- waitMatch 10 n1 $ headIsInitializingWith (Set.fromList [alice]) + (`finally` returnFundsToFaucet tracer node Bob) $ do + refuelIfNeeded tracer node Alice 30_000_000 + refuelIfNeeded tracer node Bob 30_000_000 + -- NOTE: it is important to provide _large_ enough contestation period so that + -- increment tx can be submitted before the deadline + let contestationPeriod = UnsafeContestationPeriod 20 + aliceChainConfig <- + chainConfigFor Alice workDir nodeSocket hydraScriptsTxId [Bob] contestationPeriod + <&> setNetworkId networkId + bobChainConfig <- + chainConfigFor Bob workDir nodeSocket hydraScriptsTxId [Alice] contestationPeriod + <&> setNetworkId networkId + withHydraNode hydraTracer aliceChainConfig workDir 1 aliceSk [bobVk] [2] $ \n1 -> do + withHydraNode hydraTracer bobChainConfig workDir 2 bobSk [aliceVk] [1] $ \n2 -> do + send n1 $ input "Init" [] + -- _ <- waitMatch 10 n1 $ headIsInitializingWith (Set.fromList [bob]) + headId <- waitMatch 20 n2 $ headIsInitializingWith (Set.fromList [alice, bob]) - -- Commit nothing - requestCommitTx n1 mempty >>= submitTx node - waitFor hydraTracer (10 * blockTime) [n1] $ - output "HeadIsOpen" ["utxo" .= object mempty, "headId" .= headId] + -- Commit nothing + requestCommitTx n1 mempty >>= submitTx node + requestCommitTx n2 mempty >>= submitTx node + waitFor hydraTracer (20 * blockTime) [n1, n2] $ + output "HeadIsOpen" ["utxo" .= object mempty, "headId" .= headId] - -- Get some L1 funds - (walletVk, walletSk) <- generate genKeyPair - commitUTxO <- seedFromFaucet node walletVk 5_000_000 (contramap FromFaucet tracer) + -- Get some L1 funds + (walletVk, walletSk) <- generate genKeyPair + commitUTxO <- seedFromFaucet node walletVk 5_000_000 (contramap FromFaucet tracer) + commitUTxO2 <- seedFromFaucet node walletVk 5_000_000 (contramap FromFaucet tracer) - resp <- - parseUrlThrow ("POST " <> hydraNodeBaseUrl n1 <> "/commit") - <&> setRequestBodyJSON commitUTxO - >>= httpJSON + resp <- + parseUrlThrow ("POST " <> hydraNodeBaseUrl n2 <> "/commit") + <&> setRequestBodyJSON commitUTxO + >>= httpJSON - let depositTransaction = getResponseBody resp :: Tx - let tx = signTx walletSk depositTransaction + let depositTransaction = getResponseBody resp :: Tx + let tx = signTx walletSk depositTransaction - submitTx node tx + submitTx node tx - waitFor hydraTracer 10 [n1] $ - output "CommitApproved" ["headId" .= headId, "utxoToCommit" .= commitUTxO] - waitFor hydraTracer 10 [n1] $ - output "CommitFinalized" ["headId" .= headId, "theDeposit" .= getTxId (getTxBody tx)] + waitFor hydraTracer 20 [n1, n2] $ + output "CommitApproved" ["headId" .= headId, "utxoToCommit" .= commitUTxO] + waitFor hydraTracer 20 [n1, n2] $ + output "CommitFinalized" ["headId" .= headId, "theDeposit" .= getTxId (getTxBody tx)] - send n1 $ input "GetUTxO" [] + send n2 $ input "GetUTxO" [] - waitFor hydraTracer 10 [n1] $ - output "GetUTxOResponse" ["headId" .= headId, "utxo" .= commitUTxO] + waitFor hydraTracer 20 [n2] $ + output "GetUTxOResponse" ["headId" .= headId, "utxo" .= commitUTxO] + resp2 <- + parseUrlThrow ("POST " <> hydraNodeBaseUrl n1 <> "/commit") + <&> setRequestBodyJSON commitUTxO2 + >>= httpJSON + + let depositTransaction' = getResponseBody resp2 :: Tx + let tx' = signTx walletSk depositTransaction' + + submitTx node tx' + + waitFor hydraTracer 20 [n1, n2] $ + output "CommitApproved" ["headId" .= headId, "utxoToCommit" .= commitUTxO2] + waitFor hydraTracer 20 [n1, n2] $ + output "CommitFinalized" ["headId" .= headId, "theDeposit" .= getTxId (getTxBody tx')] + + send n1 $ input "GetUTxO" [] + + waitFor hydraTracer 20 [n1] $ + output "GetUTxOResponse" ["headId" .= headId, "utxo" .= (commitUTxO <> commitUTxO2)] + + send n2 $ input "Close" [] + + deadline <- waitMatch (20 * blockTime) n2 $ \v -> do + guard $ v ^? key "tag" == Just "HeadIsClosed" + v ^? key "contestationDeadline" . _JSON + + remainingTime <- diffUTCTime deadline <$> getCurrentTime + waitFor hydraTracer (remainingTime + 3 * blockTime) [n1, n2] $ + output "ReadyToFanout" ["headId" .= headId] + send n2 $ input "Fanout" [] + waitMatch (20 * blockTime) n2 $ \v -> + guard $ v ^? key "tag" == Just "HeadIsFinalized" + + -- Assert final wallet balance + (balance <$> queryUTxOFor networkId nodeSocket QueryTip walletVk) + `shouldReturn` balance (commitUTxO <> commitUTxO2) where RunningNode{networkId, nodeSocket, blockTime} = node @@ -782,14 +829,14 @@ canCommit tracer workDir node hydraScriptsTxId = hydraNodeBaseUrl HydraClient{hydraNodeId} = "http://127.0.0.1:" <> show (4000 + hydraNodeId) -- | Open a a single participant head, deposit and then recover it. -canRecoverDeposit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +canRecoverDeposit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () canRecoverDeposit tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ (`finally` returnFundsToFaucet tracer node Bob) $ do refuelIfNeeded tracer node Alice 30_000_000 refuelIfNeeded tracer node Bob 30_000_000 -- NOTE: this value is also used to determine the deposit deadline - let deadline = 1 + let deadline = 5 let contestationPeriod = UnsafeContestationPeriod deadline aliceChainConfig <- chainConfigFor Alice workDir nodeSocket hydraScriptsTxId [Bob] contestationPeriod @@ -798,7 +845,7 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId = chainConfigFor Bob workDir nodeSocket hydraScriptsTxId [Alice] contestationPeriod <&> setNetworkId networkId withHydraNode hydraTracer aliceChainConfig workDir 1 aliceSk [bobVk] [2] $ \n1 -> do - _ <- withHydraNode hydraTracer bobChainConfig workDir 2 bobSk [aliceVk] [1] $ \n2 -> do + headId <- withHydraNode hydraTracer bobChainConfig workDir 2 bobSk [aliceVk] [1] $ \n2 -> do send n1 $ input "Init" [] headId <- waitMatch 10 n1 $ headIsInitializingWith (Set.fromList [alice, bob]) @@ -810,7 +857,7 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId = output "HeadIsOpen" ["utxo" .= object mempty, "headId" .= headId] -- stop the second node here - pure () + pure headId -- Get some L1 funds (walletVk, walletSk) <- generate genKeyPair @@ -839,7 +886,8 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId = let path = BSC.unpack $ urlEncode False $ encodeUtf8 $ T.pack $ show (getTxId $ getTxBody tx) -- NOTE: we need to wait for the deadline to pass before we can recover the deposit - threadDelay $ fromIntegral (deadline * 2) + -- NOTE: for some reason threadDelay on MacOS behaves differently than on Linux so we need + 1 here + threadDelay $ fromIntegral (deadline * 2 + 1) recoverResp <- parseUrlThrow ("DELETE " <> hydraNodeBaseUrl n1 <> "/commits/" <> path) @@ -852,6 +900,22 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId = (balance <$> queryUTxOFor networkId nodeSocket QueryTip walletVk) `shouldReturn` lovelaceToValue commitAmount + send n1 $ input "Close" [] + + deadline' <- waitMatch (10 * blockTime) n1 $ \v -> do + guard $ v ^? key "tag" == Just "HeadIsClosed" + v ^? key "contestationDeadline" . _JSON + + remainingTime <- diffUTCTime deadline' <$> getCurrentTime + waitFor hydraTracer (remainingTime + 3 * blockTime) [n1] $ + output "ReadyToFanout" ["headId" .= headId] + send n1 $ input "Fanout" [] + waitMatch (20 * blockTime) n1 $ \v -> + guard $ v ^? key "tag" == Just "HeadIsFinalized" + + -- Assert final wallet balance + (balance <$> queryUTxOFor networkId nodeSocket QueryTip walletVk) + `shouldReturn` balance commitUTxO where RunningNode{networkId, nodeSocket, blockTime} = node @@ -860,7 +924,7 @@ canRecoverDeposit tracer workDir node hydraScriptsTxId = hydraNodeBaseUrl HydraClient{hydraNodeId} = "http://127.0.0.1:" <> show (4000 + hydraNodeId) -- | Make sure to be able to see pending deposits. -canSeePendingDeposits :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +canSeePendingDeposits :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () canSeePendingDeposits tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ (`finally` returnFundsToFaucet tracer node Bob) $ do @@ -947,7 +1011,7 @@ canSeePendingDeposits tracer workDir node hydraScriptsTxId = hydraNodeBaseUrl HydraClient{hydraNodeId} = "http://127.0.0.1:" <> show (4000 + hydraNodeId) -- | Open a a single participant head with some UTxO and incrementally decommit it. -canDecommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () +canDecommit :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> [TxId] -> IO () canDecommit tracer workDir node hydraScriptsTxId = (`finally` returnFundsToFaucet tracer node Alice) $ do refuelIfNeeded tracer node Alice 30_000_000 diff --git a/hydra-cluster/src/Hydra/Cluster/Util.hs b/hydra-cluster/src/Hydra/Cluster/Util.hs index d5600caeca6..fd12068dda4 100644 --- a/hydra-cluster/src/Hydra/Cluster/Util.hs +++ b/hydra-cluster/src/Hydra/Cluster/Util.hs @@ -66,8 +66,8 @@ chainConfigFor :: Actor -> FilePath -> SocketPath -> - -- | Transaction id at which Hydra scripts should have been published. - TxId -> + -- | Transaction ids at which Hydra scripts should have been published. + [TxId] -> [Actor] -> ContestationPeriod -> IO ChainConfig diff --git a/hydra-cluster/src/HydraNode.hs b/hydra-cluster/src/HydraNode.hs index 420434566b8..c5bd60b1375 100644 --- a/hydra-cluster/src/HydraNode.hs +++ b/hydra-cluster/src/HydraNode.hs @@ -247,8 +247,8 @@ withHydraCluster :: -- | NOTE: This decides on the size of the cluster! [(VerificationKey PaymentKey, SigningKey PaymentKey)] -> [SigningKey HydraKey] -> - -- | Transaction id at which Hydra scripts should have been published. - TxId -> + -- | Transaction ids at which Hydra scripts should have been published. + [TxId] -> ContestationPeriod -> (NonEmpty HydraClient -> IO a) -> IO a diff --git a/hydra-cluster/test/Test/DirectChainSpec.hs b/hydra-cluster/test/Test/DirectChainSpec.hs index a22ed8b0e72..e01479e3190 100644 --- a/hydra-cluster/test/Test/DirectChainSpec.hs +++ b/hydra-cluster/test/Test/DirectChainSpec.hs @@ -19,6 +19,7 @@ import CardanoNode (NodeLog, withCardanoNodeDevnet) import Control.Concurrent.STM (newEmptyTMVarIO, takeTMVar) import Control.Concurrent.STM.TMVar (putTMVar) import Control.Lens ((<>~)) +import Data.List qualified as List import Data.Set qualified as Set import Hydra.Cardano.Api ( ChainPoint (..), @@ -83,6 +84,7 @@ import Hydra.Tx.IsTx (IsTx (..)) import Hydra.Tx.OnChainId (OnChainId) import Hydra.Tx.Party (Party) import Hydra.Tx.Snapshot (ConfirmedSnapshot (..), Snapshot (..)) +import Hydra.Tx.Snapshot qualified as Snapshot import Hydra.Tx.Utils ( splitUTxO, verificationKeyToOnChainId, @@ -307,7 +309,8 @@ spec = around (showLogsOnFailure "DirectChainSpec") $ do \aliceChain@DirectChainTest{postTx} -> do -- Scenario (aliceExternalVk, aliceExternalSk) <- generate genKeyPair - someUTxO <- seedFromFaucet node aliceExternalVk 1_000_000 (contramap FromFaucet tracer) + someUTxO <- seedFromFaucet node aliceExternalVk 2_000_000 (contramap FromFaucet tracer) + someUTxOToCommit <- seedFromFaucet node aliceExternalVk 2_000_000 (contramap FromFaucet tracer) participants <- loadParticipants [Alice] let headParameters = HeadParameters cperiod [alice] postTx $ InitTx{participants, headParameters} @@ -318,20 +321,20 @@ spec = around (showLogsOnFailure "DirectChainSpec") $ do postTx $ CollectComTx someUTxO headId headParameters aliceChain `observesInTime` OnCollectComTx{headId} - let (inHead, toDecommit) = splitUTxO someUTxO let v = 0 + let snapshotVersion = 0 let snapshot = Snapshot { headId , number = 1 - , utxo = inHead + , utxo = someUTxO , confirmed = [] - , utxoToCommit = Nothing - , utxoToDecommit = Just toDecommit - , version = v + , utxoToCommit = Just someUTxOToCommit + , utxoToDecommit = Nothing + , version = snapshotVersion } - postTx $ CloseTx headId headParameters v (ConfirmedSnapshot{snapshot, signatures = aggregate [sign aliceSk snapshot]}) + postTx $ CloseTx headId headParameters snapshotVersion (ConfirmedSnapshot{snapshot, signatures = aggregate [sign aliceSk snapshot]}) deadline <- waitMatch aliceChain $ \case @@ -349,14 +352,20 @@ spec = around (showLogsOnFailure "DirectChainSpec") $ do _ -> Nothing postTx $ FanoutTx - { utxo = inHead - , utxoToDecommit = Just toDecommit + { utxo = Snapshot.utxo snapshot + , -- if snapshotVersion is not the same as local version, it + -- means we observed a commit so it needs to be fanned-out as well + utxoToCommit = if snapshotVersion /= v then Snapshot.utxoToCommit snapshot else Nothing + , utxoToDecommit = Snapshot.utxoToDecommit snapshot , headSeed , contestationDeadline = deadline } + let expectedUTxO = + (Snapshot.utxo snapshot <> fromMaybe mempty (Snapshot.utxoToCommit snapshot)) + `withoutUTxO` fromMaybe mempty (Snapshot.utxoToDecommit snapshot) aliceChain `observesInTime` OnFanoutTx headId failAfter 5 $ - waitForUTxO node (inHead <> toDecommit) + waitForUTxO node expectedUTxO it "can restart head to point in the past and replay on-chain events" $ \tracer -> do withTempDir "hydra-cluster" $ \tmp -> do @@ -418,7 +427,7 @@ spec = around (showLogsOnFailure "DirectChainSpec") $ do ) ) "" - let hydraScriptsTxId = fromString hydraScriptsTxIdStr + let hydraScriptsTxId = fromString <$> List.lines hydraScriptsTxIdStr failAfter 5 $ void $ queryScriptRegistry networkId nodeSocket hydraScriptsTxId it "can only contest once" $ \tracer -> do diff --git a/hydra-cluster/test/Test/EndToEndSpec.hs b/hydra-cluster/test/Test/EndToEndSpec.hs index ed71bf79b31..332cee77201 100644 --- a/hydra-cluster/test/Test/EndToEndSpec.hs +++ b/hydra-cluster/test/Test/EndToEndSpec.hs @@ -555,7 +555,7 @@ waitForLog delay nodeOutput failureMessage predicate = do ] <> logs -timedTx :: FilePath -> Tracer IO EndToEndLog -> RunningNode -> TxId -> IO () +timedTx :: FilePath -> Tracer IO EndToEndLog -> RunningNode -> [TxId] -> IO () timedTx tmpDir tracer node@RunningNode{networkId, nodeSocket} hydraScriptsTxId = do (aliceCardanoVk, _) <- keysFor Alice let contestationPeriod = UnsafeContestationPeriod 2 @@ -619,7 +619,7 @@ timedTx tmpDir tracer node@RunningNode{networkId, nodeSocket} hydraScriptsTxId = v ^? key "snapshot" . key "confirmed" confirmedTransactions ^.. values `shouldBe` [toJSON tx] -initAndClose :: FilePath -> Tracer IO EndToEndLog -> Int -> TxId -> RunningNode -> IO () +initAndClose :: FilePath -> Tracer IO EndToEndLog -> Int -> [TxId] -> RunningNode -> IO () initAndClose tmpDir tracer clusterIx hydraScriptsTxId node@RunningNode{nodeSocket} = do aliceKeys@(aliceCardanoVk, _) <- generate genKeyPair bobKeys@(bobCardanoVk, _) <- generate genKeyPair diff --git a/hydra-node/bench/tx-cost/Main.hs b/hydra-node/bench/tx-cost/Main.hs index d1cb91fd033..70ebbbf8e10 100644 --- a/hydra-node/bench/tx-cost/Main.hs +++ b/hydra-node/bench/tx-cost/Main.hs @@ -36,6 +36,7 @@ import TxCost ( computeContestCost, computeDecrementCost, computeFanOutCost, + computeIncrementCost, computeInitCost, ) @@ -93,6 +94,7 @@ writeTransactionCostMarkdown mseed hdl = do let initC = costOfInit seed let commitC = costOfCommit seed let collectComC = costOfCollectCom seed + let incrementC = costOfIncrement seed let decrementC = costOfDecrement seed let closeC = costOfClose seed let contestC = costOfContest seed @@ -108,6 +110,7 @@ writeTransactionCostMarkdown mseed hdl = do [ initC , commitC , collectComC + , incrementC , decrementC , closeC , contestC @@ -253,6 +256,32 @@ costOfCollectCom = markdownCollectComCost . genFromSeed computeCollectComCost ) stats +costOfIncrement :: Int -> Text +costOfIncrement = markdownIncrementCost . genFromSeed computeIncrementCost + where + markdownIncrementCost stats = + unlines $ + [ "## Cost of Increment Transaction" + , "" + , "| Parties | Tx size | % max Mem | % max CPU | Min fee ₳ |" + , "| :------ | ------: | --------: | --------: | --------: |" + ] + <> fmap + ( \(numParties, txSize, mem, cpu, Coin minFee) -> + "| " + <> show numParties + <> "| " + <> show txSize + <> " | " + <> show (mem `percentOf` maxMem) + <> " | " + <> show (cpu `percentOf` maxCpu) + <> " | " + <> show (realToFrac minFee / 1_000_000 :: Centi) + <> " |" + ) + stats + costOfDecrement :: Int -> Text costOfDecrement = markdownDecrementCost . genFromSeed computeDecrementCost where diff --git a/hydra-node/bench/tx-cost/TxCost.hs b/hydra-node/bench/tx-cost/TxCost.hs index 9847e5d7799..4999c9d0bf3 100644 --- a/hydra-node/bench/tx-cost/TxCost.hs +++ b/hydra-node/bench/tx-cost/TxCost.hs @@ -31,6 +31,7 @@ import Hydra.Chain.Direct.State ( genCommits', genDecrementTx, genHydraContextFor, + genIncrementTx, genInitTx, genStClosed, genStInitial, @@ -63,6 +64,7 @@ import Hydra.Tx.Snapshot (genConfirmedSnapshot) import PlutusLedgerApi.V3 (toBuiltinData) import PlutusTx.Builtins (lengthOfByteString, serialiseData) import Test.Hydra.Tx.Gen (genOutput, genUTxOAdaOnlyOfSize) +import Test.QuickCheck (oneof) computeInitCost :: Gen [(NumParties, TxSize, MemUnit, CpuUnit, Coin)] computeInitCost = do @@ -135,6 +137,21 @@ computeCollectComCost = let spendableUTxO = getKnownUTxO stInitialized pure (fold committedUTxOs, unsafeCollect cctx headId (ctxHeadParameters ctx) utxoToCollect spendableUTxO, getKnownUTxO stInitialized <> getKnownUTxO cctx) +computeIncrementCost :: Gen [(NumParties, TxSize, MemUnit, CpuUnit, Coin)] +computeIncrementCost = do + interesting <- catMaybes <$> mapM compute [1, 2, 3, 5, 10] + limit <- maybeToList . getFirst <$> foldMapM (fmap First . compute) [50, 49 .. 11] + pure $ interesting <> limit + where + compute numParties = do + (ctx, st, utxo', tx) <- genIncrementTx numParties + let utxo = getKnownUTxO st <> getKnownUTxO ctx <> utxo' + case checkSizeAndEvaluate tx utxo of + Just (txSize, memUnit, cpuUnit, minFee) -> + pure $ Just (NumParties numParties, txSize, memUnit, cpuUnit, minFee) + Nothing -> + pure Nothing + computeDecrementCost :: Gen [(NumParties, TxSize, MemUnit, CpuUnit, Coin)] computeDecrementCost = do interesting <- catMaybes <$> mapM compute [1, 2, 3, 5, 10] @@ -183,7 +200,7 @@ computeContestCost = do genContestTx numParties = do ctx <- genHydraContextFor numParties utxo <- arbitrary - (closedSnapshotNumber, _, _, stClosed@ClosedState{headId}) <- genStClosed ctx utxo mempty + (closedSnapshotNumber, _, _, _, stClosed@ClosedState{headId}) <- genStClosed ctx utxo mempty mempty cctx <- pickChainContext ctx snapshot <- genConfirmedSnapshot headId 0 (succ closedSnapshotNumber) utxo Nothing mempty (ctxHydraSigningKeys ctx) pointInTime <- genPointInTimeBefore (getContestationDeadline stClosed) @@ -239,11 +256,15 @@ computeFanOutCost = do pure Nothing -- Generate a fanout with a defined number of outputs. + -- TODO: why are we not re-using the same functions from the Direct.State module? genFanoutTx numParties numOutputs = do utxo <- genUTxOAdaOnlyOfSize numOutputs ctx <- genHydraContextFor numParties (_committed, stOpen@OpenState{headId, seedTxIn}) <- genStOpen ctx - snapshot <- genConfirmedSnapshot headId 0 1 utxo Nothing mempty [] -- We do not validate the signatures + utxoToCommit' <- oneof [arbitrary, pure Nothing] + utxoToDecommit' <- oneof [arbitrary, pure Nothing] + let (utxoToCommit, utxoToDecommit) = if isNothing utxoToCommit' then (mempty, utxoToDecommit') else (utxoToCommit', mempty) + snapshot <- genConfirmedSnapshot headId 0 1 utxo utxoToCommit utxoToDecommit [] -- We do not validate the signatures cctx <- pickChainContext ctx let cp = ctxContestationPeriod ctx (startSlot, closePoint) <- genValidityBoundsFromContestationPeriod cp @@ -251,7 +272,7 @@ computeFanOutCost = do stClosed = snd . fromJust $ observeClose stOpen closeTx deadlineSlotNo = slotNoFromUTCTime systemStart slotLength (getContestationDeadline stClosed) utxoToFanout = getKnownUTxO stClosed <> getKnownUTxO cctx - pure (utxo, unsafeFanout cctx utxoToFanout seedTxIn utxo mempty deadlineSlotNo, getKnownUTxO stClosed <> getKnownUTxO cctx) + pure (utxo, unsafeFanout cctx utxoToFanout seedTxIn utxo mempty mempty deadlineSlotNo, getKnownUTxO stClosed <> getKnownUTxO cctx) newtype NumParties = NumParties Int deriving newtype (Eq, Show, Ord, Num, Real, Enum, Integral) diff --git a/hydra-node/exe/hydra-node/Main.hs b/hydra-node/exe/hydra-node/Main.hs index d580d57c84d..088ec8802aa 100644 --- a/hydra-node/exe/hydra-node/Main.hs +++ b/hydra-node/exe/hydra-node/Main.hs @@ -33,8 +33,8 @@ main = do publish opts = do (_, sk) <- readKeyPair (publishSigningKey opts) let PublishOptions{publishNetworkId = networkId, publishNodeSocket} = opts - txId <- publishHydraScripts networkId publishNodeSocket sk - putStr (decodeUtf8 (serialiseToRawBytesHex txId)) + txIds <- publishHydraScripts networkId publishNodeSocket sk + mapM_ putBSLn (serialiseToRawBytesHex <$> txIds) identifyNode :: RunOptions -> RunOptions identifyNode opt@RunOptions{verbosity = Verbose "HydraNode", nodeId} = opt{verbosity = Verbose $ "HydraNode-" <> show nodeId} diff --git a/hydra-node/golden/ReasonablySized (TimedServerOutput (Tx ConwayEra)).json b/hydra-node/golden/ReasonablySized (TimedServerOutput (Tx ConwayEra)).json index 47d996134ec..844cc0d521a 100644 --- a/hydra-node/golden/ReasonablySized (TimedServerOutput (Tx ConwayEra)).json +++ b/hydra-node/golden/ReasonablySized (TimedServerOutput (Tx ConwayEra)).json @@ -1,297 +1,43 @@ { "samples": [ { - "headId": "01050702070300030204020108020602", - "seq": 6, - "tag": "HeadIsFinalized", - "timestamp": "1864-05-04T06:45:44.114377206009Z", - "utxo": { - "0404000707010503070505000504040605000400020706010502040300020608#37": { - "address": "addr1z8s256383ye0ms4tqmmfkf3xjr0fjwxhxf4ay3r2zle8rpkqnclh33cqpj0lkde08a2uhtz0j9tdx03qars8lyp0d0pq0pq9wk", - "datum": null, - "datumhash": "e78747f300d2e0a12646076fb67331a8908bf36b185004ff0506cc0d48924678", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820403", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "245d5a7a06fe18358242e81281cd5ba9e6abe4efc54e7b659f25abae": { - "34": 5429439866497292323 - } - } - }, - "0407050006060702000406000204020106040000080006080405050403070405#28": { - "address": "2RhQhCGqYPDo8LPTzND9nM4njewENtu2nZmGLfrxHRNK6kGAZjhGYZbB1QfyE5uMp7KF3YYzo8tV2M9qRG3aCAMuW8Q8ZtrnGzruh7jwKGCtck", - "datum": null, - "datumhash": "2ed1e5593967bbcd8941298b3f6612a287d9750b51f3304361ed81cc58f92f8a", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "4773434438b4f1b7c956f1dd2f6c3dfe99213655546cd67362062784": { - "1616fd0500cb3c784a50a353a5": 1 - } - } - }, - "0408050203060607020104070705010406080200080102080702040303070305#60": { - "address": "addr1zyqpkg38npf90dfmaaaw5mt0yjd35twey75fmh6qzh7ypc0a03s8e5d0kq2pm6yzexthkyyc4fl3kln26q4y455y6nws4ahc48", - "datum": null, - "inlineDatum": { - "list": [ - { - "int": 1 - }, - { - "constructor": 0, - "fields": [ - { - "list": [ - { - "int": 2 - }, - { - "bytes": "530801" - }, - { - "int": -1 - } - ] - }, - { - "list": [ - { - "bytes": "56" - }, - { - "bytes": "" - }, - { - "int": -1 - }, - { - "bytes": "0bce64c3" - } - ] - }, - { - "int": -4 - }, - { - "map": [ - { - "k": { - "int": 1 - }, - "v": { - "int": 4 - } - }, - { - "k": { - "int": 3 - }, - "v": { - "int": -4 - } - }, - { - "k": { - "bytes": "69" - }, - "v": { - "int": 2 - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "int": -1 - } - } - ] - }, - { - "int": 3 - } - ] - }, - { - "map": [ - { - "k": { - "list": [ - { - "bytes": "ff44" - }, - { - "bytes": "0af463" - } - ] - }, - "v": { - "bytes": "1b0c" - } - }, - { - "k": { - "bytes": "37ccea" - }, - "v": { - "list": [ - { - "bytes": "d0" - }, - { - "int": 0 - }, - { - "int": 3 - }, - { - "int": -4 - }, - { - "bytes": "" - } - ] - } - }, - { - "k": { - "list": [ - { - "int": -4 - }, - { - "int": 3 - }, - { - "int": -2 - }, - { - "int": 2 - }, - { - "bytes": "75abcc" - } - ] - }, - "v": { - "int": 2 - } - }, - { - "k": { - "int": -2 - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "constructor": 4, - "fields": [ - { - "bytes": "7d" - }, - { - "bytes": "925bed" - } - ] - }, - "v": { - "bytes": "bcb505" - } - } - ] - }, - { - "bytes": "42" - } - ] - }, - "inlineDatumRaw": "9f01d8799f9f024353080120ff9f41564020440bce64c3ff23a401040323416902402003ffa59f42ff44430af463ff421b0c4337ccea9f41d000032340ff9f230321024375abccff022140d87d9f417d43925bedff43bcb5054142ff", - "inlineDatumhash": "9bb528740028cf281d0fb073772f870996054c39fd4649fc784265ff9493cdaf", - "referenceScript": null, - "value": { - "5e0bdeaaf568aa4b92e70f4958e79595a83e9b1d823c5f7b5a969044": { - "548133b050": 1 - } - } - }, - "0408080105040408000100060206030606050403040805030405020602050805#95": { - "address": "addr1zxaac2nsqjy4zc9c2kcy75n8kzhu43tyyhz9yds8yhu3f4emn005x8mqpv4k7e2te26mp5a9ys5p9pxc2jk4zsvfzhlsuaddae", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "5d03b481d8778bdeb7af35036af885760a0dc53a1e4d847f9edee8ac": { - "18d63e9f87c1c17670708fcd1b9020992284e0496ff5e903": 2 - } - } - } - } + "headId": "04080000010800030400030307060307", + "recoveredTxId": "0601040604050502000203070201070704080301020103040208040304060801", + "recoveredUTxO": {}, + "seq": 2, + "tag": "CommitRecovered", + "timestamp": "1864-05-04T01:06:00.218316113061Z" }, { - "headId": "06040802010308050303000007000104", + "contestationDeadline": "1864-05-14T01:37:28.261173390645Z", + "headId": "02060402070600060201010405010006", "seq": 4, - "tag": "HeadIsFinalized", - "timestamp": "1864-05-06T17:44:58.181261589597Z", - "utxo": {} - }, - { - "peer": "vviots", - "seq": 6, - "tag": "PeerDisconnected", - "timestamp": "1864-05-07T01:53:11.612655982461Z" + "snapshotNumber": 0, + "tag": "HeadIsClosed", + "timestamp": "1864-05-08T11:48:32.36545692828Z" }, { - "headId": "06060702020005020506080602070301", + "postChainTx": { + "deadline": 6, + "headId": "06060207080004000804010403040304", + "recoverTxId": "0601080304010801020806000408080000040505060403000702000304080604", + "tag": "RecoverTx" + }, + "postTxError": { + "tag": "FailedToConstructCloseTx" + }, "seq": 5, - "tag": "ReadyToFanout", - "timestamp": "1864-05-05T22:47:23.684381037412Z" + "tag": "PostTxOnChainFailed", + "timestamp": "1864-05-04T13:04:39.677899836809Z" }, { - "decommitTxId": "0801050308040403010705050805040105010107020500050004060002030101", - "headId": "03070001050203080206010608000801", - "seq": 2, - "tag": "DecommitApproved", - "timestamp": "1864-05-04T00:25:59.562978794233Z", - "utxoToDecommit": { - "0206020101030001040800070706030308000602060103030702020201060706#52": { - "address": "addr1x97wvl563d4varzhg4aaak28dnl82xzrq25dd0adwm74kfqlgpsdqsw6ehlxhfp00yqnqsj3n8cff06fnttlp99gv9mqcyuxk4", - "datum": null, - "datumhash": "9d3982c0f8868f8057f1de2278df723783482c34b25d00432e401cefca400ba2", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8201828202828201818200581c13ade2fb1eaca6faca2bb6a5a5968a08046e36b3cd7e0f8a1061e9928201818200581c8ccd219c5c71d0d2594f1344f1696187c4b53431f16b6df4a76aaddc830301818202818200581ceae7080aebbb3fe4d112e02f59465dffc356c75383d90d62458a1609", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "3b489be33bddbb713386c5422a4ea2e39477a8e0eb97b950d58ab773": { - "36": 2081723522717440080 - }, - "lovelace": 4515485056013136714 - } - }, - "0207020303050102070105040107010202050402010406070402020306050302#40": { - "address": "addr1y8q0ye36kkm7edkl56x8gt895yece47q534hvdhwulk0upym7zmrnzjumyx55p37efj9mtw4punv9j2vn4cz5uz5salqsu8t4l", + "headId": "01070508050104070401030107000605", + "seq": 0, + "tag": "GetUTxOResponse", + "timestamp": "1864-05-15T04:14:02.391919054438Z", + "utxo": { + "0105060001000204060700060203030804070607080105080604020701070201#10": { + "address": "addr_test1zrxf6rz63pwdrszf6egz93tlmsgfz77gf0y4els33mc6rzzeu9mtfd9fk6w8chdr08av2vnfxglpqaex3vewck68h0pqteshac", "datum": null, "inlineDatum": { "constructor": 0, @@ -299,20364 +45,82 @@ }, "inlineDatumRaw": "d87980", "inlineDatumhash": "923918e403bf43c34b4ef6b48eb2ee04babed17320d8d1b9ff9ad086e86f44ec", - "referenceScript": { - "script": { - "cborHex": "820409", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "30": 6860992006032785113 - } - } - }, - "0702080503000507030701020206060207020205000105060201070204070002#96": { - "address": "addr1xyh6rrc2cycvszsgq30xa8yvcm43g2lazxsy0rk3htkte4nlrh26dvnhdj6cwvlhxpg3ht3056hf73kh2zuw27050xzq0afyf2", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, "referenceScript": null, "value": { - "4a1c412d8e2b3015a7fb7d382808fb7cb721bf93a56e8bb6661cdebe": { - "37": 2122941880035554583 - }, - "lovelace": 1179649397120676574 - } - }, - "0706020706010605040103020105050502060103020503070401020108030402#0": { - "address": "addr1x83hwj0y8mytds9rsxqu5zapxu24a5m4hu6uv39yk85qvht7wz53t3q5s9lqry7gfgnfhg9gws508fk7qwyvcz9gptkq45757l", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820406", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "c8b3875fd590bdfe5cc313000ed68f4d5658ee728002cb1b": 1 - }, - "lovelace": 8589083318735482875 - } - } - } - }, - { - "postChainTx": { - "decrementingSnapshot": { - "signatures": { - "multiSignature": [ - "2719ff4367ec409c74e1b31ab2899e3b8f45d038e626ab9b2af1313f543ebb3fce2baf6fb6303acb3b62be27ee57ea54ad32bc4135ce9aa1d80bad0767925808", - "9c3179e9221e1deaecb02c621f8ac25224ad7aa3243c8244733d6e6af11b86d2bed721308206b37f40ef1d8598c03c200f22c0cf42f3017ae67edfee623f8401", - "e3e3511b5f8aa255d6058e6ad8f15c060b4f6bb3132b2130945e145f387537363ec1914b36e0a8bd1eacdd0b48434c8d8afb84e77d10cd8778d17a450da62402", - "a5da8a51be62ff4da1f2b4eec419f61f5c4da56a6e3e37582a42a18db59d4defc985ab32f38883f7755fab56696ffe2bb406f891b74e51e50b99a18bff97a50f" - ] - }, - "snapshot": { - "confirmed": [], - "headId": "03030405000801000108080706040108", - "number": 5, - "utxo": {}, - "utxoToCommit": { - "0304050003000104070607010304040706040601060707020100050803030507#31": { - "address": "addr12yk7j9ec0x0ktv03ehfy7gv47wf3636m9xg877g49pdkyasrqqyqejpezu", - "datum": null, - "inlineDatum": { - "bytes": "" - }, - "inlineDatumRaw": "40", - "inlineDatumhash": "39df024ac52722fe8ae4c1a8740e4c5624a38c3820e504a059aae8728421f8bd", - "referenceScript": { - "script": { - "cborHex": "82040c", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "59ada749e56d0bfc2da86d5bf5dd58ab9e90d9ab664420baa3e850c4": { - "17720152ef561ed298d6cd59d8d64ec7675cc1e493d8dea79108c9": 1 - }, - "lovelace": 6114841801654155259 - } - } - }, - "utxoToDecommit": null, - "version": 0 - }, - "tag": "ConfirmedSnapshot" - }, - "headId": "01000008000501080405010605070001", - "headParameters": { - "contestationPeriod": 2592000, - "parties": [] - }, - "tag": "DecrementTx" - }, - "postTxError": { - "knownUTxO": { - "0006060600000104000105050306010000000208000608070805060408080703#58": { - "address": "addr_test1yr49g0qvfh3fhe0vh8g2epldl4rnmmyh2qk0lydh880dd44z5758k0f0l6em4lm7vcfnyk3q58ynezcyyys4q3srjlcqwxacjn", - "datum": null, - "datumhash": "1142af4b569cf77dbc276497791a40efe03575c89f51643b99161933ca4f5738", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "82040c", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2e12c5e499e0521b13837391beed1248a2e36117370662ee75918b56": { - "f955044a98cae2": 2762788586977142422 - }, - "lovelace": 3643233644210263802 - } - }, - "0307030706030600030807010401060502040605010800010704010505060803#27": { - "address": "EqGAuA8vHnNvjN3CQVouz5um2f4p3ijjuDXGBhWBsz7ey7j9NoL5iFpx3k1HU9osnPUvZtBGPtdM6MNEMZkePMYb7e7FbczAmCzxnNnGh2haKhEWs7HLr3b", - "datum": null, - "inlineDatum": { - "constructor": 1, - "fields": [ - { - "bytes": "e0345007" - }, - { - "int": 4 - }, - { - "int": 1 - }, - { - "map": [ - { - "k": { - "bytes": "7814be" - }, - "v": { - "int": -2 - } - }, - { - "k": { - "int": 1 - }, - "v": { - "map": [] - } - }, - { - "k": { - "constructor": 5, - "fields": [ - { - "int": 0 - } - ] - }, - "v": { - "constructor": 1, - "fields": [] - } - } - ] - } - ] - }, - "inlineDatumRaw": "d87a9f44e03450070401a3437814be2101a0d87e9f00ffd87a80ff", - "inlineDatumhash": "3965066ee4dd40eb0f07e8a17583598c6f73bbc4437ad5712ee084f0a3936965", - "referenceScript": null, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "33": 1892547002230750494 - } - } - } - }, - "tag": "CannotFindOwnInitial" - }, - "seq": 1, - "tag": "PostTxOnChainFailed", - "timestamp": "1864-05-11T04:18:06.920727221739Z" - }, - { - "headStatus": "Closed", - "hydraNodeVersion": "-⪾\\\u001b", - "me": { - "vkey": "125b30bb68aa8021364c13867763cc8dfdd6fe5be66b8a792c667dab7985c21c" - }, - "seq": 6, - "snapshotUtxo": { - "0300050300040604020205070400050107020801030504050708040608020704#21": { - "address": "addr_test1qperr57jwr2aveqjq8k3wkndmtkkwgk79m264cks6z4e494ydnw2kjvdduxshultg67a50vujsrtuha6qu4lu458ae2sg88cyn", - "datum": null, - "inlineDatum": { - "bytes": "" - }, - "inlineDatumRaw": "40", - "inlineDatumhash": "39df024ac52722fe8ae4c1a8740e4c5624a38c3820e504a059aae8728421f8bd", - "referenceScript": { - "script": { - "cborHex": "820504", - "description": "", - "type": "SimpleScript" + "2db8410d969b6ad6b6969703c77ebf6c44061aa51c5d6ceba46557e2": { + "31": 3393696446537166585 }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "3494cb376f734ebcb3c870a607e22174c24a1b8755b578b36eb532ce": { - "4b2859513f222e90f1186e537631d451fe0a77c2": 7425510301530031755 - } + "lovelace": 1914227408225432083 } }, - "0800020403030602000202020006050507050300050807070404030106080708#39": { - "address": "addr_test1vzvxh54yh53zkfgtxqn9nxuk5298yuucu3f63ygqsa7tphc06adk3", + "0204060304030001010500060106030808060506070302080305070705000806#45": { + "address": "2RhQhCGqYPDnp4UP8NGFyFtag8ZAhL2Lo7KU8BGgcjuV39wBqF3R8cyjsUEZ19v8KLxb8KwXaViotXpUWzQZkpfCoouu5KvP9hTohTC8wZ5Wvi", "datum": null, "datumhash": null, "inlineDatum": null, "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581cd71f99209650139cadeacefe642a58e6f89caecff9a9f3ff231ecc1d", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2e12c5e499e0521b13837391beed1248a2e36117370662ee75918b56": { - "ac2ddeb2f8d81819e3c6bc23737b4a4849aa6960d5f760b862d8bf1d": 1 - }, - "lovelace": 5185225112688758684 - } - }, - "0808070506050700080002020508050000030601010107060005050707010705#0": { - "address": "addr_test1zrchmx9ml46tsl44rdp4e43c4ua9mcgyj39nesrucr27usmjng523evfa7qjrcct9fu78sdcyrrt4r6f46653fegg4xqvvkuma", - "datum": null, - "datumhash": "500dccff3f196e31cdcd2fa45743dc4ac22f2e96d8edd2be34917707fff79063", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "4746010000222601", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, + "referenceScript": null, "value": { - "f157e46ea3cf6c19c6ca423423caad7562224a093e2e5d9e66d9e42c": { - "31": 1 + "b12121d92b4ae7916d04102fa1cd2f6dd6a6c6d0ef77bb356bdadc65": { + "36": 4313057009922026869 } } } - }, - "tag": "Greetings", - "timestamp": "1864-05-10T13:56:23.135404706619Z" - }, - { - "peer": "dhjr", - "seq": 4, - "tag": "PeerDisconnected", - "timestamp": "1864-05-09T16:16:09.815190614899Z" - }, - { - "headId": "01000702020408010701030101040602", - "seq": 4, - "tag": "ReadyToFanout", - "timestamp": "1864-05-11T02:57:24.267239787708Z" + } }, { - "headId": "06000706030104040306080402040007", - "seq": 6, - "tag": "GetUTxOResponse", - "timestamp": "1864-05-06T20:54:44.916798623919Z", + "headId": "07070605060002080708040700020304", + "seq": 5, + "tag": "HeadIsOpen", + "timestamp": "1864-05-05T12:47:59.060553158458Z", "utxo": { - "0103000604080004000508050507020105070504080008070103050001030303#0": { - "address": "2RhQhCGqYPDpo2Hj5r5qAF22TTnpgBXQfGfXU6rD5EWKxm9GGFYd9xGzVvcuaGy8Rf2SYTqczFzDhGRfHP8eJYyrZRZU8Qak3KtcZqbTHKA4cy", + "0401010103010201030705080006060207030406050004040006080006030305#5": { + "address": "addr_test1xrzp2vujm8jefkxh68yhppmtrecepyk844gdahv96fte4a9sthkzd4vjc42r0myhywplvnzvg0el7t34l78q2g6wsf5scx9duu", "datum": null, "inlineDatum": { "list": [ { - "map": [ - { - "k": { - "bytes": "480a4975" - }, - "v": { - "bytes": "98bc" - } - } - ] - }, - { - "constructor": 0, + "constructor": 1, "fields": [ { - "map": [ - { - "k": { - "int": 3 - }, - "v": { - "bytes": "1a" - } - }, - { - "k": { - "int": 5 - }, - "v": { - "int": 0 - } - }, - { - "k": { - "bytes": "4e" - }, - "v": { - "bytes": "351f" - } - } - ] + "int": 0 }, { - "list": [ - { - "bytes": "098f5c" - }, - { - "bytes": "da7fd0" - }, - { - "int": -1 - } - ] + "int": 4 } ] + }, + { + "int": -5 + }, + { + "constructor": 5, + "fields": [] + }, + { + "int": -4 } ] }, - "inlineDatumRaw": "9fa144480a49754298bcd8799fa303411a0500414e42351f9f43098f5c43da7fd020ffffff", - "inlineDatumhash": "b08e7351b175e2d53c2130b54bc8a4aaa0cd1b607ce8d8c114473531c7b6be38", + "inlineDatumRaw": "9fd87a9f0004ff24d87e8023ff", + "inlineDatumhash": "175e1cf693a4f07b970716cd6fe5a252c52cf59ad96f9f93b9dd115bbaba4682", "referenceScript": { "script": { - "cborHex": "820182830300808201848200581cecacf8e4d9603af4dd2e8b9bd396c0b54ef7acae0aad066cbe4c7c658200581c8a6386002a218ec18d0cae7a7877c87c7bc1a03684fb3f3a2259a5e18202828200581ca2bae151d3eadbd89f0b91b4b62e46a408af5bece731bb49b9bd12eb8200581cd572f79ab7fd106e57acf18522ca26f752434d9d8819770e1a21d801830303838200581c45f08fab23e898a6f6c622b26319ad442edf01ab7ab716113f66842e8200581cd44897e885048d49c1a03dff56230e52ab0e30a52903453662e6e5f28200581c74b2f74228d9ef91f20cd1706d28f72da0c896c3182ae5ea3f17924e", + "cborHex": "82040a", "description": "", "type": "SimpleScript" }, "scriptLanguage": "SimpleScriptLanguage" }, "value": { - "446b65c049cb810613baa96d87063e0517f4d466a862da004b7deec3": { - "37": 2 - } - } - }, - "0503060404030606020702020502000102040805020108050504080408040308#92": { - "address": "addr_test1gregl4vs92dcylvaaqhykfl8yqkhy3kyza93ceerh379faq8qqpscf9mjq", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "d06314bd94e6a77666700e625744a3b43d315809c7c8581c04a91093": { - "33aab8c5179c26d8b4b1ef34c9be3ed1181569c6a5c7": 3783316070124844877 - } + "105a8f1bb56444cacc86378c95421aceeb326b0fb7743e493eb82fd5": { + "35": 1 + }, + "lovelace": 4498487118473707162 } } } - }, - { - "contestationDeadline": "1864-05-08T00:49:40.265767586423Z", - "headId": "00000202040408070306060104030703", - "seq": 6, - "snapshotNumber": 3, - "tag": "HeadIsContested", - "timestamp": "1864-05-11T16:42:38.650220530034Z" - }, - { - "headId": "03070101020103000404070804020605", - "seq": 3, - "tag": "TxInvalid", - "timestamp": "1864-05-08T16:34:51.62875195789Z", - "transaction": { - "cborHex": "84ad00d90102838258207ae3cd24228d76fa9dd3713f7fc08e84568d12161afe1d3e872b760f98335dae0082582093ac648d71910ea4e3da4d5fb21f7449118b6f14f669cfcaf65415b78e129e7800825820cccd04fd2ecf4659f8c2a959d2861ad097b052893b6610501182d690f1fba4e8000dd90102838258206e8cc3997c17fdf92002407e73360e17eb63d6ec8fba7500209a13f536eba3d108825820f040f02d4d26322891a7b8b5a6f47c822e22729e62413a0aab6aa95e5ac18a0c08825820ffad0f56fc2927aa91d5e7b67e9741fa2580b3d9a1bc49abfc9bb8537a8648330512d901028582582020b49c6a0a252ce593023beceeb17060d63760568cfa6b1849b1257f30f8f42103825820691feb841d753f3cefc302a85585324cbd1ae75a7403398b516f403ae43c8025088258209b0bff1a19f8ff9f424ec599dbfa6ace337810dbbfe22828501298f43a50d46004825820a44b7e66b596bb4402980b7952ca0c8bfd6395c33efc24459c47cf59312684e100825820b6f9418d95aae6cba95c521a3c95ce69a9a443071597a6211bc6524e95ae7f00020183a4005839109520df7869687e341627799ef870338748c4af8b2701262e46b16a2ed7c10b690e6d1ef7c845fc5c127ad5010d85d67b41bf5154cc92a81301821b26509becf608e3f6a1581c6b0746ad6b3eab6ad4cc155f641869f65380af833944cca7be05bb25a14bf954276cb07d16fabe263b1b2a63de709c7fed4e02820058204e85be298e4fcc399ad24dc09ad50f0b05c41ca0088055eb967b472d66767c4703d8184a82024746010000222601a300583911ea7bf71e26f17a5fffad8e706b324c024bc9303c41e3b6c0ee4babb654aeed2ea4d2bb232cc3330898bd0e74f950e5efc4d96ba05796f2f9018200a1581c105a8f1bb56444cacc86378c95421aceeb326b0fb7743e493eb82fd5a1581f331b71b41bed543615110901251edc809cb4ac7e05ccd0f4e13326f448daef1b586d645460ad1df6028201d81858b7a5a080440b11af53a3009f40ffa344fa07791b41c0050340029f422ea2ff9f40ff42198e9fd87a8080a12304a243a7389f41b12421d87c9f41e7410741c9ffffa14001a3d87b9f03ffa3052344ed902fe1052141409f414205ff9f40ffa341754368452042cfd34283fd0540a424448ec78d49434b5ec44281b50341484021d87d9fd87c9f402040413bffd87d9f4174ff425c0eff9fd8799f0303ff40ffd87e9fd87c9f2300ffa04480b35d299f41b00303ff9f40ffffa4005839113e5453f89ba588d19adf5b2cbe73015c34ba3191923f69bd7f167dc66521cb46df8d1bcf579d55f56d4c6d3bc1ed083a45eb6d86dced30b501821b3a4d2cb5d9d959bda1581c4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888da14512ee14a3100102820058206773ebe157953ecfdabcf0ff13adb79417cc14afeccc519ddd8dab552cc2fc7003d818458200820405021a000844cf05a5581de06bfcd16dbbdd694dc5e64df0c71e8e2b10df2caba3f77be0c0f756391a000f2e9b581df1ca7c8b62314e555ae46c2e24ad08b03debbf4b13d1ca5c32b5c932ec1a000d0d22581de107e049b715a5857c6a113eff7e5ecb419fa6491776c6eab082c7c4b11a00010f01581de12531b20bf41e8b278924d5195a75603c00277ca4c3558f53dd734ed61a000a1279581de1c537a80e57a5b2d9d896161f55230d21e451846b4f4a352a1cadd7df1a0005e9e90ed9010284581c04ee69dc889c70b89e892ecc7bb8822239692dc158afd78c43eec313581ccd87d3707c800cdfbe4dd0bc8ca2e74b0755e048ff95864ceae8436b581cde45e19eab6c1aacb0b7a85497ee81131fca01d9758e7712efd154f7581ce54a8d2182a535f6b0b5a0befa4b0e74f940c29f97a01210535ff1dc09a1581c48ef663f2024413d731e70e2733b72dd4f588d8dd54306bfe1a0843aa157c23e6d0c36b9f12bef7bd2e9fb47af4a690e2d01a56c5f3b0fd19097a9de75f80b582082597b05f9d99b7b5c5272d45fff92c65227e1f58964265efe02f2688750a6a4075820674d7c62c36096cf4fff57aa0261e9fa144b47c14cb6c80819250ff239daf70b14d9010281841a000987f5581de0b79f1858dde9259061ce2a40831df0dd73885700052672abffe9f3c38203f682783a68747470733a2f2f33346a31525a6862726d7043546a5a763757756b38737531504b43394f7439565a4f5a48364c794b75534e7179782e636f6d58209598ca04edc2192679535f04b6cb6a9d2b05ea7f4ed32dd0ad5317435dc7240e151a000bf864161a0009c46ea402d901028384582079406c8b66fe12bb026a3e4bb8f13e173076cb81fcb86296009d897d77b0ed35584072e065f8f7c0cef524b091e7924511044c7b041cc0cdcf6d10b5008f2effedfca451be350b6801e838f7480369bd14061bb13eea6cc423d218468ff9065c583045e2b90ab9f343b2f5e5845820e237e22527abf7ee47ffb0506687c00e45fff4074a99a5beae4a4e047d27f79858401a2777408777c8e06853834faf2fa1a325a0455a3e186ac0e988decbd502148588365876cc3881c95d5e4cddcd9e00e2fc9a6d34ac456974d470fa7f3659f20942116e429f8f845820fdc764f262996098a09581193f6916e15f0d07bc030b71b28c3b92078b71e8535840d4c378aa54e12484a6c669588b7f67d74ee7ba16f1da0d945a0f8045180d582afabfd1e8bc8a9a31275a8bacb61e484c920df200027fea449ed6a0addf294ffb4042529e01d90102848201848201818200581c0c89531e405c9695ad80f696cba7cb4abb422c40b3fe2b20ded9d9558200581c859f2da891d54dbe1fa9be163948b6c62d422bc6dd60143b44347e3e8201828202848200581cf02c1f43878caf90d92eba6c7629611b97097ef079ae11f9dfcd227a8200581c46b8eae20a7240df4e4f7b4779a7af2e1ddee355c7863e08c495bd728200581ce55d7e47848eb5ebfe08fbbc79ee79ceb59ceb67994b73da4a8a05108200581c6848ca2f7ef0fbc5d278cd89120ad712c80504da55026a2831f9a94d8202848200581cd06ca2540684d3c424883b143f7e8fb098c09151afcec1281b6cf1ad8200581cafa9b86bf24fddaf80f1937c9884156001a35f28287c5bd30571256d8200581c78c93630e53b9bbf5821c87744042c30125fb2e4a10bb6c0b67d1f248200581c14a7fd158fb7b7eb57fc19d08ae7a0bc8da53d1e9f3b6b04ca8134f08201828201848200581c6366d6a2258858b84f26a0838c3591db2b33d68d7faf83ff35ef704f8200581c8462ff328abffe15d4d72f246b19927eb3c54413034c3ce57bc418bc8200581c97ab59f8eca1b869d72c161ec34b56d1f911071db515fbb8f9f022018200581c8408645a9dfcbf04d331e7370de056ee90119313b2fed6d19496fe4b8200581cd72baf6bbe13e487941ecc47ff77398f1fc1a471d88ad50c7b7b1a6e82040c820183820283830300808201848200581cb98a00dcdc030da2556cf2a2983f32d09609770708bdcb2d6362331f8200581c591bd5f1fb0e22aa65d1114e962b15430aa5d58b967c0426a8f122968200581c1fbb2e3d809a0ca1e0dc05c96287df0ac20c0a7a1fa80dd9217499008200581c319e4a1c1a3a8cd2733abb0fa3ff26ce27227857a2ada288f9a30f598201808201828200581c0b7c7279a9dcce112e34a949b2a28c921760e51be6a9f5568f3d34ee830300848200581cbc56927400444eff4d9039eb316b6eb9b36e01ea0174fb3404ed361a8200581c185dd4f0e6cb9cadba2271a70c934c4b7c1a89da2ee6dc1a3f301ba98200581cba71a2de89e475647d5ce2b038f874e4fdbf6ac7b2a2b5ade87705eb8200581c2c5a017feaaf7af23b3834f8bffd5d895a028c14a175339a37b66ed58200581cc7b610c34fc0d89b188770a3de73c54866b11dccbb7607a87b62655b83030484820180830302828200581ca1d5de2f6e7b53887bde995313e1dc3c6c7c9700eee2d3f29d5014138201808200581c760eb6161ba0de0ff0e7c8088645de3d2d2c13201664947f0daa9d978200581ccb714fdb1b971c10327b7b8472ac1f004cc157cfaf1e0abe4daffde604d9010285d87d9fa14480fe5e36415444011d1a37d87c9fd87e9f41aa41e32243508ec8ffd87d9f0043f4ba8f0242208cffd87c9f44272ab020024338cbe60402ffff9fd87e9f2424014022ffa444f11fac1a05440b252df6224304208d05204042ecb2a222437eb4a741fd43fdefc7ff24ff9fa1249f242340441ad42a974351084cff9f9f425b6040422e8dff437df2b1d87c80ffd87c8043a75885ff9fd87e9fd87d9f00ff410ea20044e231097e4022ffa2d87b9f2405ff4226532000ff9f9fa22244490df95424029f0305412342cc33ffff9fd87c9f00429c274219eb404106ffd87e9f44c203ad4e004268730124ff9f0242bec5ff9f05ffd8799f42b6c103ffffa0a320a30323214249c2423eff4202fa41f7421693a0434985e5a0ffa521445a2c8de9a4a140420bcc22a203022320d87a9f404349c9f903419104ff04a12105d87e9f4183412d40ffa0410fa480a322000502224207f043ac0d59a09f40ff23a3020443e564cc4459b9b2c722432d5e00410fa0232140413805a18203008224821b2d43c314d5f2518d1b5404ff3e641dee86f4f6", - "description": "Ledger Cddl Format", - "txId": "84b1580e84483abf7e5f0da29549063e26dfae495a8ae9fa030992e63864bf9c", - "type": "Tx ConwayEra" - }, - "utxo": { - "0504040708020203080804050704020108050006070208010308010603070007#2": { - "address": "addr1w9zgek5hppuxf93el5le597e5mug5ja6vyrd20c00tw9xgq8qhwcq", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "82040e", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4e15913b76621930f86dd51996b512f8eab3f027515030dac4c16be2": { - "30": 8935451903783907689 - } - } - }, - "0806010106080601060700030601050308050307030402000703010803070503#49": { - "address": "addr1qxnhhrapg2zlym7pec7q3kjp35x6mmtu0ffw70tjlld5fxpx8s2l4zmv56z0gpk0yvte97yyddlqphafja4ks3tzdwaq5ytw2l", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820406", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "a08b72451d962be7a965b25550c576ef4e210f51380e82f0153f4c45": { - "bbe49b84893cfbc9cf682e5e1a72d16132cb4722d25678822a3808f4a473": 3569958842521019477 - }, - "lovelace": 1307982488243141104 - } - } - }, - "validationError": { - "reason": "\u001a`\u0006" - } - }, - { - "headId": "06060007020505030707060200060105", - "recoveredTxId": "0803070800080203040407020205070500020204020802010806050207070103", - "recoveredUTxO": { - "0805070502070501000207030606020607080504040600080104070502040506#35": { - "address": "addr_test1zpk5n6rluyvpsuwvphgnl5txhpxc23dh9rd5pes23gkaecq722q7qet778zw992fvc8fwsncs0qt0m4dre698c5hdgfqqtgsfz", - "datum": null, - "datumhash": "7c0e2a2e14615666d2cc3eedf9e7ee3ecf7ebc6ac3a14d03fe10230c6a697ee2", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581c2f0188cc4721b97d3abfff2a4b139a4ca6aa7b6e74b9faaf82450b2f", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "f2ead320df54aa5402afa0666fb05c7f24130c0abd9b2ed961bb7841": { - "32": 7685965026430363493 - }, - "lovelace": 4446748717326546305 - } - } - }, - "seq": 4, - "tag": "CommitRecovered", - "timestamp": "1864-05-13T21:56:55.493354366975Z" - }, - { - "headId": "07060303030100040100020602000401", - "recoveredTxId": "0503000606030205000008020506020803000608040003080401010300030104", - "recoveredUTxO": { - "0006040106010304060608000005000204070604030806070408020102080601#46": { - "address": "EqGAuA8vHnNto9uJnS2meZi5AVgC1Jjk4EtQ52DUyXMxi47ZLhBsxh5Yz82s3uxa6w4soSxykzC4Mh4csZQStc49mXZ2S27c9TkEJoF8JFvwJ6y1A6e7FXJ", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "4746010000220011", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "58aa2260": 1 - } - } - }, - "0105040600010302050105080604010207040403000607010202050506060107#85": { - "address": "addr_test1zp7p5lkzf6k9mfm7g0ke2fq2pl47anpvsjwuslu6s9pke06y96jtd5ggfxvtlkts4637u6x45yywse2rurnaj6mwdnkqe396xz", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "83030183830301848202838200581cbaea725247f636835ed00f2c5ea776c207c04a7e0b7f03087ca787a68200581c5967948fa08dfae11c61eb8b19296d2c22c2259b2e2027733b3ee2da8200581c1b3874def96157b66d074e7f61c8e649041703e26565bc69b4cc269e8201818200581cafb09ec9ed5d4920d814e5c335f603d0024f8f6d5baae78751f9288d8202848200581c0e8e1a9ac23d225e28e02474e49ffd251b245cf4ca61d00823f5ae3a8200581cb57eb2b1c706133deadaeb8c29681f871676ae04825f9a5dbe7a85208200581c4cae6e26c3464fbef38f8aa57e082e915edb5db32bf40838d90742548200581c386e2e9e97719ef1d7c9f75ce0e057d9efb145ca0ed0a8b1e3c0ee8d8201848200581c48f5c1402825ecd9dd262c08692550771ee63daf36191beab6ae17ec8200581c7fed0ed67541c76e88a7855a1e965105b4064fb5caa2fcd261202b628200581cd5595e3dcc7d5fc50ad4d30ade8a22e2f47d1a904ebd7dbdf16cd19a8200581c0d79a5132624342932a6dc2e032b18d1103804f2ae739024cbde0d8b830303838200581c20350383463a81519a80dd0690f567dcdb18485445a402d483e05f81830304848200581cdf62ba4898c97fca924e1648e185abd26045bbdec647150824a817218200581c3062a41a6194aa9512bc7b02b8f771d25f962ec089108e0d850de2958200581c32c7c0d919e88014fbc16dadec1579b14be194c9cb24a8c8ae622dc58200581c621e287d78366544d5a617823216e2262ec9dc07c40c35ceff85be298200581c61efa71408dc2e0c51ca4d486d320db29b0da75b011e800ce0aa4122820181830301818200581c8f9d036b41b771a5c2677720d8fb19d6eda4a17db4609882fced08fb", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "fd38e1785c69d0c4fe94d003d464933a5b2ee460c10fd7a138f959": 1 - }, - "lovelace": 9041165003753707029 - } - }, - "0108020100000305020104040702080105010403070605030703000404010401#75": { - "address": "addr_test1qzmh2qsesc2me9q9mplmxlzhxr23ax7gtrpwry34vu7nv99vf6psunqxhqvz7h4sgmrztvagd8p0lu8mg6dmwa5mgq8s3mrrqk", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV1" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV1" - }, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "f39c6397d626": 8421988368556850959 - } - } - }, - "0303050100000303020104060507060307060600080701040202040207030800#94": { - "address": "EqGAuA8vHnPANWM7qkBQqrraF5gan6fdTx6KqN85wbQwKysjJah7bP8ragCdVtjej9HbwyrimVYxEsG6pox6bB8EA7xjNVpjompUPB73EUB5UEDkHisV4Vw", - "datum": null, - "inlineDatum": { - "bytes": "cec32267" - }, - "inlineDatumRaw": "44cec32267", - "inlineDatumhash": "4c22cf2d4804d0bdc2221c283a172a2f5f33fafe8172b6473cf77aef0623f1d9", - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV1" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV1" - }, - "value": { - "a7fcd7d7f0a2ad1768f18a30981316a20296c719264e646a6e55c6c8": { - "5f629b9dded73a041d799a9f04f9799e4ee6cc52c7fc29e1c6fe9e": 1 - }, - "lovelace": 6305657787455491283 - } - }, - "0702030302080408030605020101010702060802020806020201080707060408#43": { - "address": "addr_test1qqnm9ncxjjzy4vly3mhyk08yu0cu6049syeyprrfeuxrk4wgf0ch0s63ga77gz5q3ghsujsnlhjzddy88pkd7hwkfk9sw6y3nj", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022200101", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "32": 1 - } - } - }, - "0800060006010404020705020104060602040101010106070403050305040102#76": { - "address": "addr_test1yqhqc4c3vn2fkqpryyc2nkn5zupnqhpxdx47nwnfkqjdk4tax6z8ss0d009chhdvy3rrq3fv37tyg46dmvzmdp039mus70gluq", - "datum": null, - "datumhash": "b62f94bf0a845290ee7ce3261b6dcb5669ff3011756c306aa62ee2734de38858", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820502", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "bfda9f9ee0b9a7f73be9323dfc87591649ddb1291e44872fbe2f4608": { - "99a46ada31c7309616d3e41fee60e45f637e90682fb633bd": 2 - } - } - } - }, - "seq": 3, - "tag": "CommitRecovered", - "timestamp": "1864-05-05T00:58:26.02661008611Z" - }, - { - "decommitTxId": "0404060500020401040303050007020005040007050104020702060805030407", - "headId": "08000802040703040308050606030007", - "seq": 0, - "tag": "DecommitFinalized", - "timestamp": "1864-05-13T04:12:11.813492116323Z" - }, - { - "headId": "04070803010804050700080405000401", - "parties": [ - { - "vkey": "45af27a55f10e9ca438660ee214f77d43d4ba568c8c414dbdc71b5afe8c27aaa" - }, - { - "vkey": "b73b162c9c1db538acf6722e140d8c5d5afa84f0e33fae9f3581a9094af0e4e9" - }, - { - "vkey": "83af888b87115973ef5b2081022d2a52762f0821630d5d339fc21bf318e6762f" - } - ], - "seq": 6, - "tag": "HeadIsInitializing", - "timestamp": "1864-05-07T10:28:19.805630776703Z" - }, - { - "headId": "00050108070400020802050504060108", - "recoveredTxId": "0102080401000804040606040804010305070503000200020605010602060303", - "recoveredUTxO": { - "0205050203070307050003080707010806020200060804060504060507070605#3": { - "address": "addr1y8r9060daeulmx2rfp4acfkef8athqtaqmmwthhrvs039j0k57glx4shcwerxtvkj60q9xsv37sgu0xf5weedah33mtqndg25a", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820508", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "b0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165": { - "36": 5733611821668158835 - }, - "lovelace": 6579716960126266223 - } - }, - "0703060007050804000806080808020304040404020507080202000405000407#36": { - "address": "addr1xxrvkvfarsd7wpjrexhsm9vvxwc3panwu42p9220qtd95afvnwjduala95n8hlp5dj66dxmtd66gz3z3c5dsak8zf8ssnupaqe", - "datum": null, - "inlineDatum": { - "int": 4 - }, - "inlineDatumRaw": "04", - "inlineDatumhash": "642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342", - "referenceScript": null, - "value": { - "0160fc24b86164b41cfca09ca117986dbd28f4cab6302b239944e7f3": { - "33": 1 - }, - "lovelace": 7134269397057143595 - } - }, - "0704030604020203040304010401080205030402080501070100060301010602#20": { - "address": "addr_test1qpfvnw08vn4e0n9aztvt296236hhut8yeqpq9xvgl4jv9fs0p633rsegg07s48w9d4fx6z550fyezhdzp8k078sumldsf8p40g", - "datum": null, - "inlineDatum": { - "bytes": "99b6" - }, - "inlineDatumRaw": "4299b6", - "inlineDatumhash": "64871477ad32cd1c0d6d27770bee96df1afe51c146cacb600f56dd0745f3e1ea", - "referenceScript": null, - "value": { - "b0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165": { - "605d2e824ebc55ff4843f4c4d4f8c719ef": 2 - } - } - } - }, - "seq": 4, - "tag": "CommitRecovered", - "timestamp": "1864-05-13T04:42:15.788781417446Z" - }, - { - "postChainTx": { - "headSeed": "06030204070400010707010503040800", - "tag": "AbortTx", - "utxo": { - "0005080603080006000201030401010008080406040507080508040507060201#7": { - "address": "addr1yytgp63zz69xakmruqw3n0fqeeersmd93tsf5958l0d8take6razxq6qy3fcq758t0wtdpu2vpu743trcu49a6hlyn3qz65gn0", - "datum": null, - "inlineDatum": { - "int": 3 - }, - "inlineDatumRaw": "03", - "inlineDatumhash": "e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec", - "referenceScript": { - "script": { - "cborHex": "820281820283830301838200581cbb4bc1d5046741fab16fbe8e51ab5ccb1e5ae7fb3a4955f2fdb579f78200581c756de40404e24fac345bdd53b178a378f88b978583dedd24730018ef8200581c7d8a039b4c362cd279c94d2f46b85052b2123bffdb25d356a798ac298201848200581c04a103d5f56274beb685eebb94b739249447e5b124e4bcf0cd3edd5a8200581cb86578871c3f37bfc0f8da526a694f66b2d1cf79950001def3b4b4e78200581c6eb5bd9fc7d347e06df511e2154bb7e9ad0723872013f5ed946eef8f8200581cc68195dfcac35e2a77c4b6fafd13b2e9253868331b478ec0d6eda99b8200581cb8392437cf9955e76f188f5cf2a3488bbdb435e12e28499058e7be13", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "4f4de2f23cb24afc7e4b2447c758478f807cd5": 3715514641564930355 - }, - "lovelace": 5382239702958704255 - } - }, - "0304080306010001030003050602050808040704060107020604060702010708#36": { - "address": "addr_test1qpqsju27pqsltgue6awjyvzqfef2wnn8qwaklzdktlksj7qn4qsneh4az2axh9hys39u3wrn90gvjj2ca4tdqz0lmaeq4cs27a", - "datum": null, - "datumhash": "4e453e64a1b747de52d05996a9af1da99b22f322a77d4022097ab0d024f45e3b", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "71883d562a8f6aab671ff672c2b7b7b5212819fed7c7e1e6335f8a8c": { - "d54e3859e142f93069f92b387e5c3d036dd9": 6161418656104727630 - } - } - }, - "0400040503080703080101060204030203020802070705000200010702030107#89": { - "address": "addr1yxz6l5zlenert2xdkphcez8wj8w706lxev2e90l3du6dr2de44fh0cdxe5zzln3ga9m5hplxnm9mceayzlxj67t48wssc99sm2", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "5f619b363ec2c709f019f2829eca13e99b545bfe07590129620d94fe": { - "32": 1 - }, - "lovelace": 2996695894335130769 - } - }, - "0404020408050407030100010704010403010205050603020202070802070404#2": { - "address": "addr_test1yqkeadxlntn7pxxe85fhesdnzh007gf4qyzedgc8mc9jzaav3hu3aekfyysllskrayfg7h6mtjp73plavwsggpp959pqg6vl6y", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "map": [ - { - "k": { - "map": [ - { - "k": { - "int": -4 - }, - "v": { - "bytes": "60ad" - } - }, - { - "k": { - "int": 3 - }, - "v": { - "int": 1 - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "894b8d48" - } - } - ] - }, - "v": { - "list": [ - { - "bytes": "248c98ba" - }, - { - "int": 2 - }, - { - "int": -2 - } - ] - } - }, - { - "k": { - "map": [ - { - "k": { - "int": 2 - }, - "v": { - "int": 1 - } - } - ] - }, - "v": { - "bytes": "6ee3" - } - }, - { - "k": { - "constructor": 1, - "fields": [ - { - "int": -2 - }, - { - "bytes": "77b5" - }, - { - "int": 5 - }, - { - "int": 4 - }, - { - "int": 5 - } - ] - }, - "v": { - "list": [ - { - "int": -5 - }, - { - "int": 5 - }, - { - "bytes": "07527a5e" - } - ] - } - }, - { - "k": { - "constructor": 2, - "fields": [ - { - "bytes": "e8" - }, - { - "int": -4 - } - ] - }, - "v": { - "list": [] - } - }, - { - "k": { - "constructor": 4, - "fields": [] - }, - "v": { - "list": [ - { - "int": 3 - } - ] - } - } - ] - }, - "v": { - "constructor": 5, - "fields": [ - { - "map": [ - { - "k": { - "int": -4 - }, - "v": { - "int": 5 - } - }, - { - "k": { - "int": 2 - }, - "v": { - "int": -3 - } - } - ] - }, - { - "list": [ - { - "int": 4 - }, - { - "bytes": "71b88a" - }, - { - "int": -2 - } - ] - }, - { - "bytes": "ee1740" - }, - { - "constructor": 4, - "fields": [ - { - "bytes": "" - }, - { - "bytes": "bdca1904" - }, - { - "int": 0 - }, - { - "bytes": "48b079bc" - }, - { - "bytes": "2f" - } - ] - }, - { - "bytes": "b3" - } - ] - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "list": [ - { - "constructor": 2, - "fields": [ - { - "int": 4 - }, - { - "int": 2 - }, - { - "int": -5 - }, - { - "int": 2 - } - ] - }, - { - "constructor": 2, - "fields": [] - }, - { - "list": [] - } - ] - }, - "v": { - "list": [ - { - "list": [ - { - "bytes": "0e1a" - }, - { - "bytes": "01" - } - ] - }, - { - "map": [ - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "125b" - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "eb9a" - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "f316" - } - }, - { - "k": { - "int": 1 - }, - "v": { - "bytes": "0b6aa356" - } - }, - { - "k": { - "int": -3 - }, - "v": { - "bytes": "1e" - } - } - ] - } - ] - } - }, - { - "k": { - "constructor": 5, - "fields": [ - { - "list": [ - { - "bytes": "ee" - }, - { - "int": 1 - }, - { - "bytes": "6c" - } - ] - }, - { - "int": 0 - }, - { - "list": [ - { - "bytes": "62" - }, - { - "bytes": "c1d0" - }, - { - "int": 4 - }, - { - "bytes": "" - }, - { - "int": -5 - } - ] - }, - { - "constructor": 2, - "fields": [ - { - "int": 5 - }, - { - "int": -1 - }, - { - "int": -4 - }, - { - "bytes": "" - } - ] - }, - { - "list": [ - { - "bytes": "d136ee8e" - }, - { - "int": -1 - } - ] - } - ] - }, - "v": { - "list": [ - { - "map": [ - { - "k": { - "bytes": "4e" - }, - "v": { - "int": -5 - } - } - ] - } - ] - } - }, - { - "k": { - "constructor": 3, - "fields": [ - { - "constructor": 5, - "fields": [ - { - "bytes": "89" - }, - { - "bytes": "ad" - }, - { - "int": -4 - } - ] - }, - { - "bytes": "5c" - }, - { - "bytes": "1f9481" - }, - { - "map": [] - } - ] - }, - "v": { - "list": [ - { - "int": -1 - }, - { - "list": [] - }, - { - "int": -1 - }, - { - "map": [ - { - "k": { - "bytes": "0d6359" - }, - "v": { - "int": 4 - } - }, - { - "k": { - "int": 2 - }, - "v": { - "bytes": "d69dc1" - } - }, - { - "k": { - "int": -3 - }, - "v": { - "int": 2 - } - }, - { - "k": { - "int": -4 - }, - "v": { - "int": -1 - } - }, - { - "k": { - "int": 2 - }, - "v": { - "int": -5 - } - } - ] - }, - { - "constructor": 2, - "fields": [] - } - ] - } - } - ] - }, - "inlineDatumRaw": "a5a5a3234260ad03014044894b8d489f44248c98ba0221ffa10201426ee3d87a9f214277b5050405ff9f24054407527a5effd87b9f41e823ff80d87d809f03ffd87e9fa2230502229f044371b88a21ff43ee1740d87d9f4044bdca1904004448b079bc412fff41b3ff40409fd87b9f04022402ffd87b8080ff9f9f420e1a4101ffa54042125b4042eb9a4042f31601440b6aa35622411effd87e9f9f41ee01416cff009f416242c1d0044024ffd87b9f05202340ff9f44d136ee8e20ffff9fa1414e24ffd87c9fd87e9f418941ad23ff415c431f9481a0ff9f208020a5430d6359040243d69dc1220223200224d87b80ff", - "inlineDatumhash": "52c376a9486b75c340714371c3de27e422c1ed76ab87dc3fd030e4ffc13487f3", - "referenceScript": { - "script": { - "cborHex": "4746010000220011", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "30": 170946016048031959 - } - } - }, - "0604050207040004030205030406030504020100000805020507000602000507#12": { - "address": "addr_test1yqmkq6wv55cdxs3l2u4ymz90dxrdajhpxs3grzh3zepeweuhvcv9fdqtjtppmac90mlatr8k8dckkws7mgtr05cu0y3qckaqhz", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "830301828201808202848202828200581cc0b4c7a28ff7d42bf298f513b023f7d2cb1ddf3ed4692fafe6b7dc708200581cb77f65541a371f94e778cece904aa6a5d78be4a41a28f35e06e618498200581c399efebd5c4ee7977b44af77963847e6c621f25402b3c5cf15cb7a248201848200581c80dc9bb090d3f7ef7fd323ede6674e9feb37a173bb71781ce6fe02ac8200581ca4f6500427323e183f1b6ab505fd30b727a43f56a94326bf6c2425cd8200581cc38d459ab5881927124653c48a111383a1970451872058f501043f408200581c746e80e495f7c2ee9b02b177b3ae295686a0ef11eee01011887519268200581cad309be04b9b39117d7f27e6e59ca95786a711fe58fa0f512b6438f2", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "9cc0579a17f5b6b59b9228": 6932071830355949916 - }, - "lovelace": 1361732020795520547 - } - }, - "0607030607070307040304030505050500070503070102060506060802000703#66": { - "address": "addr1x8ff26crlcpnfqsp47n3wzf5rc895vdccf623jrhr8vzucxvgu32lnrvs624qr4mlkyhfxakmuu3ctk20xejn3nqa0fsqdndzn", - "datum": null, - "datumhash": "4581da81b8b5b76785d69e6eb4efb2a0d5edcdcf2392e8a1ecf4a025fed0b092", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581cadc333341453771305c59cf8fb34f6510002a2e856754d219d05d319", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "9126c9b8b3abbf27f3c3904e8461a1e7cfa74495ddcd3cdfb79834a1": { - "e2": 1 - } - } - } - } - }, - "postTxError": { - "tag": "FailedToConstructRecoverTx" - }, - "seq": 4, - "tag": "PostTxOnChainFailed", - "timestamp": "1864-05-13T20:09:05.432602536573Z" - }, - { - "headId": "03030800080200080107000606060707", - "seq": 5, - "tag": "GetUTxOResponse", - "timestamp": "1864-05-10T09:16:06.370203132864Z", - "utxo": { - "0208030803070107060408000700020207060605040600010607010200050702#58": { - "address": "addr_test1xztwpr7p25wrnff8majkfpzfz7nrqqnkgxguf33mzuzt62reaeyzwclfmqwnchp2ph74sv9nuh20rw3g4ayn0mdpktjs3pzk07", - "datum": null, - "datumhash": "0b6b30efd72fad06611a6f177dad8b32f670002ae5622cd33f525a0a2d7c8e77", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "83030080", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "b0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165": { - "6feca11568940d6122b9150addcb2d9d321b868a9fcdbc103d": 1 - }, - "lovelace": 2327946773328696503 - } - }, - "0306030307030802060302060200030606020103020800030703070000010307#18": { - "address": "addr1x8uhq037pncwvawsp6k5cke05fancah2f2w3kac84fk4umcy0ymzl0p2zvtewfzpqqyjyqjxtq4nz4duvafztdd8a2psymgntp", - "datum": null, - "datumhash": "9401f125e1b6d6d785cccfaa8056d16ad886571bbce384c1a222425e16bad80b", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "b491dcc1b73a85ba7403761995999879496e76e088f91c0234c4b6bb": { - "f2b778dd54dd47ce0cadcec47cc915b62d6081c63a": 1 - }, - "lovelace": 5570539696467194755 - } - }, - "0307040401060007030806000702070606000306070108030805080204060501#55": { - "address": "addr_test1wzdu4h5l06n5cejl7qprgmzj8t3q6950kjzg9rcjjzrtu0q5fhfjh", - "datum": null, - "inlineDatum": { - "constructor": 4, - "fields": [] - }, - "inlineDatumRaw": "d87d80", - "inlineDatumhash": "4edbec644b7ff68b96e254d6cc71d2aee111b4f3e9f93f94d6674580aab29300", - "referenceScript": { - "script": { - "cborHex": "830303848202838202818200581cedf2794146ae22a4d6c7176abd0a3c435d5542136d50c0ec8af6a547830300808200581c835f54fb58bec6bb793aa378237ea35a44dacfb07c34e31f1ed630bf8201808202828202818200581c252b6cb6d7c9c196db287d475ce70bf6b9b731957efaf196badcc92d8200581c52734985797ae3354d8ccb9afd0a33484f1ca854775abda2ee76f87b8200581cd9ca685fb801e759f52ea6e45b966c5703a7a222f74f0042443766f6", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2e12c5e499e0521b13837391beed1248a2e36117370662ee75918b56": { - "8b278ad580f3f8125ac4c46cf7a415445691a57d5cab9d9f0cb4fc91": 1149211438802645416 - } - } - }, - "0502050007020703050000070200020204020008030104060108080803010004#23": { - "address": "addr1q8vgu93y7azksxewzkszxxkmy4gd7mun6qvr796djml6xjqwuwuvndvfnx32wlvk9yjw23vd2xqsx7kqw2jpzlycqsjqddmmy0", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "list": [ - { - "map": [ - { - "k": { - "int": -4 - }, - "v": { - "int": 0 - } - } - ] - }, - { - "constructor": 2, - "fields": [ - { - "int": -1 - } - ] - }, - { - "list": [ - { - "int": 5 - }, - { - "int": 4 - }, - { - "int": 0 - } - ] - } - ] - }, - "v": { - "int": 2 - } - }, - { - "k": { - "bytes": "08" - }, - "v": { - "constructor": 1, - "fields": [ - { - "map": [ - { - "k": { - "int": 4 - }, - "v": { - "int": -2 - } - }, - { - "k": { - "int": 5 - }, - "v": { - "int": 5 - } - } - ] - }, - { - "constructor": 5, - "fields": [] - }, - { - "map": [ - { - "k": { - "bytes": "01edf5" - }, - "v": { - "int": 4 - } - }, - { - "k": { - "int": -3 - }, - "v": { - "int": 4 - } - } - ] - }, - { - "bytes": "4ddad5" - } - ] - } - } - ] - }, - "inlineDatumRaw": "a29fa12300d87b9f20ff9f050400ffff024108d87a9fa204210505d87e80a24301edf5042204434ddad5ff", - "inlineDatumhash": "a492b4be24cd24d936017722d42b0fe3e67c6b2a8742188cf6b623ae3b83b38f", - "referenceScript": { - "script": { - "cborHex": "8200581c119e1af8479b0e68a5aff632d6c93a53c1bc22f3cb471e23eb28bc6b", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4a1c412d8e2b3015a7fb7d382808fb7cb721bf93a56e8bb6661cdebe": { - "b1ebff4c4387ae147ecec641d37dae54fcb1a8a4bf1dd7": 1 - } - } - }, - "0706000803050002010300010602070808050207010206070400000108010804#72": { - "address": "addr_test1xpsjwhlh60gfg0gewzt58darr5s0prccdnqfwaxjaeudks4uea70c44fj8ytlrqnjn9s8vlex22w8t0qpapgpmvys72qpurdmj", - "datum": null, - "datumhash": "dfe182ac30f1192800b70a0a0009fe2642521ac965d74d6d6d547519a4a4d120", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820181820180", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "f4186701e6431a30fb5021012e654c78a830e8208015a51dddfbd3f3": { - "34": 3313626375419622202 - } - } - }, - "0802000607010507060006030003040000000203010302010106000603050108#90": { - "address": "addr1wx5grsp2ehs79wwyegvw3g7rnhrashtynz544uryvn8n6fgkxvwmp", - "datum": null, - "inlineDatum": { - "bytes": "3bf03c" - }, - "inlineDatumRaw": "433bf03c", - "inlineDatumhash": "822ee1a1be0c39ce694502406d44a950d62cbbc8a2b8502543004a7c91cb9224", - "referenceScript": { - "script": { - "cborHex": "820182820284830300828200581c1e3ec90944b3a808955bc091416f18cd19e16b79be37bb6069bc618f8200581c728cbb2a189ceaf58510f2c3795ae7e29b8bc8dd93484a1ec334b4f48202848200581c761bf67251ba23e1f7a3700eaea474590cff7c42d14d35a412646a028200581c7effa7f69c37675dba22e3babed08debca5cc60cb4b11234ef84db658200581cde639e2ee86b475e77c2ec27f970885ba2b3d21e988249dea7780c318200581ca48dc5b637f7d5b16200861dca1a82d4cc9c5c79867ad98f403ccd0b8202818200581cf3ded0514cd5b18505ff890fab7ff2ea4b447e1d654cf4ec2254f4d88201818200581c22d8be579986080dba55cb267d21b887db7defbabd9a5658dfece83c8200581cf2eeb3d2614b8849b50298d3cb77a944485e74a5e48e5613c702f86a", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "c6fa36be42e66b5cbe83826e16c32a4d974e7c029f891c495731eb15": { - "7fd07cb9c2a12152953120b3": 7774821063674119864 - }, - "lovelace": 4059118946608426833 - } - } - } - }, - { - "headId": "08080000020604010006050605030304", - "seq": 6, - "tag": "TxInvalid", - "timestamp": "1864-05-12T05:54:35.488060620122Z", - "transaction": { - "cborHex": "84b200d901028582582056364ff68a01549ca528a39a3aa00d08a488ff01e7ded66cd42f50d998c5a405088258205bdf56f2b2f2de8fea583a387e3ec407744feeecf4c3933242e058e7c04f3ede00825820779e43205701c24f226533aa7b7d418b55c10a88a2f5fdf0d80cc86d0e89e80302825820d55964ffe381c8533b31c9f27a259dc9e49751e3d12c62e2fa724bea1ccdaa1401825820ea5bddcebae58e5168dcb30cb3ab8a91c85c6329bf7df48ea9406afe741bf622010dd90102818258206d54f384f5d794aecb2ae95135212a586c9ed84a558868e6ef440deb88575e660812d90102868258202eea80a97cf2f0c5781f09e341ee6795b05b6a7653ea16b2c74b23ffacae03d5068258207ac17f9a52f31588a869f4b8ed067bcefc0be38d0dcfcbef2c1e8a0cc362e3c206825820920bc7dc0b4328c985ead4b0593ee55984180d84b483362d5acaa5b21a3d86c5008258209e3f5f8c8bb5f8acdaa16a6f8f2cc96b53f837f6be0af6bfa6c922bc4461a4a705825820c38131b811a64280dddd85e6713d6adc65f736cb5f575912c2a7a6da5ce353ec03825820d1c6a5311c901d3eeed5b357c5dc261f9c18e5ec6ac01bbd1d46ecdd16f2d2730601801082583900f841951d86d7988d2044faa1a183d5df2a0148146b358cc90b770d4eaf1b865d0edf7032ba092b6266b32c5b38ee31eb140f1bea178e9e638200a1581c0faded008cbd4285d933416ae2891baaceb6360fd07229ffe24eec28a15055b218330984cacdce5147bc78b1563c01111a0002afd702198c0c030104d9010284850d8201581cb2294e0e566ae76e4aa3ae1c47f2cf396b7a8099de328fda9f54c54e581c9f43f7173cabd662727bcca9e84d3310f1e71a898cdf19085643fbb08201581c70d66cf6db1361bb84fcba2c2b4fab765427b7afdd50c1b953909fb11a0007b62b8a03581c844dd2cd6b52996cd07b8e75a54d9d989eff73b9a4d8397c2b4da0405820d25a2106ea2185ab9ad02fefef53a6a1e74d68a18f2700a2ee6cfbce19c67f031a000cb3b21a000ef900d81e821a07bec6ad1a3b9aca00581df0640ad971cea1e41ebc2f9d2baa99db9797f44b413dc9c5303afec26ed9010282581c052ffde4732bbc2bd5bb699620919b85a1cb11a2099ad9929768dde1581cfcf636f7c65e665aac2764ac079719c63d396579c2ef67cfff8f73d780826e68747470733a2f2f31722e636f6d4413e9d3818a03581c68455ed002aff08b664b931f28e64c1331f7be4fd956a9cd62d3e63f58209f9bc5c954d023e0c02647f4804532a0586d7327f2cb17213194ddd6ab5230571a000e18731a000ccd75d81e821b004c015bf546e6911b00b1a2bc2ec50000581de1f5728e9dfb35c4f1f4d5ccbcae5c524dd60c64168fafe0ece1700674d9010283581c2faa66b3b2ee70a1f0fb09b8dc2159e88941b15303508669da4fc2dc581c5b127fcd244812234998c086aa9f10b7908b8b70697c491a8ab462cc581c80c772242bad5d1273c2de03931b196f2ca5ee210790530d18eb53a880827368747470733a2f2f56585450504e2d2e636f6d4083118200581c22628aa610c38f9cb67eaf99be4d56dd0e81f0d5f8515b5a293b9ba01a0005ad1408010ed9010283581c83bff04ede4fdbee40bae4ced9844abdd6bc6c635ab08a828cd6ef15581cb0f86b7aa81fa370088fbbc2175ad62aec0981668978e75c179ec4b4581cc84a13f281279319139906147e903f02c2198650da7f95b9b57ffa8909a1581c2e12c5e499e0521b13837391beed1248a2e36117370662ee75918b56a154d13473d6ee10a80c95aac5b9e06ea587ac2b66481b6eb826537e60e2930758203cbb7a78fa157a312b5e7f454c258a1d2de6fbcf9e0ef487f3a1df9c766047070f0113a28201581cddf9a8650808bfc356e7f15d6dde0ff0db756414b5f3ed821a226acea68258204554de3771113095f1833808539e06edd43652a2db1c3f549b3e2ba8ffc33b2503820182783e68747470733a2f2f353475594e50456b4f685873463033696352707567476b4267596c41696a38474b645338664d4d50377333646a616d5a56562e636f6d58207b6551df00126b4514ab5a4cc5da8d341a50058906899b29e38d425d4de3eb2e82582056fab1116b5c0610c3050ddae7728ebd36f7b026d5ee4ab03b99ef1688947a01038202f682582083e0ec9b83d2f8ecf4c79d0e3dc05533f2f01e72da569e9b8411f4589f5bbc70028202f6825820e32cb6aca0b03960e88107fc65bf7efe24f8d0eaa2fb9cca5d56550b2c735b24088202f6825820e421d4f94a125f37a9eb36c0a0700f9449dd82b8b4941507bebaafba8737d06305820082782968747470733a2f2f5138466749426e4734376979794d32485946306136544636612d7561322e636f6d58206f2977d2d554cdf2fc1aba122cc0192f5f95d6dfb7602ad591acfc55ec411cbc825820ffcec5f0b51d1a70ab8f3260febd8c7675888b27dc7e1117f596c539a2751e9104820082783768747470733a2f2f3561304a56734e64516d43484336454e42392d344f4767694a5831467044532d33794b636b6b304e5747422e636f6d5820a8137e1116f7a09337a5436527b3632db6f22d6cf36ca52081eeee72c9f047398204581c7d9deb93f6eedd71013d77d251d9cb9949deab29295f5bb1c6f593d0a182582073925499600de1dde6fc8a93051ca239b07491f0d38597a1cf1ca6e8c4c08200048202f614d9010281841a000e103e581de0bcd18ed4ef6dfffda0f0fb5ab8b0512ac7ad78483caa833e2c564b7d83058258202ba909b3db8c65354034e7111cc7c532a956eb97eb6832bda201c9274f1b6b0a018282783d68747470733a2f2f7965346532786372573259724c4d676a50352d67587732446a2e4c7171685a62594f69722e65386b66464d3149536d2e472e636f6d5820bc30e1870513defe0fbb6039fa1fb07e5b6691852903eb1e274a46bfd0cf4278581c129265d12ca738ec934d5bd8de4f1e9d005d427d1b3a117548a9b4a982782968747470733a2f2f35715948696d38617638594b64615834786a43597a4d6c4a51376133392e636f6d582033d748b1bc813743a2216cccbe839c3c3f15013ed1d7075d7dc419297341b98e151a0006ec80161a000ee126a600d9010283825820681bfda5e813a325b8fb26256e1f54f4291c209cad57d80b3de055090d0335f25840e71db708bcc99ac562064232f5dcb8c6b20b2be4fd55b69601ac3cfb06a3a987a51c46ded709a3d9b878daa85b2059275e2412e242619a3aa17b0dbc34f04598825820d24cf7b717452d0100972b8e912d44497f0fc299f801000e3ecede964da00d6a5840512722d121d96bae863f4f8a11634a5eb7984c12bd5db8be8a363f47da6a30786626dedf50471113113de5c84986c0fd83a8a4624214249377ee7c5dad145b72825820beb972646e1898365ddcb7aed6bc2c5a13e95e14699a026ff24b5e06a29512df584097637b916a2f5839aa96ebc00eac53a9db66cf76d7ee4b1dafb696f788e848197ac182db58e61c2da34f1ee22ef0e9c41732031552d91a1df35042b6ca487da002d9010282845820b49828601692eb574415f0ef796af6c30beea1448e7c0d829dfad69cad1bbc28584036d8b99bae7385864363c1df07bf6f3a34829468d687b2fc2e4842f6325bf4f445eb930729f27693ad51a0e6c109c65696e77386b5e84e8b907a0b2801be408841ea42cd1c8458201f6c5cf984f25f5be82e8ba79279af3d79c2bb72503937ca545dac6b55e343e958407ba6e8b862732bd2bda2854768b776901e8b45119b6fa0188d5e9dab5de60c693dabaf343ca8e44c9a010e690d5f67327ef65ee44ff19f9c4fef647b8ee3fa4e4528aba2621243f30ab101d9010284820283830303838201848200581c502dcb2c4d0ec8a84449d222427d3ccb11f32c84456128bb07f2202c8200581c5da7f956d23f1fc8b2d1cbfcf879ec5934e2deb42a534e1bbf914b558200581cb9e6509c38830a2c4e7460d7d0f5afc755fd8df2151b4c66022e95548200581cf3f2808b23ffaddd8d1444793db430a19ba28e53896785ed57ebeb788202838200581c125a6b04a038a4deac6999021c0acba747874bb2d4ed251e745235ad8200581c164970f22eb6b119892a2655cdd64acbafed6fff36710cf23390e87a8200581ce53896d4b54734e844cc36d4aae36089d2ac21588be0d2cb3ba3772e830304848200581cfc770a80990848c43380e64783bbe24720660baa1517d10f2d1ce21c8200581c95cf19e24d612031ac77cf9b556980365f9ce4521ba3df06e429963a8200581cea3fc856bfa8ee4663ae9994a0fc3a253bb2e6b0e269659d28853ca98200581c203828e296572056df19d2da0d11dc9521ca93a37f317136a92f83b983030082830304848200581c3b532da6643f1e1e135a67f25fda6d1fdf6c948cf5941761d755a8908200581ce402c13461a581e6ed47e0cdeeacf85aecf030a824ea5da482abcf708200581cc86f0f15733065f8ee7ae02b1275292ac835524b5da6340c5a741e738200581c34a6bac187ad5d4eb435784111148de41fd7a06bbb9b71a6e5357b308200581c6344cce5683d33ec8882e0a991db68435fc1fc8235da065d9ac1dab8820184830300828200581c4109449616fadd5226457aacbdacd7bf1a0354454e72adb8e35e824d8200581c4e319dad9dc64f1f5897658bd2a5ac4443fa733de2be766e3331e4d08200581c05a8ff7c06eb6812b075f7384a809a77298f43bb10bfbbbf721830318202808201808202838201808200581c458d321dce09ca0ec4dcb203f9dfec526c3c61ba876d880e72d5414f830300828200581c673af2d69b1858a64d32bd4d42b1928539e16b1d82eee9ce7fb72be08202828200581c6a199b24b3ebc53f4fb05ec123e1c232236099297935c125618995ca8200581cda2983334ea5ed5248ddb126af42ae3f4459fc3f5db14711c37c237f83030181830302848202838200581cb3c5a4eb2d3ba280f6a37a9dcaee7b2df38dd75336df16607e5e7b698200581c45999bb83a40be9c76de4a382a3fcc7835ce0c8421c414961b38febc8200581c1dba14f450c3aeb838a465539e499257b883878e7cee194d4ebaacf08201828200581c8b7c5d7f038092060350d7df1c5541a94b201583ffe7b7a669b342588200581cde58a4fb6f8de7abb74988e98110b9eefeba7eee196f3a48e00a9ef8830300808202848200581c4d781aeb459cab4c1b9722919affde56309c150dae4d1264c69678cf8200581c1a331770ad465a483d923dd2ff3942b255f39d7ce66738468ccec0128200581ca55605ff0af1c0ca4b9612dbe88736e65c023c3eb411f8030507ca6e8200581c8bdb275ecfdd024d6b418c5425fa4f5e2fdfd0704635258bfd7c48408200581c6471a23c6e038f0e89384613f11dbc5e7ac14d0bbad1c8442468cac906d901028148470100002222001104d901028300a1a223d87c9f439f3a8f44302712f2426d10054113ffd87a9f2040ff9f2203ff049f43bf2d38809f9f050400ff43d79821ffd8799f9f2444d47a72f8448c46459c0440ffd87e9f204040419004ffa441d5044235844003030421ffff05a28203058205821b0b77a976ce9459e71b4659a609f593c1ef8203068202821b182719f0c782270a1b547e92f4e23d0e0cf5f6", - "description": "Ledger Cddl Format", - "txId": "371308bfc6648585084dc364687594c7b7b189e6e86fb4c4a44206a4216a9901", - "type": "Tx ConwayEra" - }, - "utxo": { - "0703030103060607070704070801030704020006050601040102070703080707#53": { - "address": "addr_test1qpgrxucp3mfm9m7mem0dwmv6q569py3r4ewawvnu8mlv0fzw6ucuhj8uxgnyz6x57at8c376rwe8kthuwv43kc58fuysrxhwsc", - "datum": null, - "inlineDatum": { - "constructor": 0, - "fields": [ - { - "int": -5 - }, - { - "int": -1 - }, - { - "bytes": "" - }, - { - "map": [ - { - "k": { - "list": [ - { - "int": -2 - }, - { - "int": 2 - }, - { - "bytes": "04e290" - }, - { - "bytes": "4c0d60" - } - ] - }, - "v": { - "bytes": "77" - } - }, - { - "k": { - "int": -4 - }, - "v": { - "int": -4 - } - } - ] - } - ] - }, - "inlineDatumRaw": "d8799f242040a29f21024304e290434c0d60ff41772323ff", - "inlineDatumhash": "22ca976555c826e557b4dce56fc839d0378109be06ea9dab1300e1b9715cfbfa", - "referenceScript": { - "script": { - "cborHex": "820401", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "08b92a10692e3cc98b5c9e3b5d6bcac096f3b9515695f26b14950ebb": { - "dc6c3ae5c7a167747d": 4645993867075912914 - }, - "lovelace": 4000808128275126352 - } - } - }, - "validationError": { - "reason": "\u0010?9" - } - }, - { - "peer": "d", - "seq": 5, - "tag": "PeerConnected", - "timestamp": "1864-05-14T23:26:15.960313819072Z" - }, - { - "headId": "00060207060107040501050007010403", - "seq": 4, - "tag": "CommitApproved", - "timestamp": "1864-05-09T17:02:34.296689062386Z", - "utxoToCommit": { - "0003000101010201050008080004080604060400020805070405080206010501#70": { - "address": "addr1yyfj378m55del59c8h6lnz0r46cf8l6nhqnnyu6sszte8j0uznj9l93plkwec9l57flfarjv7n426whyppatuvksmwcsccyj0f", - "datum": null, - "datumhash": "4b615a2613eb2e752e5bc18d75f19501d0d717d74521d3672c47a235199d5908", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581c0764324c9baff84759b88b7421201c02e964397ede4d13d07a5ef166", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "b576f9f53149f6cce5a019fddb44": 1 - }, - "lovelace": 978639582717169410 - } - }, - "0201010305000403040004010808060804010302060104060005030804000007#30": { - "address": "addr1qy0t9q6kr7axtk2s23umem38804r8340t3z2qw797aws4uj3hvrhdx2x3x64s2fss3c67rfjqqsep8523xefkz67up3q6pp6ye", - "datum": null, - "inlineDatum": { - "bytes": "1a1df2" - }, - "inlineDatumRaw": "431a1df2", - "inlineDatumhash": "0d5d8bc63c6cbee62bc8e293a5a6b532db0ad0be1d995aaca1e88cb8778049ad", - "referenceScript": { - "script": { - "cborHex": "8200581c28c581cd5092728837dab6105b88eb862f49d35844f7f328170ca442", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "b2db8fd40940185036c118cf317852dd8a1465a7ad88b7d2c65751c0": { - "30": 1 - } - } - }, - "0206040205070008020807000205030808010405080706060507040800000100#37": { - "address": "addr1zxlu8yvlj8ze2cuzgscr92ux6gx7xq79x28kvtkmj37uxlqv2r80y88mp9m7s8chy2jqaptrl9lvj0yc039fj76560ns43d7er", - "datum": null, - "datumhash": "4d1ec3c2e3c60f2c822893ee975107587e2ec8faa2bfd72df0609ac999810c1e", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "2e12c5e499e0521b13837391beed1248a2e36117370662ee75918b56": { - "db84ebff2ba7e6d4382d7a17f69c8d381f058e8dd5c9aa6d7dc144": 3094334162318242304 - }, - "lovelace": 6767931140313721052 - } - }, - "0505060302070804050805050802020600070406060303030204080600080701#18": { - "address": "addr1yysrkky2ndf9w7jmcuz0u54d6222l3kw5yser3vnqakll5skqqnl4pvk6aq5qfxhqxqvcw48wmptw288jwdfgx2nen8ss7rxsv", - "datum": null, - "inlineDatum": { - "list": [ - { - "bytes": "7904cc" - }, - { - "constructor": 4, - "fields": [ - { - "list": [ - { - "bytes": "e181" - }, - { - "bytes": "5e" - }, - { - "bytes": "f5436bc6" - }, - { - "int": -2 - }, - { - "bytes": "e5a41d" - } - ] - }, - { - "int": -3 - }, - { - "list": [] - }, - { - "int": 1 - } - ] - }, - { - "constructor": 3, - "fields": [] - }, - { - "constructor": 0, - "fields": [ - { - "int": -3 - }, - { - "list": [ - { - "int": 2 - }, - { - "int": 5 - }, - { - "int": 1 - } - ] - }, - { - "list": [ - { - "bytes": "11d37e" - }, - { - "bytes": "0781" - } - ] - }, - { - "map": [ - { - "k": { - "int": 1 - }, - "v": { - "int": 0 - } - }, - { - "k": { - "bytes": "3908a1" - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "int": 4 - } - }, - { - "k": { - "bytes": "29b2a5ef" - }, - "v": { - "bytes": "929b" - } - }, - { - "k": { - "int": 3 - }, - "v": { - "bytes": "7c19" - } - } - ] - } - ] - } - ] - }, - "inlineDatumRaw": "9f437904ccd87d9f9f42e181415e44f5436bc62143e5a41dff228001ffd87c80d8799f229f020501ff9f4311d37e420781ffa50100433908a14040044429b2a5ef42929b03427c19ffff", - "inlineDatumhash": "9f6b251d6995cb2f10df7853b53e536c27b75afcfe442405e13c0999ac2e8171", - "referenceScript": null, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "31": 5767329990493270227 - } - } - }, - "0704060101070807070802060008040500030503050700060501070506080800#82": { - "address": "addr1y8xh2ds7u9zc8pnvpljqra5tsfln89lq5lh909dvmqlpp5cmupztssgwmwcn84swc8zwv8w5ex5ne5kw9gkv2t27lu6sz6yqck", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "83030283820181820180830300818200581c17869c017672a27162d708f4583ef5e8e4f737e757cccf76fcc4559883030484830300808202828200581c3e9d1dce603d60275889ce237c944fd39994a6bcc8ac63c5f4573c058200581c1f7a54f2f63328548c4e1ee93c9f6bc4eba7f99381e5ec6239235d378202808201818200581c5aac18f57e7a8fe8502a73a31470cc9d31f0761519654c991a1edc1e", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "c18effec1078b92d4321aca527b4ef737e190b6e993ba17b3387d387": { - "32": 1 - }, - "lovelace": 4386885823412422328 - } - } - } - }, - { - "headId": "05050008020404060606070406000505", - "seq": 6, - "tag": "HeadIsFinalized", - "timestamp": "1864-05-13T16:59:14.113134444603Z", - "utxo": { - "0201060807060206080706020303040203030202000501070601020208050504#24": { - "address": "2RhQhCGqYPDnixWi33P2R4Fn3fas3QG9WgmZThogQw94GhguZsegsGyUwxCBdcuhCji752zWKVzqBAvcZxG29zUC2cKg2LNLgkvhxafZsu3z6z", - "datum": null, - "inlineDatum": { - "int": 1 - }, - "inlineDatumRaw": "01", - "inlineDatumhash": "ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25", - "referenceScript": { - "script": { - "cborHex": "820501", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "6241de0315bb53a70bce3c0798d7d17641b183c4ada9e1cf5fc5ac0d": { - "745b0d77c288fe131c2c77e7ea707f9d2030cda6f998d395": 1061897059702307770 - } - } - }, - "0208040708060702060608070204060204020003080504040603030307000300#65": { - "address": "addr1qyy67sv9tp703skjuv9yveg7fgc5qjvhll0a5mpldapj25ydyymyv4kvmp2xn03fvvgpkuq9kt3q3d7v94edcs6m42es53y5vn", - "datum": null, - "datumhash": "87cf085666507c0fac557ee2bc5dcdf224feedfd42884131f5c74c6b52c586f1", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820180", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "f09359851b919c2c2475": 1302882116234730395 - } - } - }, - "0401020802010201070803070406070306070805040403050300020707080605#82": { - "address": "addr_test1wzpqj54t7dh7hyqy5st9ymvs0tmenzfcapj58u6yxrsl2gg8y9nez", - "datum": null, - "datumhash": "9e8ba955dc826476ecd7f33121e2b92c7198adbb24f38262913db859122f2f55", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "830300818201838202818200581cbc96de9b741168856b284cec1932980ec16fa2cd056709afe73a5a2b8200581c13e80999c651dc3a345ae782708ca6cf259163b891c15df96963c03e8202838200581cf0867f17667dc31e385fa1a965bf4d0155672bf41b7acc684273af458200581c3438b57d24a6c750a43265bed774069b6ab216b53b573079a84c114d8200581cba45164affdd158b3af01bf7293867e686f13d6fd3e2d98267be3f6f", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "30": 1 - }, - "lovelace": 6563965195200116231 - } - }, - "0803030702060302030808000206010400070404050503080606080806010500#97": { - "address": "addr_test1yrd2v4s48uej2n5h4kg0q5qj77cttpr74fa4r9pqgg7f4dm6cfq2fny85yf65809pvd70ft8es78qdmsavzcjmhtp06smm34ga", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8201818200581cc596be7548dfd4b2856a5879707de8c7e43e771d2567d39dc5c37499", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "387c852f3256103d59c591c9eee914476d8ad9e35134fb296c8e002c": { - "36": 1 - }, - "lovelace": 61804120340218755 - } - }, - "0804080708070507080404080103020201020306000303010606000503010006#11": { - "address": "addr_test1qzwn5n36x7957exsjmpnz2jc50ut3vl3vns40tpwt995ta62ufprach2cwf0hcmcuj8as3shshnc8e00jsfcs2wsp9kq48h3er", - "datum": null, - "inlineDatum": { - "list": [ - { - "list": [ - { - "constructor": 5, - "fields": [ - { - "int": -5 - }, - { - "bytes": "a7972792" - }, - { - "int": 5 - }, - { - "bytes": "7179e8f1" - }, - { - "bytes": "5de2f11e" - } - ] - }, - { - "int": -1 - }, - { - "list": [ - { - "bytes": "32" - } - ] - }, - { - "int": 1 - }, - { - "int": 3 - } - ] - }, - { - "map": [ - { - "k": { - "bytes": "323a02f4" - }, - "v": { - "constructor": 0, - "fields": [ - { - "bytes": "84e494af" - } - ] - } - }, - { - "k": { - "bytes": "440f" - }, - "v": { - "bytes": "a5e2ac" - } - } - ] - }, - { - "list": [ - { - "bytes": "2f" - }, - { - "map": [ - { - "k": { - "bytes": "d90c71e1" - }, - "v": { - "bytes": "5c" - } - } - ] - }, - { - "constructor": 3, - "fields": [ - { - "int": 0 - }, - { - "bytes": "d6" - }, - { - "int": -3 - }, - { - "int": 4 - }, - { - "int": -5 - } - ] - }, - { - "int": 0 - } - ] - }, - { - "map": [] - } - ] - }, - "inlineDatumRaw": "9f9fd87e9f2444a797279205447179e8f1445de2f11eff209f4132ff0103ffa244323a02f4d8799f4484e494afff42440f43a5e2ac9f412fa144d90c71e1415cd87c9f0041d6220424ff00ffa0ff", - "inlineDatumhash": "422fe23960342b042a5385a030afb65185b9c692ed9f9dc58cf86f512a6a0120", - "referenceScript": { - "script": { - "cborHex": "83030080", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "cdb3e9286360a6ecdfe94fd807b46734dedd5f3af4da3793943b95ac": { - "3f": 5940959496842156766 - } - } - } - } - }, - { - "headId": "05060105010008020806070506060207", - "seq": 4, - "tag": "ReadyToFanout", - "timestamp": "1864-05-13T11:56:43.768829651511Z" - }, - { - "postChainTx": { - "deadline": 3, - "headId": "03000407030206030801040006080601", - "recoverTxId": "0304030303070603020604040807010002080503050603060700040400040507", - "tag": "RecoverTx" - }, - "postTxError": { - "tag": "FailedToConstructDecrementTx" - }, - "seq": 2, - "tag": "PostTxOnChainFailed", - "timestamp": "1864-05-15T13:26:47.541262065562Z" - }, - { - "clientInput": { - "tag": "Init" - }, - "seq": 0, - "state": { - "contents": { - "chainState": { - "recordedAt": { - "blockHash": "0501020704020706000705010405020001050005020203060808060806000607", - "slot": 2, - "tag": "ChainPoint" - }, - "spendableUTxO": {} - } - }, - "tag": "Idle" - }, - "tag": "CommandFailed", - "timestamp": "1864-05-09T16:31:39.428756442663Z" - }, - { - "decommitInvalidReason": { - "otherDecommitTxId": "0707060105070303040001010404040804020501070507080703000203010405", - "tag": "DecommitAlreadyInFlight" - }, - "decommitTx": { - "cborHex": "84b000d9010281825820d4dfdca7111bded7af50fa396c3e510b8fe3419ab7c99513a885e3badd838d9b070dd90102868258200c44a5e5824e6d21988414a825e92ec92823a6a5a29652278c71f622a60eb897058258207d7e0cf78e89f6093d2bbacf2220b919380034492a9564cce66f6948dd94bb41038258209d650820b4dbffdb36f8733dc68d40a5ac3ad65689b984820a6eeb47106371fb04825820a3dd883cb3ff32c73d86fae3fc0d58bbd1b98bec0a0d8a271b353ad977fc986502825820f1205cf0a670982bdc449f38a9679f867982f72973e3318cb4f396ca66d838fd07825820f6c2ba9e689e283c6391bd08501448743861220ec25e390040ed87e0b1b0b2910712d90102838258202a37f875309d1f0dfb7bf371d40606ca19c7d601a5c0f7d642a9862fb02b2cb6058258205a18f4b322eea73de93a85dcdcf4dcbebfa199c0d34ddb9ab0122d672d05c4ba08825820674d589ce889c4babbc90382958f4ff5ab0a6019e73d02c9e3afa92d5fd75102050182a400583931411a6e6fabb18e8c4cc73230df5ebc74a5bd912125f39611fd271acff533717b07016ea5fe4556a0969a028e5e5eadce23a339ea594e1fbb018200a1581cff189f3770bb07750f1f1605501e733a122e99f010351a02b33db11ea141391b6c270d0acb5c229402820058201eabe5942c55f514a7bb05d290385d0955239fe22637d223add0cc2bd33d8f7803d818582282008200581c2b8dcf10f14ba0ebb7d63eaa0fadd8ca256381462539850ac72cbf54a300583920a8730590901653e3cb8c60e63d7ada17dbd66472aec7fd61a7305b17b640334ec43c4b5a9d21c44bd1cb646d82d1c0181508acc07169beb501821b794622d262e23343a1581c22255e392be07bef274b779b5a65c997984e5a819ccde712b0fdcfefa1581cb710f37025e670b83b9fa680888ebacbc6d52ee78a37d17d1348c7581b069795660d376aea03d818582282008200581c27265ffd51c83fafa5d126e5387dc731af03d264ea0e07e161079e64111a000d8fdc021a00032bff030104d9010283830f8200581cbe08a4816ecb56a8a48a7625c63cd5e977a1414cfcf42f015932e68b827168747470733a2f2f307a7a79332e636f6d58206a26f6feda04a3fde77c850818fc39ccc8e8295e2e370e442dd1ee26f1166f9883118201581c6104ccfbe9e1258abd81d8c3c4bf0eadfc2f65b4b1a38cb85594881e1a00016b6a83078201581c2232c02874b34dc2bf6ec40680ba5f7654895bda31906cad80f9ec351a0006a446080109a1581c19cd42ec0c4fd8adf2a2dd0aebab7346b3755829fe4163cd36f53eeaa1581e594da713a79599df4ca610bf62d4345ef5ee70d7ad9d9c34fb5da4e54e701b4d55c626e865703207582061a39d27b67b4a2af3c37457c91cae874a8c1f296f1a3563304e374b842f9a250f0113a18202581c0bdab3a84ab83bb1dc90d7e2a2b356e36d27d9d3555e5b42e44f13faa5825820086f0c6ce7f391f930c10a31bd5d98e9603dccb44d18dcf500cf8754d39473fd088202f6825820846b6caa1252a3669d9c48e43dde8197e640c44a1d53cdc8f18ac0f7b9015e6f08820182783768747470733a2f2f6651466d4675636358575a4b54595a4c73384c564b49326d343449775235753033306d735679664e3059432e636f6d5820235da0a43faff12cd97e62147cce50d5a50c422acc3f9e38f443afe5d8a17e2b825820d09af26fb15deb1242b5d2b8b6f7a92a2ff97079c0af9ea4b28af1fbe2cb100502820082782a68747470733a2f2f655366545238435a6e4e6277736c35734742726f4e3330523945483337472e636f6d58208f1d2c7aae70fa7e888a5fbaa20779f98f55f750ef97b5ece67f4e62ea72216f825820e5477de9b1f8e4e372081d26bb57ab7a3eac2f2c28d07ef6d680348dc0b2c63d048200827168747470733a2f2f793768686f2e636f6d5820ae344111074d5e7a2d9bc5b50f7c0574749733cafc4d2ba7d9722e7e2839b0ef825820ea8a7864bd6598f5450a89a6fff543ee3e8b82ce50d0ba95b040c3880bb4dc9001820082783a68747470733a2f2f326f7136495157475a727a42665a6c326366596d4f4f783551754262554245314e59426a666d32573238303752382e636f6d582003562c91b4ddcbf1799eec9d8c161c3f892b2a98dabea3dddb332d588a8bcf2814d9010281841a0004fca7581de138bb6ade9a9472495a9ace3aea89c86bbd98f8e503ff0ff754fbadd08302a2581df19312f5eb7285e8063d4d409c989813378deeb36b3daf78187a351ea11a0001d7e7581de17001cc1ab89894ea7001ca3daf1782d6dbac8ac7d999f9a8bcb9c9071a000d30b1581cf45c11a09d55ebefac1de633fa065dd253a8b716b53a70cc0a24ad0e82781c68747470733a2f2f4f3958633853696b696a502d326f38782e636f6d5820931927f08c934b3ac873a87b3ed49b60bd24fc0997c14d635ffc157410528e02151a000a3f48161a000a1415a600d90102818258203742a697066d88c227fa3ebf8129b4207f552d2efa616991e456b58bfc28e51a584009f20f80b6ab411d16686d9f3de062e73497bbf5a9b97379cee2b0efbbceb4b09bbe3248dd0bc44df41c331303ac8a96f21d67fe9b09d2add5b4186dafba17c602d9010281845820ef189246915242ecf48e209498a39e52276ccc03657f406a1c43de323246175858409984bf3a8df065c3069bf43b912a046caef6286453ab03e563ecbec120703b3ce6e780f4c2dc480b5a49906be3b73ac11d52b25d0b68805e4c9e9b4302488426422ed34001d9010284820183830300808200581c450ab78cedd5af95de9657a7cd1491a72c41857aa201d4de4d25149c83030082830301838200581c85611ac3b458df4a62543f268ce052d151b9a65f85110759fec7cc488200581c07f97c17d41fdb71f93001bab8c48f27f29963d8a66526446edc76de8200581c644be543b9b145d117bc25d701a7b662de743797049081f4f8dfb1028202838200581c819e91fcab94c5251f7aa084e2f4d0a0391d42cd2b99bc52e9463ae28200581c3bfceb025568b133fcac8d062617fe00f2e4d05f01a20871b956c9288200581c21e5ac66255763971b580f6b05020b6ec9c96b3873dcbfb2e7d92b1682050a8200581cbf0845ea19923085bea964df46b1bdb193169c66e4b27dfd5295daa8830302848202828202818200581c5102de4f8737fe44b0d3131cd616ab430deda4fd5938b69e6fee56968201838200581c2a68888f65740ccfad0721545e4273bdd9e25e73c8e97d6dd5a1f0768200581c16683450bfdec667a03891454f833f0dfdd5ee9629517c7214126fea8200581c65d51d9e61f6990bfa079b772a40951ddfa6150c241bd6a43e72935b830301828201838200581c1feaa26fc131bf989a2a7a9e8be4438681337a409f443b736ed5d3338200581ce940c4b7f4dae4afb70ddfc7b8ee67005d4c1e94f1a0882346825b028200581c1e0bd126d178d5935670400492ee5b2e0827c0094b4eed85b3816fab8200581cf13d2a3b50be14109a23178d4d9d08880b721ce357dd28352a01a7248201808303008007d90102814645010000260104d90102869fd87e9f809f0541724432917633ff2380d87980ff9f8040447b1babb180a0ffffa59fa103059f4041d02343b7235f22ffa40503214024050143cf3543ffa29f2401ffa44044384602ba415c4134224237684107433a97e022442a3112809fa2202224414c03ffa59f040441014201aeffa040d8799f0103404155ff424c8e4141a544988a36cc420a0405442e88cdef230004242005d87a9f22ff04422f829f9f0001ff22415dff9f00a10541229f0320ffd87b9f23400442365724ffff9fd87c9f20400441c322ffa5436c0ca6000243194747034022224041e0ffa29f449040bd03ff01440ce9a2f4a52341fc42f1ea41ba43a97ad7034219770342daf20280409f9fd87a9f22400520ffa444774c8f0804419b20212022029f2140ffffd87e9f9f2302ffa0ffd87a9f43da9020d87c9f2305ffff9f24029f43a7a80cff419e04ff44e4d7d632ffa201230543836b8180d87c9f24d87e9fd87c9f44a6759d8f40ff44579ae692a2441bed8d41032240a240404497487e4524ff9f44293e557944b92889f9ff42e8bcff05a182010882a5a5425df3a2212321437ae55b431b568d03d87d9f000105429be64185ff02d87b9f2105ff423bd140d87a9f4178400240ffd87a9f41ada320449e821bed04240541a921a541c441c2411f42e4850044086d3e79402144fd5c06d040d87d9f44e7077279ffffa402a32444ed06a3bd40446e9837b10005a5002342f048438d077a20426f77244214f6418c212044bca4c0a89f0003ff9f44fe5a5e072041b741a943aa5bd5ff428379434d7535a1d8799f410140ff20a1229f0142cc0b446a09e1f64020ff431f3179a59f404483093d1eff01010440d87b9f43c09dd223ffa1417a430e1146a32203440f1ec49c404005a0a42341e10144c743aab94264b524010305d8799f9f432df572ff4450acd86404a52242459d2021010121230422a34146040005418722ff821b2c408230acecc8d01b211849b68261d9abf4d90103a200a4026befbb9439400138f0b191b2048241d96a0277f4878f98e4b397480a020b04018582028082050f8200581c2ba6224c723eb0ec45c8cf2c311437d12c5d9de9c26e600886ceed568200581c463a0f14e3dbd665869297a649633c01ca655e118764df7647d87472820283820282830302828200581c8eabdcb13532e615f4a41127dc8dbada86343890eacc8517b732fc2a8200581c7948131455a61810504cb2a22773e7a73c316b4b726a310c4e1231218202838200581c0ea5db1886f2aa3c0298a831bf2e86784ccb52215192f19e5041a6ea8200581c672911e8e54c15860426c48114b6903ee61c2e69b625bc1eaab4af578200581c7fd5c25b78636c96166e56ad86029ccc0a3acffa28475d2ad4e907bb8200581c82b3a8f8004d7988324c611adbee4288c0d4c5983e29b65c1ff81ae883030080", - "description": "Ledger Cddl Format", - "txId": "6fb7f44195a6d930eaaf9f274198e5bc83b307d809568a81b6a189ad422f0372", - "type": "Tx ConwayEra" - }, - "headId": "08060500000402030703010101040104", - "seq": 1, - "tag": "DecommitInvalid", - "timestamp": "1864-05-07T01:14:47.941654923125Z" - }, - { - "contestationPeriod": 604800, - "headId": "01030307060106040407010205060708", - "participants": [ - "06080002020002000707070603070703080105050307060106010201", - "00070807020505020102010302060702000702020107010406040106", - "07040402070402040505020106050605060805080607020002080203", - "03000603050305040608070102050505070701010502060102040403" - ], - "parties": [ - { - "vkey": "574ccea88f328f6f3b6c2aa5b7444498558d62a6efc4d3a8f3326758524b9b4a" - }, - { - "vkey": "2cf8489b8943a8e5139326f4fd976cd2d6be8a779e7e0a07840e612937365a66" - }, - { - "vkey": "7e02dbe5d17505c85f9c1b5946659f6fda901e52daeab863e1a6875bbf0c34de" - } - ], - "seq": 4, - "tag": "IgnoredHeadInitializing", - "timestamp": "1864-05-04T07:03:23.919025226558Z" - }, - { - "decommitTx": { - "cborHex": "84b100d901028382582073a8e012698f4e31822075b7b610c5ef5dd085761f5fa6e57d2547a06d804fe10482582087de85c2fa91a193103b34dad08b4cce52c5e855b5a807165e5bfd8d88dff30807825820c0fd0f2d62a6667bb74767a3794420ddfefa9b17fc9137c61430eeb1eb481a7d040dd9010281825820ac69607bfc2028ef8b9195b17ade4a65fc42f8adc83f63f6999dd91c0462a8f70712d901028582582040f2abde1f37a020b7ed2372c7fe552ab896224d0b765280582bf4ef2569553605825820754fe011d18c9f8020fdf6ef64c76a4d0fdbf7fcbfccbe769c55e3d104bc85fc0382582085fd9bc15f2bc0c82ea9a6ba48f2b1f011013ba044f83226d50b5050ec7040f101825820df1c6657bb2840022ca907ed57903507285f5ac3b88ae213dd7dac1bd8069c3207825820e479bde35d061e582254a0f9329b7cd9e53f5f06f9eb0f48d4782830bb5f9cbd010185835839207e23720edc0574b4c37f2817ca391b0b9d0fc01bd9a0789eb9255fe0521fbfe754641db4c39bd04b437167c2858f0d6f0b96b5aa9a7854788200a1581c4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888da14440b6e60f015820ae3edcfa0ecfbef2253ba89c9d866b75976982e89eaf6b4576d07d4e9c1c56dda300583921f2bea3b09c1464f96e695bb5bfda6ddc19f98abea9fd9fea59155df731b74eaf23da8841579f8f41f477975929825cc2a3138b1ef9eb19cb018200a1581c2e12c5e499e0521b13837391beed1248a2e36117370662ee75918b56a1553cf9fa1c67b0398ccd2b3af89d95679e0f179661111b34e8c73dbc47f9cc028201d8184102a400583901278b1f783da01aadbca0f042db3ae0294e10eab7279fe290bcd2fff43bc6c554e61ec3efd5da0786039ce36d904c5af62290f9a60f381c9f01821b257342a0c44104d7a1581c0af53b06f13528e6ff6705a5b1a521d75c19d1a7af83e7be2e6e82e0a141341b52085b29022308ae028200582084350c74c1241cff70f2a1244901e2d09b44aecf1bfcbde5ee9b9690cef1ea0103d8184b8203484701000022220011a3005839117183ae875bc52b94b1ee665815cd920b44cb9ddf89b81804ccffd51da1ac87d4c1bc6f05293de9e7801f9774cbe9262ec04109eb52a3af92018200a1581c432fe09aa1fe30f83f9538b7df3c94a1dea061c1a3929ada75eba1c8a154cc5532f357f7f0a64e62112039d8b2781f89730e02028201d8184103a400585082d818584683581c101a9629f1f45a06a6562d47cf95cb866cf76180f630c6f6ded3f59ca10158225820d6cbe3969898a904b49591c6470280b4dda997b061121766590877122f0c83e8001a7fc6e386018200a1581cb0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165a158195342dcfa6ff39b43a0e784feeb60c73aa672f64b8df9c226c802028201d8185853d87a9f049f4219caff41ffa422a5400441e624400243b1701b4494bee4c22344b18816b101a34261bd052424419a444f7b739ca344b9ae964b0444a9861046445f647aa02201034131a2002041334347daa6ff03d818582282008200581c39179d961344cb0425b123de0e16426ec468c6a4e6622398c6fd4c6710a400581d71114af9eb96086f5bbee9900ef43fcd5856d0c5cf549c6a1c6484b964018200a1581c2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1a15820cff029a312a4cbcae8d36035db5e7de595ce621391a5c3df2de147aa5ed826211b5e7e687434487b1a02820058202a31a0e7473a9c235c3eacc37ff91295e82d59c9170670a2ec90fa465106c48103d81858948200820183830302828202808200581c16c5f12dce148dde645d62fca6fc228756478e2dbe14e8de4ec8890783030082830301818200581c02ce076f48316ef8a9d18fe316deb6222a3c2fc950ede92d6cb045538200581c61cc60e21e241d78110b84b1b232324fe2ffcd3fdbfc9c2f1f3ad14a8200581c98ee983e2966d3d184e9b2498d3173d9f4e4f8d16ccef139ecdfbe9d111a000dc985021a000ce4e7030204d9010284840c8201581c7d35f92d00c0fb24db124f4555f9a0875fb983eb125fb837d357c06b81031a000e57ec8304581ca25e2d463036a78c3170df5fe33d595bbf381a587709a39a83eb866f0083088200581c2faba9eff7206844ef37103604c73386f8c55ac70f94094fc821a6ae1a00053dd083088201581c0b7c0fd0b75fd00073daedefe7787152ac56ed6fec616c781e0e1af51a0006d3ee05a2581df045cb6a71d15bb47ce2426b226e66ad6877639fcf5df1fa4509be21a61a0005a0d5581de1c48ae3b5add17ffe51a334c951b4bc1dcfdff1f65b244810f71c011e1a00020b2b0ed9010284581c09c4bf4015cd3e9200120289f781f58e36eb1aed9802db6a8e768cab581c19e95ecb0b7d1be26a1e398a9a861d16a0c840b1bfd8040ff4b8a70a581c1c6d77bb8703412abfb32b0443ea9c4d010821ebd1f0a9b4ae8c2076581ce4cde94f808451d584e14292c2a30d9aa387d05b77067d59e4ccae7809a1581c8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3a146669dbedd78b71b20f2b75a7e7100250b582069d0ac74e00887d5d15161a8ebe1dc8730efb4296757ca166032fb8e2c2123cf075820c3cae290fa2e8448565248e5bf4d1dc0c334bf80055b8222f03a7831ef33d5b013a38200581c478689f7ccfd704eccf8d92fcc8c9cfcb0a84479d053e3152c6e46a3a182582011ddc02a7c5d810e3cfc91d017f6b346bc4d51fbba2759139f7410052a14f583038202827768747470733a2f2f6d7934796d4361437352792e636f6d582029aa34e909a9d9d2b6e56f43b1dee5cbe1bc82e11b0b41af33c04060f7d5a23b8203581c9bbde32d015e9b1dc7974b80c2347da0a57ab98dd951756b8657b71da28258209cd9d8ed5e603ec1617c55c1b88cbcaf08946ebbb990b16b0d1929d84929227906820182782468747470733a2f2f42644c2e5636374150593233326f6b6365477346784d42542e636f6d5820ebbefbcf27a064ea798d328e568d021e216ef48e6a53da2629edfaa80447387a825820b334cdfe4165342f967f2fa17d57e82d78087b38b7fc042f6ec77bdafb0fecc306820082783868747470733a2f2f766371476272504352466f4263522e45436877504866653143425464754d3273774377352d796664515633502e636f6d582002a84cec72a475cc85ea66246bb77b394c42b8c8b14922a056c561c995d7cbaf8204581cdfe8b327970d0feda6721bd5969d39a27a1a0aabbb7d9dce3ceb858ea5825820387672866ff2026622ccc4a4adaa6346e3b4f38a49753dbec520d571639967d3018202f682582061bbfd881507d75fecb70913863a1c93dbd6757c742db6caa38e013614964cd1078201826e68747470733a2f2f67412e636f6d5820a710c9791b5e614a55aee0c3b6d23d3d1add97cbba086cec20557e68c1bf2f13825820625541578e0ed8f9d3a4650b05bbedc0fb4da8226487e70d76dba1ae8d367def04820082782468747470733a2f2f445269697a57646f475a3147524c45436f694962744d34552e636f6d58203aecca0d55f34fa406d462b878f27c20d46a4fe43d1143f7f7de276bc534da80825820fc5e9e9f924cee990c0c569e3cfd538f2b2c4c1add2961f54a485da581b34b6f01820082783868747470733a2f2f373155323058687443594f7442536a547854736b412d78486b4d4c71564f39757563547854554d79597553752e636f6d5820de5e2d15c3b2bfd6d8702cc0ab24c65535ad51ec0023eb04a5e2488bcb2cbbbc825820fd24f5e0196c6cde795e9e56be3d1ca02737b4e7b729fd049ee1033894e73fcf068202827368747470733a2f2f47646f347055422e636f6d58204ae58a344ffacc6835abaf9b95c765d08b62f4ef19d2fa1904f18659265d7b6a14d9010285841a000bd80c581df04d2c2dfdec0ce88462996c92c1413fc2d225812cb0a3e7bf00a901508302a5581df03a828300c5aee73c304f4fd50829dce7e98db8dbc00e3ebfaed9b7881a00029c74581de03a0477877ad1c33f3ff20c8bba72aa94267021c55084e22102f8202c1a0008e9ef581df129ec3fae10fcb073858d931f17b4764f8bca7b66f28f7300db5fe1e71a00097157581df14abbeab5ec3d6a8096103440c16bde5b9492001437cf5551730d931b1a000182a4581df1ac43f6fb8fcbd5ddeb234cccc3d54ab88de81a5a7e272766e198fe4d1a00037aae581cdec7c9b9fa7c80926318384ba901545403131d91b932b04d2ea78b8882783e68747470733a2f2f59584b736f342d30564734477946596962786a362e57326c52564261586d664f76587764753033374b357a6a4436544c64612e636f6d5820dae81ce91d181ef1697c92ab564639a0549918228a6a22b09b720fe0cdfb5e07841a00067fa1581df0ef296840f72a3a1260bae71f19e5c018713cbb58a54ab70f7f4bf93f8305f68282783968747470733a2f2f4f5578444b55656463424c4838462e36584c462e414159487a66616a36306149307a394e597766487476496f542e636f6d58208f2da357d295fd931e3062d023a16c7f2f2baf6aed7cdbad7529e977abeeb8e9f682783b68747470733a2f2f547951736466565a4f577857376d766d345359413159643661305367754c69726d4d4176416e4f65425673664e78362e636f6d5820322bbb30d2d0a3ec69fac82db954bcd15c26c7c49e73fd6e5554b49e79252099841a00017107581de1af60b6dffcda839a1047b3530aa5a0aedcecf4e6dee435e12f3dad5b8203825820a0cb9ef31e12e8edcff1c08a984d7a22d9ce7e87fee45133d0a63a9b0d67a0240582783f68747470733a2f2f6d7463316f556b355a532d536c7644383045705535744b336f6b36493165586d4d7443574d767a384b6d4f36504137672e31482e636f6d5820a0b69a1a42ef3fd3370aa0eec6ae4b978390682400f1f1819c62b1cf5f09105f841a000b81cc581df0f84a474f9a4cfc9ca34e12ca1dad4d23cb196f0342a0ace416f1c96b8302a0581ca9b39b534970d5c3b89be83151688a47217a076fc2765f89a252673182783168747470733a2f2f784e797736722e507063355052587747753037634537632e4e3734692e377352706f5143412e636f6d5820d0122545ebc390ac77f893282f67d7bce6961e9173911e56787f271f37388a0b841a000c1385581df1241f208274775d0438144d99b6be74ba23a78280e449b6e9c5ad47db8301825820f14c35ed9c40b4f1b7da5b5cb0f258f5bd715106948e5df1400d789d07d897990382090582783068747470733a2f2f6e6167773743512d4f316b31504f445748436559736564782e704a504b4e42664f5031452e636f6d582069350b978896cfa1924313e8df0fa7a4373425e6977d1dc492cf5ecf1835dff3161a0005bc0fa800d901028182582088cd3916e681a55d5a73b6da7168cb780c3ef62d15e338b11737518f31e69f8f5840bec46c62c062acd107294ab9aceee84a0830b2fed08f15468bde0a2c5c10152bf6dbabb54b1565ea29a2baa09006d5d974a1e37e1b87db3658f7a54aef3677fb02d901028384582011609c74ea7734332b6558ae5307374ba71072cc707a09d13330df51831a2b1d5840953314f240b5793bf83fe8299600b57b61e072cfc03704bc75907d1e3a4784cd750241f01e3eebb1c920ce784750ffba5a69ff8cc0eec443cb53655c2535bd1a4151428dd68458205cf8ee06bc479ef13a2ffb0f27445d8e4556b9dcb2e4e6b80888104107e4c35658400a31ec345e73c29e2aec4c382b4683b42d5b08e53de83d0343b7a0b4b7efd22bd9344043b868a6a9fdd1373f34af5e950af2a8789c1345c0dab7bb1a23cac9f245e03ee201ae410d8458207650a53583e529c5d42d1fd20cba844101ed0c7268238a4df243f76c72da15c958404bf52f2c05a2f05cf5ff6f929e3f5e9c9b62b8c0c093ccbdfc053f1b7b9f9af2eee12197f9ba89b8c547990829ec077da97ee01f38fe1cec9cb36f48f7bdb63541f54001d901028182018483030182830300808202818200581c5e80dc394b21a8b758da0e07f97613bda85d2c2eddfd45e197f60aac830303848202808201828200581cc6f3cb6435ad37c7bc38e694e52d0225f8f9124ab03604f5026e4c758200581c842bb1cafaac5e953396185b3fbcda346fefb76cf724c757e46230948201808200581c1f2fd0628919827ba010dff196b58648ca612116dafb19eb032cd9058202838202828200581c667d92a6767bfd9852b6195d015a59f4e44ab27f780f922c063cda7b8200581cd033f0abea3f433d249562a101665238d9cd6f27116ad8353651feb08201838200581c2568db235ded189f9f8634155dee97795b822ff7a4086c764c06b43c8200581cfb1501d591e2b7dfe6788c0e2c3d4fae10f14fa9be7ace8a9220c2c88200581cfc47dbd6ad089753e81502284a3625dd5ac78ec5c445909b63c1347c8202808201838201838200581c822e0754c0246428b77c1abc1913f43c0fb5b54baf428f1c6b39c1fa8200581cfa72d1403fe63ab2d8dfd95cbaf4ad5a2a491fc3c9da6162fffe4eba8200581cd7b0ae37bbe34f5c29633bd7c39ae275ae71f134da1eecc412012cce8201848200581c210f658726a5537af758f0aa7459253618c6eea38879a0a21470b7e68200581c85dba498f5a5fe7c184060bfa64802a7e59871ea9df5a98c50b86fbd8200581c09c4df6565f8ce61be30ac115c854bbecb37ae87addcdae4791c97868200581c141c941ee2f4e34c20d0ff6206b569e2495732803abde4b863403654830300848200581c4bcf83c3489c38c9efa7a5fa4ac97c9093c96d1680f29d241ec731088200581cf84a8d46635c954bd77d1434d5764a2180af6027109791725b68f5dd8200581c6c1872745f09cc23d8c0bd780dba57b8e2b4f18025f698a5c049c2a08200581ce6bf14ffdffa6b6110a32b5494f00f73276f2ac309ffb96671fe954b03d90102814645010000226106d90102814645010000260107d9010281474601000022260104d9010281a504d87e9f436dd6bd9f417842896c43307ec003ffd87b9f24ffa4431d286b2243e42b460244f759e4f0447541b63b439cf9a042e6f7ffd87e9f9f412f222403ffa404433fbcf244470288bc446338af0c22404002ff0544820b289c9fa42001419a43f018964176435c6bfc0220d87b9f4023ff413eff9fa0a0ff21d87a9f43de81a8ffa39f42b18543c2b00fff447d1acd8fd87e9f2204412821435f1cbeff24a141ed4319baa59f44c3f8671cff05a4820003829f44261894b1ff821b7d857c2f0d1e922e1b7f0814803ccc1427820301829f002041a19f9f2442dd3b02411223ffffff821b4126c32f6df631481b42ac55d451e4d41f82040382a2d87b9fa3234308bc244297da4239ca4325d62920ff9f42be2743a06bbda4402224420f870103428a4e43d88371ff4153d87b9f2042a52bd87a9f22230343b20f7d03ffff821b6834b3296f7d58ee1b6c93333e521d25708205018202821b1acba962237e48ad1b50526eff95e80571f4d90103a201838204018200581cec0e82817007b3d8273e69693fb19b2b55743bf31cb873b8ade367b38200581cbe6ca2b08f48997c8b50cf0691bf2f08bb439ff41d797e5b5b310c890381484701000022200101", - "description": "Ledger Cddl Format", - "txId": "0988d3f3752008ea3a2a657bb7e459ed4b15d68877031c9a59b7f5786fb6d13a", - "type": "Tx ConwayEra" - }, - "headId": "02050604050001050407020601060000", - "seq": 0, - "tag": "DecommitRequested", - "timestamp": "1864-05-08T13:08:10.002146937331Z", - "utxoToDecommit": {} - }, - { - "decommitTxId": "0806020103080104020806030503050205080405030401020507080105060602", - "headId": "00060407060303050206050203070708", - "seq": 2, - "tag": "DecommitFinalized", - "timestamp": "1864-05-06T14:28:16.682035484227Z" - }, - { - "headId": "07040407060800030208020708040203", - "recoveredTxId": "0505050203060503070302010408040502000305040606020601020603040100", - "recoveredUTxO": { - "0104000304020600000502050700060508050601070701050207050306000608#67": { - "address": "addr1qy60hm3zdfex45yepev5p2w4anqj3x3v3rfzlqgyercq7mcc6h8mtdmf9l30qpfcttnk7d20wjt5m8snv0qjtnam5q6qstkwjp", - "datum": null, - "datumhash": "0f6e3057473b99526a2d07a74c2587dbc99779b8f11170fb2f458db911e80330", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8202818201838201838200581c42903f275d05328e695503af5f8d214fad7f5da0b9f725d1ad5939c68200581c643cf3bb65f10cfcff13b493518dc3e99c7602022592d8487030bbd98200581ce473cf4027982b56858b808230a290e331f54484d1491e39820e2a9f830300808201848200581cdef77537e14d2d05d7f6e1d6ad3d942782c53c5aa49c9162c335c3b18200581cc93449cb2841c0d68d53f808a869cc0a56578446870750e518310bf58200581ccc24036e5583f4c45df3c7fd3e8fa2b78e80b3bf3df68cff0bfcd0948200581c7b8ea726c69e7b52a641eb87f7a67e18aa536b29d5718b67173b8123", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "7ed095b4bef83668f6fdd6afc2971f72f4cb3d82b09db8db87fa78b4": { - "d3e9b0b7fd742f02": 7786542827382944078 - }, - "lovelace": 8340178111422960222 - } - }, - "0104070303020802070006070202040803020206010508060507080706040302#83": { - "address": "addr_test1yz47aghxdq2x8xukvt5747ekqcs8v5vej9xt69hvuxvl6npt40sdk5cxcmg6wcukquqz9y5cscxjzqg6a5lawdjx6p0sasp82r", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "d4bdb80d70a5c233259873c2ec1c897770cc5aff1dc1d4db3095bd5f": { - "30": 2813959094858433208 - } - } - }, - "0302040103010002060106020604070700060105010400000401080005050704#57": { - "address": "addr1y8lrlp8c7lajr3kaa9f5a8xzrh69khve2rr90s39aev37dhc6a8pgecqcrddqdtmwjfw5vsmrtxha963jlfe695shdks5jp7nf", - "datum": null, - "inlineDatum": { - "constructor": 2, - "fields": [ - { - "bytes": "bb" - }, - { - "int": 2 - }, - { - "int": 2 - } - ] - }, - "inlineDatumRaw": "d87b9f41bb0202ff", - "inlineDatumhash": "e3410e42080e6c2e40785071a039ea1cc99ce91e29cb174f87c4b8afb478107c", - "referenceScript": { - "script": { - "cborHex": "820182820280820183830300808202838200581cc380a15435575e475f1d9adfd59d9ded0193101f8558617fb65677d38200581cebafd59f5c87d43ef2dfa3ab74bb01f434633a4b9ffb02b1975d6d868200581cdf867fb75925a42bdf46c91d4dccb70c5b3bf776f9d2841f0109acf8820280", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2db8410d969b6ad6b6969703c77ebf6c44061aa51c5d6ceba46557e2": { - "9312275560f798570ca3dc4dbee88aa94d1bb6afa331c368fe2f6a9730ed6a": 5762848890340780353 - }, - "lovelace": 6912919329478184537 - } - }, - "0404060108070505050506050304060303060304060707070207070006040003#34": { - "address": "addr1v8pq5p385k329t7s63gstvmjwu7x9z5nepx4fyaur0y47qcjvukmg", - "datum": null, - "datumhash": "53519edfbb9e86d7f81f180eade79a940cc529f6970a2ac576f3f14f6f9c0314", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "2db8410d969b6ad6b6969703c77ebf6c44061aa51c5d6ceba46557e2": { - "beaf77423a6d762421b5550a9b4afd": 4788030547536078143 - } - } - }, - "0801000300000805010103030206060603030500060608070000040102080300#49": { - "address": "addr_test1zr2p4x02x7rewypkwhrt6e6l9wzxmy9q3fw0yx6xfw94mrrhgutrygtpfav9g6tu9g9ym60hmyw2u5ngamf7lrp7lpfsflflg3", - "datum": null, - "inlineDatum": { - "constructor": 4, - "fields": [ - { - "int": -4 - }, - { - "bytes": "d8" - }, - { - "constructor": 4, - "fields": [ - { - "map": [ - { - "k": { - "int": 0 - }, - "v": { - "bytes": "3460" - } - }, - { - "k": { - "int": -5 - }, - "v": { - "bytes": "be45" - } - }, - { - "k": { - "bytes": "46c6b7fc" - }, - "v": { - "int": 0 - } - } - ] - } - ] - }, - { - "int": 0 - }, - { - "map": [ - { - "k": { - "constructor": 4, - "fields": [ - { - "int": -3 - }, - { - "bytes": "39704bbf" - } - ] - }, - "v": { - "map": [ - { - "k": { - "int": 2 - }, - "v": { - "int": -1 - } - }, - { - "k": { - "bytes": "b7af" - }, - "v": { - "int": 0 - } - }, - { - "k": { - "bytes": "dc" - }, - "v": { - "int": 0 - } - }, - { - "k": { - "int": 4 - }, - "v": { - "bytes": "94a98e" - } - } - ] - } - }, - { - "k": { - "int": 0 - }, - "v": { - "constructor": 4, - "fields": [] - } - } - ] - } - ] - }, - "inlineDatumRaw": "d87d9f2341d8d87d9fa3004234602442be454446c6b7fc00ff00a2d87d9f224439704bbfffa4022042b7af0041dc00044394a98e00d87d80ff", - "inlineDatumhash": "8c936bc15be18629aac1b1537bb7dedaa61cece3b0b2bebe0fd31cd08d6e385f", - "referenceScript": null, - "value": { - "fb612e730bb3f02e33433680d73f113d8b07ef9ebba0e280e81d345c": { - "88523cdefae1b7c3b18ec3d7ea": 1 - } - } - }, - "0804080402030507070107050705020600070204020500080507000000010604#8": { - "address": "addr_test1xqxfuar4p45ga2e9hn9zlkfayprmufyet34w6y9u7rheesckeymyf849zccchrwkfc3wj5dfl0medr6wfcpd2v4vzmgq2z30uj", - "datum": null, - "inlineDatum": { - "list": [ - { - "map": [ - { - "k": { - "constructor": 2, - "fields": [ - { - "bytes": "3b" - }, - { - "bytes": "220d" - }, - { - "bytes": "f8ceaa77" - }, - { - "bytes": "a16f57" - }, - { - "bytes": "2d0a8e" - } - ] - }, - "v": { - "constructor": 3, - "fields": [ - { - "int": 0 - }, - { - "bytes": "" - }, - { - "int": 2 - }, - { - "int": 5 - }, - { - "int": 1 - } - ] - } - }, - { - "k": { - "list": [ - { - "int": -5 - }, - { - "bytes": "27" - }, - { - "bytes": "" - }, - { - "bytes": "" - }, - { - "bytes": "95" - } - ] - }, - "v": { - "constructor": 5, - "fields": [ - { - "bytes": "8610" - }, - { - "bytes": "f958" - }, - { - "bytes": "578286" - } - ] - } - } - ] - }, - { - "map": [ - { - "k": { - "map": [ - { - "k": { - "int": 3 - }, - "v": { - "int": 0 - } - } - ] - }, - "v": { - "constructor": 3, - "fields": [] - } - }, - { - "k": { - "bytes": "62e28e" - }, - "v": { - "map": [ - { - "k": { - "bytes": "85a2" - }, - "v": { - "int": -1 - } - } - ] - } - }, - { - "k": { - "constructor": 4, - "fields": [ - { - "bytes": "1f02a8" - }, - { - "int": -4 - } - ] - }, - "v": { - "int": 1 - } - }, - { - "k": { - "list": [ - { - "bytes": "5089cbfe" - }, - { - "int": 5 - }, - { - "int": -5 - } - ] - }, - "v": { - "map": [] - } - } - ] - }, - { - "map": [ - { - "k": { - "bytes": "13e5" - }, - "v": { - "map": [ - { - "k": { - "bytes": "c783" - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "int": 5 - }, - "v": { - "bytes": "0e" - } - }, - { - "k": { - "int": 5 - }, - "v": { - "int": 5 - } - } - ] - } - }, - { - "k": { - "map": [ - { - "k": { - "bytes": "83ed" - }, - "v": { - "int": 0 - } - }, - { - "k": { - "int": -3 - }, - "v": { - "int": -1 - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "int": -5 - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "0cd3" - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "int": 5 - } - } - ] - }, - "v": { - "bytes": "0510002f" - } - }, - { - "k": { - "int": -2 - }, - "v": { - "constructor": 5, - "fields": [ - { - "int": -3 - }, - { - "bytes": "" - }, - { - "bytes": "088f307b" - }, - { - "bytes": "bc8a" - } - ] - } - }, - { - "k": { - "constructor": 5, - "fields": [ - { - "bytes": "" - }, - { - "int": 5 - } - ] - }, - "v": { - "map": [ - { - "k": { - "int": -4 - }, - "v": { - "int": -3 - } - }, - { - "k": { - "int": 0 - }, - "v": { - "int": -1 - } - }, - { - "k": { - "bytes": "59" - }, - "v": { - "int": -4 - } - }, - { - "k": { - "int": -2 - }, - "v": { - "bytes": "98a71b30" - } - }, - { - "k": { - "bytes": "20" - }, - "v": { - "bytes": "" - } - } - ] - } - } - ] - } - ] - }, - "inlineDatumRaw": "9fa2d87b9f413b42220d44f8ceaa7743a16f57432d0a8effd87c9f0040020501ff9f24412740404195ffd87e9f42861042f95843578286ffa4a10300d87c804362e28ea14285a220d87d9f431f02a823ff019f445089cbfe0524ffa0a44213e5a342c7834005410e0505a54283ed002220402440420cd34005440510002f21d87e9f224044088f307b42bc8affd87e9f4005ffa523220020415923214498a71b30412040ff", - "inlineDatumhash": "1d3ef9193758a7e5c6ab6ce1fb8b8357dff49b3e4e7e3e708f135e11ff8f4917", - "referenceScript": { - "script": { - "cborHex": "4746010000222601", - "description": "", - "type": "PlutusScriptV1" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV1" - }, - "value": { - "4a1c412d8e2b3015a7fb7d382808fb7cb721bf93a56e8bb6661cdebe": { - "f7ed4657c63c4a99434f8334129a5e": 1634924248034755108 - }, - "lovelace": 2763357872581498724 - } - } - }, - "seq": 6, - "tag": "CommitRecovered", - "timestamp": "1864-05-13T18:11:41.233858712643Z" - }, - { - "contestationDeadline": "1864-05-15T22:03:53.452896312475Z", - "headId": "04060200050606060506020607000101", - "seq": 6, - "snapshotNumber": 0, - "tag": "HeadIsContested", - "timestamp": "1864-05-09T02:38:24.646702050158Z" - }, - { - "headId": "00070400040508070607060002060000", - "seq": 2, - "tag": "ReadyToFanout", - "timestamp": "1864-05-07T10:05:18.158447451911Z" - }, - { - "headId": "02020804030606000600050403080104", - "seq": 1, - "tag": "TxInvalid", - "timestamp": "1864-05-03T14:22:41.063579740446Z", - "transaction": { - "cborHex": "84b000d90102818258204c4b8f1f1bb266736925d4f004b35b0d1dd7e47b4f2cf484032aeae357a5f020080dd90102868258201b47ed9e383d79bff8b2d535ca009c1c3aa6c652467fbcbe64347649dbb1388c018258202c85ae1c4bbdaa82dd5c954545e4191cf7bc9d514df74cef4b459faff4a94c7e08825820328c4ba739322124fd41e43a1bb834ce0accbf2da691095fdf7df5811c7bee110882582037d89fc1cac9b6d930f86cb590e10534f1bff26480e7c5e9e609911c408f265f008258209c0c097429474b1a4738198aa3be264c8a7cf083f8de6293e560b38cdbb215ce02825820eff680b0b2c98bc115eea28aafa2e112ab4754201f50ad77716c8b74a7ebcc290112d9010283825820027c4c46474dac5a9ace08da2bd79766ec66af08bccb5482a5912324f583b70607825820118260805278cfcc2852e2f159ba4d6646dad2cbdd2acd737f9f24ea80b42e1d04825820e009e78e911ce5bf721c88cd8481a6b704396d1bab8311334eb8bdf99c72d74f060180111a00043f6a021a0007b01d030105a1581df0cbafe970afee83cf325eb964aeb1a0c7dd54e9c6da0cd7ec3c4acf1b1a0008c2730ed9010282581c9cc1b7593e6ee8c218fac946fea7bc97fa0b933cbc6992127d68c401581cd5c099c0620d24497a135efb54ac3f720d01790b6e8f14cca77c0f0309a1581c105a8f1bb56444cacc86378c95421aceeb326b0fb7743e493eb82fd5a141a81b065d7b34e255e56d0b582075c5b0072b3ac72a7dc90c88e54211d533de90f411935c41418a53e5a484792e0f0013a68200581cbade7c6dd140dc65573a2ae6f43b0ea519ad3753ce45c42b34dadccfa5825820110d611c3c2fd3a1111862e4db0c3f0897c9156eb07d274967672ac056a8a38f08820082782468747470733a2f2f6873765a504748797145386a6f2d717935385058345157762e636f6d5820ec0622cbef15647e29471266b7676296eb112033f15a60b82731d2d3fe03914282582028b17591aca1e5f4fea61f4df5158cd8ae1fd98121e0f6f687b054599e938811058202f682582030105c48884671e63576b656347595f61e109f06a47dc035a1583d1b76be8c0802820282783568747470733a2f2f664247732e53726a764b764a4432346f6766624d4f346e7855335158527341466f735174416b74314e2e636f6d5820615c99cc8e96bfd013676913f3804cb8db6a75ffcc6561338b94f065f246827b82582040584ffdb6ba430243b6c9757cf60663ecfaa6fdbe3ac9e18cdccb72f7a18e8905820282781b68747470733a2f2f52495834756b7a74307169595447652e636f6d5820bb84e8775b82f4eb0986f57a1e243927c1e00872d34cbb716ba306f3abefdbda825820f9bd877c0dda8046e636eaaede73355f4559fb7ebc76876895e37e7c1836c9d6038200f68202581c545c99da6a984892b67b9b7f098b836b8003e2c830d66b08c7c256a2a38258200b7f83ff532b5998969eefb4c07a58b25610fd3f039046c144f59db26ad73e00078201827368747470733a2f2f74674a4f58486d2e636f6d58205883e172abaa664c3d68572b12d8064d39f285244c47eee0412a1952b2d4a1a4825820aecdacaaf675721b3ea197cc402049763436d6bcc876ffd63d64c4b732d9d32f02820182783268747470733a2f2f393165426267764c6272356c753271446c6e6845414d7037475136756d51714c774a4d2d62622e636f6d58207567b31e82172112dd866e89713916030a4ffe747e7d01154220f9234230df6f825820f230b1ab90204e625b8f20303d7ce966873ea68b9bca67c4ae361de1d3443388008201827668747470733a2f2f6c3875444238645a66672e636f6d5820d642493588fc81da60eac118a3270f6a24f39ee48ba2947444682fccc58fc3028202581cb6456a477a5787f696b7a50ef2e12a805db8e56c6ed4771fbfb535bfa282582075646b742eb9b50b32e1f9a30ac8c1e3db961adf0bbd372eb0ca04daf59a2f6b06820082781f68747470733a2f2f414e6c72664f6b77776837774e4e78414e4d422e636f6d5820918cfead1fe7e98d3aa6ad19335c5d510a0441436867733d83ce5e606946151782582087d84ab1e7e2d043505699cad8d978bb74e85078b2764d8b8cb43100abaaed49078202827368747470733a2f2f79416a593661742e636f6d582026f36c7cc43038e65f78bb25459d689bad0ec1c1d76ee0315b705cb77dd7aaac8204581c1ab7315074e6688c123589d84ed7345da1409b0fd27921e9b1ab91ada58258206ad7e40a85257052dd0d6948b0dcac390847a72409301581f6a40962d09797fb04820082781b68747470733a2f2f486d42592d56757166736c484875312e636f6d5820d29153c9012ffa21fe0ce391a782763304c67e261f2ab754ea59f1a894f92a6e8258209adf6040d8a04fd6a34232f8db152f8e4d7458fdabd9bbb728f6e3557d725a3c08820182782d68747470733a2f2f383052476a38433847306c72434f57773656563164664d4f51794c46437a705a382e636f6d5820c702ab0edd6f8bfb8cee1f9cabf4e2b56262aaa0f191034bc1477d1f90cdfc4d825820d03f0032d50f25ae83fcd10939528b6784555cc44f1f93b6d5313fc7883511b7058201f6825820d2b31030bdff9648a9b251362b67b69e36090ef1dd54bce3cd6a1f4fa9de6ae7078201f6825820e0477f83f5cbce387dbb16a76199e82564e373329cd9ce8ff17306a85f275ec705820282782868747470733a2f2f657a7a7a337667426234504f425133557a476742505976325466376c2e636f6d58204dc6165d21c90b9d15390e0d89b0b501550fd382de0f4210034565775d1d45618204581c69947f65f0fe38d009e2659041cd466969c8cea36a96b78c1fb83417a182582022d8f34152611250b7c30520a946da4101bc7e989089f3b09a95c19dca8c9ebd04820282782068747470733a2f2f617853506f416d3537325863614473736b666e752e636f6d582050f03352245e9f0a24def1962ae78a8a5d32f02858083b4ab00f3bd2b42dbfb38204581cbdbd313305343cb5724ec26f7158434f239e0d475c0d5701e0aba9d1a18258200bc4b78d4ed2e02fab0e7830f3d8cc9d1fe241e95acc8ccc04281b32e65ab55b00820282783f68747470733a2f2f7741527968454c696870464c425038556e7a5565506e5a4f4542746248686638315372384e516130643155464d31356545464c2e636f6d58203289409cf22323cdf006f25c7aef7e091b2f661b11603f138e41296fa983ef2e14d9010285841a0008bb52581df0f1fa82a4ae3c64e79eb26f7ed4076f1f001753adcb5fceef8976833383058258200f8efdab17f1133b83d49a61609e9b5abce425d5555fe55ab2d174be334563bb068282783268747470733a2f2f747941547048454c4f376e684d58373838732e5a2d5764584e796c773358587a574c6750662e2e636f6d582035b9e5243a255b600d657716b9c72c5d8ac167bd3d8f7dddaaf56aa637f1177c581c611a65c3dc60767ea387d0d2f54e9502c5b5a0ea7e1692c9e9f21b0582782968747470733a2f2f617964722d44437534687651504f717350436f435633646c776c7143372e636f6d5820f1d7099a0ae8dd6cc90327274c2860c353e70f339e26eee2f20e30dea51ed73f841a000c41fa581de11f4f85b130009452c9088fbfaf6f93716ea32d540b4160b41863df95810682781f68747470733a2f2f4358617374504937484d7a34757053712d564c2e636f6d58209924f9ea34aa49d03fb42623315ddf9c75ccc0a5f238ab342a8421b9528fc734841a00062e5f581de05662b282e75dca0c8c2f4d6641579478fbd616d0eaeb1cfc9fb8ba9685048258207ce137007744bb0c65f45db459c0d565553eece03a39f1f891068db468800eab03d90102828201581c97f510ef61d63ba4561ec0e34027cffc27eb0a56184dc012eac018498200581c45ed3f7ef4030413f2088a7c1ae28a8a6f1edd1eb92a341d183dc686a0d81e821a00329e791a004c4b4082783f68747470733a2f2f2d2e7a4d734f7041616b5a3057766c4f313244675148457178364d4a4f6d734e6b4862746d4b6d31375a4a3845413439702d6b2e636f6d582063d343b73d124d8766a12d6adb6b6837f683a7821195a06df7f930275e5f111b841a000e973b581de072d3bb4b0a099e95b981f92ffb282121d2c3b9b44681f48a9a2e8fb082038258207ebba7304cd4c8a11c0895751e806feddec812105e6e9bb59e3d8eeabdc2c50905827068747470733a2f2f73594d382e636f6d58206cf154fc8114e485ad1f6ae930dff85a783a4e3102defea386b9031f378f1190841a000f29e9581df0089a62cfcc72fa0c86bb49780beee5e71c3c3ac990c2a26e0242097f85048258209104c942b46768dfc7789da904ab13faebbd3cb2666e39dab457ecbc64ec944b00d90102848201581c09b75ec58652f7ca26d18ef5b450aebe3baaacd15a86ebd0d860d5528201581c69ae76aee5faa6ef5b9a7584e2e80720cc31eb9e38b122a99289b6618200581c6ef42f2d2c8beaf5f166c403baf99679a7a39195a1410a365edf12b58200581cd456039a1909bdd4bf31ece098f9e5a83270306a5b8b5dbfca0504faa68201581cadfdd440fc1f16645da56fe799d3d77dfd7e7d49ca238b9e44c281fd108200581c3d5a29dcb2f39a248cc64b7884fae304241779d4f93fff01eceda1b0008200581c7052a089d736a216c6ef202c1452daffabe8c423c06dce63f8033e58088200581c79e1d2fef399bca2953bc7123ba8ca58886aa715b78fdc71d943e0a80e8200581c8819c032a137067bfa5f96b06d9a9397dfa762f1aeb6571203feb7bd0a8200581cdd3caf394b386228a32cc8f9195faf522d66955199ac7cfc90c1da8c01d81e821a0001ff651a00030d4082783a68747470733a2f2f5a57653042416659636a4f6f6445454b703556634f6a566b31655438616274555a58394d4e7379593448527364702e636f6d582025e59f3fe35be62b2bc5a48defc26b3b975efca89a58e02019d0fc2ba8f5ede6151a00065929161a0001fe6ea402d90102818458204cf566be954ff1a4e43715d53bad3ebf191ee0ab79bb16bd1181cc9eca86ea925840b1b7fd0bda48039022edd686b079fce1a5eb11d9f35d82681b36528cc339ebe7c8df610a2f4e64cc19d5da396f13fcc8f58b4cdb840bf8d8e9bfd855a8e114fd4509137c3f5042f60301d9010286830300848201848201818200581c32239296c05a6472a8211c1218c00b08750c77d89a143b74f64e6d3d830302838200581c8a4eb5bca06d0331cedd730cb15a2040e18d145f42307d56baf793cd8200581ce333a4b07354a0925716c7b1c617a501c69b879e6b087a1239dc36148200581c900425394ab36719e8f72eac6663a2a78a7dfddfcb9bcb3e7a24237d8201838200581cefccc4c782f24373d2daba650920796b389c1f757081233bb160996a8200581cb9c2f4be1da3a402e5744c7d939e67fa72169d47dcf3f46e771be10f8200581c3a53d72a6e7edec376bb55124adb7ad93fbddc055143d372d108ad898201818200581ca72066a9369187a4196c2250b6dfe3956c2cf28d19baaa98c3f0ce148201828202828200581ccb53f74e5d6bff90db97016c3bcd2650efd735191d1ed43c21200d7a8200581cce2b41eb685f7542f81be2488ac0c95bc12f32de4f85b55b82887ec78202828200581c9779eec2fe7090bf83f3037f216b60d1125bd19df6317c028aecfd658200581c501cf39004ca88ae58076b0a48a5b835d668fe95417e2fd3df5086c28201818201828200581c351a1f1adbd87b3919aa3e6ae9792c74e6787b4eabdb2bc4557a0f748200581c11eefcd19173953a1ad7ace17986a0de9c2097058fe2f16c67f4a63a8202828201818200581c3af25de705f46829b6063586f5424f935476d20359382dbf128b78da830301818200581c00823047490d591490532f8307184398145c5ad515eb05a11e7425cf820282830300808202838200581ccaacf8bb1f1f50b45fa3761840fded2bc7f26303e727597d4fa3efe48201818200581cc914a1549c4557e4224588a5d2c8df9b0fbbd702c06d5850a873707a8202838200581c0f7decad17bbede854ac537ab791b24636abaec649dbf5590d40fff08200581cd2b99ad47dbd3653aa2838cb94e8ac23a77beefbc7b49faee32785ef8200581c021f4d9299e337761a8ce429eecb1ecb397f48ba0e33ad85460d4cdc8200581c4744d633eac09a8c23f3f30efb83045f752d3a1028aae53d569fb863820181830300808201838200581c7e0a170320ef0f478142399b4904bd6bc30af3056d0f204ddb110dcd8200581c623310fc0478cfaaf3e9e622b6bf2d3b3d17a1ab45a1cae5cffee69983030080830301828200581c0849df5a33c5b895725cad938fd55f3e67d72d7b304a4a7984cc1b208200581ce1248ac7414c03f8307ed32e72e85c18554f2a2d48829d318973422004d9010281d87a9f00ff05a382030582a543315ce1d879809f0201a524224041be05214326041c42a29c0100a444bc3eba5d402222435c764e030244bf02311ea0ff8041d8a3059f01022101ff03d87a9f2400ff8000a1d87e9f428e77ff9f232021447403820f40ff427e589fd87b9f42fea443cfa5392000ff9f010524ffd87a9f0041e4ff05ff4471edc8de821b797d8d3173d006991b7c548fcada89876d82050582a5249f9f00447962af90034126ffa50224024375fdc04044f50ccd4144c1beac2041170242426a438579d101a0ff80d87e9f41399f244000445f830702426a74ffffa3a140445d8a7591a42200431616072141cd2341452440a52140438cce0d4198411f43e0119142c04044c7c2c0d743ad087f24409f2441fe2001ffd87e8040d87d9f44022604e3a40140400321012040ffd87b9f24d87c9f402322ffa300433b6266436cbe2944fb5e33e305437d05aba50243e64b740244767269c0417f2300224043e646cdff9fd87d9f416224ffd87a9f44aead4f4fff809f40416cff9f418444e083ab4dffff821b7e494d343e20eb3a1b3dfae60443c4092f82050682d87b9fd8799fd8799f41e8ff8005ffff821b4ee6135c7de427741b6326faa13c0b9faef5f6", - "description": "Ledger Cddl Format", - "txId": "e01a0ed8763f885d700720b568b853f01a7059306d014d3ee41e22f0a349dd6b", - "type": "Tx ConwayEra" - }, - "utxo": { - "0004010605030103020801060703080206000508010203070404020107080103#17": { - "address": "addr_test1qp469mtnrsk2ge2fvpqc70qmc0e6cz94p9nz8352lp2qrd2tsj8eapml7dqeu0t2zgf7cpu9qvzxuumuh9ada4cg5tmqjantkr", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV1" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV1" - }, - "value": { - "105a8f1bb56444cacc86378c95421aceeb326b0fb7743e493eb82fd5": { - "281970": 9208371434053110243 - }, - "lovelace": 3168617693074321366 - } - }, - "0005050808050501050804080701040607070504030500060208020007030203#0": { - "address": "addr1v9s44yyj9ew90n095uggq424qszp5rwpnw4knaaruwqaxpcrs6usa", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "b0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165": { - "34": 1 - }, - "lovelace": 4903801701358168522 - } - }, - "0306010208040506000004070702080501020603020207040101000806070500#14": { - "address": "EqGAuA8vHnPBG75p7JjEXnYt1bttR7PrLeSbM8hm4dFu2TzCijruEov8UtRVosRfR4VHMkZ5Ls6yUnkLFfxQYF1NcsF3vznc92QH29SNPdwoX4YimqyUfQU", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820408", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "b906bb27166a7505fc429c81d17184b3b897b349bf3221cc4b294b41": { - "72555ee6": 1 - }, - "lovelace": 2680396456651413355 - } - }, - "0504000006030706080607050104050602060806080406040500010206020705#33": { - "address": "addr_test1zpy4ay9m2zxt9gksvx9gg23t24gtzsmjgd5d5hmgp6a4v6pw6s98k8w0cnyzt5xl6w7dpj7a5q0lhkga39n6kyh6u4eqyz8rj3", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "381b29c7795af6b37984027a653350b8761788be39b3d4a9bf796a8f": { - "2d5ed2cd61a840": 1 - }, - "lovelace": 5949807087288263821 - } - }, - "0704010803020307000006030500070607080203010006080500010804010802#75": { - "address": "addr_test1qzjmafpg9m0t7zxphe3kmsd4zmj23cvx52lk7adq4ry6vvxuj37h7k3r52x9fmaft6frrqe8vet98asavlvf4vqxccyqvgsxmd", - "datum": null, - "inlineDatum": { - "int": -4 - }, - "inlineDatumRaw": "23", - "inlineDatumhash": "2208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc1", - "referenceScript": { - "script": { - "cborHex": "8202838200581c32dac97b107e32c1d57cc8cd3c16e8203035e5dc732c8d10065caa44830300808200581c38a466593de3521ac99487050c3fa807d820bebdbb07cb6086925b27", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "11acfb840427b55a90d91ded7fed0ebb0915a236dfff0c622b81acff": { - "33": 4554468102197111076 - }, - "lovelace": 5984166055670024675 - } - }, - "0800020701060202070501060701070406080501000106060100030204000002#8": { - "address": "addr_test12rsmsgjxguafspjkxmy5xl7an5wu9ggur20wpj7k9cpz6uc8pqqspqq4c6", - "datum": null, - "datumhash": "0ac7f7be3e5f9fa7eb84242844d57be1a5cdf75ec355fc9fb5b2b2cc42965eb0", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "b928fd8b1b824f25bd78df819d59a7576e52226b4b06125250d38e43": { - "873516e98d136d1fc9b160f0a010832f": 2 - } - } - } - }, - "validationError": { - "reason": "𫎣d" - } - }, - { - "headId": "07050404000808020802080105000205", - "seq": 4, - "tag": "HeadIsAborted", - "timestamp": "1864-05-13T12:47:00.059229461498Z", - "utxo": { - "0008020208020207020108050601000705010301000108020300060406060000#3": { - "address": "EqGAuA8vHnNturbkZS8ffaWxJp5kWHURnTh2FgZjqxM2kgXre2EkLexPrcFDCGTbS8RCwj5jWM7Fdo3nrsMoWute8jX7KTJYHWMKSym2QYsTAPTQf28RWvF", - "datum": null, - "datumhash": "d2cd68682fb485082a9e3eb55a26f842751394771f038f0bf024e6347ba6e5ee", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820410", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "eed846a18fb31e8e6566913a119515a4692f1def8b3f719f3322c1dacfff": 2387294905934596318 - } - } - }, - "0008070402060203050108030506000107010203040707070404030606070006#71": { - "address": "addr1y88kuv9qycc5q3rthff257wjy2jks9920ey9xe6wjp67jtyh936n5kakquhftlrh3cnq8ws9dxfkp7g4c5wzz7x0pv3qnh4w4l", - "datum": null, - "datumhash": "e2dcec9d53dfd653e917026ce499f0018b3c32faac0e57b247c2b21aa08454f2", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "4a1c412d8e2b3015a7fb7d382808fb7cb721bf93a56e8bb6661cdebe": { - "9992223ae09ebb12bed3cb5ba6b1d6d9739d6a55b1b1845217b699": 2800954104812526029 - }, - "lovelace": 5070920917240809231 - } - }, - "0105050001020706020507050404050604060206070408010302050806020604#85": { - "address": "addr1zxu3hf4crm0d3kuscrz74ch856psqfrgmec27hrj28eqwu8pc6s5sa6uwymvc5et9xknw2whz5ps5xsd9par9nuegwyqc26srx", - "datum": null, - "datumhash": "01f4f93114bdfe9a797a4948ccd3966fd45c09f687d831d92f8e5430a9472f08", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "33": 1 - } - } - }, - "0108020402070607000602030407050502010803050008080808010100070401#60": { - "address": "addr1qx0dkaj8qy5jnvauwpj20p4r4str428um0j9jcy4wlswqg9fj37tr7hn932tggryuu8sex7d7pvctgzyamqv0t79l3js4ux6mp", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "4746010000222601", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "c2628aa25ce44da276fb7abc59c5f00fce4068de7f0dddd38087cc0f": { - "5e427306d77c7caaa3d56932e469ec9b65374511227eedc1": 7438280875150385554 - }, - "lovelace": 4721424278785581501 - } - }, - "0703070301000701070606060700070301070803030407030507080301040307#4": { - "address": "addr1wycn9v2f8jq9w06va300wuh7rtahp0cfd9cyfqejkvmn6ns2epkc6", - "datum": null, - "inlineDatum": { - "list": [] - }, - "inlineDatumRaw": "80", - "inlineDatumhash": "45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0", - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "e179d2e34d6550ca05bac934a8e95d6c6a5292f7cf2678ca1c612007": 5993093868119661006 - } - } - }, - "0807080107080706070305030308010408000101080006040002080105050302#83": { - "address": "addr_test1wr580lk6r8c4hgtky7tcczsch3puvg9auvxmduthp69fpgggfexn7", - "datum": null, - "inlineDatum": { - "int": 4 - }, - "inlineDatumRaw": "04", - "inlineDatumhash": "642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342", - "referenceScript": { - "script": { - "cborHex": "8202838200581cba9173ab05b3c3bc2df8b69c3238a829f3bffae0ec83bbe73320f296820184830302828200581c0f6545a3ba0fcfac17a0758f5b31a9871595ca4377afff123233081b8200581c6a92c5c0e2340254c258a06ac878660741fa2287c14802ed8d0944498201808202828200581cf4def2bf330fe23c0793dd79c3cf64ab70ad87c08c3517e78c253e9a8200581ce30993276baecd04cbc32d43363a48dbfbcf5cd2888294ec7ceacb3a8202838200581cf3301b77ba9a39e401a9ddce43af592231390ea58ffff02adf2614138200581c65fe5ab0b24c15df4c6f65164f87799f6f601cf1968cb9f5ddbc60208200581c177d7544b750f698a181b5ae7dbda7aba833912157f4eaef2a3eba4f830300818200581c03ea3a91e84852c24ff58949a49d24fd951b246eeea30f83a26703a5", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "991033003146270918cb2036492ee9d17f8b8100f126ec12e4629f4f": { - "8b88c2": 4225819298541227184 - } - } - } - } - }, - { - "contestationPeriod": 86400, - "headId": "06040208050305040208030107000503", - "participants": [ - "08070806040107080105010505070000050002080206000103040504", - "05060601080302050203080803020806080702040103010701020501" - ], - "parties": [ - { - "vkey": "5713f52a3a645544b4f0ac13e31748a39174629a980dfcc929cbe5fc2dfad932" - }, - { - "vkey": "3828e0d21d50b612c5b9b7566237f4866208a156aef4978bfa50377955503376" - }, - { - "vkey": "a7e2a726c70bdab355484c698c5e849b43e08fcce2d190c4aba918d5f98d8a7d" - }, - { - "vkey": "b38011b462f728d702cd1a4e2b85897639ba0edf55368616ec1fcc22db29772e" - }, - { - "vkey": "a442e532d35a5ab6c9818aea7e3f2ffc56de3fe1edd71bf263aa389df3c07b17" - } - ], - "seq": 6, - "tag": "IgnoredHeadInitializing", - "timestamp": "1864-05-07T13:28:07.654185493527Z" - }, - { - "headId": "04080100050301040301080600000601", - "seq": 1, - "tag": "HeadIsOpen", - "timestamp": "1864-05-08T14:00:18.862266763127Z", - "utxo": { - "0403060207050306080307010700020402080203040401000301070402040706#48": { - "address": "2RhQhCGqYPDqBCK7cfwS1won6KbeMS1ybyxRm6xYhHYmwoEAyt7YE82c4f86aacv2RdoDsNRromkVLRoyCCujZpSJKVM3B4skY6rWeqGNaPnPY", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8202838200581c4b6d49c1c3a5d4b4a3c2a19e16cc86e5a4da3bdd82c043c9b693ee278200581c5805c166f8281654240c7c20a7ebad2cc7ab8c4b27c71d6ad52ddb148202828202808201838200581c2b26667acd3d00e8307867f95bc1a32b3b777db1da32fa16224515548200581c924bba613b915f84fc09ccbe84cd931d8de53855a1a9b220c2373ef38200581c07a803fd7effb8ce6b6d0cd0e04dfed6a6b550dcee23f6b92c7cc70d", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "37": 9206411125761719868 - }, - "lovelace": 8302667995376302089 - } - }, - "0500050004070303010804060004030105010001060804070102010406020000#3": { - "address": "2RhQhCGqYPDpAjpUmjXz4B1jhZtgW8x8m1Pew2Bee6xqBdScgLG3mckRESUVeSCdaLP8r8oGNffoAmYf3BwykgYawdHgA6AwQy4HLq6MWuFpYs", - "datum": null, - "datumhash": "1e8ded7b62a08c4fae39e4534b2ec2935ebb1c7558b7467b00eb7aeb1a13116d", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "dbc7bfca4e4a317858df04814f1de6ccf0bfe2d84041449e7b2ec2f8": { - "38": 2 - } - } - }, - "0502040207020008000405030104000606010302040006070601050605080405#99": { - "address": "addr1xywq0ythmavplj2xqt65ex7jpw7gxrq4tp54wcdzlq26u34rw0euavwcvg58gy40eh65pf4yw78elmjgcuqj2q67u36qsdpc83", - "datum": null, - "datumhash": "a9f4df6cfd90bc83b299aaf9c97164d49c32d465ab1703f7989860e0c587a91c", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "4746010000220011", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "c9226b74a23dcb713e01d53ff3e849eb8697de5d85ea3910d8491419": { - "32": 1 - }, - "lovelace": 7238711644070455488 - } - }, - "0705060401000205000106070503020802000408050302060604040207000807#1": { - "address": "addr_test1yppsgjsggnuakc2tphrxy6rudhh4yjsas5ne2uk3ykvawvghskty3s0t8wuaqee34gutgxxqva7x9yk6jv2p7s2ucqvsa0qrez", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581cf2f0e2c26590cb6d98775cd94cedc37a787e5e7ca72759a2b668d418", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "6c73ab38c26981a7f018d2ef8c4843fa91a499b14eae0f36f4aaef95": { - "35": 1 - } - } - } - } - }, - { - "headId": "06000706020601060302070404000803", - "seq": 6, - "tag": "CommitFinalized", - "theDeposit": "0807060108050603000206010502030402010805040604010703050202030606", - "timestamp": "1864-05-05T09:50:21.920496519771Z" - }, - { - "contestationDeadline": "1864-05-09T22:10:57.806721845758Z", - "headId": "03000002050803020106020205080107", - "seq": 2, - "snapshotNumber": 0, - "tag": "HeadIsClosed", - "timestamp": "1864-05-05T23:48:09.023307512135Z" - }, - { - "headId": "02050300020205040401000801060105", - "seq": 4, - "tag": "ReadyToFanout", - "timestamp": "1864-05-12T06:01:20.303683055099Z" - }, - { - "decommitTxId": "0805050705040200040306050306030605030407070602040202060800060205", - "headId": "05000507010003030603020306010403", - "seq": 4, - "tag": "DecommitApproved", - "timestamp": "1864-05-13T01:02:01.439480471674Z", - "utxoToDecommit": { - "0203020003080006020406010601000000080806030002060805030608080005#14": { - "address": "addr1yygtrfa6a8rxeqpw55q3w684uv630gtqwfsw9nef565mz9vzvn3qvyae8pp2rek59jk6magcp39h203gp7672dudcljsr4p3mv", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "list": [ - { - "list": [ - { - "int": 4 - }, - { - "int": 2 - }, - { - "bytes": "5276" - }, - { - "bytes": "" - }, - { - "bytes": "b9a5" - } - ] - }, - { - "list": [ - { - "int": -4 - }, - { - "int": 0 - }, - { - "int": 5 - } - ] - }, - { - "list": [ - { - "bytes": "5129143c" - }, - { - "bytes": "36757db3" - }, - { - "bytes": "af94519d" - }, - { - "int": 1 - }, - { - "bytes": "40f255" - } - ] - }, - { - "list": [ - { - "bytes": "fc8e" - }, - { - "bytes": "b92933" - }, - { - "bytes": "" - }, - { - "int": 3 - }, - { - "bytes": "23" - } - ] - }, - { - "constructor": 0, - "fields": [ - { - "int": 1 - }, - { - "int": 4 - } - ] - } - ] - }, - "v": { - "list": [ - { - "int": -4 - } - ] - } - }, - { - "k": { - "bytes": "76087692" - }, - "v": { - "map": [ - { - "k": { - "int": -5 - }, - "v": { - "map": [] - } - } - ] - } - }, - { - "k": { - "bytes": "027d" - }, - "v": { - "int": 4 - } - }, - { - "k": { - "bytes": "6d345c" - }, - "v": { - "constructor": 0, - "fields": [ - { - "map": [ - { - "k": { - "int": -3 - }, - "v": { - "int": -2 - } - }, - { - "k": { - "int": 4 - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "bytes": "0d32" - }, - "v": { - "bytes": "87" - } - } - ] - } - ] - } - }, - { - "k": { - "constructor": 2, - "fields": [ - { - "list": [ - { - "int": 1 - } - ] - }, - { - "bytes": "f293b9" - }, - { - "list": [ - { - "bytes": "3a304b" - }, - { - "int": -2 - }, - { - "int": -4 - } - ] - }, - { - "constructor": 5, - "fields": [ - { - "int": 4 - } - ] - }, - { - "list": [ - { - "int": -3 - }, - { - "int": 1 - } - ] - } - ] - }, - "v": { - "bytes": "d094" - } - } - ] - }, - "inlineDatumRaw": "a59f9f04024252764042b9a5ff9f230005ff9f445129143c4436757db344af94519d014340f255ff9f42fc8e43b9293340034123ffd8799f0104ffff9f23ff4476087692a124a042027d04436d345cd8799fa322210440420d324187ffd87b9f9f01ff43f293b99f433a304b2123ffd87e9f04ff9f2201ffff42d094", - "inlineDatumhash": "509f47cd011227c994bfb1e86e61d22527529f075858dd7ff5be4d3de17544b6", - "referenceScript": { - "script": { - "cborHex": "830301818200581c24fa6529fc379ff71915b7ecfa55897dee6423dafa81b2d71595ebe0", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "f64c5b": 4667824245511152280 - } - } - }, - "0203030405050605050001010300050408050102070505040006050007010204#6": { - "address": "addr1qy7dfm9frza46kpwlrxsj99juz080d0w3llu4d3w8tspw6hahptmhwy0d9r73r3ndv3v0xec93rvxt8z48047dc6muqswzny9a", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "bytes": "4718" - }, - "v": { - "constructor": 0, - "fields": [ - { - "bytes": "d1ccf7" - }, - { - "constructor": 2, - "fields": [ - { - "bytes": "f571e8c1" - }, - { - "int": 3 - } - ] - }, - { - "list": [] - }, - { - "int": -1 - }, - { - "int": -4 - } - ] - } - }, - { - "k": { - "int": -2 - }, - "v": { - "int": -1 - } - } - ] - }, - "inlineDatumRaw": "a2424718d8799f43d1ccf7d87b9f44f571e8c103ff802023ff2120", - "inlineDatumhash": "2b7c3224cb8fa4b88a4cf89fb4291d406aca1521dd461d31698a27972d2e8a9e", - "referenceScript": null, - "value": { - "d5734ae9237840d17814f4c4ea45eb882cfb4fe782f79819f74df7fc": { - "4de5199595ed92251e363f10beb8b3a30a13d5fca4696f40d80b838b43": 8197087138024594318 - } - } - }, - "0205020601060205000107060001030803060400050506000201070300050101#93": { - "address": "addr_test1xp8flly0ze6hcma32lvxtjvl6t5sfng5tjhu84jd5vy2ervd7yd5wjnvk608cdd0en8jq95laelst7yfjh2zcj4pev5sznku4a", - "datum": null, - "datumhash": "29b42eda395d6ded0b42ec3cf3a93f3653914b413564280d33937b0bb748b35a", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "2db8410d969b6ad6b6969703c77ebf6c44061aa51c5d6ceba46557e2": { - "f3936666071182a929fe0318aeea40517d2fdb5bf96c996ffb": 5564094827352581771 - }, - "lovelace": 2033627175386432895 - } - }, - "0404050608050207050501040203020507020108030301070403050203030108#43": { - "address": "addr_test1yp97rt7h7f8fckch6upty2ftgavrakfs75nyf0wdrawdpgn3rnysanjfhk7uw5fxtdtfkavwej4mk7g0q6nxeypww7pq597w8x", - "datum": null, - "datumhash": "85c54e500a2e59d875166e10e8437947abaf7d22c67d1f3e5840f749547cc6c5", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV3" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV3" - }, - "value": { - "c7214c8ac528002328b85ccf301aaf0eb7acec1b4610e86814d3f755": { - "33": 935584095780249277 - }, - "lovelace": 2844548076756182392 - } - }, - "0600000308020204070606050805040603020207050000070400010706030206#41": { - "address": "addr_test1qzuan5tm3a88gqlrn9j9na69kcmnrrysv8cfa2ssmwwp2y725y7rq8zwjjpxc86lygshwppftaz00qyk7pz02wwvsnns0zkysr", - "datum": null, - "datumhash": "6fd06c8865d3836fe22a3cd9fd554788eeaee37f9abc6acb2ecad1e903799faa", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581c79fab5723e54f4675a6a7cf5d59d2a23d7a81f5e87942f696b70044b", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "ff992bfe0b4a005732c77dd0ae6afde671e191f2f70dc967c0f25a72": { - "006d12135ddb837f8785": 1 - } - } - }, - "0704030602040804080108040207040203000202030307080208010608040207#39": { - "address": "addr_test1xzzx27e7um24s3pd4hmxv6pzpku5t03gcdt8d29vvmnx4qnsu3svl8gcx32ze2swpv9pzmek5yfn785nahwsr5acz7csh8f62c", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8303018182018382028083030080830300818200581ce861eab033d3abfe84e1b4a06825c57f9ce15f9424eec7c884004fbc", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "68c991f9c4d2b0068bf47c19b9e813525cd62d90e808e518e5cd0b9a": { - "dde14615531497d9c5012d978fa0851280be04d8a61329bba2e6": 1 - }, - "lovelace": 2644013850198585051 - } - } - } - }, - { - "headId": "01030208040202020301060200070205", - "seq": 1, - "tag": "HeadIsOpen", - "timestamp": "1864-05-11T00:16:18.622118496826Z", - "utxo": { - "0005040202020000060604020801040207010403000002040005030307050605#42": { - "address": "addr1x8tpuyvdjuwdqxx4h55r57whwjs0sll0tthk8v8a4se8p2wlj6ltqt3e8gfdsev0f0xwlycga4wrerqnqlesrpalxehsjqc8ju", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022200101", - "description": "", - "type": "PlutusScriptV3" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV3" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "32": 7233233433603487349 - } - } - }, - "0203080001060403040500050306080500030401020707020006000807080806#44": { - "address": "addr_test1vqx9mazqh40at6r39luq56ckg9myd2lpte7mvx7ph82hlyqquf6nk", - "datum": null, - "datumhash": "a4c9066b65d055e1880be076555af78ec5ac04c6d5f66fddb8f8ec1a8db1df6c", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8201818201838202808200581c4abed918f7107d2d871931b291adae2241d8464d7afae73d457a9c10830301818200581c35302eedabb590ff046d11f49c28fee1e03ba96fd35aa4bd968eec61", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "b0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165": { - "f3e746f25ae11d34281b7affe2c2490b602e00": 1 - }, - "lovelace": 3070946310901051781 - } - }, - "0808040802080704050703020105040706050101080704060503020607000608#80": { - "address": "EqGAuA8vHnNvYbEFB6H8mLAuaKu2S6TbUsNSv52DhFBhqiy24cu288qy896Ru2TBR3i1bJqFSe3Ms4XPyLN1S96rjXjS74LDNF5U94bxULq6FtWPXwAPq45", - "datum": null, - "inlineDatum": { - "bytes": "753711" - }, - "inlineDatumRaw": "43753711", - "inlineDatumhash": "40cd9e203a975cbeafb15b8d911f80417d05c7fd2965186ffe0845f98c04b88e", - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV2" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV2" - }, - "value": { - "2db8410d969b6ad6b6969703c77ebf6c44061aa51c5d6ceba46557e2": { - "0a": 3753678310854006954 - }, - "lovelace": 3483493161276738573 - } - } - } - }, - { - "decommitTxId": "0506040806060108040608020304020006080206080803050403070105000402", - "headId": "07020206030706010703020505020705", - "seq": 0, - "tag": "DecommitApproved", - "timestamp": "1864-05-12T08:29:00.767372872276Z", - "utxoToDecommit": {} - }, - { - "peer": "tg", - "seq": 4, - "tag": "PeerDisconnected", - "timestamp": "1864-05-15T04:18:28.982024163195Z" - }, - { - "ourVersion": 4, - "remoteHost": { - "hostname": "0.0.0.8", - "port": 7 - }, - "seq": 4, - "tag": "PeerHandshakeFailure", - "theirVersions": [], - "timestamp": "1864-05-10T09:22:18.467477366189Z" - }, - { - "peer": "xm", - "seq": 5, - "tag": "PeerDisconnected", - "timestamp": "1864-05-07T11:55:56.267903247906Z" - }, - { - "ourVersion": 5, - "remoteHost": { - "hostname": "0.0.0.1", - "port": 0 - }, - "seq": 2, - "tag": "PeerHandshakeFailure", - "theirVersions": [ - 3, - 3 - ], - "timestamp": "1864-05-05T06:07:14.967728528812Z" - }, - { - "contestationDeadline": "1864-05-11T06:46:42.945806371528Z", - "headId": "01080307000106070304060001000104", - "seq": 5, - "snapshotNumber": 6, - "tag": "HeadIsContested", - "timestamp": "1864-05-07T18:09:39.488368908379Z" - }, - { - "headId": "03050206020102040101080607040006", - "seq": 2, - "tag": "ReadyToFanout", - "timestamp": "1864-05-03T02:18:36.385906865978Z" - }, - { - "headId": "07060304080603050502070704000701", - "seq": 0, - "tag": "CommitApproved", - "timestamp": "1864-05-07T12:09:41.097901263026Z", - "utxoToCommit": {} - }, - { - "headId": "01010005040102050602040404010505", - "seq": 5, - "tag": "HeadIsOpen", - "timestamp": "1864-05-06T18:04:54.591535157269Z", - "utxo": { - "0002050102070500070006070004080606080303080501080008080504060708#25": { - "address": "2RhQhCGqYPDorTSpyJK6Ee1vTNx24dyNfeqWaRGAy4gZzHVqpHq5R1mS4tsF9qsCAJZw77UxqJnjFhysJvSDjV6hw6XyDbUWYeeS63sW3Mgxf3", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581cd8d849d62898aaccf76689053bc6bd80baf843c827c1b09b7627cc00", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "c637a7924599e1a75df4d2e86ba96a3537": 1 - } - } - }, - "0100070803000402020406000606020002080205020805000200080808060103#70": { - "address": "addr_test1qrvghd0g59fsqk0jad4f4shka8yhfzrverujstkpj29jwsw0yxznz8ak4lhur750dtfhjgk6mw43zgf9nrpkpqssnv8sz0pg7d", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "bytes": "79d97d" - }, - "v": { - "int": -5 - } - } - ] - }, - "inlineDatumRaw": "a14379d97d24", - "inlineDatumhash": "a28aa159c314ba48a79c930872eb5363b1aaab31e247bf81b29867b38f063390", - "referenceScript": { - "script": { - "cborHex": "82028482028483030080830300808201838200581ce0b89337b335f5a0bcb7d163fe2da00ae1b4c7f9577abe38999f91b48200581cf5132f23e2e85b16aadd39866c6ec75378873e368302571a639458378200581c0f08400aacb79123b9dc4acdc3328b7a695c8d181ceb3ba19d63bc0d830301828200581ce9f613cf85c7364544da3f440ead644a0edac70db7785e1db743bd3f8200581c8e4fc1b119c5c0053e9628a893bd100f7d48aad2b986edbd45b80a7d8201828202828200581c6266a52908ecd001388728ff83a720ad02e9f2327838abf90c521bae8200581c961f1bd91b195188a7d05cb9754360404c394c2378a2bae32f7303e3830302828200581cbcf0ac03bcbf4ff638c38ff07a81fda98885b3e2fc10440da3dc83928200581cbd011b400683399d0e43d4413bf818d327bbd8a1bbb4799aba26171c830300818200581c5cd96ef37b0edc14531620a3cc7d19076e6cd7cc0b8f9d633c2329d2820280", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "105a8f1bb56444cacc86378c95421aceeb326b0fb7743e493eb82fd5": { - "36": 6922759057580970674 - }, - "lovelace": 2224943196122486491 - } - }, - "0205080102080503030701050001070601070107040706040600020202030001#71": { - "address": "addr1vxqlagnpwx7gll5wsw4urg0qr9grhen82kgzdydl6k8rvlcz9pwwg", - "datum": null, - "datumhash": "1d388fb6eee5c43941b1743858f9bfa086239aac2371af49dbbe1e774681d004", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "536e2c6e8f1feebbb128706e9557de85919d2ce6ff737f5e38c0840c": { - "36": 1 - }, - "lovelace": 9034400032758279527 - } - }, - "0405030706030205050000050603080403020403020603020701020805070705#49": { - "address": "EqGAuA8vHnNnmtrFug91zAZEx7pA2f6Dbg3Mt3Dzts5VuqszQWsUbEo4dZKBqnMxGQx9BFwogriVJroHVCqJ5RPnmBqJK6DH5KixREspWxbS4GYUrnppR6B", - "datum": null, - "datumhash": "e35d0eace0795a4d8db45879c81f991a31905b510f116daed7870b2439340227", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820501", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "c93389bb6160": 8083390534122880445 - }, - "lovelace": 6463465340661552029 - } - }, - "0408030304080108000605070107070108070808080200020700070306040107#45": { - "address": "EqGAuA8vHnNhmQF1yfTA7vjmrsPzegFzdVREegZzDf2dU5ritSuYxkVRuMfRoPmmucvhWjVJQnqmhD753RKZCc8NfiuXoLASyzoHTffQXZjb2kARJUuvopc", - "datum": null, - "datumhash": "5c784822378ed1e22d0a1cba21ee17a948f53f42caf3c4bf5e998a1e1edb3777", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "36ce23f91d1bc4c4830435fe80b960440eb603358203f183774b576e": { - "6a8fa84e430b181a518a93a434f6": 5054153599235827919 - } - } - } - } - }, - { - "input": "𦁔U𬈦", - "reason": "yM", - "seq": 0, - "tag": "InvalidInput", - "timestamp": "1864-05-06T11:05:00.689961495503Z" - }, - { - "decommitTxId": "0708030207060605030700000402070601000500040000000007060202080000", - "headId": "02060008080206050302020802020306", - "seq": 0, - "tag": "DecommitApproved", - "timestamp": "1864-05-07T22:55:55.776433371473Z", - "utxoToDecommit": { - "0101070303000508020303010604040204000107070806000005070805040108#30": { - "address": "addr_test1qr2fudxgph7y3682cxkwzzrrda7qz5lts3rxxtv0zuarumsdfm605ul5ztl0u204ea95znanhwsplpu57d24d4e2wyequw4wvu", - "datum": null, - "datumhash": "d0aca62e0ab4f4080226c743004892b4e1245407a92836034fb3baa9893a6a49", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820281830302848200581cc99a2dfb4236ccf4c55529a7c413c85b414a1a3a8ac09ca66fd6131b830303838200581c51130ab4c510b50d98c5de82652e94b5baf093689d572b1a852553c58200581c784f505f6465e7d35eacfa5f4c9f86929d635975676ec2e1251ba33e8200581c7130861c0ae1051f823b9d183e7f337997e27a2695ea2f48310908ab8202828200581c0664791bb0b14754eb1c3057c9670d29ade397f24dbd1073df7f774f8200581c167c6ee47c9180e16029979830b1257e6b6c16ec8ebb54e5ea95c2388200581ca654e72793ff631fdded60dc3d7e88a86e937e81559d5b826085b5ea", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4a1c412d8e2b3015a7fb7d382808fb7cb721bf93a56e8bb6661cdebe": { - "33": 1831784255321455691 - }, - "lovelace": 919265135781478072 - } - }, - "0305000701030504030705030505000103050804070707010407050108060401#41": { - "address": "addr_test1yrqcqa45dl45z4l8rs4368n38q4shw03l27ntdyl0qwfld2ct3usflrutc5u5jxnuy505zs2wnjnwdnvzwvng79yaavqppg7gj", - "datum": null, - "inlineDatum": { - "bytes": "e2f227" - }, - "inlineDatumRaw": "43e2f227", - "inlineDatumhash": "4f0b0978ef5c9bd3c4debef91f8bf01fedfb4b407d1a0a2fce7b122ae3c3d039", - "referenceScript": { - "script": { - "cborHex": "8200581c503ec8dd6b77d1a3cc6ff25ed66d0cb738fb3b353c9b910b4e8ee653", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "a15874ad6b8d9e4d6890bc5e04e608d648640a0db797f348825dad50": { - "37b396e6925e30424aa44eb53edcb617aff51be332884bcd4b261db89d9d27": 2 - } - } - }, - "0307000105010708010801080004070707060402040807070307030606080607#48": { - "address": "addr1yx5rw00cxllpf8xwudfpsaljavm4e0zlpd8aqc5ldlgwfmyfpgkclzt7duc7p0edefh0fhzmaz7lsk652yfmxnpwwg5sfhm5f7", - "datum": null, - "inlineDatum": { - "int": 4 - }, - "inlineDatumRaw": "04", - "inlineDatumhash": "642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342", - "referenceScript": { - "script": { - "cborHex": "46450100002261", - "description": "", - "type": "PlutusScriptV3" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV3" - }, - "value": { - "6a0af610b2346968fd6d22f8b5b1d7a10144deea2a936e1961a2cc89": { - "e9bae1d63d43b8": 448706416300258611 - }, - "lovelace": 3804797161367376271 - } - }, - "0407010702020805040502040708040503010107070405010607080207070502#45": { - "address": "2cWKMJemoBakqspfzL4dfGSBGXF9eeKnJ1odZk1aFhx9HmLbCoNh4jHSioZAJa79JePWF", - "datum": null, - "datumhash": "7e2bb76a20342f67e9a7919582b7c6a06849c308339d61c9e1d5ba93b7d71bd0", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820182830300808202818201848200581c6c02bf6616e2332b2da8433c95f1e528a6f6d87fb80591c5355750f88200581c31296f0e8799dd70fecc9d58c81dd1c5bf6d7697435c668bc28f53198200581c5deed708bee18f152de29ceec3c8e7f127b023741633d7427b3834d28200581c15db1735fa1c6ff5013e3b5bef34f02d60120c48bc7631a5c6f04da6", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "c6ee0347e6112d13bee1f80a99674434bd18d3e721e8244f5dc32d4f": { - "bcdd1c7e33fddfe60648374227a5d95a813c": 1 - }, - "lovelace": 2637519226476516105 - } - }, - "0705070403070003070402070607040101000003040403050406070003040502#61": { - "address": "addr1y9y57vc9gtya506ugluqm35xa737z7evlegqaakqgcpku4tsx0q426k293lpuzvpakwu3vfjh7nqq44x5ght5hm9qqgsgn30q0", - "datum": null, - "datumhash": "6bd567277078146b716df8f29944c27cf0ec4a53d628fe2fc2d26e6ba7002f0e", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8200581cc962a5987f12db821c6ea3fc450a1061ed72c834bd3a36a4890d60cb", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "8db4d87a7b5aa45591c103cfcd22d9dc0581fcd8d3b1f795193a258c": { - "3fdaa641cc0be975": 1 - } - } - } - } - }, - { - "headId": "05010201030607060003010703030800", - "recoveredTxId": "0501050604080601030803060702020105070005050403020804050502050305", - "recoveredUTxO": { - "0106000107070000080804010208030006050500070406020204030104050400#8": { - "address": "addr_test1zrjyd97ydgp89p3z6k0wsxqf92saqsac0dh4t99pez6qp95yhyzsuhtujhtysgdrc44nm2gu7d0y09uf6g3gt6z07mssal0rnx", - "datum": null, - "inlineDatum": { - "bytes": "" - }, - "inlineDatumRaw": "40", - "inlineDatumhash": "39df024ac52722fe8ae4c1a8740e4c5624a38c3820e504a059aae8728421f8bd", - "referenceScript": null, - "value": { - "0db48d19c2b48dcc3b4e0f949e8b60b711efb4ba3e2077fdce95b8dc": { - "35": 176428782084212364 - }, - "lovelace": 3564185472575376322 - } - }, - "0107050104080507020204030704040407030406040802030200070502030807#83": { - "address": "addr_test1xr5dw3gydtvqrc6jtnz8ne97k99x56x4shrfcmrhed55d5yf65jrmdpt5js40qsyckh3xyx6r83rw5amrnf5e65wxxps8usem4", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "constructor": 5, - "fields": [ - { - "bytes": "dd41" - }, - { - "constructor": 1, - "fields": [ - { - "int": 5 - }, - { - "int": 5 - }, - { - "bytes": "" - } - ] - } - ] - }, - "v": { - "bytes": "40aa4e" - } - }, - { - "k": { - "constructor": 3, - "fields": [] - }, - "v": { - "int": 3 - } - }, - { - "k": { - "list": [ - { - "bytes": "" - }, - { - "bytes": "32" - }, - { - "map": [ - { - "k": { - "int": 5 - }, - "v": { - "bytes": "1fd0918e" - } - }, - { - "k": { - "int": -5 - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "int": 1 - }, - "v": { - "int": -3 - } - }, - { - "k": { - "int": 2 - }, - "v": { - "bytes": "56" - } - }, - { - "k": { - "bytes": "6f6802" - }, - "v": { - "bytes": "0a17e109" - } - } - ] - }, - { - "int": 0 - } - ] - }, - "v": { - "list": [ - { - "constructor": 3, - "fields": [] - }, - { - "map": [ - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "3c28f1fb" - } - } - ] - } - ] - } - } - ] - }, - "inlineDatumRaw": "a3d87e9f42dd41d87a9f050540ffff4340aa4ed87c80039f404132a505441fd0918e24400122024156436f6802440a17e10900ff9fd87c80a140443c28f1fbff", - "inlineDatumhash": "cdd975102a342d7539a0ae8f2c2a532c039ab2c431fc499eee2861cf77e42206", - "referenceScript": { - "script": { - "cborHex": "8202828202818202818200581cda19e7ea49d8669c36158130f744d08cdb46376deabf2e9d6cb452368201848202828200581cfad18a626301173b5baf176ccfc949f5a365fb9a2278fbec10541f5a8200581c1e5062b8a2d20c5d0ef6376174cee5abe65268d39fc5141e4f55d8088201818200581c8986e079034936ef4eef3af0cf56174ed8ec455cd38290a716806ce88202808201818200581c6ba5be4e4dbbe2d21fc1fd09e23cae74f924e50d5890139dae0f5485", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "b746b4339b205046bdd1367e0ece21ecbfbd84885f44f01022e8160f": { - "30": 1 - }, - "lovelace": 5567215411735501275 - } - }, - "0602040305010806040503030407000201010003000303070608070604050503#50": { - "address": "addr_test1zzdutdkm9vcf9f0qmj5ly5ddumaejztqq09d25kj4l2xn5fv5r0rutu0zmm04rvlzaew2rwhs4zt98jxe6xdextzsfjqd22nfd", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "82018383030082830303838200581cd2380f31b81c47dfe323fdb69ed2aabe8fb584f2f23da91ced78f4068200581ccc660c00842d610c9572ddf9a908bd6da3f752453c5120026fc3e37c8200581cbc9464eace9e19ebd219377bc0db552fb5cf86514c0999a02e61895d8200581cdadca2c815987177eba5a858820694b799b66c63a03d13034bdbf92a8201848201828200581c1a3d137cf5bcfd69fe2e44dc7848ea46e1cc519af0bbe4d6af06443c8200581c1264af66af53cf73c5ed0317774182cc7d98466ce1908c45ac90f9cb8200581c2d44a5da54a27d0ee8ce5b96f3ac6d71bcfb69580e874352e906ce60820180830303848200581cabf7b83ccf28fed877cfb59fb20dee6454cc4d9fdbb520749a9878bb8200581c0ea1f908ee9cef6d1ad3032c3a174e6945ea239291495355a60abdcd8200581c3dbf4482b9ac98bcd92637397a51643645d16a0b0cb20f4f4c605f108200581cf6ec48d12ce49ef8e6df2a828031b3e931a18d9a1c81884a11e255098200581ca0f07dbe65991718382ec149685c03c4dc8e02b8b2f60185b2ba5495", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "2db8410d969b6ad6b6969703c77ebf6c44061aa51c5d6ceba46557e2": { - "16f1b1454843efeeb8c1f5": 1 - }, - "lovelace": 2362165080858523522 - } - } - }, - "seq": 0, - "tag": "CommitRecovered", - "timestamp": "1864-05-08T06:14:51.259812761589Z" - }, - { - "clientInput": { - "tag": "Close" - }, - "seq": 4, - "state": { - "contents": { - "chainState": { - "recordedAt": null, - "spendableUTxO": { - "0000000303030201060308050803080604020800030808020404070408010407#2": { - "address": "addr_test1vpz5a337eezgnet8dq6v9h98au2qeqn49nqdfervdkncqnqpspxsu", - "datum": null, - "datumhash": "170f4827385546df1e85a3ccc32668464e8680cdc7077ed269a0f1f309690869", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820410", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "1c7b24f5329f34fc500bf0b32dd1296d0edb275f06eb3fbf0ecbe124": { - "5e790d622498a054c3": 7775661153818099133 - } - } - }, - "0308020405070504080603010101020505060405080201030302050002040004#77": { - "address": "addr_test1qp907receh8czjasra5sv48u4dpw3cvlvxwe4qdct4u4kfpydjgtv2u6q92v6xmld3ps95wjpfnhgkjx2u7azgv0qljsf0llq3", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8201848200581caba93328282ebecc1a0e33f7955cf2d10de715c00ea8bb58f69c9fb48200581c2007eeb140a08b91037e4a9fb20cc2972e33dc7ed2d76fd61799d74b8200581ccc37a07cd7a233f5affb12518201663d9e69c72f32fade1cff2b17c68200581ccd27814f3331f3f1086833f11c85d55ba4ad75fde615d03044184017", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "677b69e263d2fb381c5b0ac282baf574853214a3b1f295ecc1b824d9": { - "ed040642b0a0db41d3a983b24d620f425060f19bbd": 1 - }, - "lovelace": 6377145547469603734 - } - }, - "0404050805000406010607030102020207030801030807030605010300070602#4": { - "address": "addr1z94gt4l4upter7rksq365tkqhpcqyj23nwa7fyrg36tt7kse2dm5f9hshk9aajv3ktf39rgxu76z9pxcymfv00nwg26sp7lpqp", - "datum": null, - "inlineDatum": { - "bytes": "93" - }, - "inlineDatumRaw": "4193", - "inlineDatumhash": "0cbac79a38b379aa68d1a89fc02ede73f4007d5f2f985ed82d78ef219c8ffb78", - "referenceScript": { - "script": { - "cborHex": "8201828200581c986ca06f5453a6c0639a271c7af719e2660cd1a7a6426a8d87ba79af830300828200581ca41db2726e4c566a8008646c3c7228fbf493b99b9a7970bc097f32898201828200581c12eb3d74adc97865aad7284915622a1f5ff77e3dda633f8332f909ef8200581ce085b01595893ecd000e12f775078eec74a5a690a2c06b053d452230", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "6e7cac469f9dc3c5548745e0bb0e429a75b6c28fae54bcf2a1249d25": { - "35": 1 - }, - "lovelace": 3532494753614363474 - } - } - } - }, - "confirmedSnapshot": { - "signatures": { - "multiSignature": [ - "9caf2291b1c64283c7553b0b676f031ab62aad71c8d32d095914aeaa8539945ff275f42a25b33db70cf025d08dd778d262945ced03a6b9a29ff44e72c7984103", - "24ee6fd54352235de8a486ae57da096c17fc76e34a0d94c3e02cd0dc15bf7b81dab2255a98b8c4d4229791d2bca42703936dbef77ab6ea6bbce8bf740eed1e0e" - ] - }, - "snapshot": { - "confirmed": [], - "headId": "06070806020503020507060702000803", - "number": 5, - "utxo": { - "0205020802070008010405080306050408040207040601070804030405080303#74": { - "address": "addr1q9lfcvc9j97stsrnurdydenkwcrd67hq5lq5myn0p0tyyftn4gscdvffkc079la3dlcc6mk4jqd354xcw0hexykukh5qrut8zp", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "8de0dadf": 1740819548977437522 - } - } - }, - "0205050201080106080804060306060308020201030400000800030202020700#80": { - "address": "addr1zyauynn7pad2mj2ceqt6ur855w9q4txkpytk9ffmlljul94rlgqn5s4devm0g80wzh2xgtzf5xg0wc9tna0e4hp25rpsffw9gs", - "datum": null, - "inlineDatum": { - "bytes": "2380685b" - }, - "inlineDatumRaw": "442380685b", - "inlineDatumhash": "0b726fb621972982e33cfb71e2b063a5da706f0092cdb353bf825048a0a84edc", - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV3" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV3" - }, - "value": { - "b0c53e2bf180858da4b64eb5598c5615bba7d723d2b604a83b7f9165": { - "754f28a3fdc054c6dfd8a27a1b29d5c401d0": 6283769710320500492 - }, - "lovelace": 5740113361819870278 - } - }, - "0402040503050303070408030600080707050005010607040108050003040108#25": { - "address": "addr_test1yqxrnkvhl9sl9q68xdjw4zq06fjp74lcmrc5c4y52jmyvmqcm2vv0l984q59vekk7rnqnts772ghzpar5ddj0k9g2w7snvvcpa", - "datum": null, - "inlineDatum": { - "constructor": 3, - "fields": [ - { - "constructor": 1, - "fields": [ - { - "list": [ - { - "bytes": "47" - }, - { - "int": 4 - }, - { - "int": -1 - }, - { - "bytes": "" - } - ] - }, - { - "bytes": "4e891b2e" - }, - { - "list": [ - { - "bytes": "12a6" - } - ] - }, - { - "int": -1 - }, - { - "bytes": "ecac67" - } - ] - }, - { - "constructor": 2, - "fields": [] - }, - { - "bytes": "eaddd6" - }, - { - "list": [ - { - "constructor": 4, - "fields": [ - { - "int": 1 - }, - { - "bytes": "5671c8" - }, - { - "bytes": "020f81a7" - }, - { - "bytes": "0e" - } - ] - }, - { - "map": [ - { - "k": { - "bytes": "31ff6611" - }, - "v": { - "int": -5 - } - }, - { - "k": { - "int": 4 - }, - "v": { - "bytes": "e9dc" - } - }, - { - "k": { - "int": 5 - }, - "v": { - "int": -1 - } - } - ] - } - ] - }, - { - "constructor": 4, - "fields": [ - { - "int": -1 - }, - { - "list": [ - { - "bytes": "3df0031c" - }, - { - "bytes": "" - }, - { - "bytes": "ce02dd" - } - ] - }, - { - "list": [ - { - "bytes": "" - }, - { - "int": 1 - }, - { - "int": -3 - } - ] - }, - { - "bytes": "44b9" - } - ] - } - ] - }, - "inlineDatumRaw": "d87c9fd87a9f9f4147042040ff444e891b2e9f4212a6ff2043ecac67ffd87b8043eaddd69fd87d9f01435671c844020f81a7410effa34431ff6611240442e9dc0520ffd87d9f209f443df0031c4043ce02ddff9f400122ff4244b9ffff", - "inlineDatumhash": "296cc5ab192626352a16ee07ea6c6542e2915dcd559f5029b24e4ef9ab34017d", - "referenceScript": null, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "ea779d": 1 - } - } - }, - "0605070808050200010500070006060103060104060702010602030803070307#64": { - "address": "addr1yxlw5nlfnev57ak794mmev3383amtcrsy558w8t5c4jm55u9ax7uw785cp6guxvk2nh60xu7mqhdwmfx22runew0e5xqegdzyz", - "datum": null, - "inlineDatum": { - "bytes": "ef7d85db" - }, - "inlineDatumRaw": "44ef7d85db", - "inlineDatumhash": "d20ba7c2285afa39ceb1287427791285230f8eab24a0218e00cbf7253a11577c", - "referenceScript": { - "script": { - "cborHex": "8200581cccbab040b5e3d6d1f034e3f3912386976fa588ed39cd005e1dbb9764", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "4d50a11e297e7783383bf06dd6e4e481230323bd96cd8b8d9ee3888d": { - "dad5a84643400420e1e1ac": 5963657745212011584 - } - } - }, - "0702040407060502010601080302040608080707040506020402000204040108#86": { - "address": "addr_test1wqhemd34kxea73jrq495tay47y25rwtqjsx5cvep67dzy6s6gkg37", - "datum": null, - "datumhash": "6bf2fe4accd3ba516d03e4a91ea76e5674a8ee043aa4f4c09aad54c8c56a2163", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "4a1c412d8e2b3015a7fb7d382808fb7cb721bf93a56e8bb6661cdebe": { - "cb1fedccc5": 1 - }, - "lovelace": 6274219818787957202 - } - } - }, - "utxoToCommit": null, - "utxoToDecommit": { - "0401040603080601020205070403080003000401070103020407080705010305#88": { - "address": "addr1wxh0v45x068v4jqead7tmxxd2nu9v94f9jpc49ukhta2sxslfpatg", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "82028483030184820180830300808200581c76d6edd946a4ea5d04907dfede6a4edb46915a7d921f519a8f3ecdaa830301848200581c8c9300f9b2607ec65694a526742f22bc8bb3edaf767010f4bb9fcbe68200581c15fca747274473662a196c756caca7033dbaf453bd3e45c29dc054dd8200581cf06398a99a87a805129b5660b6637563bfe2470657636af110265b3f8200581cb00b7b9a8923b5c36b8f9896bcf773c64ac87fa90fc136e4a2cce44d8201828201828200581c6b9855837be5034a29c62de2fc5919f31266c3e7416da69a3726478c8200581cf2cf428c270438e016cae3f679d83e08f025e09df2204716a990dec88201848200581c4318f1fb57a30b34c80d00bb2a037113ad443c8e761efc46512b78bd8200581c7a5087e2825d5174061d04cf1d93cc38ed89cbbc7742c6c6da573cc38200581ce90e4f0e3765a4836c74fe74d0da4efb29791a69732188f3755437f08200581cc6173c33b995279fb322ca280f2ad93d5fe992392734440972bbf25a830301828202818200581c4d54441f431d64b214663651ff41fe5982a22c1277f7a1124d8a0dbf820180820180", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "e39b3ffbfc0b388320b2bf53f8ee115e350c4bb879336004a8f9b35f": { - "bce44d68503c37c1": 4843527798023794312 - } - } - }, - "0605080500020407010701080703020505060005000303030305060305020205#46": { - "address": "addr1v8reqk6gg69srara6xf9dasmwtmshlrwgddqycs6qnufk6qmjck3n", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022220011", - "description": "", - "type": "PlutusScriptV1" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV1" - }, - "value": { - "2d725128406dc832eb74c4709aca0512499b3c7b17e00d7cb2e6d1b1": { - "30": 7118621025810478973 - }, - "lovelace": 4812774159035796064 - } - } - }, - "version": 0 - }, - "tag": "ConfirmedSnapshot" - }, - "contestationDeadline": "1864-05-04T10:23:25.771505518467Z", - "headId": "06030402070507080301020608050407", - "headSeed": "02000501030301010803010005040306", - "parameters": { - "contestationPeriod": 38105, - "parties": [ - { - "vkey": "4e8371dc97fed83db3e218b3be814b95ad54d6463b7b795f5a023e323c1fb8b1" - }, - { - "vkey": "16e180a2091e555b606df63e648f53b8dabd2b235aa4b4be9bf886250b4094c1" - }, - { - "vkey": "463c5b80e0ba679e3e667eebcf9174f85b3ab110a5b9d1039d50d5f1b13e2423" - }, - { - "vkey": "050b2d3594ae5298ccaa31a1009edf75a0a069bca20eb9671c3a30b944ec693e" - } - ] - }, - "readyToFanoutSent": false, - "version": 6 - }, - "tag": "Closed" - }, - "tag": "CommandFailed", - "timestamp": "1864-05-05T19:30:47.393764996537Z" - }, - { - "headId": "02020107070202000606020602030607", - "seq": 3, - "tag": "CommitApproved", - "timestamp": "1864-05-03T14:45:00.496997720387Z", - "utxoToCommit": { - "0008060004010106040401060500040008050800020500010506050502080608#16": { - "address": "addr_test1wq86j6jzpsl28wtjuq3tvwmc0u6h70jkf3ss4sw68a959ccsrxjn5", - "datum": null, - "inlineDatum": { - "constructor": 0, - "fields": [ - { - "bytes": "642a02" - }, - { - "list": [ - { - "constructor": 0, - "fields": [ - { - "bytes": "bc56110a" - }, - { - "bytes": "56" - } - ] - }, - { - "constructor": 0, - "fields": [ - { - "bytes": "9f61bad7" - } - ] - }, - { - "list": [ - { - "int": -2 - }, - { - "bytes": "4fbe" - }, - { - "bytes": "96" - }, - { - "int": 0 - } - ] - }, - { - "bytes": "6683" - }, - { - "int": -1 - } - ] - }, - { - "map": [ - { - "k": { - "map": [ - { - "k": { - "bytes": "20cb" - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "int": 1 - }, - "v": { - "int": 3 - } - } - ] - }, - "v": { - "list": [ - { - "int": -3 - }, - { - "bytes": "af" - }, - { - "int": 0 - }, - { - "bytes": "" - }, - { - "int": -4 - } - ] - } - } - ] - } - ] - }, - "inlineDatumRaw": "d8799f43642a029fd8799f44bc56110a4156ffd8799f449f61bad7ff9f21424fbe419600ff42668320ffa1a24220cb4001039f2241af004023ffff", - "inlineDatumhash": "926a394a7e6955b100d969037fd8dc40292e72d160875d77b69de7a04e8c5862", - "referenceScript": { - "script": { - "cborHex": "82040a", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "84e1c90bfb61ad9b0ce6f726fc4266a13c3597f4a9b12e756cb937dc": { - "34": 5601425926056788843 - } - } - }, - "0802080803060607030605030103040700080508040504050703070504060208#45": { - "address": "2RhQhCGqYPDogGRG3z5JXgicFCnhNC98vogFczu4zQQqHGhjdLfyYMXGdQ5ThKy2N76t9xB8ctF5fEjN54vvcoYfaxuBmB4JbokqZuPz81SDQH", - "datum": null, - "datumhash": "a69601d7734701a088735e628f40d9beff1c0b67fde1e9f3022222ba05cd7449", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820504", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "245d5a7a06fe18358242e81281cd5ba9e6abe4efc54e7b659f25abae": { - "42202066b9f9b6f5288ac7": 1 - } - } - } - } - }, - { - "decommitInvalidReason": { - "localUTxO": { - "0107040407050203080207060606030400040706070804000307000006070803#85": { - "address": "addr_test1wqm8j84fckqcs5wwnnup6cc2yq67ta8kg8a8nkx4x9xec7qkm47n3", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "8205181a", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "e1dbbb35d36caa3f3684f09f28910447f38f33a463200bd5": 1360502883579679801 - }, - "lovelace": 5618114912115781373 - } - }, - "0305000405040306030404050502050104030702080804070400080606010004#68": { - "address": "addr1q9fs26z4e0jvynu75wflq4vqzfyrt59zsu7q30krncycw9ddjk0qsgf733x6fnvnk327hnc45tswtnrkyc3k98ul7jwqjp0dr4", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "484701000022200101", - "description": "", - "type": "PlutusScriptV3" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV3" - }, - "value": { - "7107b27e6e52b2eca7aa52957d0139fd8254a789be8e11f63c1178ab": { - "39": 7230973342070961450 - }, - "lovelace": 1851232247113835010 - } - }, - "0601060802080708070100070808030407040006010100050103060008070400#99": { - "address": "2RhQhCGqYPDneMH6P3fErWK5CZ9eorqCifLNdCPkKz1yhxY4U6yYesb1eA9iWJoWkpeHhNyCg3rG4xa5jW5peBZeSUopv3WnXXGS2KPB6g6Pb7", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": null, - "value": { - "45599a781839d0c6e3b7c589f69f83f7c9c0800fa75f8c255974a538": { - "cc5d1eefe874f43350d3": 2 - } - } - }, - "0608000707030802020302080500080702080203070403000505080506020407#69": { - "address": "addr_test1qqy38ey3zshcwtsglnrcmxlju33kpae64py0tqvassnm58r5yr7sjrwumy2ejc2clegv8xrlfpgfr9dwl57la880a6jsfu84yh", - "datum": null, - "inlineDatum": { - "list": [] - }, - "inlineDatumRaw": "80", - "inlineDatumhash": "45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0", - "referenceScript": { - "script": { - "cborHex": "830301848201828201848200581cfe4d020b9f708fec9a270e5b17bf9bcee8dd01dfd3576d4ee00744678200581cac113bda1c61fa12463f1283868c38cae7720bb3dd59853e20ead36b8200581cf1d3988ac9c97034564409bba449d03857aab252fa1cb08816ef71818200581c3bebe7ef41ef51d3b101df853c3b526b96412e66128b34f856185c18830300808200581c4be80bfd616dd6e088a1c9652a09dad8144f55a25624afa3cbe297ca8200581c68b1d1d804c2c8efbf8761b4154b533295cb567560883e4a7d54b5838200581cb3c0f1b5f29e415e467ddea44c8decacdcb312bf1bf96d63ee38e96a", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "467f58932b54910584a0e8ea25a225e06a14530b2e96e938c53a3f22": { - "32": 3490324856632267377 - } - } - }, - "0705020000080808010600000600060405070205030303010700020400000805#67": { - "address": "addr_test1qrx5f9qnygsxclatu5nuus74tx4uqwat4r6p9w9nvhnc93mxen5hvjaydpkc6vasem3nv6kqp5prea4dpv8a6js26xxse6a8zm", - "datum": null, - "datumhash": "ed607c0c19a6311bb0f3ba9e8de64389afe26723852bec2c7fa8ea909b7414ce", - "inlineDatum": null, - "inlineDatumRaw": null, - "referenceScript": { - "script": { - "cborHex": "820405", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "8f461954fe2f18fee1dca233f358907e643ff839ed1f995e4bf325e3": { - "38": 2 - }, - "lovelace": 7373411895183562329 - } - }, - "0808030104060102040105070306020704030002020106060401040407000703#16": { - "address": "addr_test1qpppvfxcazm524nz7wd3wjytacvd8rukdqxqxtg6s8535hrvqhp9nkgw58w6d3t87svy8tjjmtlm00t8ch7j6e0ltp3ssdfjm9", - "datum": null, - "inlineDatum": { - "list": [ - { - "constructor": 5, - "fields": [ - { - "list": [ - { - "bytes": "" - }, - { - "bytes": "1e6bf1" - }, - { - "bytes": "c2" - }, - { - "bytes": "" - } - ] - }, - { - "list": [ - { - "bytes": "e924" - }, - { - "bytes": "47" - }, - { - "bytes": "" - } - ] - }, - { - "map": [ - { - "k": { - "bytes": "dbd76f18" - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "bytes": "876f77" - }, - "v": { - "int": 0 - } - }, - { - "k": { - "int": 3 - }, - "v": { - "int": -1 - } - } - ] - }, - { - "constructor": 1, - "fields": [ - { - "bytes": "0fe952" - }, - { - "int": 0 - } - ] - }, - { - "constructor": 5, - "fields": [ - { - "int": 5 - } - ] - } - ] - } - ] - }, - "inlineDatumRaw": "9fd87e9f9f40431e6bf141c240ff9f42e924414740ffa344dbd76f184043876f77000320d87a9f430fe95200ffd87e9f05ffffff", - "inlineDatumhash": "fad554682923222ab0cabbe7dcf72c1f3307bb100bb1d265d2fefad613f4cb94", - "referenceScript": { - "script": { - "cborHex": "820503", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "d2eedd1d494cfdd39bb43fcf15f14f004477b5ce686f1e7d17e6998e": { - "87216f5df9a86611ebceead2f2a779476d5a831ac73518936aea7273": 3776262176573872565 - }, - "lovelace": 4280915939031878726 - } - } - }, - "tag": "DecommitTxInvalid", - "validationError": { - "reason": "-} Eq (ServerOutput tx) @@ -194,13 +195,14 @@ instance (ArbitraryIsTx tx, IsChainState tx) => Arbitrary (ServerOutput tx) wher PostTxOnChainFailed p e -> PostTxOnChainFailed <$> shrink p <*> shrink e IgnoredHeadInitializing{} -> [] DecommitRequested headId txid u -> DecommitRequested headId txid <$> shrink u - DecommitInvalid{} -> [] + DecommitInvalid headId decommitTx decommitInvalidReason -> DecommitInvalid headId <$> shrink decommitTx <*> shrink decommitInvalidReason + DecommitApproved headId txid u -> DecommitApproved headId txid <$> shrink u + DecommitFinalized headId decommitTxId -> DecommitFinalized headId <$> shrink decommitTxId CommitRecorded headId u i d -> CommitRecorded headId <$> shrink u <*> shrink i <*> shrink d CommitApproved headId u -> CommitApproved headId <$> shrink u - DecommitApproved headId txid u -> DecommitApproved headId txid <$> shrink u CommitRecovered headId u rid -> CommitRecovered headId <$> shrink u <*> shrink rid - DecommitFinalized{} -> [] - CommitFinalized{} -> [] + CommitFinalized headId theDeposit -> CommitFinalized headId <$> shrink theDeposit + CommitIgnored headId depositUTxO snapshotUTxO -> CommitIgnored headId <$> shrink depositUTxO <*> shrink snapshotUTxO instance (ArbitraryIsTx tx, IsChainState tx) => ToADTArbitrary (ServerOutput tx) @@ -255,13 +257,14 @@ prepareServerOutput ServerOutputConfig{utxoInSnapshot} response = PostTxOnChainFailed{} -> encodedResponse IgnoredHeadInitializing{} -> encodedResponse DecommitRequested{} -> encodedResponse - CommitRecorded{} -> encodedResponse - CommitApproved{} -> encodedResponse DecommitApproved{} -> encodedResponse DecommitFinalized{} -> encodedResponse - CommitFinalized{} -> encodedResponse DecommitInvalid{} -> encodedResponse + CommitRecorded{} -> encodedResponse + CommitApproved{} -> encodedResponse + CommitFinalized{} -> encodedResponse CommitRecovered{} -> encodedResponse + CommitIgnored{} -> encodedResponse where handleUtxoInclusion f bs = case utxoInSnapshot of diff --git a/hydra-node/src/Hydra/Chain.hs b/hydra-node/src/Hydra/Chain.hs index 468920cb7ac..df19aaa9022 100644 --- a/hydra-node/src/Hydra/Chain.hs +++ b/hydra-node/src/Hydra/Chain.hs @@ -83,7 +83,7 @@ data PostChainTx tx , openVersion :: SnapshotVersion , contestingSnapshot :: ConfirmedSnapshot tx } - | FanoutTx {utxo :: UTxOType tx, utxoToDecommit :: Maybe (UTxOType tx), headSeed :: HeadSeed, contestationDeadline :: UTCTime} + | FanoutTx {utxo :: UTxOType tx, utxoToCommit :: Maybe (UTxOType tx), utxoToDecommit :: Maybe (UTxOType tx), headSeed :: HeadSeed, contestationDeadline :: UTCTime} deriving stock (Generic) deriving stock instance IsTx tx => Eq (PostChainTx tx) @@ -104,7 +104,7 @@ instance ArbitraryIsTx tx => Arbitrary (PostChainTx tx) where DecrementTx{headId, headParameters, decrementingSnapshot} -> DecrementTx <$> shrink headId <*> shrink headParameters <*> shrink decrementingSnapshot CloseTx{headId, headParameters, openVersion, closingSnapshot} -> CloseTx <$> shrink headId <*> shrink headParameters <*> shrink openVersion <*> shrink closingSnapshot ContestTx{headId, headParameters, openVersion, contestingSnapshot} -> ContestTx <$> shrink headId <*> shrink headParameters <*> shrink openVersion <*> shrink contestingSnapshot - FanoutTx{utxo, utxoToDecommit, headSeed, contestationDeadline} -> FanoutTx <$> shrink utxo <*> shrink utxoToDecommit <*> shrink headSeed <*> shrink contestationDeadline + FanoutTx{utxo, utxoToCommit, utxoToDecommit, headSeed, contestationDeadline} -> FanoutTx <$> shrink utxo <*> shrink utxoToCommit <*> shrink utxoToDecommit <*> shrink headSeed <*> shrink contestationDeadline -- | Describes transactions as seen on chain. Holds as minimal information as -- possible to simplify observing the chain. @@ -198,9 +198,9 @@ data PostTxError tx | FailedToConstructContestTx | FailedToConstructCollectTx | FailedToConstructDepositTx - | FailedToConstructRecoverTx - | FailedToConstructIncrementTx - | FailedToConstructDecrementTx + | FailedToConstructRecoverTx {failureReason :: Text} + | FailedToConstructIncrementTx {failureReason :: Text} + | FailedToConstructDecrementTx {failureReason :: Text} | FailedToConstructFanoutTx deriving stock (Generic) diff --git a/hydra-node/src/Hydra/Chain/Direct/Handlers.hs b/hydra-node/src/Hydra/Chain/Direct/Handlers.hs index 0665818c6fa..338f3e6118b 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Handlers.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Handlers.hs @@ -395,15 +395,15 @@ prepareTxToPost timeHandle wallet ctx spendableUTxO tx = let HeadParameters{contestationPeriod} = headParameters (upperBound, _) <- calculateTxUpperBoundFromContestationPeriod currentTime contestationPeriod case increment ctx spendableUTxO headId headParameters incrementingSnapshot depositTxId upperBound of - Left _ -> throwIO (FailedToConstructIncrementTx @Tx) + Left err -> throwIO (FailedToConstructIncrementTx{failureReason = show err} :: PostTxError Tx) Right incrementTx' -> pure incrementTx' RecoverTx{headId, recoverTxId, deadline} -> do case recover ctx headId recoverTxId spendableUTxO (fromChainSlot deadline) of - Left _ -> throwIO (FailedToConstructRecoverTx @Tx) + Left err -> throwIO (FailedToConstructRecoverTx{failureReason = show err} :: PostTxError Tx) Right recoverTx' -> pure recoverTx' DecrementTx{headId, headParameters, decrementingSnapshot} -> case decrement ctx spendableUTxO headId headParameters decrementingSnapshot of - Left _ -> throwIO (FailedToConstructDecrementTx @Tx) + Left err -> throwIO (FailedToConstructDecrementTx{failureReason = show err} :: PostTxError Tx) Right decrementTx' -> pure decrementTx' CloseTx{headId, headParameters, openVersion, closingSnapshot} -> do (currentSlot, currentTime) <- throwLeft currentPointInTime @@ -419,13 +419,13 @@ prepareTxToPost timeHandle wallet ctx spendableUTxO tx = case contest ctx spendableUTxO headId contestationPeriod openVersion contestingSnapshot upperBound of Left _ -> throwIO (FailedToConstructContestTx @Tx) Right contestTx -> pure contestTx - FanoutTx{utxo, utxoToDecommit, headSeed, contestationDeadline} -> do + FanoutTx{utxo, utxoToCommit, utxoToDecommit, headSeed, contestationDeadline} -> do deadlineSlot <- throwLeft $ slotFromUTCTime contestationDeadline case headSeedToTxIn headSeed of Nothing -> throwIO (InvalidSeed{headSeed} :: PostTxError Tx) Just seedTxIn -> - case fanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlot of + case fanout ctx spendableUTxO seedTxIn utxo utxoToCommit utxoToDecommit deadlineSlot of Left _ -> throwIO (FailedToConstructFanoutTx @Tx) Right fanoutTx -> pure fanoutTx where diff --git a/hydra-node/src/Hydra/Chain/Direct/State.hs b/hydra-node/src/Hydra/Chain/Direct/State.hs index 4cd449d44b2..287a1b78e63 100644 --- a/hydra-node/src/Hydra/Chain/Direct/State.hs +++ b/hydra-node/src/Hydra/Chain/Direct/State.hs @@ -10,10 +10,8 @@ module Hydra.Chain.Direct.State where import Hydra.Prelude hiding (init) import Cardano.Api.UTxO qualified as UTxO -import Data.Fixed (Milli) import Data.Map qualified as Map import Data.Maybe (fromJust) -import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import GHC.IsList qualified as IsList import Hydra.Cardano.Api ( AssetId (..), @@ -80,13 +78,12 @@ import Hydra.Chain.Direct.Tx ( observeInitTx, txInToHeadSeed, ) -import Hydra.Contract.Deposit qualified as Deposit import Hydra.Contract.Head qualified as Head import Hydra.Contract.HeadState qualified as Head import Hydra.Contract.HeadTokens (headPolicyId, mkHeadTokenScript) import Hydra.Ledger.Cardano.Evaluate (genPointInTimeBefore, genValidityBoundsFromContestationPeriod, slotLength, systemStart) import Hydra.Ledger.Cardano.Time (slotNoFromUTCTime) -import Hydra.Plutus (commitValidatorScript, initialValidatorScript) +import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) import Hydra.Plutus.Extras (posixToUTCTime) import Hydra.Tx ( CommitBlueprintTx (..), @@ -97,7 +94,7 @@ import Hydra.Tx ( ScriptRegistry (..), Snapshot (..), SnapshotNumber, - SnapshotVersion, + SnapshotVersion (..), deriveParty, getSnapshot, partyToChain, @@ -120,8 +117,8 @@ import Hydra.Tx.Init (initTx) import Hydra.Tx.OnChainId (OnChainId) import Hydra.Tx.Recover (recoverTx) import Hydra.Tx.Snapshot (genConfirmedSnapshot) -import Hydra.Tx.Utils (splitUTxO, verificationKeyToOnChainId) -import Test.Hydra.Tx.Fixture (testNetworkId) +import Hydra.Tx.Utils (setIncrementalActionMaybe, splitUTxO, verificationKeyToOnChainId) +import Test.Hydra.Tx.Fixture (depositDeadline, testNetworkId) import Test.Hydra.Tx.Gen ( genOneUTxOFor, genScriptRegistry, @@ -132,7 +129,6 @@ import Test.Hydra.Tx.Gen ( ) import Test.QuickCheck (choose, frequency, oneof, suchThat, vector) import Test.QuickCheck.Gen (elements) -import Test.QuickCheck.Modifiers (Positive (Positive)) -- | A class for accessing the known 'UTxO' set in a type. This is useful to get -- all the relevant UTxO for resolving transaction inputs. @@ -309,7 +305,7 @@ data ClosedState = ClosedState instance Arbitrary ClosedState where arbitrary = do -- XXX: Untangle the whole generator mess here - (_, st, _, _) <- genFanoutTx maxGenParties maxGenAssets + (_, st, _, _) <- genFanoutTx maxGenParties pure st shrink = genericShrink @@ -516,17 +512,17 @@ increment ctx spendableUTxO headId headParameters incrementingSnapshot depositTx Just deposit | null deposit -> Left SnapshotIncrementUTxOIsNull - | otherwise -> Right $ incrementTx scriptRegistry ownVerificationKey headId headParameters headUTxO sn (UTxO.singleton (depositedIn, depositedOut)) upperValiditySlot + | otherwise -> Right $ incrementTx scriptRegistry ownVerificationKey headId headParameters headUTxO sn (UTxO.singleton (depositedIn, depositedOut)) upperValiditySlot sigs where headScript = fromPlutusScript @PlutusScriptV3 Head.validatorScript - depositScript = fromPlutusScript @PlutusScriptV3 Deposit.validatorScript + depositScript = fromPlutusScript @PlutusScriptV3 depositValidatorScript Snapshot{utxoToCommit} = sn - sn = + (sn, sigs) = case incrementingSnapshot of - ConfirmedSnapshot{snapshot} -> snapshot - _ -> getSnapshot incrementingSnapshot + ConfirmedSnapshot{snapshot, signatures} -> (snapshot, signatures) + _ -> (getSnapshot incrementingSnapshot, mempty) ChainContext{ownVerificationKey, scriptRegistry} = ctx @@ -577,6 +573,7 @@ decrement ctx spendableUTxO headId headParameters decrementingSnapshot = do data CloseTxError = InvalidHeadIdInClose {headId :: HeadId} | CannotFindHeadOutputToClose + | BothCommitAndDecommitInClose deriving stock (Show) data RecoverTxError @@ -611,7 +608,7 @@ recover ctx headId depositedTxId spendableUTxO lowerValiditySlot = do then Left InvalidHeadIdInRecover{headId} else Right $ recoverTx depositedTxId deposited lowerValiditySlot where - depositScript = fromPlutusScript @PlutusScriptV3 Deposit.validatorScript + depositScript = fromPlutusScript @PlutusScriptV3 depositValidatorScript ChainContext{networkId} = ctx -- | Construct a close transaction spending the head output in given 'UTxO', @@ -648,8 +645,12 @@ close ctx spendableUTxO headId HeadParameters{parties, contestationPeriod} openV , openContestationPeriod = ContestationPeriod.toChain contestationPeriod , openParties = partyToChain <$> parties } - pure $ closeTx scriptRegistry ownVerificationKey headId openVersion confirmedSnapshot startSlotNo pointInTime openThreadOutput + + incrementalAction <- setIncrementalActionMaybe utxoToCommit utxoToDecommit ?> BothCommitAndDecommitInClose + pure $ closeTx scriptRegistry ownVerificationKey headId openVersion confirmedSnapshot startSlotNo pointInTime openThreadOutput incrementalAction where + Snapshot{utxoToCommit, utxoToDecommit} = getSnapshot confirmedSnapshot + headScript = fromPlutusScript @PlutusScriptV3 Head.validatorScript ChainContext{ownVerificationKey, scriptRegistry} = ctx @@ -661,6 +662,7 @@ data ContestTxError | MissingHeadRedeemerInContest | WrongDatumInContest | FailedToConvertFromScriptDataInContest + | BothCommitAndDecommitInContest deriving stock (Show) -- | Construct a contest transaction based on the 'ClosedState' and a confirmed @@ -688,8 +690,10 @@ contest ctx spendableUTxO headId contestationPeriod openVersion contestingSnapsh UTxO.find (isScriptTxOut headScript) (utxoOfThisHead pid spendableUTxO) ?> CannotFindHeadOutputToContest closedThreadOutput <- checkHeadDatum headUTxO - pure $ contestTx scriptRegistry ownVerificationKey headId contestationPeriod openVersion sn sigs pointInTime closedThreadOutput + incrementalAction <- setIncrementalActionMaybe utxoToCommit utxoToDecommit ?> BothCommitAndDecommitInContest + pure $ contestTx scriptRegistry ownVerificationKey headId contestationPeriod openVersion sn sigs pointInTime closedThreadOutput incrementalAction where + Snapshot{utxoToCommit, utxoToDecommit} = sn checkHeadDatum headUTxO@(_, headOutput) = do headDatum <- txOutScriptData (toTxContext headOutput) ?> MissingHeadDatumInContest datum <- fromScriptData headDatum ?> FailedToConvertFromScriptDataInContest @@ -726,6 +730,7 @@ data FanoutTxError | MissingHeadDatumInFanout | WrongDatumInFanout | FailedToConvertFromScriptDataInFanout + | BothCommitAndDecommitInFanout deriving stock (Show) -- | Construct a fanout transaction based on the 'ClosedState' and off-chain @@ -738,19 +743,20 @@ fanout :: TxIn -> -- | Snapshot UTxO to fanout UTxO -> + -- | Snapshot UTxO to commit to fanout + Maybe UTxO -> -- | Snapshot UTxO to decommit to fanout Maybe UTxO -> -- | Contestation deadline as SlotNo, used to set lower tx validity bound. SlotNo -> Either FanoutTxError Tx -fanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlotNo = do +fanout ctx spendableUTxO seedTxIn utxo utxoToCommit utxoToDecommit deadlineSlotNo = do headUTxO <- UTxO.find (isScriptTxOut headScript) (utxoOfThisHead (headPolicyId seedTxIn) spendableUTxO) ?> CannotFindHeadOutputToFanout - closedThreadUTxO <- checkHeadDatum headUTxO - - pure $ fanoutTx scriptRegistry utxo utxoToDecommit closedThreadUTxO deadlineSlotNo headTokenScript + _ <- setIncrementalActionMaybe utxoToCommit utxoToDecommit ?> BothCommitAndDecommitInFanout + pure $ fanoutTx scriptRegistry utxo utxoToCommit utxoToDecommit closedThreadUTxO deadlineSlotNo headTokenScript where headTokenScript = mkHeadTokenScript seedTxIn @@ -921,10 +927,6 @@ observeClose st tx = do maxGenParties :: Int maxGenParties = 3 --- | Maximum number of assets (ADA or other tokens) used in the generators. -maxGenAssets :: Int -maxGenAssets = 70 - -- | Generate a 'ChainState' within known limits above. genChainState :: Gen ChainState genChainState = @@ -985,7 +987,7 @@ genChainStateWithTx = genIncrementWithState :: Gen (ChainContext, ChainState, UTxO, Tx, ChainTransition) genIncrementWithState = do - (ctx, _, st, utxo, tx) <- genIncrementTx maxGenParties + (ctx, st, utxo, tx) <- genIncrementTx maxGenParties pure (ctx, Open st, utxo, tx, Increment) genDecrementWithState :: Gen (ChainContext, ChainState, UTxO, Tx, ChainTransition) @@ -1006,10 +1008,7 @@ genChainStateWithTx = genFanoutWithState :: Gen (ChainContext, ChainState, UTxO, Tx, ChainTransition) genFanoutWithState = do - Positive numParties <- arbitrary - Positive numOutputs <- arbitrary - (hctx, st, utxo, tx) <- genFanoutTx numParties numOutputs - ctx <- pickChainContext hctx + (ctx, st, utxo, tx) <- genFanoutTx maxGenParties pure (ctx, Closed st, utxo, tx, Fanout) -- ** Warning zone @@ -1066,6 +1065,9 @@ genHydraContextFor n = do , ctxScriptRegistry } +instance Arbitrary HydraContext where + arbitrary = genHydraContext maxGenParties + -- | Get all peer-specific 'ChainContext's from a 'HydraContext'. NOTE: This -- assumes that 'HydraContext' has same length 'ctxVerificationKeys' and -- 'ctxHydraSigningKeys'. @@ -1174,43 +1176,39 @@ genCollectComTx = do let spendableUTxO = getKnownUTxO stInitialized pure (cctx, committedUTxO, stInitialized, mempty, unsafeCollect cctx headId (ctxHeadParameters ctx) utxoToCollect spendableUTxO) -genDepositTx :: Gen (UTxO, Tx) -genDepositTx = do - ctx <- genHydraContextFor 1 +genDepositTx :: Int -> Gen (HydraContext, OpenState, UTxO, Tx) +genDepositTx numParties = do + ctx <- genHydraContextFor numParties utxo <- genUTxOAdaOnlyOfSize 1 `suchThat` (not . null) - (_, OpenState{headId}) <- genStOpen ctx - deadline <- posixSecondsToUTCTime . realToFrac <$> (arbitrary :: Gen Milli) - let tx = depositTx (ctxNetworkId ctx) headId CommitBlueprintTx{blueprintTx = txSpendingUTxO utxo, lookupUTxO = utxo} deadline - pure (utxo, tx) + (_, st@OpenState{headId}) <- genStOpen ctx + let tx = depositTx (ctxNetworkId ctx) headId CommitBlueprintTx{blueprintTx = txSpendingUTxO utxo, lookupUTxO = utxo} depositDeadline + pure (ctx, st, utxo <> utxoFromTx tx, tx) genRecoverTx :: Gen (UTxO, Tx) genRecoverTx = do - (_depositedUTxO, txDeposit) <- genDepositTx - let DepositObservation{deposited} = + (_, _, depositedUTxO, txDeposit) <- genDepositTx maximumNumberOfParties + let DepositObservation{deposited, deadline} = fromJust $ observeDepositTx testNetworkId txDeposit - -- TODO: generate multiple various slots after deadline - let tx = recoverTx (getTxId $ getTxBody txDeposit) deposited 100 - pure (utxoFromTx txDeposit, tx) + let slotNo = slotNoFromUTCTime systemStart slotLength (posixToUTCTime deadline) + slotNo' <- arbitrary + let tx = recoverTx (getTxId $ getTxBody txDeposit) deposited (slotNo + slotNo') + pure (depositedUTxO, tx) -genIncrementTx :: Int -> Gen (ChainContext, [TxOut CtxUTxO], OpenState, UTxO, Tx) +genIncrementTx :: Int -> Gen (ChainContext, OpenState, UTxO, Tx) genIncrementTx numParties = do - (_utxo, txDeposit) <- genDepositTx - ctx <- genHydraContextFor numParties + (ctx, st@OpenState{headId}, utxo, txDeposit) <- genDepositTx numParties cctx <- pickChainContext ctx - let DepositObservation{deposited, depositTxId} = fromJust $ observeDepositTx (ctxNetworkId ctx) txDeposit - (_, st@OpenState{headId}) <- genStOpen ctx + let DepositObservation{deposited, depositTxId, deadline} = fromJust $ observeDepositTx (ctxNetworkId ctx) txDeposit let openUTxO = getKnownUTxO st - let version = 1 - snapshot <- genConfirmedSnapshot headId 2 version openUTxO (Just deposited) Nothing (ctxHydraSigningKeys ctx) - let depositUTxO = utxoFromTx txDeposit - slotNo <- arbitrary + let version = 0 + snapshot <- genConfirmedSnapshot headId version 1 openUTxO (Just deposited) Nothing (ctxHydraSigningKeys ctx) + let slotNo = slotNoFromUTCTime systemStart slotLength (posixToUTCTime deadline) pure ( cctx - , maybe mempty toList (utxoToCommit $ getSnapshot snapshot) , st - , depositUTxO - , unsafeIncrement cctx (openUTxO <> depositUTxO) headId (ctxHeadParameters ctx) snapshot depositTxId slotNo + , utxo + , unsafeIncrement cctx (openUTxO <> utxo) headId (ctxHeadParameters ctx) snapshot depositTxId slotNo ) genDecrementTx :: Int -> Gen (ChainContext, [TxOut CtxUTxO], OpenState, UTxO, Tx) @@ -1234,22 +1232,29 @@ genCloseTx :: Int -> Gen (ChainContext, OpenState, UTxO, Tx, ConfirmedSnapshot T genCloseTx numParties = do ctx <- genHydraContextFor numParties (u0, stOpen@OpenState{headId}) <- genStOpen ctx - let (confirmedUtxo, utxoToDecommit) = splitUTxO u0 + let (inHead, toDecommit) = splitUTxO u0 + n <- elements [1 .. 10] + utxoToCommit' <- oneof [Just <$> genUTxOAdaOnlyOfSize n, pure Nothing] + utxoToDecommit' <- oneof [pure toDecommit, pure mempty] + let (confirmedUTxO, utxoToCommit, utxoToDecommit) = + if isNothing utxoToCommit' + then (inHead, Nothing, if utxoToDecommit' == mempty then Nothing else Just utxoToDecommit') + else (u0, utxoToCommit', Nothing) let version = 0 - snapshot <- genConfirmedSnapshot headId version 1 confirmedUtxo Nothing (Just utxoToDecommit) (ctxHydraSigningKeys ctx) + snapshot <- genConfirmedSnapshot headId version 1 confirmedUTxO utxoToCommit utxoToDecommit (ctxHydraSigningKeys ctx) cctx <- pickChainContext ctx let cp = ctxContestationPeriod ctx (startSlot, pointInTime) <- genValidityBoundsFromContestationPeriod cp let utxo = getKnownUTxO stOpen - pure (cctx, stOpen, mempty, unsafeClose cctx utxo headId (ctxHeadParameters ctx) version snapshot startSlot pointInTime, snapshot) + pure (cctx, stOpen, utxo, unsafeClose cctx utxo headId (ctxHeadParameters ctx) version snapshot startSlot pointInTime, snapshot) genContestTx :: Gen (HydraContext, PointInTime, ClosedState, UTxO, Tx) genContestTx = do ctx <- genHydraContextFor maximumNumberOfParties (u0, stOpen@OpenState{headId}) <- genStOpen ctx - let (confirmedUtXO, utxoToDecommit) = splitUTxO u0 + let (confirmedUTxO, utxoToDecommit) = splitUTxO u0 let version = 1 - confirmed <- genConfirmedSnapshot headId version 1 confirmedUtXO Nothing (Just utxoToDecommit) [] + confirmed <- genConfirmedSnapshot headId version 1 confirmedUTxO Nothing (Just utxoToDecommit) [] cctx <- pickChainContext ctx let cp = ctxContestationPeriod ctx (startSlot, closePointInTime) <- genValidityBoundsFromContestationPeriod cp @@ -1263,16 +1268,28 @@ genContestTx = do contestPointInTime <- genPointInTimeBefore (getContestationDeadline stClosed) pure (ctx, closePointInTime, stClosed, mempty, unsafeContest cctx utxo headId cp version contestSnapshot contestPointInTime) -genFanoutTx :: Int -> Int -> Gen (HydraContext, ClosedState, UTxO, Tx) -genFanoutTx numParties numOutputs = do - ctx <- genHydraContext numParties - utxo <- genUTxOAdaOnlyOfSize numOutputs - let (inHead', toDecommit') = splitUTxO utxo - (_, toFanout, toDecommit, stClosed@ClosedState{seedTxIn}) <- genStClosed ctx inHead' (Just toDecommit') +genFanoutTx :: Int -> Gen (ChainContext, ClosedState, UTxO, Tx) +genFanoutTx numParties = do + ctx <- genHydraContextFor numParties + (u0, stOpen@OpenState{headId}) <- genStOpen ctx + n <- elements [1 .. 10] + toCommit' <- Just <$> genUTxOAdaOnlyOfSize n + openVersion <- elements [0, 1] + version <- elements [0, 1] + confirmed <- genConfirmedSnapshot headId version 1 u0 toCommit' Nothing (ctxHydraSigningKeys ctx) cctx <- pickChainContext ctx + let cp = ctxContestationPeriod ctx + (startSlot, closePointInTime) <- genValidityBoundsFromContestationPeriod cp + let openUTxO = getKnownUTxO stOpen + let txClose = unsafeClose cctx openUTxO headId (ctxHeadParameters ctx) openVersion confirmed startSlot closePointInTime + let stClosed@ClosedState{seedTxIn} = snd $ fromJust $ observeClose stOpen txClose + let toFanout = utxo $ getSnapshot confirmed + let toCommit = utxoToCommit $ getSnapshot confirmed let deadlineSlotNo = slotNoFromUTCTime systemStart slotLength (getContestationDeadline stClosed) - spendableUTxO = getKnownUTxO stClosed - pure (ctx, stClosed, mempty, unsafeFanout cctx spendableUTxO seedTxIn toFanout toDecommit deadlineSlotNo) + let spendableUTxO = getKnownUTxO stClosed + -- if local version is not matching the snapshot version we **should** fanout commit utxo + let finalToCommit = if openVersion /= version then toCommit else Nothing + pure (cctx, stClosed, mempty, unsafeFanout cctx spendableUTxO seedTxIn toFanout finalToCommit Nothing deadlineSlotNo) getContestationDeadline :: ClosedState -> UTCTime getContestationDeadline @@ -1297,25 +1314,28 @@ genStClosed :: HydraContext -> UTxO -> Maybe UTxO -> - Gen (SnapshotNumber, UTxO, Maybe UTxO, ClosedState) -genStClosed ctx utxo utxoToDecommit = do + Maybe UTxO -> + Gen (SnapshotNumber, UTxO, Maybe UTxO, Maybe UTxO, ClosedState) +genStClosed ctx utxo utxoToCommit utxoToDecommit = do (u0, stOpen@OpenState{headId}) <- genStOpen ctx confirmed <- arbitrary - let (sn, snapshot, toFanout, toDecommit, v) = case confirmed of + let (sn, snapshot, toFanout, toCommit, toDecommit, v) = case confirmed of InitialSnapshot{} -> ( 0 , InitialSnapshot{headId, initialUTxO = u0} , u0 , Nothing + , Nothing , 0 ) ConfirmedSnapshot{snapshot = snap, signatures} -> ( number snap , ConfirmedSnapshot - { snapshot = snap{utxo = utxo, utxoToDecommit} + { snapshot = snap{utxo = utxo, utxoToDecommit, utxoToCommit} , signatures } , utxo + , utxoToCommit , utxoToDecommit , version snap ) @@ -1324,7 +1344,7 @@ genStClosed ctx utxo utxoToDecommit = do (startSlot, pointInTime) <- genValidityBoundsFromContestationPeriod cp let utxo' = getKnownUTxO stOpen let txClose = unsafeClose cctx utxo' headId (ctxHeadParameters ctx) v snapshot startSlot pointInTime - pure (sn, toFanout, toDecommit, snd . fromJust $ observeClose stOpen txClose) + pure (sn, toFanout, toCommit, toDecommit, snd . fromJust $ observeClose stOpen txClose) -- ** Danger zone @@ -1432,13 +1452,15 @@ unsafeFanout :: TxIn -> -- | Snapshot UTxO to fanout UTxO -> + -- | Snapshot commit UTxO to fanout + Maybe UTxO -> -- | Snapshot decommit UTxO to fanout Maybe UTxO -> -- | Contestation deadline as SlotNo, used to set lower tx validity bound. SlotNo -> Tx -unsafeFanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlotNo = - either (error . show) id $ fanout ctx spendableUTxO seedTxIn utxo utxoToDecommit deadlineSlotNo +unsafeFanout ctx spendableUTxO seedTxIn utxo utxoToCommit utxoToDecommit deadlineSlotNo = + either (error . show) id $ fanout ctx spendableUTxO seedTxIn utxo utxoToCommit utxoToDecommit deadlineSlotNo unsafeObserveInit :: HasCallStack => diff --git a/hydra-node/src/Hydra/Chain/Direct/Tx.hs b/hydra-node/src/Hydra/Chain/Direct/Tx.hs index 86acf3563dc..bcfe8f765fb 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Tx.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Tx.hs @@ -26,7 +26,7 @@ import Hydra.Contract.HeadState qualified as Head import Hydra.Contract.HeadTokens qualified as HeadTokens import Hydra.Data.ContestationPeriod qualified as OnChain import Hydra.Data.Party qualified as OnChain -import Hydra.Plutus (commitValidatorScript, initialValidatorScript) +import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) import Hydra.Plutus.Extras (posixToUTCTime) import Hydra.Plutus.Orphans () import Hydra.Tx ( @@ -364,7 +364,8 @@ observeIncrementTx utxo tx = do (headInput, headOutput) <- findTxOutByScript @PlutusScriptV3 inputUTxO headScript (TxIn depositTxId _, depositOutput) <- findTxOutByScript @PlutusScriptV3 utxo depositScript dat <- txOutScriptData $ toTxContext depositOutput - Deposit.DepositDatum _ <- fromScriptData dat + -- we need to be able to decode the datum, no need to use it tho + _ :: Deposit.DepositDatum <- fromScriptData dat redeemer <- findRedeemerSpending tx headInput oldHeadDatum <- txOutScriptData $ toTxContext headOutput datum <- fromScriptData oldHeadDatum @@ -384,7 +385,7 @@ observeIncrementTx utxo tx = do _ -> Nothing _ -> Nothing where - depositScript = fromPlutusScript Deposit.validatorScript + depositScript = fromPlutusScript depositValidatorScript headScript = fromPlutusScript Head.validatorScript data DecrementObservation = DecrementObservation diff --git a/hydra-node/src/Hydra/Chain/ScriptRegistry.hs b/hydra-node/src/Hydra/Chain/ScriptRegistry.hs index 51a81883bda..8e88ce079e2 100644 --- a/hydra-node/src/Hydra/Chain/ScriptRegistry.hs +++ b/hydra-node/src/Hydra/Chain/ScriptRegistry.hs @@ -62,15 +62,15 @@ queryScriptRegistry :: NetworkId -> -- | Filepath to the cardano-node's domain socket SocketPath -> - TxId -> + [TxId] -> m ScriptRegistry -queryScriptRegistry networkId socketPath txId = do +queryScriptRegistry networkId socketPath txIds = do utxo <- liftIO $ queryUTxOByTxIn networkId socketPath QueryTip candidates case newScriptRegistry utxo of Left e -> throwIO e Right sr -> pure sr where - candidates = [TxIn txId ix | ix <- [TxIx 0 .. TxIx 10]] -- Arbitrary but, high-enough. + candidates = concatMap (\txId -> [TxIn txId ix | ix <- [TxIx 0 .. TxIx 10]]) txIds -- Arbitrary but, high-enough. publishHydraScripts :: -- | Expected network discriminant. @@ -79,37 +79,34 @@ publishHydraScripts :: SocketPath -> -- | Keys assumed to hold funds to pay for the publishing transaction. SigningKey PaymentKey -> - IO TxId + IO [TxId] publishHydraScripts networkId socketPath sk = do pparams <- queryProtocolParameters networkId socketPath QueryTip - utxo <- queryUTxOFor networkId socketPath QueryTip vk - let outputs = - mkScriptTxOut pparams - <$> [ mkScriptRefV3 initialValidatorScript - , mkScriptRefV3 commitValidatorScript - , mkScriptRefV3 Head.validatorScript - ] - totalDeposit = sum (selectLovelace . txOutValue <$> outputs) - someUTxO = - maybe mempty UTxO.singleton $ - UTxO.find (\o -> selectLovelace (txOutValue o) > totalDeposit) utxo - buildTransaction - networkId - socketPath - changeAddress - someUTxO - [] - outputs - >>= \case - Left e -> - throwErrorAsException e - Right x -> do - let body = getTxBody x - let tx = makeSignedTransaction [makeShelleyKeyWitness body (WitnessPaymentKey sk)] body - submitTransaction networkId socketPath tx - void $ awaitTransaction networkId socketPath tx - return $ getTxId body + forM scriptRefs $ \scriptRef -> do + utxo <- queryUTxOFor networkId socketPath QueryTip vk + let output = mkScriptTxOut pparams <$> [mkScriptRefV3 scriptRef] + totalDeposit = sum (selectLovelace . txOutValue <$> output) + someUTxO = + maybe mempty UTxO.singleton $ + UTxO.find (\o -> selectLovelace (txOutValue o) > totalDeposit) utxo + buildTransaction + networkId + socketPath + changeAddress + someUTxO + [] + output + >>= \case + Left e -> + throwErrorAsException e + Right x -> do + let body = getTxBody x + let tx = makeSignedTransaction [makeShelleyKeyWitness body (WitnessPaymentKey sk)] body + submitTransaction networkId socketPath tx + void $ awaitTransaction networkId socketPath tx + return $ getTxId body where + scriptRefs = [initialValidatorScript, commitValidatorScript, Head.validatorScript] vk = getVerificationKey sk changeAddress = mkVkAddress networkId vk diff --git a/hydra-node/src/Hydra/HeadLogic.hs b/hydra-node/src/Hydra/HeadLogic.hs index 5b9bf037b3a..e26a24f6cca 100644 --- a/hydra-node/src/Hydra/HeadLogic.hs +++ b/hydra-node/src/Hydra/HeadLogic.hs @@ -428,6 +428,7 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn -- Spec: require 𝑈_active ◦ Treq ≠ ⊥ -- 𝑈 ← 𝑈_active ◦ Treq requireApplyTxs activeUTxO requestedTxs $ \u -> do + let snapshotUTxO = u `withoutUTxO` fromMaybe mempty mUtxoToCommit -- Spec: ŝ ← ̅S.s + 1 -- NOTE: confSn == seenSn == sn here let nextSnapshot = @@ -436,7 +437,7 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn , version = version , number = sn , confirmed = requestedTxs - , utxo = u + , utxo = snapshotUTxO , utxoToCommit = mUtxoToCommit , utxoToDecommit = mUtxoToDecommit } @@ -492,6 +493,8 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn case mIncrementUTxO of Nothing -> cont (activeUTxOAfterDecommit, Nothing) Just utxo -> + -- NOTE: this makes the commits sequential in a sense that you can't + -- commit unless the previous commit is settled. if sv == confVersion && isJust confUTxOToCommit then if confUTxOToCommit == Just utxo @@ -572,7 +575,7 @@ onOpenNetworkReqSn env ledger st otherParty sv sn requestedTxIds mDecommitTx mIn confirmedUTxO = case confirmedSnapshot of InitialSnapshot{initialUTxO} -> initialUTxO - ConfirmedSnapshot{snapshot = Snapshot{utxo}} -> utxo + ConfirmedSnapshot{snapshot = Snapshot{utxo, utxoToCommit}} -> utxo <> fromMaybe mempty utxoToCommit CoordinatedHeadState{confirmedSnapshot, seenSnapshot, allTxs, localTxs, version} = coordinatedHeadState @@ -702,7 +705,17 @@ onOpenNetworkAckSn Environment{party} openState otherParty snapshotSignature sn } } ] - _ -> outcome -- TODO: output some error here? + _ -> + cause + ( ClientEffect $ + ServerOutput.CommitIgnored + { headId + , depositUTxO = Map.elems pendingDeposits + , snapshotUTxO = utxoToCommit + } + ) + <> outcome + maybePostDecrementTx snapshot@Snapshot{utxoToDecommit} signatures outcome = case (decommitTx, utxoToDecommit) of (Just tx, Just utxo) -> @@ -1194,7 +1207,6 @@ onClosedChainContestTx closedState newChainState snapshotNumber contestationDead -- -- __Transition__: 'ClosedState' → 'ClosedState' onClosedClientFanout :: - Monoid (UTxOType tx) => ClosedState tx -> Outcome tx onClosedClientFanout closedState = @@ -1203,16 +1215,21 @@ onClosedClientFanout closedState = { postChainTx = FanoutTx { utxo + , utxoToCommit = + -- NOTE: note that logic is flipped in the commit and decommit case here. + if toInteger snapshotVersion == max (toInteger version - 1) 0 + then utxoToCommit + else Nothing , utxoToDecommit = if toInteger snapshotVersion == max (toInteger version - 1) 0 - then mempty + then Nothing else utxoToDecommit , headSeed , contestationDeadline } } where - Snapshot{utxo, utxoToDecommit, version = snapshotVersion} = getSnapshot confirmedSnapshot + Snapshot{utxo, utxoToCommit, utxoToDecommit, version = snapshotVersion} = getSnapshot confirmedSnapshot ClosedState{headSeed, confirmedSnapshot, contestationDeadline, version} = closedState @@ -1221,15 +1238,16 @@ onClosedClientFanout closedState = -- -- __Transition__: 'ClosedState' → 'IdleState' onClosedChainFanoutTx :: + IsTx tx => ClosedState tx -> -- | New chain state ChainStateType tx -> Outcome tx onClosedChainFanoutTx closedState newChainState = newState HeadFannedOut{chainState = newChainState} - <> cause (ClientEffect $ ServerOutput.HeadIsFinalized{headId, utxo}) + <> cause (ClientEffect $ ServerOutput.HeadIsFinalized{headId, utxo = (utxo <> fromMaybe mempty utxoToCommit) `withoutUTxO` fromMaybe mempty utxoToDecommit}) where - Snapshot{utxo} = getSnapshot confirmedSnapshot + Snapshot{utxo, utxoToCommit, utxoToDecommit} = getSnapshot confirmedSnapshot ClosedState{confirmedSnapshot, headId} = closedState @@ -1286,7 +1304,8 @@ update env ledger st ev = case (st, ev) of (Open OpenState{coordinatedHeadState = CoordinatedHeadState{confirmedSnapshot}, headId}, ClientInput GetUTxO) -> -- TODO: Is it really intuitive that we respond from the confirmed ledger if -- transactions are validated against the seen ledger? - cause (ClientEffect . ServerOutput.GetUTxOResponse headId $ getField @"utxo" $ getSnapshot confirmedSnapshot) + let snapshot' = getSnapshot confirmedSnapshot + in cause (ClientEffect . ServerOutput.GetUTxOResponse headId $ getField @"utxo" snapshot' <> fromMaybe mempty (getField @"utxoToCommit" snapshot')) -- NOTE: If posting the collectCom transaction failed in the open state, then -- another party likely opened the head before us and it's okay to ignore. (Open{}, ChainInput PostTxError{postChainTx = CollectComTx{}}) -> @@ -1596,16 +1615,19 @@ aggregate st = \case case st of Open os@OpenState{coordinatedHeadState} -> - Open - os - { coordinatedHeadState = - coordinatedHeadState - { pendingDeposits = Map.delete depositTxId existingDeposits - , version = newVersion - } - } + let newLocalUTxO = fromMaybe mempty (Map.lookup depositTxId existingDeposits) + pendingDeposits = Map.delete depositTxId existingDeposits + in Open + os + { coordinatedHeadState = + coordinatedHeadState + { pendingDeposits + , version = newVersion + , localUTxO = localUTxO <> newLocalUTxO + } + } where - CoordinatedHeadState{pendingDeposits = existingDeposits} = coordinatedHeadState + CoordinatedHeadState{pendingDeposits = existingDeposits, localUTxO} = coordinatedHeadState _otherState -> st DecommitFinalized{newVersion} -> case st of diff --git a/hydra-node/src/Hydra/Options.hs b/hydra-node/src/Hydra/Options.hs index 2615d41300f..8cff84c5d02 100644 --- a/hydra-node/src/Hydra/Options.hs +++ b/hydra-node/src/Hydra/Options.hs @@ -362,7 +362,7 @@ data DirectChainConfig = DirectChainConfig -- ^ Network identifer to which we expect to connect. , nodeSocket :: SocketPath -- ^ Path to a domain socket used to connect to the server. - , hydraScriptsTxId :: TxId + , hydraScriptsTxId :: [TxId] -- ^ Identifier of transaction holding the hydra scripts to use. , cardanoSigningKey :: FilePath -- ^ Path to the cardano signing key of the internal wallet. @@ -380,7 +380,7 @@ defaultDirectChainConfig = DirectChainConfig { networkId = Testnet (NetworkMagic 42) , nodeSocket = "node.socket" - , hydraScriptsTxId = TxId "0101010101010101010101010101010101010101010101010101010101010101" + , hydraScriptsTxId = [] , cardanoSigningKey = "cardano.sk" , cardanoVerificationKeys = [] , startChainFrom = Nothing @@ -455,7 +455,7 @@ directChainConfigParser = DirectChainConfig <$> networkIdParser <*> nodeSocketParser - <*> hydraScriptsTxIdParser + <*> (hydraScriptsTxIdsParser <|> many hydraScriptsTxIdParser) <*> cardanoSigningKeyFileParser <*> many cardanoVerificationKeyFileParser <*> optional startChainFromParser @@ -700,13 +700,27 @@ startChainFromParser = _emptyOrSingularList -> Nothing +hydraScriptsTxIdsParser :: Parser [TxId] +hydraScriptsTxIdsParser = + option + (eitherReader $ left show . parseFromHex . BSC.split ',' . BSC.pack) + ( long "hydra-scripts-tx-id" + <> metavar "TXID" + <> help + "The transaction which is expected to have published Hydra scripts as \ + \reference scripts in its outputs. Note: All scripts need to be in the \ + \first 10 outputs. See release notes for pre-published versions. You \ + \can use the 'publish-scripts' sub-command to publish them yourself." + ) + where + parseFromHex = mapM (deserialiseFromRawBytesHex AsTxId) + hydraScriptsTxIdParser :: Parser TxId hydraScriptsTxIdParser = option (eitherReader $ left show . deserialiseFromRawBytesHex AsTxId . BSC.pack) ( long "hydra-scripts-tx-id" <> metavar "TXID" - <> value "0101010101010101010101010101010101010101010101010101010101010101" <> help "The transaction which is expected to have published Hydra scripts as \ \reference scripts in its outputs. Note: All scripts need to be in the \ @@ -889,7 +903,7 @@ toArgs } -> toArgNetworkId networkId <> toArgNodeSocket nodeSocket - <> ["--hydra-scripts-tx-id", toString $ serialiseToRawBytesHexText hydraScriptsTxId] + <> ["--hydra-scripts-tx-id", intercalate "," $ toString . serialiseToRawBytesHexText <$> hydraScriptsTxId] <> ["--cardano-signing-key", cardanoSigningKey] <> ["--contestation-period", show contestationPeriod] <> concatMap (\vk -> ["--cardano-verification-key", vk]) cardanoVerificationKeys diff --git a/hydra-node/test/Hydra/BehaviorSpec.hs b/hydra-node/test/Hydra/BehaviorSpec.hs index 4fa1ce1cf10..09ff9ed70ea 100644 --- a/hydra-node/test/Hydra/BehaviorSpec.hs +++ b/hydra-node/test/Hydra/BehaviorSpec.hs @@ -443,6 +443,10 @@ spec = parallel $ do _ -> False waitUntil [n2] $ CommitApproved{headId = testHeadId, utxoToCommit = depositUTxO2} waitUntil [n2] $ CommitFinalized{headId = testHeadId, theDeposit = 2} + send n1 Close + waitUntil [n1, n2] $ ReadyToFanout{headId = testHeadId} + send n2 Fanout + waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [1, 3, 11, 22]} it "can process transactions while commit pending" $ shouldRunInSim $ do @@ -464,6 +468,10 @@ spec = parallel $ do SnapshotConfirmed{snapshot = Snapshot{confirmed}} -> normalTx `elem` confirmed _ -> False waitUntil [n1] $ CommitFinalized{headId = testHeadId, theDeposit = 1} + send n1 Close + waitUntil [n1, n2] $ ReadyToFanout{headId = testHeadId} + send n2 Fanout + waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [1, 3, 11]} it "can close with commit in flight" $ shouldRunInSim $ do @@ -483,17 +491,14 @@ spec = parallel $ do SnapshotConfirmed{snapshot = Snapshot{utxoToCommit}} -> maybe False (11 `member`) utxoToCommit _ -> False - injectChainEvent - n1 - Observation{observedTx = OnCloseTx testHeadId 0 deadline, newChainState = SimpleChainState{slot = ChainSlot 0}} - injectChainEvent - n2 - Observation{observedTx = OnCloseTx testHeadId 0 deadline, newChainState = SimpleChainState{slot = ChainSlot 0}} + + send n1 Close + waitUntilMatch [n1, n2] $ + \case + HeadIsClosed{snapshotNumber} -> snapshotNumber == 1 + _ -> False waitUntil [n1, n2] $ ReadyToFanout{headId = testHeadId} send n2 Fanout - waitUntilMatch [n1, n2] $ \case - HeadIsContested{headId, snapshotNumber} -> headId == testHeadId && snapshotNumber == 1 - _ -> False waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [1, 2, 11]} it "fanout utxo is correct after a commit" $ @@ -513,6 +518,37 @@ spec = parallel $ do send n2 Fanout waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [1, 2]} + it "can do new deposit once the first one has settled" $ + shouldRunInSim $ do + withSimulatedChainAndNetwork $ \chain -> + withHydraNode aliceSk [bob] chain $ \n1 -> do + withHydraNode bobSk [alice] chain $ \n2 -> do + openHead chain n1 n2 + let depositUTxO = utxoRefs [11] + let deadline = arbitrary `generateWith` 42 + let depositUTxO2 = utxoRefs [111] + let deadline2 = arbitrary `generateWith` 42 + injectChainEvent + n1 + Observation{observedTx = OnDepositTx testHeadId depositUTxO 1 deadline, newChainState = SimpleChainState{slot = ChainSlot 0}} + waitUntil [n1] $ CommitRecorded{headId = testHeadId, utxoToCommit = depositUTxO, pendingDeposit = 1, deadline} + waitUntil [n1] $ CommitApproved{headId = testHeadId, utxoToCommit = utxoRefs [11]} + waitUntil [n1, n2] $ CommitFinalized{headId = testHeadId, theDeposit = 1} + injectChainEvent + n2 + Observation{observedTx = OnDepositTx testHeadId depositUTxO2 2 deadline2, newChainState = SimpleChainState{slot = ChainSlot 1}} + waitUntil [n2] $ CommitRecorded{headId = testHeadId, utxoToCommit = depositUTxO2, pendingDeposit = 2, deadline = deadline2} + waitUntilMatch [n1, n2] $ + \case + SnapshotConfirmed{snapshot = Snapshot{utxoToCommit}} -> + maybe False (111 `member`) utxoToCommit + _ -> False + + send n1 Close + waitUntil [n1, n2] $ ReadyToFanout{headId = testHeadId} + send n2 Fanout + waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [1, 2, 11, 111]} + it "multiple commits and decommits in sequence" $ shouldRunInSim $ do withSimulatedChainAndNetwork $ \chain -> @@ -545,6 +581,10 @@ spec = parallel $ do waitUntil [n1, n2] $ DecommitApproved testHeadId (txId decommitTx) (utxoRefs [42]) waitUntil [n1, n2] $ DecommitFinalized testHeadId (txId decommitTx) + send n1 Close + waitUntil [n1, n2] $ ReadyToFanout{headId = testHeadId} + send n2 Fanout + waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [2, 11]} it "commit and decommit same utxo" $ shouldRunInSim $ do withSimulatedChainAndNetwork $ \chain -> @@ -712,6 +752,37 @@ spec = parallel $ do send n1 Fanout waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs [2]} + it "can fanout with empty utxo" $ + shouldRunInSim $ do + withSimulatedChainAndNetwork $ \chain -> + withHydraNode aliceSk [bob] chain $ \n1 -> do + withHydraNode bobSk [alice] chain $ \n2 -> do + openHead chain n1 n2 + let decommitTx = SimpleTx 1 (utxoRef 1) (utxoRef 42) + send n2 (Decommit{decommitTx}) + waitUntil [n1, n2] $ + DecommitApproved + { headId = testHeadId + , decommitTxId = txId decommitTx + , utxoToDecommit = utxoRefs [42] + } + waitUntil [n1, n2] $ + DecommitFinalized + { headId = testHeadId + , decommitTxId = txId decommitTx + } + let decommitTx2 = SimpleTx 2 (utxoRef 2) (utxoRef 88) + send n1 (Decommit{decommitTx = decommitTx2}) + waitUntil [n1, n2] $ + DecommitFinalized + { headId = testHeadId + , decommitTxId = txId decommitTx2 + } + send n1 Close + waitUntil [n1, n2] $ ReadyToFanout{headId = testHeadId} + send n1 Fanout + waitUntil [n1, n2] $ HeadIsFinalized{headId = testHeadId, utxo = utxoRefs []} + it "can be finalized by all parties after contestation period" $ shouldRunInSim $ do withSimulatedChainAndNetwork $ \chain -> diff --git a/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs b/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs index ea0f66182f6..607cebd5aeb 100644 --- a/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs +++ b/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs @@ -66,6 +66,7 @@ import Hydra.Chain.Direct.State ( genDepositTx, genFanoutTx, genHydraContext, + genIncrementTx, genInitTx, genRecoverTx, genStInitial, @@ -143,7 +144,6 @@ import Test.QuickCheck ( forAllShrink, getPositive, label, - sized, sublistOf, tabulate, (.&&.), @@ -348,17 +348,21 @@ spec = parallel $ do Nothing -> False & counterexample ("observeRecoverTx ignored transaction: " <> renderTxWithUTxO utxo tx) + describe "increment" $ do + propBelowSizeLimit maxTxSize forAllIncrement + propIsValid forAllIncrement + describe "decrement" $ do propBelowSizeLimit maxTxSize forAllDecrement propIsValid forAllDecrement - prop "observes distributed outputs" $ - forAllDecrement' $ \toDistribute utxo tx -> - case observeDecrementTx utxo tx of - Just DecrementObservation{distributedOutputs} -> - distributedOutputs === toDistribute - Nothing -> - False & counterexample ("observeDecrementTx ignored transaction: " <> renderTxWithUTxO utxo tx) + prop "observes distributed outputs" $ + forAllDecrement' $ \toDistribute utxo tx -> + case observeDecrementTx utxo tx of + Just DecrementObservation{distributedOutputs} -> + distributedOutputs === toDistribute + Nothing -> + False & counterexample ("observeDecrementTx ignored transaction: " <> renderTxWithUTxO utxo tx) describe "close" $ do propBelowSizeLimit maxTxSize forAllClose @@ -507,7 +511,7 @@ prop_canCloseFanoutEveryCollect = monadicST $ do _ -> fail "not observed close" -- Fanout let fanoutUTxO = getKnownUTxO stClosed - let txFanout = unsafeFanout cctx fanoutUTxO seedTxIn initialUTxO Nothing (slotNoFromUTCTime systemStart slotLength deadline) + let txFanout = unsafeFanout cctx fanoutUTxO seedTxIn initialUTxO Nothing Nothing (slotNoFromUTCTime systemStart slotLength deadline) -- Properties let collectFails = @@ -646,7 +650,9 @@ forAllDeposit :: (UTxO -> Tx -> property) -> Property forAllDeposit action = do - forAllShrink genDepositTx shrink $ uncurry action + forAllShrink (genDepositTx maximumNumberOfParties) shrink $ \(_ctx, st, depositUTxO, tx) -> + let utxo = getKnownUTxO st <> depositUTxO + in action utxo tx forAllRecover :: Testable property => @@ -655,6 +661,23 @@ forAllRecover :: forAllRecover action = do forAllShrink genRecoverTx shrink $ uncurry action +forAllIncrement :: + Testable property => + (UTxO -> Tx -> property) -> + Property +forAllIncrement action = do + forAllIncrement' $ \utxo tx -> + action utxo tx + +forAllIncrement' :: + Testable property => + (UTxO -> Tx -> property) -> + Property +forAllIncrement' action = do + forAllShrink (genIncrementTx maximumNumberOfParties) shrink $ \(ctx, st, incrementUTxO, tx) -> + let utxo = getKnownUTxO st <> getKnownUTxO ctx <> incrementUTxO + in action utxo tx + forAllDecrement :: Testable property => (UTxO -> Tx -> property) -> @@ -668,8 +691,8 @@ forAllDecrement' :: ([TxOut CtxUTxO] -> UTxO -> Tx -> property) -> Property forAllDecrement' action = do - forAllShrink (genDecrementTx maximumNumberOfParties) shrink $ \(ctx, distributed, st, _, tx) -> - let utxo = getKnownUTxO st <> getKnownUTxO ctx + forAllShrink (genDecrementTx maximumNumberOfParties) shrink $ \(ctx, distributed, st, utxo', tx) -> + let utxo = getKnownUTxO st <> getKnownUTxO ctx <> utxo' in action distributed utxo tx forAllClose :: @@ -729,11 +752,10 @@ forAllFanout :: Property forAllFanout action = -- TODO: The utxo to fanout should be more arbitrary to have better test coverage - forAll (sized $ \n -> genFanoutTx maximumNumberOfParties (n `min` maxSupported)) $ \(hctx, stClosed, _, tx) -> - forAllBlind (pickChainContext hctx) $ \ctx -> - let utxo = getKnownUTxO stClosed <> getKnownUTxO ctx - in action utxo tx - & label ("Fanout size: " <> prettyLength (countAssets $ txOuts' tx)) + forAll (genFanoutTx maximumNumberOfParties) $ \(ctx, stClosed, _, tx) -> + let utxo = getKnownUTxO stClosed <> getKnownUTxO ctx + in action utxo tx + & label ("Fanout size: " <> prettyLength (countAssets $ txOuts' tx)) where maxSupported = 44 diff --git a/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs b/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs index 92dbc28e98e..f4f40d74f63 100644 --- a/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs +++ b/hydra-node/test/Hydra/Chain/Direct/TxTraceSpec.hs @@ -23,13 +23,16 @@ import Test.Hydra.Prelude import Cardano.Api.UTxO (UTxO) import Cardano.Api.UTxO qualified as UTxO -import Data.List ((\\)) +import Data.List (nub, (\\)) import Data.Map.Strict qualified as Map import Data.Time.Clock.POSIX (posixSecondsToUTCTime) import Hydra.Cardano.Api ( PaymentKey, SlotNo (..), + TxId, VerificationKey, + getTxBody, + getTxId, lovelaceToValue, mkTxOutDatumInline, modifyTxOutValue, @@ -37,19 +40,10 @@ import Hydra.Cardano.Api ( throwError, txOutAddress, txOutValue, + txSpendingUTxO, ) import Hydra.Cardano.Api.Pretty (renderTxWithUTxO) -import Hydra.Chain.Direct.State ( - ChainContext (..), - CloseTxError, - ContestTxError, - DecrementTxError, - FanoutTxError, - close, - contest, - decrement, - fanout, - ) +import Hydra.Chain.Direct.State (ChainContext (..), CloseTxError, ContestTxError, DecrementTxError, FanoutTxError, IncrementTxError (..), close, contest, decrement, fanout, increment) import Hydra.Chain.Direct.Tx ( HeadObservation (NoHeadTx), observeHeadTx, @@ -58,14 +52,16 @@ import Hydra.Chain.Direct.Tx qualified as Tx import Hydra.Contract.HeadState qualified as Head import Hydra.Ledger.Cardano (Tx, adjustUTxO) import Hydra.Ledger.Cardano.Evaluate (evaluateTx) +import Hydra.Tx (CommitBlueprintTx (..)) import Hydra.Tx.ContestationPeriod qualified as CP import Hydra.Tx.Crypto (MultiSignature, aggregate, sign) +import Hydra.Tx.Deposit (depositTx) import Hydra.Tx.HeadId (headIdToCurrencySymbol, mkHeadId) import Hydra.Tx.Init (mkHeadOutput) import Hydra.Tx.IsTx (hashUTxO, utxoFromTx) import Hydra.Tx.Party (partyToChain) import Hydra.Tx.ScriptRegistry (ScriptRegistry, registryUTxO) -import Hydra.Tx.Snapshot (ConfirmedSnapshot (..), Snapshot (..), SnapshotNumber (..), SnapshotVersion (..), number) +import Hydra.Tx.Snapshot (ConfirmedSnapshot (..), Snapshot (..), SnapshotNumber (..), SnapshotVersion (..), getSnapshot, number) import PlutusTx.Builtins (toBuiltin) import Test.Hydra.Tx.Fixture (alice, bob, carol, testNetworkId) import Test.Hydra.Tx.Fixture qualified as Fixture @@ -77,7 +73,7 @@ import Test.Hydra.Tx.Gen ( genVerificationKey, ) import Test.Hydra.Tx.Mutation (addParticipationTokens) -import Test.QuickCheck (Confidence (..), Property, Smart (..), Testable, checkCoverage, checkCoverageWith, cover, elements, frequency, ioProperty, shuffle, sublistOf, (===)) +import Test.QuickCheck (Confidence (..), Property, Smart (..), Testable, checkCoverage, checkCoverageWith, cover, elements, frequency, ioProperty, (===)) import Test.QuickCheck.Monadic (monadic) import Test.QuickCheck.StateModel ( ActionWithPolarity (..), @@ -116,13 +112,14 @@ coversInterestingActions (Actions_ _ (Smart _ steps)) p = p & cover 1 (null steps) "empty" & cover 50 (hasSomeSnapshots steps) "has some snapshots" + & cover 5 (hasDeposit steps) "has deposits" + & cover 5 (hasIncrement steps) "has increments" & cover 5 (hasDecrement steps) "has decrements" - & cover 0.1 (countContests steps >= 2) "has multiple contests" + & cover 0.05 (countContests steps >= 2) "has multiple contests" & cover 5 (closeNonInitial steps) "close with non initial snapshots" & cover 10 (hasFanout steps) "reach fanout" - & cover 10 (fanoutWithEmptyUTxO steps) "fanout with empty UTxO" & cover 10 (fanoutWithSomeUTxO steps) "fanout with some UTxO" - & cover 10 (fanoutWithDelta steps) "fanout with additional UTxO to distribute" + & cover 10 (fanoutWithCommitOrDecommitDelta steps) "fanout with additional de/commit UTxO to distribute" where hasSomeSnapshots = any $ @@ -131,6 +128,7 @@ coversInterestingActions (Actions_ _ (Smart _ steps)) p = polarity == PosPolarity _ -> False + hasUTxOToCommit snapshot = not . null $ toCommit snapshot hasUTxOToDecommit snapshot = not . null $ toDecommit snapshot hasFanout = @@ -139,14 +137,6 @@ coversInterestingActions (Actions_ _ (Smart _ steps)) p = Fanout{} -> polarity == PosPolarity _ -> False - fanoutWithEmptyUTxO = - any $ - \(_ := ActionWithPolarity{polarAction, polarity}) -> case polarAction of - Fanout{utxo} -> - polarity == PosPolarity - && null utxo - _ -> False - fanoutWithSomeUTxO = any $ \(_ := ActionWithPolarity{polarAction, polarity}) -> case polarAction of @@ -155,12 +145,12 @@ coversInterestingActions (Actions_ _ (Smart _ steps)) p = && not (null utxo) _ -> False - fanoutWithDelta = + fanoutWithCommitOrDecommitDelta = any $ \(_ := ActionWithPolarity{polarAction, polarity}) -> case polarAction of - Fanout{deltaUTxO} -> + Fanout{alphaUTxO, omegaUTxO} -> polarity == PosPolarity - && not (null deltaUTxO) + && (not (null alphaUTxO) || not (null omegaUTxO)) _ -> False countContests = @@ -176,6 +166,19 @@ coversInterestingActions (Actions_ _ (Smart _ steps)) p = Close{snapshot} -> snapshot > 0 _ -> False + hasDeposit = + all $ + \(_ := ActionWithPolarity{polarAction, polarity}) -> case polarAction of + Deposit{} -> + polarity == PosPolarity + _ -> False + hasIncrement = + all $ + \(_ := ActionWithPolarity{polarAction, polarity}) -> case polarAction of + Increment{snapshot} -> + polarity == PosPolarity + && hasUTxOToCommit snapshot + _ -> False hasDecrement = all $ \(_ := ActionWithPolarity{polarAction, polarity}) -> case polarAction of @@ -194,12 +197,12 @@ prop_runActions actions = where runAppMProperty :: AppM Property -> Property runAppMProperty action = ioProperty $ do - localState <- newIORef openHeadUTxO + localState <- newIORef (Nothing, openHeadUTxO) runReaderT (runAppM action) localState -- * ============================== MODEL WORLD ========================== -data SingleUTxO = A | B | C | D | E +data SingleUTxO = A | B | C | D | E | F | G | H | I deriving (Show, Eq, Ord, Enum, Generic) instance Arbitrary SingleUTxO where @@ -213,9 +216,11 @@ data Model = Model , knownSnapshots :: [ModelSnapshot] -- ^ List of off-chain snapshots, from most recent to oldest. , currentVersion :: SnapshotVersion + , currentSnapshotNumber :: SnapshotNumber , closedSnapshotNumber :: SnapshotNumber , alreadyContested :: [Actor] , utxoInHead :: ModelUTxO + , pendingDeposit :: ModelUTxO , -- XXX: This is used in two ways, to track pending decommits for generating -- snapshots and to remember the pending (delta) utxo during close/fanout pendingDecommit :: ModelUTxO @@ -233,6 +238,7 @@ data ModelSnapshot = ModelSnapshot { version :: SnapshotVersion , number :: SnapshotNumber , inHead :: ModelUTxO + , toCommit :: ModelUTxO , toDecommit :: ModelUTxO } deriving (Show, Eq, Ord, Generic) @@ -248,6 +254,7 @@ instance Num ModelSnapshot where { version = UnsafeSnapshotVersion 0 , number = UnsafeSnapshotNumber $ fromMaybe 0 $ integerToNatural x , inHead = mempty + , toCommit = mempty , toDecommit = mempty } @@ -279,10 +286,12 @@ data TxResult = TxResult instance StateModel Model where data Action Model a where NewSnapshot :: {newSnapshot :: ModelSnapshot} -> Action Model () + Deposit :: {utxoToDeposit :: ModelUTxO} -> Action Model TxResult + Increment :: {actor :: Actor, snapshot :: ModelSnapshot} -> Action Model TxResult Decrement :: {actor :: Actor, snapshot :: ModelSnapshot} -> Action Model TxResult Close :: {actor :: Actor, snapshot :: ModelSnapshot} -> Action Model TxResult Contest :: {actor :: Actor, snapshot :: ModelSnapshot} -> Action Model TxResult - Fanout :: {utxo :: ModelUTxO, deltaUTxO :: ModelUTxO} -> Action Model TxResult + Fanout :: {utxo :: ModelUTxO, alphaUTxO :: ModelUTxO, omegaUTxO :: ModelUTxO} -> Action Model TxResult -- \| Helper action to identify the terminal state 'Final' and shorten -- traces using the 'precondition'. Stop :: Action Model () @@ -292,19 +301,29 @@ instance StateModel Model where { headState = Open , knownSnapshots = [] , currentVersion = 0 + , currentSnapshotNumber = 0 , closedSnapshotNumber = 0 , alreadyContested = [] , utxoInHead = fromList [A, B, C] + , pendingDeposit = mempty , pendingDecommit = mempty } arbitraryAction :: VarContext -> Model -> Gen (Any (Action Model)) - arbitraryAction _lookup Model{headState, knownSnapshots, currentVersion, utxoInHead, pendingDecommit} = + arbitraryAction _lookup Model{headState, currentSnapshotNumber, knownSnapshots, currentVersion, utxoInHead, pendingDeposit, pendingDecommit} = case headState of Open{} -> frequency $ - [(3, Some . NewSnapshot <$> genSnapshot)] - <> [ ( 3 + [(1, Some . NewSnapshot <$> genSnapshot)] + <> [ ( 2 + , do + actor <- elements allActors + snapshot <- elements knownSnapshots + pure $ Some Increment{actor, snapshot} + ) + | not (null knownSnapshots) -- XXX: DRY this check + ] + <> [ ( 5 , do actor <- elements allActors snapshot <- elements knownSnapshots @@ -312,7 +331,14 @@ instance StateModel Model where ) | not (null knownSnapshots) -- XXX: DRY this check ] - <> [ ( 1 + <> [ + ( 1 + , do + toCommit <- arbitrary + pure $ Some Deposit{utxoToDeposit = take 1 $ nub $ filter (`notElem` utxoInHead) toCommit} + ) + ] + <> [ ( 5 , do actor <- elements allActors snapshot <- elements knownSnapshots @@ -320,19 +346,30 @@ instance StateModel Model where ) | not (null knownSnapshots) ] + <> [ + ( 5 + , do + actor <- elements allActors + snapshot <- genCloseWithDecrement + pure $ Some $ Close{actor, snapshot = snapshot} + ) + ] Closed{} -> frequency $ - ( 1 + ( 5 , do -- Fanout with the currently known model state. + omegaUTxO <- frequency [(1, pure pendingDecommit), (1, pure mempty), (5, arbitrary)] + alphaUTxO' <- frequency [(1, if null pendingDeposit then arbitrary else elements pendingDeposit), (1, arbitrary)] pure $ Some $ Fanout { utxo = utxoInHead - , deltaUTxO = pendingDecommit + , alphaUTxO = [alphaUTxO'] + , omegaUTxO } ) - : [ ( 10 + : [ ( 5 , do actor <- elements allActors snapshot <- elements knownSnapshots @@ -340,41 +377,92 @@ instance StateModel Model where ) | not (null knownSnapshots) ] + <> [ + ( 5 + , do + actor <- elements allActors + snapshot <- genContest + pure $ Some $ Contest{actor, snapshot} + ) + ] Final -> pure $ Some Stop where + genContest = do + pure + ModelSnapshot + { version = currentVersion + , number = latestSnapshotNumber knownSnapshots + 1 + , inHead = frequency [(1, pure utxoInHead), (3, pure mempty)] `generateWith` 42 + , toCommit = mempty + , toDecommit = mempty + } + genCloseWithDecrement = do + pure + ModelSnapshot + { version = currentVersion + 1 + , number = latestSnapshotNumber knownSnapshots + 1 + , inHead = utxoInHead + , toCommit = mempty + , toDecommit = mempty + } + genSnapshot = do - -- Only decommit if not already pending - toDecommit <- - if null pendingDecommit - then sublistOf utxoInHead - else pure pendingDecommit - inHead <- shuffle $ utxoInHead \\ toDecommit - let validSnapshot = + let defaultSnapshot = ModelSnapshot { version = currentVersion , number = latestSnapshotNumber knownSnapshots + 1 - , inHead - , toDecommit + , inHead = frequency [(1, pure utxoInHead), (3, pure mempty)] `generateWith` 42 + , toCommit = mempty + , toDecommit = mempty } - pure validSnapshot + frequency + [ (3, pure defaultSnapshot) + , (3, pure $ defaultSnapshot{version = currentVersion + 1, toCommit = nub $ filter (`notElem` utxoInHead) pendingDeposit}) + , if currentSnapshotNumber > 0 + then + ( 3 + , do + let toDecommit' = take 1 utxoInHead + case toDecommit' of + [] -> pure defaultSnapshot + _ -> pure $ defaultSnapshot{version = currentVersion + 1, toDecommit = toDecommit'} + ) + else (3, pure defaultSnapshot) + ] -- Determine actions we want to perform and expect to work. If this is False, -- validFailingAction is checked too. precondition :: Model -> Action Model a -> Bool - precondition Model{headState, knownSnapshots, closedSnapshotNumber, alreadyContested, currentVersion, utxoInHead, pendingDecommit} = \case + precondition Model{headState, knownSnapshots, currentSnapshotNumber, closedSnapshotNumber, alreadyContested, currentVersion, pendingDeposit, pendingDecommit} = \case Stop -> headState /= Final NewSnapshot{newSnapshot} -> - newSnapshot.version == currentVersion + (newSnapshot.version == currentVersion || newSnapshot.version == currentVersion + 1) && newSnapshot.number > latestSnapshotNumber knownSnapshots + Deposit{utxoToDeposit} -> + headState == Open + && utxoToDeposit /= mempty + && currentSnapshotNumber > 0 + Increment{snapshot} -> + headState == Open + && snapshot `elem` knownSnapshots + && pendingDeposit /= mempty + && snapshot.toCommit == pendingDeposit + && snapshot.version == currentVersion + && currentSnapshotNumber > 0 Decrement{snapshot} -> headState == Open && snapshot `elem` knownSnapshots && snapshot.version == currentVersion + && pendingDecommit /= mempty + && snapshot.toDecommit == pendingDecommit + && currentSnapshotNumber > 0 Close{snapshot} -> headState == Open && snapshot `elem` knownSnapshots + && (pendingDeposit == snapshot.toCommit && pendingDecommit == snapshot.toDecommit) + && (if snapshot.version == currentVersion then snapshot.toCommit == mempty && snapshot.toDecommit == mempty else snapshot.toCommit /= mempty || snapshot.toDecommit /= mempty) && ( if snapshot.number == 0 - then inHead snapshot == initialUTxOInHead + then snapshot.inHead == initialUTxOInHead else snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) ) @@ -382,71 +470,107 @@ instance StateModel Model where Model{utxoInHead = initialUTxOInHead} = initialState Contest{actor, snapshot} -> headState == Closed - && snapshot `elem` knownSnapshots - && actor `notElem` alreadyContested - && snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) + && ((snapshot.version == currentVersion) && (snapshot.toCommit == mempty && snapshot.toDecommit == mempty)) && snapshot.number > closedSnapshotNumber - Fanout{utxo, deltaUTxO} -> - headState == Closed - && utxo == utxoInHead - && deltaUTxO == pendingDecommit + && snapshot.number > currentSnapshotNumber + && actor `notElem` alreadyContested + Fanout{alphaUTxO, omegaUTxO} -> + (alphaUTxO == mempty || omegaUTxO == mempty) + && headState == Closed -- Determine actions we want to perform and want to see failing. If this is -- False, the action is discarded (e.g. it's invalid or we don't want to see -- it tried to perform). validFailingAction :: Model -> Action Model a -> Bool - validFailingAction Model{headState, knownSnapshots, currentVersion} = \case + validFailingAction Model{headState, currentSnapshotNumber, closedSnapshotNumber, alreadyContested, knownSnapshots, currentVersion, pendingDeposit, pendingDecommit} = \case Stop -> False NewSnapshot{} -> False + Deposit{utxoToDeposit} -> + headState == Open + && utxoToDeposit /= mempty + && pendingDeposit == mempty + && pendingDecommit /= mempty + && currentSnapshotNumber > 0 + Increment{snapshot} -> + headState == Open + && snapshot `elem` knownSnapshots + && pendingDeposit /= mempty + && snapshot.toCommit == pendingDeposit + && currentSnapshotNumber > 0 -- Only filter non-matching states as we are not interested in these kind of -- verification failures. Decrement{snapshot} -> headState == Open && snapshot `elem` knownSnapshots - && snapshot.version /= currentVersion + && snapshot.version == currentVersion + && not (null snapshot.toDecommit) + && snapshot.toDecommit == pendingDecommit + && currentSnapshotNumber > 0 Close{snapshot} -> headState == Open && snapshot `elem` knownSnapshots - && ( snapshot.number == 0 - || snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) + && (pendingDeposit == snapshot.toCommit && pendingDecommit == snapshot.toDecommit) + && (if snapshot.version == currentVersion then snapshot.toCommit == mempty && snapshot.toDecommit == mempty else snapshot.toCommit /= mempty || snapshot.toDecommit /= mempty) + && ( if snapshot.number == 0 + then snapshot.inHead == initialUTxOInHead + else + snapshot.version `elem` (currentVersion : [currentVersion - 1 | currentVersion > 0]) ) - Contest{snapshot} -> + where + Model{utxoInHead = initialUTxOInHead} = initialState + Contest{actor, snapshot} -> headState == Closed - && snapshot `elem` knownSnapshots + && ((snapshot.version == currentVersion) && (snapshot.toCommit == mempty && snapshot.toDecommit == mempty)) + && snapshot.number > closedSnapshotNumber + && snapshot.number > currentSnapshotNumber + && actor `notElem` alreadyContested Fanout{} -> headState == Closed nextState :: Model -> Action Model a -> Var a -> Model - nextState m@Model{currentVersion} t _result = + nextState m@Model{} t _result = case t of Stop -> m NewSnapshot{newSnapshot} -> m - { knownSnapshots = newSnapshot : m.knownSnapshots + { knownSnapshots = nub $ newSnapshot : m.knownSnapshots , pendingDecommit = newSnapshot.toDecommit + , currentSnapshotNumber = newSnapshot.number + } + Deposit{utxoToDeposit} -> + m + { headState = Open + , pendingDeposit = utxoToDeposit + } + Increment{snapshot} -> + m + { headState = Open + , currentVersion = snapshot.version + , utxoInHead = m.utxoInHead <> snapshot.toCommit + , pendingDeposit = mempty + , currentSnapshotNumber = snapshot.number } Decrement{snapshot} -> m { headState = Open - , currentVersion = m.currentVersion + 1 + , currentVersion = snapshot.version , utxoInHead = m.utxoInHead \\ snapshot.toDecommit , pendingDecommit = mempty + , currentSnapshotNumber = snapshot.number } Close{snapshot} -> m { headState = Closed + , currentVersion = snapshot.version , closedSnapshotNumber = snapshot.number + , currentSnapshotNumber = snapshot.number , alreadyContested = [] - , utxoInHead = snapshot.inHead - , pendingDecommit = if currentVersion == snapshot.version then toDecommit snapshot else mempty } Contest{actor, snapshot} -> m { headState = Closed - , closedSnapshotNumber = snapshot.number , alreadyContested = actor : alreadyContested m - , utxoInHead = snapshot.inHead - , pendingDecommit = if currentVersion == snapshot.version then toDecommit snapshot else mempty + , currentSnapshotNumber = snapshot.number } Fanout{} -> m{headState = Final} @@ -463,18 +587,18 @@ deriving instance Show (Action Model a) -- | Application monad to perform model actions. Currently it only keeps a -- 'UTxO' which is updated whenever transactions are valid in 'performTx'. -newtype AppM a = AppM {runAppM :: ReaderT (IORef UTxO) IO a} +newtype AppM a = AppM {runAppM :: ReaderT (IORef (Maybe TxId, UTxO)) IO a} deriving newtype (Functor, Applicative, Monad, MonadIO, MonadFail, MonadThrow) -instance MonadReader UTxO AppM where +instance MonadReader (Maybe TxId, UTxO) AppM where ask = AppM $ ask >>= liftIO . readIORef local f action = do - utxo <- ask - r <- newIORef (f utxo) + txidAndutxo <- ask + r <- newIORef (f txidAndutxo) AppM $ local (const r) $ runAppM action -instance MonadState UTxO AppM where +instance MonadState (Maybe TxId, UTxO) AppM where get = ask put utxo = AppM $ ask >>= liftIO . flip writeIORef utxo @@ -487,18 +611,24 @@ type instance Realized AppM a = a instance RunModel Model AppM where perform Model{currentVersion} action _lookupVar = do case action of - Decrement{actor, snapshot} -> do + deposit@Deposit{utxoToDeposit} -> do + tx <- newDepositTx deposit utxoToDeposit + performTx deposit tx + i@Increment{actor, snapshot} -> do + tx <- newIncrementTx actor (confirmedSnapshot snapshot) + performTx i tx + d@Decrement{actor, snapshot} -> do tx <- newDecrementTx actor (confirmedSnapshot snapshot) - performTx tx - Close{actor, snapshot} -> do + performTx d tx + c@Close{actor, snapshot} -> do tx <- newCloseTx actor currentVersion (confirmedSnapshot snapshot) - performTx tx - Contest{actor, snapshot} -> do + performTx c tx + c@Contest{actor, snapshot} -> do tx <- newContestTx actor currentVersion (confirmedSnapshot snapshot) - performTx tx - Fanout{utxo, deltaUTxO} -> do - tx <- newFanoutTx Alice utxo deltaUTxO - performTx tx + performTx c tx + f@Fanout{utxo, alphaUTxO, omegaUTxO} -> do + tx <- newFanoutTx Alice utxo alphaUTxO omegaUTxO + performTx f tx NewSnapshot{} -> pure () Stop -> pure () @@ -506,6 +636,12 @@ instance RunModel Model AppM where counterexample' (show modelBefore) counterexample' (show action) case action of + Deposit{} -> expectValid result $ \case + Tx.Deposit{} -> pure () + _ -> fail "Expected Deposit" + Increment{} -> expectValid result $ \case + Tx.Increment{} -> pure () + _ -> fail "Expected Increment" Decrement{} -> expectValid result $ \case Tx.Decrement{} -> pure () _ -> fail "Expected Decrement" @@ -517,7 +653,7 @@ instance RunModel Model AppM where counterexample' $ "Wrong contesters: expected " <> show (alreadyContested modelAfter) <> ", got " <> show contesters guard $ length contesters == length (alreadyContested modelAfter) _ -> fail "Expected Contest" - Fanout{utxo, deltaUTxO} -> do + Fanout{utxo, omegaUTxO} -> do case result of TxResult{constructedTx = Left err} -> fail $ "Failed to construct transaction: " <> err TxResult{constructedTx = Right tx} -> do @@ -526,17 +662,20 @@ instance RunModel Model AppM where -- exactly. let sorted = sortOn (\o -> (txOutAddress o, selectLovelace (txOutValue o))) . toList let fannedOut = utxoFromTx tx - guard $ sorted fannedOut == sorted (realWorldModelUTxO utxo <> realWorldModelUTxO deltaUTxO) + guard $ sorted fannedOut == sorted (realWorldModelUTxO utxo <> realWorldModelUTxO omegaUTxO) expectValid result $ \case Tx.Fanout{} -> pure () _ -> fail "Expected Fanout" - _ -> pure () + NewSnapshot{} -> pure () + Stop -> pure () postconditionOnFailure (modelBefore, _modelAfter) action _lookup result = runPostconditionM' $ do counterexample' (show modelBefore) counterexample' (show action) case action of + Deposit{} -> either (const fulfilled) expectInvalid result + Increment{} -> either (const fulfilled) expectInvalid result Decrement{} -> either (const fulfilled) expectInvalid result Close{} -> either (const fulfilled) expectInvalid result Contest{} -> either (const fulfilled) expectInvalid result @@ -546,11 +685,11 @@ instance RunModel Model AppM where -- | Perform a transaction by evaluating and observing it. This updates the -- 'UTxO' in the 'AppM' if a transaction is valid and produces a 'TxResult' that -- can be used to assert expected success / failure. -performTx :: Show err => Either err Tx -> AppM TxResult -performTx result = +performTx :: Show err => Action Model a -> Either err Tx -> AppM TxResult +performTx action result = case result of Left err -> do - utxo <- get + (_, utxo) <- get pure TxResult { constructedTx = Left $ show err @@ -559,10 +698,14 @@ performTx result = , observation = NoHeadTx } Right tx -> do - utxo <- get + (depositTxId, utxo) <- get let validationError = getValidationError tx utxo when (isNothing validationError) $ do - put $ adjustUTxO tx utxo + let adjusted = + case action of + Deposit{} -> (Just . getTxId . getTxBody $ tx, adjustUTxO tx utxo) + _ -> (depositTxId, adjustUTxO tx utxo) + put adjusted let observation = observeHeadTx Fixture.testNetworkId utxo tx pure TxResult @@ -614,7 +757,7 @@ signedSnapshot ms = , number = ms.number , confirmed = [] , utxo - , utxoToCommit = Nothing + , utxoToCommit , utxoToDecommit } @@ -626,6 +769,10 @@ signedSnapshot ms = let u = realWorldModelUTxO (toDecommit ms) in if null u then Nothing else Just u + utxoToCommit = + let u = realWorldModelUTxO (toCommit ms) + in if null u then Nothing else Just u + -- | A confirmed snapshot (either initial or later confirmed), based onTxTra -- 'signedSnapshot'. confirmedSnapshot :: ModelSnapshot -> ConfirmedSnapshot Tx @@ -668,10 +815,44 @@ openHeadUTxO = inHeadUTxO = realWorldModelUTxO (utxoInHead initialState) +-- | Creates a deposit transaction using given UTxO. +newDepositTx :: Action Model a -> ModelUTxO -> AppM (Either String Tx) +newDepositTx _ utxoToDeposit = do + let deadline = Fixture.depositDeadline + let depositUTxO = realWorldModelUTxO utxoToDeposit + let blueprint = CommitBlueprintTx{blueprintTx = txSpendingUTxO depositUTxO, lookupUTxO = depositUTxO} + pure $ + Right $ + depositTx + Fixture.testNetworkId + (mkHeadId Fixture.testPolicyId) + blueprint + deadline + +-- | Creates a increment transaction using given utxo and given snapshot. +newIncrementTx :: Actor -> ConfirmedSnapshot Tx -> AppM (Either IncrementTxError Tx) +newIncrementTx actor snapshot = do + let Snapshot{utxoToCommit} = getSnapshot snapshot + case utxoToCommit of + Nothing -> pure $ Left SnapshotMissingIncrementUTxO + Just _ -> do + (depositTxId, spendableUTxO) <- get + let slotNo = SlotNo 0 + let txid = fromMaybe (error "No deposit txid") depositTxId + pure $ + increment + (actorChainContext actor) + spendableUTxO + (mkHeadId Fixture.testPolicyId) + Fixture.testHeadParameters + snapshot + txid + slotNo + -- | Creates a decrement transaction using given utxo and given snapshot. newDecrementTx :: Actor -> ConfirmedSnapshot Tx -> AppM (Either DecrementTxError Tx) newDecrementTx actor snapshot = do - spendableUTxO <- get + (_, spendableUTxO) <- get pure $ decrement (actorChainContext actor) @@ -686,7 +867,7 @@ newDecrementTx actor snapshot = do -- contestation deadline of 0 + cperiod. newCloseTx :: Actor -> SnapshotVersion -> ConfirmedSnapshot Tx -> AppM (Either CloseTxError Tx) newCloseTx actor openVersion snapshot = do - spendableUTxO <- get + (_, spendableUTxO) <- get pure $ close (actorChainContext actor) @@ -707,7 +888,7 @@ newCloseTx actor openVersion snapshot = do -- claims to contest at time 0. newContestTx :: Actor -> SnapshotVersion -> ConfirmedSnapshot Tx -> AppM (Either ContestTxError Tx) newContestTx actor openVersion snapshot = do - spendableUTxO <- get + (_, spendableUTxO) <- get pure $ contest (actorChainContext actor) @@ -723,9 +904,9 @@ newContestTx actor openVersion snapshot = do -- | Creates a fanout transaction using given utxo. NOTE: This uses fixtures for -- seedTxIn and contestation period. Consequently, the lower bound used is -- precisely at the maximum deadline slot as if everyone contested. -newFanoutTx :: Actor -> ModelUTxO -> ModelUTxO -> AppM (Either FanoutTxError Tx) -newFanoutTx actor utxo pendingDecommit = do - spendableUTxO <- get +newFanoutTx :: Actor -> ModelUTxO -> ModelUTxO -> ModelUTxO -> AppM (Either FanoutTxError Tx) +newFanoutTx actor utxo pendingCommit pendingDecommit = do + (_, spendableUTxO) <- get pure $ fanout (actorChainContext actor) @@ -733,6 +914,7 @@ newFanoutTx actor utxo pendingDecommit = do Fixture.testSeedInput (realWorldModelUTxO utxo) -- Model world has no 'Maybe ModelUTxO', but real world does. + (if null pendingCommit then Nothing else Just $ realWorldModelUTxO pendingCommit) (if null pendingDecommit then Nothing else Just $ realWorldModelUTxO pendingDecommit) deadline where diff --git a/hydra-node/test/Hydra/OptionsSpec.hs b/hydra-node/test/Hydra/OptionsSpec.hs index a5b5dac1287..d001b9f27a6 100644 --- a/hydra-node/test/Hydra/OptionsSpec.hs +++ b/hydra-node/test/Hydra/OptionsSpec.hs @@ -6,6 +6,7 @@ import Test.Hydra.Prelude import Hydra.Cardano.Api ( ChainPoint (..), NetworkId (..), + TxId, serialiseToRawBytesHexText, ) import Hydra.Chain (maximumNumberOfParties) @@ -265,11 +266,12 @@ spec = parallel $ { chainConfig = Direct defaultDirectChainConfig{startChainFrom = Just ChainPointAtGenesis} } - prop "parses --hydra-scripts-tx-id as a tx id" $ \txId -> - ["--hydra-scripts-tx-id", toString $ serialiseToRawBytesHexText txId] + prop "parses --hydra-scripts-tx-id as a tx id" $ \(txIds :: NonEmpty TxId) -> do + let lineToParse = intercalate "," $ toString . serialiseToRawBytesHexText <$> toList txIds + ["--hydra-scripts-tx-id", lineToParse] `shouldParse` Run defaultRunOptions - { chainConfig = Direct defaultDirectChainConfig{hydraScriptsTxId = txId} + { chainConfig = Direct defaultDirectChainConfig{hydraScriptsTxId = toList txIds} } it "switches to offline chain when using --initial-utxo" $ diff --git a/hydra-plutus/plutus.json b/hydra-plutus/plutus.json index fc8f0118f4f..4b655a90b2d 100644 --- a/hydra-plutus/plutus.json +++ b/hydra-plutus/plutus.json @@ -6,7 +6,7 @@ "plutusVersion": "v3", "compiler": { "name": "Aiken", - "version": "v1.1.4+c7ae161" + "version": "v1.1.5+a7741ec" }, "license": "Apache-2.0" }, @@ -36,6 +36,31 @@ "compiledCode": "5902ac010100323232323232323232322533300332323232325332330093001300b37540042646464a66666602800c2646464a66601e60060022a66602660246ea80245400803854ccc03cc01c00454ccc04cc048dd50048a80100700718081baa0081533300d3001300f37540042646464646464a6660266016602a6ea80344cc00cc01130103d87980003370e6660026eacc064c068c068c068c068c058dd50079bae30053016375400c91010b487964726148656164563100480044c94ccc050c020c058dd50008998021802a6103d87a8000300c333002375660346036602e6ea8c068c05cdd50009bae30063017375400e9110b4879647261486561645631001533015491054c35373b39001632533301800114c103d87a80001300333019301a0014bd701bac30053016375401e44464a66602c601c60306ea8004520001375a603860326ea8004c94ccc058c038c060dd50008a6103d87a8000132330010013756603a60346ea8008894ccc070004530103d87a8000132323232533301c337220100042a66603866e3c0200084c02ccc084dd4000a5eb80530103d87a8000133006006003375a603c0066eb8c070008c080008c078004c8cc004004010894ccc06c0045300103d87a8000132323232533301b337220100042a66603666e3c0200084c028cc080dd3000a5eb80530103d87a80001330060060033756603a0066eb8c06c008c07c008c074004dd2a400044a666024002294454cc04c0085894ccc040c010c048dd50008a4903433031001491034330320023015301630160013013301037540042a6601c9201054c34373b350016370e900000580580580598089809001180800098061baa002370e90010b1806980700118060009806001180500098031baa00114984d95854cc0092401054c34333b3500165734ae7155ceaab9e5573eae815d0aba257481", "hash": "3e5a776bcee213e3dfd15806952a10ac5590e3e97d09d62eb99266b2" }, + { + "title": "deposit.deposit.spend", + "datum": { + "title": "datum", + "schema": { + "$ref": "#/definitions/deposit~1Datum" + } + }, + "redeemer": { + "title": "redeemer", + "schema": { + "$ref": "#/definitions/deposit~1Redeemer" + } + }, + "compiledCode": "590458010100323232323232323232322533300332323232325332330093001300b37540042646464a66666602800c2646464a66601e6006002264a66602800201e264a666666032002020020020020264a66602c60320062a00a0226eb8004c058004c048dd50048a9998079803800899299980a000807899299999980c800808008008099299980b180c8018a8028089bad00101030160013012375401201c60206ea802054ccc034c004c03cdd5001099191919191929998099803980a9baa00d13253330143300430054c103d87e80003371e6eb8c00cc05cdd50038008998021802a60103d87980003322325333017300f30193754002266e24dd6980e980d1baa00100213300730084c103d87a80004a0600a60326ea8c010c064dd50011803180b9baa010375a6004602e6ea801c5281bae30193016375401a264a66602866008600a980103d87c80003322325333017300f30193754002266e20008dd6980e980d1baa00113300730084c103d87b80004a0600a60326ea8c014c064dd50011803180b9baa010375a6004602e6ea801c4c8c8c8c8cc020c02530103d87d80003371e646e48004ccc00ccc008ccc004004dd61802180d9baa01400523766002911002233714004002646e48004ccc00ccc008c8cc004004dd61802980e1baa00c22533301e00114bd70099911919800800801912999811000899811801a5eb804c8c94ccc080cdd79991192999811980d98129baa001133225333025337100040022980103d879800015333025337100020042980103d87b800014c103d87a8000375a6022604c6ea800cdd6980898131baa002100133225333024337200040022980103d8798000153330243371e0040022980103d87a800014c103d87b8000375c6022604a6ea8008dd7180898129baa001300f3023375400a601e60466ea800930103d8798000133025005003133025002330040040013026002302400133002002302100130200012375c600e60386ea80052201002233714004002444a66603466e24005200014bd700a99980f0010a5eb804cc07cc080008ccc00c00cc084008cdc0000a400244646600200200644a66603c002297ae013301f37526006604000266004004604200244464666002002008006444a66603e004200226660060066044004660080026eb8c0840088c06cc070c0700045281bad30193016375401a4603260340024603000244a666024002294454cc04c008528119299980898028008a490344303100153330113009001149010344303200153330113370e90020008a490344303300153330113370e90030008a490344303400153330113370e90040008a49034430350014910344303600301237540024602a602c602c602c602c602c602c602c002602660206ea800854cc039241054c35353b350016370e900000580580580598089809001180800098061baa002370e90010b1806980700118060009806001180500098031baa00114984d95854cc0092401054c35313b3500165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "de09cec5f84eedaf64186cb52ba4ee6e74e6fc368af25b90d457f352" + }, + { + "title": "deposit.deposit.else", + "redeemer": { + "schema": {} + }, + "compiledCode": "590458010100323232323232323232322533300332323232325332330093001300b37540042646464a66666602800c2646464a66601e6006002264a66602800201e264a666666032002020020020020264a66602c60320062a00a0226eb8004c058004c048dd50048a9998079803800899299980a000807899299999980c800808008008099299980b180c8018a8028089bad00101030160013012375401201c60206ea802054ccc034c004c03cdd5001099191919191929998099803980a9baa00d13253330143300430054c103d87e80003371e6eb8c00cc05cdd50038008998021802a60103d87980003322325333017300f30193754002266e24dd6980e980d1baa00100213300730084c103d87a80004a0600a60326ea8c010c064dd50011803180b9baa010375a6004602e6ea801c5281bae30193016375401a264a66602866008600a980103d87c80003322325333017300f30193754002266e20008dd6980e980d1baa00113300730084c103d87b80004a0600a60326ea8c014c064dd50011803180b9baa010375a6004602e6ea801c4c8c8c8c8cc020c02530103d87d80003371e646e48004ccc00ccc008ccc004004dd61802180d9baa01400523766002911002233714004002646e48004ccc00ccc008c8cc004004dd61802980e1baa00c22533301e00114bd70099911919800800801912999811000899811801a5eb804c8c94ccc080cdd79991192999811980d98129baa001133225333025337100040022980103d879800015333025337100020042980103d87b800014c103d87a8000375a6022604c6ea800cdd6980898131baa002100133225333024337200040022980103d8798000153330243371e0040022980103d87a800014c103d87b8000375c6022604a6ea8008dd7180898129baa001300f3023375400a601e60466ea800930103d8798000133025005003133025002330040040013026002302400133002002302100130200012375c600e60386ea80052201002233714004002444a66603466e24005200014bd700a99980f0010a5eb804cc07cc080008ccc00c00cc084008cdc0000a400244646600200200644a66603c002297ae013301f37526006604000266004004604200244464666002002008006444a66603e004200226660060066044004660080026eb8c0840088c06cc070c0700045281bad30193016375401a4603260340024603000244a666024002294454cc04c008528119299980898028008a490344303100153330113009001149010344303200153330113370e90020008a490344303300153330113370e90030008a490344303400153330113370e90040008a49034430350014910344303600301237540024602a602c602c602c602c602c602c602c002602660206ea800854cc039241054c35353b350016370e900000580580580598089809001180800098061baa002370e90010b1806980700118060009806001180500098031baa00114984d95854cc0092401054c35313b3500165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "de09cec5f84eedaf64186cb52ba4ee6e74e6fc368af25b90d457f352" + }, { "title": "initial.initial.spend", "datum": { @@ -84,6 +109,12 @@ "$ref": "#/definitions/cardano~1transaction~1OutputReference" } }, + "List$deposit/Commit": { + "dataType": "list", + "items": { + "$ref": "#/definitions/deposit~1Commit" + } + }, "PolicyId": { "title": "PolicyId", "dataType": "bytes" @@ -154,6 +185,75 @@ } ] }, + "deposit/Commit": { + "title": "Commit", + "anyOf": [ + { + "title": "Commit", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "input", + "$ref": "#/definitions/cardano~1transaction~1OutputReference" + }, + { + "title": "preSerializedOutput", + "$ref": "#/definitions/ByteArray" + } + ] + } + ] + }, + "deposit/Datum": { + "title": "Datum", + "anyOf": [ + { + "title": "Datum", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "title": "head_id", + "$ref": "#/definitions/PolicyId" + }, + { + "title": "deadline", + "$ref": "#/definitions/Int" + }, + { + "title": "commits", + "$ref": "#/definitions/List$deposit~1Commit" + } + ] + } + ] + }, + "deposit/Redeemer": { + "title": "Redeemer", + "anyOf": [ + { + "title": "Claim", + "dataType": "constructor", + "index": 0, + "fields": [ + { + "$ref": "#/definitions/PolicyId" + } + ] + }, + { + "title": "Recover", + "dataType": "constructor", + "index": 1, + "fields": [ + { + "$ref": "#/definitions/Int" + } + ] + } + ] + }, "initial/Redeemer": { "title": "Redeemer", "anyOf": [ diff --git a/hydra-plutus/scripts/mHead.plutus b/hydra-plutus/scripts/mHead.plutus index a11a87fbe2b..726c84d70e5 100644 --- a/hydra-plutus/scripts/mHead.plutus +++ b/hydra-plutus/scripts/mHead.plutus @@ -1,5 +1,5 @@ { "type": "PlutusScriptV3", - "description": "hydra-mHead-0.19.0-330-g475541011", - "cborHex": "592b43592b400101003332323232323232323232323232323232323232322222932323232553335734002226464646464646500132323232553335734002226464646464646464646464646464646466666666666646664664664444444444444445001010807c03a01b00c805c02a013008803c01a00b004801c00a00230013574202a60026ae8404cc0b08c8c8c8c954ccd5cd00088c004c084d5d08014c018d5d09aba200208981ea4903505431003370e90000011aab9e00235573a0026ea8004cc0b0004d5d08089191919192a999ab9a001113232800991919192a999ab9a0011180098129aba10029981a1191919192a999ab9a0011180098151aba100208992a999ab9a00111328019bad35742009375a6ae840066eb4d5d09aba20011aba200311304849103505431003370e900100199b8748000008d55cf0011aab9d00137540026ae84d5d1001044c109240103505431003370e90000011aab9e00235573a0026ea8d5d08024c020d5d08014c8c8c8c954ccd5cd00088c00044c954ccd5cd00088c014dd71aba100308992a999ab9a001118019aba1004089822248103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa357420033303075c6ae84d5d10008d5d10009aba200211303c490103505431003370e90000011aab9e00235573a0026ea8004dd69aba100f30013574201c60046004eb4cc0a805cd5d080619980b00cbad3574201664646464aa666ae6800444c8ca00264646464aa666ae68004460026600ceb4d5d08014c014d5d09aba2002089820248103505431003370e90000011aab9e00235573a0026ea8d5d08024c8c8c8c954ccd5cd00088c004cc019d69aba100298029aba13574400411304049103505431003370e90000011aab9e00235573a0026ea8d5d09aba20041191919192a999ab9a0011180108992a999ab9a00111800089820a4903505431003370e900100199b8748000008d55cf0011aab9d00137540024464646464aa666ae68004460042264aa666ae6800446002600e6ae8400c2264aa666ae6800446008226084920103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa00111303a49103505431003370e90000011aab9e00235573a0026ea8d5d0805198153ae3574201266602c464646464aa666ae68004460066eb8d5d0801044c954ccd5cd00088c024c080d5d0801844c954ccd5cd00088c01cc080d5d0802044c954ccd5cd00088c004dd69aba1005980f9aba13574400a11325533357340022300b30213574200c113255333573400223005375a6ae8401e603e6ae84d5d1003844c10124103505431003370e900500399b8748020018cdc3a400c00a66e1d20040043370e900100199b8748000008d55cf0011aab9d001375400204e6ae84020cc00809cd5d08039bae3574200c66602c0306602c052464646464aa666ae68004460042264aa666ae68004460082264aa666ae680044600022607a92103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa0013574200a6605402a6ae84010c004d5d080198009aba135744006604eeb4c051d71aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba20013574400422604c92103505431003370e90000011aab9e00235573a0026ea8d5d0804cd5d0803cc8c8c8c954ccd5cd00088c00cdd71aba100208992a999ab9a0011180498059aba10039980c80c1aba135744006113255333573400223007300b35742008113255333573400223001375a6ae8401660146ae84d5d1002844c954ccd5cd00088c02cc030d5d0803044c954ccd5cd00088c014dd69aba100798051aba13574400e11302b49103505431003370e900500399b8748020018cdc3a400c00a66e1d20040043370e900100199b8748000008d55cf0011aab9d00137546ae84d5d100388c8c8c8c954ccd5cd00088994004dd69aba100398051aba1001991919192a999ab9a00111328049980f00f9aba10039aba10019980f3ae357426ae880046ae8800844c954ccd5cd00088c004cc07807cd5d0801cc8c8c8c954ccd5cd00088c004dd69aba10029bad357426ae8800822606092103505431003370e90000011aab9e00235573a0026ea8d5d09aba200308992a999ab9a001118059998068083ad357420093301f75c6ae84d5d1002044c954ccd5cd00088c01ccc080084d5d0802844c954ccd5cd0008899194034cc08c090d5d08044cc094050d5d08014ccc044051d69aba1001c991919192a999ab9a001118009bad35742005375a6ae84d5d1001044c0d5240103505431003370e90000011aab9e00235573a0026ea8d5d09aba2001911981080100086ae88004d5d100308992a999ab9a00111802998110119aba1007991919192a999ab9a001113302675c6ae8400844c0d1240103505431003370e90000011aab9e00235573a0026ea8d5d09aba200708992a999ab9a00111801089818a4903505431003370e900600419b874802801ccdc3a401000c66e1d20060053370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa357426ae880046ae8800844c099240103505431003370e90000011aab9e00235573a0026ea800488c88c008dd58009811911999aab9f0012800119400e002600c6aae74006600a6aae78005300435744006357420050002323232325533357340022300d3007357420053301675a6ae84d5d1001044c954ccd5cd00088c04cc020d5d0801ccc05dd69aba13574400611325325333573400423003300a3574200b3001357426ae880142264aa666ae6800444ca01660186ae8401e60066ae840066eb4d5d09aba20011aba2006113255333573400223009300c3574200f375a6ae84d5d1003844c954ccd5cd00088c054c034d5d0804044c954ccd5cd00088c044c038d5d0804cdd69aba135744012113255333573400223005375c6ae8402a6eb8d5d09aba200a08992a999ab9a001118039bae35742017375a6ae84d5d1005844c954ccd5cd00088c004c044d5d08064c044d5d09aba200c08992a999ab9a0011180798091aba100d089817a4903505431003370e900a00699b8748048030cdc3a402001666e1d200e00a3370e900600499b8748028020cdc3a401000e66e1d200600623232323255333573400223001375c6ae840082264a64a666ae680084600a60026ae840102264aa666ae68004460066eb8d5d0802cc008d5d09aba2005089817248103505431003370e90020029191919192a999ab9a00111800980a1aba100208992a999ab9a0011180108992a999ab9a00111802089819a48103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa0013370e900100199b8748000008d55cf0011aab9d001375400266e1d20040043370e900100199b8748000008d55cf0011aab9d0013754002464646464aa666ae6800446002600c6ae840082264aa666ae6800446006600e6ae8400c2264aa666ae680044600a6eb8d5d0802044c09524103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa00123232323255333573400223001375c6ae840082264aa666ae68004460066eb8d5d0801844c08d240103505431003370e900100199b8748000008d55cf0011aab9d0013754002464646464aa666ae68004460026eb8d5d08014dd69aba13574400411302149103505431003370e90000011aab9e00235573a0026ea8004d5d100108980da48103505431003370e90000011aab9e00235573a0026ea8006445200322500c92c992c991919192a999ab9a0011180108992a999ab9a00111800089810a4903505431003370e900100199b8748000008d55cf0011aab9d0013754009133014491034d303600593330122232333573400300080119b8f002001301300130159001911001a426603c44b200318004886400a44b264666ae6800600100233710002900044c01800e30020003180122b266028921034d303100323301e22590018c00a442b2b320192290049119199ab9a0018004008cdc780200111900c914802488c8ccd5cd000c00200466e1c00c0048c009180044c0100040013301d22590018c002443003900291001260080024c800c88800d2222222222222222010454cc8c8c8c8a4cc0652401034d30320032333573400300080119b8732593330182232333573400300080119b8f0020015006301b9007911001a4260040031480006466446446004002604a44b20031003910c801488cc020004c01800c90019100124006440028009119b80002001a4000337012b32a0072200245407642b26666660420024464a6464646464a666ae680184564cccd55cf80394008a003001357420113574401040024320032259300500290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b266016018005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c0cc00a42b26666aae7c008a004464650010021aba20043574200700090ac99999981b00091192a999ab9a001115933335573e00450022800c004d5d0801cd5d1001900090c800c8964c0ec00a42b26666aae7c008a004464650010021aba20043574200700090ac980c000c86003001003800918012300246004460041180119b8748000008a004500228011400a43001802805c01e00700122601c9322601a93226018931130094991300849889802a4c8980224c44c00526089800a4c464a64a666ae680084564cccd55cf804940088c8ca002004357440166ae8402a001215933333302c001223255333573400222b26666aae7c008a00450018009aba10039aba20032001219001912c981880148564cccd55cf80114008a0030013574200735744006400243200322593301101200290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26026005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c06000a42b26666aae7c008a004464650010021aba20043574200700090ac981f800c8600300100f805c01e00700123002460048c0088c009180111801230022300246004460041180119b8748000008a004500228011400a4300180380091300249913001498226002931192992999ab9a002115933335573e0165002232328008010d5d10069aba100c80048564cccccc0b800488c954ccd5cd00088ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26066005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964cc04c05000a42b26666aae7c008a00450018009aba10039aba20032001219001912c980a80148564cccd55cf80114008a003001357420073574400640024320032259301a00290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b2603c005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c11c00a42b26666aae7c008a00450018009aba10039aba20032001219001912c982580148564cccd55cf80114008a0030013574200735744006400243200322593302b04f00290ac9999aab9f00228011191940040086ae88010d5d0801c00242b2605800321800c00407e037017809c03e017007801c0048c0091801230022300246004460048c0088c009180111801230022300246004460048c0088c00918011180104600466e1d2000002280114008a004500290c00600200244c0092644c00526089800a4c464aa666ae680044600300208c008cdc3a400c01866e1d200400a3370e9001004119999981400091192a999ab9a001115933335573e0045002232328008010d5d10021aba100380048564c01800643001001460048c008230023370e900000114008a004500228011199999813800914008a004500228008008a004464466666605000245002280100114008a0046050446666aae7c004a00300012c98021aba100290ac98021aba200390c0060060050012300244ca00460066ae88009000259302400190c00400518010cdc3a40000045002280114008a005215900190a80fc5407a44443001002800ccc0204488c88c008004c0a889640062007221330060023004001001a42a03e89811249034d30390048540792220012400513232593301b4901034d3033003302422590018c00a4432005223255333573400222603e00422600e00866e3c008020900191000a264b2b266038921034d30340032333573400300080119b8795990029100122a04121593333330240012232532323232325333573400c22b26666aae7c01ca00450018009aba10089aba20082001219001912c980280148564cccd55cf80114008a0030013574200735744006400243200322593300b00c00290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b2606c005215933335573e0045002232328008010d5d10021aba100380048564cccccc0e400488c954ccd5cd00088ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b2607c005215933335573e0045002232328008010d5d10021aba100380048564c06000643001800801c0048c0091801230022300208c008cdc3a40000045002280114008a00521800c01402e00f00380091300e4991300d4991300c49889804a4c8980424c44c0152644c0112622600293044c005262325325333573400422b26666aae7c024a004464650010021aba200b3574201500090ac99999981780091192a999ab9a001115933335573e00450022800c004d5d0801cd5d1001900090c800c8964c0d000a42b26666aae7c008a00450018009aba10039aba20032001219001912c9980880900148564cccd55cf80114008a003001357420073574400640024320032259301300290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26030005215933335573e0045002232328008010d5d10021aba100380048564c10800643001800807c02e00f003800918012300246004460048c0088c009180111801230022300208c008cdc3a40000045002280114008a00521800c01c0048980124c89800a4c1130014988c94c94ccd5cd00108ac9999aab9f00b28011191940040086ae88034d5d0806400242b26666660620024464aa666ae680044564cccd55cf80114008a003001357420073574400640024320032259303600290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b266026028005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c05400a42b26666aae7c008a00450018009aba10039aba20032001219001912c980d00148564cccd55cf80114008a003001357420073574400640024320032259301e00290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26094005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c13800a42b26666aae7c008a00450018009aba10039aba20032001219001912c9981582900148564cccd55cf801140088c8ca002004357440086ae8400e0012159302c00190c00600203f01b80bc04e01f00b803c00e002460048c009180111801230022300246004460048c0088c009180111801230022300246004460048c0088c008230023370e900000114008a004500228014860030010012260049322600293044c005262325533357340022300180104600466e1d200600c3370e900200519b87480080208cccccc0ac00488c954ccd5cd00088ac9999aab9f00228011191940040086ae88010d5d0801c00242b2600c00321800800a3002460041180119b8748000008a00450022801140088cccccc0a80048a00450022801140040045002232233333302b0012280114008008a0045002302b2233335573e00250018000964c010d5d080148564c010d5d1001c8600300300280091801226500230033574400480012c9813800c860020028c00866e1d2000002280114008a004500290ac800c85408a2a0432222180080140066601622446446004002605a44b20031003910998030011802000800d21502244c095241034d303900485408522200119802889119118010009813912c800c400e4426600c00460080023302522590018c002443003900291000a60080021800c804c88800d13302125933301b2232333573400300080119b8f00200100400190ac800c4c0992401034d303800910c8014896400e2b264666ae680060010023370e0029001460011302a4901034d3038004884c0b12401034d3038001130254901034d30370019812912c800c6001221801c80148800530040010c00640264440068c009159330212590018a80fc8564c090006426603e9201034d31320032333573400300080119b8f001006898132481034d31320048540806604a44b2003180048860072005220024c01000430019009911001a2646603a9201034d3035005932333573400300080119b8f90019110018012264b320032290139119199ab9a0018004008cdc7802001119001914809c88c8ccd5cd000c00200466e1c00c0048c0092003222002460045990029100122a04121593333330240012232532323232325333573400c22b26666aae7c01ca00450018009aba10089aba20082001219001912c980280148564cccd55cf80114008a0030013574200735744006400243200322593300b00c00290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b2606c005215933335573e0045002232328008010d5d10021aba100380048564cccccc0e400488c954ccd5cd00088ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b2607c005215933335573e0045002232328008010d5d10021aba100380048564c06000643001800801c0048c0091801230022300208c008cdc3a40000045002280114008a00521800c01402e00f00380091300e4991300d4991300c49889804a4c8980424c44c0152644c0112622600293044c005262325325333573400422b26666aae7c024a004464650010021aba200b3574201500090ac99999981780091192a999ab9a001115933335573e00450022800c004d5d0801cd5d1001900090c800c8964c0d000a42b26666aae7c008a00450018009aba10039aba20032001219001912c9980880900148564cccd55cf80114008a003001357420073574400640024320032259301300290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26030005215933335573e0045002232328008010d5d10021aba100380048564c10800643001800807c02e00f003800918012300246004460048c0088c009180111801230022300208c008cdc3a40000045002280114008a00521800c01c0048980124c89800a4c1130014988c94c94ccd5cd00108ac9999aab9f00b28011191940040086ae88034d5d0806400242b26666660620024464aa666ae680044564cccd55cf80114008a003001357420073574400640024320032259303600290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b266026028005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c05400a42b26666aae7c008a00450018009aba10039aba20032001219001912c980d00148564cccd55cf80114008a003001357420073574400640024320032259301e00290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26094005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c13800a42b26666aae7c008a00450018009aba10039aba20032001219001912c9981582900148564cccd55cf801140088c8ca002004357440086ae8400e0012159302c00190c00600203f01b80bc04e01f00b803c00e002460048c009180111801230022300246004460048c0088c009180111801230022300246004460048c0088c008230023370e900000114008a004500228014860030010012260049322600293044c005262325533357340022300180104600466e1d200600c3370e900200519b87480080208cccccc0ac00488c954ccd5cd00088ac9999aab9f00228011191940040086ae88010d5d0801c00242b2600c00321800800a3002460041180119b8748000008a00450022801140088cccccc0a80048a00450022801140040045002232233333302b0012280114008008a0045002302b2233335573e00250018000964c010d5d080148564c010d5d1001c8600300300280091801226500230033574400480012c9813800c860020028c00866e1d2000002280114008a004500290ac800c85408a2a0432222180080140066601622446446004002605a44b20031003910998030011802000800d21502244c0952401034d30390048540851801230021803008460045004500580088cd5400488cdc0000a400490000ac998008054801c88800d1301e491034d313100910ac800c400a44260449201034d313100088cc08089640063000910992cc801c888a4012452005280148c954ccd5cd00088c00600200d00704600466e3c0040384860060030024400460080029001911111111111111100704c04c00460051801064646464aa666ae6800444c8c8c8c8c8c8ca00264646464aa666ae6800444c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8c8cccccccccccc8ccc8cc8cc888888888888888a00202100f807403601900b80540260110078034016009003801400460026ae84054c004d5d080998181191919192a999ab9a0011180098109aba100298031aba13574400411304149103505431003370e90000011aab9e00235573a0026ea8004cc0c0004d5d08089191919192a999ab9a001113232800991919192a999ab9a0011180098129aba10029981c1191919192a999ab9a0011180098151aba100208992a999ab9a00111328019bad35742009375a6ae840066eb4d5d09aba20011aba200311304c49103505431003370e900100199b8748000008d55cf0011aab9d00137540026ae84d5d1001044c119240103505431003370e90000011aab9e00235573a0026ea8d5d08024c020d5d08014c8c8c8c954ccd5cd00088c00044c954ccd5cd00088c014dd71aba100308992a999ab9a001118019aba1004089824248103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa357420033303475c6ae84d5d10008d5d10009aba2002113040490103505431003370e90000011aab9e00235573a0026ea8004dd69aba100f30013574201c60046004eb4cc0b805cd5d080619980b00cbad3574201664646464aa666ae6800444c8ca00264646464aa666ae68004460026600ceb4d5d08014c014d5d09aba2002089822248103505431003370e90000011aab9e00235573a0026ea8d5d08024c8c8c8c954ccd5cd00088c004cc019d69aba100298029aba13574400411304449103505431003370e90000011aab9e00235573a0026ea8d5d09aba20041191919192a999ab9a0011180108992a999ab9a00111800089822a4903505431003370e900100199b8748000008d55cf0011aab9d00137540024464646464aa666ae68004460042264aa666ae6800446002600e6ae8400c2264aa666ae680044600822608c920103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa00111303e49103505431003370e90000011aab9e00235573a0026ea8d5d0805198173ae3574201266602c464646464aa666ae68004460066eb8d5d0801044c954ccd5cd00088c024c080d5d0801844c954ccd5cd00088c01cc080d5d0802044c954ccd5cd00088c004dd69aba1005980f9aba13574400a11325533357340022300b30213574200c113255333573400223005375a6ae8401e603e6ae84d5d1003844c11124103505431003370e900500399b8748020018cdc3a400c00a66e1d20040043370e900100199b8748000008d55cf0011aab9d00137540020566ae84020cc0080acd5d08039bae3574200c66602c0306602c05a464646464aa666ae68004460042264aa666ae68004460082264aa666ae680044600022608292103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa0013574200a6605c02a6ae84010c004d5d080198009aba1357440066056eb4c051d71aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba20013574400422605492103505431003370e90000011aab9e00235573a0026ea8d5d0804cd5d0803cc8c8c8c954ccd5cd00088c00cdd71aba100208992a999ab9a0011180498059aba10039980e80e1aba135744006113255333573400223007300b35742008113255333573400223001375a6ae8401660146ae84d5d1002844c954ccd5cd00088c02cc030d5d0803044c954ccd5cd00088c014dd69aba100798051aba13574400e11302f49103505431003370e900500399b8748020018cdc3a400c00a66e1d20040043370e900100199b8748000008d55cf0011aab9d00137546ae84d5d100388c8c8c8c954ccd5cd00088994004dd69aba100398051aba1001991919192a999ab9a0011132804998110119aba10039aba1001998113ae357426ae880046ae8800844c954ccd5cd00088c004cc08808cd5d0801cc8c8c8c954ccd5cd00088c004dd69aba10029bad357426ae8800822606892103505431003370e90000011aab9e00235573a0026ea8d5d09aba200308992a999ab9a001118059998068083ad357420093302375c6ae84d5d1002044c954ccd5cd00088c01ccc090094d5d0802844c954ccd5cd0008899194034cc09c0a0d5d08044cc0a4050d5d08014ccc044051d69aba1001c991919192a999ab9a001118009bad35742005375a6ae84d5d1001044c0e5240103505431003370e90000011aab9e00235573a0026ea8d5d09aba2001911981280100086ae88004d5d100308992a999ab9a00111802998130139aba1007991919192a999ab9a001113302a75c6ae8400844c0e1240103505431003370e90000011aab9e00235573a0026ea8d5d09aba200708992a999ab9a0011180108981aa4903505431003370e900600419b874802801ccdc3a401000c66e1d20060053370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa357426ae880046ae8800844c0a9240103505431003370e90000011aab9e00235573a0026ea800488c88c008dd58009813911999aab9f0012800119400e002600c6aae74006600a6aae78005300435744006357420050002323232325533357340022300d3007357420053301a75a6ae84d5d1001044c954ccd5cd00088c04cc020d5d0801ccc06dd69aba13574400611325325333573400423003300a3574200b3001357426ae880142264aa666ae6800444ca01660186ae8401e60066ae840066eb4d5d09aba20011aba2006113255333573400223009300c3574200f375a6ae84d5d1003844c954ccd5cd00088c054c034d5d0804044c954ccd5cd00088c044c038d5d0804cdd69aba135744012113255333573400223005375c6ae8402a6eb8d5d09aba200a08992a999ab9a001118039bae35742017375a6ae84d5d1005844c954ccd5cd00088c004c044d5d08064c044d5d09aba200c08992a999ab9a0011180798091aba100d089819a4903505431003370e900a00699b8748048030cdc3a402001666e1d200e00a3370e900600499b8748028020cdc3a401000e66e1d200600623232323255333573400223001375c6ae840082264a64a666ae680084600a60026ae840102264aa666ae68004460066eb8d5d0802cc008d5d09aba2005089819248103505431003370e90020029191919192a999ab9a00111800980a1aba100208992a999ab9a0011180108992a999ab9a0011180208981ba48103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa0013370e900100199b8748000008d55cf0011aab9d001375400266e1d20040043370e900100199b8748000008d55cf0011aab9d0013754002464646464aa666ae6800446002600c6ae840082264aa666ae6800446006600e6ae8400c2264aa666ae680044600a6eb8d5d0802044c0a524103505431003370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa00123232323255333573400223001375c6ae840082264aa666ae68004460066eb8d5d0801844c09d240103505431003370e900100199b8748000008d55cf0011aab9d0013754002464646464aa666ae68004460026eb8d5d08014dd69aba13574400411302549103505431003370e90000011aab9e00235573a0026ea8004d5d100108980fa48103505431003370e90000011aab9e00235573a0026ea801629345402d22500c92805c8940324a0161809911192a999ab9a001113016490103505433001132553335734002226600a66e05200000433702900000188994004cdc2002800ccdc20020008cc01801000ccdc40012400066e1c005200030122223255333573400222006226600800466e1800c008cdc3800a400026020920103505435002001223232323255333573400223002113255333573400223001300735742006113015490103505431003370e900000199b8748008008d55cf0011aab9d0013754002464646464aa666ae68004460026eb8d5d08014dd69aba13574400411301249103505431003370e90000011aab9e00235573a0026ea80048c88c008dd60009807111999aab9f00128001400cc010d5d08014c00cd5d10012000601844b200318014886400a4464aa666ae6800444c8ccd5cd000c00200466e1c00920021130070043371e0049110b487964726148656164563100088c88c008004c03489640063002910c80148964cc02000801e300100144c01800c14800c888ca400a44a0072001912801c9400a44a00725002099319ab9c491024c6800800089640063000899ab9c0028010a40064444444444444444018130064901034d31320013005491034d30390013004491034d31300023223002001300522590018c002442b2600a005130040018c00823333330020012280114008a004500228008008888888ccccccd5d2003119198039aab9d00135573c0026ea801c8c014dd5803918021bac00723003375a00e460046eb801e000464c66ae7000600046460020024600446600400400291011c00a6ddbc130ab92f5b7cb8d1ccd8d79eca5bfe25f6843c07b62841f00048811c8fc2a74df32d01d1db56b3acb561831ef9c9970123079423abfcb86e0001" + "description": "hydra-mHead-0.19.0-533-g6cb0345d5", + "cborHex": "5915b55915b20101003332323232323232323232323232323232323232323232222232930010029114800c8940364b264b264646464aa666ae68004460042264aa666ae680044600022604804666e1d20020033370e90000011aab9e00235573a0026ea801226602a921034d303600593330132232333573400300080119b8f002001301400130169001911001a426604244b200318004886400a44b264666ae6800600100233710002900044c01800e30020003180122666664644444a65266038921034d303100323302822590018c00a442b2b320112290049119199ab9a0018004008cdc7802001119008914802488c8ccd5cd000c00200466e1c00c0048c009180044c0100040013302722590018c002443003900291001260080024a800c8888888888888888041323232323215933021491034d30320032333573400300080119b8732593330202232333573400300080119b8f002001500630235007909801000c5200019199119118010009817912c800c400e4432005223300800130060032400644004900191000a0024466e0000800605233700a00290014564cc0852401034d3033003323223002001302d22590018c00a4432005223255333573400222604c00422600e00866e3c00801c50059500391000a2b2b2660429201034d30340032333573400300080119b8750013300b11223223002001302e22590018801c884cc018008c010004a0091330262593330202232333573400300080119b8f002001500600190ac800c4c0b52401034d303800910c8014896400e2b264666ae680060010023370e002900146001130314901034d3038004884c0cd2401034d30380011302c4901034d3037002802460048ac9981312c800c5409242b260520032133024491034d31320032333573400300080119b8f001500889816a49034d31320048540946605844b2003180048860072005220024c0100043300c00a5006899810a49034d3035005932333573400300080119b8f9500291100194016264b3200322900b9119199ab9a0018004008cdc7802001119001914805c88c8ccd5cd000c00200466e1c00c0048c0092a005222002460048c00918012300246004195001911000856654006440048a811c8564cccccc09c004c8c8c8c888c94c94ccd5cd00108ac9999aab9f0032801140060026ae840126ae88010800486400644b26010005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964cc03403800a42b26666aae7c008a00450018009aba10039aba20032001219001912c981c80148564cccd55cf801140088c8ca002004357440086ae8400e001215933333303c001223255333573400222b26666aae7c008a00450018009aba10039aba20032001219001912c982080148564cccd55cf801140088c8ca002004357440086ae8400e0012159301d00190c00600200700123002460048c0088c008230023370e900000114008a0045002280148600300500b803c00e00244c0392644c0352644c0312622601293226010931130054991300449889800a4c113001498c88c954ccd5cd00088ac9999aab9f00528011191940040086ae8801cd5d0803400242b26666660640024464aa666ae680044564cccd55cf80114008a003001357420073574400640024320032259303700290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b266026028005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c05800a42b26666aae7c008a00450018009aba10039aba20032001219001912c980e80148564cccd55cf801140088c8ca002004357440086ae8400e0012159304500190c00600201f00b803c00e002460048c009180111801230022300246004460048c0088c008230023370e900000114008a004500228014860030070012260089322600693044c00d263370e9001002991192a999ab9a001115933335573e00a5002232328008010d5d10039aba100680048564cccccc0c800488c954ccd5cd00088ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b2606e005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964cc04c05000a42b26666aae7c008a00450018009aba10039aba20032001219001912c980b00148564cccd55cf80114008a003001357420073574400640024320032259301d00290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26042005215933335573e00450022800c004d5d0801cd5d1001900090c800c8964c12c00a42b26666aae7c008a00450018009aba10039aba20032001219001912c982780148564cccd55cf80114008a003001357420073574400640024320032259305300290ac9999aab9f0022801140060026ae8400e6ae8800c800486400644b26605e0ae005215933335573e0045002232328008010d5d10021aba100380048564c0cc00643001800811c07e037017809c03e017007801c0048c0091801230022300246004460048c0088c009180111801230022300246004460048c0088c009180111801230022300208c008cdc3a40000045002280114008a00521800c0040048980224c89801a4c113003498cdc3a400800a464aa666ae680044600300208c008cdc3a400c00866e1d2000002233333302b001223255333573400222b26666aae7c008a004464650010021aba20043574200700090ac9804000c860020028c009180104600466e1d2000002280114008a0045002232233333302c0012280114008008a0045002302e2233335573e00250018000964c010d5d080148564c010d5d1001c8600300300280091801226500230033574400480012c9814000c860020028c008466666605000245002280114008a002002280114008a004500228014856400642a04b1502491110c00400a0033300f11223223002001303222590018801c884cc018008c01000400690a812a260549201034d30390048540902b26601200ca00713028491034d313100910ac800c400a44260589201034d31310004cc0a089640063000910c00e400a44002980200086601000ca004260360051801064006444006233550012233700002900124000446604444b200318004884c966400e444520092290029400a464aa666ae68004460030010068038230023371e00201c2430030018012200230040014800c888888888888888803801401201000230050068a4d1500c48940364a01922500d928060646464646464464646464aa666ae6800444ca0026646464464646464aa666ae6800444c8c8c8c8c8c8c8c8c8c8c8c8c8ca0026605a0286ae840426605a0286ae8403a6605a02a6ae840366eb4d5d08064ccc079d7280b1aba100b9981680f9aba100a99980f010bad357420133353232122323232325533357340022300132323232553335734002230013300c00a35742005300b357426ae8800822608e08c66e1d200000235573c0046aae74004dd51aba1002991919192a999ab9a00111800998060051aba100298059aba1357440041130470463370e90000011aab9e00235573a0026ea8d5d09aba200208982182119b8748000008d55cf0011aab9d0013754002464646464aa666ae68004460042264aa666ae680044600022608408266e1d20020033370e90000011aab9e00235573a0026ea800488c8c8c8c954ccd5cd00088c00844c954ccd5cd00088c004c01cd5d0801844c954ccd5cd00088c01044c10c108cdc3a400800866e1d20020033370e90000011aab9e00235573a0026ea8005d69aba100899816bae3574200f33301e23232323255333573400223003375c6ae840082264aa666ae680044601260506ae8400c2264aa666ae680044600e60506ae840102264aa666ae68004460026eb4d5d0802cc09cd5d09aba200508992a999ab9a0011180598149aba100608992a999ab9a001118029bad3574200f3027357426ae8801c22608a08866e1d200a0073370e900400319b8748018014cdc3a400800866e1d20020033370e90000011aab9e00235573a0026ea80040a8d5d08034ccc079d70151aba10059bae3574200933301e0203301e02c232323232553335734002230021132553335734002230041132553335734002230001130420413370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa001357420073302d01d357420053302b75a6ae8400666056eb4d5d09aba20011aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba20013574400422605a05866e1d200000235573c0046aae74004dd50009191919192a999ab9a0011180098099aba100298031aba13574400411302c02b3370e90000011aab9e00235573a0026ea80048c8c8c8c954ccd5cd0008899194004c8c8c8c954ccd5cd00088c004c05cd5d08014cc0848c8c8c8c954ccd5cd00088c004c070d5d0801044c954ccd5cd0008899400cdd69aba10049bad35742003375a6ae84d5d10008d5d100188981b81b19b874800800ccdc3a40000046aae78008d55ce8009baa001357426ae8800822606206066e1d200000235573c0046aae74004dd51aba10049998083ae5008357420053232323255333573400223000113255333573400223005375c6ae8400c2264aa666ae68004460066ae8401022606606466e1d20040043370e900100199b8748000008d55cf0011aab9d00137546ae840066603aeb8d5d09aba20011aba20013574400422605605466e1d200000235573c0046aae74004dd50008998043ae75a6ae8400e6ae8400664646464aa666ae68004460066eb8d5d0801044c954ccd5cd00088c024c044d5d0801ccc068064d5d09aba200308992a999ab9a0011180398089aba100408992a999ab9a001118009bad3574200b3010357426ae880142264aa666ae680044601660246ae840182264aa666ae680044600a6eb4d5d0803cc040d5d09aba200708981701699b874802801ccdc3a401000c66e1d20060053370e900200219b874800800ccdc3a40000046aae78008d55ce8009baa357426ae880046ae8800844c09008ccdc3a40000046aae78008d55ce8009baa0012323232325533357340022265001375a6ae8400e60146ae8400664646464aa666ae6800444ca012660320346ae8400e6ae8400666032eb8d5d09aba20011aba20021132553335734002230013301901a357420073232323255333573400223001375a6ae8400a6eb4d5d09aba200208981681619b8748000008d55cf0011aab9d00137546ae84d5d1001844c954ccd5cd00088c02cccc034041d69aba10049980d3ae357426ae880102264aa666ae680044600e660360386ae840142264aa666ae6800444c8ca01a6603c03e6ae84022660400286ae8400a666022028eb4d5d0800e4c8c8c8c954ccd5cd00088c004dd69aba10029bad357426ae8800822606406266e1d200000235573c0046aae74004dd51aba135744003223301c0020010d5d10009aba20061132553335734002230053301d01e3574200f323232325533357340022266042eb8d5d080108981881819b8748000008d55cf0011aab9d00137546ae84d5d1003844c954ccd5cd00088c00844c0b80b4cdc3a401801066e1d200a0073370e900400319b8748018014cdc3a400800866e1d20020033370e90000011aab9e00235573a0026ea8d5d09aba20011aba20021130230223370e90000011aab9e00235573a0026ea800488c88c008dd58009810111999aab9f0012800119400e002600c6aae74006600a6aae7800530043574400635742005000322323232325533357340022300d3008357420053301275a6ae84d5d1001044c954ccd5cd00088c04cc024d5d0801ccc04dd69aba135744006113255333573400223003300a357420093008357426ae880102264aa666ae6800444ca01660186ae8401a60146ae840066eb4d5d09aba20011aba2005113255333573400223009300c3574200d375a6ae84d5d1003044c954ccd5cd00088c054c034d5d0803844c954ccd5cd00088c044c038d5d08044dd69aba135744010113255333573400223005375c6ae840266eb8d5d09aba200908992a999ab9a001118039bae35742015375a6ae84d5d1005044c954ccd5cd00088c004c044d5d0805cc044d5d09aba200b08992a999ab9a0011180798091aba100c08981601599b8748050030cdc3a402401666e1d201000a3370e900700499b8748030020cdc3a401400e66e1d20080063370e900300299b8748010010cdc3a400400666e1d200000235573c0046aae74004dd5000991191919192a999ab9a001118009bae35742004113255333573400223005300735742006113255333573400223003375c6ae8401260106ae84d5d1002044c09008ccdc3a400800866e1d20020033370e90000011aab9e00235573a0026ea80048c8c8c8c954ccd5cd00088c004c01cd5d0801044c954ccd5cd00088c00844c954ccd5cd00088c01044c08c088cdc3a400800866e1d20020033370e90000011aab9e00235573a0026ea80048c8c8c8c954ccd5cd00088c004c018d5d0801044c954ccd5cd00088c00cc01cd5d0801844c954ccd5cd00088c014dd71aba100408981101099b8748010010cdc3a400400666e1d200000235573c0046aae74004dd50009191919192a999ab9a001118009bae35742004113255333573400223003375c6ae8400c22604003e66e1d20020033370e90000011aab9e00235573a0026ea80048c8c8c8c954ccd5cd00088c004dd71aba10029bad357426ae8800822603c03a66e1d200000235573c0046aae74004dd5000980a911192a999ab9a001113018490103505433001132553335734002226600a66e0405c010cdc080b80188994004cdc2002800ccdc20020008cc01801000ccdc400100b19b8700101530142223255333573400222006226600800466e1800c008cdc380080a098092481035054350020012232323232553335734002230021132553335734002230013007357420061130170163370e900000199b8748008008d55cf0011aab9d0013754002464646464aa666ae68004460026eb8d5d08014dd69aba1357440041130140133370e90000011aab9e00235573a0026ea80048c88c008dd60009808111999aab9f00128001400cc010d5d08014c00cd5d10012000601c44b200318014886400a4464aa666ae6800444c8ccd5cd000c00200466e1c00920021130070043371e00491010b487964726148656164563100088c88c008004c03c89640063002910c80148964cc02000801e300100144c01800c1914800c88a400644a00f2001912803c9401a44a00f2500604c98cd5ce249024c6800800112c800c6001133573800500214800c8888888888888888030260109201034d31320013007491034d30390013006491034d31300023223002001300722590018c002442b2600a005130040018c00823333330020012280114008a004500228008008888888ccccccd5d2003119198039aab9d00135573c0026ea801c8c014dd5803918021bac00723003375a00e460046eb801e0009000249035054310023263357380030002323001001230022330020020014891c00a6ddbc130ab92f5b7cb8d1ccd8d79eca5bfe25f6843c07b62841f00048811c5350e9d521552ebfd9e846fd70c3b801f716fc14296134ec0fb71e970001" } diff --git a/hydra-plutus/scripts/vCommit.plutus b/hydra-plutus/scripts/vCommit.plutus index 672a6052a1a..d790a5df3b2 100644 --- a/hydra-plutus/scripts/vCommit.plutus +++ b/hydra-plutus/scripts/vCommit.plutus @@ -1,5 +1,5 @@ { "type": "PlutusScriptV3", - "description": "hydra-vCommit-0.19.0-284-g2f3d76240", + "description": "hydra-vCommit-0.19.0-524-g017dc82b8", "cborHex": "5902af5902ac010100323232323232323232322533300332323232325332330093001300b37540042646464a66666602800c2646464a66601e60060022a66602660246ea80245400803854ccc03cc01c00454ccc04cc048dd50048a80100700718081baa0081533300d3001300f37540042646464646464a6660266016602a6ea80344cc00cc01130103d87980003370e6660026eacc064c068c068c068c068c058dd50079bae30053016375400c91010b487964726148656164563100480044c94ccc050c020c058dd50008998021802a6103d87a8000300c333002375660346036602e6ea8c068c05cdd50009bae30063017375400e9110b4879647261486561645631001533015491054c35373b39001632533301800114c103d87a80001300333019301a0014bd701bac30053016375401e44464a66602c601c60306ea8004520001375a603860326ea8004c94ccc058c038c060dd50008a6103d87a8000132330010013756603a60346ea8008894ccc070004530103d87a8000132323232533301c337220100042a66603866e3c0200084c02ccc084dd4000a5eb80530103d87a8000133006006003375a603c0066eb8c070008c080008c078004c8cc004004010894ccc06c0045300103d87a8000132323232533301b337220100042a66603666e3c0200084c028cc080dd3000a5eb80530103d87a80001330060060033756603a0066eb8c06c008c07c008c074004dd2a400044a666024002294454cc04c0085894ccc040c010c048dd50008a4903433031001491034330320023015301630160013013301037540042a6601c9201054c34373b350016370e900000580580580598089809001180800098061baa002370e90010b1806980700118060009806001180500098031baa00114984d95854cc0092401054c34333b3500165734ae7155ceaab9e5573eae815d0aba257481" } diff --git a/hydra-plutus/scripts/vDeposit.plutus b/hydra-plutus/scripts/vDeposit.plutus index 52c2b4fc689..4adbc24314b 100644 --- a/hydra-plutus/scripts/vDeposit.plutus +++ b/hydra-plutus/scripts/vDeposit.plutus @@ -1,5 +1,5 @@ { "type": "PlutusScriptV3", - "description": "hydra-vDeposit-0.19.0-284-g2f3d76240", - "cborHex": "5912fe5912fb0100003233223332223233223232323232323232323232323232323232323232323232323232323232323223235300100222233333350012230154910350543500230144910350543500223015490103505435002301449103505435002253350012153353322323353232325335333573466e1d20000020350341321223002003375c6ae8400454cd4ccd5cd19b87480080080d40d04c8488c00400cdd69aba10011301c01835573c0046aae74004dd50041299a9a9a9808a80111000912999a8011099809a490344303100333573466e24004d401c8880080d80d44c07124103443032001301c4910344303200133010490103443036003301c00135004222003103225335353530115002220022253335002213301349010344303400333573466e24004d401c8880080d40d84c07124103443033001301c4910344303300133010490103443035003301c3724603a66a0320026aa004444444444444444401c6e48c098c08cc0a8d401088800440c84d400488800cc8c8c94cd4ccd5cd19b87480000080c80c44c8c8c8c94cd4ccd5cd19b87480000080d80d44c8ccc88848ccc00401000c008dd71aba1002375a6ae84004c014d5d09aba2001357440022603a0326aae78008d55ce8009baa35742004602c4646464a66a666ae68cdc3a400000406c06a26644246600200600460206ae84004dd71aba1357440022603a0326aae78008d55ce8009baa0011301901535573c0046aae74004dd50009803804080e0980b249035054350013015491035054350023014491035054350032323232323232323223232325335333573466e1d2000002035034132333222123330010040030023232325335333573466e1d2000002039038132323232323232323232323232323333333333333333222222222222222212333333333333333300101101000f00e00d00c00b00a0090080070060050040030023302b01a3574201e660560346ae84038cc0ac06cd5d08069bad3574201866603eeb94078d5d08059981580c1aba100a33301f01c75a6ae84024c8c8c94cd4ccd5cd19b87480000081281244cc8848cc00400c008c8c8c94cd4ccd5cd19b87480000081341304cc8848cc00400c008cc0b9d69aba1001302d357426ae880044c0d00c0d55cf0011aab9d00137546ae84004c8c8c94cd4ccd5cd19b87480000081341304cc8848cc00400c008cc0b9d69aba1001302d357426ae880044c0d00c0d55cf0011aab9d00137546ae84d5d1000898188169aab9e00235573a0026ea8d5d080419815bae3574200e66603e4646464a66a666ae68cdc3a40000040960942642444444600a00e6eb8d5d08008a99a999ab9a3370e90010010258250990911111180100398129aba100115335333573466e1d200400204b04a132122222230030073020357420022a66a666ae68cdc3a400c0040960942664424444446600c01000e6eb4d5d0800980e1aba1357440022a66a666ae68cdc3a40100040960942642444444600200e603a6ae8400454cd4ccd5cd19b874802800812c1284cc884888888cc01002001cdd69aba1001301b357426ae880044c0c80b8d55cf0011aab9d001375400204c6ae84018ccc07dd70131aba1005375c6ae84010ccc07c064cc07c0a48c8c8c94cd4ccd5cd19b874800000812c1284488800854cd4ccd5cd19b874800800812c1284488800454cd4ccd5cd19b874801000812c1284488800c4c0c80b8d55cf0011aab9d00137540026ae8400ccc0ac05cd5d08011980ebad357420026603aeb4d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae880044c080070d55cf0011aab9d00137546ae84008d5d0800991919299a999ab9a3370e900000101c81c099091111118028039bae357420022a66a666ae68cdc3a40040040720702664424444446600401000e60266ae84004cc03c060d5d09aba200115335333573466e1d200400203903813212222223003007300e357420022a66a666ae68cdc3a400c0040720702664424444446600c01000e6eb4d5d080098051aba1357440022a66a666ae68cdc3a40100040720702642444444600200e60166ae8400454cd4ccd5cd19b87480280080e40e04cc884888888cc01002001cdd69aba10013009357426ae880044c080070d55cf0011aab9d00137546ae84d5d10009aba20011301c01835573c0046aae74004dd50009191919299a999ab9a3370e900000101a019899199911091998008020018011bad3574200460146ae84004c8c8c94cd4ccd5cd19b87480000080e00dc4c8ccc88848888888ccc00c028024020cc03c06cd5d08011aba10013300f75c6ae84d5d10009aba200115335333573466e1d20020020380371332212222222330070090083300e01a35742002646464a66a666ae68cdc3a40000040760742664424660020060046eb4d5d08009bad357426ae880044c088078d55cf0011aab9d00137546ae84d5d10008a99a999ab9a3370e900200101c01b899910911111119801004804199808006bad357420026601ceb8d5d09aba200115335333573466e1d20060020380371321222222230040083300e01a357420022a66a666ae68cdc3a401000407006e2646466664444244444446666002016014012010660200386ae8400ccc07803cd5d0801199809007bad357420026a646464a66a666ae68cdc3a400000407a0782660586eb4d5d08009bad357426ae880044c090080d55cf0011aab9d00137546ae84d5d1000911980b8010009aba2001357440022a66a666ae68cdc3a401400407006e26644244444446600a0120106601c0346ae84004c8c8c94cd4ccd5cd19b87480000080ec0e84cc045d71aba10011302201e35573c0046aae74004dd51aba1357440022a66a666ae68cdc3a401800407006e22444444400c2603e0366aae78008d55ce8009baa357426ae88004d5d10008980d80b9aab9e00235573a0026ea8004c88c8c8c94cd4ccd5cd19b87480000080d00cc4cc88488888888888cc014034030c024d5d0800998053ad357426ae8800454cd4ccd5cd19b87480080080d00cc4cc88488888888888cc008034030c024d5d0800998053ad357426ae8800454cd4ccd5cd19b87480100080d00cc4cc88488888888888cc028034030c024d5d080098029aba1357440022a66a666ae68cdc3a400c00406806626466644424444444444466600c01c01a01860146ae84008c018d5d08009bad357426ae88004d5d10008a99a999ab9a3370e900400101a019899910911111111111980380680618049aba1001375a6ae84d5d10008a99a999ab9a3370e900500101a019899091111111111180080618049aba100115335333573466e1d200c002034033133221222222222223300300d00c3009357420026eb4d5d09aba200115335333573466e1d200e002034033133221222222222223300900d00c375c6ae84004dd71aba1357440022a66a666ae68cdc3a4020004068066266442444444444446601001a0186eb8d5d08009bad357426ae8800454cd4ccd5cd19b87480480080d00cc4cc88488888888888cc02c034030c024d5d080098049aba1357440022a66a666ae68cdc3a4028004068066264244444444444600801860126ae840044c06c05cd55cf0011aab9d0013754002644646464a66a666ae68cdc3a4000004068066264244460060086eb8d5d08008a99a999ab9a3370e900100101a0198990911180080218029aba100115335333573466e1d200400203403313322122233002005004375c6ae84004c014d5d09aba20011301b01735573c0046aae74004dd50009191919299a999ab9a3370e90000010198190990911180180218041aba100115335333573466e1d20020020330321122200215335333573466e1d2004002033032112220011301a01635573c0046aae74004dd50009191919299a999ab9a3370e90000010190188990911180180218039aba100115335333573466e1d2002002032031132122230020043007357420022a66a666ae68cdc3a4008004064062264244460020086eb8d5d08008980c80a9aab9e00235573a0026ea80048c8c8c94cd4ccd5cd19b87480000080c40c04cc8848cc00400c008c02cd5d080098029aba135744002260300286aae78008d55ce8009baa00123232325335333573466e1d200000203002f13232333322221233330010050040030023232325335333573466e1d2000002035034133221233001003002300a35742002660164646464a66a666ae68cdc3a40000040720702642446004006601c6ae8400454cd4ccd5cd19b87480080080e40e04c8ccc888488ccc00401401000cdd69aba1002375a6ae84004dd69aba1357440026ae880044c080070d55cf0011aab9d00137540026ae84d5d10008980e00c1aab9e00235573a0026ea8d5d08019998053ae500935742004646464a66a666ae68cdc3a400000406a068224440062a66a666ae68cdc3a400400406a068264244460020086eb8d5d08008a99a999ab9a3370e900200101a81a099091118010021aba10011301c01835573c0046aae74004dd51aba10013300875c6ae84d5d10009aba2001357440022602e0266aae78008d55ce8009baa00123232325335333573466e1d200000202f02e1321223002003375c6ae8400454cd4ccd5cd19b87480080080bc0b84c8488c00400cdd71aba10011301601235573c0046aae74004dd500091191919299a999ab9a3370e900100101781708910008a99a999ab9a3370e9000001017817099091180100198029aba10011301601235573c0046aae74004dd5000899800bae75a4464460046eac004c0ac88cccd55cf800901391919a8139980e98031aab9d001300535573c00260086ae8800cd5d080100a1191919299a999ab9a3370e90000010150148999109198008018011bae357420026eb4d5d09aba20011301100d35573c0046aae74004dd50009813111299a999ab9a3370e00201a05004e2601e9201035054330015335333573466e200040340a009c4cc00ccdc080680119b8100d001132332212330010030023370800600266e10008004cc010008004c0948894cd4ccd5cd19b8700100c02702610021330030013370c00400244a66a002204a266ae700080908d4004888888888888888802480048c8c8c94cd4ccd5cd19b874800000809008c408c54cd4ccd5cd19b874800800809008c40904c02c01cd55cf0011aab9d001375400244646464a66a666ae68cdc3a4000004048046224440042a66a666ae68cdc3a400400404804626424446006008600a6ae8400454cd4ccd5cd19b874801000809008c448880044c02c01cd55cf0011aab9d00137540024646464a66a666ae68cdc3a40000040440422664424660020060046eb8d5d08009bad357426ae880044c024014d55cf0011aab9d00137540029210350543100232230023758002603c446666aae7c00480688cd4064c010d5d080118019aba200200748000cc06c884894cd4ccd5cd19b8900248000078074406054cd40044060884cd4064008cd4c01848004cdc08022400400224002464c66ae700040084800488ccd5cd19b8f0020010190183017225335001100c221337146eccd40088888cdd2a400066ae80d401088cdd2a400066ae80c02c008cd5d019806119a800919ba548000cd5d018068009bb100f2223374a900119aba0375000666ae80dd400119aba037500026ec4044004dd880699aba033300c75266018ea48dd400080199aba05333500213374a90001bb100b213374a900219aba000137620184266e9520023357406ea4004dd880619aba03300a7520026ec402cc0100048cd40048cdd2a400066ae80dd48009bb100423374a900119aba037520026ec4010894cd400484cdd2a400066ae80c00c004dd8802099ba548008dd8801a4c446446e98c008004c05488cd40052f5bded8c0446a0044466ae80cdd8180400118038009803001910919800801801180891299a800898011801806110a99a800880111098031803802980811299a8008805910a99a800880191099a8071980380200118030009807911299a8010800910a99a801880219110a999a998088028010a801899a807801198040038008a801899a80600119802800801980711299a80088019109a8011119b8a00130060034890035003222001350022220023500122200333230010012212323330022300222230030042300222230020042300222230010042353300400400335003001122223330042533500113350060070072215335001133500800300922153233353300d00500315001133300800333500b00500c002150011333006002233500b00500100122253350011335008335008003002300600932221533353300d00600215003133300800233500b0060050011500313350083350080030023006001222532335002130014988854c8ccd4cc03801c00c540044c011261500113330070022300633500c0070010012335009300333500900400a30070021220021221223300100400332223500222350022235005223500222533353300b00600215335333573466e1c01400404003c403854cd4ccd5cd19b8900500101000f100c100d13300b00600213300b006002225335333573466e3c00800401c018401454cd4ccd5cd19b91002001007006100310041222003122200212220011220021220012323001001230022330020020011" + "description": "hydra-vDeposit-0.19.0-524-g017dc82b8", + "cborHex": "59045b590458010100323232323232323232322533300332323232325332330093001300b37540042646464a66666602800c2646464a66601e6006002264a66602800201e264a666666032002020020020020264a66602c60320062a00a0226eb8004c058004c048dd50048a9998079803800899299980a000807899299999980c800808008008099299980b180c8018a8028089bad00101030160013012375401201c60206ea802054ccc034c004c03cdd5001099191919191929998099803980a9baa00d13253330143300430054c103d87e80003371e6eb8c00cc05cdd50038008998021802a60103d87980003322325333017300f30193754002266e24dd6980e980d1baa00100213300730084c103d87a80004a0600a60326ea8c010c064dd50011803180b9baa010375a6004602e6ea801c5281bae30193016375401a264a66602866008600a980103d87c80003322325333017300f30193754002266e20008dd6980e980d1baa00113300730084c103d87b80004a0600a60326ea8c014c064dd50011803180b9baa010375a6004602e6ea801c4c8c8c8c8cc020c02530103d87d80003371e646e48004ccc00ccc008ccc004004dd61802180d9baa01400523766002911002233714004002646e48004ccc00ccc008c8cc004004dd61802980e1baa00c22533301e00114bd70099911919800800801912999811000899811801a5eb804c8c94ccc080cdd79991192999811980d98129baa001133225333025337100040022980103d879800015333025337100020042980103d87b800014c103d87a8000375a6022604c6ea800cdd6980898131baa002100133225333024337200040022980103d8798000153330243371e0040022980103d87a800014c103d87b8000375c6022604a6ea8008dd7180898129baa001300f3023375400a601e60466ea800930103d8798000133025005003133025002330040040013026002302400133002002302100130200012375c600e60386ea80052201002233714004002444a66603466e24005200014bd700a99980f0010a5eb804cc07cc080008ccc00c00cc084008cdc0000a400244646600200200644a66603c002297ae013301f37526006604000266004004604200244464666002002008006444a66603e004200226660060066044004660080026eb8c0840088c06cc070c0700045281bad30193016375401a4603260340024603000244a666024002294454cc04c008528119299980898028008a490344303100153330113009001149010344303200153330113370e90020008a490344303300153330113370e90030008a490344303400153330113370e90040008a49034430350014910344303600301237540024602a602c602c602c602c602c602c602c002602660206ea800854cc039241054c35353b350016370e900000580580580598089809001180800098061baa002370e90010b1806980700118060009806001180500098031baa00114984d95854cc0092401054c35313b3500165734ae7155ceaab9e5573eae815d0aba257481" } diff --git a/hydra-plutus/scripts/vHead.plutus b/hydra-plutus/scripts/vHead.plutus index 6a62584a43a..01621a624bd 100644 --- a/hydra-plutus/scripts/vHead.plutus +++ b/hydra-plutus/scripts/vHead.plutus @@ -1,5 +1,5 @@ { "type": "PlutusScriptV3", - "description": "hydra-vHead-0.19.0-330-g475541011", - "cborHex": "59314b593148010000323233223332223233223232323232332232323232323322323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323233332222323232323232323232323232323232323232323232323232323232323232323232323232322323235300100322233333350012230514910350543500230504910350543500223051490103505435002305049103505435002253350012153353232325333350033232323232215333333350081306849884c1a52613068498c8c8c8c8c8c8854cd4c09d403454cd54cd4ccd5cd19b8735303c00e222222222006500208a0108901108a0113357389201034831330008901153355335333573466e25402cd402088888888801422404228044228044cd5ce249034833310008901153353350012533533301d500633333302450045003500c35303d00f22222222200430370850135303d00f222222222003001108b011335738921034833390008a012253355335333573466e3cd4c0f804088888888800cc0e0218042300422c044ccc079401ccccccc0954014cdc0a80224004a01a6a607c020444444444008607010c02002004211602211802266ae71241034834300008b01153353302e00e50031533553353323223002001308d01225335001108d012215335333573466e3c01400823c04238044238044c010005403140104228044cd5ce248103483338000890115335353535500d2222222222222222009220012253335002215335333573466e24005402823404230044234044cd5ce249034833320008c011506115061153355335333502a078500933508301500c5004108a011335738921034833360008901153355335333573466e1cc1954024c1994028228042240454cd4ccd5cd19b8735303c00e222222222001500708a0108901108a011335738920103483334000890115335333573466e1cd4c0f0038888888888004cdc02803a8030450084480884500899ab9c4901034833350008901153353330293307e500a50053307e35303c00e22222222200750063307e35303c00e222222222009500315335330395335304800e21353500122001222200310840135533535500d222222222222222200e130620342210022222003108a01133573892010248340008901108901108901108901108901108901108901108901108901108901108901135006222222222006135005222222222009135004222222222002135003222222222008135002222222222007135001222222222001213069498884d40248894cd4ccc0a4d400c8888888888888888030d4018888888888024d4018888888888020c854cd54cd4ccd5cd19b8f3035335025006500135007222222222004089010880110890113357389201034834310008801153355335333573466e3cd401c88888888800cc0d4c8cd4098018004cd40c4019400422404220044224044cd5ce248103483432000880113535350042222222222222222009220022253335002215335333573466e24004d402888888888800422c04230044230044cd5ce249034834330008b011506815068108801108801135003222222222222222200e1087012130694984d4c0cc0148888888880084d4c0c80108888888880204d4c0c400c88888888801454cd4d5400488888888888888880204c151262215335001100222130584984d400488800c4c18926222323232215323333333500a150012150021350092225332355335333573466e3cd4c0f003488888004c0dcd5400488800c22404220044224044cd5ce249034831370008801153355335333573466e1d200035303c00d22222002089010880110890113357389201034832300008801153353330283307d35303c00d2222200400b3307d35303c00d2222200300c3307d35303c00d2222200500a15335533533032533535004222222222222222200e108301221306a0013232333073075002305f335084013307f0543350840100108501085013307e05335005222222222222222200d355001222001108901133573892103483139000880115335533530095335304700d2135350012200122220031083011089011335738921034831360008801153355335333573466e1cd54004888008c1a802c22404220044224044cd5ce249034831380008801153353302d00d00a130260041088011088011088011088011088011088011300735003222222222222222201010870121500221500222150032150021533333335009135008222533533302835003222222222222222200c00800932153353302c00c00915335330763036500130343350243066500135004222222222222222200e108801133573892010348313500087011087011330050810135003222222222222222201010860121306a4984c1a52621306a49884c1a926221306b49884c1a9263084012232253350011003221350022253353305100b001133008300630550010031330080070033086012253350011003221335081010023004001308301225335001133304f07d480001f4884c8d400c88d400c8c8894cd4cc120d40148888010d4d4c124040880048888010401c54cd4cc14c0340144ccc160c00cc15c014cdc02400400400226660b00080046660e80ec0026a00a444400661160244a66a002200644266a10c020046008002600800261040244a66a0022102024426a00444a66a666ae68cdc7801003843008428089833000898030019919191910a9999999a80389833a4c6464646442a66a6048a0142a66aa66a666ae68cdc499b81353535500a2222222222222222009220012253335002210011506d1506d353535500a2222222222222222009220022253335002210011506c1506c5004087010860110870113357389201034832320008601153355335333573466e1cd4c0e402c888888888004c8d4030888d4d4d400c888888888888888802488004894ccd400884cdc00008038a8378a837a8020438084300884380899ab9c491034832330008601153353302b00b5003153355335333573466e1cd4c0e402c888888888019400821c0421804421c044cd5ce24810348313300086011533553335001153355335333573466e1d20005002087010860115335333573466e1d200035303900b22222222200508701086011333573466e3cd4c0e402c888888888010d40188888800421c0421804421804421804421c044cd5ce248103483238000860121533533301a50063333330215004500335303a00c22222222200535303a00c22222222200430340820135303a00c2222222220030011088011335738920103483239000870122153355335333573466e3cd4c0ec03488888888800cc0d420c0422404220044ccc06d401ccccccc0894014cdc0a802240046a607601a44444444400a6a607601a444444444008606a10602002004211002211202266ae71241034833300008801153355335533535303900b2222222220021087012210880110870113357389201034832360008601153355335330365335304500b21353500122001222200310810135533535500a222222222222222200e1305f031221002222200310870113357389201024834000860113330263307b35303900b22222222200850053307b35303900b22222222200750043307b35303900b2222222220095003108601108601108601108601108601108601108601108601135004222220021350032222200513500222222003135001222220041306749884c1a1263232215335333024330793500422222004500633079350042222200335303800922222003330795003500532153355335333573466e1cd4c0e402888888008cdc024004a00610c0210a02210c02266ae71240103483231000850115335333018500733333301f500650033500222200235303900a2222200130320800130325001350022220031533553353302f5335304400a21353500122001222200310800133306e07035533550081305e0302210022222003306d500110860113357389201024834000850113302a00a5004108501108501108501133502135001222001533550071305d4910350543900221001108401135002222220021350012222200522130694988420c044d4c0cc010888880144d4c0c800c888880104d4d400888800c88888888888888880384d400488800cc02402cc8c8c94cd4ccd5cd19b87480000081f81f444888888801454cd4ccd5cd19b87480080081f81f44c848888888c004020c8c8c94cd4ccd5cd19b874800000820404200044480044c164168d55cf0011aab9d00137546ae8400454cd4ccd5cd19b87480100081f81f44c848888888c00c020c8c8c94cd4ccd5cd19b874800000820404200044c8ccc88848ccc00401000c008cc065d71aba1002375a6ae84004dd69aba1357440026ae880044c164168d55cf0011aab9d00137546ae8400454cd4ccd5cd19b87480180081f81f44c848888888c018020c8c8c94cd4ccd5cd19b874800000820404200044488800c54cd4ccd5cd19b874800800820404200044c84888c008010cc061d71aba100115335333573466e1d20040020810108001133221222330010050043301875c6ae84004dd71aba135744002260b20b46aae78008d55ce8009baa357420022a66a666ae68cdc3a40100040fc0fa264244444446008010646464a66a666ae68cdc3a40000041020210002264244600400666030eb8d5d08008a99a999ab9a3370e9001001040808400089991091198008020019980c3ae357420026eb8d5d09aba20011305905a35573c0046aae74004dd51aba100115335333573466e1d200a00207e07d11222222200715335333573466e1d200c00207e07d133221222222233002009008375a6ae84004dd69aba135744002260ac0ae6aae78008d55ce8009baa0063232325335333573466e1d200000207d07c1323233330353056357420066602c0b26ae84008dd71aba1001300d357426ae88004d5d10009aba200115335333573466e1d200200207d07c130323232325335333573466e1d20000020800107f13232323333303d375c6ae84010cc068174d5d0801982d1aba1002375a6ae84004dd71aba1357440026ae88004d5d10009aba20011305805935573c0046aae74004dd51aba100115335333573466e1d200400207d07c130353232325335333573466e1d20000020800107f132323232323232333333333040375c6ae84020cc078184d5d0803982f1aba1006375a6ae84014dd69aba1004375c6ae8400cdd71aba10023301e75c6ae84004dd69aba1357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba20011305805935573c0046aae74004dd51aba100115335333573466e1d200600207d07c10341305505635573c0046aae74004dd5000881d89829249035054350013051491035054350023050491035054350032323232323232323223232325335333573466e1d20000020800107f132333222123330010040030023232325335333573466e1d20000020840108301132323232323232323232323232323333333333333333222222222222222212333333333333333300101101000f00e00d00c00b00a0090080070060050040030023302901a3574201e660520346ae84038cc0a406cd5d08069bad3574201866603eeb94078d5d08059981480c1aba100a33301f01c75a6ae84024c8c8c94cd4ccd5cd19b874800000825404250044cc8848cc00400c008c8c8c94cd4ccd5cd19b87480000082600425c044cc8848cc00400c008cc0b5d69aba1001302c357426ae880044c1c01c4d55cf0011aab9d00137546ae84004c8c8c94cd4ccd5cd19b87480000082600425c044cc8848cc00400c008cc0b5d69aba1001302c357426ae880044c1c01c4d55cf0011aab9d00137546ae84d5d1000898368371aab9e00235573a0026ea8d5d080419814bae3574200e66603e4646464a66a666ae68cdc3a400000412c0212a022642444444600a00e6eb8d5d08008a99a999ab9a3370e900100104b0084a808990911111180100398121aba100115335333573466e1d20040020960109501132122222230030073020357420022a66a666ae68cdc3a400c00412c0212a022664424444446600c01000e6eb4d5d0800980e1aba1357440022a66a666ae68cdc3a401000412c0212a022642444444600200e603a6ae8400454cd4ccd5cd19b874802800825804254044cc884888888cc01002001cdd69aba1001301b357426ae880044c1b81bcd55cf0011aab9d001375400204a6ae84018ccc07dd70129aba1005375c6ae84010ccc07c064cc07c0a08c8c8c94cd4ccd5cd19b874800000825804254044488800854cd4ccd5cd19b874800800825804254044488800454cd4ccd5cd19b874801000825804254044488800c4c1b81bcd55cf0011aab9d00137540026ae8400ccc0a405cd5d08011980ebad357420026603aeb4d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae880044c170174d55cf0011aab9d00137546ae84008d5d0800991919299a999ab9a3370e90000010420084180899091111118028039bae357420022a66a666ae68cdc3a400400410802106022664424444446600401000e60246ae84004cc03c05cd5d09aba200115335333573466e1d2004002084010830113212222223003007300e357420022a66a666ae68cdc3a400c00410802106022664424444446600c01000e6eb4d5d080098051aba1357440022a66a666ae68cdc3a401000410802106022642444444600200e60166ae8400454cd4ccd5cd19b87480280082100420c044cc884888888cc01002001cdd69aba10013009357426ae880044c170174d55cf0011aab9d00137546ae84d5d10009aba20011305805935573c0046aae74004dd50009191919299a999ab9a3370e900000103f83f099199911091998008020018011bad3574200460146ae84004c8c8c94cd4ccd5cd19b874800000820c04208044c8ccc88848888888ccc00c028024020cc03c068d5d08011aba10013300f75c6ae84d5d10009aba200115335333573466e1d200200208301082011332212222222330070090083300e01935742002646464a66a666ae68cdc3a400000410c0210a022664424660020060046eb4d5d08009bad357426ae880044c17817cd55cf0011aab9d00137546ae84d5d10008a99a999ab9a3370e90020010418084100899910911111119801004804199808006bad357420026601ceb8d5d09aba200115335333573466e1d200600208301082011321222222230040083300e019357420022a66a666ae68cdc3a401000410602104022646466664444244444446666002016014012010660200366ae8400ccc07003cd5d0801199809007bad357420026a646464a66a666ae68cdc3a40000041100210e022660f86eb4d5d08009bad357426ae880044c180184d55cf0011aab9d00137546ae84d5d1000911980b8010009aba2001357440022a66a666ae68cdc3a4014004106021040226644244444446600a0120106601c0326ae84004c8c8c94cd4ccd5cd19b874800000821804214044cc045d71aba10011305e05f35573c0046aae74004dd51aba1357440022a66a666ae68cdc3a4018004106021040222444444400c260b60b86aae78008d55ce8009baa357426ae88004d5d10008982b82c1aab9e00235573a0026ea8004c88c8c8c94cd4ccd5cd19b87480000081fc1f84cc88488888888888cc014034030c024d5d0800998053ad357426ae8800454cd4ccd5cd19b87480080081fc1f84cc88488888888888cc008034030c024d5d0800998053ad357426ae8800454cd4ccd5cd19b87480100081fc1f84cc88488888888888cc028034030c024d5d080098029aba1357440022a66a666ae68cdc3a400c0040fe0fc26466644424444444444466600c01c01a01860146ae84008c018d5d08009bad357426ae88004d5d10008a99a999ab9a3370e900400103f83f099910911111111111980380680618049aba1001375a6ae84d5d10008a99a999ab9a3370e900500103f83f099091111111111180080618049aba100115335333573466e1d200c00207f07e133221222222222223300300d00c3009357420026eb4d5d09aba200115335333573466e1d200e00207f07e133221222222222223300900d00c375c6ae84004dd71aba1357440022a66a666ae68cdc3a40200040fe0fc266442444444444446601001a0186eb8d5d08009bad357426ae8800454cd4ccd5cd19b87480480081fc1f84cc88488888888888cc02c034030c024d5d080098049aba1357440022a66a666ae68cdc3a40280040fe0fc264244444444444600801860126ae840044c15c160d55cf0011aab9d0013754002644646464a66a666ae68cdc3a40000040fe0fc264244460060086eb8d5d08008a99a999ab9a3370e900100103f83f0990911180080218029aba100115335333573466e1d200400207f07e13322122233002005004375c6ae84004c014d5d09aba20011305705835573c0046aae74004dd50009191919299a999ab9a3370e900000103f03e8990911180180218041aba100115335333573466e1d200200207e07d1122200215335333573466e1d200400207e07d112220011305605735573c0046aae74004dd50009191919299a999ab9a3370e900000103e83e0990911180180218039aba100115335333573466e1d200200207d07c132122230020043007357420022a66a666ae68cdc3a40080040fa0f8264244460020086eb8d5d08008982a82b1aab9e00235573a0026ea80048c8c8c94cd4ccd5cd19b87480000081f01ec4cc8848cc00400c008c028d5d080098029aba135744002260a80aa6aae78008d55ce8009baa00123232325335333573466e1d200000207b07a13232333322221233330010050040030023232325335333573466e1d20000020800107f133221233001003002300a35742002660164646464a66a666ae68cdc3a400000410802106022642446004006601c6ae8400454cd4ccd5cd19b87480080082100420c044c8ccc888488ccc00401401000cdd69aba1002375a6ae84004dd69aba1357440026ae880044c170174d55cf0011aab9d00137540026ae84d5d10008982c02c9aab9e00235573a0026ea8d5d08019998053ae500935742004646464a66a666ae68cdc3a4000004100020fe224440062a66a666ae68cdc3a4004004100020fe264244460020086eb8d5d08008a99a999ab9a3370e90020010400083f899091118010021aba10011305805935573c0046aae74004dd51aba10013300875c6ae84d5d10009aba200135744002260a60a86aae78008d55ce8009baa00123232325335333573466e1d200000207a0791321223002003375c6ae8400454cd4ccd5cd19b87480080081e81e44c8488c00400cdd71aba10011305205335573c0046aae74004dd500091191919299a999ab9a3370e900100103d03c8a8328a99a999ab9a3370e900000103d03c8983318029aba10011305205335573c0046aae74004dd5000899800bae75a4464460046eac004c1dc88cccd55cf800903911919a8391983698031aab9d001300535573c00260086ae8800cd5d080102e9191919299a999ab9a3370e900000103b03a89983b9bae357420026eb4d5d09aba20011304e04f35573c0046aae74004dd50009839111299a999ab9a3370e0020300e60e4260969201035054330015335333573466e200040601cc1c84cc00ccdc080c00119b81018001132332212330010030023370800600266e10008004cc010008004c1c48894cd4ccd5cd19b8700101707207110021330030013370c00400244644a66aa66a666ae68cdc3980600218068008390388980119aa80500200088388839099ab9c49010348313200071307222533500110722215335350022233500722222223335734666e54024cdc51bb3375200e66e28dd99ba8006337146eccdd400299b8a37666ea4010cdc51bb337520066eccdd480100083e83e00089802000883990009191919299a999ab9a3370e900000103803788378a99a999ab9a3370e90010010380378838098240249aab9e00235573a0026ea800488c8c8c94cd4ccd5cd19b87480000081c01bc4488800854cd4ccd5cd19b87480080081c01bc4c84888c00c010c014d5d08008a99a999ab9a3370e900200103803788911000898240249aab9e00235573a0026ea80048c8c8c94cd4ccd5cd19b87480000081b81b44cc8848cc00400c008dd71aba1001375a6ae84d5d1000898230239aab9e00235573a0026ea80048c88c008dd60009836111999aab9f0012067233506630043574200460066ae88008148cc1a88844894cd400841988854cd400c41a0884cd41a4cc190010008cd54c0204800400c0044800488888848cccccc00401c01801401000c008c1a0894cd4004520002213370090011802000983391299a8008a400044266e012002300400133066221225335333573466e24009200006806710621533500110622213350630023353006120013370200890010008900091a8009111111111111111299a9809006083a099ab9c4901035530310007330642253350011064223213500322300300130682253350011300600322135002225335333573466e1d200000106c06b13006003106b22235003223500422350052253355335333500a05800600515335333573466e1c01000c1a81a44ccd5cd19b8f00200106a06910691069106a133573892102483200069330622212225335002153350011065221066221533500310662215335330070040021333530091200100700300110681200122232330652253350011300348000884d4008894cd4ccd5cd19b8f002009069068130073370201c60180022600c0060084a66a666ae68cdc380099b8048008c01400818c188418c4cd5ce248103483134000623060225335001148000884cdc024004600800260be44a66a00220084426a0044466e00004c01800c88c8d400c8894cd4c020d400c88888888888888880204c98cd5ce248102483600048232215335001153353002300c300735006222222222222222201010651335738921024835000642213263357389210248370004d306522533500110642215335330550050021067130040013060225335001105a22135002223232330682253350011003221335063002300400100230070043302c00735001222200348000c170894cd40044158884cd415c008c010004c16c894cd40044154884cd4158008c010004cc168884894cd4ccd5cd19b890024800017016c400454cd40044158884cd4c01848004cdc080224004002240026444666660060904600c0026660060904666ae68cdc3a40000020b60b444666ae68cdc380100082e02d8010009119191191119801801000982f111299a80109802800910a99a801898040021109a80211191a80291299a998088028010a99a9980680200089980600400308338a99a9808002099806004005099801a99a98080008831099a8308038310031833911299a80088339109a80111299a980a0008998038030018a99a9980a8048010a99a99808804000899808006199837111299a80108009109980280099a835001001803001883589980399a832802003001982e11299a800882e1109a80111299a980400089803001882f982d91299a800882d9109a80111299a980380089803001882f24903505438003057225335001105722135002225335333573466e1d200000105b05a13006003105a23724600400260aa44a66a002203c44266e28dd99a801111119ba548000cd5d01a8021119ba548000cd5d0180e00119aba03301d233500123374a900019aba0301e001376204044466e9520023357406ea000ccd5d01ba80023357406ea0004dd88110009bb101e335740666018ea5402c00ccd5d02999a801099ba548000dd880e1099ba548010cd5d00009bb101d213374a900119aba037520026ec4074cd5d01980dba90013762038600800246e48c064c058c12800488ccd5cd19b8f3766666008ea5400c008dd99998023a9500300105305213300175246ea000488c88dd3180100098299119a800a5eb7bdb18088d400888cd5d019bb030080023007001300600332253353004300b00121533335001210011300349888884c01d262130044984c0092623263357389210248330003532253353003300a001215333350012130044984c00d26222213007498840044c00926232633573892010248330003432233333302000122532335333573466e1d20000030510501533533335573e0044a07a4607c6608c6ae8400cd5d100181b909a80091299a980400110a99a9999aab9f00225041230423304a357420066ae8800c0ec84d4004894cd4cc094098008854cd4cccd55cf8011282291823198271aba10033574400607e426a00244a66a605800442a66a6666aae7c008941248c8c8c130008d5d10021aba1003043215335302d00121304b333301500b0070030011300e4984c035261300c4984c02526130084984c01526130044984c0052613001498c894cd4ccd5cd19b874800801014814454cd4cccd55cf8019281f1191918208011aba20053574200807042a66a66666604a00244a66a666ae68cdc3a40000040aa0a82a66a6666aae7c004941048c108cc128d5d08011aba200203b2135001225335302800221533533335573e0044a08a4608c6609c6ae8400cd5d100181f909a80091299a9981481500110a99a9999aab9f002250492304a33052357420066ae8800c10c84d4004894cd4c050008854cd4cccd55cf80112826918271982b1aba10033574400608e426a00244a66a606a00442a66a6666aae7c008941448c8c8c150008d5d10021aba100304b21533530360012130533333302100f00b00700300115051150501504f1504c1504b1504815047150441504315040150402503f2503f2503f2503f2130403009001130034984c0092613002498c894cd4ccd5cd19b874801001014814454cd4cccd55cf8019281f1191918208011aba20053574200807042a66a66666604a00244a66a666ae68cdc3a40000040aa0a82a66a6666aae7c004941048c108cc128d5d08011aba200203b2135001225335302800221533533335573e0044a08a4608c6609c6ae8400cd5d100181f909a80091299a9981481500110a99a9999aab9f002250492304a33052357420066ae8800c10c84d4004894cd4c050008854cd4cccd55cf80112826918271982b1aba10033574400608e426a00244a66a606a00442a66a6666aae7c008941448c148cc168d5d08019aba200304b2135001225335303900221533533335573e0044a0aa460ac660bc6ae8400cd5d1001827909a80091299a981e00110a99a9999aab9f002250592305a33062357420066ae8800c14c84d4004894cd4c100008854cd4cccd55cf8011282e9182f198331aba1003357440060ae426a00244a66a6608208800442a66a6666aae7c008941848c8c8c190008d5d10021aba100305b215335304700121306333333333303001f01b01701300f00b00700300115061150601505f1505c1505b15058150571505415053150501504f1504c1504b1504815047150441504315040150402503f2503f2503f2503f213040300c001130034984c009261300249894cd4ccd5cd19b874801800c1441404c0f4020540f0940e8940e8940e8940e88cccccc07c004894cd4ccd5cd19b874800000813c13854cd4cccd55cf8009281d91919181f0011aba20033574200406a42a66a604200242607a0022a0762a0742a0744a0724a0724a0724a072424444600800a24444006444424444666600401000e00c00a424444600200a4444444442466666666600201401201000e00c00a00800600444444246666600200c00a008006004644a66a6a6a002444006444444444444444401c2600493110a99a998029a80111110021a9a98030019100091110020980e0010980224c464c66ae71241034831310002c2235002223500322533533500423350032333573466e3c00800413012c812c8cd400c812c8ccd5cd19b8f00200104c04b153350032153350022133500223350022335002233500223303e002001204f2335002204f23303e00200122204f222335004204f2225335333573466e1c01800c14814454cd4ccd5cd19b870050020520511333573466e1c01000414814441444144412854cd4004841284128412494cd4c008004840044c98cd5ce2490248380002a23500122235003222222222222222233333350112201a20192201a20192322300201330592253350011504422135002225335533535002223500922333573466e3c0100081841804d400888d402488ccd5cd19b87003001061060105c13049004130060032019233500123374a900019aba037520026ec40108cdd2a400466ae80dd48009bb1004225335001213374a900019aba030030013762008266e9520023762006932814981f91299a80089801180181c910a99a800880111098031803802981f11299a800881c110a99a800880191099a81d998038020011803000981e911299a8010800910a99a801880219110a999a9981f0028010a801899a81e001198040038008a801899a81c80119802800801981e11299a800880291099a801111b8a001300400122333573466e1d200230053300300235001222200303b03a232253355335300200121302800115026213303e225335001103822132533535003225335333573466e1d20020010430421302f0021502e2133503b001002100130040010011035303b2253350011502622135002225335333573466e3c00801c0fc0f84c0ac0044c01800d2201003038225335001148000884cdc02400460080024a66a646466666601400444a66a666ae68cdc3a40000040740722a66a6666aae7c004940988c09ccc0bcd5d08011aba20020202135001225335300b00221533533335573e0044a05446056660666ae8400cd5d1001812109a80091299a980500110a99a9999aab9f0022502e232323031002357440086ae8400c0a0854cd4c04c00484c0c0ccc04001c00c004540b8540b4540b0540a4540a0540945409494090940909409094090c0108cccccc028004894cd4ccd5cd19b87480000080e80e454cd4cccd55cf8009281311813998179aba100235744004040426a00244a66a601800442a66a6666aae7c008940a88c8c8c0b4008d5d10021aba1003024215335300f00121302c12330010040021502a150291502815025150252502425024250242502430090012135001222002103022212333001004003002232233333300800122502325022002250222502230362233335573e002460460624a66a60086ae84008854cd4c010d5d100190981299a8190010008a811899281198019aba200201c2533530030012130200011501e2333333004001225335333573466e1d20000020340331533533335573e0024a04046042660526ae84008d5d100100d109a80091299a980380110a99a9999aab9f00225024232323027002357440086ae8400c078854cd4c02800484c098cc0ec00c004540905408c540885407c5407c940789407894078940788cccccc00c0048940789407494074940748c0780048cccccc00800489407494070940708c07400494070888888ccccccd5d2003119198039aab9d00135573c0026ea801c8c014dd5803918021bac00723003375a00e460046eb801c06894ccd4d400488880084c98cd5ce2490248390001421001213263357389210348313000015302e22533500110282213350293500222330260023301b23370490008008009802000899319ab9c490103483333000112326335738921034833370001123232325335333573466e1d200000202d02c1375a6ae840044c014018d55cf0011aab9d0013754002464c66ae7000403d240103505431002375c002604e44a66a0022900011099b8048008c010004c098894cd4004520002213370090011802000899319ab9c49103483434000093024225335001148000884cdc0240046008002604644a66a002203a44266a0044444660220260066008002604444a66a00220424426a00444a66a666ae68cdc7a450b4879647261486561645631000020260251333573466e1d2002001026025130060033021225335001148000884cdc0240046008002264c66ae712410348323700004132633573892103483235000031326335738921034832340000223263357389210248310000212001301b225335001101522133500222223300900b00330040012322230033009333500b00a002001301b225335001101522133501635002223301300233008233350012330094800000488cc0280080048cc0240052000001300400123223002001301a2253350011014221335015350022233012002300700130040012233700004002424460040062244002602a44a66a002201e44266a0206a004446601a004666a0024601400244666a01401200400246016002600800244666ae68cdc780100080a00989911119191980c91299a800880191099a80a0011802000980100218029980c11299a800880911099299a9a80191911801005980f11299a800880f1109a80111299a99808001003881089803001899a80a00180088009802000801180b91299a800880891099a8091a8011119198080019800804180e91299a80089aa8078019109a80111299a998078010040891119801005002098030019802000980991299a800880691099a8071a801111980580118050009802000980911299a800880611099a8069a801111980500118048009802000980891299a800880591099a8061a80111198048011aa8038009802000909111801802089091118008021109198008018011a8019110009a8011110011a800911001999180080091091919980111801111180180211801111180100211801111180080211a998020020019a801800891111998021299a800899a803003803910a99a800899a804001804910a99199a998068028018a800899980400199a8058028060010a8008999803001119a805802800800911299a800899a80419a804001801180300499110a999a998068030010a801899980400119a8058030028008a801899a80419a804001801180300091129919a80109800a4c442a64666a6601c00e0062a00226008930a80089998038011180319a806003800800919a804980199a80480200518038010910010910911980080200199111a9a80111001111a9a80191001112999a998038020010a99a999ab9a3370e00600201801620142a66a666ae68cdc48018008060058804080489980380200109980380200111299a999ab9a3371e00400200e00c200a2a66a666ae68cdc8801000803803080188020911001891100109110008910010910009109198008018011191800800918011198010010009" + "description": "hydra-vHead-0.19.0-533-g6cb0345d5", + "cborHex": "59389c593899010000323233223332223233223232323232332232323322323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323233332222323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232322323235300100322233333350012230564910350543500230554910350543500223056490103505435002305549103505435002253350012153353232325333350033232323232215333333350081306c49884c1b5261306c498c8c8c8c8c8c8854cd4c09d403454cd54cd4ccd5cd19b8735304900e222222222200750020900108f011090011335738921034831330008f01153355335333573466e25402cd4020888888888801823c04240044240044cd5ce2481034832390008f0115335333335001253355335333573466e3cd4c12803c8888888888010c0ec22c04244042400454cd4ccd5cd19b8f35304a00f2222222222003303b08b010910109001133301d500633333302450045003500c35304a00f2222222222005303b08b01303b08b0100110900110900110910113357389201034833370009001253355335333573466e3cd4c12803c8888888888010c0ec22c0424404240044ccc0754018cccccc0914011400d4030d4c12803c8888888888014c0ec22c04d4c12803c888888888800c0044240044244044cd5ce2490348343700090012253355335333573466e3cd4c12c040888888888800cc0f02300424804244044ccc079401ccccccc0954014cdc0a80224004a01a6a6096020444444444400a002607811802004212202212402266ae712410348343800091012253355335333573466e3cd4c12c0408888888888010c0f023004248042440454cd4ccd5cd19b8f35304b0102222222222003303c08c010920109101133301e5007333333025500533702a008900128069a98258081111111111002981e04600800801084880884880884900899ab9c4901034833380009101253355335333573466e3cd4c12803c888888888800cc0ec22c0424404240044ccc0754018cccccc0914011400d4030d4c12803c8888888888014d4c12803c8888888888010c0ec22c040044240044244044cd5ce249034834390009001153353302e00e500315335533533232230020013093012253350011093012215335333573466e3c01400825404250044250044c010005403140104240044cd5ce2481034833360008f0115335353535500d2222222222222222009220012253335002215335333573466e24005402824c0424804424c044cd5ce2490348333000092011506615066153355335333502a07a500933508901500c50041090011335738921034833340008f01153355335333573466e1cc1a94024c1ad40282400423c0454cd4ccd5cd19b8735304900e222222222200150070900108f011090011335738921034833320008f0115335333573466e1cd4c1240388888888888004cdc02803a8030480084780884800899ab9c491034833330008f01153353330293308401500a5005330840135304900e22222222220085006330840135304900e222222222200a5003153353303c5335305400e213535001220012222003108a0135533535500d222222222222222200e130670332210022222003109001133573892010248340008f01108f01108f01108f01108f01108f01108f01108f01108f01108f01108f011350062222222222007135005222222222200a135004222222222200213500322222222220091350022222222222008135001222222222200121306d4988884d40288894cd4ccc0a8d400c8888888888888888030d401c8888888888028d401c8888888888024c854cd54cd4ccd5cd19b8f303a33502600750013500822222222220050900108f0110900113357389201034833390008f01153355335333573466e3cd40208888888888010c0e8c8cd409c01c004cd411001d40042400423c044240044cd5ce249034835340008f01153355335333573466e3cd4020888888888800cc0e8c8cd409c018004cd411001d40042400423c044240044cd5ce249034834300008f0113535350042222222222222222009220022253335002215335333573466e24004d402c88888888880042480424c04424c044cd5ce24810348343100092011506e1506e108f01108f01108f01135003222222222222222200e108e0121306d4984d4c10001488888888880084d4c0fc01088888888880244d4c0f800c888888888801854cd4d5400488888888888888880204c1652622153350011002221305d4984d400488800c4c1992622232322153233333335009150012150021350082225332355335333573466e3cd4c0f403088888004c0c0d5400488800c23804234044238044cd5ce2481034831370008d01153355335333573466e1d200035303d00c2222200208e0108d01108e0113357389201034832300008d0115335333027330820135303d00c2222200400a330820135303d00c2222200300b330820135303d00c2222200500915335533533043533535004222222222222222200e108801221306e001323233307607800230633350890133084010433350890100108a0108a01330830104235005222222222222222200d355001222001108e011335738921034831390008d01153355335330360095335305200c213535001220012222003108801108e011335738921034831360008d01153355335333573466e1cd54004888008c1b402823804234044238044cd5ce249034831380008d01153353302c00c00913025004108d01108d01108d01108d01108d01108d0113007350032222222222222222010108c01215002215002222150042150021533333335008135007222533533302735003222222222222222200c00700832153353302b00b0081533533077302f50013037335023306a500135004222222222222222200e108d011335738921034831350008c01108c0113300508601350032222222222222222010108b0121306d4984c1b12621306d49884c1b5262221306f49884c1b5263089012232253350011003221350022253353304600a00113300830063057001003133008007003308b0122533500110032213350860100230040013088012253350011333056082014800020804884c8d400c88d400c8c8894cd4cc14cd40148888010d4d4c15003c880048888010401c54cd4cc1200300144ccc17cc00cc164014cdc02400400400226660be0080046660ee0f20026a00a444400661200244a66a002200644266a11602004600800260080026464646464646464464642a6666666a01a260e2931919191910a99a981528080a99aa99a999ab9a3371266e04d4d4d54040888888888888888802488004894ccd400884004541dc541dcd4d4d54040888888888888888802488008894ccd400884004541d8541d9401024c0424804424c044cd5ce2481034832320009201153355335333573466e1cd4c1300448888888888004c8d4048888d4d4d400c888888888888888802488004894ccd400884cdc00008038a83c8a83ca8020498084900884980899ab9c490103483233000920115335330310115003153355335333573466e1cd4c130044888888888801d400824c0424804424c044cd5ce24903483133000920115335533333350012153355335333573466e2540412000093010940115335333573466e3cd4c1340488888888888010c0f8238042500424c0454cd4ccd5cd19b8f500f303e08e0109401093011333020500633333302750045003501035304d0122222222222005303e08e01303e08e0100110930110930110930110940113357389201034834360009301153355335333573466e1d20005002093010920115335333573466e1d2000500f09301092011333573466e3cd4c1300448888888888014d40208888800424c0424804424804424804424c044cd5ce2490348323800092012153355335333573466e3cd4c1340488888888888010c0f8238042500424c0454cd54cd4ccd5cd19b8f500f303e08e0109401093011093011094011333020500633333302750045003501035304d0122222222222005303e08e01500f0011093011093011094011335738920103483530000930122153355335333573466e3cd4c13804c8888888888010c0fc23c04254042500454cd4ccd5cd19b8f5010303f08f0109501094011333021500733333302850055004501135304e0132222222222005001303f08f010021094011094011095011335738920103483532000940122153355335333573466e3cd4c13804c8888888888010c0fc23c04254042500454cd4ccd5cd19b8f5010303f08f01095010940113330215007333333028500533702a008900128089a98270099111111111002981f84780800801084a00884a00884a80899ab9c49103483531000940122153355335333573466e3cd4c13804c8888888888010004254042500454cd4ccd5cd19b8f5010303f08f01095010940113330215007333333028500533702a008900128089a98270099111111111002800981f84780801084a00884a00884a80899ab9c491034835330009401153355335533535304c01122222222220021093012210940110930113357389210348323600092011533553353303f53353057011213535001220012222003108d01355335355010222222222222222200e1306a0362210022222003109301133573892010248340009201133302c330870135304c01122222222220095005330870135304c01122222222220085004330870135304c011222222222200a5003109201109201109201109201109201109201109201109201135006222220021350052222200513500422222003135003222220041307149884c1c926323221533533302a33085013500622222004500a3308501350062222200335304000f2222200333085015003500932153355335333573466e1cd4c10404088888008cdc024004a0061240212202212402266ae712410348323100091011533533301e500b333333025500a50033500222200235304101022222001303c08c01303c5001350022220031533553353304753353056010213535001220012222003108c0133307807a355335500c1306903522100222220033077500110920113357389201024834000910113303001050041091011091011091011335027350012220015335500b130684910350543900221001109001135004222220021350032222200522213074498c88c8c84d40408894cd4ccc0b8cc22404d4028888880114030cc22404d40288888800cd4c11004c8888800ccc224054025402cc854cd54cd4ccd5cd19b8735304501422222002337009001280404b0084a80884b00899ab9c49010348323100095011533553353304233307c07e53353009308601350042222222222222222010210011326335738921034834350007a3535500122001222200335533535004222222222222222200e1306d0392210022222003109601133573892102483400095011533533034014500a15335333022500d333333029500c500835007222002353045014222220013038533532333306406706350600013068355001220012135001222001109001304009001350072220031533530053087013500422222222222222220101096011335738920103483433000950110950110950110950110950115335323235005222222222222222230110103098012253350011508a0122135002225335330610020071308f010041300600350052100113263357389201034834340007910940130930122533500110920122153353305a50050021095011300400113500122200113500322222002308f01225335001150810122153353303950050021308401002130040011350012222200513530390082222200513530380072222200413530370062222200513530360052222200413535004222003222222222222222200e135303e0032222222222003135303d0022222222222006135001222003300900b3232325335333573466e1d2000002084010830111222222200515335333573466e1d200200208401083011321222222230010083232325335333573466e1d20000020870108601132333222123330010040030023301975c6ae84008dd69aba10013010357426ae88004d5d10008982f02f9aab9e00235573a0026ea8d5d08008a99a999ab9a3370e90020010420084180899091111111801804191919299a999ab9a3370e90000010438084300899199911091998008020018011980cbae357420046eb4d5d08009bad357426ae88004d5d10008982f02f9aab9e00235573a0026ea8d5d08008a99a999ab9a3370e90030010420084180899091111111803004191919299a999ab9a3370e90000010438084300889111110028a99a999ab9a3370e90010010438084300899091111118030039980c3ae357420022a66a666ae68cdc3a400800410e0210c022642444444600800e66030eb8d5d08008a99a999ab9a3370e90030010438084300899910911111198010040039980c3ae357420026eb8d5d09aba200115335333573466e1d20080020870108601133221222222330030080073301875c6ae84004dd71aba1357440022a66a666ae68cdc3a401400410e0210c022664424444446600201000e66030eb8d5d08009bae357426ae880044c17817cd55cf0011aab9d00137546ae8400454cd4ccd5cd19b87480200082100420c044c848888888c010020c8c8c94cd4ccd5cd19b874800000821c04218044c8488888c014018cc061d71aba100115335333573466e1d2002002087010860113322122222330020070063301875c6ae84004dd71aba1357440022a66a666ae68cdc3a400800410e0210c02264244444600800c66030eb8d5d08008a99a999ab9a3370e9003001043808430089991091111198018038031980c3ae357420026eb8d5d09aba200115335333573466e1d2008002087010860113212222230010063301875c6ae840044c17817cd55cf0011aab9d00137546ae8400454cd4ccd5cd19b87480280082100420c0444888888801c54cd4ccd5cd19b87480300082100420c044c8ccc88848888888ccc008028024020dd69aba1002375a6ae84004dd69aba1357440026ae880044c16c170d55cf0011aab9d001375400c646464a66a666ae68cdc3a4000004106021040226464666608260b66ae8400ccc058178d5d08011bae35742002601a6ae84d5d10009aba2001357440022a66a666ae68cdc3a400400410602104022607c646464a66a666ae68cdc3a400000410c0210a022646464666660926eb8d5d08021980d0311aba1003305f357420046eb4d5d08009bae357426ae88004d5d10009aba200135744002260ba0bc6aae78008d55ce8009baa357420022a66a666ae68cdc3a4008004106021040226082646464a66a666ae68cdc3a400000410c0210a0226464646464646464666666666609a6eb8d5d08049980f8339aba100830643574200e6eb4d5d08031bad3574200a6eb8d5d08021bae357420066eb8d5d08011980fbae357420026eb4d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba20011305d05e35573c0046aae74004dd51aba100115335333573466e1d2006002083010820110401305a05b35573c0046aae74004dd500088190982ba49035054350013056491035054350023055491035054350032323232323232323223232325335333573466e1d20000020860108501132333222123330010040030023232325335333573466e1d200000208a0108901132323232323232323232323232323333333333333333222222222222222212333333333333333300101101000f00e00d00c00b00a0090080070060050040030023302901a3574201e660520346ae84038cc0a406cd5d08069bad3574201866603eeb94078d5d08059981480c1aba100a33301f01c75a6ae84024c8c8c94cd4ccd5cd19b874800000826c04268044cc8848cc00400c008c8c8c94cd4ccd5cd19b874800000827804274044cc8848cc00400c008cc0b5d69aba1001302c357426ae880044c1d41d8d55cf0011aab9d00137546ae84004c8c8c94cd4ccd5cd19b874800000827804274044cc8848cc00400c008cc0b5d69aba1001302c357426ae880044c1d41d8d55cf0011aab9d00137546ae84d5d1000898390399aab9e00235573a0026ea8d5d080419814bae3574200e66603e4646464a66a666ae68cdc3a400000413802136022642444444600a00e6eb8d5d08008a99a999ab9a3370e900100104e0084d808990911111180100398121aba100115335333573466e1d200400209c0109b01132122222230030073020357420022a66a666ae68cdc3a400c00413802136022664424444446600c01000e6eb4d5d0800980e1aba1357440022a66a666ae68cdc3a401000413802136022642444444600200e603a6ae8400454cd4ccd5cd19b87480280082700426c044cc884888888cc01002001cdd69aba1001301b357426ae880044c1cc1d0d55cf0011aab9d001375400204a6ae84018ccc07dd70129aba1005375c6ae84010ccc07c064cc07c0a08c8c8c94cd4ccd5cd19b87480000082700426c044488800854cd4ccd5cd19b87480080082700426c044488800454cd4ccd5cd19b87480100082700426c044488800c4c1cc1d0d55cf0011aab9d00137540026ae8400ccc0a405cd5d08011980ebad357420026603aeb4d5d09aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae88004d5d10009aba2001357440026ae880044c184188d55cf0011aab9d00137546ae84008d5d0800991919299a999ab9a3370e90000010450084480899091111118028039bae357420022a66a666ae68cdc3a400400411402112022664424444446600401000e60246ae84004cc03c05cd5d09aba200115335333573466e1d200400208a010890113212222223003007300e357420022a66a666ae68cdc3a400c00411402112022664424444446600c01000e6eb4d5d080098051aba1357440022a66a666ae68cdc3a401000411402112022642444444600200e60166ae8400454cd4ccd5cd19b874802800822804224044cc884888888cc01002001cdd69aba10013009357426ae880044c184188d55cf0011aab9d00137546ae84d5d10009aba20011305d05e35573c0046aae74004dd50009191919299a999ab9a3370e90000010428084200899199911091998008020018011bad3574200460146ae84004c8c8c94cd4ccd5cd19b874800000822404220044c8ccc88848888888ccc00c028024020cc03c068d5d08011aba10013300f75c6ae84d5d10009aba200115335333573466e1d200200208901088011332212222222330070090083300e01935742002646464a66a666ae68cdc3a400000411802116022664424660020060046eb4d5d08009bad357426ae880044c18c190d55cf0011aab9d00137546ae84d5d10008a99a999ab9a3370e90020010448084400899910911111119801004804199808006bad357420026601ceb8d5d09aba200115335333573466e1d200600208901088011321222222230040083300e019357420022a66a666ae68cdc3a401000411202110022646466664444244444446666002016014012010660200366ae8400ccc07003cd5d0801199809007bad357420026a646464a66a666ae68cdc3a400000411c0211a02266104026eb4d5d08009bad357426ae880044c194198d55cf0011aab9d00137546ae84d5d1000911980b8010009aba2001357440022a66a666ae68cdc3a4014004112021100226644244444446600a0120106601c0326ae84004c8c8c94cd4ccd5cd19b87480000082300422c044cc045d71aba10011306306435573c0046aae74004dd51aba1357440022a66a666ae68cdc3a4018004112021100222444444400c260c00c26aae78008d55ce8009baa357426ae88004d5d10008982e02e9aab9e00235573a0026ea8004c88c8c8c94cd4ccd5cd19b874800000821404210044cc88488888888888cc014034030c024d5d0800998053ad357426ae8800454cd4ccd5cd19b874800800821404210044cc88488888888888cc008034030c024d5d0800998053ad357426ae8800454cd4ccd5cd19b874801000821404210044cc88488888888888cc028034030c024d5d080098029aba1357440022a66a666ae68cdc3a400c00410a021080226466644424444444444466600c01c01a01860146ae84008c018d5d08009bad357426ae88004d5d10008a99a999ab9a3370e90040010428084200899910911111111111980380680618049aba1001375a6ae84d5d10008a99a999ab9a3370e90050010428084200899091111111111180080618049aba100115335333573466e1d200c0020850108401133221222222222223300300d00c3009357420026eb4d5d09aba200115335333573466e1d200e0020850108401133221222222222223300900d00c375c6ae84004dd71aba1357440022a66a666ae68cdc3a402000410a0210802266442444444444446601001a0186eb8d5d08009bad357426ae8800454cd4ccd5cd19b874804800821404210044cc88488888888888cc02c034030c024d5d080098049aba1357440022a66a666ae68cdc3a402800410a0210802264244444444444600801860126ae840044c170174d55cf0011aab9d0013754002644646464a66a666ae68cdc3a400000410a0210802264244460060086eb8d5d08008a99a999ab9a3370e900100104280842008990911180080218029aba100115335333573466e1d2004002085010840113322122233002005004375c6ae84004c014d5d09aba20011305c05d35573c0046aae74004dd50009191919299a999ab9a3370e900000104200841808990911180180218041aba100115335333573466e1d200200208401083011122200215335333573466e1d20040020840108301112220011305b05c35573c0046aae74004dd50009191919299a999ab9a3370e900000104180841008990911180180218039aba100115335333573466e1d20020020830108201132122230020043007357420022a66a666ae68cdc3a40080041060210402264244460020086eb8d5d08008982d02d9aab9e00235573a0026ea80048c8c8c94cd4ccd5cd19b874800000820804204044cc8848cc00400c008c028d5d080098029aba135744002260b20b46aae78008d55ce8009baa00123232325335333573466e1d2000002081010800113232333322221233330010050040030023232325335333573466e1d20000020860108501133221233001003002300a35742002660164646464a66a666ae68cdc3a400000411402112022642446004006601c6ae8400454cd4ccd5cd19b874800800822804224044c8ccc888488ccc00401401000cdd69aba1002375a6ae84004dd69aba1357440026ae880044c184188d55cf0011aab9d00137540026ae84d5d10008982e82f1aab9e00235573a0026ea8d5d08019998053ae500935742004646464a66a666ae68cdc3a400000410c0210a02224440062a66a666ae68cdc3a400400410c0210a02264244460020086eb8d5d08008a99a999ab9a3370e90020010430084280899091118010021aba10011305d05e35573c0046aae74004dd51aba10013300875c6ae84d5d10009aba200135744002260b00b26aae78008d55ce8009baa00123232325335333573466e1d20000020800107f1321223002003375c6ae8400454cd4ccd5cd19b8748008008200041fc4c8488c00400cdd71aba10011305705835573c0046aae74004dd500091191919299a999ab9a3370e90010010400083f8a8390a99a999ab9a3370e90000010400083f8983998029aba10011305705835573c0046aae74004dd5000899800bae75a4464460046eac004c1f488cccd55cf800903c11919a83c1983998031aab9d001300535573c00260086ae8800cd5d08010309191919299a999ab9a3370e900000103e03d89983e9bae357420026eb4d5d09aba20011305305435573c0046aae74004dd5000983c111299a999ab9a3370e0020300f20f0260a09201035054330015335333573466e200040601e41e04cc00ccdc080c00119b81018001132332212330010030023370800600266e10008004cc010008004c1dc8894cd4ccd5cd19b8700101707807710021330030013370c00400244644a66aa66a666ae68cdc39806002180680083c03b8980119aa805002000883b883c099ab9c49010348313200077307822533500110782215335350022233500722222223335734666e54024cdc51bb3375200e66e28dd99ba8006337146eccdd400299b8a37666ea4010cdc51bb337520066eccdd4801000841808410080089802000883c90009191919299a999ab9a3370e900000103b03a883a8a99a999ab9a3370e900100103b03a883b098268271aab9e00235573a0026ea800488c8c8c94cd4ccd5cd19b87480000081d81d44488800854cd4ccd5cd19b87480080081d81d44c84888c00c010c014d5d08008a99a999ab9a3370e900200103b03a88911000898268271aab9e00235573a0026ea80048c8c8c94cd4ccd5cd19b87480000081d01cc4cc8848cc00400c008dd71aba1001375a6ae84d5d1000898258261aab9e00235573a0026ea80048c88c008dd60009839111999aab9f001206d233506c30043574200460066ae88008158cc1c08844894cd400841b08854cd400c41b8884cd41bccc1a8010008cd54c0204800400c0044800488888848cccccc00401c01801401000c008c1b8894cd4004520002213370090011802000983691299a8008a400044266e01200230040013306c221225335333573466e24009200006e06d10681533500110682213350690023353006120013370200890010008900091a8009111111111111111299a9809006083d099ab9c49010355303100079306a225335001106a2232135003223003001306e2253350011300600322135002225335333573466e1d200000107207113006003107122235003223500422350052253355335333500a05a00600515335333573466e1c01000c1c01bc4ccd5cd19b8f00200107006f106f106f107013357389210248320006f33068221222533500215335001106b22106c2215335003106c22153353300700400213335300912001007003001106e12001222323306b2253350011300348000884d4008894cd4ccd5cd19b8f00200906f06e130073370201c60180022600c0060084a66a666ae68cdc380099b8048008c0140081a41a041a44cd5ce248103483134000683066225335001148000884cdc024004600800260ca44a66a00220084426a0044466e00004c01800c88c8d400c8894cd4c020d400c88888888888888880204c98cd5ce24810248360004c232215335001153353002300c3007350062222222222222222010106b13357389210248350006a22132633573892102483700051306b225335001106a221533533057005002106d1300400130662253350011060221350022232323306e2253350011003221335069002300400100230070043302200735001222200348000c188894cd40044170884cd4174008c010004c184894cd4004416c884cd4170008c0100048dc918031801982b000a4810350543800305e2253350011300230030582215335001100222130063007005305d22533500110572215335001100322133505a330070040023006001305c222533500210012215335003100432221533353305d00500215003133505b0023300800700115003133505800233005001003305b225335001100e221350022233714002600c0064644600400260b644a66a00220b44426a00444a66a666ae68cdc780100382f82f0980400089803001982c91299a800882c1109a80111299a999ab9a3371e91010b48796472614865616456310000205d05c1333573466e1d200200105d05c1300600323724600400260ae44a66a002201444266e28dd99a801111119ba548000cd5d01a8021119ba548000cd5d0180780119aba033010233500123374a900019aba03011001376202644466e9520023357406ea000ccd5d01ba80023357406ea0004dd880a8009bb1011335740666016ea5402800ccd5d02999a801099ba548000dd88079099ba548010cd5d00009bb1010213374a900119aba037520026ec4040cd5d0198073a9001376201e600800244666ae68cdc79bb3333004752a0060046eccccc011d4a80180082b02a899800ba923750002446446e98c008004c15888cd40052f5bded8c0446a0044466ae80cdd8180400118038009803001991299a9806980a00090a9999a80090980224c2600693111109803a4c420022600493119319ab9c490102483300036233500123374a900019aba037520026ec40108cdd2a400466ae80dd48009bb1004225335001213374a900019aba030030013762008266e9520023762006932441003304e221225335333573466e24009200005004f100115335001104a2213353006120013370200890010008900099111999980181c1180280099980181c1199ab9a3370e900000082782711199ab9a3370e0040020a009e004002446464464446600600400260a4444a66a0042600a002442a66a006260100084426a00844646a00a44a66a6602200a0042a66a6601a00800226601801000c20b62a66a6020008266018010014266006a66a602000220ac266a0aa00e0ac00c60b6444a66a00220b64426a00444a66a602800226600e00c0062a66a6602a0120042a66a660220100022660200186660c4444a66a00420024426600a00266a0bc00400600c00620be26600e66a0b200800c00660a044a66a00220a04426a00444a66a60100022600c00620a6609e44a66a002209e4426a00444a66a600e0022600c00620a4609844a66a00220984426a00444a66a666ae68cdc3a40000020a009e2600c006209e44666ae68cdc3a40046024660060046a00244440060960944644a66aa66a600400242607e0022a07a426609c44a66a002209044264a66a6a00644a66a666ae68cdc3a40040020a60a42608c0042a08a4266a09600200420026008002002208a609644a66a0022a07a4426a00444a66a666ae68cdc78010038278270982100089803001991299a9801980500090a9999a8009080089801a4c44442600e9310980224c2600493119319ab9c49010248330002c32233333301900122532335333573466e1d200000304b04a1533533335573e0044a07c4607e660806ae8400cd5d1001817909a80091299a980400110a99a9999aab9f002250422304333044357420066ae8800c0cc84d4004894cd4cc070084008854cd4cccd55cf8011282311823998241aba10033574400606e426a00244a66a604c00442a66a6666aae7c008941288c8c8c134008d5d10021aba100303b215335302300121304c333301500b0070030011300e4984c035261300c4984c02526130084984c01526130044984c0052613001498c894cd4ccd5cd19b874800801013012c54cd4cccd55cf8019281f9191918210011aba20053574200806042a66a66666603c00244a66a666ae68cdc3a400000409e09c2a66a6666aae7c004941088c10ccc110d5d08011aba20020332135001225335302200221533533335573e0044a08c4608e660906ae8400cd5d100181b909a80091299a9981001280110a99a9999aab9f0022504a2304b3304c357420066ae8800c0ec84d4004894cd4c050008854cd4cccd55cf8011282711827998281aba10033574400607e426a00244a66a605400442a66a6666aae7c008941488c8c8c154008d5d10021aba100304321533530300012130543333302100f00b0070030011505215051150501504d1504c150491504815045150441504115041250402504025040250402130413009001130034984c0092613002498c894cd4ccd5cd19b874801001013012c54cd4cccd55cf8019281f9191918210011aba20053574200806042a66a66666603c00244a66a666ae68cdc3a400000409e09c2a66a6666aae7c004941088c10ccc110d5d08011aba20020332135001225335302200221533533335573e0044a08c4608e660906ae8400cd5d100181b909a80091299a9981001280110a99a9999aab9f0022504a2304b3304c357420066ae8800c0ec84d4004894cd4c050008854cd4cccd55cf8011282711827998281aba10033574400607e426a00244a66a605400442a66a6666aae7c008941488c14ccc150d5d08019aba20030432135001225335302e00221533533335573e0044a0ac460ae660b06ae8400cd5d1001823909a80091299a981b00110a99a9999aab9f0022505a2305b3305c357420066ae8800c12c84d4004894cd4c0e8008854cd4cccd55cf8011282f1182f998301aba10033574400609e426a00244a66a607c00442a66a6666aae7c008941888c18ccc190d5d08019aba200305321350012253353303c04200221533533335573e0044a0cc4646460d20046ae88010d5d080182b90a99a9820000909834199999999981a01180f80d80b8098078058038018008a8330a8328a8320a8308a8300a82e8a82e0a82c8a82c0a82a8a82a0a8288a8280a8268a8260a8248a8240a8228a8220a8208a82092820128201282012820109820980600089801a4c26004930980124c4a66a666ae68cdc3a400c0060960942607c0102a07a4a0764a0764a0764a076466666603000244a66a666ae68cdc3a40000040920902a66a6666aae7c004940f08c8c8c0fc008d5d10019aba100202d215335301600121303e0011503c1503b1503b2503a2503a2503a2503a21222230040051222200322221222233330020080070060052122223001005222222222212333333333300100b00a00900800700600500400300222222123333300100600500400300232253353535001222003222222222222222200e130024988854cd4cc014d40088888010d4d4c01800c8800488880104c0540084c01126232633573892103483131000242235002223500322533533500423350032333573466e3c00800411811481148cd400c81148ccd5cd19b8f002001046045153350032153350022133500223350022335002233500223303400200120492335002204923303400200122204922233500420492225335333573466e1c01800c13012c54cd4ccd5cd19b8700500204c04b1333573466e1c01000413012c412c412c411054cd4004841104110410c94cd4c008004840044c98cd5ce24902483800022235001222350032222222222222222333333501122018201722018201723223002013305322533500115045221350022253353301c0020071304a00413006003201722533535002223500322333573466e3c0100081041004d400888d400c88ccd5cd19b87003001041040103c502c303b225335001148000884cdc02400460080024a66a64666600e012a0060140026016002426a002444004206626002466666601200244a66a666ae68cdc3a40000040740722a66a6666aae7c004940b48c0b8cc0bcd5d08011aba200201e2135001225335300800221533533335573e0044a0624646460680046ae88010d5d080181110a99a980780090981989198008020010a8188a8180a8178a8160a816128159281592815928159191199999805000912816928160011281612816181c911999aab9f0012302d0342533530043574200442a66a60086ae8800c84c0bccd40d4008004540b44c940b4c00cd5d100100e919999980380091299a999ab9a3370e900000101c01b8a99a9999aab9f0012502b2302c3302d357420046ae8800807084d4004894cd4c02c008854cd4cccd55cf801128179191918190011aba20043574200604042a66a60120024260626607e0060022a05e2a05c2a05a2a0542a0544a0524a0524a0524a052466666600c00244a0524a0504a050460520024a050444466666601000244a66a666ae68cdc3a40000040720702a66a6666aae7c004940b08c0b4cc0b8d5d08011aba200201d2135001225335300900221533533335573e0044a06046062660646ae8400cd5d1001810909a80091299a980600110a99a9999aab9f00225034232323037002357440086ae8400c094854cd4c03400484c0d8ccc04401c00c004540d0540cc540c8540bc540b8540ac540ac940a8940a8940a8940a888848ccc00401000c00894cd4c00800484c098004540908cccccc0080048940949409094090940908c094004888888ccccccd5d2003119198039aab9d00135573c0026ea801c8c014dd5803918021bac00723003375a00e460046eb801c06494ccd4d400488880084c98cd5ce2490248390001321001213263357389210348313000014302f225335001102922133502a3500222330270023301a23370490008008009802000899319ab9c490103483331000102326335738921034833350001023232325335333573466e1d200000202e02d1375a6ae840044c014018d55cf0011aab9d0013754002464c66ae70004039240103505431002375c002605044a66a0022900011099b8048008c010004c09c894cd4004520002213370090011802000899319ab9c49103483432000083025225335001148000884cdc0240046008002604844a66a002203c44266a0044444660200240066008002604644a66a0022900011099b8048008c0100044c98cd5ce24810348323700004132633573892103483235000031326335738921034832340000223263357389210248310000212001301d225335001101722133500222223300900b003300400123222300330073335009008002001301d225335001101722133501835002223301500233008233350012330094800000488cc0280080048cc0240052000001300400123223002001301c2253350011016221335017350022233014002300700130040012233700004002603244a66a002202644266a0286a0044466022004666a0024601400244666a01401200400246016002600800244666ae68cdc780100080c00b89911119191980e91299a800880191099a80c0011802000980100218029980e11299a800880b11099299a9a80191911801005981111299a80088111109a80111299a99808001003881289803001899a80c00180088009802000801180d91299a800880a91099a80b1a80111191980a0019800804181091299a80089aa8078019109a80111299a998078010040891119801005002098030019802000980b91299a800880891099a8091a801111980780118050009802000980b11299a800880811099a8089a801111980700118048009802000980a91299a800880791099a8081a80111198068011aa803800980200090911180180208909111800802180911299a800880611099a8069a801111a80091110019802000980891299a800880591099a8061a8011100118020009091180100188910009109198008018011a8019110009a8011110011a800911001999180080091091919980111801111180180211801111180100211801111180080211a998020020019a801800891111998021299a800899a803003803910a99a800899a804001804910a99199a998068028018a800899980400199a8058028060010a8008999803001119a805802800800911299a800899a80419a804001801180300499110a999a998068030010a801899980400119a8058030028008a801899a80419a804001801180300091129919a80109800a4c442a64666a6601c00e0062a00226008930a80089998038011180319a806003800800919a804980199a80480200518038010910010910911980080200199111a801111a801111a802911a801112999a998058030010a99a999ab9a3370e00a00202001e201c2a66a666ae68cdc48028008080078806080689980580300109980580300111299a999ab9a3371e00400200e00c200a2a66a666ae68cdc88010008038030801880209110018911001091100089100109100091091980080180111918008009180111980100100081" } diff --git a/hydra-plutus/scripts/vInitial.plutus b/hydra-plutus/scripts/vInitial.plutus index e92599025e1..23e652c2789 100644 --- a/hydra-plutus/scripts/vInitial.plutus +++ b/hydra-plutus/scripts/vInitial.plutus @@ -1,5 +1,5 @@ { "type": "PlutusScriptV3", - "description": "hydra-vInitial-0.19.0-284-g2f3d76240", + "description": "hydra-vInitial-0.19.0-524-g017dc82b8", "cborHex": "590a68590a6501010033232323232323232323223225333005323232323253323300b3001300d37540042646464a66666602c00c26464646464a66602660080022a66602e602c6ea802c5400804854ccc04cc0240044c94ccc06000404c4c94cccccc0740040500504c94ccc068c07400c4cc020004894ccc0700085401c4c94cccccc0840044ccc0240044c008c08000c060060060060060c078008054dd600080a00a180d000980b1baa00b012301437540142a666022600460266ea80104c8c8c8c8c8c8c94ccc060c024c068dd5008099802248103493031003370e6660026eacc018c06cdd5009003a4410b487964726148656164563100480044cc8c8c8c8c8c8c8c8c8c8c8c8c8c8c88c8c8c8c8c94cccccc0d40040080084c8cc080004894ccc0d00084c8c94ccc0c8cc07924103493133003371e0426eb8c058c0d4dd50040a999819191919299981a981300089811249034930350015333035302b001132533303a0011302349103493036001533303a303d001133022491034930320032323300100100622533303d00114a0264a66607466e3cdd718200010020a511330030030013040001375c60780022604692010349303600323300100100322533303b00114bd700991919299981d18181bad303d00313303f37520026600a00a00426600a00a0046eb8c0ec008c0fc008c0f40044c08924010349303600301a001330183301d0020224bd6f7b6301bac303830393039303930393039303930393039303537540582a6660646603c92103493134003375e6040606a6ea80b1300101a000153330323301e49103493033003371266e00c048004c048ccc050cc04c00894ccc0ccc090c0d4dd500089bab3010303637546020606c6ea8c0e4c0d8dd50008a5eb7bdb1812f5bded8c002a60246660286602601446eacc040c0d8dd5000a5eb7bdb1800544cc0300080145280a5014a02940cc058c94ccc0c8c0a0c0d0dd50008a60103d87a80001301d33037300f30353754601e606a6ea8c0e0c0d4dd5000a5eb80cc034dd6180c981a1baa02b0254bd6f7b6301980780491929998191811981a1baa0011301d3303730383035375400297ae013010490103493135003300d3758603260686ea80ac0044c94cccccc0e400454ccc0c4c088c0ccdd5000899299981b000803899299999981d800899299981c000804899299999981e800805005005005099299981d181e801899981300209803981e8040058059bae001303a001303a00200800800800830380013034375400200c00c00c00c00c606c0046eb0004008008c024c0bcdd50010980c2491f4661696c656420746f206465636f6465206c6f636b65645f636f6d6d69747300533302e0011300849103493132001533302e303100113232533302c301d0011300a49103493039001533302c30220011300a490103493130001323253333330360021533302e301f30303754004264a66606600200426464a66606a00200826464a66606e00200c264a66666607800200e00e00e00e264a666072607800620120106eb8004c0e4004c0e4008c0dc004c0dc008c0d4004c0c4dd500100080080080080089805a4903493131003032302f3754004605a6ea8004c0c00044c02124010349313200330080012300e302d375400264660020026eb0c034c0b0dd50119129998170008a5eb804c8c94ccc0b0c94ccc0b4c08cc0bcdd5000899b8f02a375c606660606ea8004528180a18179baa3014302f37540042660620046600800800226600800800260640046060002600200244464646464a6660600042a666060006294400400454ccc0bc0044c06124103493037001533302f0021301849010349303800132323232533302f30203031375400826466038921034930340053330303371e6eccc034c0ccdd50009bae300d303337540062a66606066ebcc060c0ccdd5000980c18199baa003133300b00b00400214a02940c0d4c0c8dd50020a503035005303300430330023031001375860600046eb0c0bcc0c0004cc0b4dd3801198169ba70014bd701119198008008019129998160008a6103d87a800013232533302a3375e6024605a6ea80080144c054cc0bc0092f5c02660080080026060004605c0024605460560024a660480022c44646600200200644a666052002297ae013302a3003302b00133002002302c001233300a00148810048810022323300100100322533302700114bd700998141ba63003302900133002002302a00122232333001001004003222533302800210011333003003302b00233004001375660540044464666002002006004444a66604c004200226466600800860540066644646600200200a44a66605600226605866ec0dd48021ba60034bd6f7b630099191919299981599b90008002133030337606ea4020dd30038028a99981599b8f008002132533302c301d302e375400226606266ec0dd4804981918179baa001004100432533302c533303000114a22940530103d87a80001301733031374c00297ae03233300100100800222253330320021001132333004004303600333223233001001005225333037001133038337606ea4010dd4001a5eb7bdb1804c8c8c8c94ccc0dccdc800400109981e19bb037520106ea001c01454ccc0dccdc7804001099299981c1814981d1baa00113303d337606ea4024c0f8c0ecdd5000802080219299981c18148008a60103d87a8000130233303d375000297ae03370000e00226607866ec0dd48011ba800133006006003375a60720066eb8c0dc008c0ec008c0e4004dd718188009bad30320013034002133030337606ea4008dd3000998030030019bab302d003375c6056004605e004605a0026eb8c094004dd598130009814001118119812181200091299980e9809980f9baa002100113756604660406ea8008c004004894ccc07c0045200013370090011980100118110009180f8009bac301e301b375402044464a6660366022603a6ea8004520001375a6042603c6ea8004c94ccc06cc044c074dd50008a6103d87a80001323300100137566044603e6ea8008894ccc084004530103d87a80001323232325333021337220100042a66604266e3c0200084c030cc098dd4000a5eb80530103d87a8000133006006003375a60460066eb8c084008c094008c08c004cc01000c00888c8cc00400400c894ccc078004530103d87a8000132323232533301e3372200e0042a66603c66e3c01c0084c024cc08cdd3000a5eb80530103d87a8000133006006003375660400066eb8c078008c088008c080004dd2a400044a66602c00229444c00c00894cc054004588c064c068c068c068c068004dd7180b980a1baa0041533012491054c36323b3500162225333013300430153754006264a666030002004264a66666603a00200600600600626464a66603600200a264a66666604000200c00c00c264a66603a60400062a01000e6eb4004018c074004c07400cdd7000980d000980b1baa003001370e9000111919800800801911980180098010010068068068069809980a001180900098071baa002370e90010b1807980800118070009807001180600098041baa00114984d958dd70008a998012481054c35383b3500165734ae7155ceaab9e5573eae815d0aba257489811e581c3e5a776bcee213e3dfd15806952a10ac5590e3e97d09d62eb99266b20001" } diff --git a/hydra-plutus/src/Hydra/Contract.hs b/hydra-plutus/src/Hydra/Contract.hs index b496d7e1401..85333b23fcd 100644 --- a/hydra-plutus/src/Hydra/Contract.hs +++ b/hydra-plutus/src/Hydra/Contract.hs @@ -14,10 +14,9 @@ import Hydra.Cardano.Api ( pattern PlutusScript, ) import Hydra.Cardano.Api.Prelude qualified as Api -import Hydra.Contract.Deposit qualified as Deposit import Hydra.Contract.Head qualified as Head import Hydra.Contract.HeadTokens qualified as HeadTokens -import Hydra.Plutus (commitValidatorScript, initialValidatorScript) +import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) import PlutusLedgerApi.V3 (TxId (..), TxOutRef (..), toBuiltin) -- | Information about relevant Hydra scripts. @@ -51,8 +50,8 @@ scriptInfo = , commitScriptSize = scriptSize commitValidatorScript , headScriptHash = plutusScriptHash Head.validatorScript , headScriptSize = scriptSize Head.validatorScript - , depositScriptHash = plutusScriptHash Deposit.validatorScript - , depositScriptSize = scriptSize Deposit.validatorScript + , depositScriptHash = hashScript $ Api.PlutusScript PlutusScriptV3 $ fromPlutusScript depositValidatorScript + , depositScriptSize = scriptSize depositValidatorScript } where plutusScriptHash = diff --git a/hydra-plutus/src/Hydra/Contract/Deposit.hs b/hydra-plutus/src/Hydra/Contract/Deposit.hs index 6c9ad764f2b..11f02cc86f4 100644 --- a/hydra-plutus/src/Hydra/Contract/Deposit.hs +++ b/hydra-plutus/src/Hydra/Contract/Deposit.hs @@ -11,39 +11,15 @@ module Hydra.Contract.Deposit where import PlutusTx.Prelude -import Hydra.Cardano.Api (PlutusScriptVersion (PlutusScriptV3)) import Hydra.Contract.Commit (Commit) -import Hydra.Contract.DepositError ( - DepositError ( - DepositDeadlineNotReached, - DepositDeadlineSurpassed, - DepositNoLowerBoundDefined, - DepositNoUpperBoundDefined, - IncorrectDepositHash, - WrongHeadIdInDepositDatum - ), - ) -import Hydra.Contract.Error (errorCode) -import Hydra.Contract.Head (hashPreSerializedCommits, hashTxOuts) -import Hydra.Plutus.Extras (ValidatorType, scriptValidatorHash, wrapValidator) import PlutusLedgerApi.V3 ( CurrencySymbol, Datum (Datum), - Extended (Finite), - Interval (ivFrom), - LowerBound (LowerBound), POSIXTime, Redeemer (Redeemer), - ScriptContext (..), - ScriptHash, - SerialisedScript, - UpperBound (..), - ivTo, - serialiseCompiledCode, - txInfoOutputs, - txInfoValidRange, ) -import PlutusTx (CompiledCode, toBuiltinData) +import PlutusLedgerApi.V3 qualified as PlutusV3 +import PlutusTx (toBuiltinData) import PlutusTx qualified data DepositRedeemer @@ -56,70 +32,9 @@ data DepositRedeemer PlutusTx.unstableMakeIsData ''DepositRedeemer -- | Deposit datum containing HeadId, deadline and a list of deposits. -newtype DepositDatum - = DepositDatum (CurrencySymbol, POSIXTime, [Commit]) - -PlutusTx.unstableMakeIsData ''DepositDatum - --- | v_deposit validator checks --- --- * Claim redeemer -> --- * The deadline has not been reached. --- * HeadId matches. --- --- * Recover redeemer --- * The deadline has been reached. --- * The hash of recovered outputs are matching the deposited outputs. -validator :: DepositDatum -> DepositRedeemer -> ScriptContext -> Bool -validator depositDatum r ctx = - case r of - Claim headId' -> beforeDeadline && checkHeadId headId' - Recover m -> - afterDeadline - && recoverOutputs m - where - DepositDatum (headId, dl, deposits) = depositDatum - - checkHeadId headId' = - traceIfFalse $(errorCode WrongHeadIdInDepositDatum) $ - headId' == headId - - recoverOutputs m = - traceIfFalse $(errorCode IncorrectDepositHash) $ - hashOfOutputs m == hashPreSerializedCommits deposits - - hashOfOutputs m = - hashTxOuts $ take m (txInfoOutputs txInfo) - - beforeDeadline = - case ivTo (txInfoValidRange txInfo) of - UpperBound (Finite t) _ -> - traceIfFalse $(errorCode DepositDeadlineSurpassed) $ - t <= dl - _ -> traceError $(errorCode DepositNoUpperBoundDefined) - - 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 PlutusScriptV3 validatorScript +type DepositDatum = (CurrencySymbol, POSIXTime, [Commit]) -datum :: DepositDatum -> Datum +datum :: DepositDatum -> PlutusV3.Datum datum a = Datum (toBuiltinData a) redeemer :: DepositRedeemer -> Redeemer diff --git a/hydra-plutus/src/Hydra/Contract/Head.hs b/hydra-plutus/src/Hydra/Contract/Head.hs index 0c9b2dc6072..a22a275013b 100644 --- a/hydra-plutus/src/Hydra/Contract/Head.hs +++ b/hydra-plutus/src/Hydra/Contract/Head.hs @@ -3,6 +3,7 @@ {-# OPTIONS_GHC -fno-specialize #-} {-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:conservative-optimisation #-} {-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:optimize #-} -- 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 #-} @@ -14,9 +15,23 @@ import PlutusTx.Prelude import Hydra.Cardano.Api (PlutusScriptVersion (PlutusScriptV3)) import Hydra.Contract.Commit (Commit (..)) import Hydra.Contract.Commit qualified as Commit +import Hydra.Contract.Deposit qualified as Deposit import Hydra.Contract.HeadError (HeadError (..), errorCode) -import Hydra.Contract.HeadState (CloseRedeemer (..), ClosedDatum (..), ContestRedeemer (..), DecrementRedeemer (..), Hash, IncrementRedeemer, Input (..), OpenDatum (..), Signature, SnapshotNumber, SnapshotVersion, State (..)) -import Hydra.Contract.Util (hasST, mustBurnAllHeadTokens, mustNotMintOrBurn, (===)) +import Hydra.Contract.HeadState ( + CloseRedeemer (..), + ClosedDatum (..), + ContestRedeemer (..), + DecrementRedeemer (..), + Hash, + IncrementRedeemer (..), + Input (..), + OpenDatum (..), + Signature, + SnapshotNumber, + SnapshotVersion, + State (..), + ) +import Hydra.Contract.Util (hasST, hashPreSerializedCommits, hashTxOuts, mustBurnAllHeadTokens, mustNotMintOrBurn, (===)) import Hydra.Data.ContestationPeriod (ContestationPeriod, addContestationPeriod, milliseconds) import Hydra.Data.Party (Party (vkey)) import Hydra.Plutus.Extras (ValidatorType, scriptValidatorHash, wrapValidator) @@ -41,11 +56,10 @@ import PlutusLedgerApi.V3 ( TxInInfo (..), TxInfo (..), TxOut (..), - TxOutRef (..), UpperBound (..), Value (Value), ) -import PlutusLedgerApi.V3.Contexts (findOwnInput) +import PlutusLedgerApi.V3.Contexts (findOwnInput, findTxInByTxOutRef) import PlutusTx (CompiledCode) import PlutusTx qualified import PlutusTx.AssocMap qualified as AssocMap @@ -78,8 +92,8 @@ headValidator oldState input ctx = checkClose ctx openDatum redeemer (Closed closedDatum, Contest redeemer) -> checkContest ctx closedDatum redeemer - (Closed closedDatum, Fanout{numberOfFanoutOutputs, numberOfDecommitOutputs}) -> - checkFanout ctx closedDatum numberOfFanoutOutputs numberOfDecommitOutputs + (Closed closedDatum, Fanout{numberOfFanoutOutputs, numberOfCommitOutputs, numberOfDecommitOutputs}) -> + checkFanout ctx closedDatum numberOfFanoutOutputs numberOfCommitOutputs numberOfDecommitOutputs _ -> traceError $(errorCode InvalidHeadStateTransition) @@ -221,16 +235,85 @@ commitDatum input = do Nothing -> [] {-# INLINEABLE commitDatum #-} +-- | Try to find the deposit datum in the input and +-- if it is there return the committed utxo +depositDatum :: TxOut -> [Commit] +depositDatum input = do + let datum = getTxOutDatum input + case fromBuiltinData @Deposit.DepositDatum $ getDatum datum of + Just (_headId, _deadline, commits) -> + commits + Nothing -> [] +{-# INLINEABLE depositDatum #-} + -- | Verify a increment transaction. checkIncrement :: ScriptContext -> - -- | Open state before the decrement + -- | Open state before the increment OpenDatum -> IncrementRedeemer -> Bool -checkIncrement _ctx _openBefore _redeemer = - -- FIXME: Implement checkIncrement - True +checkIncrement ctx@ScriptContext{scriptContextTxInfo = txInfo} openBefore redeemer = + -- FIXME: spec is mentioning the n also needs to be unchanged - what is n here? utxo hash? + -- "parameters cid, 𝑘̃ H , 𝑛, 𝑇 stay unchanged" + mustNotChangeParameters (prevParties, nextParties) (prevCperiod, nextCperiod) (prevHeadId, nextHeadId) + && mustIncreaseVersion + && mustIncreaseValue + && mustBeSignedByParticipant ctx prevHeadId + && checkSnapshotSignature + && claimedDepositIsSpent + where + inputs = txInfoInputs txInfo + + depositInput = + case findTxInByTxOutRef increment txInfo of + Nothing -> traceError $(errorCode DepositInputNotFound) + Just i -> i + + commits = depositDatum $ txInInfoResolved depositInput + + depositHash = hashPreSerializedCommits commits + + depositValue = txOutValue $ txInInfoResolved depositInput + + headInValue = + case find (hasST prevHeadId) $ txOutValue . txInInfoResolved <$> inputs of + Nothing -> traceError $(errorCode HeadInputNotFound) + Just i -> i + + headOutValue = txOutValue $ head $ txInfoOutputs txInfo + + IncrementRedeemer{signature, snapshotNumber, increment} = redeemer + + claimedDepositIsSpent = + traceIfFalse $(errorCode DepositNotSpent) $ + increment `elem` (txInInfoOutRef <$> txInfoInputs txInfo) + + checkSnapshotSignature = + verifySnapshotSignature nextParties (nextHeadId, prevVersion, snapshotNumber, nextUtxoHash, depositHash, emptyHash) signature + + mustIncreaseVersion = + traceIfFalse $(errorCode VersionNotIncremented) $ + nextVersion == prevVersion + 1 + + mustIncreaseValue = + traceIfFalse $(errorCode HeadValueIsNotPreserved) $ + headInValue <> depositValue === headOutValue + + OpenDatum + { parties = prevParties + , contestationPeriod = prevCperiod + , headId = prevHeadId + , version = prevVersion + } = openBefore + + OpenDatum + { utxoHash = nextUtxoHash + , parties = nextParties + , contestationPeriod = nextCperiod + , headId = nextHeadId + , version = nextVersion + } = decodeHeadOutputOpenDatum ctx {-# INLINEABLE checkIncrement #-} -- | Verify a decrement transaction. @@ -332,7 +415,8 @@ checkClose ctx openBefore redeemer = ClosedDatum { snapshotNumber = snapshotNumber' , utxoHash = utxoHash' - , deltaUTxOHash = deltaUTxOHash' + , alphaUTxOHash = alphaUTxOHash' + , omegaUTxOHash = omegaUTxOHash' , parties = parties' , contestationDeadline = deadline , contestationPeriod = cperiod' @@ -352,19 +436,48 @@ checkClose ctx openBefore redeemer = version == 0 && snapshotNumber' == 0 && utxoHash' == initialUtxoHash - CloseUnused{signature} -> - traceIfFalse $(errorCode FailedCloseCurrent) $ - verifySnapshotSignature - parties - (headId, version, snapshotNumber', utxoHash', emptyHash, deltaUTxOHash') - signature - CloseUsed{signature, alreadyDecommittedUTxOHash} -> - traceIfFalse $(errorCode FailedCloseOutdated) $ - deltaUTxOHash' == emptyHash + -- FIXME: reflect the new CloseAny redeemer in the spec as well + CloseAny{signature} -> + traceIfFalse $(errorCode FailedCloseAny) $ + snapshotNumber' > 0 + && alphaUTxOHash' == emptyHash + && omegaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version, snapshotNumber', utxoHash', emptyHash, emptyHash) + signature + CloseUnusedDec{signature} -> + traceIfFalse $(errorCode FailedCloseUnusedDec) $ + alphaUTxOHash' == emptyHash + && omegaUTxOHash' /= emptyHash + && verifySnapshotSignature + parties + (headId, version, snapshotNumber', utxoHash', emptyHash, omegaUTxOHash') + signature + CloseUsedDec{signature, alreadyDecommittedUTxOHash} -> + traceIfFalse $(errorCode FailedCloseUsedDec) $ + alphaUTxOHash' == emptyHash + && omegaUTxOHash' == emptyHash && verifySnapshotSignature parties (headId, version - 1, snapshotNumber', utxoHash', emptyHash, alreadyDecommittedUTxOHash) signature + CloseUnusedInc{signature, alreadyCommittedUTxOHash} -> + traceIfFalse $(errorCode FailedCloseUnusedInc) $ + alphaUTxOHash' == emptyHash + && omegaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version, snapshotNumber', utxoHash', alreadyCommittedUTxOHash, emptyHash) + signature + CloseUsedInc{signature, alreadyCommittedUTxOHash} -> + traceIfFalse $(errorCode FailedCloseUsedInc) $ + alphaUTxOHash' == alreadyCommittedUTxOHash + && omegaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version - 1, snapshotNumber', utxoHash', alreadyCommittedUTxOHash, emptyHash) + signature checkDeadline = traceIfFalse $(errorCode IncorrectClosedContestationDeadline) $ @@ -428,17 +541,41 @@ checkContest ctx closedDatum redeemer = case redeemer of ContestCurrent{signature} -> traceIfFalse $(errorCode FailedContestCurrent) $ - verifySnapshotSignature - parties - (headId, version, snapshotNumber', utxoHash', emptyHash, deltaUTxOHash') - signature - ContestOutdated{signature, alreadyDecommittedUTxOHash} -> - traceIfFalse $(errorCode FailedContestOutdated) $ - deltaUTxOHash' == emptyHash + alphaUTxOHash' == emptyHash + && omegaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version, snapshotNumber', utxoHash', emptyHash, emptyHash) + signature + ContestUsedDec{signature, alreadyDecommittedUTxOHash} -> + traceIfFalse $(errorCode FailedContestUsedDec) $ + alphaUTxOHash' == emptyHash + && omegaUTxOHash' == emptyHash && verifySnapshotSignature parties (headId, version - 1, snapshotNumber', utxoHash', emptyHash, alreadyDecommittedUTxOHash) signature + ContestUnusedDec{signature} -> + traceIfFalse $(errorCode FailedContestUnusedDec) $ + alphaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version, snapshotNumber', utxoHash', emptyHash, omegaUTxOHash') + signature + ContestUnusedInc{signature, alreadyCommittedUTxOHash} -> + traceIfFalse $(errorCode FailedContestUnusedInc) $ + omegaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version - 1, snapshotNumber', utxoHash', alreadyCommittedUTxOHash, emptyHash) + signature + ContestUsedInc{signature} -> + traceIfFalse $(errorCode FailedContestUsedInc) $ + omegaUTxOHash' == emptyHash + && verifySnapshotSignature + parties + (headId, version, snapshotNumber', utxoHash', alphaUTxOHash', emptyHash) + signature mustBeWithinContestationPeriod = case ivTo (txInfoValidRange txInfo) of @@ -473,7 +610,8 @@ checkContest ctx closedDatum redeemer = ClosedDatum { snapshotNumber = snapshotNumber' , utxoHash = utxoHash' - , deltaUTxOHash = deltaUTxOHash' + , alphaUTxOHash = alphaUTxOHash' + , omegaUTxOHash = omegaUTxOHash' , parties = parties' , contestationDeadline = contestationDeadline' , contestationPeriod = contestationPeriod' @@ -501,13 +639,16 @@ checkFanout :: ClosedDatum -> -- | Number of normal outputs to fanout Integer -> + -- | Number of alpha outputs to fanout + Integer -> -- | Number of delta outputs to fanout Integer -> Bool -checkFanout ScriptContext{scriptContextTxInfo = txInfo} closedDatum numberOfFanoutOutputs numberOfDecommitOutputs = +checkFanout ScriptContext{scriptContextTxInfo = txInfo} closedDatum numberOfFanoutOutputs numberOfCommitOutputs numberOfDecommitOutputs = mustBurnAllHeadTokens minted headId parties && hasSameUTxOHash - && hasSameUTxOToDecommitHash + && hasSameCommitUTxOHash + && hasSameDecommitUTxOHash && afterContestationDeadline where minted = txInfoMint txInfo @@ -516,15 +657,21 @@ checkFanout ScriptContext{scriptContextTxInfo = txInfo} closedDatum numberOfFano traceIfFalse $(errorCode FanoutUTxOHashMismatch) $ fannedOutUtxoHash == utxoHash - hasSameUTxOToDecommitHash = + hasSameCommitUTxOHash = + traceIfFalse $(errorCode FanoutUTxOToCommitHashMismatch) $ + alphaUTxOHash == commitUtxoHash + + hasSameDecommitUTxOHash = traceIfFalse $(errorCode FanoutUTxOToDecommitHashMismatch) $ - deltaUTxOHash == decommitUtxoHash + omegaUTxOHash == decommitUtxoHash fannedOutUtxoHash = hashTxOuts $ take numberOfFanoutOutputs txInfoOutputs + commitUtxoHash = hashTxOuts $ take numberOfCommitOutputs $ drop numberOfFanoutOutputs txInfoOutputs + decommitUtxoHash = hashTxOuts $ take numberOfDecommitOutputs $ drop numberOfFanoutOutputs txInfoOutputs - ClosedDatum{utxoHash, deltaUTxOHash, parties, headId, contestationDeadline} = closedDatum + ClosedDatum{utxoHash, alphaUTxOHash, omegaUTxOHash, parties, headId, contestationDeadline} = closedDatum TxInfo{txInfoOutputs} = txInfo @@ -547,6 +694,7 @@ makeContestationDeadline cperiod ScriptContext{scriptContextTxInfo} = _ -> traceError $(errorCode CloseNoUpperBoundDefined) {-# INLINEABLE makeContestationDeadline #-} +-- | This is safe only because usually Head transaction only consume one input. getHeadInput :: ScriptContext -> TxInInfo getHeadInput ctx = case findOwnInput ctx of Nothing -> traceError $(errorCode ScriptNotSpendingAHeadInput) @@ -620,31 +768,6 @@ getTxOutDatum o = OutputDatum d -> d {-# INLINEABLE getTxOutDatum #-} --- | Hash a potentially unordered list of commits by sorting them, concatenating --- their 'preSerializedOutput' bytes and creating a SHA2_256 digest over that. --- --- NOTE: See note from `hashTxOuts`. -hashPreSerializedCommits :: [Commit] -> BuiltinByteString -hashPreSerializedCommits commits = - sha2_256 . foldMap preSerializedOutput $ - sortBy (\a b -> compareRef (input a) (input b)) commits -{-# INLINEABLE hashPreSerializedCommits #-} - --- | Hash a pre-ordered list of transaction outputs by serializing each --- individual 'TxOut', concatenating all bytes together and creating a SHA2_256 --- digest over that. --- --- NOTE: In general, from asserting that `hash(x || y) = hash (x' || y')` it is --- not safe to conclude that `(x,y) = (x', y')` as the same hash could be --- obtained by moving one or more bytes from the end of `x` to the beginning of --- `y`, but in the context of Hydra validators it seems impossible to exploit --- this property without breaking other logic or verification (eg. producing a --- valid and meaningful `TxOut`). -hashTxOuts :: [TxOut] -> BuiltinByteString -hashTxOuts = - sha2_256 . foldMap (Builtins.serialiseData . toBuiltinData) -{-# INLINEABLE hashTxOuts #-} - -- | Check if 'TxOut' contains the PT token. hasPT :: CurrencySymbol -> TxOut -> Bool hasPT headCurrencySymbol txOut = @@ -677,13 +800,6 @@ verifyPartySignature (headId, snapshotVersion, snapshotNumber, utxoHash, utxoToC <> Builtins.serialiseData (toBuiltinData utxoToDecommitHash) {-# INLINEABLE verifyPartySignature #-} -compareRef :: TxOutRef -> TxOutRef -> Ordering -TxOutRef{txOutRefId, txOutRefIdx} `compareRef` TxOutRef{txOutRefId = id', txOutRefIdx = idx'} = - case compare txOutRefId id' of - EQ -> compare txOutRefIdx idx' - ord -> ord -{-# INLINEABLE compareRef #-} - compiledValidator :: CompiledCode ValidatorType compiledValidator = $$(PlutusTx.compile [||wrap headValidator||]) diff --git a/hydra-plutus/src/Hydra/Contract/HeadError.hs b/hydra-plutus/src/Hydra/Contract/HeadError.hs index d86a6580d02..a1e83129353 100644 --- a/hydra-plutus/src/Hydra/Contract/HeadError.hs +++ b/hydra-plutus/src/Hydra/Contract/HeadError.hs @@ -34,8 +34,7 @@ data HeadError | ContestersNonEmpty | CloseNoUpperBoundDefined | FailedCloseInitial - | FailedCloseCurrent - | FailedCloseOutdated + | FailedCloseAny | TooOldSnapshot | UpperBoundBeyondContestationDeadline | ContestNoUpperBoundDefined @@ -45,11 +44,22 @@ data HeadError | WrongNumberOfSigners | SignerAlreadyContested | FailedContestCurrent - | FailedContestOutdated + | FailedContestUsedDec | FanoutUTxOHashMismatch | LowerBoundBeforeContestationDeadline | FanoutNoLowerBoundDefined + | FanoutUTxOToCommitHashMismatch | FanoutUTxOToDecommitHashMismatch + | DepositNotSpent + | DepositInputNotFound + | HeadInputNotFound + | FailedContestUnusedDec + | FailedContestUnusedInc + | FailedContestUsedInc + | FailedCloseUnusedDec + | FailedCloseUsedDec + | FailedCloseUnusedInc + | FailedCloseUsedInc instance ToErrorCode HeadError where toErrorCode = \case @@ -86,21 +96,31 @@ instance ToErrorCode HeadError where ContestersNonEmpty -> "H26" CloseNoUpperBoundDefined -> "H27" FailedCloseInitial -> "H28" - FailedCloseCurrent -> "H29" - FailedCloseOutdated -> "H30" -- Contest - TooOldSnapshot -> "H31" - UpperBoundBeyondContestationDeadline -> "H32" - ContestNoUpperBoundDefined -> "H33" - MustNotPushDeadline -> "H34" - MustPushDeadline -> "H35" - ContesterNotIncluded -> "H36" - WrongNumberOfSigners -> "H37" - SignerAlreadyContested -> "H38" - FailedContestCurrent -> "H39" - FailedContestOutdated -> "H40" + TooOldSnapshot -> "H29" + UpperBoundBeyondContestationDeadline -> "H30" + ContestNoUpperBoundDefined -> "H31" + MustNotPushDeadline -> "H32" + MustPushDeadline -> "H33" + ContesterNotIncluded -> "H34" + WrongNumberOfSigners -> "H35" + SignerAlreadyContested -> "H36" + FailedContestCurrent -> "H37" + FailedContestUsedDec -> "H38" -- Fanout - FanoutUTxOHashMismatch -> "H41" - FanoutUTxOToDecommitHashMismatch -> "H42" - LowerBoundBeforeContestationDeadline -> "H43" - FanoutNoLowerBoundDefined -> "H44" + FanoutUTxOHashMismatch -> "H39" + FanoutUTxOToDecommitHashMismatch -> "H40" + LowerBoundBeforeContestationDeadline -> "H41" + FanoutNoLowerBoundDefined -> "H42" + DepositNotSpent -> "H43" + DepositInputNotFound -> "H44" + HeadInputNotFound -> "H45" + FailedCloseAny -> "H46" + FailedContestUnusedDec -> "H47" + FailedContestUnusedInc -> "H48" + FailedContestUsedInc -> "H49" + FailedCloseUnusedDec -> "H50" + FailedCloseUsedDec -> "H51" + FailedCloseUnusedInc -> "H52" + FailedCloseUsedInc -> "H53" + FanoutUTxOToCommitHashMismatch -> "H54" diff --git a/hydra-plutus/src/Hydra/Contract/HeadState.hs b/hydra-plutus/src/Hydra/Contract/HeadState.hs index f2a4a147652..ab15f3fcc87 100644 --- a/hydra-plutus/src/Hydra/Contract/HeadState.hs +++ b/hydra-plutus/src/Hydra/Contract/HeadState.hs @@ -52,7 +52,9 @@ data ClosedDatum = ClosedDatum -- ^ Spec: s , utxoHash :: Hash -- ^ Spec: η. Digest of snapshotted UTxO - , deltaUTxOHash :: Hash + -- | TODO: add alphaUTxOHash to the spec + , alphaUTxOHash :: Hash + , omegaUTxOHash :: Hash -- ^ Spec: ηΔ. Digest of UTxO still to be distributed , contesters :: [PubKeyHash] -- ^ Spec: C @@ -81,18 +83,35 @@ PlutusTx.unstableMakeIsData ''State data CloseRedeemer = -- | Intial snapshot is used to close. CloseInitial + | -- | Any snapshot which doesn't contain anything to inc/decrement but snapshot number is higher than zero. + CloseAny + {signature :: [Signature]} | -- | Closing snapshot refers to the current state version - CloseUnused + CloseUnusedDec { signature :: [Signature] -- ^ Multi-signature of a snapshot ξ } | -- | Closing snapshot refers to the previous state version - CloseUsed + CloseUsedDec { signature :: [Signature] -- ^ Multi-signature of a snapshot ξ , alreadyDecommittedUTxOHash :: Hash -- ^ UTxO which was already decommitted ηω } + | -- | Closing snapshot refers to the current state version + CloseUnusedInc + { signature :: [Signature] + -- ^ Multi-signature of a snapshot ξ + , alreadyCommittedUTxOHash :: Hash + -- ^ UTxO which was signed but not committed ηα + } + | -- | Closing snapshot refers to the previous state version + CloseUsedInc + { signature :: [Signature] + -- ^ Multi-signature of a snapshot ξ + , alreadyCommittedUTxOHash :: Hash + -- ^ UTxO which was already committed ηα + } deriving stock (Show, Generic) PlutusTx.unstableMakeIsData ''CloseRedeemer @@ -105,19 +124,38 @@ data ContestRedeemer -- ^ Multi-signature of a snapshot ξ } | -- | Contesting snapshot refers to the previous state version - ContestOutdated + ContestUsedDec { signature :: [Signature] -- ^ Multi-signature of a snapshot ξ , alreadyDecommittedUTxOHash :: Hash -- ^ UTxO which was already decommitted ηω } + | -- | Redeemer to use when the decommit was not yet observed but we closed the Head. + ContestUnusedDec + { signature :: [Signature] + -- ^ Multi-signature of a snapshot ξ + } + | -- | Redeemer to use when the commit was not yet observed but we closed the Head. + ContestUnusedInc + { signature :: [Signature] + -- ^ Multi-signature of a snapshot ξ + , alreadyCommittedUTxOHash :: Hash + -- ^ UTxO which was already committed ηα + } + | ContestUsedInc + { signature :: [Signature] + -- ^ Multi-signature of a snapshot ξ + } deriving stock (Show, Generic) PlutusTx.unstableMakeIsData ''ContestRedeemer -- | Sub-type for increment transition --- TODO: add more fields as needed. data IncrementRedeemer = IncrementRedeemer + { signature :: [Signature] + , snapshotNumber :: SnapshotNumber + , increment :: TxOutRef + } deriving stock (Show, Generic) PlutusTx.unstableMakeIsData ''IncrementRedeemer @@ -144,7 +182,8 @@ data Input | Abort | Fanout { numberOfFanoutOutputs :: Integer - -- ^ Spec: m + , -- TODO: add this to the spec + numberOfCommitOutputs :: Integer , numberOfDecommitOutputs :: Integer -- ^ Spec: n } diff --git a/hydra-plutus/src/Hydra/Contract/HeadTokens.hs b/hydra-plutus/src/Hydra/Contract/HeadTokens.hs index c9ba29361c0..ab31cf0c1a3 100644 --- a/hydra-plutus/src/Hydra/Contract/HeadTokens.hs +++ b/hydra-plutus/src/Hydra/Contract/HeadTokens.hs @@ -1,9 +1,11 @@ {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE TemplateHaskell #-} {-# OPTIONS_GHC -fno-specialize #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:conservative-optimisation #-} {-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:defer-errors #-} -- Avoid trace calls to be optimized away when inlining functions. {-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:no-simplifier-inline #-} +{-# OPTIONS_GHC -fplugin-opt PlutusTx.Plugin:optimize #-} -- 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.1.0 #-} diff --git a/hydra-plutus/src/Hydra/Contract/Util.hs b/hydra-plutus/src/Hydra/Contract/Util.hs index 871181539e4..4a4e99183b2 100644 --- a/hydra-plutus/src/Hydra/Contract/Util.hs +++ b/hydra-plutus/src/Hydra/Contract/Util.hs @@ -3,6 +3,7 @@ module Hydra.Contract.Util where +import Hydra.Contract.Commit import Hydra.Contract.Error (ToErrorCode (..)) import Hydra.Contract.HeadError (HeadError (..), errorCode) import Hydra.Data.Party (Party) @@ -24,6 +25,7 @@ import PlutusLedgerApi.V3 ( ) import PlutusTx.AssocMap qualified as AssocMap import PlutusTx.Builtins (serialiseData) +import PlutusTx.Builtins qualified as Builtins import PlutusTx.Prelude hydraHeadV1 :: BuiltinByteString @@ -82,6 +84,38 @@ infix 4 === serialiseData (toBuiltinData val) == serialiseData (toBuiltinData val') {-# INLINEABLE (===) #-} +-- | Hash a potentially unordered list of commits by sorting them, concatenating +-- their 'preSerializedOutput' bytes and creating a SHA2_256 digest over that. +-- +-- NOTE: See note from `hashTxOuts`. +hashPreSerializedCommits :: [Commit] -> BuiltinByteString +hashPreSerializedCommits commits = + sha2_256 . foldMap preSerializedOutput $ + sortBy (\a b -> compareRef (input a) (input b)) commits +{-# INLINEABLE hashPreSerializedCommits #-} + +-- | Hash a pre-ordered list of transaction outputs by serializing each +-- individual 'TxOut', concatenating all bytes together and creating a SHA2_256 +-- digest over that. +-- +-- NOTE: In general, from asserting that `hash(x || y) = hash (x' || y')` it is +-- not safe to conclude that `(x,y) = (x', y')` as the same hash could be +-- obtained by moving one or more bytes from the end of `x` to the beginning of +-- `y`, but in the context of Hydra validators it seems impossible to exploit +-- this property without breaking other logic or verification (eg. producing a +-- valid and meaningful `TxOut`). +hashTxOuts :: [TxOut] -> BuiltinByteString +hashTxOuts = + sha2_256 . foldMap (Builtins.serialiseData . toBuiltinData) +{-# INLINEABLE hashTxOuts #-} + +compareRef :: TxOutRef -> TxOutRef -> Ordering +TxOutRef{txOutRefId, txOutRefIdx} `compareRef` TxOutRef{txOutRefId = id', txOutRefIdx = idx'} = + case compare txOutRefId id' of + EQ -> compare txOutRefIdx idx' + ord -> ord +{-# INLINEABLE compareRef #-} + -- * Errors data UtilError diff --git a/hydra-plutus/src/Hydra/Plutus.hs b/hydra-plutus/src/Hydra/Plutus.hs index 5cb33b37028..956384a4fcc 100644 --- a/hydra-plutus/src/Hydra/Plutus.hs +++ b/hydra-plutus/src/Hydra/Plutus.hs @@ -22,11 +22,11 @@ blueprintJSON = -- | Access the commit validator script from the 'blueprintJSON'. commitValidatorScript :: SerialisedScript commitValidatorScript = - case Base16.decode base16Bytes of + case Base16.decode commitBase16Bytes of Left e -> error $ "Failed to decode commit validator: " <> show e Right bytes -> toShort bytes where - base16Bytes = encodeUtf8 base16Text + commitBase16Bytes = encodeUtf8 base16Text -- NOTE: we are using a hardcoded index to access the commit validator. -- This is fragile and will raise problems when we move another plutus validator -- to Aiken. @@ -40,10 +40,14 @@ initialValidatorScript = Left e -> error $ "Failed to decode initial validator: " <> show e Right bytes -> toShort bytes where - base16Bytes = encodeUtf8 base16Text + base16Bytes = encodeUtf8 initialBase16Text + initialBase16Text = blueprintJSON ^. key "validators" . nth 4 . key "compiledCode" . _String - -- NOTE: we are using a hardcoded index to access the commit validator. - -- This is fragile and will raise problems when we move another plutus validator - -- to Aiken. - -- Reference: https://github.com/cardano-foundation/CIPs/tree/master/CIP-0057 - base16Text = blueprintJSON ^. key "validators" . nth 2 . key "compiledCode" . _String +depositValidatorScript :: SerialisedScript +depositValidatorScript = + case Base16.decode depositBase16Bytes of + Left e -> error $ "Failed to decode commit validator: " <> show e + Right bytes -> toShort bytes + where + depositBase16Bytes = encodeUtf8 depositBase16Text + depositBase16Text = blueprintJSON ^. key "validators" . nth 2 . key "compiledCode" . _String diff --git a/hydra-plutus/test/Hydra/Plutus/GoldenSpec.hs b/hydra-plutus/test/Hydra/Plutus/GoldenSpec.hs index c636a8afc16..92cf4901671 100644 --- a/hydra-plutus/test/Hydra/Plutus/GoldenSpec.hs +++ b/hydra-plutus/test/Hydra/Plutus/GoldenSpec.hs @@ -23,10 +23,9 @@ import Hydra.Cardano.Api ( writeFileTextEnvelope, pattern PlutusScript, ) -import Hydra.Contract.Deposit qualified as Deposit import Hydra.Contract.Head qualified as Head import Hydra.Contract.HeadTokens qualified as HeadTokens -import Hydra.Plutus (commitValidatorScript, initialValidatorScript) +import Hydra.Plutus (commitValidatorScript, depositValidatorScript, initialValidatorScript) import Hydra.Version (gitDescribe) import PlutusLedgerApi.V3 (serialiseCompiledCode) import PlutusLedgerApi.V3 qualified as Plutus @@ -39,7 +38,7 @@ spec = do it "Head minting policy script" $ goldenScript "mHead" (serialiseCompiledCode HeadTokens.unappliedMintingPolicy) it "Deposit validator script" $ - goldenScript "vDeposit" Deposit.validatorScript + goldenScript "vDeposit" depositValidatorScript it "Initial validator script" $ goldenScript "vInitial" initialValidatorScript it "Commit validator script" $ diff --git a/hydra-plutus/validators/deposit.ak b/hydra-plutus/validators/deposit.ak new file mode 100644 index 00000000000..a1107e965b7 --- /dev/null +++ b/hydra-plutus/validators/deposit.ak @@ -0,0 +1,145 @@ +use aiken/builtin +use aiken/collection/list +use aiken/crypto.{Hash, Sha2_256, sha2_256} +use aiken/interval.{Finite, Interval, IntervalBound} +use aiken/primitive/bytearray +use cardano/assets.{PolicyId} +use cardano/transaction.{Output, OutputReference, Transaction, ValidityRange} +use cardano/transaction/output_reference + +pub type Commit { + Commit { + input: OutputReference, + preSerializedOutput: ByteArray + } +} + +pub type Datum { + head_id: PolicyId, + deadline: Int, + commits: List, +} + +pub type Redeemer { + Claim(PolicyId) + Recover(Int) +} + +type DepositError { + DepositDeadlineSurpassed + DepositNoUpperBoundDefined + DepositNoLowerBoundDefined + DepositDeadlineNotReached + IncorrectDepositHash + WrongHeadIdInDepositDatum +} + +fn toErrorCode(err: DepositError) -> String { + when err is { + DepositDeadlineSurpassed -> @"D01" + DepositNoUpperBoundDefined -> @"D02" + DepositNoLowerBoundDefined -> @"D03" + DepositDeadlineNotReached -> @"D04" + IncorrectDepositHash -> @"D05" + WrongHeadIdInDepositDatum -> @"D06" + } +} + +validator deposit { + spend( + datum: Option, + redeemer: Redeemer, + _utxo: OutputReference, + self: Transaction, + ) { + expect Some(datum) = datum + when redeemer is { + Claim(currencySymbol) -> + traceIfFalse( + toErrorCode(WrongHeadIdInDepositDatum), + check_head_id(datum.head_id, currencySymbol), + ) && + traceIfFalse( + toErrorCode(DepositDeadlineSurpassed), + before_deadline(self.validity_range, datum.deadline), + ) + Recover(n) -> + traceIfFalse( + toErrorCode(DepositDeadlineNotReached), + after_deadline(self.validity_range, datum.deadline), + ) && recover_outputs(n, datum.commits, self.outputs) + } + } + + else(_) { + fail + } +} + + +fn check_head_id(datumCS: ByteArray, redeemerCS: ByteArray) { + datumCS == redeemerCS +} + +fn before_deadline(range: ValidityRange, dl) { + when range.upper_bound.bound_type is { + Finite(tx_upper_validity) -> tx_upper_validity <= dl + _ -> traceIfFalse(toErrorCode(DepositNoUpperBoundDefined), False) + } +} + +fn after_deadline(range: ValidityRange, dl) { + when range.lower_bound.bound_type is { + Finite(tx_lower_validity) -> tx_lower_validity > dl + _ -> traceIfFalse(toErrorCode(DepositNoLowerBoundDefined), False) + } +} + +fn recover_outputs( + n: Int, + commits: List, + outputs: List, +) { + let depositOutputs = outputs |> list.take(n) + let deposited = commits // |> list.map(fn(commit){ commit.input}) + + let hashOfOutputs = hash_tx_outs(depositOutputs) + let preSerializedCommits = hashPreSerializedCommits(deposited) + + traceIfFalse( + toErrorCode(IncorrectDepositHash), + hashOfOutputs == preSerializedCommits, + ) +} + +// Helpers + +// Hash a potentially unordered list of commits +fn hashPreSerializedCommits(commits: List) -> Hash { + commits + |> list.sort( + fn(commit, commit2){ + output_reference.compare(commit.input, commit2.input) + } + ) + |> list.map(fn(commit) { commit.preSerializedOutput }) + |> list.reduce(#"", bytearray.concat) + |> sha2_256 +} + +// Hash a pre-ordered list of transaction outputs +fn hash_tx_outs(outputs: List) -> Hash { + outputs + |> list.map(fn(output) { builtin.serialise_data(output) }) + |> list.reduce(#"", bytearray.concat) + |> sha2_256 +} + +fn traceIfFalse(traceLog: String, predicate: Bool) -> Bool { + if predicate { + True + } else { + trace traceLog + False + } +} diff --git a/hydra-tui/src/Hydra/Client.hs b/hydra-tui/src/Hydra/Client.hs index 66256d4f849..c2594a4f961 100644 --- a/hydra-tui/src/Hydra/Client.hs +++ b/hydra-tui/src/Hydra/Client.hs @@ -12,6 +12,7 @@ import Data.Aeson (eitherDecodeStrict, encode) import Hydra.API.ClientInput (ClientInput) import Hydra.API.HTTPServer (DraftCommitTxRequest (..), DraftCommitTxResponse (..)) import Hydra.API.ServerOutput (TimedServerOutput) +import Hydra.Cardano.Api (TxId) import Hydra.Cardano.Api.Prelude ( AsType (AsPaymentKey, AsSigningKey), PaymentKey, @@ -43,6 +44,7 @@ data Client tx m = Client -- ^ Send some input to the server. , sk :: SigningKey PaymentKey , externalCommit :: UTxO.UTxO -> m () + , recoverCommit :: TxId -> m () } -- | Callback for receiving server outputs. @@ -68,6 +70,7 @@ withClient Options{hydraNodeHost = Host{hostname, port}, cardanoSigningKey, card { sendInput = atomically . writeTBQueue q , sk , externalCommit = externalCommit' sk + , recoverCommit = recoverCommit' } where readExternalSk = readFileTextEnvelopeThrow (AsSigningKey AsPaymentKey) cardanoSigningKey @@ -110,6 +113,15 @@ withClient Options{hydraNodeHost = Host{hostname, port}, cardanoSigningKey, card Req.jsonResponse (Req.port $ fromIntegral port) + recoverCommit' txId = + void . runReq defaultHttpConfig $ + Req.req + Req.DELETE + (Req.http hostname Req./: "commits" Req./: show txId) + Req.NoReqBody + Req.ignoreResponse + (Req.port $ fromIntegral port) + data ClientError = ClientJSONDecodeError String ByteString deriving stock (Eq, Show, Generic) deriving anyclass (Exception) diff --git a/hydra-tui/src/Hydra/TUI/Drawing.hs b/hydra-tui/src/Hydra/TUI/Drawing.hs index 1f60ac213f8..d2f7462f48a 100644 --- a/hydra-tui/src/Hydra/TUI/Drawing.hs +++ b/hydra-tui/src/Hydra/TUI/Drawing.hs @@ -110,7 +110,7 @@ drawCommandList s = vBox . fmap txt $ case s ^. connectedStateL of Idle -> ["[I]nit", "[Q]uit"] Active (ActiveLink{activeHeadState}) -> case activeHeadState of Initializing{} -> ["[C]ommit", "[A]bort", "[Q]uit"] - Open{} -> ["[N]ew Transaction", "[D]ecommit", "[I]ncrement", "[C]lose", "[Q]uit"] + Open{} -> ["[N]ew Transaction", "[D]ecommit", "[I]ncrement", "[R]ecover", "[C]lose", "[Q]uit"] Closed{} -> ["[Q]uit"] FanoutPossible{} -> ["[F]anout", "[Q]uit"] Final{} -> ["[I]nit", "[Q]uit"] @@ -141,26 +141,26 @@ drawRemainingDepositDeadline deadline now = then padLeftRight 1 $ vBox [txt "Remaining time to deposit: ", str (renderTime remaining)] else txt "Deposit deadline passed, ready to recover." -drawPendingIncrement :: AddressInEra -> Maybe PendingIncrement -> UTCTime -> Widget Name -drawPendingIncrement ownAddress pendingIncrement now = - case pendingIncrement of - Nothing -> vBox [] - Just PendingDeposit{utxoToCommit, deposit, depositDeadline} -> - vBox - [ drawUTxO (highlightOwnAddress ownAddress) utxoToCommit - , padTop (Pad 1) $ txt "Pending deposit: " - , txt $ show deposit - , txt "Pending deposit deadline: " - , drawRemainingDepositDeadline depositDeadline now - ] - Just PendingIncrement{utxoToCommit} -> - vBox - [ drawUTxO (highlightOwnAddress ownAddress) utxoToCommit - , padTop (Pad 1) $ txt "NO Pending deposit" - ] - -drawFocusPanelOpen :: NetworkId -> VerificationKey PaymentKey -> UTxO -> UTxO -> Maybe PendingIncrement -> UTCTime -> OpenScreen -> Widget Name -drawFocusPanelOpen networkId vk utxo pendingUTxOToDecommit pendingIncrement now = \case +drawPendingIncrement :: AddressInEra -> [PendingIncrement] -> UTCTime -> Widget Name +drawPendingIncrement ownAddress pendingIncrements now = + padLeft (Pad 2) $ + vBox $ + foldl' pendingWidget [] pendingIncrements + where + pendingWidget acc = \case + PendingIncrement{utxoToCommit, deposit, depositDeadline, status} -> + acc + <> [ txt $ "id: " <> show deposit + , txt $ "status: " <> show status + , txt "utxo: " + , drawUTxO (highlightOwnAddress ownAddress) utxoToCommit + , txt "deadline: " + , drawRemainingDepositDeadline depositDeadline now + , hBorder + ] + +drawFocusPanelOpen :: NetworkId -> VerificationKey PaymentKey -> UTxO -> UTxO -> [PendingIncrement] -> UTCTime -> OpenScreen -> Widget Name +drawFocusPanelOpen networkId vk utxo pendingUTxOToDecommit pendingIncrements now = \case OpenHome -> vBox [ vBox @@ -173,12 +173,15 @@ drawFocusPanelOpen networkId vk utxo pendingUTxOToDecommit pendingIncrement now , drawUTxO (highlightOwnAddress ownAddress) pendingUTxOToDecommit ] , hBorder - , txt "Pending UTxO to commit: " - , drawPendingIncrement ownAddress pendingIncrement now + , vBox + [ txt "Pending UTxO to commit: " + , drawPendingIncrement ownAddress pendingIncrements now + ] ] SelectingUTxO x -> renderForm x SelectingUTxOToDecommit x -> renderForm x SelectingUTxOToIncrement x -> renderForm x + SelectingDepositIdToRecover x -> renderForm x EnteringAmount _ x -> renderForm x SelectingRecipient _ _ x -> renderForm x EnteringRecipientAddress _ _ x -> renderForm x @@ -206,9 +209,9 @@ highlightOwnAddress ownAddress a = drawFocusPanel :: NetworkId -> VerificationKey PaymentKey -> UTCTime -> Connection -> Widget Name drawFocusPanel networkId vk now (Connection{me, headState}) = case headState of Idle -> emptyWidget - Active (ActiveLink{utxo, pendingUTxOToDecommit, pendingIncrement, activeHeadState}) -> case activeHeadState of + Active (ActiveLink{utxo, pendingUTxOToDecommit, pendingIncrements, activeHeadState}) -> case activeHeadState of Initializing x -> drawFocusPanelInitializing me x - Open x -> drawFocusPanelOpen networkId vk utxo pendingUTxOToDecommit pendingIncrement now x + Open x -> drawFocusPanelOpen networkId vk utxo pendingUTxOToDecommit pendingIncrements now x Closed x -> drawFocusPanelClosed now x FanoutPossible -> txt "Ready to fanout!" Final -> drawFocusPanelFinal networkId vk utxo diff --git a/hydra-tui/src/Hydra/TUI/Forms.hs b/hydra-tui/src/Hydra/TUI/Forms.hs index 2bea2ed95c5..49e10c90057 100644 --- a/hydra-tui/src/Hydra/TUI/Forms.hs +++ b/hydra-tui/src/Hydra/TUI/Forms.hs @@ -63,6 +63,27 @@ utxoRadioField u = ] (Prelude.head $ Map.toList u) +depositIdRadioField :: + forall s e n. + ( s ~ (TxId, TxIn, TxOut CtxUTxO) + , n ~ Text + ) => + [(TxId, UTxO)] -> + Form s e n +depositIdRadioField txIdUTxO = + newForm + [ radioField + id + [ ((txid, i, o), show txid, UTxO.render (i, o)) + | (txid, i, o) <- flattened txIdUTxO + ] + ] + (Prelude.head $ flattened txIdUTxO) + where + flattened = + concatMap + (\(txId, u) -> (\(i, o) -> (txId, i, o)) <$> Map.toList (UTxO.toMap u)) + confirmRadioField :: forall s e n. ( s ~ Bool diff --git a/hydra-tui/src/Hydra/TUI/Handlers.hs b/hydra-tui/src/Hydra/TUI/Handlers.hs index 953f059c5da..90095a80078 100644 --- a/hydra-tui/src/Hydra/TUI/Handlers.hs +++ b/hydra-tui/src/Hydra/TUI/Handlers.hs @@ -113,16 +113,41 @@ handleHydraEventsActiveLink e = do Update TimedServerOutput{time, output = HeadIsFinalized{utxo}} -> do utxoL .= utxo activeHeadStateL .= Final - Update TimedServerOutput{time, output = DecommitRequested{utxoToDecommit}} -> + Update TimedServerOutput{time, output = DecommitRequested{utxoToDecommit}} -> do + ActiveLink{utxo} <- get pendingUTxOToDecommitL .= utxoToDecommit - Update TimedServerOutput{time, output = DecommitFinalized{}} -> + utxoL .= UTxO.difference utxo utxoToDecommit + Update TimedServerOutput{time, output = DecommitFinalized{}} -> do + ActiveLink{utxo, pendingUTxOToDecommit} <- get pendingUTxOToDecommitL .= mempty + utxoL .= utxo Update TimedServerOutput{time, output = CommitRecorded{utxoToCommit, pendingDeposit, deadline}} -> do - pendingIncrementL .= Just (PendingDeposit utxoToCommit pendingDeposit deadline) - Update TimedServerOutput{time, output = CommitApproved{utxoToCommit}} -> do - pendingIncrementL .= Just (PendingIncrement utxoToCommit) - Update TimedServerOutput{time, output = CommitFinalized{}} -> do - pendingIncrementL .= Nothing + ActiveLink{utxo, pendingIncrements} <- get + pendingIncrementsL .= pendingIncrements <> [PendingIncrement utxoToCommit pendingDeposit deadline PendingDeposit] + utxoL .= utxo + Update TimedServerOutput{time, output = CommitApproved{utxoToCommit = approvedUtxoToCommit}} -> do + ActiveLink{utxo, pendingIncrements} <- get + pendingIncrementsL + .= fmap + ( \inc@PendingIncrement{utxoToCommit = pendingUtxoToCommit, deposit, depositDeadline} -> + if hashUTxO pendingUtxoToCommit == hashUTxO approvedUtxoToCommit + then PendingIncrement pendingUtxoToCommit deposit depositDeadline FinalizingDeposit + else inc + ) + pendingIncrements + utxoL .= utxo + Update TimedServerOutput{time, output = CommitFinalized{theDeposit}} -> do + ActiveLink{utxo, pendingIncrements} <- get + let activePendingIncrements = filter (\PendingIncrement{deposit} -> deposit /= theDeposit) pendingIncrements + let approvedIncrement = find (\PendingIncrement{deposit} -> deposit == theDeposit) pendingIncrements + let activeUtxoToCommit = maybe mempty (\PendingIncrement{utxoToCommit} -> utxoToCommit) approvedIncrement + pendingIncrementsL .= activePendingIncrements + utxoL .= utxo <> activeUtxoToCommit + Update TimedServerOutput{time, output = CommitRecovered{recoveredUTxO, recoveredTxId}} -> do + ActiveLink{utxo, pendingIncrements} <- get + let activePendingIncrements = filter (\PendingIncrement{deposit} -> deposit /= recoveredTxId) pendingIncrements + pendingIncrementsL .= activePendingIncrements + utxoL .= UTxO.difference utxo recoveredUTxO _ -> pure () handleHydraEventsInfo :: HydraEvent Tx -> EventM Name [LogMessage] () @@ -147,14 +172,47 @@ handleHydraEventsInfo = \case report Success time "Transaction submitted successfully" Update TimedServerOutput{time, output = TxInvalid{transaction, validationError}} -> warn time ("Transaction with id " <> show (txId transaction) <> " is not applicable: " <> show validationError) - Update TimedServerOutput{time, output = DecommitApproved{}} -> - report Success time "Decommit approved and submitted to Cardano" + Update TimedServerOutput{time, output = DecommitApproved{decommitTxId, utxoToDecommit}} -> + report Success time $ + "Decommit approved and submitted to Cardano " + <> show decommitTxId + <> " " + <> foldMap UTxO.render (UTxO.pairs utxoToDecommit) + Update TimedServerOutput{time, output = DecommitFinalized{decommitTxId}} -> + report Success time $ + "Decommit finalized " + <> show decommitTxId Update TimedServerOutput{time, output = DecommitInvalid{decommitTx, decommitInvalidReason}} -> - warn time ("Decommit Transaction with id " <> show (txId decommitTx) <> " is not applicable: " <> show decommitInvalidReason) - Update TimedServerOutput{time, output = CommitRecorded{}} -> - report Success time "Commit deposit recorded and pending for approval" - Update TimedServerOutput{time, output = CommitApproved{}} -> - report Success time "Commit approved and submitted to Cardano" + warn time $ + "Decommit Transaction with id " + <> show (txId decommitTx) + <> " is not applicable: " + <> show decommitInvalidReason + Update TimedServerOutput{time, output = CommitRecorded{utxoToCommit, pendingDeposit}} -> + report Success time $ + "Commit deposit recorded with " + <> " deposit tx id " + <> show pendingDeposit + <> "and pending for approval " + <> foldMap UTxO.render (UTxO.pairs utxoToCommit) + Update TimedServerOutput{time, output = CommitApproved{utxoToCommit}} -> + report Success time $ + "Commit approved and submitted to Cardano " + <> foldMap UTxO.render (UTxO.pairs utxoToCommit) + Update TimedServerOutput{time, output = CommitRecovered{recoveredTxId, recoveredUTxO}} -> + report Success time $ + "Commit recovered " + <> show recoveredTxId + <> " " + <> foldMap UTxO.render (UTxO.pairs recoveredUTxO) + Update TimedServerOutput{time, output = CommitFinalized{theDeposit}} -> + report Success time $ + "Commit finalized " + <> show theDeposit + Update TimedServerOutput{time, output = CommitIgnored{depositUTxO}} -> + warn time $ + "Commit ignored. Local pending deposits " + <> foldMap (foldMap UTxO.render . UTxO.pairs) depositUTxO Update TimedServerOutput{time, output = HeadIsFinalized{utxo}} -> do info time "Head is finalized" Update TimedServerOutput{time, output = InvalidInput{reason}} -> @@ -189,12 +247,13 @@ handleVtyEventsHeadState cardanoClient hydraClient e = do handleVtyEventsActiveLink :: CardanoClient -> Client Tx IO -> Vty.Event -> EventM Name ActiveLink () handleVtyEventsActiveLink cardanoClient hydraClient e = do utxo <- use utxoL - zoom activeHeadStateL $ handleVtyEventsActiveHeadState cardanoClient hydraClient utxo e + pendingIncrements <- use pendingIncrementsL + zoom activeHeadStateL $ handleVtyEventsActiveHeadState cardanoClient hydraClient utxo pendingIncrements e -handleVtyEventsActiveHeadState :: CardanoClient -> Client Tx IO -> UTxO -> Vty.Event -> EventM Name ActiveHeadState () -handleVtyEventsActiveHeadState cardanoClient hydraClient utxo e = do +handleVtyEventsActiveHeadState :: CardanoClient -> Client Tx IO -> UTxO -> [PendingIncrement] -> Vty.Event -> EventM Name ActiveHeadState () +handleVtyEventsActiveHeadState cardanoClient hydraClient utxo pendingIncrements e = do zoom (initializingStateL . initializingScreenL) $ handleVtyEventsInitializingScreen cardanoClient hydraClient e - zoom openStateL $ handleVtyEventsOpen cardanoClient hydraClient utxo e + zoom openStateL $ handleVtyEventsOpen cardanoClient hydraClient utxo pendingIncrements e s <- use id case s of FanoutPossible -> handleVtyEventsFanoutPossible hydraClient e @@ -235,8 +294,8 @@ handleVtyEventsInitializingScreen cardanoClient hydraClient e = do _ -> pure () zoom confirmingAbortFormL $ handleFormEvent (VtyEvent e) -handleVtyEventsOpen :: CardanoClient -> Client Tx IO -> UTxO -> Vty.Event -> EventM Name OpenScreen () -handleVtyEventsOpen cardanoClient hydraClient utxo e = +handleVtyEventsOpen :: CardanoClient -> Client Tx IO -> UTxO -> [PendingIncrement] -> Vty.Event -> EventM Name OpenScreen () +handleVtyEventsOpen cardanoClient hydraClient utxo pendingIncrements e = get >>= \case OpenHome -> do case e of @@ -249,6 +308,9 @@ handleVtyEventsOpen cardanoClient hydraClient utxo e = EvKey (KChar 'i') [] -> do utxo' <- liftIO $ queryUTxOByAddress cardanoClient [mkMyAddress cardanoClient hydraClient] put $ SelectingUTxOToIncrement (utxoRadioField $ UTxO.toMap utxo') + EvKey (KChar 'r') [] -> do + let pendingDepositIds = (\PendingIncrement{deposit, utxoToCommit} -> (deposit, utxoToCommit)) <$> pendingIncrements + put $ SelectingDepositIdToRecover (depositIdRadioField pendingDepositIds) EvKey (KChar 'c') [] -> put $ ConfirmingClose confirmRadioField _ -> pure () @@ -293,6 +355,14 @@ handleVtyEventsOpen cardanoClient hydraClient utxo e = liftIO $ externalCommit hydraClient commitUTxO put OpenHome _ -> zoom selectingUTxOToIncrementFormL $ handleFormEvent (VtyEvent e) + SelectingDepositIdToRecover i -> do + case e of + EvKey KEsc [] -> put OpenHome + EvKey KEnter [] -> do + let (selectedTxId, _, _) = formState i + liftIO $ recoverCommit hydraClient selectedTxId + put OpenHome + _ -> zoom selectingDepositIdToRecoverFormL $ handleFormEvent (VtyEvent e) EnteringAmount utxoSelected i -> case e of EvKey KEsc [] -> put OpenHome diff --git a/hydra-tui/src/Hydra/TUI/Model.hs b/hydra-tui/src/Hydra/TUI/Model.hs index cd864f1e146..ce982a9a3b9 100644 --- a/hydra-tui/src/Hydra/TUI/Model.hs +++ b/hydra-tui/src/Hydra/TUI/Model.hs @@ -42,6 +42,8 @@ type UTxOCheckboxForm e n = Form (Map TxIn (TxOut CtxUTxO, Bool)) e n type UTxORadioFieldForm e n = Form (TxIn, TxOut CtxUTxO) e n +type TxIdRadioFieldForm e n = Form (TxId, TxIn, TxOut CtxUTxO) e n + type ConfirmingRadioFieldForm e n = Form Bool e n data InitializingState = InitializingState @@ -59,6 +61,7 @@ data OpenScreen | SelectingUTxO {selectingUTxOForm :: UTxORadioFieldForm (HydraEvent Tx) Name} | SelectingUTxOToDecommit {selectingUTxOToDecommitForm :: UTxORadioFieldForm (HydraEvent Tx) Name} | SelectingUTxOToIncrement {selectingUTxOToIncrementForm :: UTxORadioFieldForm (HydraEvent Tx) Name} + | SelectingDepositIdToRecover {selectingDepositIdToRecoverForm :: TxIdRadioFieldForm (HydraEvent Tx) Name} | EnteringAmount {utxoSelected :: (TxIn, TxOut CtxUTxO), enteringAmountForm :: Form Integer (HydraEvent Tx) Name} | SelectingRecipient { utxoSelected :: (TxIn, TxOut CtxUTxO) @@ -88,20 +91,23 @@ data HeadState = Idle | Active {activeLink :: ActiveLink} -data PendingIncrement +data PendingIncrementStatus = PendingDeposit - { utxoToCommit :: UTxO - , deposit :: TxId - , depositDeadline :: UTCTime - } - | PendingIncrement - { utxoToCommit :: UTxO - } + | FinalizingDeposit + deriving (Show) + +data PendingIncrement + = PendingIncrement + { utxoToCommit :: UTxO + , deposit :: TxId + , depositDeadline :: UTCTime + , status :: PendingIncrementStatus + } data ActiveLink = ActiveLink { utxo :: UTxO , pendingUTxOToDecommit :: UTxO - , pendingIncrement :: Maybe PendingIncrement + , pendingIncrements :: [PendingIncrement] , parties :: [Party] , headId :: HeadId , activeHeadState :: ActiveHeadState @@ -120,6 +126,7 @@ makeLensesFor [ ("selectingUTxOForm", "selectingUTxOFormL") , ("selectingUTxOToDecommitForm", "selectingUTxOToDecommitFormL") , ("selectingUTxOToIncrementForm", "selectingUTxOToIncrementFormL") + , ("selectingDepositIdToRecoverForm", "selectingDepositIdToRecoverFormL") , ("enteringAmountForm", "enteringAmountFormL") , ("selectingRecipientForm", "selectingRecipientFormL") , ("enteringRecipientAddressForm", "enteringRecipientAddressFormL") @@ -174,7 +181,7 @@ makeLensesFor makeLensesFor [ ("utxo", "utxoL") , ("pendingUTxOToDecommit", "pendingUTxOToDecommitL") - , ("pendingIncrement", "pendingIncrementL") + , ("pendingIncrements", "pendingIncrementsL") , ("parties", "partiesL") , ("activeHeadState", "activeHeadStateL") , ("headId", "headIdL") @@ -209,7 +216,7 @@ newActiveLink parties headId = } , utxo = mempty , pendingUTxOToDecommit = mempty - , pendingIncrement = Nothing + , pendingIncrements = mempty , headId } diff --git a/hydra-tx/hydra-tx.cabal b/hydra-tx/hydra-tx.cabal index 7b7d12f9b80..641825fc61a 100644 --- a/hydra-tx/hydra-tx.cabal +++ b/hydra-tx/hydra-tx.cabal @@ -159,6 +159,8 @@ test-suite tests Hydra.Tx.Contract.CollectCom Hydra.Tx.Contract.Commit Hydra.Tx.Contract.Contest.ContestCurrent + Hydra.Tx.Contract.Contest.ContestDec + Hydra.Tx.Contract.Contest.Healthy Hydra.Tx.Contract.ContractSpec Hydra.Tx.Contract.Decrement Hydra.Tx.Contract.Deposit diff --git a/hydra-tx/src/Hydra/Tx/Close.hs b/hydra-tx/src/Hydra/Tx/Close.hs index bd0c4808bab..c0938a0f279 100644 --- a/hydra-tx/src/Hydra/Tx/Close.hs +++ b/hydra-tx/src/Hydra/Tx/Close.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DuplicateRecordFields #-} module Hydra.Tx.Close where @@ -35,7 +34,7 @@ import Hydra.Tx ( ) import Hydra.Tx.Contest (PointInTime) import Hydra.Tx.Crypto (toPlutusSignatures) -import Hydra.Tx.Utils (mkHydraHeadV1TxName) +import Hydra.Tx.Utils (IncrementalAction (..), mkHydraHeadV1TxName) import PlutusLedgerApi.V3 (toBuiltin) -- | Representation of the Head output after a CollectCom transaction. @@ -66,8 +65,9 @@ closeTx :: PointInTime -> -- | Everything needed to spend the Head state-machine output. OpenThreadOutput -> + IncrementalAction -> Tx -closeTx scriptRegistry vk headId openVersion confirmedSnapshot startSlotNo (endSlotNo, utcTime) openThreadOutput = +closeTx scriptRegistry vk headId openVersion confirmedSnapshot startSlotNo (endSlotNo, utcTime) openThreadOutput incrementalAction = unsafeBuildTransaction $ emptyTxBody & addInputs [(headInput, headWitness)] @@ -100,15 +100,29 @@ closeTx scriptRegistry vk headId openVersion confirmedSnapshot startSlotNo (endS closeRedeemer = case confirmedSnapshot of InitialSnapshot{} -> Head.CloseInitial - ConfirmedSnapshot{signatures, snapshot = Snapshot{version, utxoToDecommit}} - | version == openVersion -> - Head.CloseUnused{signature = toPlutusSignatures signatures} - | otherwise -> - -- NOTE: This will only work for version == openVersion - 1 - Head.CloseUsed - { signature = toPlutusSignatures signatures - , alreadyDecommittedUTxOHash = toBuiltin . hashUTxO $ fromMaybe mempty utxoToDecommit - } + ConfirmedSnapshot{signatures, snapshot = Snapshot{version}} -> + case incrementalAction of + ToCommit utxo' -> + if version == openVersion + then + Head.CloseUnusedInc + { signature = toPlutusSignatures signatures + , alreadyCommittedUTxOHash = toBuiltin $ hashUTxO utxo' + } + else + Head.CloseUsedInc + { signature = toPlutusSignatures signatures + , alreadyCommittedUTxOHash = toBuiltin $ hashUTxO utxo' + } + ToDecommit utxo' -> + if version == openVersion + then Head.CloseUnusedDec{signature = toPlutusSignatures signatures} + else + Head.CloseUsedDec + { signature = toPlutusSignatures signatures + , alreadyDecommittedUTxOHash = toBuiltin $ hashUTxO utxo' + } + NoThing -> Head.CloseAny{signature = toPlutusSignatures signatures} headOutputAfter = modifyTxOutDatum (const headDatumAfter) headOutputBefore @@ -120,10 +134,15 @@ closeTx scriptRegistry vk headId openVersion confirmedSnapshot startSlotNo (endS { snapshotNumber = fromIntegral . number $ getSnapshot confirmedSnapshot , utxoHash = - toBuiltin . hashUTxO . utxo $ getSnapshot confirmedSnapshot - , deltaUTxOHash = + toBuiltin . hashUTxO $ utxo (getSnapshot confirmedSnapshot) + , alphaUTxOHash = case closeRedeemer of - Head.CloseUnused{} -> + Head.CloseUsedInc{} -> + toBuiltin . hashUTxO @Tx . fromMaybe mempty . utxoToCommit $ getSnapshot confirmedSnapshot + _ -> toBuiltin $ hashUTxO @Tx mempty + , omegaUTxOHash = + case closeRedeemer of + Head.CloseUnusedDec{} -> toBuiltin . hashUTxO @Tx . fromMaybe mempty . utxoToDecommit $ getSnapshot confirmedSnapshot _ -> toBuiltin $ hashUTxO @Tx mempty , parties = openParties diff --git a/hydra-tx/src/Hydra/Tx/Contest.hs b/hydra-tx/src/Hydra/Tx/Contest.hs index 519dbf809e9..d0d1be156ba 100644 --- a/hydra-tx/src/Hydra/Tx/Contest.hs +++ b/hydra-tx/src/Hydra/Tx/Contest.hs @@ -23,7 +23,8 @@ import Hydra.Tx.HeadId (HeadId, headIdToCurrencySymbol) import Hydra.Tx.IsTx (hashUTxO) import Hydra.Tx.ScriptRegistry (ScriptRegistry, headReference) import Hydra.Tx.Snapshot (Snapshot (..), SnapshotVersion) -import Hydra.Tx.Utils (mkHydraHeadV1TxName) + +import Hydra.Tx.Utils (IncrementalAction (..), mkHydraHeadV1TxName) import PlutusLedgerApi.V3 (toBuiltin) import PlutusLedgerApi.V3 qualified as Plutus @@ -59,8 +60,9 @@ contestTx :: PointInTime -> -- | Everything needed to spend the Head state-machine output. ClosedThreadOutput -> + IncrementalAction -> Tx -contestTx scriptRegistry vk headId contestationPeriod openVersion Snapshot{number, utxo, utxoToDecommit, version} sig (slotNo, _) closedThreadOutput = +contestTx scriptRegistry vk headId contestationPeriod openVersion snapshot sig (slotNo, _) closedThreadOutput incrementalAction = unsafeBuildTransaction $ emptyTxBody & addInputs [(headInput, headWitness)] @@ -70,6 +72,8 @@ contestTx scriptRegistry vk headId contestationPeriod openVersion Snapshot{numbe & setValidityUpperBound slotNo & setTxMetadata (TxMetadataInEra $ mkHydraHeadV1TxName "ContestTx") where + Snapshot{number, version, utxo, utxoToCommit, utxoToDecommit} = snapshot + ClosedThreadOutput { closedThreadUTxO = (headInput, headOutputBefore) , closedParties @@ -88,19 +92,33 @@ contestTx scriptRegistry vk headId contestationPeriod openVersion Snapshot{numbe headScript = fromPlutusScript @PlutusScriptV3 Head.validatorScript - headRedeemer = toScriptData $ Head.Contest contestRedeemer + contestRedeemer = + case incrementalAction of + ToCommit utxo' -> + if version == openVersion + then + Head.ContestUnusedInc + { signature = toPlutusSignatures sig + , alreadyCommittedUTxOHash = toBuiltin $ hashUTxO utxo' + } + else + Head.ContestUsedInc + { signature = toPlutusSignatures sig + } + ToDecommit utxo' -> + if version == openVersion + then + Head.ContestUnusedDec + { signature = toPlutusSignatures sig + } + else + Head.ContestUsedDec + { signature = toPlutusSignatures sig + , alreadyDecommittedUTxOHash = toBuiltin $ hashUTxO utxo' + } + NoThing -> Head.ContestCurrent{signature = toPlutusSignatures sig} - contestRedeemer - | version == openVersion = - Head.ContestCurrent - { signature = toPlutusSignatures sig - } - | otherwise = - -- NOTE: This will only work for version == openVersion - 1 - Head.ContestOutdated - { signature = toPlutusSignatures sig - , alreadyDecommittedUTxOHash = toBuiltin $ hashUTxO @Tx $ fromMaybe mempty utxoToDecommit - } + headRedeemer = toScriptData $ Head.Contest contestRedeemer headOutputAfter = modifyTxOutDatum (const headDatumAfter) headOutputBefore @@ -120,9 +138,14 @@ contestTx scriptRegistry vk headId contestationPeriod openVersion Snapshot{numbe Head.ClosedDatum { snapshotNumber = toInteger number , utxoHash = toBuiltin $ hashUTxO @Tx utxo - , deltaUTxOHash = + , alphaUTxOHash = + case contestRedeemer of + Head.ContestUsedInc{} -> + toBuiltin $ hashUTxO @Tx $ fromMaybe mempty utxoToCommit + _ -> toBuiltin $ hashUTxO @Tx mempty + , omegaUTxOHash = case contestRedeemer of - Head.ContestCurrent{} -> + Head.ContestUnusedDec{} -> toBuiltin $ hashUTxO @Tx $ fromMaybe mempty utxoToDecommit _ -> toBuiltin $ hashUTxO @Tx mempty , parties = closedParties diff --git a/hydra-tx/src/Hydra/Tx/Deposit.hs b/hydra-tx/src/Hydra/Tx/Deposit.hs index cd774caeb10..955bf4ef97e 100644 --- a/hydra-tx/src/Hydra/Tx/Deposit.hs +++ b/hydra-tx/src/Hydra/Tx/Deposit.hs @@ -11,6 +11,7 @@ import Hydra.Cardano.Api import Hydra.Cardano.Api.Network (Network) import Hydra.Contract.Commit qualified as Commit import Hydra.Contract.Deposit qualified as Deposit +import Hydra.Plutus (depositValidatorScript) import Hydra.Plutus.Extras.Time (posixFromUTCTime) import Hydra.Tx (CommitBlueprintTx (..), HeadId, fromCurrencySymbol, headIdToCurrencySymbol) import Hydra.Tx.Utils (addMetadata, mkHydraHeadV1TxName) @@ -45,11 +46,11 @@ depositTx networkId headId commitBlueprintTx deadline = depositValue = foldMap txOutValue depositUTxO - depositScript = fromPlutusScript @PlutusScriptV3 Deposit.validatorScript + depositScript = fromPlutusScript @PlutusScriptV3 depositValidatorScript deposits = mapMaybe Commit.serializeCommit $ UTxO.pairs depositUTxO - depositPlutusDatum = Deposit.datum $ Deposit.DepositDatum (headIdToCurrencySymbol headId, posixFromUTCTime deadline, deposits) + depositPlutusDatum = Deposit.datum (headIdToCurrencySymbol headId, posixFromUTCTime deadline, deposits) depositDatum = mkTxOutDatumInline depositPlutusDatum @@ -60,6 +61,9 @@ depositTx networkId headId commitBlueprintTx deadline = depositDatum ReferenceScriptNone +depositAddress :: NetworkId -> AddressInEra +depositAddress networkId = mkScriptAddress @PlutusScriptV3 networkId (fromPlutusScript @PlutusScriptV3 depositValidatorScript) + -- * Observation data DepositObservation = DepositObservation @@ -76,7 +80,7 @@ observeDepositTx :: Maybe DepositObservation observeDepositTx networkId tx = do -- TODO: could just use the first output and fail otherwise - (TxIn depositTxId _, depositOut) <- findTxOutByAddress depositAddress tx + (TxIn depositTxId _, depositOut) <- findTxOutByAddress (depositAddress networkId) tx (headId, deposited, deadline) <- observeDepositTxOut (networkIdToNetwork networkId) (toUTxOContext depositOut) if all (`elem` txIns' tx) (UTxO.inputSet deposited) then @@ -88,17 +92,13 @@ observeDepositTx networkId tx = do , deadline } else Nothing - where - depositScript = fromPlutusScript Deposit.validatorScript - - depositAddress = mkScriptAddress @PlutusScriptV3 networkId depositScript observeDepositTxOut :: Network -> TxOut CtxUTxO -> Maybe (HeadId, UTxO, POSIXTime) observeDepositTxOut network depositOut = do dat <- case txOutDatum depositOut of TxOutDatumInline d -> pure d _ -> Nothing - Deposit.DepositDatum (headCurrencySymbol, deadline, onChainDeposits) <- fromScriptData dat + (headCurrencySymbol, deadline, onChainDeposits) <- fromScriptData dat deposit <- do depositedUTxO <- traverse (Commit.deserializeCommit network) onChainDeposits pure . UTxO.fromPairs $ depositedUTxO diff --git a/hydra-tx/src/Hydra/Tx/Fanout.hs b/hydra-tx/src/Hydra/Tx/Fanout.hs index 4a5776f2db2..b0f88138dfa 100644 --- a/hydra-tx/src/Hydra/Tx/Fanout.hs +++ b/hydra-tx/src/Hydra/Tx/Fanout.hs @@ -26,6 +26,8 @@ fanoutTx :: ScriptRegistry -> -- | Snapshotted UTxO to fanout on layer 1 UTxO -> + -- | Snapshotted commit UTxO to fanout on layer 1 + Maybe UTxO -> -- | Snapshotted decommit UTxO to fanout on layer 1 Maybe UTxO -> -- | Everything needed to spend the Head state-machine output. @@ -35,12 +37,12 @@ fanoutTx :: -- | Minting Policy script, made from initial seed PlutusScript -> Tx -fanoutTx scriptRegistry utxo utxoToDecommit (headInput, headOutput) deadlineSlotNo headTokenScript = +fanoutTx scriptRegistry utxo utxoToCommit utxoToDecommit (headInput, headOutput) deadlineSlotNo headTokenScript = unsafeBuildTransaction $ emptyTxBody & addInputs [(headInput, headWitness)] & addReferenceInputs [headScriptRef] - & addOutputs (orderedTxOutsToFanout <> orderedTxOutsToDecommit) + & addOutputs (orderedTxOutsToFanout <> orderedTxOutsToCommit <> orderedTxOutsToDecommit) & burnTokens headTokenScript Burn headTokens & setValidityLowerBound (deadlineSlotNo + 1) & setTxMetadata (TxMetadataInEra $ mkHydraHeadV1TxName "FanoutTx") @@ -56,8 +58,10 @@ fanoutTx scriptRegistry utxo utxoToDecommit (headInput, headOutput) deadlineSlot headRedeemer = toScriptData $ Head.Fanout - { numberOfFanoutOutputs = fromIntegral $ length utxo - , numberOfDecommitOutputs = fromIntegral $ maybe 0 length utxoToDecommit + { numberOfFanoutOutputs = fromIntegral $ length $ toList utxo + , -- TODO: Update the spec with this new field 'numberOfCommitOutputs' + numberOfCommitOutputs = fromIntegral $ length orderedTxOutsToCommit + , numberOfDecommitOutputs = fromIntegral $ length orderedTxOutsToDecommit } headTokens = @@ -66,6 +70,11 @@ fanoutTx scriptRegistry utxo utxoToDecommit (headInput, headOutput) deadlineSlot orderedTxOutsToFanout = toTxContext <$> toList utxo + orderedTxOutsToCommit = + case utxoToCommit of + Nothing -> [] + Just commitUTxO -> toTxContext <$> toList commitUTxO + orderedTxOutsToDecommit = case utxoToDecommit of Nothing -> [] diff --git a/hydra-tx/src/Hydra/Tx/Increment.hs b/hydra-tx/src/Hydra/Tx/Increment.hs index 41e0f8ef1f1..2a216556062 100644 --- a/hydra-tx/src/Hydra/Tx/Increment.hs +++ b/hydra-tx/src/Hydra/Tx/Increment.hs @@ -17,7 +17,9 @@ import Hydra.Ledger.Cardano.Builder ( setValidityUpperBound, unsafeBuildTransaction, ) +import Hydra.Plutus (depositValidatorScript) import Hydra.Tx.ContestationPeriod (toChain) +import Hydra.Tx.Crypto (MultiSignature (..), toPlutusSignatures) import Hydra.Tx.HeadId (HeadId, headIdToCurrencySymbol) import Hydra.Tx.HeadParameters (HeadParameters (..)) import Hydra.Tx.IsTx (hashUTxO) @@ -45,8 +47,9 @@ incrementTx :: -- | Deposit output UTxO to be spent in increment transaction UTxO -> SlotNo -> + MultiSignature (Snapshot Tx) -> Tx -incrementTx scriptRegistry vk headId headParameters (headInput, headOutput) snapshot depositScriptUTxO upperValiditySlot = +incrementTx scriptRegistry vk headId headParameters (headInput, headOutput) snapshot depositScriptUTxO upperValiditySlot sigs = unsafeBuildTransaction $ emptyTxBody & addInputs [(headInput, headWitness), (depositIn, depositWitness)] @@ -57,9 +60,13 @@ incrementTx scriptRegistry vk headId headParameters (headInput, headOutput) snap & setTxMetadata (TxMetadataInEra $ mkHydraHeadV1TxName "IncrementTx") where headRedeemer = - toScriptData $ Head.Increment Head.IncrementRedeemer - - utxoHash = toBuiltin $ hashUTxO @Tx (utxo <> fromMaybe mempty utxoToCommit) + toScriptData $ + Head.Increment + Head.IncrementRedeemer + { signature = toPlutusSignatures sigs + , snapshotNumber = fromIntegral number + , increment = toPlutusTxOutRef depositIn + } HeadParameters{parties, contestationPeriod} = headParameters @@ -77,6 +84,8 @@ incrementTx scriptRegistry vk headId headParameters (headInput, headOutput) snap ScriptWitness scriptWitnessInCtx $ mkScriptReference headScriptRef headScript InlineScriptDatum headRedeemer + utxoHash = toBuiltin $ hashUTxO @Tx utxo + headDatumAfter = mkTxOutDatumInline $ Head.Open @@ -88,18 +97,18 @@ incrementTx scriptRegistry vk headId headParameters (headInput, headOutput) snap , version = toInteger version + 1 } - depositedValue = txOutValue depositOut + depositedValue = foldMap (txOutValue . snd) $ UTxO.pairs (fromMaybe mempty utxoToCommit) - depositScript = fromPlutusScript @PlutusScriptV3 Deposit.validatorScript + depositScript = fromPlutusScript @PlutusScriptV3 depositValidatorScript -- NOTE: we expect always a single output from a deposit tx - (depositIn, depositOut) = List.head $ UTxO.pairs depositScriptUTxO + (depositIn, _) = List.head $ UTxO.pairs depositScriptUTxO - depositRedeemer = toScriptData $ Deposit.Claim $ headIdToCurrencySymbol headId + depositRedeemer = toScriptData $ Deposit.redeemer $ Deposit.Claim $ headIdToCurrencySymbol headId depositWitness = BuildTxWith $ ScriptWitness scriptWitnessInCtx $ mkScriptWitness depositScript InlineScriptDatum depositRedeemer - Snapshot{utxo, utxoToCommit, version} = snapshot + Snapshot{utxo, utxoToCommit, version, number} = snapshot diff --git a/hydra-tx/src/Hydra/Tx/IsTx.hs b/hydra-tx/src/Hydra/Tx/IsTx.hs index 4b115dd2185..4e83a9bd912 100644 --- a/hydra-tx/src/Hydra/Tx/IsTx.hs +++ b/hydra-tx/src/Hydra/Tx/IsTx.hs @@ -22,7 +22,7 @@ import Data.Text.Lazy.Builder (toLazyText) import Formatting.Buildable (build) import Hydra.Cardano.Api.Tx qualified as Api import Hydra.Cardano.Api.UTxO qualified as Api -import Hydra.Contract.Head qualified as Head +import Hydra.Contract.Util qualified as Util import PlutusLedgerApi.V3 (fromBuiltin) -- | Types of transactions that can be used by the Head protocol. The associated @@ -164,8 +164,8 @@ instance IsTx Tx where txId = getTxId . getTxBody balance = foldMap txOutValue - -- NOTE: See note from `Head.hashTxOuts`. - hashUTxO = fromBuiltin . Head.hashTxOuts . mapMaybe toPlutusTxOut . toList + -- NOTE: See note from `Util.hashTxOuts`. + hashUTxO = fromBuiltin . Util.hashTxOuts . mapMaybe toPlutusTxOut . toList txSpendingUTxO = Api.txSpendingUTxO diff --git a/hydra-tx/src/Hydra/Tx/Recover.hs b/hydra-tx/src/Hydra/Tx/Recover.hs index 9505df15eab..8c0898b1eec 100644 --- a/hydra-tx/src/Hydra/Tx/Recover.hs +++ b/hydra-tx/src/Hydra/Tx/Recover.hs @@ -13,6 +13,7 @@ import Hydra.Ledger.Cardano.Builder ( setValidityLowerBound, unsafeBuildTransaction, ) +import Hydra.Plutus (depositValidatorScript) import Hydra.Tx (HeadId, mkHeadId) import Hydra.Tx.Utils (mkHydraHeadV1TxName) @@ -35,7 +36,7 @@ recoverTx depositTxId deposited lowerBoundSlot = where recoverInputs = (,depositWitness) <$> [TxIn depositTxId (TxIx 0)] - redeemer = toScriptData $ Deposit.Recover $ fromIntegral $ length depositOutputs + redeemer = toScriptData $ Deposit.redeemer $ Deposit.Recover $ fromIntegral $ length depositOutputs depositWitness = BuildTxWith $ @@ -45,7 +46,7 @@ recoverTx depositTxId deposited lowerBoundSlot = depositOutputs = toTxContext <$> toList deposited - depositScript = fromPlutusScript @PlutusScriptV3 Deposit.validatorScript + depositScript = fromPlutusScript @PlutusScriptV3 depositValidatorScript data RecoverObservation = RecoverObservation { headId :: HeadId @@ -62,7 +63,7 @@ observeRecoverTx networkId utxo tx = do let inputUTxO = resolveInputsUTxO utxo tx (TxIn depositTxId _, depositOut) <- findTxOutByScript @PlutusScriptV3 inputUTxO depositScript dat <- txOutScriptData $ toTxContext depositOut - Deposit.DepositDatum (headCurrencySymbol, _, onChainDeposits) <- fromScriptData dat + (headCurrencySymbol, _, onChainDeposits) <- fromScriptData dat :: Maybe Deposit.DepositDatum deposits <- do depositedUTxO <- traverse (Commit.deserializeCommit (networkIdToNetwork networkId)) onChainDeposits pure $ UTxO.fromPairs depositedUTxO @@ -80,4 +81,4 @@ observeRecoverTx networkId utxo tx = do ) else Nothing where - depositScript = fromPlutusScript Deposit.validatorScript + depositScript = fromPlutusScript depositValidatorScript diff --git a/hydra-tx/src/Hydra/Tx/Utils.hs b/hydra-tx/src/Hydra/Tx/Utils.hs index e075fecf92a..bd53b730042 100644 --- a/hydra-tx/src/Hydra/Tx/Utils.hs +++ b/hydra-tx/src/Hydra/Tx/Utils.hs @@ -86,3 +86,19 @@ addMetadata (TxMetadata newMetadata) blueprintTx tx = tx & auxDataTxL .~ SJust newAuxData & bodyTxL . auxDataHashTxBodyL .~ SJust (hashTxAuxData newAuxData) + +-- | Type to encapsulate one of the two possible incremental actions or a +-- regular snapshot. This actually signals that our snapshot modeling is likely +-- not ideal but for now we want to keep track of both fields (de/commit) since +-- we might want to support batch de/commits too in the future, but having both fields +-- be Maybe UTxO intruduces a lot of checks if the value is Nothing or mempty. +data IncrementalAction = ToCommit UTxO | ToDecommit UTxO | NoThing deriving (Eq, Show) + +setIncrementalActionMaybe :: Maybe UTxO -> Maybe UTxO -> Maybe IncrementalAction +setIncrementalActionMaybe utxoToCommit utxoToDecommit = + case (utxoToCommit, utxoToDecommit) of + (Just _, Just _) -> Nothing + (Just _, Nothing) -> + ToCommit <$> utxoToCommit + (Nothing, Just _) -> ToDecommit <$> utxoToDecommit + (Nothing, Nothing) -> Just NoThing diff --git a/hydra-tx/test/Hydra/Tx/Contract/Close/CloseInitial.hs b/hydra-tx/test/Hydra/Tx/Contract/Close/CloseInitial.hs index b54e34f6a57..c57941f967d 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Close/CloseInitial.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Close/CloseInitial.hs @@ -16,6 +16,7 @@ import Hydra.Plutus.Extras (posixFromUTCTime) import Hydra.Plutus.Orphans () import Hydra.Tx ( ConfirmedSnapshot (..), + Snapshot (utxoToCommit, utxoToDecommit), SnapshotVersion, hashUTxO, mkHeadId, @@ -33,6 +34,8 @@ import Hydra.Tx.Contract.Close.Healthy ( healthyUTxO, somePartyCardanoVerificationKey, ) +import Hydra.Tx.Snapshot (getSnapshot) +import Hydra.Tx.Utils (IncrementalAction (..), setIncrementalActionMaybe) import PlutusLedgerApi.V3 (POSIXTime, toBuiltin) import Test.Hydra.Tx.Fixture qualified as Fixture import Test.Hydra.Tx.Gen (genScriptRegistry) @@ -65,6 +68,11 @@ healthyCloseInitialTx = healthyCloseLowerBoundSlot healthyCloseUpperBoundPointInTime openThreadOutput + incrementalAction + + incrementalAction = + fromMaybe NoThing $ + setIncrementalActionMaybe (utxoToCommit $ getSnapshot closingSnapshot) (utxoToDecommit $ getSnapshot closingSnapshot) initialDatum :: TxOutDatum CtxUTxO initialDatum = toUTxOContext (mkTxOutDatumInline healthyInitialOpenDatum) diff --git a/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUnused.hs b/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUnused.hs index 37dc64bae5d..21389f5a05a 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUnused.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUnused.hs @@ -33,7 +33,9 @@ import Hydra.Tx.Contract.Close.Healthy ( somePartyCardanoVerificationKey, ) import Hydra.Tx.Crypto (MultiSignature, toPlutusSignatures) +import Hydra.Tx.Snapshot (getSnapshot) import Hydra.Tx.Snapshot qualified as Snapshot +import Hydra.Tx.Utils (IncrementalAction (..), setIncrementalActionMaybe) import PlutusLedgerApi.V1.Time (DiffMilliSeconds (..), fromMilliSeconds) import PlutusLedgerApi.V3 (POSIXTime, PubKeyHash (PubKeyHash), toBuiltin) import Test.Hydra.Tx.Fixture qualified as Fixture @@ -53,8 +55,8 @@ import Test.Hydra.Tx.Mutation ( replaceContestationDeadline, replaceContestationPeriod, replaceContesters, - replaceDeltaUTxOHash, replaceHeadId, + replaceOmegaUTxOHash, replaceParties, replacePolicyIdWith, replaceSnapshotNumber, @@ -82,11 +84,17 @@ healthyCloseCurrentTx = somePartyCardanoVerificationKey (mkHeadId Fixture.testPolicyId) healthyCurrentSnapshotVersion - (healthyConfirmedSnapshot healthyCurrentSnapshot) + closeUnusedSnapshot healthyCloseLowerBoundSlot healthyCloseUpperBoundPointInTime openThreadOutput + incrementalAction + closeUnusedSnapshot = healthyConfirmedSnapshot healthyCurrentSnapshot + + incrementalAction = + fromMaybe NoThing $ + setIncrementalActionMaybe (utxoToCommit $ getSnapshot closeUnusedSnapshot) (utxoToDecommit $ getSnapshot closeUnusedSnapshot) datum = toUTxOContext $ mkTxOutDatumInline healthyCurrentOpenDatum lookupUTxO = @@ -212,7 +220,7 @@ genCloseCurrentMutation (tx, _utxo) = pure $ ChangeOutput 0 (modifyTxOutAddress (const mutatedAddress) headTxOut) , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateSignatureButNotSnapshotNumber . ChangeHeadRedeemer <$> do signature <- toPlutusSignatures <$> (arbitrary :: Gen (MultiSignature (Snapshot Tx))) - pure $ Head.Close Head.CloseUnused{signature} + pure $ Head.Close Head.CloseUnusedDec{signature} , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateSnapshotNumberButNotSignature <$> do mutatedSnapshotNumber <- arbitrarySizedNatural `suchThat` (> healthyCurrentSnapshotNumber) pure $ ChangeOutput 0 $ modifyInlineDatum (replaceSnapshotNumber $ toInteger mutatedSnapshotNumber) headTxOut @@ -277,7 +285,7 @@ genCloseCurrentMutation (tx, _utxo) = ( Just $ toScriptData ( Head.Close - Head.CloseUnused + Head.CloseUnusedDec { signature = toPlutusSignatures $ healthySignature healthyCurrentSnapshot } ) @@ -296,7 +304,7 @@ genCloseCurrentMutation (tx, _utxo) = pure $ ChangeOutput 0 (headTxOut{txOutValue = newValue}) , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateCloseUTxOToDecommitHash . ChangeOutput 0 <$> do mutatedHash <- arbitrary `suchThat` (/= (toBuiltin $ hashUTxO @Tx healthySplitUTxOToDecommit)) - pure $ headTxOut & modifyInlineDatum (replaceDeltaUTxOHash mutatedHash) + pure $ headTxOut & modifyInlineDatum (replaceOmegaUTxOHash mutatedHash) ] where genOversizedTransactionValidity = do diff --git a/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUsed.hs b/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUsed.hs index 390e9ef1a48..a52cffaae0d 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUsed.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Close/CloseUsed.hs @@ -40,9 +40,11 @@ import Hydra.Tx.Contract.Close.Healthy ( healthyOpenHeadTxOut, healthySignature, healthySplitUTxOInHead, + healthySplitUTxOToDecommit, somePartyCardanoVerificationKey, ) import Hydra.Tx.Crypto (MultiSignature (..), toPlutusSignatures) +import Hydra.Tx.Utils (IncrementalAction (..), setIncrementalActionMaybe) import PlutusLedgerApi.V1.Time (DiffMilliSeconds (..), fromMilliSeconds) import PlutusLedgerApi.V3 (POSIXTime, PubKeyHash (PubKeyHash), toBuiltin) import Test.Hydra.Tx.Fixture qualified as Fixture @@ -89,7 +91,7 @@ healthyOutdatedSnapshot = , confirmed = [] , utxo = healthySplitUTxOInHead , utxoToCommit = Nothing - , utxoToDecommit = Nothing -- NOTE: In the `CloseOutdated` case, we expect the utxoToDecommit to be Nothing + , utxoToDecommit = Just healthySplitUTxOToDecommit } healthyOutdatedOpenDatum :: Head.State @@ -120,10 +122,17 @@ healthyCloseOutdatedTx = somePartyCardanoVerificationKey (mkHeadId Fixture.testPolicyId) healthyOpenStateVersion - (healthyConfirmedSnapshot healthyOutdatedSnapshot) + closeUsedSnapshot healthyCloseLowerBoundSlot healthyCloseUpperBoundPointInTime openThreadOutput + incrementalAction + + closeUsedSnapshot = healthyConfirmedSnapshot healthyOutdatedSnapshot + + incrementalAction = + fromMaybe NoThing $ + setIncrementalActionMaybe (utxoToCommit $ getSnapshot closeUsedSnapshot) (utxoToDecommit $ getSnapshot closeUsedSnapshot) lookupUTxO :: UTxO' (TxOut CtxUTxO) lookupUTxO = @@ -236,17 +245,17 @@ genCloseOutdatedMutation (tx, _utxo) = [ SomeMutation (pure $ toErrorCode NotPayingToHead) NotContinueContract <$> do mutatedAddress <- genAddressInEra Fixture.testNetworkId pure $ ChangeOutput 0 (modifyTxOutAddress (const mutatedAddress) headTxOut) - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateSignatureButNotSnapshotNumber . ChangeHeadRedeemer <$> do + , SomeMutation (pure $ toErrorCode FailedCloseUnusedDec) MutateSignatureButNotSnapshotNumber . ChangeHeadRedeemer <$> do signature <- toPlutusSignatures <$> (arbitrary :: Gen (MultiSignature (Snapshot Tx))) - pure $ Head.Close Head.CloseUnused{signature} - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateSnapshotNumberButNotSignature <$> do + pure $ Head.Close Head.CloseUnusedDec{signature} + , SomeMutation (pure $ toErrorCode FailedCloseUsedDec) MutateSnapshotNumberButNotSignature <$> do mutatedSnapshotNumber <- arbitrarySizedNatural `suchThat` (> healthyOutdatedSnapshotNumber) pure $ ChangeOutput 0 $ modifyInlineDatum (replaceSnapshotNumber $ toInteger mutatedSnapshotNumber) headTxOut , -- Last known open state version is recorded in closed state SomeMutation (pure $ toErrorCode MustNotChangeVersion) MutateSnapshotVersion <$> do mutatedSnapshotVersion <- arbitrarySizedNatural `suchThat` (/= healthyOpenStateVersion) pure $ ChangeOutput 0 $ modifyInlineDatum (replaceSnapshotVersion $ toInteger mutatedSnapshotVersion) headTxOut - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) SnapshotNotSignedByAllParties <$> do + , SomeMutation (pure $ toErrorCode FailedCloseUsedDec) SnapshotNotSignedByAllParties <$> do mutatedParties <- arbitrary `suchThat` (/= healthyOnChainParties) pure . ChangeInputHeadDatum $ replaceParties mutatedParties healthyOutdatedOpenDatum , SomeMutation (pure $ toErrorCode ChangedParameters) MutatePartiesInOutput <$> do @@ -267,7 +276,7 @@ genCloseOutdatedMutation (tx, _utxo) = otherSigners <- listOf1 (genVerificationKey `suchThat` (/= somePartyCardanoVerificationKey)) let signerAndOthers = somePartyCardanoVerificationKey : otherSigners pure $ ChangeRequiredSigners (verificationKeyHash <$> signerAndOthers) - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateCloseUTxOHash . ChangeOutput 0 <$> do + , SomeMutation (pure $ toErrorCode FailedCloseUsedDec) MutateCloseUTxOHash . ChangeOutput 0 <$> do mutatedUTxOHash <- (toBuiltin <$> genHash) `suchThat` (/= healthyCloseUTxOHash) pure $ modifyInlineDatum (replaceUTxOHash mutatedUTxOHash) headTxOut , -- Correct contestation deadline is set @@ -303,7 +312,7 @@ genCloseOutdatedMutation (tx, _utxo) = ( Just $ toScriptData ( Head.Close - Head.CloseUnused + Head.CloseUnusedDec { signature = toPlutusSignatures $ healthySignature healthyOutdatedSnapshot @@ -323,7 +332,7 @@ genCloseOutdatedMutation (tx, _utxo) = newValue <- genValue pure $ ChangeOutput 0 (headTxOut{txOutValue = newValue}) , -- XXX: The following mutations are quite redundant - SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateCloseUTxOToDecommitHash . ChangeHeadRedeemer <$> do + SomeMutation (pure $ toErrorCode FailedCloseUsedDec) MutateCloseUTxOToDecommitHash . ChangeHeadRedeemer <$> do -- Close redeemer contains the hash of a decommit utxo. If we -- change it should cause invalid signature error. let healthyUTxOToDecommitHash = @@ -334,11 +343,11 @@ genCloseOutdatedMutation (tx, _utxo) = mutatedUTxOHash <- genHash `suchThat` (/= healthyUTxOToDecommitHash) pure $ Head.Close - Head.CloseUsed + Head.CloseUsedDec { signature = toPlutusSignatures $ signatures healthyOutdatedConfirmedClosingSnapshot , alreadyDecommittedUTxOHash = toBuiltin mutatedUTxOHash } - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateCloseSignatures . ChangeHeadRedeemer <$> do + , SomeMutation (pure $ toErrorCode FailedCloseUsedDec) MutateCloseSignatures . ChangeHeadRedeemer <$> do -- Close redeemer contains the signatures. If we change them should -- cause invalid signature error. let healthyUTxOToDecommitHash = @@ -349,15 +358,15 @@ genCloseOutdatedMutation (tx, _utxo) = signature <- toPlutusSignatures <$> (arbitrary `suchThat` (/= signatures healthyOutdatedConfirmedClosingSnapshot)) pure $ Head.Close - Head.CloseUsed + Head.CloseUsedDec { signature , alreadyDecommittedUTxOHash = toBuiltin healthyUTxOToDecommitHash } - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateCloseType . ChangeHeadRedeemer <$> do + , SomeMutation (pure $ toErrorCode FailedCloseUnusedDec) MutateCloseType . ChangeHeadRedeemer <$> do -- Close redeemer claims whether the snapshot is valid against current -- or previous version. If we change it then it should cause invalid -- signature error. - pure $ Head.Close Head.CloseUnused{signature = toPlutusSignatures $ signatures healthyOutdatedConfirmedClosingSnapshot} + pure $ Head.Close Head.CloseUnusedDec{signature = toPlutusSignatures $ signatures healthyOutdatedConfirmedClosingSnapshot} ] where genOversizedTransactionValidity = do diff --git a/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestCurrent.hs b/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestCurrent.hs index 601f7d3503f..64828b6092d 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestCurrent.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestCurrent.hs @@ -8,219 +8,64 @@ import Hydra.Prelude hiding (label) import Data.Maybe (fromJust) -import Cardano.Api.UTxO as UTxO import Hydra.Contract.Error (toErrorCode) import Hydra.Contract.HeadError (HeadError (..)) import Hydra.Contract.HeadState qualified as Head import Hydra.Contract.HeadTokens (headPolicyId) import Hydra.Contract.Util (UtilError (MintingOrBurningIsForbidden)) -import Hydra.Data.ContestationPeriod qualified as OnChain import Hydra.Data.Party (partyFromVerificationKeyBytes) -import Hydra.Data.Party qualified as OnChain import Hydra.Ledger.Cardano.Time (slotNoToUTCTime) import Hydra.Plutus.Extras (posixFromUTCTime) import Hydra.Plutus.Orphans () -import Hydra.Tx (registryUTxO) -import Hydra.Tx.Contest (ClosedThreadOutput (..), contestTx) -import Hydra.Tx.ContestationPeriod (ContestationPeriod, fromChain) -import Hydra.Tx.Crypto (HydraKey, MultiSignature, aggregate, sign, toPlutusSignatures) -import Hydra.Tx.HeadId (mkHeadId) -import Hydra.Tx.Init (mkHeadOutput) -import Hydra.Tx.IsTx (hashUTxO) -import Hydra.Tx.Party (Party, deriveParty, partyToChain) -import Hydra.Tx.Snapshot (Snapshot (..), SnapshotNumber, SnapshotVersion) -import Hydra.Tx.Utils ( - splitUTxO, +import Hydra.Tx.Contract.Contest.Healthy ( + healthyCloseSnapshotVersion, + healthyClosedHeadTxIn, + healthyClosedHeadTxOut, + healthyClosedState, + healthyContestSnapshotNumber, + healthyContestUTxOHash, + healthyContestUTxOToDecommitHash, + healthyContestationDeadline, + healthyContesterVerificationKey, + healthyOnChainContestationPeriod, + healthyOnChainParties, + healthyParticipants, + healthyParties, + healthySignature, ) -import PlutusLedgerApi.V3 (BuiltinByteString, toBuiltin) +import Hydra.Tx.Crypto (MultiSignature, toPlutusSignatures) +import Hydra.Tx.Snapshot (Snapshot (..)) +import PlutusLedgerApi.V3 (toBuiltin) import PlutusLedgerApi.V3 qualified as Plutus -import Test.Hydra.Tx.Fixture (aliceSk, bobSk, carolSk, slotLength, systemStart, testNetworkId, testPolicyId) +import Test.Hydra.Tx.Fixture (slotLength, systemStart, testNetworkId, testPolicyId) import Test.Hydra.Tx.Fixture qualified as Fixture import Test.Hydra.Tx.Gen ( genAddressInEra, - genForParty, genHash, genMintedOrBurnedValue, - genOneUTxOFor, - genScriptRegistry, genValue, genVerificationKey, ) import Test.Hydra.Tx.Mutation ( Mutation (..), SomeMutation (..), - addParticipationTokens, changeMintedTokens, modifyInlineDatum, replaceContestationDeadline, replaceContestationPeriod, replaceContesters, - replaceDeltaUTxOHash, replaceHeadId, + replaceOmegaUTxOHash, replaceParties, replacePolicyIdWith, replaceSnapshotNumber, replaceSnapshotVersion, replaceUTxOHash, ) -import Test.QuickCheck (arbitrarySizedNatural, elements, listOf, listOf1, oneof, resize, suchThat, vectorOf) +import Test.QuickCheck (arbitrarySizedNatural, listOf, listOf1, oneof, resize, suchThat, vectorOf) import Test.QuickCheck.Gen (choose) import Test.QuickCheck.Instances () --- --- ContestTx --- - --- | Healthy contest tx where the contester is the first one to contest and --- correctly pushing out the deadline by the contestation period. -healthyContestTx :: (Tx, UTxO) -healthyContestTx = - (tx, lookupUTxO) - where - lookupUTxO = - UTxO.singleton (healthyClosedHeadTxIn, healthyClosedHeadTxOut) - <> registryUTxO scriptRegistry - - tx = - contestTx - scriptRegistry - healthyContesterVerificationKey - (mkHeadId testPolicyId) - healthyContestationPeriod - healthyCloseSnapshotVersion - healthyContestSnapshot - (healthySignature healthyContestSnapshotNumber) - (healthySlotNo, slotNoToUTCTime systemStart slotLength healthySlotNo) - closedThreadOutput - - scriptRegistry = genScriptRegistry `generateWith` 42 - - closedThreadOutput = - ClosedThreadOutput - { closedThreadUTxO = (healthyClosedHeadTxIn, healthyClosedHeadTxOut) - , closedParties = - healthyOnChainParties - , closedContestationDeadline = posixFromUTCTime healthyContestationDeadline - , closedContesters = [] - } - -healthyContestSnapshotNumber :: SnapshotNumber -healthyContestSnapshotNumber = 4 - -healthyCloseSnapshotVersion :: SnapshotVersion -healthyCloseSnapshotVersion = 4 - -healthyClosedUTxO :: UTxO -healthyClosedUTxO = - genOneUTxOFor healthyContesterVerificationKey `generateWith` 42 - -healthyContestUTxO :: UTxO -healthyContestUTxO = - (genOneUTxOFor healthyContesterVerificationKey `suchThat` (/= healthyClosedUTxO)) - `generateWith` 42 - -splittedContestUTxO :: (UTxO, UTxO) -splittedContestUTxO = splitUTxO healthyContestUTxO - -splitUTxOInHead :: UTxO -splitUTxOInHead = fst splittedContestUTxO - -splitUTxOToDecommit :: UTxO -splitUTxOToDecommit = snd splittedContestUTxO - -healthyContestSnapshot :: Snapshot Tx -healthyContestSnapshot = - Snapshot - { headId = mkHeadId testPolicyId - , number = healthyContestSnapshotNumber - , utxo = splitUTxOInHead - , confirmed = [] - , utxoToCommit = Nothing - , utxoToDecommit = Just splitUTxOToDecommit - , version = healthyCloseSnapshotVersion - } - -healthyClosedState :: Head.State -healthyClosedState = - Head.Closed - Head.ClosedDatum - { snapshotNumber = fromIntegral healthyClosedSnapshotNumber - , utxoHash = healthyClosedUTxOHash - , deltaUTxOHash = mempty - , parties = healthyOnChainParties - , contestationDeadline = posixFromUTCTime healthyContestationDeadline - , contestationPeriod = healthyOnChainContestationPeriod - , headId = toPlutusCurrencySymbol testPolicyId - , contesters = [] - , version = toInteger healthyCloseSnapshotVersion - } - -healthyContestUTxOHash :: BuiltinByteString -healthyContestUTxOHash = - toBuiltin $ hashUTxO @Tx splitUTxOInHead - -healthyContestUTxOToDecommitHash :: BuiltinByteString -healthyContestUTxOToDecommitHash = - toBuiltin $ hashUTxO @Tx splitUTxOToDecommit - -healthyClosedUTxOHash :: BuiltinByteString -healthyClosedUTxOHash = - toBuiltin $ hashUTxO @Tx healthyClosedUTxO - -healthyClosedSnapshotNumber :: SnapshotNumber -healthyClosedSnapshotNumber = 3 - -healthySlotNo :: SlotNo -healthySlotNo = arbitrary `generateWith` 42 - -healthyClosedHeadTxIn :: TxIn -healthyClosedHeadTxIn = generateWith arbitrary 42 - -healthyClosedHeadTxOut :: TxOut CtxUTxO -healthyClosedHeadTxOut = - mkHeadOutput testNetworkId testPolicyId headTxOutDatum - & addParticipationTokens healthyParticipants - where - headTxOutDatum = toUTxOContext (mkTxOutDatumInline healthyClosedState) - -healthyOnChainContestationPeriod :: OnChain.ContestationPeriod -healthyOnChainContestationPeriod = OnChain.contestationPeriodFromDiffTime $ fromInteger healthyContestationPeriodSeconds - -healthyContestationPeriod :: ContestationPeriod -healthyContestationPeriod = fromChain healthyOnChainContestationPeriod - -healthyContestationPeriodSeconds :: Integer -healthyContestationPeriodSeconds = 10 - -healthyParticipants :: [VerificationKey PaymentKey] -healthyParticipants = - genForParty genVerificationKey <$> healthyParties - -healthyContesterVerificationKey :: VerificationKey PaymentKey -healthyContesterVerificationKey = - elements healthyParticipants `generateWith` 42 - -healthySigningKeys :: [SigningKey HydraKey] -healthySigningKeys = [aliceSk, bobSk, carolSk] - -healthyParties :: [Party] -healthyParties = deriveParty <$> healthySigningKeys - -healthyOnChainParties :: [OnChain.Party] -healthyOnChainParties = partyToChain <$> healthyParties - -healthySignature :: SnapshotNumber -> MultiSignature (Snapshot Tx) -healthySignature number = - aggregate [sign sk snapshot | sk <- healthySigningKeys] - where - snapshot = healthyContestSnapshot{number} - -healthyContestationDeadline :: UTCTime -healthyContestationDeadline = - addUTCTime - (fromInteger healthyContestationPeriodSeconds) - (slotNoToUTCTime systemStart slotLength healthySlotNo) - -- FIXME: Should try to mutate the 'closedAt' recorded time to something else data ContestMutation = -- | Ensures collectCom does not allow any output address but νHead. @@ -306,7 +151,7 @@ genContestMutation (tx, _utxo) = [ SomeMutation (pure $ toErrorCode NotPayingToHead) NotContinueContract <$> do mutatedAddress <- genAddressInEra testNetworkId pure $ ChangeOutput 0 (modifyTxOutAddress (const mutatedAddress) headTxOut) - , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) MutateSignatureButNotSnapshotNumber . ChangeHeadRedeemer <$> do + , SomeMutation (pure $ toErrorCode FailedContestCurrent) MutateSignatureButNotSnapshotNumber . ChangeHeadRedeemer <$> do mutatedSignature <- arbitrary :: Gen (MultiSignature (Snapshot Tx)) pure $ Head.Contest @@ -337,6 +182,27 @@ genContestMutation (tx, _utxo) = , SomeMutation (pure $ toErrorCode SignerIsNotAParticipant) MutateRequiredSigner <$> do newSigner <- verificationKeyHash <$> genVerificationKey `suchThat` (/= healthyContesterVerificationKey) pure $ ChangeRequiredSigners [newSigner] + , -- REVIEW: This is a bit confusing and not giving much value. Maybe we can remove this. + -- This also seems to be covered by MutateRequiredSigner + SomeMutation (pure $ toErrorCode FailedContestCurrent) ContestFromDifferentHead <$> do + otherHeadId <- headPolicyId <$> arbitrary `suchThat` (/= healthyClosedHeadTxIn) + pure $ + Changes + [ ChangeOutput 0 (replacePolicyIdWith testPolicyId otherHeadId headTxOut) + , ChangeInput + healthyClosedHeadTxIn + (replacePolicyIdWith testPolicyId otherHeadId healthyClosedHeadTxOut) + ( Just $ + toScriptData + ( Head.Contest + Head.ContestCurrent + { signature = + toPlutusSignatures $ + healthySignature healthyContestSnapshotNumber + } + ) + ) + ] , SomeMutation (pure $ toErrorCode NoSigners) MutateNoRequiredSigner <$> do pure $ ChangeRequiredSigners [] , SomeMutation (pure $ toErrorCode TooManySigners) MutateMultipleRequiredSigner <$> do @@ -353,7 +219,7 @@ genContestMutation (tx, _utxo) = mutatedUTxOHash <- arbitrary `suchThat` (/= healthyContestUTxOToDecommitHash) pure $ modifyInlineDatum - (replaceDeltaUTxOHash mutatedUTxOHash) + (replaceOmegaUTxOHash mutatedUTxOHash) headTxOut , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) SnapshotNotSignedByAllParties . ChangeInputHeadDatum <$> do mutatedParties <- arbitrary `suchThat` (/= healthyOnChainParties) @@ -363,27 +229,6 @@ genContestMutation (tx, _utxo) = lb <- arbitrary ub <- TxValidityUpperBound <$> arbitrary `suchThat` slotOverContestationDeadline pure (lb, ub) - , -- REVIEW: This is a bit confusing and not giving much value. Maybe we can remove this. - -- This also seems to be covered by MutateRequiredSigner - SomeMutation (pure $ toErrorCode SignerIsNotAParticipant) ContestFromDifferentHead <$> do - otherHeadId <- headPolicyId <$> arbitrary `suchThat` (/= healthyClosedHeadTxIn) - pure $ - Changes - [ ChangeOutput 0 (replacePolicyIdWith testPolicyId otherHeadId headTxOut) - , ChangeInput - healthyClosedHeadTxIn - (replacePolicyIdWith testPolicyId otherHeadId healthyClosedHeadTxOut) - ( Just $ - toScriptData - ( Head.Contest - Head.ContestCurrent - { signature = - toPlutusSignatures $ - healthySignature healthyContestSnapshotNumber - } - ) - ) - ] , SomeMutation (pure $ toErrorCode MintingOrBurningIsForbidden) MutateTokenMintingOrBurning <$> (changeMintedTokens tx =<< genMintedOrBurnedValue) , SomeMutation (pure $ toErrorCode SignerAlreadyContested) MutateInputContesters . ChangeInputHeadDatum <$> do diff --git a/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestDec.hs b/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestDec.hs new file mode 100644 index 00000000000..9516f640343 --- /dev/null +++ b/hydra-tx/test/Hydra/Tx/Contract/Contest/ContestDec.hs @@ -0,0 +1,81 @@ +{-# LANGUAGE DuplicateRecordFields #-} + +module Hydra.Tx.Contract.Contest.ContestDec where + +import Hydra.Cardano.Api +import Hydra.Prelude hiding (label) + +import Data.Maybe (fromJust) + +import Hydra.Contract.Error (toErrorCode) +import Hydra.Contract.HeadError (HeadError (..)) +import Hydra.Contract.HeadState qualified as Head +import Hydra.Tx.Crypto (MultiSignature, toPlutusSignatures) + +import Hydra.Tx (Snapshot) +import Hydra.Tx.Contract.Contest.Healthy ( + healthyCloseSnapshotVersion, + healthyContestSnapshotNumber, + healthySignature, + ) +import Test.Hydra.Tx.Mutation ( + Mutation (..), + SomeMutation (..), + modifyInlineDatum, + replaceOmegaUTxOHash, + replaceSnapshotVersion, + ) +import Test.QuickCheck (arbitrarySizedNatural, oneof, suchThat) +import Test.QuickCheck.Instances () + +data ContestDecMutation + = ContestUsedDecAlterRedeemerDecommitHash + | ContestUnusedDecAlterRedeemerDecommitHash + | ContestUsedDecAlterDatumomegaUTxOHash + | ContestUnusedDecAlterDatumomegaUTxOHash + | ContestUsedDecMutateSnapshotVersion + | ContestUnusedDecMutateSnapshotVersion + deriving stock (Generic, Show, Enum, Bounded) + +genContestDecMutation :: (Tx, UTxO) -> Gen SomeMutation +genContestDecMutation (tx, _utxo) = + oneof + [ SomeMutation (pure $ toErrorCode FailedContestUsedDec) ContestUsedDecAlterRedeemerDecommitHash <$> do + pure $ + ChangeHeadRedeemer $ + Head.Contest + Head.ContestUsedDec + { signature = toPlutusSignatures (healthySignature healthyContestSnapshotNumber) + , alreadyDecommittedUTxOHash = mempty + } + , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) ContestUnusedDecAlterRedeemerDecommitHash . ChangeHeadRedeemer <$> do + mutatedSignature <- arbitrary :: Gen (MultiSignature (Snapshot Tx)) + pure $ + Head.Contest + Head.ContestUnusedDec + { signature = toPlutusSignatures mutatedSignature + } + , SomeMutation (pure $ toErrorCode FailedContestUsedDec) ContestUsedDecAlterRedeemerDecommitHash <$> do + mutatedHash <- arbitrary `suchThat` (/= mempty) + pure $ + ChangeHeadRedeemer $ + Head.Contest + Head.ContestUsedDec + { signature = toPlutusSignatures (healthySignature healthyContestSnapshotNumber) + , alreadyDecommittedUTxOHash = mutatedHash + } + , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) ContestUsedDecAlterDatumomegaUTxOHash . ChangeOutput 0 <$> do + mutatedHash <- arbitrary `suchThat` (/= mempty) + pure $ headTxOut & modifyInlineDatum (replaceOmegaUTxOHash mutatedHash) + , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) ContestUnusedDecAlterDatumomegaUTxOHash . ChangeOutput 0 <$> do + mutatedHash <- arbitrary `suchThat` (/= mempty) + pure $ headTxOut & modifyInlineDatum (replaceOmegaUTxOHash mutatedHash) + , SomeMutation (pure $ toErrorCode MustNotChangeVersion) ContestUsedDecMutateSnapshotVersion <$> do + mutatedSnapshotVersion <- arbitrarySizedNatural `suchThat` (/= healthyCloseSnapshotVersion) + pure $ ChangeOutput 0 $ modifyInlineDatum (replaceSnapshotVersion $ toInteger mutatedSnapshotVersion) headTxOut + , SomeMutation (pure $ toErrorCode MustNotChangeVersion) ContestUnusedDecMutateSnapshotVersion <$> do + mutatedSnapshotVersion <- arbitrarySizedNatural `suchThat` (/= healthyCloseSnapshotVersion) + pure $ ChangeOutput 0 $ modifyInlineDatum (replaceSnapshotVersion $ toInteger mutatedSnapshotVersion) headTxOut + ] + where + headTxOut = fromJust $ txOuts' tx !!? 0 diff --git a/hydra-tx/test/Hydra/Tx/Contract/Contest/Healthy.hs b/hydra-tx/test/Hydra/Tx/Contract/Contest/Healthy.hs new file mode 100644 index 00000000000..1343aed77b3 --- /dev/null +++ b/hydra-tx/test/Hydra/Tx/Contract/Contest/Healthy.hs @@ -0,0 +1,198 @@ +{-# LANGUAGE DuplicateRecordFields #-} + +module Hydra.Tx.Contract.Contest.Healthy where + +import Hydra.Cardano.Api +import Hydra.Prelude hiding (label) + +import Cardano.Api.UTxO as UTxO +import Hydra.Contract.HeadState qualified as Head +import Hydra.Data.ContestationPeriod qualified as OnChain +import Hydra.Data.Party qualified as OnChain +import Hydra.Ledger.Cardano.Time (slotNoToUTCTime) +import Hydra.Plutus.Extras (posixFromUTCTime) +import Hydra.Plutus.Orphans () +import Hydra.Tx (registryUTxO) +import Hydra.Tx.Contest (ClosedThreadOutput (..), contestTx) +import Hydra.Tx.ContestationPeriod (ContestationPeriod, fromChain) +import Hydra.Tx.Crypto (HydraKey, MultiSignature, aggregate, sign) +import Hydra.Tx.HeadId (mkHeadId) +import Hydra.Tx.Init (mkHeadOutput) +import Hydra.Tx.IsTx (hashUTxO) +import Hydra.Tx.Party (Party, deriveParty, partyToChain) +import Hydra.Tx.Snapshot (Snapshot (..), SnapshotNumber, SnapshotVersion) +import Hydra.Tx.Utils ( + IncrementalAction (..), + setIncrementalActionMaybe, + splitUTxO, + ) +import PlutusLedgerApi.V2 (BuiltinByteString, toBuiltin) +import Test.Hydra.Tx.Fixture (aliceSk, bobSk, carolSk, slotLength, systemStart, testNetworkId, testPolicyId) +import Test.Hydra.Tx.Gen ( + genForParty, + genOneUTxOFor, + genScriptRegistry, + genVerificationKey, + ) +import Test.Hydra.Tx.Mutation ( + addParticipationTokens, + ) +import Test.QuickCheck (elements, suchThat) +import Test.QuickCheck.Instances () + +-- +-- ContestTx +-- + +-- | Healthy contest tx where the contester is the first one to contest and +-- correctly pushing out the deadline by the contestation period. +healthyContestTx :: (Tx, UTxO) +healthyContestTx = + (tx, lookupUTxO) + where + lookupUTxO = + UTxO.singleton (healthyClosedHeadTxIn, healthyClosedHeadTxOut) + <> registryUTxO scriptRegistry + + tx = + contestTx + scriptRegistry + healthyContesterVerificationKey + (mkHeadId testPolicyId) + healthyContestationPeriod + healthyCloseSnapshotVersion + healthyContestSnapshot + (healthySignature healthyContestSnapshotNumber) + (healthySlotNo, slotNoToUTCTime systemStart slotLength healthySlotNo) + closedThreadOutput + incrementalAction + + incrementalAction = fromMaybe NoThing $ setIncrementalActionMaybe (utxoToCommit healthyContestSnapshot) (utxoToDecommit healthyContestSnapshot) + scriptRegistry = genScriptRegistry `generateWith` 42 + + closedThreadOutput = + ClosedThreadOutput + { closedThreadUTxO = (healthyClosedHeadTxIn, healthyClosedHeadTxOut) + , closedParties = + healthyOnChainParties + , closedContestationDeadline = posixFromUTCTime healthyContestationDeadline + , closedContesters = [] + } + +healthyContestSnapshotNumber :: SnapshotNumber +healthyContestSnapshotNumber = 4 + +healthyCloseSnapshotVersion :: SnapshotVersion +healthyCloseSnapshotVersion = 4 + +healthyClosedUTxO :: UTxO +healthyClosedUTxO = + genOneUTxOFor healthyContesterVerificationKey `generateWith` 42 + +healthyContestUTxO :: UTxO +healthyContestUTxO = + (genOneUTxOFor healthyContesterVerificationKey `suchThat` (/= healthyClosedUTxO)) + `generateWith` 42 + +splittedContestUTxO :: (UTxO, UTxO) +splittedContestUTxO = splitUTxO healthyContestUTxO + +splitUTxOInHead :: UTxO +splitUTxOInHead = fst splittedContestUTxO + +splitUTxOToDecommit :: UTxO +splitUTxOToDecommit = snd splittedContestUTxO + +healthyContestSnapshot :: Snapshot Tx +healthyContestSnapshot = + Snapshot + { headId = mkHeadId testPolicyId + , number = healthyContestSnapshotNumber + , utxo = splitUTxOInHead + , confirmed = [] + , utxoToCommit = Nothing + , utxoToDecommit = Just splitUTxOToDecommit + , version = healthyCloseSnapshotVersion + } + +healthyClosedState :: Head.State +healthyClosedState = + Head.Closed + Head.ClosedDatum + { snapshotNumber = fromIntegral healthyClosedSnapshotNumber + , utxoHash = healthyClosedUTxOHash + , alphaUTxOHash = mempty + , omegaUTxOHash = mempty + , parties = healthyOnChainParties + , contestationDeadline = posixFromUTCTime healthyContestationDeadline + , contestationPeriod = healthyOnChainContestationPeriod + , headId = toPlutusCurrencySymbol testPolicyId + , contesters = [] + , version = toInteger healthyCloseSnapshotVersion + } + +healthyContestUTxOHash :: BuiltinByteString +healthyContestUTxOHash = + toBuiltin $ hashUTxO @Tx splitUTxOInHead + +healthyContestUTxOToDecommitHash :: BuiltinByteString +healthyContestUTxOToDecommitHash = + toBuiltin $ hashUTxO @Tx splitUTxOToDecommit + +healthyClosedUTxOHash :: BuiltinByteString +healthyClosedUTxOHash = + toBuiltin $ hashUTxO @Tx healthyClosedUTxO + +healthyClosedSnapshotNumber :: SnapshotNumber +healthyClosedSnapshotNumber = 3 + +healthySlotNo :: SlotNo +healthySlotNo = arbitrary `generateWith` 42 + +healthyClosedHeadTxIn :: TxIn +healthyClosedHeadTxIn = generateWith arbitrary 42 + +healthyClosedHeadTxOut :: TxOut CtxUTxO +healthyClosedHeadTxOut = + mkHeadOutput testNetworkId testPolicyId headTxOutDatum + & addParticipationTokens healthyParticipants + where + headTxOutDatum = toUTxOContext (mkTxOutDatumInline healthyClosedState) + +healthyOnChainContestationPeriod :: OnChain.ContestationPeriod +healthyOnChainContestationPeriod = OnChain.contestationPeriodFromDiffTime $ fromInteger healthyContestationPeriodSeconds + +healthyContestationPeriod :: ContestationPeriod +healthyContestationPeriod = fromChain healthyOnChainContestationPeriod + +healthyContestationPeriodSeconds :: Integer +healthyContestationPeriodSeconds = 10 + +healthyParticipants :: [VerificationKey PaymentKey] +healthyParticipants = + genForParty genVerificationKey <$> healthyParties + +healthyContesterVerificationKey :: VerificationKey PaymentKey +healthyContesterVerificationKey = + elements healthyParticipants `generateWith` 42 + +healthySigningKeys :: [SigningKey HydraKey] +healthySigningKeys = [aliceSk, bobSk, carolSk] + +healthyParties :: [Party] +healthyParties = deriveParty <$> healthySigningKeys + +healthyOnChainParties :: [OnChain.Party] +healthyOnChainParties = partyToChain <$> healthyParties + +healthySignature :: SnapshotNumber -> MultiSignature (Snapshot Tx) +healthySignature number = + aggregate [sign sk snapshot | sk <- healthySigningKeys] + where + snapshot = healthyContestSnapshot{number} + +healthyContestationDeadline :: UTCTime +healthyContestationDeadline = + addUTCTime + (fromInteger healthyContestationPeriodSeconds) + (slotNoToUTCTime systemStart slotLength healthySlotNo) diff --git a/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs b/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs index 0f6ebdf6ac9..d70729529d6 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/ContractSpec.hs @@ -23,7 +23,7 @@ import Hydra.Cardano.Api ( import Hydra.Cardano.Api.Network (networkIdToNetwork) import Hydra.Contract.Commit qualified as Commit import Hydra.Contract.Head (verifySnapshotSignature) -import Hydra.Contract.Head qualified as OnChain +import Hydra.Contract.Util qualified as OnChain import Hydra.Ledger.Cardano.Evaluate (propTransactionEvaluates) import Hydra.Plutus.Orphans () import Hydra.Tx ( @@ -39,7 +39,9 @@ import Hydra.Tx.Contract.Close.CloseUnused (genCloseCurrentMutation, healthyClos import Hydra.Tx.Contract.Close.CloseUsed (genCloseOutdatedMutation, healthyCloseOutdatedTx) import Hydra.Tx.Contract.CollectCom (genCollectComMutation, healthyCollectComTx) import Hydra.Tx.Contract.Commit (genCommitMutation, healthyCommitTx) -import Hydra.Tx.Contract.Contest.ContestCurrent (genContestMutation, healthyContestTx) +import Hydra.Tx.Contract.Contest.ContestCurrent (genContestMutation) +import Hydra.Tx.Contract.Contest.ContestDec (genContestDecMutation) +import Hydra.Tx.Contract.Contest.Healthy (healthyContestTx) import Hydra.Tx.Contract.Decrement (genDecrementMutation, healthyDecrementTx) import Hydra.Tx.Contract.Deposit (healthyDepositTx) import Hydra.Tx.Contract.FanOut (genFanoutMutation, healthyFanoutTx) @@ -132,12 +134,12 @@ spec = parallel $ do propTransactionEvaluates healthyCloseInitialTx prop "does not survive random adversarial mutations" $ propMutation healthyCloseInitialTx genCloseInitialMutation - describe "CloseUnused" $ do + describe "CloseUnusedDec" $ do prop "is healthy" $ propTransactionEvaluates healthyCloseCurrentTx prop "does not survive random adversarial mutations" $ propMutation healthyCloseCurrentTx genCloseCurrentMutation - describe "CloseUsed" $ do + describe "CloseUsedDec" $ do prop "is healthy" $ propTransactionEvaluates healthyCloseOutdatedTx prop "does not survive random adversarial mutations" $ @@ -147,6 +149,12 @@ spec = parallel $ do propTransactionEvaluates healthyContestTx prop "does not survive random adversarial mutations" $ propMutation healthyContestTx genContestMutation + -- TODO: Add CloseAny and ContestCurrent examples too + describe "ContestDec" $ do + prop "is healthy" $ + propTransactionEvaluates healthyContestTx + prop "does not survive random adversarial mutations" $ + propMutation healthyContestTx genContestDecMutation describe "Fanout" $ do prop "is healthy" $ propTransactionEvaluates healthyFanoutTx diff --git a/hydra-tx/test/Hydra/Tx/Contract/Deposit.hs b/hydra-tx/test/Hydra/Tx/Contract/Deposit.hs index bc6bde8b003..da1c1ec5b19 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Deposit.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Deposit.hs @@ -3,12 +3,10 @@ module Hydra.Tx.Contract.Deposit where import Hydra.Cardano.Api import Hydra.Prelude -import Data.Time (UTCTime (..), secondsToDiffTime) -import Data.Time.Calendar (fromGregorian) import Hydra.Tx (mkHeadId) import Hydra.Tx.BlueprintTx (CommitBlueprintTx (..)) import Hydra.Tx.Deposit (depositTx) -import Test.Hydra.Tx.Fixture (testNetworkId, testPolicyId) +import Test.Hydra.Tx.Fixture (depositDeadline, testNetworkId, testPolicyId) import Test.Hydra.Tx.Gen (genUTxOAdaOnlyOfSize) healthyDepositTx :: (Tx, UTxO) @@ -22,8 +20,5 @@ healthyDepositTx = CommitBlueprintTx{blueprintTx = txSpendingUTxO healthyDepositUTxO, lookupUTxO = healthyDepositUTxO} depositDeadline -depositDeadline :: UTCTime -depositDeadline = UTCTime (fromGregorian 2024 15 0) (secondsToDiffTime 0) - healthyDepositUTxO :: UTxO -healthyDepositUTxO = genUTxOAdaOnlyOfSize 5 `generateWith` 42 +healthyDepositUTxO = genUTxOAdaOnlyOfSize 1 `generateWith` 42 diff --git a/hydra-tx/test/Hydra/Tx/Contract/FanOut.hs b/hydra-tx/test/Hydra/Tx/Contract/FanOut.hs index 3828c20e99c..36b7cd66c34 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/FanOut.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/FanOut.hs @@ -41,6 +41,7 @@ healthyFanoutTx = fanoutTx scriptRegistry (fst healthyFanoutSnapshotUTxO) + Nothing (Just $ snd healthyFanoutSnapshotUTxO) (headInput, headOutput) healthySlotNo @@ -84,7 +85,8 @@ healthyFanoutDatum = Head.ClosedDatum { snapshotNumber = 1 , utxoHash = toBuiltin $ hashUTxO @Tx (fst healthyFanoutSnapshotUTxO) - , deltaUTxOHash = toBuiltin $ hashUTxO @Tx (snd healthyFanoutSnapshotUTxO) + , alphaUTxOHash = toBuiltin $ hashUTxO @Tx mempty + , omegaUTxOHash = toBuiltin $ hashUTxO @Tx (snd healthyFanoutSnapshotUTxO) , parties = partyToChain <$> healthyParties , contestationDeadline = posixFromUTCTime healthyContestationDeadline diff --git a/hydra-tx/test/Hydra/Tx/Contract/Increment.hs b/hydra-tx/test/Hydra/Tx/Contract/Increment.hs index 3458de22c26..cfb72b45a97 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Increment.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Increment.hs @@ -5,41 +5,46 @@ module Hydra.Tx.Contract.Increment where import Hydra.Cardano.Api import Hydra.Prelude hiding (label) import Test.Hydra.Tx.Mutation ( - Mutation (ChangeInput), + Mutation (..), SomeMutation (..), addParticipationTokens, modifyInlineDatum, + replaceParties, + replaceSnapshotVersion, ) import Cardano.Api.UTxO qualified as UTxO +import Data.List qualified as List import Data.Maybe (fromJust) -import Hydra.Contract.Deposit (DepositDatum (..), DepositRedeemer (Claim)) -import Hydra.Contract.Deposit qualified as Deposit +import Hydra.Contract.Commit (Commit) +import Hydra.Contract.Deposit (DepositRedeemer (Claim)) import Hydra.Contract.DepositError (DepositError (..)) import Hydra.Contract.Error (toErrorCode) +import Hydra.Contract.HeadError (HeadError (..)) import Hydra.Contract.HeadState qualified as Head import Hydra.Data.Party qualified as OnChain import Hydra.Ledger.Cardano.Time (slotNoFromUTCTime) import Hydra.Plutus.Orphans () import Hydra.Tx.ContestationPeriod (ContestationPeriod, toChain) -import Hydra.Tx.Contract.Deposit (depositDeadline, healthyDepositTx) -import Hydra.Tx.Crypto (HydraKey) -import Hydra.Tx.HeadId (headIdToCurrencySymbol, mkHeadId) +import Hydra.Tx.Contract.Deposit (healthyDepositTx, healthyDepositUTxO) +import Hydra.Tx.Crypto (HydraKey, MultiSignature (..), aggregate, sign, toPlutusSignatures) +import Hydra.Tx.Deposit qualified as Deposit +import Hydra.Tx.HeadId (mkHeadId) import Hydra.Tx.HeadParameters (HeadParameters (..)) import Hydra.Tx.Increment ( incrementTx, ) import Hydra.Tx.Init (mkHeadOutput) -import Hydra.Tx.IsTx (IsTx (hashUTxO, withoutUTxO)) +import Hydra.Tx.IsTx (IsTx (hashUTxO)) import Hydra.Tx.Party (Party, deriveParty, partyToChain) import Hydra.Tx.ScriptRegistry (registryUTxO) import Hydra.Tx.Snapshot (Snapshot (..), SnapshotNumber, SnapshotVersion) -import Hydra.Tx.Utils (adaOnly, splitUTxO) -import PlutusLedgerApi.V3 qualified as Plutus +import Hydra.Tx.Utils (adaOnly) +import PlutusLedgerApi.V2 qualified as Plutus import PlutusTx.Builtins (toBuiltin) -import Test.Hydra.Tx.Fixture (aliceSk, bobSk, carolSk, slotLength, systemStart, testHeadId, testNetworkId, testPolicyId) -import Test.Hydra.Tx.Gen (genForParty, genScriptRegistry, genUTxOSized, genVerificationKey) -import Test.QuickCheck (elements, oneof) +import Test.Hydra.Tx.Fixture (aliceSk, bobSk, carolSk, depositDeadline, slotLength, systemStart, testNetworkId, testPolicyId) +import Test.Hydra.Tx.Gen (genForParty, genScriptRegistry, genUTxOSized, genValue, genVerificationKey) +import Test.QuickCheck (arbitrarySizedNatural, elements, oneof, suchThat) import Test.QuickCheck.Instances () healthyIncrementTx :: (Tx, UTxO) @@ -61,8 +66,7 @@ healthyIncrementTx = healthySnapshot depositUTxO (slotNoFromUTCTime systemStart slotLength depositDeadline) - - depositUTxO = utxoFromTx $ fst healthyDepositTx + healthySignature parameters = HeadParameters @@ -79,6 +83,9 @@ healthyIncrementTx = & addParticipationTokens healthyParticipants & modifyTxOutValue (<> foldMap txOutValue healthyUTxO) +depositUTxO :: UTxO +depositUTxO = utxoFromTx (fst healthyDepositTx) + somePartyCardanoVerificationKey :: VerificationKey PaymentKey somePartyCardanoVerificationKey = elements healthyParticipants `generateWith` 42 @@ -96,6 +103,9 @@ healthyParties = deriveParty <$> healthySigningKeys healthyOnChainParties :: [OnChain.Party] healthyOnChainParties = partyToChain <$> healthyParties +healthySignature :: MultiSignature (Snapshot Tx) +healthySignature = aggregate [sign sk healthySnapshot | sk <- healthySigningKeys] + healthySnapshotNumber :: SnapshotNumber healthySnapshotNumber = 1 @@ -104,24 +114,15 @@ healthySnapshotVersion = 1 healthySnapshot :: Snapshot Tx healthySnapshot = - let (utxoToDecommit', utxo) = splitUTxO healthyUTxO - in Snapshot - { headId = mkHeadId testPolicyId - , version = healthySnapshotVersion - , number = succ healthySnapshotNumber - , confirmed = [] - , utxo - , utxoToCommit = Nothing - , utxoToDecommit = Just utxoToDecommit' - } - -splitDecommitUTxO :: UTxO -> (UTxO, UTxO) -splitDecommitUTxO utxo = - case UTxO.pairs utxo of - [] -> error "empty utxo in splitDecommitUTxO" - (decommit : _rest) -> - let decommitUTxO' = UTxO.fromPairs [decommit] - in (utxo `withoutUTxO` decommitUTxO', decommitUTxO') + Snapshot + { headId = mkHeadId testPolicyId + , version = healthySnapshotVersion + , number = succ healthySnapshotNumber + , confirmed = [] + , utxo = healthyUTxO + , utxoToCommit = Just healthyDepositUTxO + , utxoToDecommit = Nothing + } healthyContestationPeriod :: ContestationPeriod healthyContestationPeriod = @@ -132,15 +133,14 @@ healthyUTxO = adaOnly <$> generateWith (genUTxOSized 3) 42 healthyDatum :: Head.State healthyDatum = - let (_utxoToDecommit', utxo) = splitDecommitUTxO healthyUTxO - in Head.Open - Head.OpenDatum - { utxoHash = toBuiltin $ hashUTxO @Tx utxo - , parties = healthyOnChainParties - , contestationPeriod = toChain healthyContestationPeriod - , headId = toPlutusCurrencySymbol testPolicyId - , version = toInteger healthySnapshotVersion - } + Head.Open + Head.OpenDatum + { utxoHash = toBuiltin $ hashUTxO @Tx healthyUTxO + , parties = healthyOnChainParties + , contestationPeriod = toChain healthyContestationPeriod + , headId = toPlutusCurrencySymbol testPolicyId + , version = toInteger healthySnapshotVersion + } data IncrementMutation = -- | Move the deadline from the deposit datum back in time @@ -148,6 +148,18 @@ data IncrementMutation DepositMutateDepositDeadline | -- | Alter the head id DepositMutateHeadId + | -- | Change parties in incrment output datum + IncrementMutateParties + | -- | New version is incremented correctly + IncrementUseDifferentSnapshotVersion + | -- | Produce invalid signatures + ProduceInvalidSignatures + | -- | Change the head value + ChangeHeadValue + | -- | Change the required signers + AlterRequiredSigner + | -- | Alter the Claim redeemer `TxOutRef` + IncrementDifferentClaimRedeemer deriving stock (Generic, Show, Enum, Bounded) genIncrementMutation :: (Tx, UTxO) -> Gen SomeMutation @@ -157,27 +169,55 @@ genIncrementMutation (tx, utxo) = let datum = txOutDatum $ flip modifyInlineDatum (toTxContext depositOut) $ \case - DepositDatum (headCS', depositDatumDeadline, commits) -> - DepositDatum (headCS', Plutus.POSIXTime $ Plutus.getPOSIXTime depositDatumDeadline - 1, commits) + ((headCS', depositDatumDeadline, commits) :: (Plutus.CurrencySymbol, Plutus.POSIXTime, [Commit])) -> + (headCS', Plutus.POSIXTime $ Plutus.getPOSIXTime depositDatumDeadline - 1000, commits) let newOutput = toCtxUTxOTxOut $ TxOut addr val datum rscript - pure $ ChangeInput depositIn newOutput (Just $ toScriptData $ Claim (headIdToCurrencySymbol testHeadId)) + pure $ ChangeInput depositIn newOutput (Just $ toScriptData $ Claim (toPlutusCurrencySymbol testPolicyId)) , SomeMutation (pure $ toErrorCode WrongHeadIdInDepositDatum) DepositMutateHeadId <$> do otherHeadId <- arbitrary let datum = txOutDatum $ flip modifyInlineDatum (toTxContext depositOut) $ \case - DepositDatum (_headCS, depositDatumDeadline, commits) -> - DepositDatum (otherHeadId, depositDatumDeadline, commits) + ((_headCS, depositDatumDeadline, commits) :: (Plutus.CurrencySymbol, Plutus.POSIXTime, [Commit])) -> + (otherHeadId, depositDatumDeadline, commits) let newOutput = toCtxUTxOTxOut $ TxOut addr val datum rscript - pure $ ChangeInput depositIn newOutput (Just $ toScriptData $ Claim (headIdToCurrencySymbol testHeadId)) + pure $ ChangeInput depositIn newOutput (Just $ toScriptData $ Claim (toPlutusCurrencySymbol testPolicyId)) + , SomeMutation (pure $ toErrorCode ChangedParameters) IncrementMutateParties <$> do + mutatedParties <- arbitrary `suchThat` (/= healthyOnChainParties) + pure $ ChangeOutput 0 $ modifyInlineDatum (replaceParties mutatedParties) headTxOut + , SomeMutation (pure $ toErrorCode VersionNotIncremented) IncrementUseDifferentSnapshotVersion <$> do + mutatedSnapshotVersion <- arbitrarySizedNatural `suchThat` (/= healthySnapshotVersion + 1) + pure $ ChangeOutput 0 $ modifyInlineDatum (replaceSnapshotVersion $ toInteger mutatedSnapshotVersion) headTxOut + , SomeMutation (pure $ toErrorCode SignatureVerificationFailed) ProduceInvalidSignatures . ChangeHeadRedeemer <$> do + invalidSignature <- toPlutusSignatures <$> (arbitrary :: Gen (MultiSignature (Snapshot Tx))) + pure $ + Head.Increment + Head.IncrementRedeemer + { signature = invalidSignature + , snapshotNumber = fromIntegral healthySnapshotNumber + , increment = toPlutusTxOutRef $ fst $ List.head $ UTxO.pairs depositUTxO + } + , SomeMutation (pure $ toErrorCode HeadValueIsNotPreserved) ChangeHeadValue <$> do + newValue <- genValue `suchThat` (/= txOutValue headTxOut) + pure $ ChangeOutput 0 (headTxOut{txOutValue = newValue}) + , SomeMutation (pure $ toErrorCode SignerIsNotAParticipant) AlterRequiredSigner <$> do + newSigner <- verificationKeyHash <$> genVerificationKey `suchThat` (/= somePartyCardanoVerificationKey) + pure $ ChangeRequiredSigners [newSigner] + , SomeMutation (pure $ toErrorCode DepositInputNotFound) IncrementDifferentClaimRedeemer . ChangeHeadRedeemer <$> do + invalidDepositRef <- genTxIn + pure $ + Head.Increment + Head.IncrementRedeemer + { signature = toPlutusSignatures healthySignature + , snapshotNumber = fromIntegral $ succ healthySnapshotNumber + , increment = toPlutusTxOutRef invalidDepositRef + } ] where - depositScript = fromPlutusScript @PlutusScriptV3 Deposit.validatorScript - - depositAddress = mkScriptAddress @PlutusScriptV3 testNetworkId depositScript + headTxOut = fromJust $ txOuts' tx !!? 0 (depositIn, depositOut@(TxOut addr val _ rscript)) = fromJust $ find - (\(_, TxOut address _ _ _) -> address == depositAddress) + (\(_, TxOut address _ _ _) -> address == Deposit.depositAddress testNetworkId) (UTxO.pairs (resolveInputsUTxO utxo tx)) diff --git a/hydra-tx/test/Hydra/Tx/Contract/Recover.hs b/hydra-tx/test/Hydra/Tx/Contract/Recover.hs index ef43b240060..aba9b12c1bc 100644 --- a/hydra-tx/test/Hydra/Tx/Contract/Recover.hs +++ b/hydra-tx/test/Hydra/Tx/Contract/Recover.hs @@ -7,7 +7,8 @@ import Cardano.Api.UTxO qualified as UTxO import Data.Fixed (Milli) import Data.List qualified as List import Data.Time.Clock.POSIX qualified as POSIX -import Hydra.Contract.Deposit (DepositDatum (..), DepositRedeemer (Recover)) +import Hydra.Contract.Commit (Commit) +import Hydra.Contract.Deposit (DepositRedeemer (Recover)) import Hydra.Contract.DepositError (DepositError (..)) import Hydra.Contract.Error (toErrorCode) import Hydra.Ledger.Cardano.Evaluate (slotLength, systemStart) @@ -17,7 +18,7 @@ import Hydra.Tx.BlueprintTx (CommitBlueprintTx (..)) import Hydra.Tx.Deposit (depositTx) import Hydra.Tx.HeadId (mkHeadId) import Hydra.Tx.Recover (recoverTx) -import PlutusLedgerApi.V3 (CurrencySymbol) +import PlutusLedgerApi.V3 (CurrencySymbol, POSIXTime) import Test.Hydra.Tx.Fixture (testNetworkId, testPolicyId) import Test.Hydra.Tx.Gen (genUTxOAdaOnlyOfSize, genValue) import Test.Hydra.Tx.Mutation ( @@ -88,8 +89,8 @@ genRecoverMutation (tx, utxo) = let datum = txOutDatum $ flip modifyInlineDatum (toTxContext depositOut) $ \case - DepositDatum (headCS', depositDatumDeadline, commits) -> - DepositDatum (headCS', depositDatumDeadline + posixFromUTCTime n, commits) + ((headCS', depositDatumDeadline, commits) :: (CurrencySymbol, POSIXTime, [Commit])) -> + (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 diff --git a/hydra-tx/test/Hydra/Tx/Hash.hs b/hydra-tx/test/Hydra/Tx/Hash.hs new file mode 100644 index 00000000000..45857960fc9 --- /dev/null +++ b/hydra-tx/test/Hydra/Tx/Hash.hs @@ -0,0 +1,15 @@ +module Hydra.Tx.Hash where + +import Hydra.Prelude + +import Hydra.Contract.Util (hashTxOuts) +import Test.Hspec (Spec, describe, it) +import Test.QuickCheck ((===)) + +spec :: Spec +spec = do + describe "hashTxOuts/hashUTxO" $ + it "hashing empty [TxOut] is the same as empty UTxO hash" $ do + let hashUTxO = hashUTxO mempty + let hashOuts = hashTxOuts [] + in hashUTxO === hashOuts diff --git a/hydra-tx/testlib/Test/Hydra/Tx/Fixture.hs b/hydra-tx/testlib/Test/Hydra/Tx/Fixture.hs index a827919ed38..664c257444c 100644 --- a/hydra-tx/testlib/Test/Hydra/Tx/Fixture.hs +++ b/hydra-tx/testlib/Test/Hydra/Tx/Fixture.hs @@ -39,6 +39,7 @@ import Hydra.Tx.Environment (Environment (..)) import Hydra.Tx.HeadParameters (HeadParameters (..)) import Hydra.Tx.OnChainId (AsType (..), OnChainId) import Hydra.Tx.Party (deriveParty) +import System.IO.Unsafe (unsafePerformIO) -- | Our beloved alice, bob, and carol. alice, bob, carol :: Party @@ -59,6 +60,10 @@ testHeadId = UnsafeHeadId "1234" testHeadSeed :: HeadSeed testHeadSeed = UnsafeHeadSeed "000000000000000000#0" +depositDeadline :: UTCTime +depositDeadline = unsafePerformIO getCurrentTime +{-# NOINLINE depositDeadline #-} + -- | Derive some 'OnChainId' from a Hydra party. In the real protocol this is -- currently not done, but in this simulated chain setting this is definitely -- fine. diff --git a/hydra-tx/testlib/Test/Hydra/Tx/Mutation.hs b/hydra-tx/testlib/Test/Hydra/Tx/Mutation.hs index e9e129b9afe..dec711e0a5e 100644 --- a/hydra-tx/testlib/Test/Hydra/Tx/Mutation.hs +++ b/hydra-tx/testlib/Test/Hydra/Tx/Mutation.hs @@ -570,8 +570,7 @@ modifyInlineDatum fn txOut = case fromScriptData sd of Just st -> txOut{txOutDatum = mkTxOutDatumInline $ fn st} - Nothing -> - error "Invalid data" + Nothing -> error "invalid data" addParticipationTokens :: [VerificationKey PaymentKey] -> TxOut CtxUTxO -> TxOut CtxUTxO addParticipationTokens vks txOut = @@ -763,13 +762,14 @@ replaceSnapshotVersion snapshotVersion = \case , Head.headId = headId , Head.version = snapshotVersion } - Head.Closed Head.ClosedDatum{parties, snapshotNumber, utxoHash, deltaUTxOHash, contestationDeadline, headId, contesters, contestationPeriod} -> + Head.Closed Head.ClosedDatum{parties, snapshotNumber, utxoHash, alphaUTxOHash, omegaUTxOHash, contestationDeadline, headId, contesters, contestationPeriod} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash = utxoHash - , Head.deltaUTxOHash = deltaUTxOHash + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId @@ -780,13 +780,14 @@ replaceSnapshotVersion snapshotVersion = \case replaceSnapshotNumber :: Head.SnapshotNumber -> Head.State -> Head.State replaceSnapshotNumber snapshotNumber = \case - Head.Closed Head.ClosedDatum{parties, utxoHash, deltaUTxOHash, contestationDeadline, headId, contesters, contestationPeriod, version} -> + Head.Closed Head.ClosedDatum{parties, utxoHash, alphaUTxOHash, omegaUTxOHash, contestationDeadline, headId, contesters, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash = utxoHash - , Head.deltaUTxOHash = deltaUTxOHash + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId @@ -813,13 +814,14 @@ replaceParties parties = \case , Head.headId = headId , Head.version = version } - Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, deltaUTxOHash, contestationDeadline, headId, contesters, contestationPeriod, version} -> + Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, alphaUTxOHash, omegaUTxOHash, contestationDeadline, headId, contesters, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash = utxoHash - , Head.deltaUTxOHash = deltaUTxOHash + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId @@ -839,13 +841,14 @@ replaceUTxOHash utxoHash = \case , Head.headId = headId , Head.version = version } - Head.Closed Head.ClosedDatum{parties, deltaUTxOHash, snapshotNumber, contestationDeadline, headId, contesters, contestationPeriod, version} -> + Head.Closed Head.ClosedDatum{parties, alphaUTxOHash, omegaUTxOHash, snapshotNumber, contestationDeadline, headId, contesters, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash = utxoHash - , Head.deltaUTxOHash = deltaUTxOHash + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId @@ -854,15 +857,16 @@ replaceUTxOHash utxoHash = \case } otherState -> otherState -replaceDeltaUTxOHash :: Head.Hash -> Head.State -> Head.State -replaceDeltaUTxOHash deltaUTxOHash' = \case - Head.Closed Head.ClosedDatum{parties, utxoHash, snapshotNumber, contestationDeadline, headId, contesters, contestationPeriod, version} -> +replaceOmegaUTxOHash :: Head.Hash -> Head.State -> Head.State +replaceOmegaUTxOHash omegaUTxOHash' = \case + Head.Closed Head.ClosedDatum{parties, utxoHash, alphaUTxOHash, snapshotNumber, contestationDeadline, headId, contesters, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash - , Head.deltaUTxOHash = deltaUTxOHash' + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash' , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId @@ -873,12 +877,13 @@ replaceDeltaUTxOHash deltaUTxOHash' = \case replaceContestationDeadline :: POSIXTime -> Head.State -> Head.State replaceContestationDeadline contestationDeadline = \case - Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, deltaUTxOHash, parties, headId, contesters, contestationPeriod, version} -> + Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, alphaUTxOHash, omegaUTxOHash, parties, headId, contesters, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { snapshotNumber , utxoHash - , deltaUTxOHash + , alphaUTxOHash + , omegaUTxOHash , parties , contestationDeadline , contestationPeriod @@ -890,12 +895,13 @@ replaceContestationDeadline contestationDeadline = \case replaceContestationPeriod :: ContestationPeriod -> Head.State -> Head.State replaceContestationPeriod contestationPeriod = \case - Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, deltaUTxOHash, parties, headId, contesters, contestationDeadline, version} -> + Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, alphaUTxOHash, omegaUTxOHash, parties, headId, contesters, contestationDeadline, version} -> Head.Closed Head.ClosedDatum { snapshotNumber , utxoHash - , deltaUTxOHash + , alphaUTxOHash + , omegaUTxOHash , parties , contestationDeadline , contestationPeriod @@ -923,13 +929,14 @@ replaceHeadId headId = \case , Head.headId = headId , Head.version = version } - Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, deltaUTxOHash, contestationDeadline, parties, contesters, contestationPeriod, version} -> + Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, alphaUTxOHash, omegaUTxOHash, contestationDeadline, parties, contesters, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash = utxoHash - , Head.deltaUTxOHash = deltaUTxOHash + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId @@ -940,13 +947,14 @@ replaceHeadId headId = \case replaceContesters :: [Plutus.PubKeyHash] -> Head.State -> Head.State replaceContesters contesters = \case - Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, deltaUTxOHash, contestationDeadline, parties, headId, contestationPeriod, version} -> + Head.Closed Head.ClosedDatum{snapshotNumber, utxoHash, alphaUTxOHash, omegaUTxOHash, contestationDeadline, parties, headId, contestationPeriod, version} -> Head.Closed Head.ClosedDatum { Head.parties = parties , Head.snapshotNumber = snapshotNumber , Head.utxoHash = utxoHash - , Head.deltaUTxOHash = deltaUTxOHash + , Head.alphaUTxOHash = alphaUTxOHash + , Head.omegaUTxOHash = omegaUTxOHash , Head.contestationDeadline = contestationDeadline , Head.contestationPeriod = contestationPeriod , Head.headId = headId diff --git a/networks.json b/networks.json index e5cd494b6ed..6d1fce7f484 100644 --- a/networks.json +++ b/networks.json @@ -7,7 +7,10 @@ "0.17.0": "0d2eca8c8daf23061f5ba24a8f3113afba52a2e26318dc78c5583d9fc86b7b85", "0.18.0": "747c39eb53a4092fd46e10b417beef9781bf336a4fc1fd439e7492fe3876a1ba", "0.18.1": "747c39eb53a4092fd46e10b417beef9781bf336a4fc1fd439e7492fe3876a1ba", - "0.19.0": "ab1d9f8cca896bca06b70df74860deecf20774e03d8562aecaed37525f6ebead" + "0.19.0": "ab1d9f8cca896bca06b70df74860deecf20774e03d8562aecaed37525f6ebead", + "0.20.0": "1f0bc3326fcc73377f3b7aec2d6298e07dc654a80e1e804439abce4fbd47ba02,2bcce5704847edbe96919e35d1c0afa8e3fffd69ea4827d4f09473440a4a483f,77d4141cfa323351dd0cd1afc6d2e8a01bd3624bb12a3b7d869960018cab8f61" + + }, "preprod": { "0.13.0": "f917dcd1fa2653e33d6d0ca5a067468595b546120c3085fab60848c34f92c265", @@ -17,7 +20,8 @@ "0.17.0": "c7b9db4986611d0ce7ff8546ef5d42af68566783a40604c372182342c4124e7d", "0.18.0": "976b28bc716490fbaa4e17d7bf33b04f27fcfafef58c436c4f2644adeeb48829", "0.18.1": "976b28bc716490fbaa4e17d7bf33b04f27fcfafef58c436c4f2644adeeb48829", - "0.19.0": "03f8deb122fbbd98af8eb58ef56feda37728ec957d39586b78198a0cf624412a" + "0.19.0": "03f8deb122fbbd98af8eb58ef56feda37728ec957d39586b78198a0cf624412a", + "0.20.0": "8c3d846facf3b01e391b5a31e5de79b6ebb3c0a31b948bb328214542b130cdf8,cbd662b676da5284c99b17fc1b2e863447020b91cfe795054de1c09662601491,af047b631b723c9698689b9672e94cab16ddcf225af5cbc753801f3d6de18043" }, "preview": { "0.13.0": "1e00c627ec4b2ad0b4aa68068d3818ca0e41338c87e5504cda118c4050a98763", @@ -27,12 +31,21 @@ "0.17.0": "6d3f02bc648c1b62bb90fc221a8476fc47d4faaea4a293b00e58ac40c3377b85", "0.18.0": "19d25f489ffa66ba3568342657fe441f47a417d4e31585b5f0278ebe619ecf41", "0.18.1": "19d25f489ffa66ba3568342657fe441f47a417d4e31585b5f0278ebe619ecf41", - "0.19.0": "0fd2468a66a0b1cb944cff9512ecfa25cdd2799cb48b07210c449a5ecace267d" + "0.19.0": "0fd2468a66a0b1cb944cff9512ecfa25cdd2799cb48b07210c449a5ecace267d", + "0.20.0": "bc0572b529f746b03a8549cb95dbd69b70b1a31b3207538db3f3b24b0d835410,e2d44465fb229f81ffb0b1e3170a1e7eb4a4aeeecaf1b6356281f8557629be7d,feb67f2116c8e52cb677068bc37a3121a9d0c05f25acd4bc950f69c717f442d5" + + + + + + + }, "sanchonet": { "0.16.0": "af37f4f6bf7459d2ae1d6b2a1a2e4049465b62a8ebc308f3d6d6af68240a4419", "0.17.0": "", "0.18.0": "", "0.19.0": "" + "0.29.0": "" } }