diff --git a/docs/package.json b/docs/package.json index 18ac75e7285..07bfaab78f3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -10,9 +10,7 @@ "start": "yarn dummy-spec && docusaurus start", "validate:inputs": "./validate-api.js publish '/' '../hydra-node/golden/ReasonablySized (ClientInput (Tx BabbageEra)).json'", "validate:outputs": "./validate-api.js subscribe '/' '../hydra-node/golden/ReasonablySized (TimedServerOutput (Tx BabbageEra)).json'", - "validate:commit-inputs": "./validate-api.js publish '/commit' '../hydra-node/golden/ReasonablySized (DraftCommitTxRequest (Tx BabbageEra)).json'", - "validate:commit-outputs": "./validate-api.js subscribe '/commit' '../hydra-node/golden/ReasonablySized (DraftCommitTxResponse (Tx BabbageEra)).json'", - "validate": "yarn validate:inputs && yarn validate:outputs && yarn validate:commit-inputs && yarn validate:commit-outputs", + "validate": "yarn validate:inputs && yarn validate:outputs", "swizzle": "docusaurus swizzle", "deploy": "docusaurus deploy", "clear": "docusaurus clear", diff --git a/hydra-cardano-api/src/Cardano/Api/UTxO.hs b/hydra-cardano-api/src/Cardano/Api/UTxO.hs index 119f0aa6a92..41b1ff429f4 100644 --- a/hydra-cardano-api/src/Cardano/Api/UTxO.hs +++ b/hydra-cardano-api/src/Cardano/Api/UTxO.hs @@ -36,6 +36,8 @@ newtype UTxO' out = UTxO , Foldable , Semigroup , Monoid + , ToJSON + , FromJSON ) instance Traversable UTxO' where @@ -46,7 +48,7 @@ fromPairs :: [(TxIn, out)] -> UTxO' out fromPairs = UTxO . Map.fromList -- | Create a 'UTxO' from a single unspent transaction output. -singleton :: (TxIn, TxOut CtxUTxO Era) -> UTxO +singleton :: (TxIn, out) -> UTxO' out singleton (i, o) = UTxO $ Map.singleton i o -- | Find an 'out' for a given 'TxIn'. diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs index 3b7af28d46d..4f4f0d41c10 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/PlutusScript.hs @@ -6,7 +6,9 @@ import Hydra.Cardano.Api.Prelude import qualified Cardano.Ledger.Alonzo.Language as Ledger import qualified Cardano.Ledger.Alonzo.Scripts as Ledger +import qualified Data.ByteString.Short as SBS import qualified PlutusLedgerApi.Common as Plutus +import Test.QuickCheck (listOf) -- * Type Conversions @@ -49,3 +51,7 @@ instance IsPlutusScriptLanguage lang => FromJSON (PlutusScript lang) where case deserialiseFromTextEnvelope (proxyToAsType Proxy) env of Left e -> fail $ show e Right a -> pure a + +instance Arbitrary (PlutusScript lang) where + arbitrary = + PlutusScriptSerialised . SBS.pack <$> listOf arbitrary diff --git a/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs b/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs index c4cda022e05..03e114e6da1 100644 --- a/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs +++ b/hydra-cardano-api/src/Hydra/Cardano/Api/ScriptData.hs @@ -9,10 +9,12 @@ import qualified Cardano.Ledger.Alonzo.Data as Ledger import qualified Cardano.Ledger.Alonzo.TxWitness as Ledger import Codec.Serialise (deserialiseOrFail, serialise) import Control.Arrow (left) -import Data.Aeson (Value (String)) +import Data.Aeson (Value (String), withText) +import qualified Data.ByteString as BS import qualified Data.ByteString.Base16 as Base16 import qualified Data.Map as Map import qualified PlutusLedgerApi.V2 as Plutus +import Test.QuickCheck (arbitrarySizedNatural, choose, oneof, scale, sized, vector) -- * Extras @@ -96,13 +98,30 @@ instance FromJSON ScriptData where bytes <- Base16.decode (encodeUtf8 text) left show $ deserialiseOrFail $ fromStrict bytes --- NOTE: We are okay with storing the data and re-serializing + hashing it into --- 'HashableScriptData' in these ToJSON/FromJSON instances as the serialization --- ambiguity addressed by 'HashableScriptData' is long overboard if we are --- dealing with JSON. +instance Arbitrary ScriptData where + arbitrary = + scale (`div` 2) $ + oneof + [ ScriptDataConstructor <$> arbitrarySizedNatural <*> arbitrary + , ScriptDataNumber <$> arbitrary + , ScriptDataBytes <$> arbitraryBS + , ScriptDataList <$> arbitrary + , ScriptDataMap <$> arbitrary + ] + where + arbitraryBS = sized $ \n -> + BS.pack <$> (choose (0, min n 64) >>= vector) instance ToJSON HashableScriptData where - toJSON = toJSON . getScriptData + toJSON = String . decodeUtf8 . Base16.encode . serialiseToCBOR instance FromJSON HashableScriptData where - parseJSON = fmap unsafeHashableScriptData . parseJSON + parseJSON = + withText "HashableScriptData" $ \text -> do + bytes <- either (fail . show) pure $ Base16.decode $ encodeUtf8 text + either (fail . show) pure $ deserialiseFromCBOR (proxyToAsType Proxy) bytes + +instance Arbitrary HashableScriptData where + arbitrary = + -- NOTE: Safe to use here as the data was not available in serialized form. + unsafeHashableScriptData <$> arbitrary diff --git a/hydra-cluster/hydra-cluster.cabal b/hydra-cluster/hydra-cluster.cabal index 5440baeae49..953e53e9ec2 100644 --- a/hydra-cluster/hydra-cluster.cabal +++ b/hydra-cluster/hydra-cluster.cabal @@ -133,6 +133,7 @@ library , directory , filepath , hspec-expectations + , http-client , hydra-cardano-api , hydra-node , hydra-plutus @@ -159,6 +160,7 @@ library , unix , unordered-containers , websockets + , plutus-ledger-api:{plutus-ledger-api, plutus-ledger-api-testlib} >=1.1.1.0 ghc-options: -haddock @@ -238,7 +240,7 @@ test-suite tests , lens , lens-aeson , ouroboros-network - , plutus-ledger-api + , plutus-ledger-api:{plutus-ledger-api, plutus-ledger-api-testlib} >=1.1.1.0 , process , QuickCheck , say diff --git a/hydra-cluster/src/Hydra/Cluster/Faucet.hs b/hydra-cluster/src/Hydra/Cluster/Faucet.hs index 4ba23a45a76..95c908bb548 100644 --- a/hydra-cluster/src/Hydra/Cluster/Faucet.hs +++ b/hydra-cluster/src/Hydra/Cluster/Faucet.hs @@ -6,6 +6,7 @@ module Hydra.Cluster.Faucet where import Hydra.Cardano.Api import Hydra.Prelude +import Test.Hydra.Prelude import qualified Cardano.Api.UTxO as UTxO import CardanoClient ( @@ -24,7 +25,7 @@ import CardanoNode (RunningNode (..)) import Control.Exception (IOException) import Control.Monad.Class.MonadThrow (Handler (Handler), catches) import Control.Tracer (Tracer, traceWith) -import qualified Data.Map as Map +import qualified Data.Map.Strict as Map import GHC.IO.Exception (IOErrorType (ResourceExhausted), IOException (ioe_type)) import Hydra.Chain.Direct.ScriptRegistry ( publishHydraScripts, @@ -62,27 +63,19 @@ seedFromFaucet :: Marked -> Tracer IO FaucetLog -> IO UTxO -seedFromFaucet RunningNode{networkId, nodeSocket} receivingVerificationKey lovelace marked tracer = do +seedFromFaucet node@RunningNode{networkId, nodeSocket} receivingVerificationKey lovelace marked tracer = do (faucetVk, faucetSk) <- keysFor Faucet retryOnExceptions tracer $ submitSeedTx faucetVk faucetSk waitForPayment networkId nodeSocket lovelace receivingAddress where submitSeedTx faucetVk faucetSk = do - faucetUTxO <- findUTxO faucetVk + faucetUTxO <- findFaucetUTxO node lovelace let changeAddress = ShelleyAddressInEra (buildAddress faucetVk networkId) buildTransaction networkId nodeSocket changeAddress faucetUTxO [] [theOutput] >>= \case Left e -> throwIO $ FaucetFailedToBuildTx{reason = e} Right body -> do submitTransaction networkId nodeSocket (sign faucetSk body) - findUTxO faucetVk = do - faucetUTxO <- queryUTxO networkId nodeSocket QueryTip [buildAddress faucetVk networkId] - let foundUTxO = UTxO.filter (\o -> txOutLovelace o >= lovelace) faucetUTxO - when (null foundUTxO) $ - throwIO $ - FaucetHasNotEnoughFunds{faucetUTxO} - pure foundUTxO - receivingAddress = buildAddress receivingVerificationKey networkId theOutput = @@ -96,6 +89,16 @@ seedFromFaucet RunningNode{networkId, nodeSocket} receivingVerificationKey lovel Fuel -> TxOutDatumHash markerDatumHash Normal -> TxOutDatumNone +findFaucetUTxO :: RunningNode -> Lovelace -> IO UTxO +findFaucetUTxO RunningNode{networkId, nodeSocket} lovelace = do + (faucetVk, _) <- keysFor Faucet + faucetUTxO <- queryUTxO networkId nodeSocket QueryTip [buildAddress faucetVk networkId] + let foundUTxO = UTxO.filter (\o -> txOutLovelace o >= lovelace) faucetUTxO + when (null foundUTxO) $ + throwIO $ + FaucetHasNotEnoughFunds{faucetUTxO} + pure foundUTxO + -- | Like 'seedFromFaucet', but without returning the seeded 'UTxO'. seedFromFaucet_ :: RunningNode -> @@ -140,6 +143,49 @@ returnFundsToFaucet tracer node@RunningNode{networkId, nodeSocket} sender = do Left e -> throwIO $ FaucetFailedToBuildTx{reason = e} Right body -> pure body +-- Use the Faucet utxo to create the output at specified address +createOutputAtAddress :: + ToScriptData a => + RunningNode -> + ProtocolParameters -> + AddressInEra -> + a -> + IO (TxIn, TxOut CtxUTxO) +createOutputAtAddress node@RunningNode{networkId, nodeSocket} pparams atAddress datum = do + (faucetVk, faucetSk) <- keysFor Faucet + -- we don't care which faucet utxo we use here so just pass lovelace 0 to grab + -- any present utxo + utxo <- findFaucetUTxO node 0 + buildTransaction + networkId + nodeSocket + (changeAddress faucetVk) + utxo + collateralTxIns + [output] + >>= \case + Left e -> + throwErrorAsException e + Right body -> do + let tx = makeSignedTransaction [makeShelleyKeyWitness body (WitnessPaymentKey faucetSk)] body + submitTransaction networkId nodeSocket tx + newUtxo <- awaitTransaction networkId nodeSocket tx + case UTxO.find (\out -> txOutAddress out == atAddress) newUtxo of + Nothing -> failure $ "Could not find script output: " <> decodeUtf8 (encodePretty newUtxo) + Just u -> pure u + where + collateralTxIns = mempty + + changeAddress vk = mkVkAddress networkId vk + + output = + mkTxOutAutoBalance + pparams + atAddress + mempty + (mkTxOutDatumHash datum) + ReferenceScriptNone + -- | Build and sign tx and return the calculated fee. -- - Signing key should be the key of a sender -- - Address is used as a change address. diff --git a/hydra-cluster/src/Hydra/Cluster/Scenarios.hs b/hydra-cluster/src/Hydra/Cluster/Scenarios.hs index 768adcf8bd5..2e354d437ab 100644 --- a/hydra-cluster/src/Hydra/Cluster/Scenarios.hs +++ b/hydra-cluster/src/Hydra/Cluster/Scenarios.hs @@ -5,31 +5,58 @@ module Hydra.Cluster.Scenarios where import Hydra.Prelude -import CardanoClient (queryTip, submitTx) +import qualified Cardano.Api.UTxO as UTxO +import CardanoClient ( + QueryPoint (QueryTip), + queryProtocolParameters, + queryTip, + submitTx, + ) import CardanoNode (RunningNode (..)) import Control.Lens ((^?)) import Data.Aeson (Value, object, (.=)) import Data.Aeson.Lens (key, _JSON) import Data.Aeson.Types (parseMaybe) +import qualified Data.ByteString as B import qualified Data.Set as Set +import Hydra.API.RestServer (DraftCommitTxRequest (..), DraftCommitTxResponse (..), ScriptInfo (..), TxOutWithWitness (..)) import Hydra.Cardano.Api ( - Lovelace, + Lovelace (..), + PlutusScriptV2, + Tx, TxId, + fromPlutusScript, + mkScriptAddress, selectLovelace, + toScriptData, ) import Hydra.Chain (HeadId) -import Hydra.Cluster.Faucet (Marked (Fuel), queryMarkedUTxO, seedFromFaucet, seedFromFaucet_) +import Hydra.Cluster.Faucet (Marked (Fuel, Normal), createOutputAtAddress, queryMarkedUTxO, seedFromFaucet, seedFromFaucet_) import qualified Hydra.Cluster.Faucet as Faucet import Hydra.Cluster.Fixture (Actor (..), actorName, alice, aliceSk, aliceVk, bob, bobSk, bobVk) import Hydra.Cluster.Util (chainConfigFor, keysFor) import Hydra.ContestationPeriod (ContestationPeriod (UnsafeContestationPeriod)) import Hydra.Ledger (IsTx (balance)) -import Hydra.Ledger.Cardano (Tx) import Hydra.Logging (Tracer, traceWith) import Hydra.Options (ChainConfig, networkId, startChainFrom) import Hydra.Party (Party) import HydraNode (EndToEndLog (..), externalCommit, input, output, send, waitFor, waitForAllMatch, waitMatch, withHydraNode) -import Test.Hspec.Expectations (shouldBe) +import qualified Network.HTTP.Client as L +import Network.HTTP.Req ( + HttpException (VanillaHttpException), + JsonResponse, + POST (POST), + ReqBodyJson (ReqBodyJson), + defaultHttpConfig, + http, + port, + req, + responseBody, + runReq, + (/:), + ) +import qualified PlutusLedgerApi.Test.Examples as Plutus +import Test.Hspec.Expectations (shouldBe, shouldThrow) restartedNodeCanObserveCommitTx :: Tracer IO EndToEndLog -> FilePath -> RunningNode -> TxId -> IO () restartedNodeCanObserveCommitTx tracer workDir cardanoNode hydraScriptsTxId = do @@ -171,6 +198,102 @@ singlePartyCommitsUsingFuel tracer workDir node hydraScriptsTxId = where RunningNode{nodeSocket} = node +-- | Single hydra-node where the commit is done from an external UTxO owned by a +-- script which requires providing script, datum and redeemer instead of +-- signing the transaction. +singlePartyCommitsFromExternalScript :: + Tracer IO EndToEndLog -> + FilePath -> + RunningNode -> + TxId -> + IO () +singlePartyCommitsFromExternalScript tracer workDir node hydraScriptsTxId = + (`finally` returnFundsToFaucet tracer node Alice) $ do + refuelIfNeeded tracer node Alice 25_000_000 + aliceChainConfig <- chainConfigFor Alice workDir nodeSocket [] $ UnsafeContestationPeriod 100 + let hydraNodeId = 1 + withHydraNode tracer aliceChainConfig workDir hydraNodeId aliceSk [] [1] hydraScriptsTxId $ \n1 -> do + send n1 $ input "Init" [] + headId <- waitMatch 600 n1 $ headIsInitializingWith (Set.fromList [alice]) + + -- Prepare a script output on the network + let script = fromPlutusScript @PlutusScriptV2 $ Plutus.alwaysSucceedingNAryFunction 2 + scriptAddress = mkScriptAddress @PlutusScriptV2 networkId script + reedemer = 1 :: Integer + datum = 2 :: Integer + scriptInfo = ScriptInfo (toScriptData reedemer) (toScriptData datum) script + pparams <- queryProtocolParameters networkId nodeSocket QueryTip + (scriptTxIn, scriptTxOut) <- createOutputAtAddress node pparams scriptAddress datum + + -- Commit the script output using known witness + let clientPayload = + DraftCommitTxRequest + { utxos = + UTxO.singleton + ( scriptTxIn + , TxOutWithWitness + { txOut = scriptTxOut + , witness = Just scriptInfo + } + ) + } + res <- + runReq defaultHttpConfig $ + req + POST + (http "127.0.0.1" /: "commit") + (ReqBodyJson clientPayload) + (Proxy :: Proxy (JsonResponse DraftCommitTxResponse)) + (port $ 4000 + hydraNodeId) + + let DraftCommitTxResponse{commitTx} = responseBody res + submitTx node commitTx + + lockedUTxO <- waitMatch 60 n1 $ \v -> do + guard $ v ^? key "headId" == Just (toJSON headId) + guard $ v ^? key "tag" == Just "HeadIsOpen" + pure $ v ^? key "utxo" + lockedUTxO `shouldBe` Just (toJSON $ UTxO.singleton (scriptTxIn, scriptTxOut)) + where + RunningNode{networkId, nodeSocket} = node + +singlePartyCannotCommitExternallyWalletUtxo :: + Tracer IO EndToEndLog -> + FilePath -> + RunningNode -> + TxId -> + IO () +singlePartyCannotCommitExternallyWalletUtxo tracer workDir node hydraScriptsTxId = + (`finally` returnFundsToFaucet tracer node Alice) $ do + refuelIfNeeded tracer node Alice 25_000_000 + aliceChainConfig <- chainConfigFor Alice workDir nodeSocket [] $ UnsafeContestationPeriod 100 + let hydraNodeId = 1 + withHydraNode tracer aliceChainConfig workDir hydraNodeId aliceSk [] [1] hydraScriptsTxId $ \n1 -> do + send n1 $ input "Init" [] + _headId <- waitMatch 60 n1 $ headIsInitializingWith (Set.fromList [alice]) + + -- these keys should mimic external wallet keys needed to sign the commit tx + + -- internal wallet uses the actor keys internally so we need to use utxo + -- present at this public key + (userVk, _userSk) <- keysFor Alice + -- submit the tx using our external user key to get a utxo to commit + utxoToCommit <- seedFromFaucet node userVk 2_000_000 Normal (contramap FromFaucet tracer) + -- Request to build a draft commit tx from hydra-node + externalCommit n1 utxoToCommit `shouldThrow` selector400 + where + RunningNode{nodeSocket} = node + selector400 :: HttpException -> Bool + selector400 + ( VanillaHttpException + ( L.HttpExceptionRequest + _ + (L.StatusCodeException response chunk) + ) + ) = + L.responseStatus response == toEnum 400 && not (B.null chunk) + selector400 _ = False + -- | Initialize open and close a head on a real network and ensure contestation -- period longer than the time horizon is possible. For this it is enough that -- we can close a head and not wait for the deadline. diff --git a/hydra-cluster/src/HydraNode.hs b/hydra-cluster/src/HydraNode.hs index 5bf448c055b..698be3b119c 100644 --- a/hydra-cluster/src/HydraNode.hs +++ b/hydra-cluster/src/HydraNode.hs @@ -20,7 +20,7 @@ import Data.Aeson.Types (Pair) import qualified Data.List as List import Data.Text (pack) import qualified Data.Text as T -import Hydra.API.RestServer (DraftCommitTxRequest (..), DraftCommitTxResponse (..)) +import Hydra.API.RestServer (DraftCommitTxRequest (..), DraftCommitTxResponse (..), TxOutWithWitness (..)) import Hydra.Cluster.Faucet (FaucetLog) import Hydra.Cluster.Util (readConfigFile) import Hydra.ContestationPeriod (ContestationPeriod) @@ -163,20 +163,23 @@ waitForAll tracer delay nodes expected = do tryNext c msgs stillExpected -- | Create a commit tx using the hydra-node for later submission -externalCommit :: HydraClient -> UTxO -> IO Tx -externalCommit HydraClient{hydraNodeId} utxos = - runReq defaultHttpConfig request - <&> responseBody - >>= \DraftCommitTxResponse{commitTx} -> pure commitTx +externalCommit' :: HydraClient -> UTxO' TxOutWithWitness -> IO Tx +externalCommit' HydraClient{hydraNodeId} utxos = + runReq defaultHttpConfig request <&> commitTx . responseBody where request = Req.req POST (Req.http "127.0.0.1" /: "commit") - (ReqBodyJson (DraftCommitTxRequest{utxos} :: DraftCommitTxRequest Tx)) - (Proxy :: Proxy (JsonResponse (DraftCommitTxResponse Tx))) + (ReqBodyJson $ DraftCommitTxRequest utxos) + (Proxy :: Proxy (JsonResponse DraftCommitTxResponse)) (Req.port $ 4000 + hydraNodeId) +-- | Helper to make it easy to externally commit non-script utxo +externalCommit :: HydraClient -> UTxO -> IO Tx +externalCommit client = + externalCommit' client . fmap (`TxOutWithWitness` Nothing) + getMetrics :: HasCallStack => HydraClient -> IO ByteString getMetrics HydraClient{hydraNodeId} = do failAfter 3 $ diff --git a/hydra-cluster/test/Test/EndToEndSpec.hs b/hydra-cluster/test/Test/EndToEndSpec.hs index d88b00f10d9..aecf31107c7 100644 --- a/hydra-cluster/test/Test/EndToEndSpec.hs +++ b/hydra-cluster/test/Test/EndToEndSpec.hs @@ -67,6 +67,8 @@ import Hydra.Cluster.Scenarios ( headIsInitializingWith, restartedNodeCanAbort, restartedNodeCanObserveCommitTx, + singlePartyCannotCommitExternallyWalletUtxo, + singlePartyCommitsFromExternalScript, singlePartyCommitsUsingFuel, singlePartyHeadFullLifeCycle, ) @@ -115,7 +117,7 @@ withClusterTempDir name = withTempDir ("hydra-cluster-e2e-" <> name) spec :: Spec -spec = around showLogsOnFailure $ do +spec = around showLogsOnFailure $ describe "End-to-end on Cardano devnet" $ do describe "single party hydra head" $ do it "full head life-cycle" $ \tracer -> do @@ -138,6 +140,16 @@ spec = around showLogsOnFailure $ do withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node -> publishHydraScriptsAs node Faucet >>= singlePartyCommitsUsingFuel tracer tmpDir node + it "commits from external with script utxo" $ \tracer -> do + withClusterTempDir "single-commits-script-from-external" $ \tmpDir -> do + withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node -> + publishHydraScriptsAs node Faucet + >>= singlePartyCommitsFromExternalScript tracer tmpDir node + it "can't commit externally with internal wallet utxo" $ \tracer -> do + withClusterTempDir "commit-internal-wallet-utxo" $ \tmpDir -> do + withCardanoNodeDevnet (contramap FromCardanoNode tracer) tmpDir $ \node -> + publishHydraScriptsAs node Faucet + >>= singlePartyCannotCommitExternallyWalletUtxo tracer tmpDir node describe "three hydra nodes scenario" $ do it "inits a Head, processes a single Cardano transaction and closes it again" $ \tracer -> diff --git a/hydra-node/golden/ReasonablySized (DraftCommitTxRequest (Tx BabbageEra)).json b/hydra-node/golden/ReasonablySized (DraftCommitTxRequest (Tx BabbageEra)).json deleted file mode 100644 index 3ab3e8f2efb..00000000000 --- a/hydra-node/golden/ReasonablySized (DraftCommitTxRequest (Tx BabbageEra)).json +++ /dev/null @@ -1,1107 +0,0 @@ -{ - "samples": [ - { - "tag": "DraftCommitTxRequest", - "utxos": { - "0103050804080403050205060701050704000503030006020506030804080506#71": { - "address": "addr_test1vz66ue36465w2qq40005h2hadad6pnjht8mu6sgplsfj74q9pm4f4", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "referenceScript": { - "script": { - "cborHex": "4746010000220011", - "description": "", - "type": "PlutusScriptV1" - }, - "scriptLanguage": "PlutusScriptLanguage PlutusScriptV1" - }, - "value": { - "1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48": { - "030605050701": 11 - }, - "a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a": { - "050405": 9 - }, - "lovelace": 5 - } - }, - "0106060406050806030104060306080505070200080701040102040303060405#41": { - "address": "EqGAuA8vHnPFLW2XmXEmeFPMzvPeDJP9WaPqKeKDhvvTsapBsy4EmY2SuWPLWMfgWaDV2Pga1cFAgpsWL9FMvZktF1EBnmG6jVDLDDnjXYz4Bj9HAL4nAnB", - "datum": null, - "inlineDatum": { - "bytes": "6c6ad23b" - }, - "inlineDatumhash": "b62666b7b1ed7e557939051b718501628d1c09c82f83d9beb10b4ce12c3ec3bc", - "referenceScript": { - "script": { - "cborHex": "82018182018382041a0001753f820419c9bb82041a000185ae", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48": { - "0004070207": 12, - "040708010005": 7 - }, - "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { - "080001": 12 - }, - "lovelace": 3 - } - }, - "0802080104080700030804030200060603000504070405020802030401060707#62": { - "address": "2RhQhCGqYPDpXY3H5vUh3keN5TopNgsAp1Rg5rQCcnzSJjMHdKdHqJusc3EC3ATUDD4Gh25zzv2QSyFXAKeVnyzYtJnxcM24YiG6TFa6q4N17i", - "datum": null, - "inlineDatum": { - "constructor": 462, - "fields": [ - { - "map": [] - } - ] - }, - "inlineDatumhash": "59d5b012f08d8c0b31a743f8fbce1ec1eddc6561ad6e4410a9a73a1e5908b84e", - "referenceScript": { - "script": { - "cborHex": "8204196287", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { - "060808040302": 9 - }, - "lovelace": 1 - } - } - } - }, - { - "tag": "DraftCommitTxRequest", - "utxos": { - "0404050600060407040404040200020405080105060305050205040301040105#85": { - "address": "2cWKMJemoBajna1zeMCztvbPmvEXKCkgK4AVpMSheQcAwtLXnB39NsZH5LqAxL8qb8PR3", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "referenceScript": null, - "value": { - "65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7": { - "0107": 16 - }, - "eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5": { - "010306": 11 - }, - "lovelace": 13 - } - }, - "0406000705050706020107060805010606060101000500000604070502010605#80": { - "address": "EqGAuA8vHnPACRqKWhNSZq4Mr8rNYGqXiZ8hcQox3mZ5qE7UZkCwVEmFgHY1DembXyaum2Y2W3ezQk6oKhdzMwxA7f5tNxvgwTc7QcMDxYomw5wJwBsk53y", - "datum": null, - "inlineDatum": { - "int": -5 - }, - "inlineDatumhash": "f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d99229", - "referenceScript": null, - "value": { - "4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56": { - "040202": 12 - }, - "58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7": { - "03": 11 - }, - "b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54": { - "040100": 8 - }, - "eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5": { - "060303030108": 15 - }, - "lovelace": 11 - } - }, - "0806040800050503050307060708050300040503060702030301080403040407#47": { - "address": "addr1yxnyv36t3a2rzfs4q6mvyu7nqlr4dxjwkmykkskafg54yz444enr4t4gu5qp277lfw406m6m5r89wk0he4qsrlqn9a2qw86cxv", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "list": [ - { - "bytes": "ee0e" - }, - { - "int": -2 - }, - { - "constructor": 674, - "fields": [ - { - "bytes": "c0" - }, - { - "int": -5 - }, - { - "bytes": "af" - }, - { - "int": 3 - }, - { - "int": -3 - } - ] - }, - { - "bytes": "e1" - }, - { - "bytes": "335a" - } - ] - }, - "v": { - "list": [ - { - "constructor": 504, - "fields": [ - { - "int": 5 - }, - { - "int": -2 - } - ] - }, - { - "list": [ - { - "int": -5 - }, - { - "bytes": "d5fa79" - }, - { - "bytes": "d6" - }, - { - "int": -1 - }, - { - "bytes": "2fe9e255" - } - ] - }, - { - "list": [ - { - "int": -1 - }, - { - "int": 2 - }, - { - "bytes": "60ec35" - } - ] - }, - { - "int": 0 - }, - { - "map": [ - { - "k": { - "bytes": "3e9d" - }, - "v": { - "int": 2 - } - } - ] - } - ] - } - }, - { - "k": { - "map": [ - { - "k": { - "int": -1 - }, - "v": { - "int": 3 - } - }, - { - "k": { - "int": 5 - }, - "v": { - "list": [] - } - }, - { - "k": { - "map": [ - { - "k": { - "int": -4 - }, - "v": { - "int": 3 - } - }, - { - "k": { - "int": -5 - }, - "v": { - "int": 5 - } - }, - { - "k": { - "bytes": "d8a3f2" - }, - "v": { - "int": 0 - } - }, - { - "k": { - "bytes": "f8361e13" - }, - "v": { - "bytes": "ab1b7d" - } - }, - { - "k": { - "bytes": "e2d4fa" - }, - "v": { - "int": 4 - } - } - ] - }, - "v": { - "list": [ - { - "bytes": "412b" - }, - { - "bytes": "" - }, - { - "int": -2 - } - ] - } - }, - { - "k": { - "int": 3 - }, - "v": { - "int": 3 - } - } - ] - }, - "v": { - "map": [ - { - "k": { - "int": -4 - }, - "v": { - "constructor": 84, - "fields": [ - { - "int": -2 - }, - { - "int": 2 - }, - { - "int": 1 - }, - { - "bytes": "d9" - } - ] - } - }, - { - "k": { - "list": [] - }, - "v": { - "map": [] - } - }, - { - "k": { - "map": [ - { - "k": { - "int": 1 - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "bytes": "5d" - }, - "v": { - "int": 5 - } - }, - { - "k": { - "int": -1 - }, - "v": { - "bytes": "3c2ef4" - } - } - ] - }, - "v": { - "constructor": 251, - "fields": [] - } - }, - { - "k": { - "map": [ - { - "k": { - "int": 4 - }, - "v": { - "int": -1 - } - }, - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "f1d93d0c" - } - }, - { - "k": { - "int": 2 - }, - "v": { - "int": 2 - } - }, - { - "k": { - "bytes": "a4" - }, - "v": { - "bytes": "" - } - } - ] - }, - "v": { - "constructor": 518, - "fields": [ - { - "int": 2 - }, - { - "bytes": "7e83f2a8" - }, - { - "int": 3 - }, - { - "int": -4 - }, - { - "bytes": "" - } - ] - } - }, - { - "k": { - "int": -2 - }, - "v": { - "int": 4 - } - } - ] - } - }, - { - "k": { - "list": [ - { - "constructor": 395, - "fields": [] - }, - { - "list": [ - { - "bytes": "af" - }, - { - "int": 4 - } - ] - }, - { - "int": 3 - }, - { - "constructor": 637, - "fields": [ - { - "bytes": "" - } - ] - }, - { - "list": [] - } - ] - }, - "v": { - "map": [ - { - "k": { - "list": [ - { - "bytes": "218a68" - } - ] - }, - "v": { - "map": [ - { - "k": { - "bytes": "b9" - }, - "v": { - "int": -4 - } - }, - { - "k": { - "bytes": "003725f3" - }, - "v": { - "bytes": "88be92" - } - }, - { - "k": { - "int": -5 - }, - "v": { - "bytes": "" - } - } - ] - } - }, - { - "k": { - "constructor": 790, - "fields": [ - { - "bytes": "30" - } - ] - }, - "v": { - "list": [ - { - "bytes": "5b59" - }, - { - "bytes": "06a373" - }, - { - "int": 2 - } - ] - } - } - ] - } - } - ] - }, - "inlineDatumhash": "04a0d84fe1e4017bf053b39355c99238362c3233b66c564e953c435a637211d7", - "referenceScript": null, - "value": {} - } - } - }, - { - "tag": "DraftCommitTxRequest", - "utxos": { - "0704030006010806000802060104070106050308080302000004070004020100#75": { - "address": "addr1v8kvh76uvxt88ury3fpvctuz9jquhs62aeqjw33cazd84age0a6xj", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "referenceScript": { - "script": { - "cborHex": "8200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { - "010602030600": 16 - }, - "4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56": { - "": 10, - "0203010808": 7 - }, - "eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5": { - "070401040100": 15 - }, - "lovelace": 13 - } - }, - "0802060105050105060206020105050703080706060405020707040601080103#32": { - "address": "2RhQhCGqYPDoCkJUJG4SKRaEB9xgutKfJecfXTq8LYoY2zkHPcsE76SuZgrVTaAD3dQmh43zG7USzhGksygm2bJxfQzVdmupt7ndsTQTjuL7AX", - "datum": null, - "datumhash": null, - "inlineDatum": null, - "referenceScript": null, - "value": {} - } - } - }, - { - "tag": "DraftCommitTxRequest", - "utxos": { - "0208080000010806080400060606070204040705070108000104030105040805#1": { - "address": "addr_test1zqvjpeuz7pywnm6j4nvfcs6p4zwrjzxxupr2mp7ywnllkjz2eunh8ytu0d28c4m20lc3p5462ueuruw2nnwxtxh28ftqcyhey8", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "int": 5 - }, - "v": { - "map": [ - { - "k": { - "bytes": "4da270" - }, - "v": { - "bytes": "d6345902" - } - }, - { - "k": { - "list": [ - { - "int": 2 - } - ] - }, - "v": { - "list": [ - { - "int": -4 - }, - { - "bytes": "" - }, - { - "int": -3 - }, - { - "bytes": "933a74e1" - }, - { - "int": 0 - } - ] - } - }, - { - "k": { - "map": [ - { - "k": { - "bytes": "814265" - }, - "v": { - "bytes": "da5d8e" - } - } - ] - }, - "v": { - "list": [] - } - } - ] - } - }, - { - "k": { - "map": [ - { - "k": { - "list": [ - { - "int": 5 - }, - { - "int": 0 - }, - { - "int": -5 - }, - { - "bytes": "" - }, - { - "bytes": "4ebc" - } - ] - }, - "v": { - "map": [] - } - }, - { - "k": { - "list": [ - { - "bytes": "82eab17a" - }, - { - "bytes": "" - }, - { - "bytes": "dc8240" - }, - { - "bytes": "" - }, - { - "bytes": "e0de" - } - ] - }, - "v": { - "int": -4 - } - }, - { - "k": { - "bytes": "9775ec" - }, - "v": { - "constructor": 244, - "fields": [] - } - } - ] - }, - "v": { - "bytes": "df3af859" - } - } - ] - }, - "inlineDatumhash": "15894fdba454dc17ec885d0abf89e584ac00b30ae818e3a4082bfe90850298c8", - "referenceScript": null, - "value": { - "lovelace": 7 - } - } - } - }, - { - "tag": "DraftCommitTxRequest", - "utxos": { - "0304070203070403060803080406000101080105080602020308000403080305#11": { - "address": "2RhQhCGqYPDpo7f2LSbv7RSAXmGJgBn8EYxdT5Y5H9f1WUcMUXU66RqhE9sXWt9ZAzzN4yTAMkx9sNAXW6JxJ6Z118Tt2m2YARjJMrnLQDnQjJ", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "map": [ - { - "k": { - "constructor": 629, - "fields": [ - { - "int": 3 - }, - { - "int": 4 - }, - { - "bytes": "62ac" - }, - { - "int": -3 - }, - { - "int": 5 - } - ] - }, - "v": { - "map": [] - } - }, - { - "k": { - "bytes": "8e" - }, - "v": { - "bytes": "bb5413" - } - }, - { - "k": { - "constructor": 250, - "fields": [] - }, - "v": { - "map": [ - { - "k": { - "bytes": "d3" - }, - "v": { - "int": 1 - } - }, - { - "k": { - "bytes": "39e12893" - }, - "v": { - "int": 1 - } - }, - { - "k": { - "int": 1 - }, - "v": { - "int": 2 - } - } - ] - } - }, - { - "k": { - "int": 2 - }, - "v": { - "constructor": 609, - "fields": [ - { - "int": -1 - } - ] - } - }, - { - "k": { - "list": [ - { - "bytes": "e4f0" - }, - { - "int": 0 - }, - { - "bytes": "7d8f6118" - } - ] - }, - "v": { - "constructor": 221, - "fields": [ - { - "int": 3 - }, - { - "bytes": "e1" - }, - { - "bytes": "2cce0b" - } - ] - } - } - ] - }, - "v": { - "int": 5 - } - }, - { - "k": { - "int": -4 - }, - "v": { - "constructor": 963, - "fields": [ - { - "list": [ - { - "bytes": "e2c480" - } - ] - }, - { - "map": [ - { - "k": { - "bytes": "" - }, - "v": { - "bytes": "" - } - }, - { - "k": { - "int": -5 - }, - "v": { - "bytes": "e7" - } - } - ] - }, - { - "int": -5 - }, - { - "bytes": "43" - }, - { - "bytes": "d81f5477" - } - ] - } - }, - { - "k": { - "int": 1 - }, - "v": { - "list": [ - { - "constructor": 205, - "fields": [ - { - "int": 5 - }, - { - "bytes": "1c48de23" - }, - { - "int": 2 - } - ] - } - ] - } - }, - { - "k": { - "int": -2 - }, - "v": { - "map": [ - { - "k": { - "int": -3 - }, - "v": { - "map": [] - } - } - ] - } - } - ] - }, - "inlineDatumhash": "2348042812fd5704e8eefc545a9f2c93d39265fb9786e3a7aaddac58788c3046", - "referenceScript": null, - "value": { - "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { - "010606": 10 - }, - "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { - "000200": 4 - }, - "b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54": { - "0700020302": 5 - }, - "e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541": { - "030606020203": 6 - }, - "lovelace": 16 - } - }, - "0308050000020802010302060007060101030300040603060301020107030101#67": { - "address": "2RhQhCGqYPDogL3sRz1L28gTfAHJYadPTg1ZYZbX95da6qqBG1SBiska79ZrTRPSHHkT8eXxMrzrk7GtzbU9twp71hNmKShEDtiDHXKd3qvVZk", - "datum": null, - "inlineDatum": { - "map": [ - { - "k": { - "map": [] - }, - "v": { - "list": [ - { - "int": -1 - }, - { - "constructor": 766, - "fields": [] - } - ] - } - }, - { - "k": { - "bytes": "4e0ccc4a" - }, - "v": { - "list": [] - } - } - ] - }, - "inlineDatumhash": "564d870549e4c7d3c5dd95244cf78a545d3cdd284bc1983e991c13f6fbc16cd9", - "referenceScript": null, - "value": { - "65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7": { - "03070300": 15 - }, - "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { - "070506040805": 1 - }, - "bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2": { - "": 5, - "020400060701": 7 - }, - "lovelace": 16 - } - }, - "0406010505070506020100050004080507070205040201010308000506080508#17": { - "address": "2cWKMJemoBakjYiHDCCgXqey688KX5GSTQ8boe9ZjS5AeRYS5amN3WGocaZnW5WfRhHtS", - "datum": null, - "inlineDatum": { - "bytes": "" - }, - "inlineDatumhash": "39df024ac52722fe8ae4c1a8740e4c5624a38c3820e504a059aae8728421f8bd", - "referenceScript": null, - "value": { - "3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e": { - "0504": 9 - }, - "eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5": { - "080800020200": 14 - }, - "lovelace": 2 - } - }, - "0600080805080503000305070100020306010605010700030707080103020802#93": { - "address": "addr12xckk4h4asryhe4v8j4kqd0046rtxekv8hz2p4t3vq7hpevy5czsxzqxvpmv7", - "datum": null, - "inlineDatum": { - "int": 3 - }, - "inlineDatumhash": "e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec", - "referenceScript": { - "script": { - "cborHex": "8201848200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54830300848200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b782041933d2820419577082051a0001810b8202818202818200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88201858200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88201848200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88202838200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e82051944af820519c5e1", - "description": "", - "type": "SimpleScript" - }, - "scriptLanguage": "SimpleScriptLanguage" - }, - "value": { - "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { - "060402": 10 - }, - "1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48": { - "0305070508": 6 - }, - "58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7": { - "060704030800": 6 - }, - "65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7": { - "02": 7 - }, - "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { - "0208050403": 3 - }, - "lovelace": 8 - } - }, - "0805080505000508080606060800050407080306040502020402050308030104#17": { - "address": "addr_test12p9v7fmnj978k4ru2a48lugs62a9wv7p789fehr9nt4r54k9zgqsswlcpfp", - "datum": null, - "datumhash": "4f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce8", - "inlineDatum": null, - "referenceScript": null, - "value": { - "1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48": { - "020207": 4 - }, - "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { - "000504080103": 11 - }, - "a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a": { - "0200010307": 10 - }, - "b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5": { - "": 2 - }, - "e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541": { - "0401": 9 - }, - "lovelace": 4 - } - } - } - } - ], - "seed": -1356442595 -} \ No newline at end of file diff --git a/hydra-node/golden/ReasonablySized (DraftCommitTxResponse (Tx BabbageEra)).json b/hydra-node/golden/ReasonablySized (DraftCommitTxResponse (Tx BabbageEra)).json deleted file mode 100644 index eaf214f1e81..00000000000 --- a/hydra-node/golden/ReasonablySized (DraftCommitTxResponse (Tx BabbageEra)).json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "samples": [ - { - "commitTx": "590aac84aa00818258200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c060d828258202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc101825820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce070183a3005822513542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e86875f0608018203a1581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a14506080808000a03d8184e8200820181830300818205194879a300585082d818584683581cf761ff93c249013d9f3a403758f4d27dde6b269a1867d3cae4946c5aa10158225820747577796e746f69696376636d716265787a766b726961696a72767671726965021a4634d483018205a1581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a142030503028200582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314a200583910bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c20d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4018207a5581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a14009581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea1460508050701010b581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a145080102060502581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa14605060508080809581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a1430804010c0219033b048583028201581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b782018200581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb4882008201581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af58405581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b75820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e258405581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e558200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c05a4581df0b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54190307581de04acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5608581de0b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e51903c7581de0bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c21901580e82581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af509a1581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea143060402250758204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce80f00a60085825820dd68e3831c03ee95777db844d3dbb7a4511e5db8fd1d83690598a78d6e0c767058409205e45668ef02ac3d2994f88e01e88c6ebccc3261daf98925a963a4fa92cb4907f21184326d85d9989e25b89cc8ee1147ebdea3bb30b60bc4af98a742ff41fe825820929ed67e7223310e635fa221b4f78efacd50ed36e35f31ac7eefd3cc1d998caa5840afac243b5c8c3670495c696191a38ea7ad51397c2e79d9e416276600ebdaf3cbbcb9a2316b3e98426f36221af64ebe7874bbcfe21cb1fc32556755aa279d0b5d82582045315314159232edd7d538e3199eacc7056e3839166d64f106421c83547bb277584041eb075cb9609669a72abf2156794e3ff695aecc4f6f3e239be7538fd43e30100e14f7f7a62575c226fb381416bdfbc5f513730772d47afdeba8ab8ad27b22ef825820db4bd7fed059de2c97270147fdc4693ff8675fddb6ce9d3fee3a290ef5ba2c725840d5487d6b9d8e534cbbd6c023d8d6fd747f176be7ea2dc003dca34d3af63e9b85ad6c8554d427a8ee0be52fe2c4ca1281045c96e675292413e3f28a6319edbf9b825820a45e22527406171b27b59680a767b4a9b21a5020079e330058f4f260f9db85b15840122f4b64fffc5940bd118195f7e178810dd32fbabb5cb156b0f6f8491830ebe112fb03157257e885c28c976df4a2b337730e20e6dcb09cf1d5aac590fddb9ddf0281845820afb8ad5008f037a28ada8c79091df8cda2f34d5c110732a2fab9fb16b405578658402cf70a08e34deb1fa66510a0f82d09a9c60d8fd5fb6f0484670f5af3570f54b3ed9a507ad365014f719d6fc1e3f1ef2c78c76c153481720be8d2f3d59982a7c6455207338a55457c42710ce9018182051a0001782f0381464501000026010482d866821902289fd8668219022f9fa143d12e784438c276aba421446d20f8bf020540402143787a44ff9f9f0041c10142158640ff24ffd8668218ce9f2242b5a9a043201b1fffd8668219035b9fa400439f507d240224402144f55a93ca214459fd0424a0ffffa5d866821902af9f9f23ff21ffd8668219036d809f9f0244990d7c7942e6d12201ff9f2223004174ffd866821901139f200424ff23d8668219026f9f23ffff8020d87d9f439195702401a40224425d37024044c98c0a4a43a70e3d43129c3180ffa4d866821902309f2342187f4022ff0244ddd23120d86682188e9f423cef21404001ff9f01ff9f41040141d3ff43e52165a522425471034297f8441561bdc02240404243764043f6f57b43a6eb16a3a500240543f707bc05417f42e8590444039774a8209f414d40ff4109d866821903af9f44b0b9317902ff9f418902ffa44196240444296bd9c64165242042cb5a05818400014192821b2d434789f8c5de571b1674ec8f239b7068f4d90103a200a20e030f425ec2018483030182820519325582041a0001714882018382028482051a000124f98202838200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548303008082018082041995c98200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e782041950ac8201838303008382041a000153e5830300818200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8820519e92f820281830300838200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8201838202818200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8201838200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f5482051a000163c5", - "tag": "DraftCommitTxResponse" - }, - { - "commitTx": "590dbb84ac0084825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de9273420482582095c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd305825820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa00825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad030d858258202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc10282582095c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd308825820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce01825820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e2505825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922905128482582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113140682582095c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd308825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec03825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d99229000186a300585782d818584d83581cbbfdbbc53f5debc784448d0f80ab439bbb6131ae885a77385a1c1a2ca20158225820706c696373626c7178656e73696c7566626d717872647963667470766d796e7002451ab042271d021a942ad93b018201a3581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a14604050400060607581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a14607060408040402581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a14005028201d81858629fd86682190215809f4080a1432f869124d866821902e29f03ff20ffa44208fc42ed19d8668219025d80a324244440723ff0014022422a2ca102009f01ffd866821901569f445835c67224034407ce863cffa19f4267da4266d440ff44bc3d5f84ffa300585782d818584d83581c1c36248e874bbb3df23c33c4de8b7f9e6ec5f7652e9a52a9e6326076a201582258207861766c6262787075737677637167796b736e727165647467646e6d6272696602451a26c34d66001a314b9d33018204a1581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a244040201000c4408020804080282005820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ada300585082d818584683581c69455b3f9ef9ccb9c1e388dbc08298329a560645da30b6f7fa935a49a101582258204e87f39c5b04dd765fccf108e1d99c2aafefcda12d0c4fa75b33096489c98078001a9b378c40018204a5581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a14504070102050b581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea14202020c581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a144080500050e581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a14603030605070305581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a144000803030703d8184a82014746010000220011a400582140bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2d97e0001018207a4581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a14007581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a145030104020008581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a1430202020c581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1450501040102050282005820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e2503d81849820146450100002601a400583901bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c23542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e018208a4581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea14305040708581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1430000010d581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a141000b581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a14206000f028201d818412203d818582282008200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a3005839000d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5018208a4581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a14307070409581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa142060602581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a1460500080306060d581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1460001010003030a03d81858fc8200820284830302838201838200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5830300828200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e482041a00014b968200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54820519111310a300585082d818584683581ce90d35df20f8b4ec5f218291453246f2e07b33eb152bee70dca01211a10158225820726875627567696b6d736c6c656b78666467706e71746f77786f7269766a6478021ae4002853010c028201d81841400219035c04818304581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f541a00011ce505a5581df0b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e51901e3581de00d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4190297581de04acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56190201581df165fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b715581de1e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541190313081a000109600e83581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b809a1581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a2402d420105020b5820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29eca600838258208b1b73e98349a1d8933390a2d6cb222d5df04b914373dfb76679d0fcaf813d0d584060a16f4fcc915b1434336fab7a8cb0f455366accf03498b597ac1cdf4d9735c3b20b6e0bad90f73110f724523734b60c9e4332f24f5e458ee6aa4b171967355f8258203ad7187de6de19f551d293b66ccaea88e89bc56de9c6784b2003049493276e23584012415c5a6408b17a31b43cdfd264472504efe28c9438f280b090d3b8164851343a35fc88a5eb906f5eabf2c6f368b80813f155e5dbe3e40974b391c22b76b9e6825820dc211ebd9a2ce28111b4d1df7f16db3be24dc467ab185fb6e08f2db185a80f7f5840f803e741563491ed4ced339ff7f119255dda2fd9816bffd7a31845877bd8aeb918a75b78b2253c8b86afc0e47eadbf9afe20206e9443792bb1d60b88b875eb860282845820f4588c8dad561778b138b06aa991378ec65fada1b4b9af5e5f18de502b30adba584064737866796e787a676c737669636c66687971716664686f736763766e79766b6c6e746f677061666c726f69777263617a75666270646e796e6d687a70716e6c44c45c58a9449a6f9ccd8458203fc97a816240bfd72894d93a425c0fb61126f87148f0819497d3d44c7d30f3515840666b6f667369666966686b61697979766b7a6e6c756a757273777876676478647467727a7068616f64746376616d7a747a6a6f686f756f62796c6d6b6874666d404342fdc001838200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a0681464501000026010481d866821902cb9fd8668218c99fa044e0027d709f41a70042d74642473740ff4154ffd866821902cc9f9f20ff2200ff9fd866821903e19f0300ffd866821901f69f03431616c102ff41d8ffd8668218909fa0d866821902db9f42b929ffffff0581840103d8668219023c9fd905109f9f42293d04ff01ffd9055f9f9f044359c7aeff809f2443f420a04040ffd905229f4262be05ff9f42b180415344fdc6a28644b27f2d46ffff41d0ff821b7833f3757f84cbd81b76d2979c1713751ff4f6", - "tag": "DraftCommitTxResponse" - }, - { - "commitTx": "590fd484ac00838258200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c048258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce802825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342070186a200585782d818584d83581c3f813e8826cec9c3b8ccf528b8bc27d543c065d54fb4f647aad20938a201582258207073747864686b7964616b72707468746b70766f6e6772726879766f6f6f736802451ab74aece0001a411c35b101820fa3581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a14507030006040a581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a142040002581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a14608030200060308a400585082d818584683581c22f99cc85129e9f77df95f48d51e52c8d68a062142e1e083b2dee872a10158225820042014ad208d9dadc76cbe9f198c84f651cbc6f698bbcbce197e248c07c55748021a9f9a7ad1010f028201d818439f40ff03d818478200820419e2cfa400585782d818584d83581c8a39a45a085c15915036c61666ad3cbeb90f58b9224aa0d40acf449ba201582258206f617168747a62646f707869647a63776f6270647471686b6a7675676d6e6a7002451a4314b4fa001ac299a8a5018202a1581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea144050208060c028200582095c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd303d818582282008200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a400585782d818584d83581c082009dca920b87a760d29acbedf10ada44a2f5ddab13438d026c577a201582258206264786179657264676b7678696e7877766f6c766b6378646d7561656f6d737902451a181809f2001a3977cbd301820aa6581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a145030805080507581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a14303010808581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1440308000603581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a14001581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a14202040e581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1450303060407050282005820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce03d818585e8200820182820285820519301a82041a000178778200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c282051919c9820419fb8ca200581d71eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5018205a4581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a141020c581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa1400a581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a244040602000f4504080800070d581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a14608040206040508a300582251e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b08254185b9500702018204a4581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a1430306000a581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a144080704030f581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a1400a581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a142030106028201d81858459fa59f43bb3c25ff4024804001409f400205ff039f0143d67a56ff9f9f05ff9f2421ffd866821902f79f412942d15fff9f22ff00ff41bb9fd8668218919f04230521ffffff10a300583921eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af558e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7018209a3581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a1410703581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a1410603581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a1450201070800040282005820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de92734211190187021903a70319d710048282008201581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b882018200581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb4805a4581df01920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb481902e2581df176e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b818d4581de11920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb4818bd581de158e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e719028b081a000115d70e84581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f5409a4581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a1402b581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1400e581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a1430105010e581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1450301030408240b5820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342a6008282582099b3f820b688abd5dd6f42cd5e613b88e70f1842ba6c0d552ab99b9f16a899b25840ea968d01067886e1b2ffe15a1577a0c62c579a454f8d043ee342a0d0815e5c2e38a93b6f27445bcd38e8cba4d00617d04ffb46573150ff364b57dd9a7065286a825820bba2b0ec0c662029120c3a31ba3aa2ea2cf0dbf2676a0f2db54cda4d97a4133a5840deb5218f101b6fb5fd42114d9c3d509a5b36901425550a3e1f7ffd2e68e480618a11d2cc0453fc9bbe3995094f305af9a0f04a4600beada30576510a3eef62a3028584582048954680cfb1917a8d8f9e85b7cb43ee69b95109019b8767bd6489ff6d5f24ad5840686d656170686166656a7664776170796e62696b6f76767273796e7763717167736361626b647570676e6c64636c7368746d7765716d787a6b68666b6361647843876b5c42c87684582046a07312e7fdd35a35927d68f37ea851bc937750ecfa7fd71a62180257a4a7d45840ad829a1f7f5bcd9f10e653c53fa9233a4d1ba30ba81c68426267792ba109598ad85809406da8198f96e6941f08c9414a3ad799b88983319b325c1e411cfe238643f592a5433770db84582010fbe831dff0bcc52fd6a20f2fbeeeaa57abe916512318d0e8b10942f36855375840c54794dc76a5db71a1674b0b9c4c39cd5bcc1131b50ff87b01c56026dd49ce780314449fdafe7085620abbc6c2a84691992a375cbcee2dda960610fbf2093fff45a31781be8942d16e845820edef3d4e8e159ff67621ed916bb58078e53eab2164681439d5427b2d740aad55584075fce64cd031b570598b2bf935fe218f03f5ab687139e3bd78dd7cf1c895b1d69e34ac69269e2a342ea817a2afe2890ed3d4e64633fdf74b59f57cf4788ee914415543927baf8458208f2b5007acbb1f4b6a3754f2029ae9204abefe5cbd88719078840ba27d821d5d5840686c6c656d706e79716766786a6779637469696f6679786c616161776b6964756a71636b726a66776f716b6d7574636e72756965636f757564656c6a7272726644bcb25b9041d90185820419cfd783030182830303858201838200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78201858200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541830301818200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58303008282051957638201838200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4820280820419d30682041990570681474601000022001104869f4480e86966ffa5d8668219038c9fa50120419d01034320b44922413003410ad87d9f01404040ff42df90d866821903c09f04404311b12824ff00ffa19f2000ffa2437d45c8431a51340201039fd866821901b79f41b901ffff40a49f4043062c24ff41b3a24303c8cb02447590155322a144a7bad598413ed866821901759f437688414461f40eafffa0a324234042bc7c224042ac58424efe052143d47e25448e1f50e2429d51244306edd6058384000c9f22445a522fa5a4d866821902b09f43e2238941f821ffa54001411443fcf7cc0042d2bb43147e0f224121410f029f414104ffd8668219023a9f240140ffa42042a7610441a8040342ca1243499bd88041c720ff821b78605f68091a3e2c1b185824fe868da5ef840208a4a09fa0ff410f24a4d8668218a180d86682190256802140a2240544a6864fc942b2f8a10300a0a2020100429e78d8668218d79fa241484444eff44d437aed7305d866821903ae9f02432603a801444fe45fe2ffa30021242022426f08d8668219018f9f40415b4449095485ff445d2e9925ffa49f0520ff24d866821903b79f0124420ad4449a898f7e42a59dffa242d9d44021424c8f204314400980d866821901649f2440ff44a51b120b821b7b9231d76013cc371b74c008c92ff82ce984020a9f42ea3301d866821901d49f409f234432a7f11205ff20ff9f432c6eaa41fcffff821b6e75d57c60f9490e1b3ac70ffcc465d2e5f5f6", - "tag": "DraftCommitTxResponse" - }, - { - "commitTx": "59095d84ab0085825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec08825820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e2506825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922902825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad01825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad050d868258200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c03825820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa02825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec01825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec05825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922908825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad03018010a200581d70a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a018207a3581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1430408000f581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a14006581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a1400d0219038c0319d6be04848206820119021d8304581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b81a00013ea78a03581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b75820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa18cc1825d81e820001581de0bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c284581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418682026f666f6f2e6578616d706c652e636f6d840007f6f68301006f666f6f2e6578616d706c652e636f6d8301f66f666f6f2e6578616d706c652e636f6d8400f6f650b80d012000000000000000000100000082026f666f6f2e6578616d706c652e636f6df68405581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e58200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c05a5581df0bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c21901a2581de00d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e41876581df1b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f541902f1581de10d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e419033e581de165fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b718240e83581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b709a5581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a14200032e581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a1460807030306050d581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a1440003020821581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a144070008020a581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a14204052a0f00a50084825820e4d8d45d6ba19c67a48f76b87fdd6bccc430eb76a7f3ca9733b17aa75f66514158408d17b4b72e3cee05cb45f04ceab79362e9815b6e08077ac8176d3db795f87a73baad5e4e76867b5b0be1e6ffd5da5087b86738e4327334eab78b15d6203e980c8258206d1a5bcc1fc50b3be647273190af6e15f5315baa018ca5348b427b551221d88d58400fba855abc567a89f0ae5ebd47d45c9fef887a384a40122b6d77848f8324bcdc57695a44002a8e68c4bb393c64205eaa9cf078f05954f0bb2cc418e49504dc98825820ae16a860d64fc08a6c212963a97128071bbe5b027f2dd25172acd7ebbd637368584048f1a0b621f311ec5516e996e24b34722f94ea5157539819655efa411597c0bb41a5ccbe6d69beb681c05a438aefb7cbb9a7921ae08a2429faee9bcb9aaf024c825820a37c93c0218211bb560e99a47c8b093bbce6990f6aef6dbc5db94d12de9a8d085840a065f36a7684904f7589e71f4920dd58715bdcccc3efef885147a93c87d653a894208b07b1cc02cc4b76998126d914f5a7d19fc0675f778f68ea76d02c317c780282845820d48668a5ace477790e2561ffeaa3b9106069e61a92ed28170650c0f1e565b398584071796f6d706c656a6c7466676d6a767464746d6b6c7a79626f7272636168786579657a737477617272616f76786a7576697877726b67686a71616c617776796841a840845820e53a4f834dfbeef9fb77b9e7994ca0e992f553e3e978ef678438d569e6afda8558401adcdf70973030ed5e8a2821fa67ce1c4221e188e7b4189bf474084c8c9bf0ae57c0151d499bdf40d586aa9523af6a1143e45024be7d49490a7bbfce84af381241574218f20181820519dd0e04824020058584000620821b162026b952db067e1b5d2d97faf4609a22840200a4d866821901ff9fa09f43cc2b88ff427b1cffd8668219024280d905339fa044be0e8d6d438a23394452e86d26a444045bf59202445200395341af44e5a66a5d40445078172e04ff214321a198d8668219016f80d866821903379f002220a52344a947651a20224002425a8002220104ffd9050d9fa09f02ff9f42397f0040ff21ff821b5658e76626d3d0651b4290fe09f23bcce6840205d905669f9f9f4041640141d722ffd866821901af9f2040234231cf04ffffff821b4d8a3985f52b76141b7a5a520eb6075c298403084480aeccf8821b75be54373d9ff5101b447d2fde82503add84030f05821b4c34a9f5699c176c1b22abceb17520970ef4d90103a100a202210b64453c373e", - "tag": "DraftCommitTxResponse" - }, - { - "commitTx": "5913f684ad00800d828258200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c08825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d992290412838258202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc107825820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de04825820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce030184a300585782d818584d83581c3d05f0f7f5e54cb789be8bc5e2c506f05f3c3f7a11f35a07979d168ea20158225820636c6a796a6b777a7878706b6f79757262616167776f7073687461627265796802451a8ec0ab72001adf75d2b6018209a3581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a1400c581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea144010703060a581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a143040302070282005820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711dea300585782d818584d83581cb27f74dd83248d84ec73170c3421a59a2cfe8a3573d3c7261594d8f4a2015822582042f2bf32c6bcc8fa171135e58d8fbb72ead672d064ca3f6eb8bf36ced3aece5f02451a3d09386e001aafa50aa701820ca4581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a24201040a410304581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a1430506010d581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a14305080103581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1400d03d81859036d8200820185830302838202848200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541830304858200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f5482051a0001324482051987de830304858202818200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58201838200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48202838200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8820180820419c5428202848200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5682051937b08200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48202858202828200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78202828200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2830300818200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5682041a00014f9da3005822414acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5682b745010101820aa4581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a14007581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1460504040000070c581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a145000006080806581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a14201080d03d8184782008204190103a400585082d818584683581c3a59e43114bd1f03c8531273710840698138bce930d7e397c049eb99a101582258206a65776a78686f66716377747569706c78676762746b616569727770746a7465021af81b6541018208a3581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a1440601000202581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a1440205000208581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a14407050400040282005820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de03d8185901f682008202838201848202858200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78202828200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8303008082051a00010d7f82041a00010aa0820284830302838200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c282051a00016c508202848200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a820419465910a400581d7058e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7018201a3581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a14302010205581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a1440208080102581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a143030606030282005820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de03d8184782008204191e6a1119039c0219014c03195d9c04858405581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b85820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e2582008201581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b08254182068201a28201581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a563903e48201581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af519023082068200a18201581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e41901fe82008201581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb4805a5581df00d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4190392581de03542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e190208581de065fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b719012a581df1b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e518fe581de1eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af518bc081a0001159c0e84581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e509a3581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a1440506050229581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa14501080205052e581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a1440403010710a50082825820a1878324362e643f1656917b00dfaa3ad5f69882e9f44b011f2adc745850e20e5840068516ccd479ae66aff7b39cb5e189a2e8e3ca288f3b32edf753c2bd46043b928377fe7216db4544b6acb5936cfa88d51534d622c4e62818d86342e1305a29a48258200668b906a88d74d966fd221442df1a16d8d2d22e80eee5de076dfce0b451ff5058407c5d3fbaa6d9f61e2d68fe8590e7ef2c666d6f75515b253dcc325e4a2655e2566c20ab4f34aeef1cf08c8b7ae182f6d3ab5febdf72194f73b8feac0a692152fd02868458200cfd7ef2ed7cf3241fa93f3b78c397245ca6cbdbf61386ac1a2c8be0c885642b58406e71656b7468627165777a7371756b746866786c656e6d76656169676c687a626d6f6170646c74727a68656b6e6c7a666976726d696a636e72617a6d7a6f737a415e44309a1816845820aee547874df5a6cdc448d1ed200408f0133bfcd0179412b841d5f2d213cdce985840553213978626a376f1b3a55cb029ae636598c0cb50a6d5ed38d9e73e88ddabc8285533fe9d4ea7cb1e134a55d98f7500a351c85194a59ea4b9a042d9cb2dac2a44d7ce1a514209378458208660c6f1c9c665d28d095607c27ba5cb91a7d9c811e51ff2ba820d1b5605fb4c584063676e716b677974666373636278776666667877726a686e62786d6c786576706f74736478726476767069727169726368617361667268676d646e6d736772734045c66c56af10845820267610d8fab4f4c6feb77cc06c7654ce41e6581be95debf0b246e1ca36fa9b2d5840033bb86d350a1fc38e2a652cd6dfe3beac3cd1ba4510ea2246b4a0ebc89d686c2bbf42bcae6b9f4534fd7abc45cab4962bdbe8bf5d745f79cc5746f1507e6f6b43213c044346045184582008abbadc683aa8ceb4b3d2bf395c9059e3e9b6e68eff875ea3bda7d4d5d56ed358406c6b66626e797472746d7078676f627868686b636d6f69656f667761637976697a6864716a63676c6b76676f6a7a6a65736c637a7061696c706c757175727463416641cf845820d08ea174c78737961e07cb09993f526054982c66f3e4463aa9decefc3c6860f75840676168747671786c6d6e796e7a756b7869736672707a696a656c6977646d636d6b6f6e6a67766e6d676870696b77727773777463776d6f75676172647365646244ef50d62143f92bf201828202808303018182041a0001615d048380d866821901619f40d866821903a59f80ff0140ffd8668219026f9f0320d866821902bc9f42b7f5d866821902ca9f40ffff01ff0583840201a323d9057280d8668219010d80d8668218c09f4333e42effa204a242962d0542d0a923428309019f809f44e0235862ff445bdb834fff821b0801e249aecad24d1b5d04bfbeb3f86328840202a0821b5d90c2c81f77e09f1b7a3ee110bd529f08840310d9051f9f448a3714194451a513d6d86682189d9f40d8668218a8809f04432fb83d032443c2e716ffffa09f44c59f2db0d866821902669f04ff20ffff821b6df8b7a7c76e20eb1b2f69a9ce05cbd9faf5d90103a300a30da4a30200046044c2007cda624457a024451d72a47ec341ad452155ca22fd80456a7fba03290e440120858f0f21018482051a0001276482018482018282041a000106e9820419bf9782051906d0830300818200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e820182820419c0c58200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541830302858202858201818200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5830305858200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88205197ba082041a00016ab082041990258201838200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78202818200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28202838200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f5482051a00015147820519d73382028003814746010000220011", - "tag": "DraftCommitTxResponse" - } - ], - "seed": -1771961123 -} \ No newline at end of file diff --git a/hydra-node/golden/ReasonablySized DraftCommitTxRequest.json b/hydra-node/golden/ReasonablySized DraftCommitTxRequest.json new file mode 100644 index 00000000000..3edcc65b8b9 --- /dev/null +++ b/hydra-node/golden/ReasonablySized DraftCommitTxRequest.json @@ -0,0 +1,657 @@ +{ + "samples": [ + { + "utxos": { + "0103000005040505060604010004070607040305070802070306030506030801#24": { + "address": "addr_test1wq659t9n5excps5nqgnq6ckrhpa8g2k3f2lc2h4uvuess8s24hsvh", + "datum": null, + "datumhash": "ca695f3543876c961b97734fef4027a4fc45ca7cc6d5f796fc980915b17caadc", + "inlineDatum": null, + "referenceScript": null, + "value": { + "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { + "": 28 + }, + "bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2": { + "": 7, + "05060006060305": 3 + }, + "e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541": { + "060600": 29 + }, + "lovelace": 22 + } + }, + "0406030404070608070607040306030708050103070204060800030807050200#56": { + "address": "addr_test1wq3lgnn7swsu6a3yspd86mgkch722vt64gw6n87qt6xd7fs74u0mp", + "datum": null, + "datumhash": null, + "inlineDatum": null, + "referenceScript": null, + "value": { + "4b279a388de46bb4d33c4df64da357640be900b04625a43651b7b059": { + "0103050b04100a03": 50, + "0f0a": 63 + }, + "lovelace": 57 + }, + "witness": { + "datum": "22", + "plutusV2Script": { + "cborHex": "46040008070508", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "05" + } + }, + "0606020701020502060402000004060504010500000102020707000508030607#53": { + "address": "addr_test1vzckk4h4asryhe4v8j4kqd0046rtxekv8hz2p4t3vq7hpegexfjtk", + "datum": null, + "datumhash": "642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342", + "inlineDatum": null, + "referenceScript": null, + "value": { + "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { + "050305050207": 12 + }, + "3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e": { + "": 10 + }, + "b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54": { + "": 4 + }, + "lovelace": 15 + }, + "witness": { + "datum": "01", + "plutusV2Script": { + "cborHex": "46030007060402", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "06" + } + }, + "0701010408010403020000080005050203060502040600010503080508050501#70": { + "address": "addr_test1vqxefct5wvh0n2h88uu44dz9q7l6nq7k2q3uzx54ruxr9eqq6x8va", + "datum": null, + "inlineDatum": { + "map": [ + { + "k": { + "int": -3 + }, + "v": { + "constructor": 668, + "fields": [ + { + "int": -4 + }, + { + "map": [ + { + "k": { + "bytes": "71" + }, + "v": { + "bytes": "d7" + } + } + ] + }, + { + "constructor": 246, + "fields": [] + }, + { + "list": [ + { + "int": -3 + } + ] + }, + { + "bytes": "934a" + } + ] + } + }, + { + "k": { + "list": [ + { + "constructor": 443, + "fields": [ + { + "int": -1 + } + ] + }, + { + "map": [ + { + "k": { + "int": 3 + }, + "v": { + "int": -5 + } + }, + { + "k": { + "bytes": "68945d66" + }, + "v": { + "bytes": "62" + } + } + ] + }, + { + "int": 4 + }, + { + "int": -5 + }, + { + "list": [ + { + "bytes": "7938432f" + }, + { + "bytes": "ed5dd96f" + }, + { + "int": -4 + } + ] + } + ] + }, + "v": { + "constructor": 834, + "fields": [ + { + "constructor": 268, + "fields": [ + { + "int": 1 + }, + { + "int": 4 + }, + { + "int": 1 + }, + { + "int": 3 + }, + { + "int": -3 + } + ] + }, + { + "int": -3 + }, + { + "bytes": "" + } + ] + } + }, + { + "k": { + "bytes": "a501" + }, + "v": { + "map": [] + } + } + ] + }, + "inlineDatumhash": "f2d6eacdd86b4ad3c80719f164b6e8e540fa25b68bd6ac85ce4b00427c078b49", + "referenceScript": null, + "value": { + "3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e": { + "000605": 13 + }, + "4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56": { + "080200": 12 + }, + "lovelace": 3 + } + }, + "0705060804000004000502010506010801070106050606020503050004070102#80": { + "address": "addr_test1vrcnc35pk8mjgjjc0gfkqsgast76wc9jn36d23akk63zv3qu44jsz", + "datum": null, + "datumhash": "f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d99229", + "inlineDatum": null, + "referenceScript": null, + "value": { + "1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48": { + "05050505": 2 + }, + "65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7": { + "": 28 + }, + "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { + "": 2 + }, + "a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a": { + "0101": 26, + "0805": 25 + }, + "b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5": { + "03": 19 + }, + "bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2": { + "08050505080401": 6 + }, + "lovelace": 17 + }, + "witness": { + "datum": "04", + "plutusV2Script": { + "cborHex": "43040707", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "05" + } + } + } + }, + { + "utxos": { + "0205080806080102050101070602070500070706070201070408040803020400#16": { + "address": "addr_test1vq659t9n5excps5nqgnq6ckrhpa8g2k3f2lc2h4uvuess8sratsmh", + "datum": null, + "inlineDatum": { + "map": [ + { + "k": { + "int": 4 + }, + "v": { + "map": [] + } + }, + { + "k": { + "list": [ + { + "bytes": "2b16" + }, + { + "list": [ + { + "bytes": "0e5e" + }, + { + "int": 2 + }, + { + "int": -2 + }, + { + "bytes": "0c" + }, + { + "bytes": "41545781" + } + ] + }, + { + "map": [ + { + "k": { + "int": -2 + }, + "v": { + "int": 3 + } + }, + { + "k": { + "int": -1 + }, + "v": { + "bytes": "01f1a4" + } + } + ] + }, + { + "int": 3 + } + ] + }, + "v": { + "bytes": "4acaa504" + } + }, + { + "k": { + "int": 1 + }, + "v": { + "constructor": 515, + "fields": [ + { + "map": [ + { + "k": { + "int": -5 + }, + "v": { + "bytes": "264f69" + } + }, + { + "k": { + "bytes": "8c199754" + }, + "v": { + "bytes": "c6" + } + }, + { + "k": { + "int": -4 + }, + "v": { + "bytes": "" + } + } + ] + } + ] + } + }, + { + "k": { + "bytes": "" + }, + "v": { + "int": -4 + } + }, + { + "k": { + "constructor": 226, + "fields": [ + { + "int": 2 + }, + { + "bytes": "56" + }, + { + "int": -2 + }, + { + "int": 1 + }, + { + "map": [ + { + "k": { + "int": -3 + }, + "v": { + "int": -4 + } + }, + { + "k": { + "bytes": "" + }, + "v": { + "bytes": "885c4c07" + } + }, + { + "k": { + "bytes": "" + }, + "v": { + "bytes": "7da5" + } + } + ] + } + ] + }, + "v": { + "constructor": 711, + "fields": [] + } + } + ] + }, + "inlineDatumhash": "fc99dec556f00b361cfa01f40c070d6c49982cca2efd8cac3280f9d255857a46", + "referenceScript": null, + "value": { + "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { + "0e0b0a040110": 47 + }, + "eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5": { + "00040801040c09": 16 + }, + "lovelace": 5 + }, + "witness": { + "datum": "02", + "plutusV2Script": { + "cborHex": "450503050704", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "06" + } + }, + "0708070603050204010005080502040807000000000500060505050201010108#53": { + "address": "addr_test1vrs2w9p3nqfv8amnhgzwchtt8l7dt2kc2qrgqkcy0vyz2sgcfea4g", + "datum": null, + "datumhash": "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + "inlineDatum": null, + "referenceScript": null, + "value": { + "3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e": { + "01": 4 + }, + "65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7": { + "08": 10 + }, + "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { + "07000702": 6 + }, + "lovelace": 8 + }, + "witness": { + "datum": "22", + "plutusV2Script": { + "cborHex": "40", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "25" + } + } + } + }, + { + "utxos": { + "0803030404060006050507040406070103060007040505010506030007050401#29": { + "address": "addr_test1vrkvh76uvxt88ury3fpvctuz9jquhs62aeqjw33cazd84agz8fxfh", + "datum": null, + "datumhash": null, + "inlineDatum": null, + "referenceScript": null, + "value": { + "b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5": { + "060708": 2 + }, + "lovelace": 16 + }, + "witness": { + "datum": "04", + "plutusV2Script": { + "cborHex": "450104060005", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "22" + } + } + } + }, + { + "utxos": { + "0207030501040508070104080302000500060107020703030704080706020502#91": { + "address": "addr_test1wpjlcuy6tcqehz46wmmfwlqusacwfvm05ah5xnhutzr50dcsj4erd", + "datum": null, + "datumhash": "2208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc1", + "inlineDatum": null, + "referenceScript": null, + "value": { + "a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a": { + "": 11 + }, + "lovelace": 12 + }, + "witness": { + "datum": "05", + "plutusV2Script": { + "cborHex": "46040701060803", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "01" + } + }, + "0402000601070104000401040400000200020406070007080106080601040307#79": { + "address": "addr_test1wz66ue36465w2qq40005h2hadad6pnjht8mu6sgplsfj74qvf8474", + "datum": null, + "datumhash": "95c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd3", + "inlineDatum": null, + "referenceScript": null, + "value": { + "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { + "040603060303": 26 + }, + "23f44e7e83a1cd7624805a7d6d16c5fca5317aaa1da99fc05e8cdf26": { + "03": 7 + }, + "58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7": { + "00060503": 26 + }, + "b16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5": { + "": 7 + }, + "e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541": { + "030308": 11, + "05": 11 + }, + "lovelace": 14 + } + }, + "0407000107080202010807010006060200060204030800000500040507030303#46": { + "address": "addr_test1wp9v7fmnj978k4ru2a48lugs62a9wv7p789fehr9nt4r54sq6c329", + "datum": null, + "datumhash": null, + "inlineDatum": null, + "referenceScript": null, + "value": { + "0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4": { + "0802070502": 4 + }, + "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { + "00010208": 9, + "04000503": 2 + }, + "lovelace": 3 + }, + "witness": { + "datum": "21", + "plutusV2Script": { + "cborHex": "46030406060204", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "20" + } + }, + "0602040000070601030406040707030103040701070307020001060205060207#25": { + "address": "addr_test1wq3lgnn7swsu6a3yspd86mgkch722vt64gw6n87qt6xd7fs74u0mp", + "datum": null, + "datumhash": "ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25", + "inlineDatum": null, + "referenceScript": null, + "value": { + "58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7": { + "": 3 + }, + "76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8": { + "07": 12 + }, + "a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a": { + "040702": 12 + }, + "bd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2": { + "050501": 28 + }, + "e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541": { + "01": 5 + }, + "lovelace": 6 + }, + "witness": { + "datum": "04", + "plutusV2Script": { + "cborHex": "4407080104", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "00" + } + } + } + }, + { + "utxos": { + "0102020407080100080404020705070705050302020708060508040005030208#12": { + "address": "addr_test1wzckk4h4asryhe4v8j4kqd0046rtxekv8hz2p4t3vq7hpegsw4juk", + "datum": null, + "datumhash": null, + "inlineDatum": null, + "referenceScript": null, + "value": { + "a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a": { + "02": 2 + }, + "e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541": { + "000400": 4 + }, + "eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5": { + "0002": 9 + }, + "lovelace": 9 + }, + "witness": { + "datum": "04", + "plutusV2Script": { + "cborHex": "4100", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "02" + } + } + } + } + ], + "seed": 1516724826 +} \ No newline at end of file diff --git a/hydra-node/golden/ReasonablySized DraftCommitTxResponse.json b/hydra-node/golden/ReasonablySized DraftCommitTxResponse.json new file mode 100644 index 00000000000..227a44484fd --- /dev/null +++ b/hydra-node/golden/ReasonablySized DraftCommitTxResponse.json @@ -0,0 +1,20 @@ +{ + "samples": [ + { + "commitTx": "84ad00848258200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c06825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de9273420282582095c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd308825820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce040d85825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de92734203825820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa06825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec07825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec08825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad061284825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de92734208825820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de01825820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce08825820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec030184a400585782d818584d83581c0ab8d95ece6f8c5ec22ca9b6bd6ead48c29b28ad293851c9666931eaa201582258206671626c77717874666a6e73636c72727864786b786367757a74696e7478637402451a87ab04c8021a6cf0b0f701820ea5581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a1460003030501020d581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a2401042000408581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a145020107000701581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a142070401581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1440605010304028201d818412003d818582282008200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a400585782d818584d83581cc457b0349a5742814ecf9b6ecde00c9f7e17e1c23ae2c75527939fa4a2015822582062626a766a6a6f636276617463717476756563776365766e75676b646f656f6502451a2296ed0a021a4118ef6a01820ea5581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea14206080c581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1460806000105000f581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a1440707040803581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a14304040306581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a2460001010004020d41030f0282005820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922903d818478200820419db52a400581d60b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54018206a2581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a1460500040208080d581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a3460502050607020d42060206460705000601060f028201d818581b9fa1d87a9f446b63407c429a5203ff0502a280a02443b82d5d23ff03d818478200820519f74da300581d6165fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7010703d8185833820082018382041a0001853a830300818200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78202800219031b03199c0d04848a03581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb485820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa1901991852d81e820508581de1a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a85581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28384000344c000020150b80d012000000000000000000100000082026f666f6f2e6578616d706c652e636f6d8301f66f666f6f2e6578616d706c652e636f6d8264746578744a62797465737472696e678a03581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb485820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de927342185a190327d81e820405581de158e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e784581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5818301f66f666f6f2e6578616d706c652e636f6d8264746578744a62797465737472696e678a03581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a565820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de1903d818cad81e820102581df04acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5684581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2858301f66f666f6f2e6578616d706c652e636f6d8400f644c000020150b80d01200000000000000000010000008400f644c000020150b80d012000000000000000000100000082026f666f6f2e6578616d706c652e636f6d82026f666f6f2e6578616d706c652e636f6d8264746578744a62797465737472696e678405581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e75820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad05a4581de0eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5183d581df1e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b08254119022b581de165fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7190108581de1e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825411901070819c8d80e81581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e709a3581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a145000803000726581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea1430203070f581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a14102020b5820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad0f00a400868258209ca80d378e4ed84e4496d73136c36ad9a4b5c37b6a0bb74c85f2a5110bafdb945840bb1e017acf3e0d221f9f2082164cab8604ab8e389bffd4a934e50b3302f7266ba00c560796c47f311e8df2ef566e227981a2021692b121279b89dfd3a2d48556825820d7106abab021f9e7846960c4f4b43db7828524706418240c48f742e53d3042f958400f9b872a54ccb9ad33473e7211ce2c4ab0211a296fcdfb967a6f9644b5ee3ba51d59054dcba3def756b10e1394c0da8323c6848546a0a6b7b7cad1d44ad020a4825820dc9337a7bfeea633775356ad61abbd920a407f4369ab219130d1391a155801c25840a8add343aa764cb0f00697545405582e0517cf76884db5b5b86d38df2148a1e7f0d1127eee9ed9aed7abc4830a55416924b6739fc0c21bded6762814979b64ea82582050aa9b8534b3a40237842ba4ed162dce740b14f04b50fe31125b739bccfd939e584092dc1ab142d91d347b5a8975fc30afe1af29a0778d2c66148e6d4839050036c45fee7081d1be46b93a49ae5c6c88eb0095dddfd232190d1ded60020ba986134d825820f0b43efd50f79e5cd1fc150fa9ce2e8b0390d73bbc0a2a3f64ee1267dc4c0a1b5840fd7ebd27c48432e9834e19978ac12f5c679bb6a4500e77a6b411fb0457b2237b6bc526601cf3455f66ae91023332f1ac36bd4093a8d7790ce8f0d51a9777866182582098cc2e85f00340f1bd89eda1caf7a332afc7f7406045ae3182185e9bb77b50eb58408be6dcf30b93822e7d133e9e39225c567024cf5ddca176f50798b7615efe21cdbb85b5d0eaefe94900eec8c55f3b31c9aacad79e0a9fef67e655c7f7cd683b8c028184582017c9cf0481cfe5613bbcff1897ffbda410c3c240fc2585561610eb23fd5832e55840e32c149647fc74c85ff4c59a40a8252876bae654093d987626ed4abf9bb99ded58e2bc44397dfa3d4de4a4aa40fdfb7938018f1485f24ad25bedb99bbb61c35841ed4450333f46018282028383030181820519e8828202858202818200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2820419ecd08202848200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78201808201838200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2830300818201828200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c282028004844004444f380964a39fa1224001219f445e28d98bff9f428d530442316640ffffd8668219020d9f04ff9fd866821901f79f4041a8ff8004ff43aca134a022f4f6" + }, + { + "commitTx": "84ae0081825820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25030d8382582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314068258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce802825820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de0112828258202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc104825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad030182a300585782d818584d83581c44e53c8740a4098e03d7f53b538cfc2e45ff47ac9da198411812e780a201582258207277716c7574776479707374716a726378726665686e6d6b796c72716f627a6c02451a2567f6c7001ad1dc1ea7018202a5581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea1440305010201581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a14602050403070802581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a1430504010b581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a142020410581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a143050106040282005820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600cea400582b82d818582183581c8ba1028c40cfac46d0617ce80996c471fc93d98caba666b248fa7b78a0021a22df3dfc010c028201d818581c9fd866821901939fd8668219013380ffa19f2140ff441d35407223ff03d81858b7820083030284820419da8c8205196d4e820281830300848200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a111902830218470319a1b804868405581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b85820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce8304581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56196ea682018200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b08254183028200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568206820018b68a03581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e5820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa19025d19025fd81e820105581df1e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b08254184581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418182026f666f6f2e6578616d706c652e636f6d8264746578744a62797465737472696e6705a4581de01920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48190160581de0b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54190187581de176e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8190346581de1b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54184c08190ec00e84581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825410b5820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de07582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113140f00a30082825820f0ba28be376edbf78c07a98fc67c1a1a600fc789eec9e534e3d37ce33adfb4625840dfb67ba391d77fc0ba75a7b1802c98b0c689331f149a7795c31b8acaede26729bf5e1d46586aec4eedd377a4203bf09e35cc5c0e1615e234e52723366f3274068258206810b5b01c9cc19de7d9fb65f6c0adef005baffc4d851b3129ac226b0ba7dafb5840cf060fd1f4872176819ca07f9e58425851b74ce70c18da3429fb835b3b444b1b7a25158baa41da2f49965de0ea8b338dc695397f4f058640aa0d8b8df997dfae01868204199cb5820519274e8202848200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56830300808202838200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e582051a000160308200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48205195feb8303008082028382051a000147df82028082028382041a000125cf82051a00013d4f82051a00016f708205194c3a058284000b05821b6a318acf848b02ae1b681ce177073874c384020504821b4eb0f367bc019b041b6b34af95ac67b511f4d90103a200a401a340614b8041a5a08241c46de782913bf09899a4f0a99d922d02822242c2cb096577f0a6898110426b0a0181820183820284820419a1af8202838200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c282051a00011c6282041a000129038200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5" + }, + { + "commitTx": "84ad008582582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131406825820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de02825820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa04825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922908825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad080d8282582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113140882582095c3003a78585e0db8c9496f6deef4de0ff000994b8534cd66d4fe96bb21ddd30412838258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce802825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de92734201825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d99229060183a300585082d818584683581c67fa44aa283b77ce90d10c786d6b2bc7292ad356c134a51a58732571a101582258200d075343c1a27de6d91a79fe415c76daaecb84340406109890e569708190c731001adfd41146018209a3581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a243040704094605070600000010581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a2460004060300010e41040c581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a1460402060505080e028201d8184342eb0ca400581d61b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54018201a3581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a14205040f581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa142040007581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a243020001024606010105060807028201d818414003d81849820082051a00012743a300585082d818584683581c011ae11c0b732270a8a04ddcc6ac78d138924f17c40b77067b8aa25ea101582258206165626d73687169706b716c7666687a756473797177787871646c6a64687677001a344f03ba018202a5581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea145030307080602581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a142010405581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a1440703000201581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa144000206000c581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a14200070802820058202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc110a400585782d818584d83581c692d925c024075156343e6b6f0032af3a780e4d450b5510786567530a20158225820787a7079756f79787a70627962646c7971756766636a676f797a746c7779776702451a960a2aec001a5c5637ae018206a2581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a1430305050e581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a1430602020a028201d818434245a303d818582282008200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2111901e9021901ab048682068200a58201581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb481901d78201581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e53902c38200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b718e48200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c219034a8200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541390339820682011901e28a03581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f545820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e2518871837d81e820203581de0e0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b08254183581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541808264746578744a62797465737472696e678405581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e5820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce82068200a08405581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c25820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad05a1581de0eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5190252081a00012d260e84581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af509a3581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea1410601581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a14010581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa14408000001030b58200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621ca50082825820c46fc8fc5c4b3db3c102c24155619bed7427b6abb35e238908f38dd6b4200e4d5840ac6f9e17b7b4af4900c3f49e7bce30d079783ced94342e1780f8e7c27988511f4bf46d819b1add78c382f211ddccc09d62cde3c9581fe6acfe2ebfb4b4d10fca825820a0c4e1d10d6085eff5f6d5c97d470b8d2d876eccbe50b736f4df26e11c17dfb658406f278d02303a0e09c52ac17832ec1fc6370afb3c526c77062847fdf337a689156f01219ec302c779e330590bc1415b547ad3c022ffbc6e8eb4918076c076cc740282845820ba835577a585d835a2252d44fc12061d16cc2e6c13d923d67ec39c36e7b24ff65840a5858812bd926e53dd5f4a5a83afef780b461228302eb8b439a8af88e55e6421e928bf83f24e94b95db8d5aa060373a273c277b38cc10ae57b99b05a2f75460c42dee441e2845820cd472123feb72c46b1df581c53c68b27e33659f3ed5fef945df8456c96d12f595840fe7eda80e45c0e5c3e2f871cd0588593f9976e325cb5099b1b0b1c059fa57427c613b8251952b7eedbe7c76ba73238cf9289ded3749a39d08040decb3dee5c4844bba095e74306128301818202800484d866821901e48042218d020105868400019fa0d9055e9f0142778744fef66a26ff40ff821b3d7a4d21fa4ca7621b4887bec6ae030696840003d87f9fd866821901639f9f42b07705ffff2104a5d866821902e19f422756ffd905499f404024ff8043095b35d866821902309f20400000ff01435a9ccda42144aac5c52d431a3744404233e50144271685fd00d866821901a480439d573dff821b753b23ec10673d611b4b6ff54534a4affe84010d9f40ff821b2009f65cd7f50cd91b43c7da2e7b7d48a884020a02821b6e9ba3a98d7a25f71b3cb3981d4e67e2ca84020f02821b3ff56eac7c8e63261b056d96ab4c6022a9840301a5a2a24472f7972402432787c5019f43452c9341b7234210e440ffd8668219035f9f415140ffa20144edf731052000a3a42220052141194484a91d78425f180420a2412a0244528a29ed43b2b86cd866821901db9f438bea600443549a0a420035ffa5212142f1770305426307030301249f22ff9f0440a1224335516820ffa541c041589f0540ffd866821903e79f222041b44220e202ffa3034042a26643ef7777402124d866821903bc9f204451f223860041924130ffa4034161447560bb544334533c004042d3880240d905379f446752cf79014212a2ff0423d8668218bf9fd866821901129f21ff20ff059f40ff22821b53738ddd94e3bfbf1b37333116d0e58be9f5d90103a200a403a303a460450750ffb73541c2054113614a60434f6021020522452e2cdfe5c009a00f0010650a32280864018382041a00016a918200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8830304848303048482041930ec8201848200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56830300808200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7820419d15e8205198d05" + }, + { + "commitTx": "84aa00868258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce806825820642206314f534b29ad297d82440a5f9f210e30ca5ced805a587ca402de92734208825820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711de06825820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922906825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad00825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad010d818258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce80712838258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce8018258204f539156bfbefc070a3b61cad3d1cedab3050e2b2a62f0ffe16a43eb0edc1ce807825820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25020186a400583910a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56018209a2581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a142040808581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a14506010305000802820058202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc103d81849820082051a00010be0a400581d604acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5601820ba2581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a14307000410581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a241030b44060204040b0282005820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec03d818582d8200830301828200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e782041a0001132ca4005821514acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1190606018209a3581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1400d581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a1430402070e581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a14005028201d818581da122d866821902909fa0a503044358791901050020442b816f1b2102ff03d818582d82008201838200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7820419f489820180a300583900eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af53542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e018210a2581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2a14207040e581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a14205050c03d818582282008200581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a300582b82d818582183581c3cdc4c2d3204691824263c5d96765e9adeb1c08a7994efbcb16f7c68a0001a54d1f65f018206a4581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea1410207581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a1410107581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54a145030607060009581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a14301080601028201d81858449fd866821903669f41daa44493fcdd88444b9e2096423c344403334fac430fd7b742eb940301ffd866821901d49f9f22404004ff41cb2042a0bdff9f80ff44204b6d88ffa300585082d818584683581c4029e24126599502351abce28438733cdd93254cbc832dfb5d904cc7a10158225820686a797974757770706e69796878756c636f6671687a786b6b7a737a74676b79001ad32fc14a01820ca1581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a146060000030302100282005820e88bd757ad5b9bedf372d8d3f0cf6c962a469db61a265f6418e1ffed86da29ec021849031a0001444604858405581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e5820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad8405581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a565820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d99229820682001902568a03581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb4858200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c19025919022cd81e820710581de0eccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af583581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28182026f666f6f2e6578616d706c652e636f6df682008201581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c20819d8df0e82581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c2075820ae85d245a3d00bfde01f59f3c4fe0b4bfae1cb37e9cf91929eadcea4985711dea50081825820a5abb33b8f5f273c388a954792b3144d183be1c083ec6e34b3b9d92d1138815e5840325fb0a1dfcb2fcac089dc9d9a09f0ee0677b4d810487bffb76cae3ee2bf5e4f2164149053d28ed310e6f13d47792456a0cf48c2f958c2de40c1358794b2c7330281845820422ef2b0cc9e9bae019b724d315b735763fad676411211b9e685a18136cdf00158407768666b68766378727977636d6d7864626878797a7a7a6b6a7262776e68726e76706461676d696a667764776765647068796c76766a6c6d767079686c787964404001828200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c282028182041a00016d240485d8668219029e9fa5d866821901649f24ff9f0021ff219f4002ffa34432fc1dad4159002242bd9b22230543afbe719f2443514a1240ff02ff41bb43bf3b55d866821901108003058284020040821b7952d27b2e9e66b01b09cce49e334bff3e840201a544bdef464b9f249f40000122ff9f43d56ac3ffa5230343fea95e429deb43ae589e0541580044e3677df842211c9f04044233daffff9fd866821901739f439563cdffff43d5eb57d866821902c29f0022ff009fa4438de277200142593f02212044913adeb6a52041aa402141c121242244966fb14042ec4e42cf99ff9f40ff8040821b2f07fc56af176c4e1b11c17e9edfff1375f5d90103a20183820519762e82041a00016bbc82041972170382464501000026014746010000220011" + }, + { + "commitTx": "84ac008282582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131402825820bfa726c3c149165b108e6ff550cb1a1c4f0fdc2e9f26a9a16f48babe73b600ce050d858258200268be9dbd0446eaa217e1dec8f399249305e551d7fc1437dd84521f74aa621c0782582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131401825820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa05825820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e2508825820fb3d635c7cb573d1b9e9bff4a64ab4f25190d29b6fd8db94c605a218a23fa9ad02128482582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314028258202208e439244a1d0ef238352e3693098aba9de9dd0154f9056551636c8ed15dc104825820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aa04825820ee155ace9c40292074cb6aff8c9ccdd273c81648ff1149ef36bcea6ebb8a3e25020185a30058392058e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e70d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4018202a4581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea244000304010845050604070509581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7a1410301581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a14306050007581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a14103080282005820bb30a42c1e62f0afda5f0a4e8a562f7a13a24cea00ee81917b86b89e801314aaa400585782d818584d83581cf4362c1db60604ff86e13f5c9a2cbeb8dd886d0acb7bb0eb72500b75a2015822582075727971656f646f797a756d78766a727173656f77627165726771666576667202451a67e48ceb021a7a5ae89b018202a2581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a14605010404070009581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1460404020603000e028201d818410003d8185901c6820082018382018282051a0001326282051a00014e4c8200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78202848201858200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b88200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8201828200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54830303848200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78201818200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520aa400585082d818584683581cbfeb771b4bb042887009ccd1420a6a63c18e443adf658fde6e8788eea1015822582074636675797171726e6864627a787371776374666a71736f6e786b756676736e001a02f9417a01820ea2581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a1430506030a581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a146010403080108090282005820f63498b4ae65be466e4a71878971b9c524458996450b0ff8262cddf3f0d9922903d8185902af82008303008582028482051986a482051a000142868201858200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e58202838200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e782028082051980b48201848202838200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b78200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8201828200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b0825418200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28202858200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c28200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581cb5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f548200581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a568200581ce0a714319812c3f773ba04ec5d6b3ffcd5aad85006805b047b082541a3005822401920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb488295680005018206a4581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7a1400c581c76e607db2a31c9a2c32761d2431a186a550cc321f79cd8d6a82b29b8a14006581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a1460500050404030e581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a142000409028201d8184104a300582b82d818582183581ccbbcf5e081952f05e75a5c9f484fab3dd70195e2241369a4142b443aa0021a428f503f01820fa1581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081ea1430801031003d818582282008200581cbd039f956f4b302f3ab6fc7c4bac3350a540f44af81a8492194dd2c210a20058393065fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b74acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a5601820aa4581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e4a1440604020801581c4acf2773917c7b547c576a7ff110d2ba5733c1f1ca9cdc659aea3a56a145060707010302581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5a24102074205020f581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af5a1440408080607021901d10319a3b70481820682010a05a1581de0a646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a1903190e84581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b7581cb16b56f5ec064be6ac3cab6035efae86b366cc3dc4a0d571603d70e5581ceccbfb5c619673f0648a42cc2f822c81cbc34aee41274638e89a7af509a1581c1920e782f048e9ef52acd89c4341a89c3908c6e046ad87c474fffb48a14204002a0f00a500858258206af2f57e0027505e3f6b08d6abe5336fde3891e2ced65dbb255d4d354f4a3a365840d5e0211042075e8f2471379ecc2cfb5e80eaa9a2ae5f2182670dd2d4392bdcac9da4347a5883fcfd109b4ff0ccf55fbd78dafc0748cb92648e247be288142ba58258208aa6b76cdcbd9635cc4a48a791f7738f56071274fd35820b74b0646d2922188e5840f51bc9f8f4646eda8b244708d0a298b8c783d1e25bd753dd3caaaf729a345376bd4ee8ff4477494f996d599d845f4a6c0a083aff8d0e464cf84245a9124753bf825820a0573d850bb9a408164ccb4522d09a61537187b745dc2135fb16ab9e5a9289345840319878be9ae6e2d57c4b86faf9a13f43a53aa087b7f195cc74a1eb8676f21f06134e9b150f28b2a4cdd5272acc1c17f45fefc6bcab7c858f85044ac4862da1c6825820fced95dd37c88c9031329cddc3357a3d8ebb6e4661cae658f7e6a69b5af771555840e1b869106866c8e882bc5b27e17c4bdcf4c6fe13aebeeb6c45d266b3f9ab851ce355dd9c25f0a160d12bc1064ac001c04d88ead2a53cf6de4c02dc53f222d12f825820669b10b77f4ac754d19cc48b06ddd1b4355e9ef968c145f952a3c74e84065d675840b8b08ef0bc3bfe10bfb875e57cd46679bf36d957f5ed16acb6f69d12b7670fe5344f0089f54efc36d957ac01abac75ed7ed2e9f7c996a7ef1bfd2f462b5c3ac60286845820b7780a8d1488809d35b6424e0bc1810268a9ae26455965d37f9da2372493031a58405b26c7e936df958adf31ea83963c866ae9b3d5c1a2ddeb7bd3b1ffab7592a9e1bf748ed0893a414c83117c87ef9432697c838b87c4435eb277f33735ffdf455242665541fd84582095c3f864a26175545c87464d4095317c8b72803a82a0d1f6e7db718ef3749aa35840796c6e64736274796a656e79686e707464646e737673627066646e616f6a61726a677173636a6e686d656a6266626372636c79766b62797065757376636e6b654043b39ac78458205174a34bbfd0cf1b66cfdd7cccfc9753e8f615ca2dd019a104595de54b81d1845840b428e5412a13aa34c5da73effd3058822d8246b62b26e977c48ff1f5f0137486954cd8844df08b1d2970db0c5546cb2402ef5976bf93cae3d3b3176a87ac6d6042aebc43984b208458200776905a8510e12617f24c059316cdd39e342eaa0d08814f952e69276c0c0b6558408937f2b104653eb655a257ed3477a87aa5507c8b14e60cc572ad8e54fe891b063592a96e1fd87392f555a0ce4bdac5b559a6d73fc3bf5dc0e14a8d9e1632ffbf444abad7d642d6a2845820f707819b3141e650dad70ac385e9ab8ba11b3aeba980b7275521c7fd0b3bc3ff58406d73716a747a74776d67696a696d647464736d656e646f716e636b7362697177796b6166706b696b6b676a6564796e78677a737a76696868686e6566766173644040845820f964ffa949c9c5a5dc8e7183a14f27a2aa60e329fda7157bd5838ae9667d2b8a584091ca4fb091e281e008ee0f7d59f8062ec35c01314b210dd45eb724f0e93af1557cbca9f11fc16015a330f048a2289e28fadb8a6470cd287d288dde7b885e7923419e41ff0184820419fbf782051a00010290820184820519689c820182830300828200581c0d94e174732ef9aae73f395ab44507bfa983d65023c11a951f0c32e48200581c3542acb3a64d80c29302260d62c3b87a742ad14abf855ebc6733081e8202838200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e78200581ca646474b8f5431261506b6c273d307c7569a4eb6c96b42dd4a29520a8200581c58e1b65718531b42494610c506cef10ff031fa817a8ff75c0ab180e7820180830300828202808200581c65fc709a5e019b8aba76f6977c1c8770e4b36fa76f434efc588747b782051a0001347d0486d866821901f59f8021a39f21ff2343ba6755a201004022809f202023ffffd8668218ef9f80a18041caff42bbfe41f7d8668218ce9f21ffd86682188d9f800440ff05848400079fd866821903b89f446e45939941be05d9054c9f420a2a01ffa4054469c5ef0e44867a9b9a04419240446d8275f0426ef8ffff821b487aca54793ad2171b59fb1d14ebb2293a84010741df821b04c2d622ef1cb90d1b7d77ecedd526d9ac84020d434efc0d821b56f369b8392b179a1b001070d3446980b284030ca3a1d866821903099f43784536ffa3050201440718f87142496f430e0619a3a3052302446e5d54300001408042722fd866821903229f242123415eff004041264279d7412e821b41f72cc9684ae1951b0b054f83eceea2a1f5f6" + } + ], + "seed": 1986993722 +} \ No newline at end of file diff --git a/hydra-node/json-schemas/api.yaml b/hydra-node/json-schemas/api.yaml index c4c2d9c11a5..b42f151293c 100644 --- a/hydra-node/json-schemas/api.yaml +++ b/hydra-node/json-schemas/api.yaml @@ -72,7 +72,6 @@ channels: type: string enum: ["yes", "no"] - subscribe: summary: Events emitted by the Hydra node. operationId: serverOutput @@ -116,8 +115,15 @@ channels: servers: - localhost-http subscribe: - summary: Hydra node drafted commit transaction responses. + summary: Draft commit tx response operationId: draftCommitTxResponse + description: | + Possible responses of commit endpoint are: + * DraftCommitTxResponse - 200 ok + * CannotCommitReferenceScript - 400 bad request + * CommittedTooMuchADAForMainnet - 400 bad request + * UnsupportedLegacyOutput - 400 bad request + * SpendingNodeUtxoForbidden - 400 bad request message: $ref: "#/components/messages/DraftCommitTxResponse" bindings: @@ -126,7 +132,7 @@ channels: method: POST bindingVersion: '0.1.0' publish: - summary: Requests sent to the Hydra node to draft a commit transactions. + summary: Draft commit tx request operationId: draftCommitTxRequest message: $ref: "#/components/messages/DraftCommitTxRequest" @@ -257,22 +263,6 @@ components: type: string enum: ["GetUTxO"] - DraftCommitTxRequest: - title: DraftCommitTxRequest - description: | - Provide a utxo that will be used to draft a commit transaction that will be sent back to the user. - payload: - type: object - required: - - tag - - utxos - properties: - tag: - type: string - enum: ["DraftCommitTxRequest"] - utxos: - $ref: "#/components/schemas/UTxO" - ######## # # Server Outputs @@ -755,19 +745,57 @@ components: timestamp: $ref: "#/components/schemas/UTCTime" + DraftCommitTxRequest: + title: DraftCommitTxRequest + description: | + Provide utxos that will be used to draft a commit transaction that will be sent back to the user. + Script utxos must provide a witness, regulars can omit this. + payload: + type: object + required: + - utxos + additionalProperties: false + properties: + utxos: + $ref: "#/components/schemas/UTxOWithWitness" + example: + { + "utxos": + { + "0406060506030602040508060506060306050406020207000508040704040203#89": { + "address": "addr_test1vz66ue36465w2qq40005h2hadad6pnjht8mu6sgplsfj74q9pm4f4", + "value": { + "lovelace": 7620669 + } + }, + "09d34606abdcd0b10ebc89307cbfa0b469f9144194137b45b7a04b273961add8#687": { + "address": "addr1w9htvds89a78ex2uls5y969ttry9s3k9etww0staxzndwlgmzuul5", + "value": { + "lovelace": 7620669 + }, + "witness": { + "datum": "02", + "plutusV2Script": { + "cborHex": "420606", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "21" + } + } + } + } + DraftCommitTxResponse: title: DraftCommitTxResponse description: | - Emitted by the server after drafting a commit transaction with the user provided utxo. Transaction returned to the user is in it's cbor representation encoded as Base16. + Emitted by the server after drafting a commit transaction with the user provided utxos. Transaction returned to the user is in it's cbor representation encoded as Base16. payload: type: object required: - - tag - commitTx + additionalProperties: false properties: - tag: - type: string - enum: ["DraftCommitTxResponse"] commitTx: $ref: "#/components/schemas/RawTransaction" @@ -1246,6 +1274,18 @@ components: tag: type: string enum: ["FailedToDraftTxNotInitializing"] + - title: SpendingNodeUtxoForbidden + description: | + Raised if the user tried to draft a commit tx using internal wallet's utxo. + type: object + additionalProperties: false + required: + - tag + properties: + tag: + type: string + enum: ["SpendingNodeUtxoForbidden"] + Signature: type: string @@ -1565,6 +1605,65 @@ components: contentEncoding: base16 - type: "null" + TxOutWithWitness: + type: object + description: | + A single transaction output with optional witness to spend it. + required: + - address + - value + - witness + additionalProperties: false + properties: + address: + $ref: "#/components/schemas/Address" + value: + $ref: "#/components/schemas/Value" + referenceScript: + oneOf: + - $ref: "#/components/schemas/Script" + - type: "null" + datumhash: + oneOf: + - type: string + contentEncoding: base16 + - type: "null" + inlineDatum: + oneOf: + - type: object + - type: "null" + inlineDatumhash: + oneOf: + - type: string + contentEncoding: base16 + - type: "null" + datum: + oneOf: + - type: string + contentEncoding: base16 + - type: "null" + witness: + oneOf: + - $ref: "#/components/schemas/Witness" + - type: "null" + + Witness: + type: object + description: | + A script witness + required: + - datum + - plutusV2Script + - redeemer + additionalProperties: false + properties: + datum: + type: string + plutusV2Script: + $ref: "#/components/schemas/PlutusV2Script" + redeemer: + type: string + SequenceNumber: type: integer minimum: 0 @@ -1600,6 +1699,67 @@ components: } } + UTxOWithWitness: + type: object + propertyNames: + pattern: "^[0-9a-f]{64}#[0-9]+$" + items: + $ref: "#/components/schemas/TxOutWithWitness" + example: + { + "09d34606abdcd0b10ebc89307cbfa0b469f9144194137b45b7a04b273961add8#687": { + "address": "addr1w9htvds89a78ex2uls5y969ttry9s3k9etww0staxzndwlgmzuul5", + "value": { + "lovelace": 7620669 + }, + "witness": { + "datum": "02", + "plutusV2Script": { + "cborHex": "420606", + "description": "", + "type": "PlutusScriptV2" + }, + "redeemer": "21" + } + } + } + + ScriptInfo: + description: | + Script data needed to spend user provided utxo + required: + - redeemer + - datum + - plutusV2Script + payload: + type: object + properties: + redeemer: + $ref: "#/components/schemas/Cbor" + datum: + $ref: "#/components/schemas/Cbor" + plutusV2Script: + type: object + $ref: "#/components/schemas/PlutusV2Script" + + PlutusV2Script: + type: object + description: | + Plutus V2 Script wrapped in a text-envelope. + additionalProperties: false + required: + - cborHex + - description + - type + properties: + cborHex: + $ref: "#/components/schemas/Cbor" + description: + type: string + type: + type: string + enum: ["PlutusScriptV2"] + Value: type: object description: | diff --git a/hydra-node/json-schemas/logs.yaml b/hydra-node/json-schemas/logs.yaml index abb58945a2e..cc033177585 100644 --- a/hydra-node/json-schemas/logs.yaml +++ b/hydra-node/json-schemas/logs.yaml @@ -11,158 +11,150 @@ description: > type: object additionalProperties: false - +required: + - namespace + - timestamp + - threadId + - message properties: - messages: - type: array - additionalItems: false - items: - type: object - additionalProperties: false - required: - - namespace - - timestamp - - threadId - - message - properties: - namespace: - type: string - description: >- - An arbitrary string identifying the tracer generating this entry. For a - node, this is always 'HydraNode'. + namespace: + type: string + description: >- + An arbitrary string identifying the tracer generating this entry. For a + node, this is always 'HydraNode'. - timestamp: - type: string - format: "date-time" - description: >- - Timestamp denoting the wall-clock time at which this log entry was - recorded. + timestamp: + type: string + format: "date-time" + description: >- + Timestamp denoting the wall-clock time at which this log entry was + recorded. - threadId: - type: integer - description: >- - The id of the thread which produced the log entry. + threadId: + type: integer + description: >- + The id of the thread which produced the log entry. - message: - oneOf: - - title: APIServer - type: object - additionalProperties: false - required: - - tag - - api - description: >- - A log entry produced by the API server. - properties: - tag: - type: string - enum: ["APIServer"] - api: - $ref: "#/definitions/APIServer" + message: + oneOf: + - title: APIServer + type: object + additionalProperties: false + required: + - tag + - api + description: >- + A log entry produced by the API server. + properties: + tag: + type: string + enum: ["APIServer"] + api: + $ref: "logs.yaml#/definitions/APIServer" - - title: Node - type: object - additionalProperties: false - required: - - tag - - node - description: >- - A log entry denoting events and effects processed by the Node as part - of the Head protocol. - properties: - tag: - type: string - enum: ["Node"] - node: - $ref: "#/definitions/Node" + - title: Node + type: object + additionalProperties: false + required: + - tag + - node + description: >- + A log entry denoting events and effects processed by the Node as part + of the Head protocol. + properties: + tag: + type: string + enum: ["Node"] + node: + $ref: "logs.yaml#/definitions/Node" - - title: DirectChain - type: object - additionalProperties: false - required: - - tag - - directChain - description: >- - A log entry produced by the chain component watching the chain. - properties: - tag: - type: string - enum: ["DirectChain"] - directChain: - $ref: "#/definitions/DirectChain" + - title: DirectChain + type: object + additionalProperties: false + required: + - tag + - directChain + description: >- + A log entry produced by the chain component watching the chain. + properties: + tag: + type: string + enum: ["DirectChain"] + directChain: + $ref: "logs.yaml#/definitions/DirectChain" - - title: Network - type: object - additionalProperties: false - required: - - tag - - network - description: >- - A log entry from the Hydra network (i.e. the layer-two network between Hydra nodes). - properties: - tag: - type: string - enum: ["Network"] - network: - $ref: "#/definitions/Network" + - title: Network + type: object + additionalProperties: false + required: + - tag + - network + description: >- + A log entry from the Hydra network (i.e. the layer-two network between Hydra nodes). + properties: + tag: + type: string + enum: ["Network"] + network: + $ref: "logs.yaml#/definitions/Network" - - title: NodeOptions - description: >- - Hydra node parsed command line arguments - type: object - additionalProperties: false - required: - - tag - - runOptions - properties: - tag: - type: string - enum: ["NodeOptions"] - runOptions: - <<: { "$ref": "#/definitions/RunOptions" } - description: >- - Configuration needed to run the hydra node + - title: NodeOptions + description: >- + Hydra node parsed command line arguments + type: object + additionalProperties: false + required: + - tag + - runOptions + properties: + tag: + type: string + enum: ["NodeOptions"] + runOptions: + "$ref": "logs.yaml#/definitions/RunOptions" + description: >- + Configuration needed to run the hydra node - - title: CreatedState - description: >- - Created new state in persistence (instead of loading) - type: object - additionalProperties: false - required: - - tag - properties: - tag: - type: string - enum: ["CreatedState"] + - title: CreatedState + description: >- + Created new state in persistence (instead of loading) + type: object + additionalProperties: false + required: + - tag + properties: + tag: + type: string + enum: ["CreatedState"] - - title: LoadedState - description: >- - Loaded state from persistence - type: object - additionalProperties: false - required: - - tag - properties: - tag: - type: string - enum: ["LoadedState"] + - title: LoadedState + description: >- + Loaded state from persistence + type: object + additionalProperties: false + required: + - tag + properties: + tag: + type: string + enum: ["LoadedState"] - - title: Misconfiguration - description: >- - Hydra node detected a difference between loaded state and the node arguments. - type: object - additionalProperties: false - required: - - tag - - misconfigurationErrors - properties: - tag: - type: string - enum: ["Misconfiguration"] - misconfigurationErrors: - type: array - items: - $ref: "#definitions/ParamMismatch" + - title: Misconfiguration + description: >- + Hydra node detected a difference between loaded state and the node arguments. + type: object + additionalProperties: false + required: + - tag + - misconfigurationErrors + properties: + tag: + type: string + enum: ["Misconfiguration"] + misconfigurationErrors: + type: array + items: + $ref: "logs.yaml#/definitions/ParamMismatch" definitions: APIServer: @@ -409,7 +401,7 @@ definitions: type: string enum: ["Wallet"] contents: - $ref: "#/definitions/Wallet" + $ref: "logs.yaml#/definitions/Wallet" Wallet: oneOf: @@ -507,11 +499,11 @@ definitions: type: string enum: ["ContestationPeriodMismatch"] loadedCp: - <<: { "$ref": "api.yaml#/components/schemas/ContestationPeriod" } + "$ref": "api.yaml#/components/schemas/ContestationPeriod" description: >- Contestation period present in the node state. configuredCp: - <<: { "$ref": "api.yaml#/components/schemas/ContestationPeriod" } + "$ref": "api.yaml#/components/schemas/ContestationPeriod" description: >- Contestation period configured as the node argument. - title: PartiesMismatch @@ -529,12 +521,14 @@ definitions: enum: ["PartiesMismatch"] loadedParties: type: array - <<: { "$ref": "api.yaml#/components/schemas/Party" } + items: + "$ref": "api.yaml#/components/schemas/Party" description: >- Parties present in the node state. configuredParties: type: array - <<: { "$ref": "api.yaml#/components/schemas/Party" } + items: + "$ref": "api.yaml#/components/schemas/Party" description: >- Parties configured as the node argument. @@ -559,7 +553,7 @@ definitions: type: string enum: ["BeginEvent"] by: - <<: { "$ref": "api.yaml#/components/schemas/Party" } + "$ref": "api.yaml#/components/schemas/Party" description: >- The Party emitting the log entry. eventId: @@ -570,7 +564,7 @@ definitions: the stream of events from this node. This is useful to correlate with `EndEvent`. event: - <<: { "$ref": "#/definitions/Event" } + "$ref": "logs.yaml#/definitions/Event" - title: EndEvent description: >- Head has succesfully finished processing an event. @@ -585,7 +579,7 @@ definitions: type: string enum: ["EndEvent"] by: - <<: { "$ref": "api.yaml#/components/schemas/Party" } + "$ref": "api.yaml#/components/schemas/Party" description: >- The Party emitting the log entry. eventId: @@ -608,7 +602,7 @@ definitions: type: string enum: ["BeginEffect"] by: - <<: { "$ref": "api.yaml#/components/schemas/Party" } + "$ref": "api.yaml#/components/schemas/Party" description: >- The Party emitting the log entry. eventId: @@ -626,7 +620,7 @@ definitions: the span of a specific `eventId`. This number along with the `eventId` field is used to correlate the beginning and end of an effect. effect: - $ref: "#/definitions/Effect" + $ref: "logs.yaml#/definitions/Effect" - title: EndEffect description: >- Head has finished processing an effect produced by some transition in @@ -643,7 +637,7 @@ definitions: type: string enum: ["EndEffect"] by: - <<: { "$ref": "api.yaml#/components/schemas/Party" } + "$ref": "api.yaml#/components/schemas/Party" description: >- The Party emitting the log entry. eventId: @@ -666,11 +660,11 @@ definitions: type: string enum: ["LogicOutcome"] by: - <<: { "$ref": "api.yaml#/components/schemas/Party" } + "$ref": "api.yaml#/components/schemas/Party" description: >- The Party emitting the log entry. outcome: - $ref: "#/definitions/Outcome" + $ref: "logs.yaml#/definitions/Outcome" LogicError: oneOf: @@ -686,8 +680,8 @@ definitions: contents: type: array prefixItems: - - $ref: "#/definitions/Event" - - $ref: "#/definitions/HeadState" + - $ref: "logs.yaml#/definitions/Event" + - $ref: "logs.yaml#/definitions/HeadState" - title: InvalidState additionalProperties: false required: @@ -698,7 +692,7 @@ definitions: type: string enum: ["InvalidState"] contents: - $ref: "#/definitions/HeadState" + $ref: "logs.yaml#/definitions/HeadState" - title: InvalidSnapshot additionalProperties: false required: @@ -723,7 +717,7 @@ definitions: type: string enum: ["LedgerError"] contents: - $ref: "#/definitions/ValidationError" + $ref: "logs.yaml#/definitions/ValidationError" - title: RequireFailed description: >- A precondition for some state transition within the Hydra @@ -741,7 +735,7 @@ definitions: type: string enum: ["RequireFailed"] contents: - $ref: "#/definitions/RequirementFailure" + $ref: "logs.yaml#/definitions/RequirementFailure" - title: NotOurHead description: >- We just observed an on-chain event that does not apply to @@ -871,7 +865,7 @@ definitions: type: string enum: ["Idle"] contents: - $ref: "#/definitions/IdleState" + $ref: "logs.yaml#/definitions/IdleState" - title: "Initial" additionalProperties: false required: @@ -882,7 +876,7 @@ definitions: type: string enum: ["Initial"] contents: - $ref: "#/definitions/InitialState" + $ref: "logs.yaml#/definitions/InitialState" - title: "Open" additionalProperties: false required: @@ -893,7 +887,7 @@ definitions: type: string enum: ["Open"] contents: - $ref: "#/definitions/OpenState" + $ref: "logs.yaml#/definitions/OpenState" - title: "Closed" additionalProperties: false required: @@ -904,7 +898,7 @@ definitions: type: string enum: ["Closed"] contents: - $ref: "#/definitions/ClosedState" + $ref: "logs.yaml#/definitions/ClosedState" IdleState: type: object @@ -953,7 +947,7 @@ definitions: parameters: $ref: "api.yaml#/components/schemas/HeadParameters" coordinatedHeadState: - $ref: "#/definitions/CoordinatedHeadState" + $ref: "logs.yaml#/definitions/CoordinatedHeadState" chainState: $ref: "api.yaml#/components/schemas/ChainState" headId: @@ -1003,7 +997,7 @@ definitions: confirmedSnapshot: $ref: "api.yaml#/components/schemas/ConfirmedSnapshot" seenSnapshot: - $ref: "#/definitions/SeenSnapshot" + $ref: "logs.yaml#/definitions/SeenSnapshot" SeenSnapshot: oneOf: @@ -1106,7 +1100,7 @@ definitions: type: string enum: ["NetworkEvent"] message: - $ref: "#/definitions/Message" + $ref: "logs.yaml#/definitions/Message" ttl: type: number - title: OnChainEvent @@ -1123,7 +1117,7 @@ definitions: type: string enum: ["OnChainEvent"] chainEvent: - $ref: "#/definitions/OnChainEvent" + $ref: "logs.yaml#/definitions/OnChainEvent" - title: ShouldPostFanout type: object additionalProperties: false @@ -1267,7 +1261,7 @@ definitions: type: string enum: ["Observation"] observedTx: - $ref: "#/definitions/OnChainTx" + $ref: "logs.yaml#/definitions/OnChainTx" newChainState: $ref: "api.yaml#/components/schemas/ChainState" @@ -1428,7 +1422,7 @@ definitions: type: string enum: ["ClientEffect"] serverOutput: - $ref: "#/definitions/ServerOutput" + $ref: "logs.yaml#/definitions/ServerOutput" - title: NetworkEffect type: object @@ -1444,7 +1438,7 @@ definitions: type: string enum: ["NetworkEffect"] message: - $ref: "#/definitions/Message" + $ref: "logs.yaml#/definitions/Message" - title: OnChainEffect type: object additionalProperties: false @@ -1485,9 +1479,9 @@ definitions: description: >- The length of the delay, in seconds. reason: - $ref: "#/definitions/WaitReason" + $ref: "logs.yaml#/definitions/WaitReason" event: - $ref: "#/definitions/Event" + $ref: "logs.yaml#/definitions/Event" Outcome: description: >- @@ -1510,7 +1504,7 @@ definitions: type: array items: type: object - $ref: "#/definitions/Effect" + $ref: "logs.yaml#/definitions/Effect" - title: NewState type: object additionalProperties: false @@ -1527,12 +1521,12 @@ definitions: enum: ["NewState"] headState: type: object - $ref: "#/definitions/HeadState" + $ref: "logs.yaml#/definitions/HeadState" effects: type: array items: type: object - $ref: "#/definitions/Effect" + $ref: "logs.yaml#/definitions/Effect" - title: Wait type: object additionalProperties: false @@ -1548,7 +1542,7 @@ definitions: enum: ["Wait"] reason: type: object - $ref: "#/definitions/WaitReason" + $ref: "logs.yaml#/definitions/WaitReason" - title: Error type: object additionalProperties: false @@ -1564,7 +1558,7 @@ definitions: enum: ["Error"] error: type: object - $ref: "#/definitions/LogicError" + $ref: "logs.yaml#/definitions/LogicError" WaitReason: oneOf: @@ -1581,7 +1575,7 @@ definitions: type: string enum: ["WaitOnNotApplicableTx"] validationError: - <<: { "$ref": "#/definitions/ValidationError" } + "$ref": "logs.yaml#/definitions/ValidationError" description: >- Description of the cause of the validation failure. - title: WaitOnSnapshotNumber @@ -1598,7 +1592,7 @@ definitions: type: string enum: ["WaitOnSnapshotNumber"] waitingFor: - <<: { "$ref": "api.yaml#/components/schemas/SnapshotNumber" } + "$ref": "api.yaml#/components/schemas/SnapshotNumber" description: >- The expected number. - title: WaitOnSeenSnapshot @@ -1679,16 +1673,15 @@ definitions: type: string host: type: object - $ref: "#/definitions/IP" + $ref: "logs.yaml#/definitions/IP" port: type: integer peers: type: array items: - $ref: "api.yaml#/components/schemas/Host" + $ref: "api.yaml#/components/schemas/Peer" apiHost: - type: object - $ref: "#/definitions/IP" + $ref: "logs.yaml#/definitions/IP" apiPort: type: integer monitoringPort: diff --git a/hydra-node/src/Hydra/API/RestServer.hs b/hydra-node/src/Hydra/API/RestServer.hs index a8eeedf14bb..36b70dcfa69 100644 --- a/hydra-node/src/Hydra/API/RestServer.hs +++ b/hydra-node/src/Hydra/API/RestServer.hs @@ -1,81 +1,122 @@ +{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE UndecidableInstances #-} module Hydra.API.RestServer where import Hydra.Prelude -import Cardano.Binary (decodeFull', serialize') -import Data.Aeson (Value (String), object, withObject, (.:), (.=)) +import qualified Cardano.Api.UTxO as UTxO +import Data.Aeson (Value (Object, String), object, withObject, (.:), (.:?), (.=)) +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.ByteString.Base16 as Base16 -import Hydra.Ledger (IsTx, UTxOType) +import Data.ByteString.Short () +import Hydra.Cardano.Api ( + CtxUTxO, + HashableScriptData, + KeyWitnessInCtx (..), + PlutusScript, + ScriptDatum (ScriptDatumForTxIn), + ScriptWitnessInCtx (ScriptWitnessForSpending), + SerialiseAsCBOR (deserialiseFromCBOR, serialiseToCBOR), + Tx, + TxOut, + UTxO', + WitCtxTxIn, + Witness, + mkScriptWitness, + proxyToAsType, + pattern KeyWitness, + pattern ScriptWitness, + ) +import Hydra.Ledger.Cardano () -newtype DraftCommitTxResponse tx = DraftCommitTxResponse - { commitTx :: tx +newtype DraftCommitTxResponse = DraftCommitTxResponse + { commitTx :: Tx } - deriving (Generic) + deriving (Show, Generic) -deriving stock instance IsTx tx => Eq (DraftCommitTxResponse tx) -deriving stock instance IsTx tx => Show (DraftCommitTxResponse tx) - -instance (IsTx tx, ToCBOR tx) => ToJSON (DraftCommitTxResponse tx) where +instance ToJSON DraftCommitTxResponse where toJSON (DraftCommitTxResponse tx) = object - [ "tag" .= String "DraftCommitTxResponse" - , "commitTx" .= (String . decodeUtf8 . Base16.encode $ serialize' tx) + [ "commitTx" .= (String . decodeUtf8 . Base16.encode $ serialiseToCBOR tx) ] -instance - (IsTx tx, FromCBOR tx) => - FromJSON (DraftCommitTxResponse tx) - where - parseJSON = withObject "DraftCommitTxResponse" $ \o -> do - tag <- o .: "tag" - case tag :: Text of - "DraftCommitTxResponse" -> do - encodedTx :: Text <- o .: "commitTx" - case Base16.decode $ encodeUtf8 encodedTx of - Left e -> fail e - Right commitTx -> - case decodeFull' commitTx of - Left err -> fail $ show err - Right v -> pure $ DraftCommitTxResponse v - _ -> fail "Expected tag to be DraftCommitTxResponse" - -instance IsTx tx => Arbitrary (DraftCommitTxResponse tx) where +instance FromJSON DraftCommitTxResponse where + parseJSON = Aeson.withObject "DraftCommitTxResponse" $ \o -> do + encodedTx :: Text <- o .: "commitTx" + case Base16.decode $ encodeUtf8 encodedTx of + Left e -> fail e + Right bytes -> + case deserialiseFromCBOR (proxyToAsType Proxy) bytes of + Left err -> fail $ show err + Right v -> pure $ DraftCommitTxResponse v + +instance Arbitrary DraftCommitTxResponse where arbitrary = genericArbitrary shrink = \case DraftCommitTxResponse xs -> DraftCommitTxResponse <$> shrink xs -newtype DraftCommitTxRequest tx = DraftCommitTxRequest - { utxos :: UTxOType tx +-- TODO: This should actually be isomorphic to ScriptWitness of cardano-api, +-- i.e. we should support also native scripts, other versions of plutus and +-- witnessing via reference inputs +data ScriptInfo = ScriptInfo + { redeemer :: HashableScriptData + , datum :: HashableScriptData + , plutusV2Script :: PlutusScript } - deriving (Generic) + deriving stock (Show, Eq, Generic) + deriving anyclass (ToJSON, FromJSON) -deriving newtype instance IsTx tx => Eq (DraftCommitTxRequest tx) -deriving newtype instance IsTx tx => Show (DraftCommitTxRequest tx) +instance Arbitrary ScriptInfo where + arbitrary = genericArbitrary -instance (IsTx tx, ToCBOR tx) => ToJSON (DraftCommitTxRequest tx) where - toJSON (DraftCommitTxRequest utxo) = - object - [ "tag" .= String "DraftCommitTxRequest" - , "utxos" .= toJSON utxo - ] +data TxOutWithWitness = TxOutWithWitness + { txOut :: TxOut CtxUTxO + , witness :: Maybe ScriptInfo + } + deriving stock (Show, Eq, Generic) + +instance ToJSON TxOutWithWitness where + toJSON TxOutWithWitness{txOut, witness} = + case toJSON txOut of + Object km + | isJust witness -> + Object $ km & "witness" `KeyMap.insert` toJSON witness + x -> x -instance - (IsTx tx, FromCBOR tx) => - FromJSON (DraftCommitTxRequest tx) - where - parseJSON = withObject "DraftCommitTxRequest" $ \o -> do - tag <- o .: "tag" - case tag :: Text of - "DraftCommitTxRequest" -> do - utxos :: (UTxOType tx) <- o .: "utxos" - pure $ DraftCommitTxRequest utxos - _ -> fail "Expected tag to be DraftCommitTxRequest" - -instance Arbitrary (UTxOType tx) => Arbitrary (DraftCommitTxRequest tx) where +instance FromJSON TxOutWithWitness where + parseJSON v = do + txOut <- parseJSON v + flip (withObject "TxOutWithWitness") v $ \o -> do + witness <- o .:? "witness" + pure $ TxOutWithWitness{txOut, witness} + +instance Arbitrary TxOutWithWitness where + arbitrary = genericArbitrary + +deriving newtype instance Arbitrary (UTxO' TxOutWithWitness) + +newtype DraftCommitTxRequest = DraftCommitTxRequest + { utxos :: UTxO' TxOutWithWitness + } + deriving stock (Eq, Show, Generic) + deriving anyclass (ToJSON, FromJSON) + +instance Arbitrary DraftCommitTxRequest where arbitrary = genericArbitrary shrink = \case - DraftCommitTxRequest xs -> DraftCommitTxRequest <$> shrink xs + DraftCommitTxRequest u -> DraftCommitTxRequest <$> shrink u + +fromTxOutWithWitness :: TxOutWithWitness -> (TxOut CtxUTxO, Witness WitCtxTxIn) +fromTxOutWithWitness TxOutWithWitness{txOut, witness} = + (txOut, toScriptWitness witness) + where + toScriptWitness = \case + Nothing -> + KeyWitness KeyWitnessForSpending + Just ScriptInfo{redeemer, datum, plutusV2Script} -> + ScriptWitness ScriptWitnessForSpending $ + mkScriptWitness plutusV2Script (ScriptDatumForTxIn datum) redeemer diff --git a/hydra-node/src/Hydra/API/Server.hs b/hydra-node/src/Hydra/API/Server.hs index d270039b3a4..25a2a544d04 100644 --- a/hydra-node/src/Hydra/API/Server.hs +++ b/hydra-node/src/Hydra/API/Server.hs @@ -17,7 +17,11 @@ import qualified Data.ByteString.Lazy as LBS import Data.Text (pack) import Hydra.API.ClientInput (ClientInput) import Hydra.API.Projection (Projection (..), mkProjection) -import Hydra.API.RestServer (DraftCommitTxRequest (..), DraftCommitTxResponse (..)) +import Hydra.API.RestServer ( + DraftCommitTxRequest (..), + DraftCommitTxResponse (..), + fromTxOutWithWitness, + ) import Hydra.API.ServerOutput ( HeadStatus (Idle), OutputFormat (..), @@ -32,14 +36,31 @@ import Hydra.API.ServerOutput ( projectSnapshotUtxo, snapshotUtxo, ) -import Hydra.Chain (Chain (..), IsChainState, PostTxError (CannotCommitReferenceScript, CommittedTooMuchADAForMainnet, UnsupportedLegacyOutput)) +import Hydra.Chain ( + Chain (..), + IsChainState, + PostTxError ( + CannotCommitReferenceScript, + CommittedTooMuchADAForMainnet, + SpendingNodeUtxoForbidden, + UnsupportedLegacyOutput + ), + ) +import Hydra.Chain.Direct.State () import Hydra.Ledger (UTxOType) import Hydra.Logging (Tracer, traceWith) import Hydra.Network (IP, PortNumber) import Hydra.Party (Party) import Hydra.Persistence (PersistenceIncremental (..)) import Network.HTTP.Types (Method, status200, status400, status500) -import Network.Wai (Request (pathInfo), Response, ResponseReceived, consumeRequestBodyStrict, requestMethod, responseLBS) +import Network.Wai ( + Request (pathInfo), + Response, + ResponseReceived, + consumeRequestBodyStrict, + requestMethod, + responseLBS, + ) import Network.Wai.Handler.Warp ( defaultSettings, runSettings, @@ -71,7 +92,11 @@ data APIServerLog | APIInvalidInput {reason :: String, inputReceived :: Text} | APIConnectionError {reason :: String} | APIHandshakeError {reason :: String} - | APIRestInputReceived {method :: Text, paths :: [Text], requestInputBody :: Maybe Aeson.Value} + | APIRestInputReceived + { method :: Text + , paths :: [Text] + , requestInputBody :: Maybe Aeson.Value + } deriving stock (Eq, Show, Generic) deriving anyclass (ToJSON, FromJSON) @@ -271,17 +296,13 @@ runAPIServer host port party tracer history chain callback headStatusP snapshotU let k = [queryKey|tx-output|] v = [queryValue|cbor|] queryP = QueryParam k v - in case queryP `elem` qp of - True -> OutputCBOR - False -> OutputJSON + in if queryP `elem` qp then OutputCBOR else OutputJSON decideOnUTxODisplay qp = let k = [queryKey|snapshot-utxo|] v = [queryValue|no|] queryP = QueryParam k v - in case queryP `elem` qp of - True -> WithoutUTxO - False -> WithUTxO + in if queryP `elem` qp then WithoutUTxO else WithUTxO shouldNotServeHistory qp = flip any qp $ \case @@ -337,8 +358,6 @@ instance Exception RunServerException -- Handle user requests to obtain a draft commit tx handleDraftCommitUtxo :: - forall tx. - IsChainState tx => Chain tx IO -> Tracer IO APIServerLog -> LBS.ByteString -> @@ -347,20 +366,17 @@ handleDraftCommitUtxo :: (Response -> IO ResponseReceived) -> IO ResponseReceived handleDraftCommitUtxo directChain tracer body reqMethod reqPaths respond = do - case Aeson.eitherDecode' body :: Either String (DraftCommitTxRequest tx) of + case Aeson.eitherDecode' body :: Either String DraftCommitTxRequest of Left err -> respond $ responseLBS status400 [] (Aeson.encode $ Aeson.String $ pack err) - Right requestInput -> do + Right requestInput@DraftCommitTxRequest{utxos} -> do traceWith tracer $ APIRestInputReceived { method = decodeUtf8 reqMethod , paths = reqPaths , requestInputBody = Just $ toJSON requestInput } - - let userUtxo = utxos requestInput - eCommitTx <- draftTx userUtxo - + eCommitTx <- draftCommitTx $ fromTxOutWithWitness <$> utxos respond $ case eCommitTx of Left e -> @@ -370,9 +386,11 @@ handleDraftCommitUtxo directChain tracer body reqMethod reqPaths respond = do CannotCommitReferenceScript -> return400 e CommittedTooMuchADAForMainnet _ _ -> return400 e UnsupportedLegacyOutput _ -> return400 e + walletUtxoErr@SpendingNodeUtxoForbidden -> return400 walletUtxoErr _ -> responseLBS status500 [] (Aeson.encode $ toJSON e) Right commitTx -> responseLBS status200 [] (Aeson.encode $ DraftCommitTxResponse commitTx) where return400 = responseLBS status400 [] . Aeson.encode . toJSON - Chain{draftTx} = directChain + + Chain{draftCommitTx} = directChain diff --git a/hydra-node/src/Hydra/Chain.hs b/hydra-node/src/Hydra/Chain.hs index a5269b30cf0..c5d64b17662 100644 --- a/hydra-node/src/Hydra/Chain.hs +++ b/hydra-node/src/Hydra/Chain.hs @@ -20,10 +20,16 @@ import Data.List (nub) import Hydra.Cardano.Api ( Address, ByronAddr, + CtxUTxO, HasTypeProxy (..), Lovelace (..), SerialiseAsRawBytes (..), + Tx, + TxOut, + UTxO', UsingRawBytesHex (..), + WitCtxTxIn, + Witness, ) import Hydra.ContestationPeriod (ContestationPeriod) import Hydra.Ledger (ChainSlot, IsTx, TxIdType, UTxOType) @@ -143,6 +149,8 @@ data PostTxError tx CommittedTooMuchADAForMainnet {userCommittedLovelace :: Lovelace, mainnetLimitLovelace :: Lovelace} | -- | We can only draft commit tx for the user when in Initializing state FailedToDraftTxNotInitializing + | -- | Committing UTxO addressed to the internal wallet is forbidden. + SpendingNodeUtxoForbidden deriving (Generic) deriving instance (IsTx tx, IsChainState tx) => Eq (PostTxError tx) @@ -186,12 +194,12 @@ data Chain tx m = Chain -- reasonable local view of the chain and throw an exception when invalid. -- -- Does at least throw 'PostTxError'. - , draftTx :: (IsChainState tx, MonadThrow m) => UTxOType tx -> m (Either (PostTxError tx) tx) - -- ^ Create a commit transaction using user provided utxos (zero or many). - -- Errors are handled at the call site. We are handling the following with 400 - -- responses: 'CannotFindOwnInitial', 'CannotCommitReferenceScript', - -- 'CommittedTooMuchADAForMainnet', 'UnsupportedLegacyOutput' and other - -- possible exceptions are turned into 500 errors + , draftCommitTx :: + (MonadThrow m, MonadIO m) => + UTxO' (TxOut CtxUTxO, Witness WitCtxTxIn) -> + m (Either (PostTxError Tx) Tx) + -- ^ Create a commit transaction using user provided utxos (zero or many) and + -- information to spend from a script. Errors are handled at the call site. } data ChainEvent tx diff --git a/hydra-node/src/Hydra/Chain/Direct.hs b/hydra-node/src/Hydra/Chain/Direct.hs index 2261e57bf76..1a2a465656f 100644 --- a/hydra-node/src/Hydra/Chain/Direct.hs +++ b/hydra-node/src/Hydra/Chain/Direct.hs @@ -200,6 +200,7 @@ withDirectChain tracer config ctx wallet chainStateAt callback action = do let getTimeHandle = queryTimeHandle networkId nodeSocket localChainState <- newLocalChainState chainStateAt + let chainHandle = mkChain tracer @@ -208,6 +209,7 @@ withDirectChain tracer config ctx wallet chainStateAt callback action = do ctx localChainState (submitTx queue) + let handler = chainSyncHandler tracer callback getTimeHandle ctx localChainState res <- race diff --git a/hydra-node/src/Hydra/Chain/Direct/Fixture.hs b/hydra-node/src/Hydra/Chain/Direct/Fixture.hs index 7af3b7b0ebd..e0eeb93ca49 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Fixture.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Fixture.hs @@ -46,14 +46,15 @@ testSeedInput = generateWith arbitrary 42 -- zeroed fees and prices. NOTE: This is using still a constant SlotNo = 1. defaultLedgerEnv :: Ledger.LedgerEnv LedgerEra defaultLedgerEnv = - newLedgerEnv pparams' - where - pparams' = - pparams - { protocolParamPrices = Just $ ExecutionUnitPrices 0 0 - , protocolParamTxFeePerByte = 0 - , protocolParamTxFeeFixed = 0 - } + newLedgerEnv defaultPParams + +defaultPParams :: ProtocolParameters +defaultPParams = + pparams + { protocolParamPrices = Just $ ExecutionUnitPrices 0 0 + , protocolParamTxFeePerByte = 0 + , protocolParamTxFeeFixed = 0 + } defaultGlobals :: Ledger.Globals defaultGlobals = diff --git a/hydra-node/src/Hydra/Chain/Direct/Handlers.hs b/hydra-node/src/Hydra/Chain/Direct/Handlers.hs index 2abc913ab01..a14ae5db4ed 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Handlers.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Handlers.hs @@ -15,17 +15,27 @@ import qualified Cardano.Api.UTxO as UTxO import Cardano.Slotting.Slot (SlotNo (..)) import Control.Concurrent.Class.MonadSTM (modifyTVar, newTVarIO, writeTVar) import Control.Monad.Class.MonadSTM (throwSTM) +import qualified Data.Map.Strict as Map +import qualified Data.Set as Set import Hydra.Cardano.Api ( BlockHeader, ChainPoint (..), Tx, TxId, chainPointToSlotNo, + fromLedgerTxIn, getChainPoint, getTxBody, getTxId, ) -import Hydra.Chain (Chain (..), ChainCallback, ChainEvent (..), ChainStateType, PostChainTx (..), PostTxError (..)) +import Hydra.Chain ( + Chain (..), + ChainCallback, + ChainEvent (..), + ChainStateType, + PostChainTx (..), + PostTxError (..), + ) import Hydra.Chain.Direct.State ( ChainContext (contestationPeriod), ChainState (Closed, Idle, Initial, Open), @@ -34,6 +44,7 @@ import Hydra.Chain.Direct.State ( close, collect, commit, + commit', contest, fanout, getKnownUTxO, @@ -123,7 +134,7 @@ mkChain :: LocalChainState m -> SubmitTx m -> Chain Tx m -mkChain tracer queryTimeHandle wallet ctx LocalChainState{getLatest} submitTx = +mkChain tracer queryTimeHandle wallet@TinyWallet{getUTxO} ctx LocalChainState{getLatest} submitTx = Chain { postTx = \tx -> do chainState <- atomically getLatest @@ -145,11 +156,21 @@ mkChain tracer queryTimeHandle wallet ctx LocalChainState{getLatest} submitTx = submitTx vtx , -- Handle that creates a draft commit tx using the user utxo. -- Possible errors are handled at the api server level. - draftTx = \utxo -> do + draftCommitTx = \utxoToCommit -> do chainState <- atomically getLatest case Hydra.Chain.Direct.State.chainState chainState of - Initial st -> - sequenceA $ finalizeTx wallet ctx chainState utxo <$> commit ctx st utxo + Initial st -> do + walletUtxos <- atomically getUTxO + let walletTxIns = fromLedgerTxIn <$> Map.keys walletUtxos + let userTxIns = Set.toList $ UTxO.inputSet utxoToCommit + let matchedWalletUtxo = filter (`elem` walletTxIns) userTxIns + -- prevent trying to spend internal wallet's utxo + if null matchedWalletUtxo + then + sequenceA $ + commit' ctx st utxoToCommit + <&> finalizeTx wallet ctx chainState (fst <$> utxoToCommit) + else pure $ Left SpendingNodeUtxoForbidden _ -> pure $ Left FailedToDraftTxNotInitializing } @@ -177,7 +198,7 @@ finalizeTx TinyWallet{sign, coverFee} ctx ChainStateAt{chainState} userUTxO part } :: PostTxError Tx ) - Left e -> + Left e -> do throwIO ( InternalWalletError { headUTxO @@ -304,6 +325,8 @@ prepareTxToPost timeHandle wallet ctx cst@ChainStateAt{chainState} tx = -- here. The 'Party' is already part of the state and it is the only party -- which can commit from this Hydra node. (CommitTx{committed}, Initial st) -> + -- NOTE: Eventually we will deprecate the internal 'CommitTx' command and + -- only have external commits via 'draftCommitTx'. either throwIO pure (commit ctx st committed) -- TODO: We do not rely on the utxo from the collect com tx here because the -- chain head-state is already tracking UTXO entries locked by commit scripts, diff --git a/hydra-node/src/Hydra/Chain/Direct/State.hs b/hydra-node/src/Hydra/Chain/Direct/State.hs index d6f712c248f..6e304977842 100644 --- a/hydra-node/src/Hydra/Chain/Direct/State.hs +++ b/hydra-node/src/Hydra/Chain/Direct/State.hs @@ -22,6 +22,7 @@ import Hydra.Cardano.Api ( CtxUTxO, Hash, Key (SigningKey, VerificationKey, verificationKeyHash), + KeyWitnessInCtx (..), NetworkId (Mainnet, Testnet), NetworkMagic (NetworkMagic), PaymentKey, @@ -34,6 +35,8 @@ import Hydra.Cardano.Api ( UTxO, UTxO' (UTxO), Value, + WitCtxTxIn, + Witness, chainPointToSlotNo, genTxIn, modifyTxOutValue, @@ -44,6 +47,7 @@ import Hydra.Cardano.Api ( valueFromList, valueToList, pattern ByronAddressInEra, + pattern KeyWitness, pattern ReferenceScript, pattern ReferenceScriptNone, pattern ShelleyAddressInEra, @@ -298,72 +302,84 @@ initialize ctx = -- | Construct a commit transaction based on the 'InitialState'. This does look -- for "our initial output" to spend and check the given 'UTxO' to be -- compatible. Hence, this function does fail if already committed. +-- +-- NOTE: This version of 'commit' does only commit outputs which are held by +-- payment keys. For a variant which supports committing scripts, see `commit'`. commit :: ChainContext -> InitialState -> - UTxO -> + UTxO' (TxOut CtxUTxO) -> Either (PostTxError Tx) Tx -commit ctx st utxo = do - case ownInitial of +commit ctx st utxoToCommit = + commit' ctx st $ utxoToCommit <&> (,KeyWitness KeyWitnessForSpending) + +-- | Construct a commit transaction base on the 'InitialState' and some +-- arbitrary UTxOs to commit. +-- +-- NOTE: A simpler variant only supporting pubkey outputs is 'commit'. +commit' :: + ChainContext -> + InitialState -> + UTxO' (TxOut CtxUTxO, Witness WitCtxTxIn) -> + Either (PostTxError Tx) Tx +commit' ctx st utxoToCommit = do + case ownInitial ctx st of Nothing -> Left (CannotFindOwnInitial{knownUTxO = getKnownUTxO st}) Just initial -> do + let utxo = fst <$> utxoToCommit rejectByronAddress utxo rejectReferenceScripts utxo rejectMoreThanMainnetLimit networkId utxo - Right $ commitTx networkId scriptRegistry headId ownParty utxo initial + Right $ commitTx networkId scriptRegistry headId ownParty utxoToCommit initial where - ChainContext{networkId, ownParty, ownVerificationKey, scriptRegistry} = ctx + ChainContext{networkId, ownParty, scriptRegistry} = ctx - InitialState - { initialInitials - , seedTxIn - , headId - } = st + InitialState{headId} = st - ownInitial :: Maybe (TxIn, TxOut CtxUTxO, Hash PaymentKey) - ownInitial = - foldl' go Nothing initialInitials - where - go (Just x) _ = Just x - go Nothing (i, out, _) = do - let vkh = verificationKeyHash ownVerificationKey - guard $ hasMatchingPT vkh (txOutValue out) - pure (i, out, vkh) - - hasMatchingPT :: Hash PaymentKey -> Value -> Bool - hasMatchingPT vkh val = - case headTokensFromValue (mkHeadTokenScript seedTxIn) val of - [(AssetName bs, 1)] -> bs == serialiseToRawBytes vkh - _ -> False - - rejectByronAddress :: UTxO -> Either (PostTxError Tx) () - rejectByronAddress u = do - forM_ u $ \case - (TxOut (ByronAddressInEra addr) _ _ _) -> - Left (UnsupportedLegacyOutput addr) - (TxOut ShelleyAddressInEra{} _ _ _) -> - Right () - - rejectReferenceScripts :: UTxO -> Either (PostTxError Tx) () - rejectReferenceScripts u = - when (any hasReferenceScript u) $ - Left CannotCommitReferenceScript - where - hasReferenceScript out = - case txOutReferenceScript out of - ReferenceScript{} -> True - ReferenceScriptNone -> False - - -- Rejects outputs with more than 'maxMainnetLovelace' lovelace on mainnet - -- NOTE: Remove this limit once we have more experiments on mainnet. - rejectMoreThanMainnetLimit :: NetworkId -> UTxO -> Either (PostTxError Tx) () - rejectMoreThanMainnetLimit network u = do - when (network == Mainnet && lovelaceAmt > maxMainnetLovelace) $ - Left $ - CommittedTooMuchADAForMainnet lovelaceAmt maxMainnetLovelace - where - lovelaceAmt = foldMap (selectLovelace . txOutValue) u +ownInitial :: ChainContext -> InitialState -> Maybe (TxIn, TxOut CtxUTxO, Hash PaymentKey) +ownInitial ChainContext{ownVerificationKey} st@InitialState{initialInitials} = + foldl' go Nothing initialInitials + where + go (Just x) _ = Just x + go Nothing (i, out, _) = do + let vkh = verificationKeyHash ownVerificationKey + guard $ hasMatchingPT st vkh (txOutValue out) + pure (i, out, vkh) + +hasMatchingPT :: InitialState -> Hash PaymentKey -> Value -> Bool +hasMatchingPT InitialState{seedTxIn} vkh val = + case headTokensFromValue (mkHeadTokenScript seedTxIn) val of + [(AssetName bs, 1)] -> bs == serialiseToRawBytes vkh + _ -> False + +rejectByronAddress :: UTxO -> Either (PostTxError Tx) () +rejectByronAddress u = do + forM_ u $ \case + (TxOut (ByronAddressInEra addr) _ _ _) -> + Left (UnsupportedLegacyOutput addr) + (TxOut ShelleyAddressInEra{} _ _ _) -> + Right () + +rejectReferenceScripts :: UTxO -> Either (PostTxError Tx) () +rejectReferenceScripts u = + when (any hasReferenceScript u) $ + Left CannotCommitReferenceScript + where + hasReferenceScript out = + case txOutReferenceScript out of + ReferenceScript{} -> True + ReferenceScriptNone -> False + +-- Rejects outputs with more than 'maxMainnetLovelace' lovelace on mainnet +-- NOTE: Remove this limit once we have more experiments on mainnet. +rejectMoreThanMainnetLimit :: NetworkId -> UTxO -> Either (PostTxError Tx) () +rejectMoreThanMainnetLimit network u = do + when (network == Mainnet && lovelaceAmt > maxMainnetLovelace) $ + Left $ + CommittedTooMuchADAForMainnet lovelaceAmt maxMainnetLovelace + where + lovelaceAmt = foldMap (selectLovelace . txOutValue) u -- | Construct a collect transaction based on the 'InitialState'. This will -- reimburse all the already committed outputs. @@ -884,11 +900,11 @@ genCommits' :: HydraContext -> Tx -> Gen [Tx] -genCommits' genUTxOToCommit ctx txInit = do +genCommits' genUTxO ctx txInit = do -- Prepare UTxO to commit. We need to scale down the quantities by number of -- committed UTxOs to ensure we are not as easily hitting overflows of the max -- bound (Word64) when collecting all the commits together later. - commitUTxOs <- forM (ctxParties ctx) $ \_p -> genUTxOToCommit + commitUTxOs <- forM (ctxParties ctx) $ const genUTxO let scaledCommitUTxOs = scaleCommitUTxOs commitUTxOs allChainContexts <- deriveChainContexts ctx @@ -995,6 +1011,7 @@ genStClosed ctx utxo = do (startSlot, pointInTime) <- genValidityBoundsFromContestationPeriod cp let txClose = close cctx stOpen snapshot startSlot pointInTime pure (sn, toFanout, snd . fromJust $ observeClose stOpen txClose) + -- ** Danger zone unsafeCommit :: diff --git a/hydra-node/src/Hydra/Chain/Direct/Tx.hs b/hydra-node/src/Hydra/Chain/Direct/Tx.hs index 3048df4d7f8..f047718f2c4 100644 --- a/hydra-node/src/Hydra/Chain/Direct/Tx.hs +++ b/hydra-node/src/Hydra/Chain/Direct/Tx.hs @@ -170,18 +170,18 @@ commitTx :: ScriptRegistry -> HeadId -> Party -> - -- | The UTxO to commit to the Head - UTxO -> + -- | The UTxO to commit to the Head along with witnesses. + UTxO' (TxOut CtxUTxO, Witness WitCtxTxIn) -> -- | The initial output (sent to each party) which should contain the PT and is -- locked by initial script (TxIn, TxOut CtxUTxO, Hash PaymentKey) -> Tx -commitTx networkId scriptRegistry headId party utxo (initialInput, out, vkh) = +commitTx networkId scriptRegistry headId party utxoToCommitWitnessed (initialInput, out, vkh) = unsafeBuildTransaction $ emptyTxBody & addInputs [(initialInput, initialWitness)] & addReferenceInputs [initialScriptRef] - & addVkInputs committedTxIns + & addInputs committedTxIns & addExtraRequiredSigners [vkh] & addOutputs [commitOutput] where @@ -189,27 +189,39 @@ commitTx networkId scriptRegistry headId party utxo (initialInput, out, vkh) = BuildTxWith $ ScriptWitness scriptWitnessInCtx $ mkScriptReference initialScriptRef initialScript initialDatum initialRedeemer + initialScript = fromPlutusScript @PlutusScriptV2 Initial.validatorScript + initialScriptRef = fst (initialReference scriptRegistry) + initialDatum = mkScriptDatum $ Initial.datum (headIdToCurrencySymbol headId) + initialRedeemer = toScriptData . Initial.redeemer $ - Initial.ViaCommit (toPlutusTxOutRef <$> committedTxIns) + Initial.ViaCommit (toPlutusTxOutRef . fst <$> committedTxIns) + committedTxIns = - Set.toList $ UTxO.inputSet utxo + map (\(i, (_, w)) -> (i, BuildTxWith w)) $ UTxO.pairs utxoToCommitWitnessed + commitOutput = TxOut commitAddress commitValue commitDatum ReferenceScriptNone + commitScript = fromPlutusScript Commit.validatorScript + commitAddress = mkScriptAddress @PlutusScriptV2 networkId commitScript + commitValue = - txOutValue out <> foldMap txOutValue utxo + txOutValue out <> foldMap txOutValue utxoToCommit + commitDatum = - mkTxOutDatum $ mkCommitDatum party utxo (headIdToCurrencySymbol headId) + mkTxOutDatum $ mkCommitDatum party utxoToCommit (headIdToCurrencySymbol headId) + + utxoToCommit = fst <$> utxoToCommitWitnessed mkCommitDatum :: Party -> UTxO -> CurrencySymbol -> Plutus.Datum mkCommitDatum party utxo headId = diff --git a/hydra-node/src/Hydra/Ledger/Cardano.hs b/hydra-node/src/Hydra/Ledger/Cardano.hs index daf25ff7c77..98cd1316f42 100644 --- a/hydra-node/src/Hydra/Ledger/Cardano.hs +++ b/hydra-node/src/Hydra/Ledger/Cardano.hs @@ -426,10 +426,6 @@ instance Arbitrary (Hash PaymentKey) where arbitrary = do unsafePaymentKeyHashFromBytes . BS.pack <$> vectorOf 28 arbitrary -deriving newtype instance ToJSON UTxO - -deriving newtype instance FromJSON UTxO - instance ToCBOR UTxO where toCBOR = toCBOR . toLedgerUTxO encodedSizeExpr sz _ = encodedSizeExpr sz (Proxy @(Ledger.UTxO LedgerEra)) diff --git a/hydra-node/test/Hydra/API/RestServerSpec.hs b/hydra-node/test/Hydra/API/RestServerSpec.hs index aa4971f41e4..6bc8e532ee5 100644 --- a/hydra-node/test/Hydra/API/RestServerSpec.hs +++ b/hydra-node/test/Hydra/API/RestServerSpec.hs @@ -5,15 +5,24 @@ module Hydra.API.RestServerSpec where import Hydra.Prelude import Test.Hydra.Prelude +import Data.Aeson.Lens (key) import Hydra.API.RestServer (DraftCommitTxRequest, DraftCommitTxResponse) import Hydra.Chain.Direct.State () -import Hydra.Ledger.Cardano (Tx) +import Hydra.JSONSchema (prop_validateJSONSchema) import Test.Aeson.GenericSpecs (roundtripAndGoldenSpecs) +import Test.QuickCheck.Property (property, withMaxSuccess) spec :: Spec spec = parallel $ do - roundtripAndGoldenSpecs - (Proxy @(ReasonablySized (DraftCommitTxResponse Tx))) + roundtripAndGoldenSpecs (Proxy @(ReasonablySized DraftCommitTxResponse)) + roundtripAndGoldenSpecs (Proxy @(ReasonablySized DraftCommitTxRequest)) - roundtripAndGoldenSpecs - (Proxy @(ReasonablySized (DraftCommitTxRequest Tx))) + prop "Validate /commit publish api schema" $ + property $ + withMaxSuccess 1 $ + prop_validateJSONSchema @DraftCommitTxRequest "api.json" (key "components" . key "messages") + + prop "Validate /commit subscribe api schema" $ + property $ + withMaxSuccess 1 $ + prop_validateJSONSchema @DraftCommitTxResponse "api.json" (key "channels" . key "/commit" . key "subscribe") diff --git a/hydra-node/test/Hydra/API/ServerSpec.hs b/hydra-node/test/Hydra/API/ServerSpec.hs index 3215c002e41..0324e1bc633 100644 --- a/hydra-node/test/Hydra/API/ServerSpec.hs +++ b/hydra-node/test/Hydra/API/ServerSpec.hs @@ -32,7 +32,7 @@ import Hydra.Chain ( PostChainTx (CloseTx), PostTxError (NoSeedInput), confirmedSnapshot, - draftTx, + draftCommitTx, postTx, ) import Hydra.Ledger (txId) @@ -406,7 +406,7 @@ dummyChainHandle :: Chain tx IO dummyChainHandle = Chain { postTx = \_ -> error "unexpected call to postTx" - , draftTx = \_ -> error "unexpected call to draftTx" + , draftCommitTx = \_ -> error "unexpected call to draftCommitTx" } noop :: Applicative m => a -> m () diff --git a/hydra-node/test/Hydra/BehaviorSpec.hs b/hydra-node/test/Hydra/BehaviorSpec.hs index 249008b4a38..71e6e654169 100644 --- a/hydra-node/test/Hydra/BehaviorSpec.hs +++ b/hydra-node/test/Hydra/BehaviorSpec.hs @@ -597,7 +597,7 @@ simulatedChainAndNetwork initialChainState = do { oc = Chain { postTx = postTx nodes history chainStateVar - , draftTx = \_ -> error "unexpected call to draftTx" + , draftCommitTx = \_ -> error "unexpected call to draftCommitTx" } , hn = createMockNetwork node nodes } @@ -761,7 +761,11 @@ createHydraNode ledger nodeState signingKey otherParties outputs outputHistory c , hn = Network{broadcast = \_ -> pure ()} , nodeState , ledger - , oc = Chain{postTx = \_ -> pure (), draftTx = \_ -> error "draftTx not implemented"} + , oc = + Chain + { postTx = \_ -> pure () + , draftCommitTx = \_ -> error "draftCommitTx not implemented" + } , server = Server { sendOutput = \out -> atomically $ do diff --git a/hydra-node/test/Hydra/Chain/Direct/Contract/Commit.hs b/hydra-node/test/Hydra/Chain/Direct/Contract/Commit.hs index 76abbfff6ee..ade1d6237a9 100644 --- a/hydra-node/test/Hydra/Chain/Direct/Contract/Commit.hs +++ b/hydra-node/test/Hydra/Chain/Direct/Contract/Commit.hs @@ -53,7 +53,7 @@ healthyCommitTx = scriptRegistry (mkHeadId Fixture.testPolicyId) commitParty - healthyCommittedUTxO + (healthyCommittedUTxO <&> (,KeyWitness KeyWitnessForSpending)) (healthyIntialTxIn, toUTxOContext healthyInitialTxOut, initialPubKeyHash) scriptRegistry = genScriptRegistry `generateWith` 42 diff --git a/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs b/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs index 6b4c14ca66f..3bf67d58f5e 100644 --- a/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs +++ b/hydra-node/test/Hydra/Chain/Direct/StateSpec.hs @@ -196,12 +196,12 @@ spec = parallel $ do prop "is not observed if not invited" $ forAll2 (genHydraContext maximumNumberOfParties) (genHydraContext maximumNumberOfParties) $ \(ctxA, ctxB) -> - null (ctxParties ctxA `intersect` ctxParties ctxB) ==> - forAll2 (pickChainContext ctxA) (pickChainContext ctxB) $ - \(cctxA, cctxB) -> - forAll genTxIn $ \seedInput -> - let tx = initialize cctxA (ctxHeadParameters ctxA) seedInput - in isLeft (observeInit cctxB tx) + null (ctxParties ctxA `intersect` ctxParties ctxB) + ==> forAll2 (pickChainContext ctxA) (pickChainContext ctxB) + $ \(cctxA, cctxB) -> + forAll genTxIn $ \seedInput -> + let tx = initialize cctxA (ctxHeadParameters ctxA) seedInput + in isLeft (observeInit cctxB tx) describe "commit" $ do propBelowSizeLimit maxTxSize forAllCommit @@ -419,6 +419,7 @@ forAllCommit' action = do forAll (genHydraContext maximumNumberOfParties) $ \hctx -> forAll (genStInitial hctx) $ \(ctx, stInitial) -> forAllShow genCommit renderUTxO $ \toCommit -> + -- TODO: generate script inputs here? let tx = unsafeCommit ctx stInitial toCommit in action ctx stInitial toCommit tx & classify diff --git a/hydra-node/test/Hydra/JSONSchema.hs b/hydra-node/test/Hydra/JSONSchema.hs index 5f2f4741fd1..d1bba315116 100644 --- a/hydra-node/test/Hydra/JSONSchema.hs +++ b/hydra-node/test/Hydra/JSONSchema.hs @@ -6,7 +6,7 @@ module Hydra.JSONSchema where import Hydra.Prelude -import Control.Lens (Traversal', at, (?~), (^..)) +import Control.Lens (Traversal', at, (?~), (^..), (^?)) import Data.Aeson ((.=)) import qualified Data.Aeson as Aeson import Data.Aeson.Lens (key, _Array, _String) @@ -23,36 +23,54 @@ import System.Exit (ExitCode (..)) import System.FilePath (normalise, takeBaseName, takeExtension, (<.>), ()) import System.IO.Error (IOError, ioeGetErrorType) import System.Process (readProcessWithExitCode) -import Test.Hydra.Prelude (createSystemTempDirectory, failure) -import Test.QuickCheck (Property, counterexample, forAllBlind, forAllShrink, vectorOf) +import Test.Hydra.Prelude (failure, withTempDir) +import Test.QuickCheck (Property, counterexample, forAllBlind, forAllShrink, resize, vectorOf) import Test.QuickCheck.Monadic (assert, monadicIO, monitor, run) import qualified Prelude --- | Generate arbitrary serializable (JSON) value, and check their validity --- against a known JSON schema. --- This property ensures that JSON instances we produce abide by --- the specification. Note this, because this uses an external tool each --- property iteration is pretty slow. So instead, we run the property only --- once, but on a list of 100 elements all arbitrarily generated. -prop_validateToJSON :: +-- | Validate an 'Arbitrary' value against a JSON schema. +-- +-- The second argument is a lens that says which part of the JSON file to use to +-- do the validation, for example: +-- +-- @@ +-- key "components" . key "schemas" . key "Address" +-- @@ +-- +-- which selects the JSON schema for "Address" types in a bigger specification, +-- say an asyncapi description. +prop_validateJSONSchema :: forall a. (ToJSON a, Arbitrary a, Show a) => - FilePath -> - Aeson.Key -> - FilePath -> + -- | Path to the JSON file holding the schema. + String -> + -- | Selector into the JSON file pointing to the schema to be validated. + SpecificationSelector -> Property -prop_validateToJSON specFile selector inputFile = - forAllShrink (vectorOf 500 arbitrary) shrink $ \(a :: [a]) -> - monadicIO $ - do +prop_validateJSONSchema specFileName selector = + forAllShrink (resize 10 arbitrary) shrink $ \(samples :: [a]) -> + monadicIO $ do + withJsonSpecifications $ \tmpDir -> do run ensureSystemRequirements - let obj = Aeson.encode $ Aeson.object [selector .= a] + let jsonInput = tmpDir "jsonInput" + let jsonSchema = tmpDir "jsonSchema" + let specJsonFile = tmpDir specFileName + mSpecs <- run $ Aeson.decodeFileStrict specJsonFile + case mSpecs of + Nothing -> error "Failed to decode specFile to JSON" + Just specs -> run $ do + let jsonSpecSchema = + Aeson.object + [ "$id" .= ("file://" <> tmpDir <> "/") + , "type" .= Aeson.String "array" + , "items" .= (specs ^? selector) + ] + writeFileLBS jsonInput (Aeson.encode samples) + writeFileLBS jsonSchema (Aeson.encode jsonSpecSchema) + monitor $ counterexample (decodeUtf8 . Aeson.encode $ samples) (exitCode, _out, err) <- run $ do - writeFileLBS inputFile obj - readProcessWithExitCode "jsonschema" ["-i", inputFile, specFile] mempty - + readProcessWithExitCode "jsonschema" ["-i", jsonInput, jsonSchema] mempty monitor $ counterexample err - monitor $ counterexample (decodeUtf8 obj) assert (exitCode == ExitSuccess) -- | Check specification is complete wr.t. to generated data @@ -86,32 +104,34 @@ prop_validateToJSON specFile selector inputFile = prop_specIsComplete :: forall a. (Arbitrary a, Show a) => - FilePath -> + String -> SpecificationSelector -> Property -prop_specIsComplete specFile typeSpecificationSelector = +prop_specIsComplete specFileName typeSpecificationSelector = forAllBlind (vectorOf 1000 arbitrary) $ \(a :: [a]) -> monadicIO $ do - specs <- run $ Aeson.decodeFileStrict specFile - let knownKeys = classify specs a - let unknownConstructors = Map.keys $ Map.filter (== 0) knownKeys + withJsonSpecifications $ \tmpDir -> do + let specFile = tmpDir specFileName + specs <- run $ Aeson.decodeFileStrict specFile + let knownKeys = classify specFile specs a + let unknownConstructors = Map.keys $ Map.filter (== 0) knownKeys - when (null knownKeys) $ do - monitor $ counterexample "No keys found in given specification fragment" - assert False + when (null knownKeys) $ do + monitor $ counterexample "No keys found in given specification fragment" + assert False - unless (null unknownConstructors) $ do - let commaSeparated = intercalate ", " (toString <$> unknownConstructors) - monitor $ counterexample $ "Unimplemented constructors present in specification: " <> commaSeparated - monitor $ counterexample $ show a - assert False + unless (null unknownConstructors) $ do + let commaSeparated = intercalate ", " (toString <$> unknownConstructors) + monitor $ counterexample $ "Unimplemented constructors present in specification: " <> commaSeparated + monitor $ counterexample $ show a + assert False where -- Like Generics, if you squint hard-enough. poormansGetConstr :: a -> Text poormansGetConstr = toText . Prelude.head . words . show - classify :: Maybe Aeson.Value -> [a] -> Map Text Integer - classify (Just specs) = + classify :: FilePath -> Maybe Aeson.Value -> [a] -> Map Text Integer + classify _ (Just specs) = let ks = specs ^.. typeSpecificationSelector . key "oneOf" . _Array . traverse . key "title" . _String knownKeys = Map.fromList $ zip ks (repeat @Integer 0) @@ -119,7 +139,7 @@ prop_specIsComplete specFile typeSpecificationSelector = countMatch (poormansGetConstr -> tag) = Map.alter (Just . maybe 1 (+ 1)) tag in foldr countMatch knownKeys - classify _ = + classify specFile _ = error $ "Invalid specification file. Does not decode to an object: " <> show specFile -- | An alias for a traversal selecting some part of a 'Value' @@ -132,22 +152,26 @@ type SpecificationSelector = Traversal' Aeson.Value Aeson.Value -- But tools (and in particular jsonschema) only works from JSON, so this -- function makes sure to also convert our local yaml into JSON. withJsonSpecifications :: - (FilePath -> IO ()) -> - IO () + MonadIO m => + (FilePath -> m r) -> + m r withJsonSpecifications action = do - specDir <- ( "json-schemas") . normalise <$> Pkg.getDataDir - specFiles <- listDirectory specDir - dir <- createSystemTempDirectory "Hydra_APISpec" - forM_ specFiles $ \file -> do - when (takeExtension file == ".yaml") $ do - spec <- Yaml.decodeFileThrow @_ @Aeson.Value (specDir file) - let spec' = addField "$id" ("file://" <> dir <> "/") spec - Aeson.encodeFile (dir takeBaseName file <.> "yaml") spec' - action dir - where - addField :: ToJSON a => Aeson.Key -> a -> Aeson.Value -> Aeson.Value - addField k v = withObject (at k ?~ toJSON v) + specDir <- ( "json-schemas") . normalise <$> liftIO Pkg.getDataDir + specFiles <- liftIO $ listDirectory specDir + withTempDir "Hydra_APISpec" $ \dir -> do + forM_ specFiles $ \file -> do + when (takeExtension file == ".yaml") $ do + spec <- Yaml.decodeFileThrow @_ @Aeson.Value (specDir file) + let spec' = addField "$id" ("file://" <> dir <> "/") spec + liftIO $ Aeson.encodeFile (dir takeBaseName file <.> "json") spec' + -- XXX: We need to write the specFile as .yaml although it is a JSON document now, + -- because internally the spec reference elements using the original .yaml file name. + liftIO $ Aeson.encodeFile (dir takeBaseName file <.> "yaml") spec + action dir +addField :: ToJSON a => Aeson.Key -> a -> Aeson.Value -> Aeson.Value +addField k v = withObject (at k ?~ toJSON v) + where withObject :: (Aeson.Object -> Aeson.Object) -> Aeson.Value -> Aeson.Value withObject fn = \case Aeson.Object m -> Aeson.Object (fn m) @@ -177,5 +201,5 @@ ensureSystemRequirements = do pure (dropWhileEnd isSpace out <$ guard (exitCode == ExitSuccess)) Left (err :: IOError) | ioeGetErrorType err == OtherError -> - pure (Left $ "Check jsonschema is installed and in $PATH") + pure (Left "Check jsonschema is installed and in $PATH") Left err -> pure (Left $ show err) diff --git a/hydra-node/test/Hydra/LoggingSpec.hs b/hydra-node/test/Hydra/LoggingSpec.hs index 682b3e26501..53fb40081dd 100644 --- a/hydra-node/test/Hydra/LoggingSpec.hs +++ b/hydra-node/test/Hydra/LoggingSpec.hs @@ -7,11 +7,10 @@ import Test.Hydra.Prelude import Data.Aeson (object, (.=)) import Data.Aeson.Lens (key) -import Hydra.JSONSchema (SpecificationSelector, prop_specIsComplete, prop_validateToJSON, withJsonSpecifications) +import Hydra.JSONSchema (prop_specIsComplete, prop_validateJSONSchema) import Hydra.Ledger.Cardano (Tx) import Hydra.Logging (Envelope (..), Verbosity (Verbose), traceWith, withTracer) import Hydra.Logging.Messages (HydraLog) -import System.FilePath (()) import System.IO.Silently (capture_) import Test.QuickCheck.Property (conjoin, property, withMaxSuccess) @@ -24,14 +23,10 @@ spec = do captured `shouldContain` "{\"foo\":42}" - aroundAll withJsonSpecifications $ do - specify "HydraLog" $ \dir -> do - property $ - withMaxSuccess 1 $ - conjoin - [ prop_validateToJSON @(Envelope (HydraLog Tx ())) (dir "logs.yaml") "messages" (dir "HydraLog") - , prop_specIsComplete @(HydraLog Tx ()) (dir "logs.yaml") apiSpecificationSelector - ] - -apiSpecificationSelector :: SpecificationSelector -apiSpecificationSelector = key "properties" . key "message" + prop "HydraLog" $ + property $ + withMaxSuccess 1 $ + conjoin + [ prop_validateJSONSchema @(Envelope (HydraLog Tx ())) "logs.json" id + , prop_specIsComplete @(HydraLog Tx ()) "logs.json" (key "properties" . key "message") + ] diff --git a/hydra-node/test/Hydra/Model/MockChain.hs b/hydra-node/test/Hydra/Model/MockChain.hs index 7e28b7f2f5b..29abd4c4bc4 100644 --- a/hydra-node/test/Hydra/Model/MockChain.hs +++ b/hydra-node/test/Hydra/Model/MockChain.hs @@ -231,7 +231,13 @@ createMockChain tracer ctx submitTx timeHandle seedInput chainState = , reset = pure () , update = \_ _ -> pure () } - in mkChain tracer timeHandle wallet ctx chainState submitTx + in mkChain + tracer + timeHandle + wallet + ctx + chainState + submitTx mkMockTxIn :: VerificationKey PaymentKey -> Word -> TxIn mkMockTxIn vk ix = TxIn (TxId tid) (TxIx ix) diff --git a/hydra-node/test/Hydra/NodeSpec.hs b/hydra-node/test/Hydra/NodeSpec.hs index 24a8a3cb745..78c4f2d7834 100644 --- a/hydra-node/test/Hydra/NodeSpec.hs +++ b/hydra-node/test/Hydra/NodeSpec.hs @@ -170,7 +170,11 @@ createHydraNode signingKey otherParties contestationPeriod events = do { eq , hn = Network{broadcast = \_ -> pure ()} , nodeState - , oc = Chain{postTx = \_ -> pure (), draftTx = \_ -> error "draftTx not implemented"} + , oc = + Chain + { postTx = \_ -> pure () + , draftCommitTx = \_ -> error "draftCommitTx not implemented" + } , server = Server{sendOutput = \_ -> pure ()} , ledger = simpleLedger , env = @@ -212,4 +216,11 @@ throwExceptionOnPostTx :: HydraNode tx IO -> IO (HydraNode tx IO) throwExceptionOnPostTx exception node = - pure node{oc = Chain{postTx = \_ -> throwIO exception, draftTx = \_ -> error "draftTx not implemented"}} + pure + node + { oc = + Chain + { postTx = \_ -> throwIO exception + , draftCommitTx = \_ -> error "draftCommitTx not implemented" + } + }