From 20fb62290cb64abea3b9c76d6eb50e84293edf72 Mon Sep 17 00:00:00 2001 From: Martin Kourim Date: Mon, 17 Aug 2026 18:59:05 +0200 Subject: [PATCH 1/2] feat(scripts): register Dijkstra-era pools with BLS keys when supported Generate BLS keypairs for pools and embed them in the pool registration certificate when both cardano-cli and cardano-node support Leios BLS (dijkstra node key-gen-BLS, --shelley-bls-key), gated on PROTOCOL_VERSION>=12. Fast flavor embeds the BLS key directly since its one-shot pool registration can land post-Dijkstra. Slow flavor registers pools early (pre-Dijkstra, shelley-era cert has no BLS field) and re-registers with a dijkstra-era cert once hf_to_dijkstra confirms the era. --- .../scripts/common/common-start-fast | 16 ++++- .../scripts/common/common-start-slow | 26 +++++++ .../scripts/common/common.sh | 69 +++++++++++++++++++ .../leios_fast/template-cardano-node-pool | 4 ++ .../local_fast/template-cardano-node-pool | 4 ++ .../local_slow/template-cardano-node-pool | 4 ++ .../mainnet_fast/template-cardano-node-pool | 4 ++ 7 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/cardonnay_scripts/scripts/common/common-start-fast b/src/cardonnay_scripts/scripts/common/common-start-fast index 2ab9022..d1b145a 100644 --- a/src/cardonnay_scripts/scripts/common/common-start-fast +++ b/src/cardonnay_scripts/scripts/common/common-start-fast @@ -388,6 +388,12 @@ _create_pool_node_keys() { mv "${STATE_CLUSTER}/create_staked/pools/vrf${pool_ix}.skey" "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/vrf.skey" mv "${STATE_CLUSTER}/create_staked/pools/vrf${pool_ix}.vkey" "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/vrf.vkey" + if [ "$PROTOCOL_VERSION" -ge 12 ] && has_bls_support; then + cardano_cli_log dijkstra node key-gen-BLS \ + --verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.vkey" \ + --signing-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.skey" + fi + echo "Generating Pool $pool_ix Secrets" cardano_cli_log conway address key-gen \ @@ -437,9 +443,17 @@ _create_pool_registration() { echo "$pool_port" > "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/port" echo "$POOL_PLEDGE" > "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/pledge" - cardano_cli_log conway stake-pool registration-certificate \ + local reg_command_era="conway" + local -a bls_args=() + if [ "$PROTOCOL_VERSION" -ge 12 ] && [ -e "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.skey" ]; then + reg_command_era="dijkstra" + bls_args=( "--bls-signing-key-file" "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.skey" ) + fi + + cardano_cli_log "$reg_command_era" stake-pool registration-certificate \ --cold-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/cold.vkey" \ --vrf-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/vrf.vkey" \ + "${bls_args[@]}" \ --pool-pledge "$POOL_PLEDGE" \ --pool-margin 0.35 \ --pool-cost "$POOL_COST" \ diff --git a/src/cardonnay_scripts/scripts/common/common-start-slow b/src/cardonnay_scripts/scripts/common/common-start-slow index 3774052..4011a03 100644 --- a/src/cardonnay_scripts/scripts/common/common-start-slow +++ b/src/cardonnay_scripts/scripts/common/common-start-slow @@ -371,6 +371,12 @@ _create_pool_node_keys() { --verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/vrf.vkey" \ --signing-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/vrf.skey" + if [ "$PROTOCOL_VERSION" -ge 12 ] && has_bls_support; then + cardano_cli_log dijkstra node key-gen-BLS \ + --verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.vkey" \ + --signing-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.skey" + fi + cardano_cli_log compatible shelley stake-address stake-delegation-certificate \ --stake-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/owner-stake.vkey" \ --cold-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/cold.vkey" \ @@ -427,6 +433,24 @@ _create_pool_registration() { --pool-relay-ipv4 "127.0.0.1" \ --testnet-magic "$NETWORK_MAGIC" \ --out-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/register.cert" + + if [ -e "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.skey" ]; then + cardano_cli_log dijkstra stake-pool registration-certificate \ + --cold-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/cold.vkey" \ + --vrf-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/vrf.vkey" \ + --bls-signing-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/bls.skey" \ + --pool-pledge "$POOL_PLEDGE" \ + --pool-margin 0.35 \ + --pool-cost "$POOL_COST" \ + --pool-reward-account-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/reward.vkey" \ + --pool-owner-stake-verification-key-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/owner-stake.vkey" \ + --metadata-url "$metadata_url" \ + --metadata-hash "$metadata_hash" \ + --pool-relay-port "$pool_port" \ + --pool-relay-ipv4 "127.0.0.1" \ + --testnet-magic "$NETWORK_MAGIC" \ + --out-file "${STATE_CLUSTER}/nodes/node-pool${pool_ix}/register.dijkstra.cert" + fi } create_pools_files() { @@ -1023,6 +1047,8 @@ hf_to_dijkstra() { local cur_era cur_era="$(get_era)" [ "$cur_era" = "Dijkstra" ] || { echo "Unexpected era '$cur_era' after HF to Dijkstra PV12, line $LINENO in ${BASH_SOURCE[0]}" >&2; exit 1; } + + reregister_pools_with_bls } main() { diff --git a/src/cardonnay_scripts/scripts/common/common.sh b/src/cardonnay_scripts/scripts/common/common.sh index 24a499a..ebece0a 100644 --- a/src/cardonnay_scripts/scripts/common/common.sh +++ b/src/cardonnay_scripts/scripts/common/common.sh @@ -51,6 +51,12 @@ get_block_interval_sec() { 'if $co > 0 then ($sl / $co | ceil) else ($sl | ceil) end' } +has_bls_support() { + cardano-cli dijkstra node key-gen-BLS --help > /dev/null 2>&1 || return 1 + cardano-node run --help 2>&1 | grep -q -- '--shelley-bls-key' || return 1 + return 0 +} + cardano_cli_log() { : "${STATE_CLUSTER:?STATE_CLUSTER is required}" @@ -494,6 +500,69 @@ submit_votes() { fi } +reregister_pools_with_bls() { + : "${STATE_CLUSTER:?STATE_CLUSTER is required}" + : "${FAUCET_ADDR:?FAUCET_ADDR is required}" + : "${FAUCET_SKEY:?FAUCET_SKEY is required}" + : "${FEE:?FEE is required}" + : "${NETWORK_MAGIC:?NETWORK_MAGIC is required}" + : "${SUBMIT_DELAY:?SUBMIT_DELAY is required}" + + local pool_dir cert_file + local -a cert_args=() + local -a pool_signing=() + + for pool_dir in "${STATE_CLUSTER}"/nodes/node-pool*; do + [ -e "$pool_dir" ] || continue + cert_file="${pool_dir}/register.dijkstra.cert" + [ -e "$cert_file" ] || continue + cert_args+=( "--certificate-file" "$cert_file" ) + pool_signing+=( \ + "--signing-key-file" "${pool_dir}/owner-stake.skey" \ + "--signing-key-file" "${pool_dir}/cold.skey" \ + ) + done + + if [ "${#cert_args[@]}" -eq 0 ]; then + echo "No Dijkstra pool registration certs found, skipping BLS re-registration" + return + fi + + echo "Re-registering pools with BLS keys" + + local -a txins=() + local txin_amount=0 + + get_txins "${FAUCET_ADDR}" "${FEE}" txins txin_amount + + local txout_amount="$((txin_amount - FEE))" + local reg_base="${STATE_CLUSTER}/pool-bls-reregistration" + + cardano_cli_log dijkstra transaction build-raw \ + --fee "${FEE}" \ + "${txins[@]}" \ + "${cert_args[@]}" \ + --tx-out "${FAUCET_ADDR}+${txout_amount}" \ + --out-file "${reg_base}-tx.txbody" + + cardano_cli_log dijkstra transaction sign \ + --signing-key-file "${FAUCET_SKEY}" \ + "${pool_signing[@]}" \ + --testnet-magic "${NETWORK_MAGIC}" \ + --tx-body-file "${reg_base}-tx.txbody" \ + --out-file "${reg_base}-tx.tx" + + cardano_cli_log dijkstra transaction submit \ + --tx-file "${reg_base}-tx.tx" \ + --testnet-magic "${NETWORK_MAGIC}" + + sleep "${SUBMIT_DELAY}" + if ! check_spend_success "${txins[@]}"; then + echo "Failed to spend Tx inputs for pool BLS re-registration, line $LINENO in ${BASH_SOURCE[0]}" >&2 + exit 1 + fi +} + configure_supervisor() { : "${STATE_CLUSTER:?STATE_CLUSTER is required}" : "${STATE_CLUSTER_NAME:?STATE_CLUSTER_NAME is required}" diff --git a/src/cardonnay_scripts/scripts/leios_fast/template-cardano-node-pool b/src/cardonnay_scripts/scripts/leios_fast/template-cardano-node-pool index 510d152..2d7a9d9 100644 --- a/src/cardonnay_scripts/scripts/leios_fast/template-cardano-node-pool +++ b/src/cardonnay_scripts/scripts/leios_fast/template-cardano-node-pool @@ -19,6 +19,10 @@ args=( \ "$@" \ ) +if [ -f ../nodes/node-pool%%POOL_NUM%%/bls.skey ]; then + args+=( --shelley-bls-key ../nodes/node-pool%%POOL_NUM%%/bls.skey ) +fi + echo "Starting cardano-node run with PID $$ in db-pool%%POOL_NUM%% directory:" echo "cardano-node ${args[*]}" exec cardano-node "${args[@]}" diff --git a/src/cardonnay_scripts/scripts/local_fast/template-cardano-node-pool b/src/cardonnay_scripts/scripts/local_fast/template-cardano-node-pool index 510d152..2d7a9d9 100644 --- a/src/cardonnay_scripts/scripts/local_fast/template-cardano-node-pool +++ b/src/cardonnay_scripts/scripts/local_fast/template-cardano-node-pool @@ -19,6 +19,10 @@ args=( \ "$@" \ ) +if [ -f ../nodes/node-pool%%POOL_NUM%%/bls.skey ]; then + args+=( --shelley-bls-key ../nodes/node-pool%%POOL_NUM%%/bls.skey ) +fi + echo "Starting cardano-node run with PID $$ in db-pool%%POOL_NUM%% directory:" echo "cardano-node ${args[*]}" exec cardano-node "${args[@]}" diff --git a/src/cardonnay_scripts/scripts/local_slow/template-cardano-node-pool b/src/cardonnay_scripts/scripts/local_slow/template-cardano-node-pool index 510d152..2d7a9d9 100644 --- a/src/cardonnay_scripts/scripts/local_slow/template-cardano-node-pool +++ b/src/cardonnay_scripts/scripts/local_slow/template-cardano-node-pool @@ -19,6 +19,10 @@ args=( \ "$@" \ ) +if [ -f ../nodes/node-pool%%POOL_NUM%%/bls.skey ]; then + args+=( --shelley-bls-key ../nodes/node-pool%%POOL_NUM%%/bls.skey ) +fi + echo "Starting cardano-node run with PID $$ in db-pool%%POOL_NUM%% directory:" echo "cardano-node ${args[*]}" exec cardano-node "${args[@]}" diff --git a/src/cardonnay_scripts/scripts/mainnet_fast/template-cardano-node-pool b/src/cardonnay_scripts/scripts/mainnet_fast/template-cardano-node-pool index 510d152..2d7a9d9 100644 --- a/src/cardonnay_scripts/scripts/mainnet_fast/template-cardano-node-pool +++ b/src/cardonnay_scripts/scripts/mainnet_fast/template-cardano-node-pool @@ -19,6 +19,10 @@ args=( \ "$@" \ ) +if [ -f ../nodes/node-pool%%POOL_NUM%%/bls.skey ]; then + args+=( --shelley-bls-key ../nodes/node-pool%%POOL_NUM%%/bls.skey ) +fi + echo "Starting cardano-node run with PID $$ in db-pool%%POOL_NUM%% directory:" echo "cardano-node ${args[*]}" exec cardano-node "${args[@]}" From 759d81423b342cc1b035a43755a0dbef1a5db123 Mon Sep 17 00:00:00 2001 From: Martin Kourim Date: Mon, 17 Aug 2026 19:13:45 +0200 Subject: [PATCH 2/2] fix(scripts): start fast-flavor testnet directly in target era Remove the TMP_PROTOCOL_VERSION clamp and hf_to_dijkstra() workaround. Genesis now sets protocolParams.protocolVersion.major to the real PROTOCOL_VERSION and TestDijkstraHardForkAtEpoch=0 handles the PV12 case, so the cluster runs in the target era from slot 0 instead of starting at PV11 and hard-forking to Dijkstra after the fact. --- .../scripts/common/common-start-fast | 49 +------------------ 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/src/cardonnay_scripts/scripts/common/common-start-fast b/src/cardonnay_scripts/scripts/common/common-start-fast index d1b145a..990816b 100644 --- a/src/cardonnay_scripts/scripts/common/common-start-fast +++ b/src/cardonnay_scripts/scripts/common/common-start-fast @@ -22,13 +22,6 @@ readonly NODE_PORT_BASE=%%NODE_PORT_BASE%% readonly PORTS_PER_NODE=%%PORTS_PER_NODE%% readonly WEBSERVER_PORT=%%WEBSERVER_PORT%% -# TODO: cannot hf directly to Dijkstra yet -TMP_PROTOCOL_VERSION="$PROTOCOL_VERSION" -if [ "$PROTOCOL_VERSION" -ge 12 ]; then - TMP_PROTOCOL_VERSION=11 -fi -readonly TMP_PROTOCOL_VERSION - initialize_globals() { if [ -z "${CARDANO_NODE_SOCKET_PATH:-}" ]; then echo "CARDANO_NODE_SOCKET_PATH is not set" >&2 @@ -259,7 +252,7 @@ create_genesis() { jq \ --argjson max_supply "$MAX_SUPPLY" \ - --argjson prot_ver "$TMP_PROTOCOL_VERSION" ' + --argjson prot_ver "$PROTOCOL_VERSION" ' .protocolParams.protocolVersion.major = $prot_ver | .maxLovelaceSupply = $max_supply ' "${STATE_CLUSTER}/create_staked/genesis.json" > "${STATE_CLUSTER}/shelley/genesis.json" @@ -345,7 +338,7 @@ edit_node_configs() { fi jq \ - --argjson prot_ver "$TMP_PROTOCOL_VERSION" ' + --argjson prot_ver "$PROTOCOL_VERSION" ' if $prot_ver >= 12 then .TestDijkstraHardForkAtEpoch = 0 else @@ -606,43 +599,6 @@ register_entities() { fi } -hf_to_dijkstra() { - if [ "$PROTOCOL_VERSION" -lt 12 ]; then - echo "Skipping HF to Dijkstra PV12 as PROTOCOL_VERSION is set to $PROTOCOL_VERSION" - return - fi - - echo "TODO: remove \`hf_to_dijkstra\` function once \`TestDijkstraHardForkAtEpoch\` fully works" >&2 - - local cur_epoch="${1:?}" - - echo "Submitting hard fork proposal to update to Dijkstra PV12" - - local pv12_hf_base="${STATE_CLUSTER}/governance_data/hardfork_pv12_action" - local pv12_hf_action="${pv12_hf_base}_action" - - create_and_submit_hf_action "$pv12_hf_action" "latest" 12 - - PV12_HF_ACTION_TXID="$(cardano_cli_log conway transaction txid \ - --output-text --tx-body-file "${pv12_hf_action}-tx.txbody")" - readonly PV12_HF_ACTION_TXID - - vote_on_action "$PV12_HF_ACTION_TXID" "$pv12_hf_action" "yes" "yes" - submit_votes "${pv12_hf_base}_votes" "$pv12_hf_action" - - echo "Waiting for Dijkstra PV12 to start" - wait_for_epoch "$((cur_epoch + 2))" - - save_protocol_params "$PPARAMS_FILE" - local cur_protver - cur_protver="$(jq '.protocolVersion.major' < "$PPARAMS_FILE")" - [ "$cur_protver" = 12 ] || { echo "Unexpected protocol version '$cur_protver' on line $LINENO in ${BASH_SOURCE[0]}" >&2; exit 1; } - - local cur_era - cur_era="$(get_era)" - [ "$cur_era" = "Dijkstra" ] || { echo "Unexpected era '$cur_era' after HF to Dijkstra PV12, line $LINENO in ${BASH_SOURCE[0]}" >&2; exit 1; } -} - main() { initialize_globals setup_state_cluster "${STATE_CLUSTER}/create_staked" @@ -659,7 +615,6 @@ main() { start_cluster_nodes start_optional_services register_entities - hf_to_dijkstra "$(get_epoch)" use_genesis_mode setup_tx_generator "$TX_GENERATOR_MIN_FUNDS" setup_tx_centrifuge