A ReST-ish server and CLI tool to expose Cardano-node's DB.
The goal is to produce arbitrary Amaru snapshots, from a cardano-node database.
E.g.
db-server amaru --db db --config config.json 531 532 533
would produce, in current directory, 531.snapshot, 532.snapshot and 533.snapshot, which can be used to start an Amaru node.
Current status:
- we read a chain-db in non UTxO-hd mode and we can serve (over HTTP or query) blocks, headers, and in-memory snapshots.
Next steps:
- read a UTxO-hd chain-db (update dependencies - and test)
- generate cardano-node ledger snapshot for arbitrary slot
- copy/adapt from db-synthesizer
- make these snapshots complete for Amaru (add UTxO tables)
- in a single command, produce a complete set of data to bootstrap Amaru.
- data is suitable for use by Amaru bootstrap command
- might need Amaru modification to bootstrap.
- demonstrate this works on a mithril snapshot.
- Install Haskell toolchain, for example using GHCUp or Nix
- Install Cardano node's system dependencies (see cardano-node wiki
db-server affords using Shake as a driver to build itself. This has the advantage of taking care of building and installing cardano-node's native dependencies.
./build.hs
cabal test
db-server can be used in two modes: as an HTTP server exposing some endpoints over an existing cardano-node DB, or as command-line query tool.
To run db-server over a preprod network database:
- Follow instructions from Mithril website to retrieve a preprod database using Preprod configuration. If all goes well, you should have a directory containing a primed database for example in
./db - Retrieve all configuration files for
Preprodnetwork from the environment page into a directory, say./config
Then from the source directory of db-server, starts the server with the following command:
cabal run db-server -- serve --db db --config config/config.json
In the terminal, one should start seeing JSON-formatted log entries like:
{"log":"TraceOpenEvent StartedOpeningDB","tag":"ChainDB","timestamp":"2025-01-17T21:35:25.84556Z"}
{"log":"TraceOpenEvent StartedOpeningImmutableDB","tag":"ChainDB","timestamp":"2025-01-17T21:35:25.845566Z"}
{"log":"TraceImmutableDBEvent (ChunkValidationEvent (StartedValidatingChunk 3735 3735))","tag":"ChainDB","timestamp":"2025-01-17T21:35:25.89414Z"}
...
{"log":{"host":"127.0.0.1","port":9003,"tag":"HttpServerListening"},"tag":"HttpServer","timestamp":"2025-01-17T21:35:38.118951Z"}
The last entry above with the HttpServerListening signals the database is open and the server can answer queries.
GET /blocks/:slot/:hash/header: Retrieves raw hex-encoded bytes of a block header at given:slotand with given:hash(aka. point)200: Returns the raw hex-encoded bytes for header400: Wrongly formatted:slotor:hashpaths404: No block exists at given point
Example (result truncated for legibility):
% curl -v http://localhost:9003/blocks/69206375/6f99b5f3deaeae8dc43fce3db2f3cd36ad8ed174ca3400b5b1bed76fdf248912/header
828a1a0028375b1a0420016758209694aa14a063868d37c5601b7b...
GET /blocks/:slot/:hash/parent: Retrieves raw hex-encoded bytes of the block header which is the parent of the header at given:slotand with given:hash(aka. point)200: Returns the raw hex-encoded bytes for header400: Wrongly formatted:slotor:hashpaths404: No block exists at given point
Example (result truncated for legibility):
% curl -v http://localhost:9003/blocks/69206375/6f99b5f3deaeae8dc43fce3db2f3cd36ad8ed174ca3400b5b1bed76fdf248912/parent
828a1a0028375b1a0420016758209694aa14a063868d37c5601b7b...
GET /blocks/:slot/:hash: Retrieves raw hex-encoded CBOR bytes of a block at given:slotand with given:hash(aka. point)200: Returns hex-encoded bytes for the block serialised as CBOR400: Wrongly formatted:slotor:hashpaths404: No block exists at given point
Example (result is truncated for legibility, and the block is empty):
% curl -v http://localhost:9003/blocks/69206375/6f99b5f3deaeae8dc43fce3db2f3cd36ad8ed174ca3400b5b1bed76fdf248912
820685828a0c19012...8080a080
GET /snapshots: List all the points for which this db-server has a ledger state snapshot200: Returns JSON-encoded list of points
Example (result is truncated for legibility, and the block is empty):
% curl -v http://localhost:9003/snapshots | jq .
...
{
"hash": "82499f71f6ab9dda3f84023897ca1e3cb3fe5c19b7018be2e55df57b191713a0",
"slot": 59735
},
{
"hash": "574a6ed18ccca232028a4b2632abdb7b99ef28adf25e58ee7392574fe69a4c74",
"slot": 59737
},
{
"hash": "578cbb520f441b7d1530dac16844302c3e5e9ba4c434b439359c89c62a08cd69",
"slot": 59747
}
]
GET /snapshots/:slot: Retrieve raw hex-encoded CBOR bytes of ledger state at given:slot, if it exists200: Returns hex-encoded bytes for the snapshot serialised as CBOR400: Wrongly formatted:slot404: No snapshot exists at given slot
Example (result is truncated for legibility, and the block is empty):
% curl -v http://localhost:9003/snapshots/59737
...
76ba082c604e6af7c482f716934ed08d19c227331b00071a1474e7f000f6