Comment on page
Deploying a DA Node
Deploy a Mantle DA node to provide data availability services to Mantle network
All Mantle DA nodes are run by Mantle Core Contributor Team for the time being. Stay tuned for updates!
Data Availability, or DA nodes basically get rewards for storing the calldata that is traditionally published to Ethereum. There are multiple advantages to this solution, and you can read up more on why data availability is a major concern for optimistic rollups, and how Mantle addresses it by navigating to the Data Availability page.
The data storage process consists of two steps:
- 1.The DA Operator node receives data from the Disperser and stores it
- 2.It then sends a BLS signature to Disperser after performing data recovery verification
The minimum recommended specifications for a DA node are:
- Quad core CPU or higher
- 8GB+ RAM
- 500GB+ disk space (HDD works, SSD recommended for future-proofing)
- 10 Mbps+ download speed
Before getting started, make sure you have Docker installed in your environment and superuser access configured for your account.
Please make sure you have Foundry installed and configured in your local environment! You'll need it to use the
cast
tool to make RPC calls.You can get in touch with us via mail to with your wallet address, and we'll whitelist it so you can move ahead with the deployment process.
You can start by cloning the GitHub repo.
git clone https://github.com/mantlenetworkio/networks
The downloaded directory contains the compose files to run both Mantle verifier/sequencer nodes, and DA nodes. The file is named
docker-compose.da.yml
and we'll be using it to spin up our DA node.The
./da/scripts
directory contains a binary that will automatically download all the necessary files and spin up a DA node. Let's see how to start up a DA node using the binary, as well as Docker.Before starting up a node you'll need to configure the node environment. You can do this by creating a
.env
file in the ./scripts
directory. The configuration is shown below. You can go ahead and use the same configuration to connect to Mantle testnet.
1
DL_NODE_CHAIN_ID: 5
2
DL_NODE_CHAIN_RPC: https://rpc.ankr.com/eth_goerli
3
DL_NODE_CHALLENGE_ORDER: 200000
4
DL_NODE_DB_PATH: /data/da-node
5
DL_NODE_DLSM_ADDRESS: 0x5d88885659dc1ba1C25d9e9a78ec4df313672d48
6
DL_NODE_FILE_LOG_LEVEL: trace
7
DL_NODE_G1_PATH: /data/kzg/g1.point
8
DL_NODE_G2_PATH: /data/kzg/g2.point
9
DL_NODE_GRAPH_PROVIDER: http://k8s-app-graphnod-30887b7825-5c5d19b37726120d.elb.ap-southeast-1.amazonaws.com:8000/subgraphs/name/datalayr
10
DL_NODE_GRPC_PORT: 32000
11
DL_NODE_HOSTNAME: ${publicip_of_da-node}
12
DL_NODE_LOG_PATH: /data/logs/da-node
13
DL_NODE_SRS_ORDER: 200000
14
DL_NODE_PRIVATE_BLS: '8332518314'
15
DL_NODE_SRS_TABLE_PATH: /data/kzg/SRSTables
16
DL_NODE_STD_LOG_LEVEL: debug
17
DL_NODE_TIMEOUT: 3000ms
18
DL_NODE_CACHE_PATH: data/kzg/SRSTables
19
DL_NODE_VERBOSE: true
20
DL_NODE_NUM_WORKERS: 8
21
DL_NODE_ENABLE_METRICS: true
22
DL_NODE_METRICS_PORT: 7001
23
DL_NODE_PRIVATE_KEY: ${danode-privatekey}
Here's a brief description of each setting.
Field name | Description |
---|---|
DL_NODE_CHAIN_ID | L1 chain ID |
DL_NODE_CHAIN_RPC | L1 RPC provider URL |
DL_NODE_CHALLENGE_ORDER | Challenge order, 3000 by default |
DL_NODE_DB_PATH | DA node database directory |
DL_NODE_DLSM_ADDRESS | DataLayrServiceManager contract address |
DL_NODE_FILE_LOG_LEVEL | DA node log file level |
DL_NODE_G1_PATH | G1 SRS path |
DL_NODE_G2_PATH | G2 SRS path |
DL_NODE_GRAPH_PROVIDER | GraphQL API endpoint for Graph node |
DL_NODE_GRPC_PORT | Port at which node listens for gRPC calls |
DL_NODE_HOSTNAME | DA Node host name |
DL_NODE_LOG_PATH | DA Node log path |
DL_NODE_SRS_ORDER | SRS order |
DL_NODE_PRIVATE_BLS | BLS private key for node operator |
DL_NODE_SRS_TABLE_PATH | SRS table path |
DL_NODE_STD_LOG_LEVEL | DA Node STD Log level |
DL_NODE_TIMEOUT | gRPC request timeout in ms |
DL_NODE_CACHE_PATH | DA node cache directory |
DL_NODE_VERBOSE | DA node verbose |
DL_NODE_NUM_WORKERS | DA node workers |
DL_NODE_ENABLE_METRICS | Enable/disable metrics for DA node |
DL_NODE_METRICS_PORT | Metrics port |
DL_NODE_PRIVATE_KEY | DA node operator wallet private key |
After completing the Docker environment variable configuration in the
docker-compose.da.yml
file, use the following Docker command to spin up a DA node.cd network
sudo docker compose -f docker-compose.da.yml up -d
Stay tuned!
- Mantle DA delegation contract:
0xe6394303385f50b22F8E6fDe7ddE3236794A62a6
- Investment manager contract:
0x14dA377F5d37fa501E76D5208418714E3A26a2F0
- $MNT token contract on Goerli:
0xc1dC2d65A2243c22344E725677A3E3BEBD26E604
- Open node RPC:
http://goerli.test
You'll need to register your operator node to enable user staking and delegation via your wallet. You can do this by calling the
registerAsOperator
function of the EigenLayrDelegation
contract. Here's an example.cast send --from $FromAddress --private-key $PrivateKey --rpc-url $L1Rpc $DelegationAddress "registerAsOperator(address)" $OperatorAddress
Parameter | Description |
---|---|
FromAddress | Operator wallet address |
PrivateKey | Operator wallet private key |
L1Rpc | Ethereum RPC URL |
Mantle DA delegation contract address | |
OperatorAddress | Operator EOA address |
To withdraw a node from the DA network, the first step is to fetch the public key and index for your node from the staker subgraph, like so:
query MyQuery {
operators(orderBy: id, where: {status: 0}) {
status
id
pubkeys {
id
pubkeyG1
}
indexHistory {
index
}
}
}
Next, you can call the
deregisterOperator
method which is a part of the BLSRegistryWithBomb
contract. The method takes the following parameters:deregisterOperator(uint256[4], uint32, bytes32):(pubKey,index,0x0)
Here's a sample request:
cast send --from $FromAddress --private-key $PrivateKey --rpc-url $L1Rpc $DlReg "deregisterOperator( (uint256,uint256), uint32 )" '($pubkeyG1-01,$pubkeyG1-02)' $Index
Parameter | Description |
---|---|
FromAddress | Operator wallet address |
PrivateKey | Operator wallet private key |
L1Rpc | Ethereum RPC URL |
Mantle DA BLSRegistry contract address | |
Index | Activity index queried from the staker subgraph |
pubkeyG1-01 , pubkeyG1-02 | pubkeyG1 queried from the subgraph above |
Node staking is optional!
The staking process consists of the following steps:
To stake $MNT to a DA node, it first needs to be approved to the
InvestmentManager
contract. It is no different from a standard ERC-20 approval action. Here's a sample request.cast send --from $FromAddress --private-key $PrivateKey --rpc-url $L1Rpc $MantleTokenAddress "approve(address,uint256)" $InvestmentManagerAddress $Amount
Parameter | Description |
---|---|
FromAddress | Staker wallet address |
PrivateKey | Staker wallet private key |
L1Rpc | Ethereum RPC URL |
$MNT token contract address | |
Amount | Stake amount |
InvestmentManager contract address |
To delegate the approved tokens to the operator, it needs to be deposited into the investment strategy using the investment strategy contract. We do this by calling the
depositIntoStrategy
function. Here's a sample request.cast send --from $FromAddress --private-key $PrivateKey --rpc-url $L1Rpc InvestmentManagerAddress "depositIntoStrategy(address, address, uint256)" $StrategyAddress $MantleTokenAddress $Amount
Parameter | Description |
---|---|
FromAddress | Staker wallet address |
PrivateKey | Staker wallet private key |
L1Rpc | Ethereum RPC URL |
Strategy contract address | |
$MNT token contract address | |
Amount | Staking amount |
After approving and depositing the $MNT tokens, we can now invoke the
delegateTo
function of the EigenLayrDelegation
contract to stake your tokens to the operator. Here's a sample request.cast send --from $FromAddress --private-key $PrivateKey --rpc-url $L1Rpc $DelegationAddress "delegateTo(address)" $OperatorAddress
Parameter | Description |
---|---|
FromAddress | Staker wallet address |
PrivateKey | Staker private key |
L1Rpc | Ethereum RPC URL |
Delegation contract address | |
OperatorAddress | Operator address to be delegated to |
You can fetch details on the amount of $MNT deposited into the investment manager contract by a wallet address by invoking the
getDeposits()
function. Here's an sample request.cast call --rpc-url $L1Rpc $InvestmentManagerAddress "getDeposits(address)(address[],uint256[])" $StakerAddress
Parameter | Description |
---|---|
L1Rpc | Ethereum RPC URL |
Investment manager contract address | |
StakerAddress | Staker wallet address |
You can withdraw the delegated $MNT from a wallet address by invoking the delegatorWithdraw() function. Here's a sample request.
cast send --from $FromAddress --private-key $PrivateKey --rpc-url $L1Rpc $InvestmentManagerAddress "delegatorWithdraw(uint256[], address[], address[], uint256[], bool)" "$StrategyIndexList" "$StrategyList" "$TokenList" "$AmountList" $IsUndelegate
delegatorWithdraw() arguments
function delegatorWithdraw(
uint256[] calldata strategyIndexes,
IInvestmentStrategy[] calldata strategies,
IERC20[] calldata tokens,
uint256[] calldata shares,
bool undelegateIfPossible
)
Parameter | Description |
---|---|
FromAddress | Staker wallet address |
PrivateKey | Staker wallet private key |
L1Rpc | Etherem RPC URL |
Investment manager contract address | |
StrategyIndexList | Strategy index list |
StrategyList | Strategy list, only Mantle strategy supported |
TokenList | Strategy token list, only Mantle token supported |
AmountList | Staking amount list |
IsUndelegate | Undelegate action boolean |
Last modified 4mo ago