Skip to content

Commit

Permalink
Merge pull request #222 from ginnun/feat/custom-network-support
Browse files Browse the repository at this point in the history
Feat/custom network support
  • Loading branch information
slowbackspace authored Nov 11, 2024
2 parents c415362 + ad84ced commit d5b2f7e
Show file tree
Hide file tree
Showing 25 changed files with 169 additions and 139 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Added custom network support
- Added option to disable token registery lookups

## [2.3.1] - 2024-11-04

### Fixed
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ If you are using an authenticated db connection that requires a password, you'd
database: 'dbname'
# Optionally define a password
password: 'randomstringthatissolongandpowerfulthatnoonecanguess'
# Cardano network - mainnet, testnet, preview, preprod
# Cardano network - mainnet, testnet, preview, preprod, custom
network: 'mainnet'
# path to the folder containing genesis data. If left blank, ./genesis/${network} will be used
genesisDataFolder: './genesis/mainnet'
# Path to token registry directory (see next section for more details)
tokenRegistryUrl: 'https://tokens.cardano.org'
# Experimental Mithril proxy
Expand All @@ -71,7 +73,7 @@ If you are using an authenticated db connection that requires a password, you'd
<details>
<summary>:bulb: All config variables can be also set via environment variables which take precedence over values from a config file.</summary>
These values are `BLOCKFROST_CONFIG_SERVER_PORT`, `BLOCKFROST_CONFIG_SERVER_DEBUG`, `BLOCKFROST_CONFIG_SERVER_PROMETHEUS_METRICS`, `BLOCKFROST_CONFIG_DBSYNC_HOST`, `BLOCKFROST_CONFIG_DBSYNC_USER`, `BLOCKFROST_CONFIG_DBSYNC_DATABASE`, `BLOCKFROST_CONFIG_DBSYNC_MAX_CONN`, `BLOCKFROST_CONFIG_NETWORK`, `BLOCKFROST_CONFIG_TOKEN_REGISTRY_URL`.
These values are `BLOCKFROST_CONFIG_SERVER_PORT`, `BLOCKFROST_CONFIG_SERVER_DEBUG`, `BLOCKFROST_CONFIG_SERVER_PROMETHEUS_METRICS`, `BLOCKFROST_CONFIG_DBSYNC_HOST`, `BLOCKFROST_CONFIG_DBSYNC_USER`, `BLOCKFROST_CONFIG_DBSYNC_DATABASE`, `BLOCKFROST_CONFIG_DBSYNC_MAX_CONN`, `BLOCKFROST_CONFIG_NETWORK`, `BLOCKFROST_CONFIG_GENESIS_DATA_FOLDER`, `BLOCKFROST_CONFIG_TOKEN_REGISTRY_URL`.

</details>

Expand Down Expand Up @@ -229,6 +231,9 @@ A minimal usage example is:

Check the [nixos-module.nix file](./nixos-module.nix) to check options and the default values.

## Custom Networks
blockfrost-ryo can be configured to run with any genesis parameters. Setting network to `custom`, and using `genesisDataFolder` value in the yaml configuration or environment variable `BLOCKFROST_CONFIG_GENESIS_DATA_FOLDER` you can specify your genesis details.

## Developing

