Developer mode for the node #800
Replies: 3 comments 4 replies
-
|
In the current form of the miden node, it's quite easy to start a local Miden node and then connect the Rust client to it. Here's an example to show that its is quite simple. Generate the genesis file and initialize the data and accounts directories: miden-node store dump-genesis > genesis.toml
mkdir -p data accounts
miden-node bundled bootstrap \
--data-directory data \
--accounts-directory accounts \
--config genesis.tomlThen, start the node: miden-node bundled start \
--data-directory data \
--rpc.url http://0.0.0.0:57123Voila, the node is running locally :) This is how you instantiate the Rust client against this local node: let endpoint = Endpoint::new(
"http".to_string(),
"localhost".to_string(),
Some(57123),
);
let timeout_ms = 10_000;
let rpc_api = Arc::new(TonicRpcClient::new(&endpoint, timeout_ms));
let mut client = ClientBuilder::new()
.with_rpc(rpc_api)
.with_filesystem_keystore("./keystore")
.in_debug_mode(true)
.build()
.await?;Given how easy it is to run the node locally, I don't think there is actually too much left to be done to make the miden-node have a similar functionality as Anvil. Ideas for “testing mode” featuresIt would be beneficial to have the following features to in the miden-node's "testing mode":
However, to make the dev mode for the node work seamlessly in the test environment of miden-app it will also require a bit of coordination with the test harness @bitwalker is working on. Also the test harness should work with the rust client so that when developers are writing unit & integration tests, they don't have to completely rewrite logic for their production application. |
Beta Was this translation helpful? Give feedback.
-
My initial thoughts here were to only provide access via the CLI i.e. out-of-process. But it would probably make life easier if the node is directly controllable in the code. This would allow specifying account code in rust with components, injecting them into the genesis block etc, all without leaving rust. |
Beta Was this translation helpful? Give feedback.
-
|
Example node integration test // This is a test to ensure our open-telemetry trace spans are correct for a block build.
//
// More complexity might be required to test negatives aka error reporting, because those
// _should_ only occur when we have a bug. So we may have to corrupt the database or something
// to force such a condition as part of setup. Not dealing with that here though.
// Collects he OTel spans for this test.
let otel_collector = ..;
// Setup test conditions; create chain with enough state to be useful i.e. with a little bit of
// everything. Variety of accounts, notes, nullifiers and txs.
let chain = MockChain::builder()
.with_default_genesis()
.push_block(...)
.push_block(...)
.build()
.expect("blocks are valid")'
// Launch the node in manual mode.
let mut store = Store::builder()
.in_memory()
.with_otel_collector(otel_collector.clone())
,build();
// Inject the chain blocks into the node's store.
for block in chain {
// This is equivalent to gRPC call to store.apply_block.
store.apply_block(block).unwrap();
}
// Create the block-producer in manual mode aka no automatic block-production.
// This is to make the test more deterministic.
let mut bp = BlockProducer::builder()
.manual_mode()
.with_store(store.grpc_endpoint())
.with_otel_collector(otel_collector.clone())
.build()
.unwrap();
// Create the block we want to test.
// This also requires knowing the batches etc as well.
// I don't believe this exists at the moment.
let txs = chain... // Somehow create them using the chain.
// Insert into mempool.
for tx in txs {
// Equivalent to the grpc method.
bp.add_tx(tx).unwrap();
}
// Create the batches.
let (batch_0, batch_1) = txs.split_at(5);
let batch_id_0 = bp.add_batch(batch_0.map(Transaction::id)).unwrap();
let batch_id_1 = bp.add_batch(batch_1.map(Transaction::id)).unwrap();
// Create block (actual test bit)
// Drain all spans until now since they're not part of
// this test.
otel_collector.flush();
bp.create_block(vec![batch_id_0, batch_id_1]).unwrap();
let spans = otel_collector.flush().as_json();
// Expected output, retrieved as a snapshot.
let expected = insta!(...);
assert_eq!(spans, expected); |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Block and batch production is currently automatic, every
Mseconds a batch build is triggered, and everyNa block.This makes it difficult to get the chain into a specific state since batches and blocks are somewhat random. It would be useful for integration tests, demonstrations and test tooling for builders if this was more controllable.
I propose an additional manual
block-producermode. When launched in this mode, the block-producer does not spin up batch and block producer tasks, but instead launches a server to accept commands from.The first concrete step of this issue should be a API design, but I imagine we could start with a simple
/build_batchand/build_block. Maybe we want to allow specifying number of transactions/batches to select, or even which ones to include.It would also be ideal if the user of this API did not need to know about its specifics, and could instead use CLI to control it. This should be described in the initial design proposal.
After some discussion with @sergerad, it sounds like we should consider something a bit more extensive in a similar vein to foundry's anvil for ethereum development.
This could include support for
I'm thinking we could provide a cohesive crate API which would be used by
anvil(could also be part of the node binary if we choose)which ensures that the same underlying code is used by both the formal node and the tooling around it.
This could cover use cases like:
I'd appreciate input on what flows would be nice to have from a dx / user perspective. I don't have enough experience with foundry etc to understand potential issues and desires here.
In my mind the main difference in execution is that the dev-node would always operate sequentially in order to be repeatable.
Beta Was this translation helpful? Give feedback.
All reactions