| 235 | const ED25519_PUBLIC_KEY_HEX_LENGTH = 66 // 0x prefix + 64 hex chars (32 bytes) |
| 236 | |
| 237 | function parseOverridePublicKeys(input: string): Map<number, Hex> { |
| 238 | const map = new Map<number, Hex>() |
| 239 | if (input.trim() === '') { |
| 240 | return map |
| 241 | } |
| 242 | |
| 243 | const entries = input.split(',') |
| 244 | |
| 245 | for (const entry of entries) { |
| 246 | const [idStr, key, ...extra] = entry.split(':') |
| 247 | |
| 248 | if (extra.length > 0) { |
| 249 | throw new Error(`Invalid format in overridePublicKeys: ${entry} (too many colons)`) |
| 250 | } |
| 251 | if (!idStr || !key) { |
| 252 | throw new Error(`Invalid format in overridePublicKeys: ${entry} (missing ID or key)`) |
| 253 | } |
| 254 | |
| 255 | const id = Number(idStr) |
| 256 | |
| 257 | if (isNaN(id) || id < 1) { |
| 258 | throw new Error(`Invalid validator ID in overridePublicKeys: ${idStr}`) |
| 259 | } |
| 260 | if (map.has(id)) { |
| 261 | throw new Error(`Duplicate validator ID in overridePublicKeys: ${id}`) |
| 262 | } |
| 263 | if (!key.startsWith('0x') || key.length !== ED25519_PUBLIC_KEY_HEX_LENGTH) { |
| 264 | throw new Error(`Invalid public key format for validator ${id}: ${key}`) |
| 265 | } |
| 266 | |
| 267 | map.set(id, key as Hex) |
| 268 | } |
| 269 | |
| 270 | return map |
| 271 | } |