diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index 3b45526f2..b93a511c8 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -227,7 +227,7 @@ jobs: os: [ linux ] arch: [ x86_64 ] network: [ preview ] - cardano-node: [ 9.1.0 ] + cardano-node: [ 9.1.1 ] runs-on: ${{ matrix.os == 'linux' && 'ubuntu-22.04' }} steps: @@ -404,8 +404,8 @@ jobs: os: [ linux ] target: [ cardano-node-ogmios ] network: [ mainnet, preprod, preview, sanchonet ] - cardano-node: [ 9.1.0 ] - cardano-node-latest: [ 9.1.0 ] + cardano-node: [ 9.1.1 ] + cardano-node-latest: [ 9.1.1 ] arch: [ x86_64 ] steps: - name: 📥 Checkout repository diff --git a/.github/workflows/network-synchronization.yaml b/.github/workflows/network-synchronization.yaml index 197bcb487..77807d3df 100644 --- a/.github/workflows/network-synchronization.yaml +++ b/.github/workflows/network-synchronization.yaml @@ -16,8 +16,8 @@ jobs: strategy: matrix: network: [ preview ] - ogmios_version: [ v6.6.0 ] - cardano_node_version: [ 9.1.0 ] + ogmios_version: [ v6.6.2 ] + cardano_node_version: [ 9.1.1 ] runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 77cc2e944..8ffe9a3fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,20 @@ pre: "6. " math: true --- +### [6.7.0] - 2024-09-13 + +#### Added + +- Automatically upgrade transactions from previous era (up until Alonzo) on submission. + +#### Changed + +- N/A + +#### Removed + +- N/A + ### [6.6.2] - 2024-09-10 #### Added diff --git a/Dockerfile b/Dockerfile index 1667aabd8..e886d415f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -ARG CARDANO_NODE_IMAGE=ghcr.io/intersectmbo/cardano-node:9.0.0 +ARG CARDANO_NODE_IMAGE=ghcr.io/intersectmbo/cardano-node:9.1.1 # # # --------------------------- BUILD (ogmios) --------------------------------- # diff --git a/clients/TypeScript/package.json b/clients/TypeScript/package.json index 21b6fbf2f..ce53bd5d6 100644 --- a/clients/TypeScript/package.json +++ b/clients/TypeScript/package.json @@ -1,6 +1,6 @@ { "name": "cardano-ogmios", - "version": "6.6.2", + "version": "6.7.0", "private": true, "description": "TypeScript monorepo with client libraries for Cardano Ogmios", "engines": { diff --git a/clients/TypeScript/packages/client/package.json b/clients/TypeScript/packages/client/package.json index 98069f4fe..436bf64ad 100644 --- a/clients/TypeScript/packages/client/package.json +++ b/clients/TypeScript/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@cardano-ogmios/client", - "version": "6.6.2", + "version": "6.7.0", "description": "TypeScript client library for Cardano Ogmios", "engines": { "node": ">=14" @@ -47,7 +47,7 @@ "typescript": "^4.2.3" }, "dependencies": { - "@cardano-ogmios/schema": "6.6.2", + "@cardano-ogmios/schema": "6.7.0", "@cardanosolutions/json-bigint": "^1.0.1", "@types/json-bigint": "^1.0.1", "bech32": "^2.0.0", diff --git a/clients/TypeScript/packages/repl/package.json b/clients/TypeScript/packages/repl/package.json index 5589a9f4e..061b7cede 100644 --- a/clients/TypeScript/packages/repl/package.json +++ b/clients/TypeScript/packages/repl/package.json @@ -1,6 +1,6 @@ { "name": "@cardano-ogmios/repl", - "version": "6.6.2", + "version": "6.7.0", "description": "REPL for Cardano Ogmios", "engines": { "node": ">=14" @@ -39,7 +39,7 @@ "typescript": "^4.2.3" }, "dependencies": { - "@cardano-ogmios/client": "6.6.2", + "@cardano-ogmios/client": "6.7.0", "yargs-parser": "^20.2.7" }, "files": [ diff --git a/clients/TypeScript/packages/schema/package.json b/clients/TypeScript/packages/schema/package.json index 748d904d2..995c15cc0 100644 --- a/clients/TypeScript/packages/schema/package.json +++ b/clients/TypeScript/packages/schema/package.json @@ -1,6 +1,6 @@ { "name": "@cardano-ogmios/schema", - "version": "6.6.2", + "version": "6.7.0", "description": "Generated TypeScript from the Cardano Ogmios schema", "engines": { "node": ">=14" diff --git a/docker-compose.yml b/docker-compose.yml index 8b774d35d..76644d4a0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.5" services: cardano-node: - image: ghcr.io/intersectmbo/cardano-node:9.1.0 + image: ghcr.io/intersectmbo/cardano-node:9.1.1 command: [ "run", "--config", "/config/config.json", diff --git a/docs/content/api/_index.md b/docs/content/api/_index.md index ec5937d6b..608eb90ce 100644 --- a/docs/content/api/_index.md +++ b/docs/content/api/_index.md @@ -1,5 +1,5 @@ +++ -title = "WebSocket API Reference (v6.6.*)" +title = "WebSocket API Reference (v6.7.*)" weight = 4 chapter = false pre = "4. " diff --git a/docs/static/api/specification.yaml b/docs/static/api/specification.yaml index ca543fdf0..722ee4efb 100644 --- a/docs/static/api/specification.yaml +++ b/docs/static/api/specification.yaml @@ -1,7 +1,7 @@ asyncapi: '2.4.0' info: title: Ogmios - version: '6.6.*' + version: '6.7.*' description: | ### Protocols diff --git a/server/src/Ogmios/App/Protocol/TxSubmission.hs b/server/src/Ogmios/App/Protocol/TxSubmission.hs index aa33ed62f..1bbdae030 100644 --- a/server/src/Ogmios/App/Protocol/TxSubmission.hs +++ b/server/src/Ogmios/App/Protocol/TxSubmission.hs @@ -53,6 +53,7 @@ import Cardano.Ledger.BaseTypes import Cardano.Ledger.Core ( EraTx (..) , EraTxBody (..) + , eraName ) import Control.Monad.Trans.Except ( Except @@ -85,8 +86,10 @@ import Ogmios.Control.MonadSTM , takeTMVar ) import Ogmios.Data.EraTranslation - ( MultiEraUTxO (..) + ( MostRecentEra + , MultiEraUTxO (..) , Upgrade (..) + , upgradeGenTx ) import Ogmios.Data.Json ( Json @@ -128,10 +131,14 @@ import Ouroboros.Consensus.Cardano.Block , CardanoBlock , CardanoQueryResult , GenTx (..) + , HardForkApplyTxErr (..) ) import Ouroboros.Consensus.HardFork.Combinator ( HardForkBlock ) +import Ouroboros.Consensus.HardFork.Combinator.AcrossEras + ( EraMismatch (..) + ) import Ouroboros.Consensus.HardFork.Combinator.Ledger.Query ( QueryHardFork (..) ) @@ -180,6 +187,7 @@ import Type.Reflection import qualified Codec.Json.Rpc as Rpc import qualified Data.Aeson as Json import qualified Data.Map.Strict as Map +import qualified Data.Text as T import qualified Ouroboros.Consensus.HardFork.Combinator as HF import qualified Ouroboros.Consensus.Ledger.Query as Ledger import qualified Ouroboros.Network.Protocol.LocalStateQuery.Client as LSQ @@ -212,6 +220,16 @@ mkTxSubmissionClient tr defaultWithInternalError TxSubmissionCodecs{..} Executio await :: m (TxSubmissionMessage block) await = atomically (readTQueue queue) + isMostRecentEra era = + T.toLower (toText era) == T.toLower (toText (eraName @(MostRecentEra block))) + + -- NOTE: On successful submission, clear our cached + -- mempool to ensure we always use the latest available + -- mempool snapshot during evaluation. + clearMempoolOnSuccess = \case + SubmitSuccess -> clearMempoolM + _ -> pure () + clientStIdle :: m (LocalTxClientStIdle (SerializedTransaction block) (SubmitTransactionError block) m ()) clientStIdle = await >>= \case @@ -219,17 +237,34 @@ mkTxSubmissionClient tr defaultWithInternalError TxSubmissionCodecs{..} Executio defaultWithInternalError clientStIdle yield toResponse $ case request of MultiEraDecoderSuccess transaction -> do pure $ SendMsgSubmitTx transaction $ \result -> do - -- NOTE: On successful submission, clear our cached - -- mempool to ensure we always use the latest available - -- mempool snapshot during evaluation. case result of - SubmitSuccess -> clearMempoolM - SubmitFail{} -> pure () - mkSubmitTransactionResponse transaction result - & toResponse - & encodeSubmitTransactionResponse - & yield - clientStIdle + SubmitFail (ApplyTxErrWrongEra eraMismatch) | isMostRecentEra (ledgerEraName eraMismatch) -> do + case upgradeGenTx transaction of + Left hint -> do + SubmitTransactionFailedToUpgrade hint + & toResponse + & encodeSubmitTransactionResponse + & yield + clientStIdle + Right upgradedTx -> + pure $ SendMsgSubmitTx upgradedTx $ \result' -> do + clearMempoolOnSuccess result' + mkSubmitTransactionResponse transaction result' + & toResponse + & encodeSubmitTransactionResponse + & yield + clientStIdle + _ -> do + -- NOTE: On successful submission, clear our cached + -- mempool to ensure we always use the latest available + -- mempool snapshot during evaluation. + clearMempoolOnSuccess result + mkSubmitTransactionResponse transaction result + & toResponse + & encodeSubmitTransactionResponse + & yield + clientStIdle + MultiEraDecoderErrors errs -> do SubmitTransactionDeserialisationFailure errs & toResponse diff --git a/server/src/Ogmios/Data/EraTranslation.hs b/server/src/Ogmios/Data/EraTranslation.hs index 1af9e44fd..fafa1afa1 100644 --- a/server/src/Ogmios/Data/EraTranslation.hs +++ b/server/src/Ogmios/Data/EraTranslation.hs @@ -16,6 +16,7 @@ module Ogmios.Data.EraTranslation -- * Translations , Upgrade (..) + , upgradeGenTx ) where import Ogmios.Prelude @@ -51,13 +52,20 @@ import Data.Maybe.Strict import Ouroboros.Consensus.Cardano ( CardanoBlock ) +import Ouroboros.Consensus.Cardano.Block + ( GenTx (..) + ) import Ouroboros.Consensus.Shelley.Ledger ( ShelleyBlock ) +import Ouroboros.Consensus.Shelley.Ledger.Mempool + ( GenTx (..) + ) import qualified Cardano.Ledger.Alonzo.Tx as Alonzo import qualified Cardano.Ledger.Babbage.TxBody as Babbage import qualified Cardano.Ledger.Conway.Core as Conway +import qualified Cardano.Ledger.Core as Core import qualified Cardano.Ledger.Crypto as Ledger type family MostRecentEra block :: Type where @@ -106,6 +114,35 @@ instance let isValid = Alonzo.isValid tx pure $ AlonzoTx{body,wits,auxiliaryData,isValid} +---------- +-- GenTx +---------- + +upgradeGenTx + :: forall crypto. + ( Crypto crypto + ) + => GenTx (CardanoBlock crypto) + -> Either Text (GenTx (CardanoBlock crypto)) +upgradeGenTx = \case + GenTxByron _ -> + Left "cannot upgrade from Byron transaction: too old, use a more recent transaction builder." + GenTxShelley _ -> + Left "cannot upgrade from Shelley transaction: too old, use a more recent transaction builder." + GenTxAllegra _ -> + Left "cannot upgrade from Allegra transaction: too old, use a more recent transaction builder." + GenTxMary _ -> + Left "cannot upgrade from Mary transaction: too old, use a more recent transaction builder." + GenTxAlonzo (ShelleyTx hash txInAlonzo) -> do + txInBabbage <- left show $ Core.upgradeTx @(BabbageEra crypto) txInAlonzo + txInConway <- left show $ Core.upgradeTx @(ConwayEra crypto) txInBabbage + pure $ GenTxConway $ ShelleyTx hash txInConway + GenTxBabbage (ShelleyTx hash txInBabbage) -> do + txInConway <- left show $ Core.upgradeTx @(ConwayEra crypto) txInBabbage + pure $ GenTxConway $ ShelleyTx hash txInConway + latest@(GenTxConway(_))-> + Right latest + unsafeFromRight :: (HasCallStack) => Either Text a -> a unsafeFromRight = either error id diff --git a/server/src/Ogmios/Data/Protocol/TxSubmission.hs b/server/src/Ogmios/Data/Protocol/TxSubmission.hs index 33b36b211..75b8dee26 100644 --- a/server/src/Ogmios/Data/Protocol/TxSubmission.hs +++ b/server/src/Ogmios/Data/Protocol/TxSubmission.hs @@ -254,6 +254,7 @@ _decodeSubmitTransaction = data SubmitTransactionResponse block = SubmitTransactionSuccess (GenTxId block) | SubmitTransactionFailure (SubmitTransactionError block) + | SubmitTransactionFailedToUpgrade Text | SubmitTransactionDeserialisationFailure [(SomeShelleyEra, Binary.DecoderError, Word)] deriving (Generic) deriving instance @@ -281,6 +282,16 @@ _encodeSubmitTransactionResponse _proxy resolve $ encodeObject ("transaction" .= encodeTransactionId i) SubmitTransactionFailure e -> encodeSubmitTransactionError reject e + SubmitTransactionFailedToUpgrade hint -> + reject Rpc.FaultInvalidParams + "Non-upgradable transaction; it seems that you're trying to submit a \ + \transaction in a format that presents incompatibility with the current \ + \ledger era. The field \"data.hint\" contains possible useful information \ + \about what went wrong." + (pure $ encodeObject + ( "hint" .= encodeText hint + ) + ) SubmitTransactionDeserialisationFailure errs -> encodeDeserialisationFailure reject errs