This is an open-source project and anyone is welcome to contribute, please see [CONTRIBUTING](CONTRIBUTING.md) for more information.
6 changes: 6 additions & 0 deletions genesis/mainnet/byron_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"epoch_length": 21600,
"slot_length": 20,
"safe_zone": 4320,
"end_epoch": 208
}
12 changes: 12 additions & 0 deletions genesis/mainnet/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"active_slots_coefficient": 0.05,
"update_quorum": 5,
"max_lovelace_supply": "45000000000000000",
"network_magic": 764824073,
"epoch_length": 432000,
"system_start": 1506203091,
"slots_per_kes_period": 129600,
"slot_length": 1,
"max_kes_evolutions": 62,
"security_param": 2160
}
6 changes: 6 additions & 0 deletions genesis/preprod/byron_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"epoch_length": 21600,
"slot_length": 20,
"safe_zone": 4320,
"end_epoch": 4
}
12 changes: 12 additions & 0 deletions genesis/preprod/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"active_slots_coefficient": 0.05,
"update_quorum": 5,
"max_lovelace_supply": "45000000000000000",
"network_magic": 1,
"epoch_length": 432000,
"system_start": 1654041600,
"slots_per_kes_period": 129600,
"slot_length": 1,
"max_kes_evolutions": 62,
"security_param": 2160
}
6 changes: 6 additions & 0 deletions genesis/preview/byron_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"epoch_length": 4320,
"slot_length": 20,
"safe_zone": 864,
"end_epoch": 0
}
12 changes: 12 additions & 0 deletions genesis/preview/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"active_slots_coefficient": 0.05,
"update_quorum": 5,
"max_lovelace_supply": "45000000000000000",
"network_magic": 2,
"epoch_length": 86400,
"system_start": 1666656000,
"slots_per_kes_period": 129600,
"slot_length": 1,
"max_kes_evolutions": 62,
"security_param": 432
}
6 changes: 6 additions & 0 deletions genesis/sanchonet/byron_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"epoch_length": 4320,
"slot_length": 20,
"safe_zone": 864,
"end_epoch": 0
}
12 changes: 12 additions & 0 deletions genesis/sanchonet/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"active_slots_coefficient": 0.05,
"update_quorum": 3,
"max_lovelace_supply": "45000000000000000",
"network_magic": 4,
"epoch_length": 86400,
"system_start": 1686789000,
"slots_per_kes_period": 129600,
"slot_length": 1,
"max_kes_evolutions": 62,
"security_param": 432
}
6 changes: 6 additions & 0 deletions genesis/testnet/byron_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"epoch_length": 21600,
"slot_length": 20,
"safe_zone": 4320,
"end_epoch": 74
}
12 changes: 12 additions & 0 deletions genesis/testnet/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"active_slots_coefficient": 0.05,
"update_quorum": 5,
"max_lovelace_supply": "45000000000000000",
"network_magic": 1097911063,
"epoch_length": 432000,
"system_start": 1563999616,
"slots_per_kes_period": 129600,
"slot_length": 1,
"max_kes_evolutions": 62,
"security_param": 2160
}
28 changes: 26 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import config from 'config';
import { CARDANO_NETWORKS, Network } from './types/common.js';
import { ByronEraParameters, CARDANO_NETWORKS, Network } from './types/common.js';
import { readFileSync } from 'node:fs';
import * as ResponseTypes from './types/responses/ledger.js';

