Local Deployment Deep Dive
Relay Contracts deployment follows a 4-step process. Understanding what happens under the hood is crucial for customizing deployments and troubleshooting issues.
Overview of the Steps
InitSetup → MasterSetup → GenesisGeneration → GenesisSetup
↓ ↓ ↓ ↓
Core & Network Initial Settlement
Base Config ValSet Commitment
Step 1: InitSetup
Purpose: Deploy core infrastructure and Symbiotic Core integration
Configuration
# Environment variables that affect InitSetup
SYMBIOTIC_CORE_NUMBER_OF_VAULTS=3
SYMBIOTIC_CORE_NUMBER_OF_OPERATORS=5
SYMBIOTIC_CORE_NUMBER_OF_STAKERS=1
SYMBIOTIC_CORE_TOKENS_TO_SET_TIMES_1e18=0.03
What Gets Deployed
Symbiotic Core Setup
InitSetup also configures the underlying Symbiotic infrastructure:
- Tokens: Creates test tokens for staking (configurable via
SYMBIOTIC_CORE_*
env vars) - Vaults: Deploys vaults that will hold operator stake
- Operators: Registers test operators in the OperatorRegistry
- Stakers: Creates test stakers with token balances
Network Middleware
// 5 Core Contracts
MyNetwork network = new MyNetwork(networkRegistry, networkMiddlewareService);
MyKeyRegistry keyRegistry = new MyKeyRegistry();
MyVotingPowerProvider votingPowerProvider = new MyVotingPowerProvider(operatorRegistry, vaultFactory);
MyValSetDriver valSetDriver = new MyValSetDriver();
MySettlement settlement = new MySettlement();
Step 2: MasterSetup
Purpose: Configure network parameters, set up extensions, and register operators
Network Configuration
// Key parameters from environment
networkSetupParams.OPERATORS_TO_REGISTER = vm.envOr("OPERATORS", 4);
networkSetupParams.EPOCH_DURATION = uint48(vm.envOr("EPOCH_DURATION", 60));
networkSetupParams.SLASHING_WINDOW = uint48(vm.envOr("SLASHING_WINDOW", 1200));
networkSetupParams.VERIFICATION_TYPE = uint32(vm.envOr("VERIFICATION_TYPE", 1));
VotingPowerProvider Initialization
Sample initialization:
votingPowerProvider.initialize(
// Core parameters
IVotingPowerProvider.VotingPowerProviderInitParams({
networkManagerInitParams: INetworkManager.NetworkManagerInitParams({
network: vars.network.addr,
subnetworkID: IDENTIFIER
}),
ozEip712InitParams: IOzEIP712.OzEIP712InitParams({name: "VotingPowerProvider", version: "1"}),
slashingWindow: networkSetupParams.SLASHING_WINDOW,
token: tokens[0]
}),
// Ownership
IOzOwnable.OzOwnableInitParams({owner: vars.network.addr}),
// Extensions
IOperatorsWhitelist.OperatorsWhitelistInitParams({isWhitelistEnabled: false}),
IBaseSlashing.BaseSlashingInitParams({slasher: address(1)}),
IBaseRewards.BaseRewardsInitParams({rewarder: address(1)})
);
Operator Registration Flow
For each operator being registered:
- Generate Keys: Creates BLS and ECDSA key pairs
// BLS key generation
BN254.G1Point memory blsPublicKey = BN254.generatorG1().scalar_mul(privateKey);
// ECDSA key from private key
address ecdsaPublicKey = vm.addr(privateKey);
- Register Keys: Adds keys to KeyRegistry
keyRegistry.registerKey(
operator,
KEY_TYPE_BLS_BN254,
blsKeyBytes,
signature
);
keyRegistry.registerKey(
operator,
KEY_TYPE_ECDSA_SECP256K1,
ecdsaKeyBytes,
signature
);
- Operator Registration: Registers with VotingPowerProvider
votingPowerProvider.registerOperator(
operator,
signature
);
Signature Verifier Setup
The verification type is set to "BLS" (1) by default, but can be overridden by setting the VERIFICATION_TYPE
environment variable to 0 (ZK).
The number of operators is set to 4 by default, but can be overridden by setting the OPERATORS
environment variable.
If the verification type is set to 0 or the number of operators exceeds 100, SigVerifierBlsBn254ZK
is used.
Otherwise, SigVerifierBlsBn254Simple
is used.
Middleware Integration
Connects the VotingPowerProvider to Symbiotic's middleware system:
// Set network middleware to our VotingPowerProvider
INetworkMiddlewareService(networkMiddlewareService).setMiddleware(
network,
address(votingPowerProvider)
);
Step 3: GenesisGeneration
Purpose: Create initial validator set data using external tooling
What Happens
- Binary Execution: Runs
script/test/utils/generate_genesis
binary - Data Collection: Gathers operator keys and voting power from deployed contracts
- Validator Set Creation: Constructs initial validator set with:
- Operator addresses
- BLS public keys
- Voting power weights
- Aggregated public key
Output Format
Generates JSON data structure:
{
"validators": [
{
"address": "0x...",
"blsPublicKey": "0x...",
"votingPower": "1000000000000000000"
}
],
"aggregatedPublicKey": "0x...",
"totalVotingPower": "4000000000000000000"
}
Binary Details
The generate_genesis
tool:
- Queries deployed contracts for current state
- Validates operator keys and registration
- Computes BLS key aggregation
- Outputs validator set in format expected by GenesisSetup
Step 4: GenesisSetup
Purpose: Initialize Settlement contract with initial validator set
ValSetDriver Initialization
valSetDriver.initialize(
IValSetDriver.ValSetDriverInitParams({
networkManagerInitParams: INetworkManager.NetworkManagerInitParams({
network: vars.network.addr,
subnetworkID: IDENTIFIER
}),
ozEip712InitParams: IOzEIP712.OzEIP712InitParams({name: "ValSetDriver", version: "1"}),
votingPowerProvider: address(votingPowerProvider),
keyRegistry: address(keyRegistry),
epochDuration: EPOCH_DURATION
}),
defaultAdmin
);
Settlement Contract Setup
settlement.initialize(
ISettlement.SettlementInitParams({
networkManagerInitParams: INetworkManager.NetworkManagerInitParams({
network: vars.network.addr,
subnetworkID: IDENTIFIER
}),
ozEip712InitParams: IOzEIP712.OzEIP712InitParams({name: "Settlement", version: "1"}),
valSetDriver: address(valSetDriver),
sigVerifier: address(sigVerifier)
}),
defaultAdmin
);
Genesis Commitment
Commits the initial validator set to the Settlement contract:
// Create validator set header from genesis data
bytes32 headerHash = keccak256(abi.encode(
validatorSetData.validators,
validatorSetData.totalVotingPower,
validatorSetData.aggregatedPublicKey
));
// Commit to settlement
settlement.commitValSetHeader(
0, // epoch 0
headerHash,
extraDataHash
);
Configuration Parameters
Core Parameters
OPERATORS
: Number of operators (affects gas costs and verification type choice)EPOCH_DURATION
: How often validator sets can change (seconds)SLASHING_WINDOW
: Time window for slashing events (seconds)VERIFICATION_TYPE
: Signature verification approach (0=ZK, 1=Simple)
Advanced Parameters
DEPLOYMENT_BUFFER
: Wait time between deployment stepsSUBNETWORK_ID
: Unique identifier for your network
Post-Deployment State
After successful completion:
- Active Network: Ready to accept Relay binary connections
- Registered Operators: With verified BLS and ECDSA keys
- Initial Validator Set: Committed to Settlement contract
- Epoch 0: System ready for first epoch transition