🧪 BLS Signing Demo (Ethereum Validators)
About this demo
This page demonstrates the core steps of BLS signing used by Ethereum validators using a simple Python script based on
py_ecc
(Ethereum's BLS library). It is a local demo, not Web3Signer. Web3Signer provides similar functionality as a network service, but it does not implement EIP‑3030 at this time.
How to run locally
$ python3 -m pip install py_ecc
$ python3 bls_signing_demo.py
Demo code (excerpt)
from py_ecc.bls import G2ProofOfPossession as bls
def simulate_ethereum_domain(domain_type: bytes, fork_version: bytes = b'\x00\x00\x00\x00') -> bytes:
genesis_validators_root = b'\x00' * 32
fork_data_root = hashlib.sha256(fork_version + genesis_validators_root).digest()
return domain_type + fork_data_root[:28]
def create_signing_root(message: bytes, domain: bytes) -> bytes:
return hashlib.sha256(message + domain).digest()
# ... see repository for full code ...
Sample output
🚀 ETHEREUM VALIDATOR BLS SIGNING DEMONSTRATION
============================================================
✅ Using py_ecc (Ethereum's official BLS library)
🔐 BLS SIGNATURE BASICS DEMONSTRATION
1️⃣ Generating Validator Keys...
Private Key: 12345
Public Key: 8a3e3a...d5c4be (BLS12-381 G1 point)
2️⃣ Creating Attestation Data...
Slot: 1000
Committee: 5
Block Root: aaaaaaaaaaaaaaaa...
3️⃣ Preparing Message for Signing...
Serialized Length: 128 bytes
Domain: 01000000...
Signing Root: 6f2bf9f4...de91
4️⃣ Creating BLS Signature...
Signature: b3aa4d2f...7c1e9d2f
Signature Length: 96 bytes (BLS12-381 G2 point)
5️⃣ Verifying Signature...
Verification Result: ✅ VALID
🔗 BLS SIGNATURE AGGREGATION DEMONSTRATION
📝 5 validators signing the same attestation...
Signing Root: 6f2bf9f4...de91
Validator 0: 9c0f... → a1b2...
Validator 1: 81d3... → c3d4...
...
🪄 Aggregating 5 signatures into one...
Individual Signatures: 5 × 96 = 480 bytes
Aggregated Signature: 1 × 96 = 96 bytes
Space Savings: 80.0%
✅ Verifying Aggregated Signature...
Verification Result: ✅ VALID
⚡ Fast Aggregate Verify (same message optimization)...
Fast Verification: ✅ VALID
📋 DIFFERENT VALIDATOR SIGNING DUTIES
1️⃣ Attestation → VALID
2️⃣ Block Proposal→ VALID
3️⃣ RANDAO Reveal → VALID
4️⃣ Voluntary Exit→ VALID
🎉 DEMONSTRATION COMPLETE!
💡 Key Takeaways:
• BLS signatures can be aggregated (ECDSA cannot)
• Massive space savings for consensus (96 bytes vs thousands)
• Domain separation prevents signature reuse
• Essential for Ethereum's scalability
• Web3Signer implements these operations as a service (no EIP-3030 yet)
Notes on Web3Signer and EIP‑3030
This page uses a local Python demo to illustrate BLS flows. Web3Signer is a production service that handles validator signing over HTTP, offering protection and auditing around key usage. As of now, Web3Signer does not implement EIP‑3030 (BLS remote signer API proposal).
Web3Signer vs Local Demo
The local demo signs directly with
py_ecc
in-process. Web3Signer moves keys and signing to a hardened HTTP service with slashing protection and auditability.
- Invocation model: Demo calls
bls.Sign(...)
in Python; Web3Signer receives an HTTP request and returns a signature. - Key management: Demo embeds a private key in code; Web3Signer stores keys (e.g., EIP‑2335 keystores) and never exposes them to clients.
- Slashing protection: Demo has none; Web3Signer enforces slashing protection with a database to prevent double proposals/votes.
- Message construction: Demo computes domains/SSZ/signing root manually; with Web3Signer, validator clients send duty payloads and signer handles the spec‑correct root.
- Integration: Demo is standalone; Web3Signer is configured in Lighthouse/Prysm/Teku as an external signer (e.g.,
--validators-external-signer-url=http://host:9000
). - EIP‑3030 status: This demo is not Web3Signer and does not implement EIP‑3030; Web3Signer also does not implement EIP‑3030 currently.