Skip to content

Commit 1f00422

Browse files
authored
Merge pull request #1305 from IntersectMBO/mgalazyn/fix/rpc-initial-funds-extraconfig
cardano-rpc: fix ReadGenesis initial funds and stop retaining the genesis in memory
2 parents d65d8a0 + 9c71b65 commit 1f00422

12 files changed

Lines changed: 441 additions & 65 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
project: cardano-api
2+
3+
pr: 1305
4+
5+
kind:
6+
- compatible
7+
8+
description: |
9+
Export resolveShelleyInitialFunds from Cardano.Api.LedgerState. It takes a ShelleyGenesis and resolves its initial funds against its sgExtraConfig the way ledger's own genesis state construction does, including streaming InjectionFromFile sources with content-hash verification.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
project: cardano-rpc
2+
3+
pr: 1305
4+
5+
kind:
6+
- bugfix
7+
- breaking
8+
9+
description: |
10+
Fixed the UTxO RPC `ReadGenesis` response reporting no initial funds for networks created with `cardano-cli create-testnet-data`, and stopped the node retaining the parsed genesis in memory for its whole lifetime. The Shelley genesis is now read from disk when `ReadGenesis` is served, verified against the genesis hash computed at node startup, and kept for five minutes after the last request; a genesis file that changed since startup fails the request with `FAILED_PRECONDITION`. Breaking change: `mkNodeKernelAccess` no longer takes `ProtocolInfoArgs` and takes the Shelley genesis file path instead.

cardano-api/cardano-api.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ library
167167
filepath,
168168
formatting,
169169
fs-api ^>=0.4,
170+
io-classes,
170171
iproute,
171172
memory,
172173
mempack,

cardano-api/src/Cardano/Api/Consensus.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ module Cardano.Api.Consensus
5353
-- * Reexports from @ouroboros-consensus@
5454
, BlockComponent (..)
5555
, ByronBlock
56+
, ByronPartialLedgerConfig (..)
5657
, CardanoBlock
5758
, ChainDB.ChainDB
5859
, ChainDB.ChainType (..)
@@ -66,23 +67,28 @@ module Cardano.Api.Consensus
6667
, ChainDepState
6768
, GenTx (..)
6869
, EraMismatch (..)
70+
, HardForkLedgerConfig (..)
6971
, HasHardForkHistory (..)
7072
, HasHeader
7173
, Header
7274
, HeaderHash
7375
, NodeKernel (..)
7476
, OneEraHash (..)
7577
, PastHorizonException
78+
, PerEraLedgerConfig (..)
7679
, PraosProtocolSupportsNode
7780
, PraosProtocolSupportsNodeCrypto
7881
, RealPoint (..)
7982
, ResourceRegistry
8083
, SecurityParam (..)
8184
, ShelleyGenesisStaking (..)
85+
, ShelleyPartialLedgerConfig (..)
8286
, StandardCrypto
8387
, TopLevelConfig
88+
, WrapPartialLedgerConfig (..)
8489
, ledgerState
8590
, shelleyLedgerGenesis
91+
, shelleyLedgerTranslationContext
8692
, blockHash
8793
, blockNo
8894
, blockSlot

