Configure EIP-3076 signing-history backends and import/export validator history safely
Ethereum validators can be slashed — permanently penalized and forcibly exited — for signing conflicting blocks or attestations. EIP-3076 defines a slashing protection interchange format for carrying that signing history across validator clients and signers.
Containment Chamber implements EIP-3076 slashing protection with pluggable backends. Block proposals and attestations are checked and recorded before the BLS signature is produced. If a request would result in a slashable message, the signer returns HTTP 412 and refuses to sign. Backend or integrity failures fail closed, usually as HTTP 503.
direction: down
req: "HTTP Request"auth: "Auth Check"sem: "Semaphore"gvr: "GVR Validation"key: "Key Loaded?"root: "Compute Signing Root"as: "Anti-Slashing\ncheck_and_update"bls: "BLS Sign"ok: "HTTP 200\n{ signature: 0x... }"missing: "HTTP 404\nKey not found"rejected: "HTTP 412\nSlashing violation"wrongnet: "HTTP 400\nNetwork mismatch"
req.style.fill: "#FFF6EF"req.style.stroke: "#D35F0A"req.style.font-color: "#170206"auth.style.fill: "#FFF6EF"auth.style.stroke: "#D35F0A"auth.style.font-color: "#170206"sem.style.fill: "#FFF6EF"sem.style.stroke: "#D35F0A"sem.style.font-color: "#170206"gvr.style.fill: "#FEEC8C"gvr.style.stroke: "#D35F0A"gvr.style.font-color: "#170206"key.style.fill: "#FEEC8C"key.style.stroke: "#D35F0A"key.style.font-color: "#170206"root.style.fill: "#FEEC8C"root.style.stroke: "#D35F0A"root.style.font-color: "#170206"as.style.fill: "#FEEC8C"as.style.stroke: "#D35F0A"as.style.font-color: "#170206"bls.style.fill: "#CAF2E6"bls.style.stroke: "#13A477"bls.style.font-color: "#170206"ok.style.fill: "#CAF2E6"ok.style.stroke: "#13A477"ok.style.font-color: "#170206"missing.style.fill: "#FEE2E2"missing.style.stroke: "#B42318"missing.style.font-color: "#170206"rejected.style.fill: "#FEE2E2"rejected.style.stroke: "#B42318"rejected.style.font-color: "#170206"wrongnet.style.fill: "#FEE2E2"wrongnet.style.stroke: "#B42318"wrongnet.style.font-color: "#170206"
req -> auth: "POST /api/v1/eth2/sign/{pubkey}"auth -> sem: "Token validated"sem -> gvr: "Permit acquired"gvr -> wrongnet: "Wrong GVR" {style.stroke: "#B42318"}gvr -> key: "Network verified"key -> missing: "Not loaded" {style.stroke: "#B42318"}key -> root: "Loaded"root -> as: "Signing root"as -> rejected: "Slashing violation" {style.stroke: "#B42318"}as -> bls: "Safe to sign" {style.stroke: "#13A477"}bls -> okBackend Comparison
Section titled “Backend Comparison”| Backend | Multi-Instance | Slashing Protection | Recommended |
|---|---|---|---|
| PostgreSQL | ✅ | ✅ Complete | ✅ Production |
| DynamoDB | ✅ | ✅ Hybrid | ✅ Production at scale / AWS |
| SQLite | ❌ | ✅ Complete | Dev / single instance |
| Noop | — | ❌ None | ⚠️ Testing only |
Per-Backend Configuration
Section titled “Per-Backend Configuration”anti_slashing: backend: postgres url: "postgresql://user:password@localhost:5432/slashing?sslmode=require" pool_size: 64 # connection pool size force_ipv4: false # set true if IPv6 causes issuesPostgreSQL is the default production choice for most deployments. It supports multiple signer instances sharing the same database and provides complete-mode surround vote detection.
TLS is enabled by default. Append ?sslmode=disable to the URL to disable it.
anti_slashing: backend: sqlite path: ./slashing_protection.sqliteSQLite provides complete slashing protection (including surround vote detection) in a single file. Ideal for development or single-instance deployments.
anti_slashing: backend: dynamodb table: "slashing-protection" max_concurrent_writes: 256 # Uses AWS SDK default credential chain # (env vars, instance profile, IRSA, etc.)DynamoDB provides multi-instance safety via AWS-native infrastructure. It uses Hybrid mode: high-water marks (slots and epochs can only advance forward) combined with per-slot block records and per-target attestation records that store signing roots. This enables:
- Double-vote detection: signing the same target epoch with a different message is rejected
- Re-broadcast support: re-signing the exact same message (same signing root) is allowed
- Surround vote prevention: algebraically impossible under watermark invariants — no full history scan needed
- Requires a pre-created DynamoDB table with partition key
pk(String) and sort keysk(String). Do not reuse the DynamoDB key-source or signer-state table; the schemas are different. - The table name is specified via
table:config option or--anti-slashing-dynamodb-tableCLI flag max_concurrent_writesgates in-flight anti-slashing writes inside the process so signing bursts do not overwhelm the AWS SDK connection pool- Watermarks enforce forward-only progression; signing root records enable precise double-vote detection
- Credentials are resolved via the standard AWS SDK credential chain
anti_slashing: backend: noopThe Noop backend disables all slashing protection checks. Signing requests are never rejected for slashing reasons.
EIP-3076 Import and Export
Section titled “EIP-3076 Import and Export”Slashing-protection history is imported before runtime key imports make a key signable:
POST /eth/v1/keystoresacceptsslashing_protectionin the Web3Signer-compatible Key Manager API.POST /api/v1/chamber/keysacceptsslashing_protectionin the Chamber key-management API.
Both paths validate the interchange data against the signer’s configured genesis validators root before writing to the anti-slashing backend. Invalid interchange data rejects the import before keys are inserted.
Deleting keys exports slashing-protection history:
DELETE /eth/v1/keystoresreturns the EIP-3076 interchange payload required by the Web3Signer API.DELETE /api/v1/chamber/keysincludesslashing_protectionwhen at least one key was deleted and export succeeds.
SQL backends export stored block and attestation records. DynamoDB Hybrid mode exports watermark-derived synthetic entries so importing into another signer preserves the correct lower bounds.
Environment Variable Override
Section titled “Environment Variable Override”You can configure the anti-slashing backend via environment variables using the CONTAINMENT_ prefix with __ for nesting:
CONTAINMENT_ANTI_SLASHING__BACKEND=postgresCONTAINMENT_ANTI_SLASHING__URL="postgresql://user:password@localhost:5432/slashing"CONTAINMENT_ANTI_SLASHING__POOL_SIZE=64CONTAINMENT_ANTI_SLASHING__FORCE_IPV4=falseFor DynamoDB:
CONTAINMENT_ANTI_SLASHING__BACKEND=dynamodbCONTAINMENT_ANTI_SLASHING__TABLE=slashing-protectionCONTAINMENT_ANTI_SLASHING__MAX_CONCURRENT_WRITES=256CLI Flags
Section titled “CLI Flags”For quick testing, you can also set the backend via CLI flags:
# SQLite via CLIcontainment-chamber server \ --anti-slashing-backend sqlite \ --anti-slashing-sqlite-path ./slashing.sqlite \ --key-sources-filesystem-paths ./keystores/raw
# PostgreSQL via CLIcontainment-chamber server \ --anti-slashing-backend postgres \ --anti-slashing-postgres-url "postgresql://user:pass@localhost/slashing" \ --anti-slashing-postgres-pool-size 64 \ --key-sources-filesystem-paths ./keystores/raw
# DynamoDB via CLIcontainment-chamber server \ --anti-slashing-backend dynamodb \ --anti-slashing-dynamodb-table slashing-protection \ --anti-slashing-dynamodb-max-concurrent-writes 256 \ --key-sources-filesystem-paths ./keystores/rawNext Steps
Section titled “Next Steps”- Backend at Scale — PostgreSQL pool sizing and DynamoDB scaling guidance
- AWS IAM Permissions — DynamoDB anti-slashing permissions and table separation
- Upgrading — back up the slashing database before version bumps

