Skip to content

Commit d77a652

Browse files
authored
refactor: use publishers-per-pod in deployments (#21039)
This PR changes `VALIDATOR_PUBLISHERS_PER_VALIDATOR_KEY` to `VALIDATOR_PUBLISHERS_PER_REPLICA` to reduce the number of overall publishers used for a test deployment Fix A-609
1 parent df0235c commit d77a652

31 files changed

Lines changed: 89 additions & 94 deletions

spartan/CLAUDE.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ The main entry point is `terraform/deploy-aztec-infra/`:
5757
**aztec-validator** (extends aztec-node):
5858
- Wrapper chart with `aztec-node` as dependency (aliased as `validator`)
5959
- Adds validator-specific ConfigMap (`env.configmap.yaml`)
60-
- Configures mnemonic, validators-per-node, publisher keys
60+
- Configures mnemonic, validators-per-node, publishers-per-replica
6161

6262
**aztec-prover-stack**:
6363
- Multi-component: prover node, broker, and agent replicas
@@ -263,26 +263,31 @@ locals {
263263

264264
**Key derivation via Terraform + `setup-attester-keystore.sh`:**
265265

266-
Each release receives a different `PUBLISHER_KEY_INDEX_START` from Terraform:
266+
Publishers are allocated **per replica (pod)**, not per attester key. Each release receives a different `PUBLISHER_KEY_INDEX_START` from Terraform:
267267

268268
```hcl
269269
# In main.tf custom_settings per release:
270270
"validator.node.env.PUBLISHER_KEY_INDEX_START" = var.VALIDATOR_PUBLISHER_MNEMONIC_START_INDEX +
271-
(idx * (var.VALIDATORS_PER_NODE * var.VALIDATOR_PUBLISHERS_PER_VALIDATOR_KEY * var.VALIDATOR_REPLICAS))
271+
(idx * (var.VALIDATOR_PUBLISHERS_PER_REPLICA * var.VALIDATOR_REPLICAS))
272272
```
273273

274-
Example with 4 replicas, 12 validators/node, 2 publishers/key, base index 5000:
274+
Example with 4 replicas, 4 publishers/replica, base index 5000:
275275
- Primary (idx=0): `PUBLISHER_KEY_INDEX_START = 5000`
276-
- HA-1 (idx=1): `PUBLISHER_KEY_INDEX_START = 5000 + (1 * 12 * 2 * 4) = 5096`
276+
- HA-1 (idx=1): `PUBLISHER_KEY_INDEX_START = 5000 + (1 * 4 * 4) = 5016`
277277

278278
At runtime, `setup-attester-keystore.sh` calculates publisher indices:
279279

280280
```bash
281281
# POD_INDEX extracted from pod name (validator-0 → 0, validator-1 → 1, etc.)
282-
PUBLISHER_KEY_INDEX=$((POD_INDEX * VALIDATORS_PER_NODE * PUBLISHERS_PER_VALIDATOR_KEY + PUBLISHER_KEY_INDEX_START))
282+
PUBLISHER_KEY_INDEX=$((POD_INDEX * VALIDATOR_PUBLISHERS_PER_REPLICA + PUBLISHER_KEY_INDEX_START))
283283
```
284284

285-
This ensures each release uses non-overlapping publisher key ranges.
285+
The keystore uses **schema v2** with a top-level `publisher` array shared by all validators on the pod:
286+
```json
287+
{"schemaVersion": 2, "publisher": ["0x1", "0x2", "0x3", "0x4"], "validators": [{"attester": "..."}]}
288+
```
289+
290+
This ensures each release uses non-overlapping publisher key ranges while decoupling publisher count from attester count.
286291

287292
**HA coordination:**
288293
- Both releases connect to shared PostgreSQL via `VALIDATOR_HA_DATABASE_URL`

spartan/aztec-keystore/templates/batchjob.yaml

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ spec:
3333
NODES="{{ .Values.attesters.nodeCount }}"
3434
HA_COUNT="{{ .Values.attesters.haCount }}"
3535
ATTESTERS_PER_NODE="{{ .Values.attesters.attestersPerNode }}"
36-
PUBLISHERS_PER_VALIDATOR_KEY="{{ .Values.publishers.perValidatorKey }}"
36+
VALIDATOR_PUBLISHERS_PER_REPLICA="{{ .Values.publishers.perReplica }}"
3737
ATTESTER_KEY_INDEX_START="{{ .Values.attesters.mnemonicStartIndex }}"
3838
PUBLISHER_KEY_INDEX_START="{{ .Values.publishers.mnemonicStartIndex }}"
3939
PROVER_COUNT=1
@@ -73,29 +73,27 @@ spec:
7373
printf '%s' "$addr" >> "$ADDR_FILE"
7474
done
7575
76-
# Publishers: start index per node, then pack by validator j and publisher p
77-
pub_base=$((PUBLISHER_KEY_INDEX_START + i * ATTESTERS_PER_NODE * PUBLISHERS_PER_VALIDATOR_KEY))
78-
for ((j=0;j<ATTESTERS_PER_NODE;j++)); do
79-
for ((p=0;p<PUBLISHERS_PER_VALIDATOR_KEY;p++)); do
80-
pub_idx=$((pub_base + j * PUBLISHERS_PER_VALIDATOR_KEY + p))
81-
ppk="$(cast wallet private-key --mnemonic "$MNEMONIC" --mnemonic-index "$pub_idx")"
82-
paddr="$(cast wallet address --private-key $ppk)"
83-
84-
# write keystore file-separated entries
85-
[[ $j -gt 0 || $p -gt 0 ]] && echo '---' >> "$PUB_KS_FILE"
86-
printf 'type: file-raw\nkeyType: SECP256K1\nprivateKey: %s\n' "$ppk" >> "$PUB_KS_FILE"
87-
88-
# write addresses CSV per node
89-
if [[ $j -gt 0 || $p -gt 0 ]]; then printf ',' >> "$PUB_ADDR_FILE"; fi
90-
printf '%s' "$paddr" >> "$PUB_ADDR_FILE"
91-
done
76+
# Publishers: flat pool per replica (shared by all attesters on the node)
77+
pub_base=$((PUBLISHER_KEY_INDEX_START + i * VALIDATOR_PUBLISHERS_PER_REPLICA))
78+
for ((p=0;p<VALIDATOR_PUBLISHERS_PER_REPLICA;p++)); do
79+
pub_idx=$((pub_base + p))
80+
ppk="$(cast wallet private-key --mnemonic "$MNEMONIC" --mnemonic-index "$pub_idx")"
81+
paddr="$(cast wallet address --private-key $ppk)"
82+
83+
# write keystore file-separated entries
84+
[[ $p -gt 0 ]] && echo '---' >> "$PUB_KS_FILE"
85+
printf 'type: file-raw\nkeyType: SECP256K1\nprivateKey: %s\n' "$ppk" >> "$PUB_KS_FILE"
86+
87+
# write addresses CSV per node
88+
[[ $p -gt 0 ]] && printf ',' >> "$PUB_ADDR_FILE"
89+
printf '%s' "$paddr" >> "$PUB_ADDR_FILE"
9290
done
9391
9492
echo "Generated config for attesters on node $i"
9593
done
9694
9795
# Generate HA publisher keys (separate key ranges for each HA release)
98-
PUBLISHERS_PER_STS=$((NODES * ATTESTERS_PER_NODE * PUBLISHERS_PER_VALIDATOR_KEY))
96+
PUBLISHERS_PER_STS=$((NODES * VALIDATOR_PUBLISHERS_PER_REPLICA))
9997
10098
for ((ha=0;ha<HA_COUNT;ha++)); do
10199
HA_PUB_KS_FILE=/shared/publishers/keystores/ha_${ha}.yaml

spartan/aztec-keystore/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ attesters:
2727
name: "" # if empty name will be generated based on Release.Name
2828

2929
publishers:
30-
perValidatorKey: 1
30+
perReplica: 4
3131
mnemonicStartIndex: 5000
3232
keyStoreSecret:
3333
create: true

spartan/aztec-node/scripts/setup-attester-keystore.sh

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -eu
33

44
VALIDATORS_PER_NODE=${VALIDATORS_PER_NODE:-1}
5-
PUBLISHERS_PER_VALIDATOR_KEY=${PUBLISHERS_PER_VALIDATOR_KEY:-1}
5+
VALIDATOR_PUBLISHERS_PER_REPLICA=${VALIDATOR_PUBLISHERS_PER_REPLICA:-4}
66

77
# We get the index in the config map from the pod name, which will have the service index within it
88
# For multiple validators per node, we need to multiply the pod index by VALIDATORS_PER_NODE
@@ -11,8 +11,8 @@ KEY_INDEX=$((POD_INDEX * VALIDATORS_PER_NODE))
1111
# Add the index to the start index to get the private key index
1212
PRIVATE_KEY_INDEX=$((KEY_INDEX_START + KEY_INDEX))
1313

14-
# Calculate publisher key starting index for this pod
15-
PUBLISHER_KEY_INDEX=$((POD_INDEX * VALIDATORS_PER_NODE * PUBLISHERS_PER_VALIDATOR_KEY + PUBLISHER_KEY_INDEX_START))
14+
# Calculate publisher key starting index for this pod (flat per-replica pool)
15+
PUBLISHER_KEY_INDEX=$((POD_INDEX * VALIDATOR_PUBLISHERS_PER_REPLICA + PUBLISHER_KEY_INDEX_START))
1616

1717
WEB3_SIGNER_URL=${WEB3_SIGNER_URL:-""}
1818

@@ -25,7 +25,7 @@ echo "PUBLISHER_KEY_INDEX: $PUBLISHER_KEY_INDEX"
2525
echo "WEB3_SIGNER_URL: ${WEB3_SIGNER_URL}"
2626
# Specific for validators that can hold multiple keys on one node
2727
echo "VALIDATORS_PER_NODE: ${VALIDATORS_PER_NODE}"
28-
echo "PUBLISHERS_PER_VALIDATOR_KEY: ${PUBLISHERS_PER_VALIDATOR_KEY}"
28+
echo "VALIDATOR_PUBLISHERS_PER_REPLICA: ${VALIDATOR_PUBLISHERS_PER_REPLICA}"
2929
echo "MNEMONIC: $(echo $MNEMONIC | cut -d' ' -f1-2)..."
3030

3131
private_keys=()
@@ -43,13 +43,11 @@ for ((i = 0; i < VALIDATORS_PER_NODE; i++)); do
4343
addresses+=("$address")
4444
done
4545

46-
# Generate publisher keys
46+
# Generate publisher keys (shared pool for this replica)
4747
publisher_private_keys=()
4848
publisher_addresses=()
4949

50-
total_publishers=$((VALIDATORS_PER_NODE * PUBLISHERS_PER_VALIDATOR_KEY))
51-
52-
for ((i = 0; i < total_publishers; i++)); do
50+
for ((i = 0; i < VALIDATOR_PUBLISHERS_PER_REPLICA; i++)); do
5351
current_pub_index=$((PUBLISHER_KEY_INDEX + i))
5452
pub_private_key=$(cast wallet private-key "$MNEMONIC" --mnemonic-index $current_pub_index)
5553
pub_address=$(cast wallet address --private-key $pub_private_key)
@@ -59,24 +57,31 @@ for ((i = 0; i < total_publishers; i++)); do
5957
done
6058

6159
remoteSigner=""
62-
attesters=()
6360
publishers=()
6461

6562
if [ -n "$WEB3_SIGNER_URL" ]; then
6663
remoteSigner=$(jq -n '{remoteSignerUrl: $url}' --arg url "$WEB3_SIGNER_URL")
67-
attesters=(${addresses[*]})
6864
publishers=(${publisher_addresses[*]})
6965
else
7066
remoteSigner="null"
71-
attesters=(${private_keys[*]})
7267
# Without web3signer, use private keys for publishers
7368
publishers=(${publisher_private_keys[*]})
7469
fi
7570

7671
export KEY_STORE_DIRECTORY="/shared/config/keys"
7772
mkdir -p "$KEY_STORE_DIRECTORY"
7873

79-
# Build validators array with multiple entries
74+
# Build top-level publisher array (shared by all validators on this replica)
75+
publishers_json="["
76+
for ((p = 0; p < VALIDATOR_PUBLISHERS_PER_REPLICA; p++)); do
77+
if [ $p -gt 0 ]; then
78+
publishers_json+=","
79+
fi
80+
publishers_json+="\"${publishers[$p]}\""
81+
done
82+
publishers_json+="]"
83+
84+
# Build validators array with multiple entries (no per-validator publishers)
8085
validators_json="["
8186
for ((v = 0; v < VALIDATORS_PER_NODE; v++)); do
8287
if [ $v -gt 0 ]; then
@@ -90,34 +95,23 @@ for ((v = 0; v < VALIDATORS_PER_NODE; v++)); do
9095
attester="${private_keys[$v]}"
9196
fi
9297

93-
# Get the publisher keys for this validator
94-
validator_publishers="["
95-
for ((p = 0; p < PUBLISHERS_PER_VALIDATOR_KEY; p++)); do
96-
if [ $p -gt 0 ]; then
97-
validator_publishers+=","
98-
fi
99-
pub_index=$((v * PUBLISHERS_PER_VALIDATOR_KEY + p))
100-
validator_publishers+="\"${publishers[$pub_index]}\""
101-
done
102-
validator_publishers+="]"
103-
104-
10598
validators_json+="{
10699
\"attester\": \"$attester\",
107100
\"coinbase\": \"$attester\",
108-
\"publisher\": $validator_publishers,
109101
\"feeRecipient\": \"0x0000000000000000000000000000000000000000000000000000000000000000\"
110102
}"
111103
done
112104
validators_json+="]"
113105

114-
# Create final JSON structure
106+
# Create final JSON structure (schema v2 with top-level publisher array)
115107
jq -n --argjson remoteSigner "$remoteSigner" \
116108
--argjson validators "$validators_json" \
109+
--argjson publisher "$publishers_json" \
117110
'{
118-
schemaVersion: 1,
111+
schemaVersion: 2,
119112
remoteSigner: $remoteSigner,
113+
publisher: $publisher,
120114
validators: $validators
121115
}' > "$KEY_STORE_DIRECTORY/attesters.json"
122116