cardano-api/src/Cardano/Api/Consensus/Internal/Reexport.hs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Cardano.Api.Consensus.Internal.Reexport
22
( BlockComponent (..)
33
, ByronBlock
4+
, ByronPartialLedgerConfig (..)
45
, CardanoBlock
56
, ChainUpdate (..)
67
, ConfigSupportsNode
@@ -12,18 +13,23 @@ module Cardano.Api.Consensus.Internal.Reexport
1213
, EraMismatch (..)
1314
, NodeKernel (..)
1415
, OneEraHash (..)
16+
, HardForkLedgerConfig (..)
1517
, HasHardForkHistory (..)
1618
, PastHorizonException
19+
, PerEraLedgerConfig (..)
1720
, PraosProtocolSupportsNode
1821
, PraosProtocolSupportsNodeCrypto
1922
, RealPoint (..)
2023
, ResourceRegistry
2124
, SecurityParam (..)
2225
, ShelleyGenesisStaking (..)
26+
, ShelleyPartialLedgerConfig (..)
2327
, StandardCrypto
2428
, TopLevelConfig
29+
, WrapPartialLedgerConfig (..)
2530
, ledgerState
2631
, shelleyLedgerGenesis
32+
, shelleyLedgerTranslationContext
2733
, blockHash
2834
, blockNo
2935
, blockSlot
@@ -52,6 +58,7 @@ import Ouroboros.Consensus.Block
5258
, blockNo
5359
, blockSlot
5460
)
61+
import Ouroboros.Consensus.Byron.ByronHFC (ByronPartialLedgerConfig (..))
5562
import Ouroboros.Consensus.Byron.Ledger (ByronBlock (byronBlockRaw), GenTx (..), byronIdTx)
5663
import Ouroboros.Consensus.Cardano.Block (CardanoBlock, EraMismatch (..))
5764
import Ouroboros.Consensus.Config
@@ -63,7 +70,12 @@ import Ouroboros.Consensus.Config
6370
import Ouroboros.Consensus.Config.SecurityParam (SecurityParam (..))
6471
import Ouroboros.Consensus.Config.SupportsNode (ConfigSupportsNode)
6572
import Ouroboros.Consensus.HardFork.Abstract (HasHardForkHistory (..))
66-
import Ouroboros.Consensus.HardFork.Combinator.AcrossEras (OneEraHash (..))
73+
import Ouroboros.Consensus.HardFork.Combinator.AcrossEras
74+
( OneEraHash (..)
75+
, PerEraLedgerConfig (..)
76+
)
77+
import Ouroboros.Consensus.HardFork.Combinator.Basics (HardForkLedgerConfig (..))
78+
import Ouroboros.Consensus.HardFork.Combinator.PartialConfig (WrapPartialLedgerConfig (..))
6779
import Ouroboros.Consensus.HardFork.History.EpochInfo (interpreterToEpochInfo)
6880
import Ouroboros.Consensus.HardFork.History.Qry
6981
( PastHorizonException
@@ -79,7 +91,11 @@ import Ouroboros.Consensus.Protocol.Praos.Common
7991
, PraosProtocolSupportsNodeCrypto
8092
, getOpCertCounters
8193
)
82-
import Ouroboros.Consensus.Shelley.Ledger.Ledger (shelleyLedgerGenesis)
94+
import Ouroboros.Consensus.Shelley.Ledger.Ledger
95+
( ShelleyPartialLedgerConfig (..)
96+
, shelleyLedgerGenesis
97+
, shelleyLedgerTranslationContext
98+
)
8399
import Ouroboros.Consensus.Shelley.Node (ShelleyGenesisStaking (..))
84100
import Ouroboros.Consensus.Storage.Common (BlockComponent (..))
85101
import Ouroboros.Consensus.Util.Condense (condense)

cardano-api/src/Cardano/Api/LedgerState.hs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ module Cardano.Api.LedgerState
7777
, GenesisConfig (..)
7878
, readCardanoGenesisConfig
7979
, mkProtocolInfoCardano
80+
, resolveShelleyInitialFunds
8081

8182
-- *** Byron Genesis Config
8283
, readByronGenesisConfig
@@ -174,6 +175,7 @@ import Cardano.Ledger.Keys qualified as SL
174175
import Cardano.Ledger.Shelley.API qualified as ShelleyAPI
175176
import Cardano.Ledger.Shelley.Core qualified as Core
176177
import Cardano.Ledger.Shelley.Genesis qualified as Ledger
178+
import Cardano.Ledger.Shelley.Transition qualified as Ledger
177179
import Cardano.Ledger.Slot qualified as Ledger
178180
import Cardano.Ledger.State qualified as SL
179181
import Cardano.Protocol.Crypto qualified as Crypto
@@ -221,8 +223,10 @@ import Ouroboros.Network.Protocol.ChainSync.PipelineDecision
221223
import Control.Concurrent
222224
import Control.DeepSeq
223225
import Control.Error.Util (note)
224-
import Control.Exception.Safe
226+
import Control.Exception.Safe hiding (MonadThrow)
225227
import Control.Monad
228+
import Control.Monad.Class.MonadST (MonadST)
229+
import Control.Monad.Class.MonadThrow (MonadThrow)
226230
import Control.Monad.State.Strict
227231
import Control.Tracer qualified as Tracer
228232
import Data.Aeson as Aeson
@@ -272,7 +276,7 @@ import GHC.Stack (HasCallStack)
272276
import Lens.Micro
273277
import Network.Mux qualified as Mux
274278
import Network.TypedProtocol.Core (Nat (..))
275-
import System.FS.API (SomeHasFS)
279+
import System.FS.API (SomeHasFS (..))
276280
import System.FilePath
277281

