Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/kupmios-ogmios-params-variants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@evolution-sdk/evolution": patch
---

The Kupmios provider's `getProtocolParameters` no longer fails against Ogmios servers whose protocol-parameter reply differs from the preprod shape it was written against. The Ogmios schema makes each `plutusCostModels` language optional — Ogmios builds that map from the cost models that exist on the network, so a language with no cost model is omitted entirely — and a missing language now maps to an empty cost model instead of failing the whole call (#568). The schema also accepts the Ogmios v7 spelling of the reference-script size limit: `maxReferenceScriptsSize` was renamed to `maxReferenceScriptsSizePerTransaction` (with a new `maxReferenceScriptsSizePerBlock` alongside), so all three keys are optional and either server generation decodes (#559).
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ const toProtocolParameters = (result: Ogmios.ProtocolParameters): Provider.Proto
maxCollateralInputs: Number(result.maxCollateralInputs),
minFeeRefScriptCostPerByte: result.minFeeReferenceScripts.base,
costModels: {
// A language Ogmios omitted has no cost model on this network: {}
PlutusV1: Object.fromEntries(
result.plutusCostModels["plutus:v1"].map((value, index) => [index.toString(), Number(value)])
(result.plutusCostModels["plutus:v1"] ?? []).map((value, index) => [index.toString(), Number(value)])
),
PlutusV2: Object.fromEntries(
result.plutusCostModels["plutus:v2"].map((value, index) => [index.toString(), Number(value)])
(result.plutusCostModels["plutus:v2"] ?? []).map((value, index) => [index.toString(), Number(value)])
),
PlutusV3: Object.fromEntries(
result.plutusCostModels["plutus:v3"].map((value, index) => [index.toString(), Number(value)])
(result.plutusCostModels["plutus:v3"] ?? []).map((value, index) => [index.toString(), Number(value)])
)
}
}
Expand Down
30 changes: 24 additions & 6 deletions packages/evolution/src/sdk/provider/internal/Ogmios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,25 @@ export const ProtocolParametersSchema = Schema.Struct({
range: Schema.BigInt,
multiplier: Schema.NumberFromString
}),
maxReferenceScriptsSize: Schema.Struct({
bytes: Schema.BigInt
}),
// Ogmios v7 renamed this to maxReferenceScriptsSizePerTransaction and
// added maxReferenceScriptsSizePerBlock; deployed servers run both major
// versions, so every spelling is optional (the value is not mapped into
// the provider's ProtocolParameters).
maxReferenceScriptsSize: Schema.optional(
Schema.Struct({
bytes: Schema.BigInt
})
),
maxReferenceScriptsSizePerTransaction: Schema.optional(
Schema.Struct({
bytes: Schema.BigInt
})
),
maxReferenceScriptsSizePerBlock: Schema.optional(
Schema.Struct({
bytes: Schema.BigInt
})
),
stakePoolVotingThresholds: Schema.Struct({
noConfidence: TupleNumberFromString,
constitutionalCommittee: Schema.Struct({
Expand Down Expand Up @@ -89,10 +105,12 @@ export const ProtocolParametersSchema = Schema.Struct({
minStakePoolCost: Schema.Struct({ ada: LovelaceAsset }),
minUtxoDepositConstant: Schema.Struct({ ada: LovelaceAsset }),
minUtxoDepositCoefficient: Schema.BigInt,
// Ogmios builds this map from the cost models that exist on the network,
// so a language with no cost model is omitted entirely, not sent empty.
plutusCostModels: Schema.Struct({
"plutus:v1": Schema.Array(Schema.BigInt),
"plutus:v2": Schema.Array(Schema.BigInt),
"plutus:v3": Schema.Array(Schema.BigInt)
"plutus:v1": Schema.optional(Schema.Array(Schema.BigInt)),
"plutus:v2": Schema.optional(Schema.Array(Schema.BigInt)),
"plutus:v3": Schema.optional(Schema.Array(Schema.BigInt))
}),
scriptExecutionPrices: Schema.Struct({
memory: TupleNumberFromString,
Expand Down
46 changes: 46 additions & 0 deletions packages/evolution/test/provider/Kupmios.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,52 @@ describe("Kupmios read paths", () => {
expect(Object.values(params.costModels.PlutusV3)).toEqual(expected.plutusCostModels["plutus:v3"])
})

it("getProtocolParameters with an Ogmios cost model language missing (#568)", async () => {
// Ogmios builds plutusCostModels from costModelsValid, so a network
// without a Plutus V1 cost model omits the "plutus:v1" key entirely.
const withoutV1 = protocolParameters.replace(/"plutus:v1": \[[^\]]*\],\s*/, "")
expect(withoutV1).not.toContain('"plutus:v1"')
stubKupmios({ ogmios: { "queryLedgerState/protocolParameters": withoutV1 } })
const { result: expected } = JSON.parse(withoutV1)

const params = await Effect.runPromise(KupmiosEffects.getProtocolParametersEffect(OGMIOS_URL))

// A missing language maps to an empty cost model; the others are intact
expect(params.costModels.PlutusV1).toEqual({})
expect(Object.values(params.costModels.PlutusV2)).toEqual(expected.plutusCostModels["plutus:v2"])
expect(Object.values(params.costModels.PlutusV3)).toEqual(expected.plutusCostModels["plutus:v3"])
expect(params.minFeeA).toBe(44)
})

it("getProtocolParameters with no Ogmios cost models at all (#568)", async () => {
const noModels = protocolParameters.replace(
/"plutusCostModels": \{[\s\S]*?\},\s*"scriptExecutionPrices"/,
`"plutusCostModels": {},\n "scriptExecutionPrices"`
)
expect(JSON.parse(noModels).result.plutusCostModels).toEqual({})
stubKupmios({ ogmios: { "queryLedgerState/protocolParameters": noModels } })

const params = await Effect.runPromise(KupmiosEffects.getProtocolParametersEffect(OGMIOS_URL))

expect(params.costModels).toEqual({ PlutusV1: {}, PlutusV2: {}, PlutusV3: {} })
})

it("getProtocolParameters against Ogmios v7 (maxReferenceScriptsSize renamed, #559)", async () => {
// Ogmios v7 renames maxReferenceScriptsSize to
// maxReferenceScriptsSizePerTransaction and adds a PerBlock key.
const v7 = protocolParameters.replace(
/"maxReferenceScriptsSize": \{\s*"bytes": 204800\s*\}/,
`"maxReferenceScriptsSizePerTransaction": {"bytes": 204800},\n "maxReferenceScriptsSizePerBlock": {"bytes": 1048576}`
)
expect(v7).toContain('"maxReferenceScriptsSizePerTransaction"')
expect(v7).not.toContain('"maxReferenceScriptsSize":')
stubKupmios({ ogmios: { "queryLedgerState/protocolParameters": v7 } })

const params = await Effect.runPromise(KupmiosEffects.getProtocolParametersEffect(OGMIOS_URL))

expect(params).toMatchObject({ minFeeA: 44, minFeeB: 155381, maxTxSize: 16384 })
})

it("getUtxos by address", async () => {
stubKupmios({ kupo: kupo() })

Expand Down