Skip to content

Commit

Permalink
CAD-2420 supervisord: the wealth of profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
deepfire committed Jan 26, 2021
1 parent 7501d99 commit c85a983
Show file tree
Hide file tree
Showing 11 changed files with 472 additions and 84 deletions.
14 changes: 9 additions & 5 deletions nix/supervisord-cluster/default.nix
Expand Up @@ -18,6 +18,9 @@ let
profile = lib.recursiveUpdate profiles."${profileName}" profileOverride;
inherit (profile) composition monetary;

profileDump = pkgs.writeText "profile-${profile.name}.json"
(__toJSON profile);

## This yields two attributes: 'params' and 'files'
genesis = pkgs.callPackage ./genesis.nix
{ inherit
Expand Down Expand Up @@ -61,7 +64,7 @@ let
addr = "127.0.0.1";
port = p;
valency = 1;
}) (lib.filter (p: p != selfPort) (lib.genList (i: basePort + i + 1) (composition.numBft + composition.numPools)));
}) (lib.filter (p: p != selfPort) (lib.genList (i: basePort + i + 1) (composition.n_bft_hosts + composition.n_pools)));
};
supervisorConfig = pkgs.writeText "supervisor.conf" (pkgs.commonLib.supervisord.writeSupervisorConfig ({
supervisord = {
Expand Down Expand Up @@ -93,7 +96,7 @@ let
stdout_logfile = "${stateDir}/bft${toString i}.stdout";
stderr_logfile = "${stateDir}/bft${toString i}.stderr";
}
) (lib.genList (i: i + 1) composition.numBft))
) (lib.genList (i: i + 1) composition.n_bft_hosts))
// lib.listToAttrs (map (i:
lib.nameValuePair "program:pool${toString i}" {
command = let
Expand All @@ -104,15 +107,15 @@ let
topology = __toFile "topology.yaml" (__toJSON (topologyFile port));
socketPath = "${stateDir}/pool${toString i}.socket";
dbPrefix = "db-pool${toString i}";
port = basePort + composition.numBft + i;
port = basePort + composition.n_bft_hosts + i;
nodeConfigFile = "${stateDir}/config.json";
};
script = mkStartScript envConfig;
in "${script}";
stdout_logfile = "${stateDir}/pool${toString i}.stdout";
stderr_logfile = "${stateDir}/pool${toString i}.stderr";
}
) (lib.genList (i: i + 1) composition.numPools))
) (lib.genList (i: i + 1) composition.n_pools))
// {
"program:webserver" = {
command = "${pkgs.python3}/bin/python -m http.server ${toString basePort}";
Expand All @@ -123,6 +126,7 @@ let
path = lib.makeBinPath [ cardano-cli bech32 pkgs.jq pkgs.gnused pkgs.coreutils pkgs.bash pkgs.moreutils ];

start = pkgs.writeScriptBin "start-cluster" ''
echo "Profile '${profile.name}' dump in: ${profileDump}"
set -euo pipefail
if [ -f ${stateDir}/supervisord.pid ]
then
Expand All @@ -134,7 +138,7 @@ let
echo "Transfering genesis funds to pool owners, register pools and delegations"
cardano-cli transaction submit --shelley-mode \
--tx-file ${stateDir}/shelley/transfer-register-delegate-tx.tx \
--testnet-magic ${toString genesis.params.networkMagic}
--testnet-magic ${toString genesis.params.network_magic}
sleep 5
echo 'Cluster started. Run `stop-cluster` to stop'
'';
Expand Down
75 changes: 39 additions & 36 deletions nix/supervisord-cluster/genesis.nix
Expand Up @@ -11,19 +11,18 @@
, profile
}:

with profile;
let
inherit (profile) composition monetary;

# creates a dummy genesis used as a template
genesisSpecJSON = runCommand "create-genesis" { buildInputs = [ cardano-cli ]; } ''
cardano-cli genesis create \
--testnet-magic ${toString profile.genesis.networkMagic} \
--genesis-dir . \
--gen-genesis-keys ${toString composition.numBft}
genesisSpecJSON = runCommand "genesis-spec" { buildInputs = [ cardano-cli ]; } ''
cardano-cli genesis create --genesis-dir . \
${toString cli_args.createSpec}
mv genesis.spec.json $out
'';
genesisSpec = __fromJSON (__readFile genesisSpecJSON);
genesis = lib.recursiveUpdate genesisSpec profile.genesis;
genesisSpec = lib.recursiveUpdate
(__fromJSON (__readFile genesisSpecJSON))
genesis.verbatim;
in