123-
echo "Generated configuration for $VALIDATORS_PER_NODE validators with $PUBLISHERS_PER_VALIDATOR_KEY publishers each"
117+
echo "Generated configuration for $VALIDATORS_PER_NODE validators with $VALIDATOR_PUBLISHERS_PER_REPLICA shared publishers per replica"

spartan/aztec-validator/templates/env.configmap.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ metadata:
66
{{- include "chart.labels" . | nindent 4 }}
77
data:
88
VALIDATORS_PER_NODE: {{ .Values.validator.validatorsPerNode | quote }}
9-
PUBLISHERS_PER_VALIDATOR_KEY: {{ .Values.validator.publishersPerValidatorKey | default 1 | quote }}
9+
VALIDATOR_PUBLISHERS_PER_REPLICA: {{ .Values.validator.publishersPerReplica | default 4 | quote }}
1010
WEB3_SIGNER_URL: {{ .Values.validator.web3signerUrl | default "" | quote }}

spartan/aztec-validator/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ validator:
1414
mnemonic: "test test test test test test test test test test test junk"
1515
mnemonicStartIndex: 2000
1616
validatorsPerNode: 1
17-
publishersPerValidatorKey: 2
17+
publishersPerReplica: 4
1818
publisherMnemonicStartIndex: 7000
1919