278282
data InitialLedgerStateError
@@ -1521,6 +1525,53 @@ readCardanoGenesisConfig enc = do
15211525
let transCfg = Ledger.mkLatestTransitionConfig shelleyGenesis alonzoGenesis conwayGenesis dijkstraGenesis
15221526
pure $ GenesisCardano enc byronGenesis shelleyGenesisHash transCfg
15231527

1528+
-- | Resolve a Shelley genesis' 'Ledger.sgInitialFunds' against its
1529+
-- 'Ledger.sgExtraConfig', mirroring the resolution ledger's own
1530+
-- @registerInitialFunds@ performs when building the initial ledger state
1531+
-- from genesis.
1532+
--
1533+
-- A 'Ledger.ShelleyGenesis' carries two sources of initial funds: the legacy
1534+
-- 'Ledger.sgInitialFunds' field, and 'Ledger.sgExtraConfig', which is where
1535+
-- @cardano-cli create-testnet-data@ puts the funded addresses, embedded or in
1536+
-- an external hash-verified file. The ledger reconciles the two only while
1537+
-- building the initial ledger state and never writes the result back into the
1538+
-- 'Ledger.ShelleyGenesis' value, so a parsed genesis read outside that path
1539+
-- must repeat the resolution. Once the ledger drops the legacy field, the
1540+
-- two-source reconciliation here can go, but turning 'Ledger.secInitialFunds'
1541+
-- into actual funds (including reading and hash-checking an injection file)
1542+
-- is still needed.
1543+
--
1544+
-- Throws 'Ledger.InjectionConflictingSources' if the genesis specifies initial
1545+
-- funds through both the legacy field and the extra config, and
1546+
-- 'Ledger.InjectionHashMismatch' if an 'Ledger.InjectionFromFile' source does
1547+
-- not hash to the value the genesis declares for it.
1548+
resolveShelleyInitialFunds
1549+
:: (MonadST m, MonadThrow m)
1550+
=> SomeHasFS m
1551+
-- ^ Filesystem capability used to stream an 'Ledger.InjectionFromFile'
1552+
-- source, mounted at the Shelley genesis file's directory.
1553+
-> Ledger.ShelleyGenesis
1554+
-- ^ The Shelley genesis whose initial funds to resolve.
1555+
-> m Ledger.ShelleyGenesis
1556+
resolveShelleyInitialFunds (SomeHasFS hasFS) genesis = do
1557+
initialFundsSource <-
1558+
Ledger.resolveInjectionSource
1559+
"initialFunds"
1560+
(Ledger.sgExtraConfig genesis)
1561+
Ledger.secInitialFunds
1562+
(Ledger.sgInitialFunds genesis)
1563+
resolvedInitialFunds <-
1564+
fromList <$> Ledger.foldInjectionData hasFS initialFundsSource (flip (:)) []
1565+
pure $
1566+
genesis
1567+
& Ledger.sgInitialFundsL .~ resolvedInitialFunds
1568+
-- The source has now been folded into 'sgInitialFunds'; null it out
1569+
-- so that re-resolving this (already-resolved) genesis later does
1570+
-- not trip 'Ledger.InjectionConflictingSources'.
1571+
& Ledger.sgExtraConfigL .~ (clearInitialFundsSource <$> Ledger.sgExtraConfig genesis)
1572+
where
1573+
clearInitialFundsSource extraConfig = extraConfig{Ledger.secInitialFunds = Ledger.NoInjection}
1574+
15241575
exampleDijkstraGenesis :: Ledger.DijkstraGenesis
15251576
exampleDijkstraGenesis =
15261577
Ledger.DijkstraGenesis

cardano-rpc/cardano-rpc.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ library
5858
Cardano.Rpc.Server.Internal.Error
5959
Cardano.Rpc.Server.Internal.Monad
6060
Cardano.Rpc.Server.Internal.Node
61+
Cardano.Rpc.Server.Internal.TimedCache
6162
Cardano.Rpc.Server.Internal.Tracing
6263
Cardano.Rpc.Server.Internal.UtxoRpc.Eval
6364
Cardano.Rpc.Server.Internal.UtxoRpc.Predicate
@@ -115,6 +116,7 @@ library
115116
errors,
116117
filepath,
117118
formatting,
119+
fs-api ^>=0.4,
118120
generic-data,
119121
grapesy,
120122
grpc-spec,
@@ -125,6 +127,7 @@ library
125127
proto-lens-protobuf-types,
126128
random,
127129
rio,
130+
strict-sop-core,
128131
text,
129132
time,
130133

0 commit comments

Comments
 (0)