const MITHRIL_ENDPOINT_ALLOWLIST_DEFAULT = [
'', // root endpoint, same as "/", but some env are trimming trailing slash so request to /mithril/ could be received as /mithril
Expand Down Expand Up @@ -60,9 +62,15 @@ export const loadConfig = () => {
const network = process.env.BLOCKFROST_CONFIG_NETWORK ?? config.get('network');

if (!network || !CARDANO_NETWORKS.includes(network)) {
throw new Error('Invalid network configuration.');
throw new Error(`Invalid network configuration: ${network}`);
}
// token registry
const tokenRegistryEnabled = Boolean(
process.env.BLOCKFROST_CONFIG_TOKEN_REGISTRY_ENABLED ?? config.has('tokenRegistryEnabled')
? config.get<boolean>('tokenRegistryEnabled')
: true,
);

const tokenRegistryUrl =
process.env.BLOCKFROST_CONFIG_TOKEN_REGISTRY_URL ?? config.get('tokenRegistryUrl');

Expand Down Expand Up @@ -98,6 +106,19 @@ export const loadConfig = () => {
throw new Error('Invalid Mithril Aggregator configuration');
}

// genesis
const genesisDataFolder =
process.env.BLOCKFROST_CONFIG_GENESIS_DATA_FOLDER ?? config.has('genesisDataFolder')
? config.get<string>('genesisDataFolder')
: `./genesis/${network}`;

const genesis = JSON.parse(
readFileSync(genesisDataFolder + '/genesis.json', 'utf8'),
) as ResponseTypes.Ledger;
const byronGenesis = JSON.parse(
readFileSync(genesisDataFolder + '/byron_genesis.json', 'utf8'),
) as ByronEraParameters;

return {
server: {
listenAddress,
Expand All @@ -116,7 +137,10 @@ export const loadConfig = () => {
ssl,
},
network: network as Network,
genesis,
byronGenesis,
tokenRegistryUrl,
tokenRegistryEnabled,
mithril: {
enabled: mithrilEnabled,
aggregator: mithrilAggregator as string,
Expand Down
99 changes: 1 addition & 98 deletions src/constants/genesis.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,4 @@
import * as ResponseTypes from '../types/responses/ledger.js';
import { Network, ByronEraParameters, ProtocolInfo } from '../types/common.js';

export const GENESIS: Record<Network, ResponseTypes.Ledger> = {
mainnet: {
active_slots_coefficient: 0.05,
update_quorum: 5,
max_lovelace_supply: '45000000000000000',
network_magic: 764_824_073,
epoch_length: 432_000,
system_start: 1_506_203_091,
slots_per_kes_period: 129_600,
slot_length: 1,
max_kes_evolutions: 62,
security_param: 2160,
},
testnet: {
active_slots_coefficient: 0.05,
update_quorum: 5,
max_lovelace_supply: '45000000000000000',
network_magic: 1_097_911_063,
epoch_length: 432_000,
system_start: 1_563_999_616,
slots_per_kes_period: 129_600,
slot_length: 1,
max_kes_evolutions: 62,
security_param: 2160,
},
preview: {
active_slots_coefficient: 0.05,
update_quorum: 5,
max_lovelace_supply: '45000000000000000',
network_magic: 2,
epoch_length: 86_400,
system_start: 1_666_656_000,
slots_per_kes_period: 129_600,
slot_length: 1,
max_kes_evolutions: 62,
security_param: 432,
},
preprod: {
active_slots_coefficient: 0.05,
update_quorum: 5,
max_lovelace_supply: '45000000000000000',
network_magic: 1,
epoch_length: 432_000,
system_start: 1_654_041_600,
slots_per_kes_period: 129_600,
slot_length: 1,
max_kes_evolutions: 62,
security_param: 2160,
},
sanchonet: {
active_slots_coefficient: 0.05,
update_quorum: 3,
max_lovelace_supply: '45000000000000000',
network_magic: 4,
epoch_length: 86_400,
system_start: 1_686_789_000,
slots_per_kes_period: 129_600,
slot_length: 1,
max_kes_evolutions: 62,
security_param: 432,
},
};

export const BYRON_GENESIS: Record<Network, ByronEraParameters> = {
mainnet: {
epoch_length: 21_600,
slot_length: 20,
safe_zone: 4320,
end_epoch: 208,
},
testnet: {
epoch_length: 21_600,
slot_length: 20,
safe_zone: 4320,
end_epoch: 74,
},
preprod: {
epoch_length: 21_600,
slot_length: 20,
safe_zone: 4320,
end_epoch: 4,
},
preview: {
epoch_length: 4320,
slot_length: 20,
safe_zone: 864,
end_epoch: 0,
},
sanchonet: {
epoch_length: 4320,
slot_length: 20,
safe_zone: 864,
end_epoch: 0,
},
};
import { ProtocolInfo } from '../types/common.js';

export const PROTOCOL_VERSIONS: Record<number, ProtocolInfo> = {
0: {
Expand Down
4 changes: 1 addition & 3 deletions src/routes/epochs/latest/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { FastifyInstance } from 'fastify';

import { getConfig } from '../../../config.js';
import { GENESIS } from '../../../constants/genesis.js';
import { SQLQuery } from '../../../sql/index.js';
import * as QueryTypes from '../../../types/queries/epochs.js';
import * as ResponseTypes from '../../../types/responses/epochs.js';
Expand All @@ -18,8 +17,7 @@ async function route(fastify: FastifyInstance) {
const clientDbSync = await getDbSync(fastify);

try {
const network = getConfig().network;
const epochLength = GENESIS[network].epoch_length;
const epochLength = getConfig().genesis.epoch_length;
const { rows }: { rows: ResponseTypes.Epoch[] } =
await clientDbSync.query<QueryTypes.Epoch>(SQLQuery.get('epochs_latest'), [epochLength]);

Expand Down
4 changes: 1 addition & 3 deletions src/routes/epochs/number/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { FastifyInstance, FastifyRequest } from 'fastify';

import { getConfig } from '../../../config.js';
import { GENESIS } from '../../../constants/genesis.js';
import { SQLQuery } from '../../../sql/index.js';
import * as QueryTypes from '../../../types/queries/epochs.js';
import * as ResponseTypes from '../../../types/responses/epochs.js';
Expand All @@ -24,8 +23,7 @@ async function route(fastify: FastifyInstance) {
return handle400Custom(reply, 'Missing, out of range or malformed epoch_number.');
}

const network = getConfig().network;
const epochLength = GENESIS[network].epoch_length;
const epochLength = getConfig().genesis.epoch_length;
const { rows }: { rows: ResponseTypes.Epoch[] } =
await clientDbSync.query<QueryTypes.Epoch>(SQLQuery.get('epochs_number'), [
request.params.number,
Expand Down
4 changes: 1 addition & 3 deletions src/routes/epochs/number/next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { isUnpaged } from '../../../utils/routes.js';
import { toJSONStream } from '../../../utils/string-utils.js';
import { FastifyInstance, FastifyRequest } from 'fastify';
import { getConfig } from '../../../config.js';
import { GENESIS } from '../../../constants/genesis.js';
import { SQLQuery } from '../../../sql/index.js';
import * as QueryTypes from '../../../types/queries/epochs.js';
import * as ResponseTypes from '../../../types/responses/epochs.js';
Expand Down Expand Up @@ -35,8 +34,7 @@ async function route(fastify: FastifyInstance) {
return handle404(reply);
}

const network = getConfig().network;
const epochLength = GENESIS[network].epoch_length;
const epochLength = getConfig().genesis.epoch_length;

const unpaged = isUnpaged(request);
const { rows }: { rows: ResponseTypes.Epoch[] } = unpaged
Expand Down
4 changes: 1 addition & 3 deletions src/routes/epochs/number/previous.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { toJSONStream } from '../../../utils/string-utils.js';
import { FastifyInstance, FastifyRequest } from 'fastify';

import { getConfig } from '../../../config.js';
import { GENESIS } from '../../../constants/genesis.js';
import { SQLQuery } from '../../../sql/index.js';
import * as QueryTypes from '../../../types/queries/epochs.js';
import * as ResponseTypes from '../../../types/responses/epochs.js';
Expand Down Expand Up @@ -36,8 +35,7 @@ async function route(fastify: FastifyInstance) {
return handle404(reply);
}

const network = getConfig().network;
const epochLength = GENESIS[network].epoch_length;
const epochLength = getConfig().genesis.epoch_length;

const unpaged = isUnpaged(request);
const { rows }: { rows: ResponseTypes.Epoch[] } = unpaged
Expand Down
4 changes: 1 addition & 3 deletions src/routes/ledger/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import { FastifyInstance } from 'fastify';
import { getSchemaForEndpoint } from '@blockfrost/openapi';
import * as ResponseTypes from '../../types/responses/ledger.js';
import { getConfig } from '../../config.js';
import { GENESIS } from '../../constants/genesis.js';

async function route(fastify: FastifyInstance) {
fastify.route({
url: '/genesis',
method: 'GET',
schema: getSchemaForEndpoint('/genesis'),
handler: async (_request, reply) => {
const network = getConfig().network;
const genesisData: ResponseTypes.Ledger | undefined = GENESIS[network];
const genesisData: ResponseTypes.Ledger = getConfig().genesis;

if (genesisData) {
return reply.send(genesisData);
Expand Down
Loading

0 comments on commit d5b2f7e

Please sign in to comment.