2020
persistence:

spartan/environments/alpha-net.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ OTEL_COLLECTOR_ENDPOINT=REPLACE_WITH_GCP_SECRET
3939

4040
VALIDATOR_REPLICAS=12
4141
VALIDATORS_PER_NODE=4
42-
PUBLISHERS_PER_VALIDATOR_KEY=2
42+
VALIDATOR_PUBLISHERS_PER_REPLICA=4
4343
VALIDATOR_PUBLISHER_MNEMONIC_START_INDEX=5000
4444
VALIDATOR_RESOURCE_PROFILE="2-core-dedicated"
4545

spartan/environments/devnet.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ AZTEC_TARGET_COMMITTEE_SIZE=1
5252
VALIDATOR_MNEMONIC_START_INDEX=$((1 + MNEMONIC_INDEX_OFFSET))
5353
VALIDATOR_INDICES=$(seq -s ',' $VALIDATOR_MNEMONIC_START_INDEX $((VALIDATOR_MNEMONIC_START_INDEX + TOTAL_VALIDATORS - 1)))
5454
VALIDATOR_PUBLISHER_MNEMONIC_START_INDEX=$((5000 + MNEMONIC_INDEX_OFFSET))
55-
PUBLISHERS_PER_VALIDATOR_KEY=1
55+
VALIDATOR_PUBLISHERS_PER_REPLICA=8
5656
SEQ_MIN_TX_PER_BLOCK=0
5757
SEQ_MAX_TX_PER_BLOCK=32
5858

spartan/environments/five-tps-long-epoch.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ OTEL_COLLECTOR_ENDPOINT=REPLACE_WITH_GCP_SECRET
2525

2626
VALIDATOR_REPLICAS=12
2727
VALIDATORS_PER_NODE=4
28-
PUBLISHERS_PER_VALIDATOR_KEY=2
28+
VALIDATOR_PUBLISHERS_PER_REPLICA=4
2929
VALIDATOR_PUBLISHER_MNEMONIC_START_INDEX=5000
3030
VALIDATOR_RESOURCE_PROFILE="2-core-dedicated"
3131

spartan/environments/five-tps-short-epoch.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ OTEL_COLLECTOR_ENDPOINT=REPLACE_WITH_GCP_SECRET
2525

2626
VALIDATOR_REPLICAS=12
2727
VALIDATORS_PER_NODE=4
28-
PUBLISHERS_PER_VALIDATOR_KEY=2
28+
VALIDATOR_PUBLISHERS_PER_REPLICA=4
2929
VALIDATOR_PUBLISHER_MNEMONIC_START_INDEX=5000
3030
VALIDATOR_RESOURCE_PROFILE="2-core-dedicated"
3131

0 commit comments

Comments
 (0)