rec {
Expand All @@ -33,17 +32,17 @@ rec {
rm -rf ${stateDir}
mkdir -p ${stateDir}/{shelley,webserver}
cp ${__toFile "node.json" (__toJSON baseEnvConfig.nodeConfig)} ${stateDir}/config.json
cp ${writeText "genesis.spec.json" (__toJSON genesis)} ${stateDir}/shelley/genesis.spec.json
cardano-cli genesis create --testnet-magic ${toString genesis.networkMagic} \
--genesis-dir ${stateDir}/shelley \
--gen-genesis-keys ${toString composition.numBft} \
--gen-utxo-keys 1
jq -r --arg systemStart $(date --utc +"%Y-%m-%dT%H:%M:%SZ" --date="5 seconds") \
cp ${writeText "genesis.spec.json" (__toJSON genesisSpec)} ${stateDir}/shelley/genesis.spec.json
cardano-cli genesis create --genesis-dir ${stateDir}/shelley \
${toString
(__trace "creating genesis for profile \"${name}\""
cli_args.createSpec)}
jq -r --arg systemStart $(date --utc +"%Y-%m-%dT%H:%M:%SZ" --date="${genesis.genesis_future_offset}") \
'.systemStart = $systemStart |
.updateQuorum = ${toString composition.numBft} |
.initialFunds = (${__toJSON monetary.initialFunds})' \
.initialFunds = ${__toJSON genesisSpec.initialFunds} |
.updateQuorum = ${toString composition.n_bft_hosts}' \
${stateDir}/shelley/genesis.json | sponge ${stateDir}/shelley/genesis.json
for i in {1..${toString composition.numBft}}
for i in {1..${toString composition.n_bft_hosts}}
do
mkdir -p "${stateDir}/nodes/node-bft$i"
ln -s "../../shelley/delegate-keys/delegate$i.vrf.skey" "${stateDir}/nodes/node-bft$i/vrf.skey"
Expand All @@ -60,7 +59,7 @@ rec {
BFT_PORT=$(("${toString basePort}" + $i))
echo "$BFT_PORT" > "${stateDir}/nodes/node-bft$i/port"
done
for i in {1..${toString composition.numPools}}
for i in {1..${toString composition.n_pools}}
do
mkdir -p "${stateDir}/nodes/node-pool$i"
echo "Generating Pool $i Secrets"
Expand All @@ -74,12 +73,12 @@ rec {
cardano-cli address build \
--payment-verification-key-file "${stateDir}/nodes/node-pool$i/owner-utxo.vkey" \
--stake-verification-key-file "${stateDir}/nodes/node-pool$i/owner-stake.vkey" \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--out-file "${stateDir}/nodes/node-pool$i/owner.addr"
# Stake addresses
cardano-cli stake-address build \
--stake-verification-key-file "${stateDir}/nodes/node-pool$i/owner-stake.vkey" \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--out-file "${stateDir}/nodes/node-pool$i/owner-stake.addr"
# Stake addresses registration certs
cardano-cli stake-address registration-certificate \
Expand Down Expand Up @@ -128,9 +127,9 @@ rec {
METADATA_URL="http://localhost:${toString basePort}/pool$i.json"
METADATA_HASH=$(cardano-cli stake-pool metadata-hash --pool-metadata-file "${stateDir}/webserver/pool$i.json")
POOL_IP="127.0.0.1"
POOL_PORT=$(("${toString basePort}" + "${toString composition.numBft}" + $i))
POOL_PORT=$(("${toString basePort}" + "${toString composition.n_bft_hosts}" + $i))
echo "$POOL_PORT" > "${stateDir}/nodes/node-pool$i/port"
POOL_PLEDGE=${toString monetary.delegatePoolAmount}
POOL_PLEDGE=${toString genesis.pool_coin}
echo $POOL_PLEDGE > "${stateDir}/nodes/node-pool$i/pledge"
POOL_MARGIN_NUM=$(( $RANDOM % 10 + 1))
Expand All @@ -146,7 +145,7 @@ rec {
--metadata-hash "$METADATA_HASH" \
--pool-relay-port "$POOL_PORT" \
--pool-relay-ipv4 "127.0.0.1" \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--out-file "${stateDir}/nodes/node-pool$i/register.cert"
done
Expand All @@ -161,29 +160,29 @@ rec {
jq .protocolParams < ${stateDir}/shelley/genesis.json > ${stateDir}/pparams.json
TXIN_ADDR=$(cardano-cli genesis initial-addr \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--verification-key-file ${stateDir}/shelley/genesis-utxo.vkey)
cardano-cli transaction build-raw \
--ttl 1000 \
--fee 0 \
--tx-in $(cardano-cli genesis initial-txin \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--verification-key-file ${stateDir}/shelley/genesis-utxo.vkey) \
--tx-out "$TXIN_ADDR+0" \
${lib.concatMapStringsSep "" (i: ''
--tx-out $(cat "${stateDir}/nodes/node-pool${toString i}/owner.addr")+${toString monetary.delegatePoolAmount} \
--tx-out $(cat "${stateDir}/nodes/node-pool${toString i}/owner.addr")+${toString genesis.delegator_coin} \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/stake.reg.cert" \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/stake-reward.reg.cert" \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/register.cert" \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/owner-stake.deleg.cert" \'') (lib.genList (i: i + 1) composition.numPools)}
--certificate-file "${stateDir}/nodes/node-pool${toString i}/owner-stake.deleg.cert" \'') (lib.genList (i: i + 1) composition.n_pools)}
--out-file "${stateDir}/shelley/transfer-register-delegate-tx.txbody"
FEE=$(cardano-cli transaction calculate-min-fee \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--protocol-params-file ${stateDir}/pparams.json \
--tx-in-count 1 \
--tx-out-count ${toString (composition.numPools + 1)} \
--witness-count ${toString (3 * composition.numPools + 1)} \
--tx-out-count ${toString (composition.n_pools + 1)} \
--witness-count ${toString (3 * composition.n_pools + 1)} \
--byron-witness-count 0 \
--tx-body-file "${stateDir}/shelley/transfer-register-delegate-tx.txbody" |
cut -d' ' -f1)
Expand All @@ -192,29 +191,33 @@ rec {
TXOUT_AMOUNT=$(jq --arg addr "$TXIN_ADDR_HEX" \
--arg fee "$FEE" \
'.initialFunds[$addr] - ($fee|tonumber) - (.protocolParams.poolDeposit + (2 * .protocolParams.keyDeposit) + ${toString monetary.delegatePoolAmount}) * ${toString composition.numPools}' < ${stateDir}/shelley/genesis.json)
'(if .initialFunds | has($addr)
then .initialFunds[$addr]
else error("initialFunds has no address corresponding to the genesis key: \($addr)")
end) as $funds
| $funds - ($fee|tonumber) - (.protocolParams.poolDeposit + (2 * .protocolParams.keyDeposit) + ${toString genesis.delegator_coin}) * ${toString composition.n_pools}' < ${stateDir}/shelley/genesis.json)
cardano-cli transaction build-raw \
--ttl 1000 \
--fee "$FEE" \
--tx-in $(cardano-cli genesis initial-txin \
--testnet-magic ${toString genesis.networkMagic} \
--testnet-magic ${toString genesis.network_magic} \
--verification-key-file ${stateDir}/shelley/genesis-utxo.vkey) \
--tx-out "$TXIN_ADDR+$TXOUT_AMOUNT" \
${lib.concatMapStringsSep "" (i: ''
--tx-out $(cat "${stateDir}/nodes/node-pool${toString i}/owner.addr")+${toString monetary.delegatePoolAmount} \
--tx-out $(cat "${stateDir}/nodes/node-pool${toString i}/owner.addr")+${toString genesis.delegator_coin} \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/stake.reg.cert" \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/stake-reward.reg.cert" \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/register.cert" \
--certificate-file "${stateDir}/nodes/node-pool${toString i}/owner-stake.deleg.cert" \'') (lib.genList (i: i + 1) composition.numPools)}
--certificate-file "${stateDir}/nodes/node-pool${toString i}/owner-stake.deleg.cert" \'') (lib.genList (i: i + 1) composition.n_pools)}
--out-file "${stateDir}/shelley/transfer-register-delegate-tx.txbody"
cardano-cli transaction sign \
--signing-key-file ${stateDir}/shelley/genesis-utxo.skey \
${lib.concatMapStringsSep "" (i: ''
--signing-key-file "${stateDir}/nodes/node-pool${toString i}/owner-stake.skey" \
--signing-key-file "${stateDir}/nodes/node-pool${toString i}/reward.skey" \
--signing-key-file "${stateDir}/nodes/node-pool${toString i}/cold.skey" \'') (lib.genList (i: i + 1) composition.numPools)}
--testnet-magic ${toString genesis.networkMagic} \
--signing-key-file "${stateDir}/nodes/node-pool${toString i}/cold.skey" \'') (lib.genList (i: i + 1) composition.n_pools)}
--testnet-magic ${toString genesis.network_magic} \
--tx-body-file "${stateDir}/shelley/transfer-register-delegate-tx.txbody" \
--out-file "${stateDir}/shelley/transfer-register-delegate-tx.tx"
Expand Down
10 changes: 0 additions & 10 deletions nix/supervisord-cluster/initial-funds.nix

This file was deleted.

68 changes: 68 additions & 0 deletions nix/supervisord-cluster/profiles.jq
@@ -0,0 +1,68 @@
## Profiles are named bundles of parameters, classified into sections:
##
## - genesis
## - generator
## - node
## - tolerances (ranges of acceptable properties, given above parameters)
##
## When combined with cluster COMPOsition (an extract from topology) and
## service parameters (non-crucial things like state directory, port ranges, etc),
## profiles ought to completely specify cluster parameters,
## allowing genesis and all necessary configuration files to be generated.
##
## Profiles themselves are layered as follows:
##
## - era-dependent defaults for the aforementioned sections:
## - profiles/defaults.jq
##
## - overlayed with generated profile variants + aux (ad-hoc) profiles:
## - profiles/variants.jq and profiles/aux.jq
##
## - each then further overlayed with derived parameters, computed from the above:
## - profiles/derived.jq
##
## Profiles variants are generated as a cartesian product of variations
## of the three axes: genesis, generator and node.
## These generated profiles are assigned computed names, as per the
## profile_name() function in 'profiles/derived.jq'.
##
## Composition must have the following structure:
## { n_hosts: INT
## , n_bft_hosts: INT
## , n_singular_hosts: INT
## , n_dense_hosts: INT
## }
## ..where n_hosts must be equal to a sum of the rest.
##
## Testable by:
##
## jq -n 'include "profiles" { search: "nix/supervisord-cluster" }; profiles("shelley"; { n_bft_hosts: 1, n_dense_hosts: 1, n_singular_hosts: 1, n_hosts: 3 }; null)'
##

include "topology" { search: "profiles" };
include "defaults" { search: "profiles" };
include "aux" { search: "profiles" };
include "variants" { search: "profiles" };
include "derived" { search: "profiles" };

def profiles($era; $mcompo; $topo):
($mcompo // topology_composition($topo // {}) // {}) as $compo

## Profiles are variants + custom (or aux) profiles:
| all_profile_variants + aux_profiles

| map (## Each profile extends defaults:
era_defaults($era) * .

## Profiles can define their own cluster composition.
| . * { composition: (.composition // $compo) }

## Compute the derived params.
| add_derived_params

## Finally, assembly into a dictionary..
| { "\(.name)":
## ..and cleanup:
. | delpaths ([["generator", "epochs"]])}
)
| add;
45 changes: 12 additions & 33 deletions nix/supervisord-cluster/profiles.nix
@@ -1,34 +1,13 @@
{ ...
{ runCommand
, jq
, ...
}:

rec {
default = {
composition = {
numBft = 1;
numPools = 2;
};
monetary = {
delegatePoolAmount = 1000000000000;
initialFunds = import ./initial-funds.nix;
};
genesis = {
protocolParams = {
poolDeposit = 500000000;
keyDeposit = 400000;
nOpt = 10;
rho = 0.0022;
tau = 0.05;
a0 = 0.3;
minFeeA = 44;
minFeeB = 155381;
decentralisationParam = 0.8;
};
slotLength = 0.2;
activeSlotsCoeff = 0.1;
securityParam = 10;
epochLength = 1000;
maxLovelaceSupply = 45000000000000000;
networkMagic = 42;
};
};
}
let
profilesJSON = runCommand "profiles" { buildInputs = [ jq ]; } ''
jq --null-input '
include "profiles" { search: "${./.}" };
profiles("shelley"; null; null)
' > $out
'';
in
__fromJSON (__readFile profilesJSON)

0 comments on commit c85a983

Please sign in to comment.