Awesome
<!-- markdownlint-disable --> <div align="center"> <img src="https://github.com/keep-starknet-strange/madara-branding/blob/main/logo/PNGs/Madara%20logomark%20-%20Red%20-%20Duotone.png?raw=true" width="500"> </div> <div align="center"> <br /> <!-- markdownlint-restore --><a href="https://twitter.com/madara-alliance"> <img src="https://img.shields.io/twitter/follow/madara-alliance?style=social"/> </a> <a href="https://github.com/madara-alliance/madara"> <img src="https://img.shields.io/github/stars/madara-alliance/madara?style=social"/> </a>
</div>š„· Madara: Starknet Client
Madara is a powerful Starknet client written in Rust.
Table of Contents
- ā¬ļø Installation
- āļø Configuration
- š Database Migration
- ā Supported Features
- š¬ Get in touch
ā¬ļø Installation
Run from Source
1. Install dependencies
Ensure you have all the necessary dependencies available on your host system.
Dependency | Version | Installation |
---|---|---|
Rust | rustc 1.81 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
Clang | Latest | sudo apt-get install clang |
Openssl | 0.10 | sudo apt install openssl |
Once all dependencies are satisfied, you can clone the Madara repository:
cd <your-destination-path>
git clone https://github.com/madara-alliance/madara .
2. Build Madara
You can choose between different build modes:
-
Debug (low performance, fastest builds, for testing purposes only):
cargo build
-
Release (fast performance, slower build times):
cargo build --release
-
Production (fastest performance, very slow build times):
cargo build --profile=production
3. Run Madara
Start the Madara client with a basic set of arguments depending on your chosen mode:
Full Node
Synchronizes the state of the chain from genesis.
cargo run --release -- \
--name Madara \
--full \
--base-path /var/lib/madara \
--network mainnet \
--l1-endpoint ${ETHEREUM_API_URL}
Sequencer
Produces new blocks for other nodes to synchronize.
cargo run --release -- \
--name Madara \
--sequencer \
--base-path /var/lib/madara \
--preset sepolia \
--l1-endpoint ${ETHEREUM_API_URL}
Devnet
A node in a private local network.
cargo run --release -- \
--name Madara \
--devnet \
--base-path /var/lib/madara \
--preset sepolia
[!NOTE] Head to the Configuration section to learn more about customizing your node.
4. Presets
You can use cli presets for certain common node configurations, for example enabling rpc endpoints:
cargo run --release -- \
--name Madara \
--full \
--preset mainnet \
--rpc
...or the madara feeder gateway:
cargo run --release -- \
--name Madara \
--full \
--preset mainnet \
--fgw
Run with Docker
1. Manual Setup
Dependency | Version | Installation |
---|---|---|
Docker | Latest | Official instructions |
Once you have Docker installed, you will need to pull the madara image from the github container registry (ghr):
docker pull ghcr.io/madara-alliance/madara:latest
docker tag ghcr.io/madara-alliance/madara:latest madara:latest
docker rmi ghcr.io/madara-alliance/madara:latest
You can then launch madara as follows:
docker run -d \
-p 9944:9944 \
-v /var/lib/madara:/tmp/madara \
--name Madara \
madara:latest \
--name Madara \
--full \
--network mainnet \
--l1-endpoint ${ETHEREUM_API_URL}
To display the node's logs, you can use:
docker logs -f -n 100 Madara
[!WARNING] Make sure to change the volume
-v
of your container if ever you update--base-path
.
2. Using the project Makefile
Alternatively, you can use the provided Makefile and compose.yaml
to
simplify this process.
Dependency | Version | Installation |
---|---|---|
Docker Compose | Latest | Official instructions |
Gnu Make | Latest | sudo apt install make |
Once you have all the dependencies installed, start by saving your rpc key
to a .secrets
forlder:
mkdir .secrets
echo *** .secrets/rpc_api.secret
Then, run madara with the following commands:
make start # This will automatically pull the madara image if not available
make logs # Displays the last 100 lines of logs
make stop # Stop the madara node
make clean-db # Removes the madara db, including files on the host
make restart # Restarts the madara node
[!IMPORTANT] By default,
make start
will try and restart Madara indefinitely if it is found to be unhealthy using docker autoheal. This is done by checking the availability ofhttp://localhost:9944/health
, which means your container will be marked asunhealthy
and restart if you have disabled the RPC service! You can runwatch docker ps
to monitor the health of your containers.
To change runtime arguments, you can update the script in madara-runner.sh
:
#!/bin/sh
export RPC_API_KEY=$(cat $RPC_API_KEY_FILE)
./madara \
--name madara \
--network mainnet \
--rpc-external \
--rpc-cors all \
--full \
--l1-endpoint $RPC_API_KEY
For more information, run:
make help
[!TIP] When running Madara from a docker container, make sure to set options such as
--rpc-external
,--gateway-external
and--rpc-admin-external
so as to be able to access these services from outside the container.
āļø Configuration
For a comprehensive list of all command-line options, check out:
cargo run -- --help
Or if you are using docker, simply:
docker run madara:latest --help
Basic Command-Line Options
Here are some recommended options to get up and started with your Madara client:
Option | About |
---|---|
--name <NAME> | The human-readable name for this node. It's used as the network node name. |
--base-path <PATH> | Sets the database location for Madara (default is/tmp/madara ) |
--full | The mode of your Madara client (either --sequencer , --full , or --devnet ) |
--l1-endpoint <URL> | The Layer 1 endpoint the node will verify its state from |
--rpc-port <PORT> | The JSON-RPC server TCP port, used to receive requests |
--rpc-cors <ORIGINS> | Browser origins allowed to make calls to the RPC servers |
--rpc-external | Exposes the rpc service on 0.0.0.0 |
Environment Variables
Each cli argument has its own corresponding environment variable you can set to change its value. For example:
MADARA_BASE_PATH=/path/to/db
MADARA_RPC_PORT=1111
These variables allow you to adjust the node's configuration without using command-line arguments, which can be useful in CI pipelines or with docker.
[!NOTE] If the command-line argument is specified then it takes precedent over the environment variable.
š Interactions
Madara fully supports all the JSON-RPC methods as of the latest version of the
Starknet mainnet official JSON-RPC specs.
These methods can be categorized into three main types: Read-Only Access Methods,
Trace Generation Methods, and Write Methods. They are accessible through port
9944 unless specified otherwise with --rpc-port
.
[!TIP] You can use the special
rpc_methods
call to view a list of all the methods which are available on an endpoint.
Supported JSON-RPC Methods
Here is a list of all the supported methods with their current status:
<details> <summary>Read Methods</summary>Status | Method |
---|---|
ā | starknet_specVersion |
ā | starknet_getBlockWithTxHashes |
ā | starknet_getBlockWithTxs |
ā | starknet_getBlockWithReceipts |
ā | starknet_getStateUpdate |
ā | starknet_getStorageAt |
ā | starknet_getTransactionStatus |
ā | starknet_getTransactionByHash |
ā | starknet_getTransactionByBlockIdAndIndex |
ā | starknet_getTransactionReceipt |
ā | starknet_getClass |
ā | starknet_getClassHashAt |
ā | starknet_getClassAt |
ā | starknet_getBlockTransactionCount |
ā | starknet_call |
ā | starknet_estimateFee |
ā | starknet_estimateMessageFee |
ā | starknet_blockNumber |
ā | starknet_blockHashAndNumber |
ā | starknet_chainId |
ā | starknet_syncing |
ā | starknet_getEvents |
ā | starknet_getNonce |
ā | starknet_getCompiledCasm (v0.8.0) |
š§ | starknet_getMessageStatus (v0.8.0) |
š§ | starknet_getStorageProof (v0.8.0) |
Status | Method |
---|---|
ā | starknet_traceTransaction |
ā | starknet_simulateTransactions |
ā | starknet_traceBlockTransactions |
Status | Method |
---|---|
ā | starknet_addInvokeTransaction |
ā | starknet_addDeclareTransaction |
ā | starknet_addDeployAccountTransaction |
Status | Method |
---|---|
ā | starknet_unsubscribe (v0.8.0) |
ā | starknet_subscribeNewHeads (v0.8.0) |
ā | starknet_subscribeEvents (v0.8.0) |
ā | starknet_subscribeTransactionStatus (v0.8.0) |
ā | starknet_subscribePendingTransactions (v0.8.0) |
ā | starknet_subscriptionReorg (v0.8.0) |
[!IMPORTANT] Write methods are forwarded to the Sequencer and are not executed by Madara. These might fail if you provide the wrong arguments or in case of a conflicting state. Make sure to refer to the Starknet JSON-RPC specs for a list of potential errors.
Madara-specific JSON-RPC Methods
As well as the official RPC methods, Madara also supports its own set of custom
extensions to the starknet specs. These are referred to as admin
methods and
are exposed on a separate port 9943 unless specified otherwise with
--rpc-admin-port
.
Method | About |
---|---|
madara_addDeclareV0Transaction | Adds a legacy Declare V0 Transaction to the state |
Method | About |
---|---|
madara_ping | Return the unix time at which this method was called |
madara_shutdown | Gracefully stops the running node |
madara_service | Sets the status of one or more services |
Method | About |
---|---|
madara_pulse | Periodically sends a signal that the node is alive |
[!CAUTION] These methods are exposed on
locahost
by default for obvious security reasons. You can always exposes them externally using--rpc-admin-external
, but be very careful when doing so as you might be compromising your node! Madara does not do any authorization checks on the caller of these methods and instead leaves it up to the user to set up their own proxy to handle these situations.
Example of Calling a JSON-RPC Method
You can use any JSON-RPC client to interact with Madara, such as curl
,
httpie
, websocat
or any client sdk in your preferred programming language.
For more detailed information on how to call each method, please refer to the
Starknet JSON-RPC specs.
Http RPC
Dependency | Version | Installation |
---|---|---|
Curl | Latest | sudo apt install curl |
Here is an example of how to call a JSON-RPC method using Madara. Before running the bellow code, make sure you have a node running with rpc enabled on port 9944 (this is the default configuration).
[!IMPORTANT] Madara currently defaults to
v0.7.1
for its rpc calls. To access methods in other or more recent versions, addrpc/v*_*_*/
to your rpc url. This Also works for websocket methods.
curl --location 'localhost:9944'/v0_7_1/ \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "rpc_methods",
"params": [],
"id": 1
}' | jq --sort-keys
You should receive something like the following:
{
"id": 1,
"jsonrpc": "2.0",
"result": {
"methods": [
"rpc/V0_7_1/starknet_addDeclareTransaction",
"rpc/V0_7_1/starknet_addDeployAccountTransaction",
"rpc/V0_7_1/starknet_addInvokeTransaction",
...
"rpc/V0_8_0/starknet_traceBlockTransactions",
"rpc/V0_8_0/starknet_traceTransaction",
"rpc/V0_8_0/starknet_unsubscribe",
"rpc/rpc_methods"
]
}
}
Websocket RPC
Dependency | Version | Installation |
---|---|---|
Websocat | Latest | Official instructions |
Websockets methods are enabled by default and are accessible through the same
port as http RPC methods. Here is an example of how to call a JSON-RPC method
using websocat
.
(echo '{"jsonrpc":"2.0","method":"starknet_subscribeNewHeads","params":{"block_id":"latest"},"id":1}'; cat -) | \
websocat -v ws://localhost:9944/rpc/v0_8_0
[!TIP] This command and the strange use of
echo
in combination withcat
is just a way to start a websocket stream withwebsocat
while staying in interactive mode, meaning you can still enter other websocket requests.
This will display header information on each new block synchronized. Use
Ctrl-C
to stop the subscription. Alternatively, you can achieve the same
result more gracefully by calling starknet_unsubscribe
. Paste the following
into the subscription stream:
{ "jsonrpc": "2.0", "method": "starknet_unsubscribe", "params": ["your-subscription-id"], "id": 1 }
Where you-subscription-id
corresponds to the value of the subscription
field
which is returned with each websocket response.
š Database Migration
When migration to a newer version of Madara you might need to update your database. Instead of re-synchronizing the entirety of your chain's state from genesis, you can use Madara's warp update feature. This is essentially a form of trusted sync with better performances as it is run from a local source.
Warp Update
Warp update requires a working database source for the migration. If you do not already have one, you can use the following command to generate a sample database:
cargo run --release -- \
--name madara \
--network mainnet \
--full \
--l1-sync-disabled `# We disable sync, for testing purposes` \
--n-blocks-to-sync 1000 `# Only synchronize the first 1000 blocks` \
--stop-on-sync `# ...and shutdown the node once this is done`
To begin the database migration, you will need to start your node with
admin methods and
feeder gateway enabled. This will be
the source of the migration. You can do this with the --warp-update-sender
preset:
cargo run --release -- \
--name Sender \
--full `# This also works with other types of nodes` \
--network mainnet \
--warp-update-sender \
--l1-sync-disabled `# We disable sync, for testing purposes` \
--l2-sync-disabled
[!TIP] Here, we have disabled sync for testing purposes, so the migration only synchronizes the blocks that were already present in the source node's database. In a production usecase, you most likely want the source node to keep synchronizing with an
--l1-endpoint
, that way when the migration is complete the receiver is fully up-to-date with any state that might have been produced by the chain during the migration.
You will then need to start a second node to synchronize the state of your database:
cargo run --release -- \
--name Receiver \
--base-path /tmp/madara_new `# Where you want the new database to be stored` \
--full \
--network mainnet \
--l1-sync-disabled `# We disable sync, for testing purposes` \
--warp-update-receiver \
--warp-update-shutdown-receiver `# Shuts down the receiver once the migration has completed`
This will start generating a new up-to-date database under /tmp/madara_new
.
Once this process is over, the receiver node will automatically shutdown.
[!TIP] There also exists a
--warp-update--shutdown-sender
option which allows the receiver to take the place of the sender in certain limited circumstances.
Running without --warp-update-sender
Up until now we have had to start a node with --warp-update-sender
to begin
a migration, but this is only a preset. In a production
environment, you can start your node with the following arguments and achieve
the same results:
cargo run --release -- \
--name Sender \
--full `# This also works with other types of nodes` \
--network mainnet \
--feeder-gateway-enable `# The source of the migration` \
--gateway-port 8080 `# Default port, change as required` \
--rpc-admin `# Used to shutdown the sender after the migration` \
--rpc-admin-port 9943 `# Default port, change as required` \
--l1-sync-disabled `# We disable sync, for testing purposes` \
--l2-sync-disabled
--warp-update-receiver
doesn't override any cli arguments but is still needed
on the receiver end to start the migration. Here is an example of using it with
custom ports:
[!IMPORTANT] If you have already run a node with
--warp-update-receiver
following the examples above, remember to delete its database withrm -rf /tmp/madara_new
.
cargo run --release -- \
--name Receiver \
--base-path /tmp/madara_new `# Where you want the new database to be stored` \
--full \
--network mainnet \
--l1-sync-disabled `# We disable sync, for testing purposes` \
--warp-update-port-rpc 9943 `# Same as set with --rpc-admin-port on the sender` \
--warp-update-port-fgw 8080 `# Same as set with --gateway-port on the sender` \
--feeder-gateway-enable \
--warp-update-receiver \
--warp-update-shutdown-receiver `# Shuts down the receiver once the migration has completed`
ā Supported Features
Starknet compliant
Madara is compliant with the latest v0.13.2
version of Starknet and v0.7.1
JSON-RPC specs. You can find out more about this in the interactions
section or at the official Starknet JSON-RPC specs.
Feeder-Gateway State Synchronization
Madara supports its own implementation of the Starknet feeder gateway, which allows nodes to synchronize state from each other at much faster speeds than a regular sync.
[!NOTE] Starknet does not currently have a specification for its feeder-gateway protocol, so despite our best efforts at output parity, you might still notice some discrepancies between official feeder gateway endpoints and our own implementation. Please let us know about if you encounter this by raising an issue
State Commitment Computation
Madara supports merkelized state commitments through its own implementation of Besu Bonsai Merkle Tries. See the bonsai lib. You can read more about Starknet Block structure and how it affects state commitment here.
š¬ Get in touch
Contributing
For guidelines on how to contribute to Madara, please see the Contribution Guidelines.
Partnerships
To establish a partnership with the Madara team, or if you have any suggestions or special requests, feel free to reach us on Telegram.
License
Madara is open-source software licensed under the Apache-2.0 License.