Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Added chain tip to the block producer status ([#1419](https://github.com/0xMiden/miden-node/pull/1419)).
- The mempool's transaction capacity is now configurable ([#1433](https://github.com/0xMiden/miden-node/pull/1433)).
- Renamed card's names in the `miden-network-monitor` binary ([#1441](https://github.com/0xMiden/miden-node/pull/1441)).
- Integrated RPC stack with Validator component for transaction validation ([#1457](https://github.com/0xMiden/miden-node/pull/1457)).

### Changes

Expand Down
15 changes: 8 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions bin/network-monitor/src/counter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
use anyhow::{Context, Result};
use miden_lib::AuthScheme;
use miden_lib::account::interface::AccountInterface;
use miden_lib::utils::ScriptBuilder;
use miden_lib::utils::CodeBuilder;
use miden_node_proto::clients::RpcClient;
use miden_node_proto::generated::rpc::BlockHeaderByNumberRequest;
use miden_node_proto::generated::transaction::ProvenTransaction;
Expand Down Expand Up @@ -528,7 +528,7 @@ async fn create_and_submit_network_note(
fn create_increment_script() -> Result<(NoteScript, Library)> {
let library = get_counter_library()?;

let script_builder = ScriptBuilder::new(true)
let script_builder = CodeBuilder::new(true)
.with_dynamically_linked_library(&library)
.context("Failed to create script builder with library")?;

Expand Down
20 changes: 14 additions & 6 deletions bin/network-monitor/src/deploy/counter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Counter program account creation functionality.

use std::path::Path;
use std::sync::Arc;

use anyhow::Result;
use miden_lib::testing::account_component::IncrNonceAuthComponent;
Expand All @@ -16,6 +17,7 @@ use miden_objects::account::{
StorageSlot,
StorageSlotName,
};
use miden_objects::assembly::{DefaultSourceManager, LibraryPath, Module, ModuleKind};
use miden_objects::utils::sync::LazyLock;
use miden_objects::{Felt, FieldElement, Word};
use tracing::instrument;
Expand Down Expand Up @@ -50,12 +52,18 @@ pub fn create_counter_account(owner_account_id: AccountId) -> Result<Account> {

let counter_slot = StorageSlot::with_value(COUNTER_SLOT_NAME.clone(), Word::empty());

let account_code = AccountComponent::compile(
script,
TransactionKernel::assembler(),
vec![counter_slot, owner_id_slot],
)?
.with_supports_all_types();
let assembler = TransactionKernel::assembler();
let source_manager = Arc::new(DefaultSourceManager::default());
let library_path = LibraryPath::new("counter::program")?;
let module = Module::parser(ModuleKind::Library)
.parse_str(library_path, script, &source_manager)
.map_err(|e| anyhow::anyhow!("Failed to parse module: {e}"))?;
let library = assembler
.assemble_library([module])
.map_err(|e| anyhow::anyhow!("Failed to assemble library: {e}"))?;

let account_code = AccountComponent::new(library, vec![counter_slot, owner_id_slot])?
.with_supports_all_types();

let incr_nonce_auth: AccountComponent = IncrNonceAuthComponent.into();

Expand Down
3 changes: 3 additions & 0 deletions bin/node/src/commands/bundled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,13 @@ impl BundledCommand {
.context("Failed to parse URL")?;
let block_producer_url = Url::parse(&format!("http://{block_producer_address}"))
.context("Failed to parse URL")?;
let validator_url = Url::parse(&format!("http://{validator_address}"))
.context("Failed to parse URL")?;
Rpc {
listener: grpc_rpc,
store_url,
block_producer_url: Some(block_producer_url),
validator_url,
grpc_timeout,
}
.serve()
Expand Down
8 changes: 7 additions & 1 deletion bin/node/src/commands/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden_node_rpc::Rpc;
use miden_node_utils::grpc::UrlExt;
use url::Url;

use super::{ENV_BLOCK_PRODUCER_URL, ENV_RPC_URL, ENV_STORE_RPC_URL};
use super::{ENV_BLOCK_PRODUCER_URL, ENV_RPC_URL, ENV_STORE_RPC_URL, ENV_VALIDATOR_URL};
use crate::commands::{DEFAULT_TIMEOUT, ENV_ENABLE_OTEL, duration_to_human_readable_string};

#[derive(clap::Subcommand)]
Expand All @@ -25,6 +25,10 @@ pub enum RpcCommand {
#[arg(long = "block-producer.url", env = ENV_BLOCK_PRODUCER_URL, value_name = "URL")]
block_producer_url: Option<Url>,

/// The validator's gRPC url.
#[arg(long = "validator.url", env = ENV_VALIDATOR_URL, value_name = "URL")]
validator_url: Url,

/// Enables the exporting of traces for OpenTelemetry.
///
/// This can be further configured using environment variables as defined in the official
Expand All @@ -51,6 +55,7 @@ impl RpcCommand {
url,
store_url,
block_producer_url,
validator_url,
enable_otel: _,
grpc_timeout,
} = self;
Expand All @@ -64,6 +69,7 @@ impl RpcCommand {
listener,
store_url,
block_producer_url,
validator_url,
grpc_timeout,
}
.serve()
Expand Down
8 changes: 3 additions & 5 deletions bin/stress-test/src/seeding/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,13 +443,11 @@ fn create_emit_note_tx(
) -> ProvenTransaction {
let initial_account_hash = faucet.commitment();

let slot = faucet.storage().get_item(BasicFungibleFaucet::metadata_slot_name()).unwrap();
let metadata_slot_name = AccountStorage::faucet_sysdata_slot();
let slot = faucet.storage().get_item(metadata_slot_name).unwrap();
faucet
.storage_mut()
.set_item(
AccountStorage::faucet_metadata_slot(),
[slot[0], slot[1], slot[2], slot[3] + Felt::new(10)].into(),
)
.set_item(metadata_slot_name, [slot[0], slot[1], slot[2], slot[3] + Felt::new(10)].into())
.unwrap();

faucet.increment_nonce(ONE).unwrap();
Expand Down
20 changes: 10 additions & 10 deletions crates/proto/src/domain/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use miden_objects::account::{
AccountId,
AccountStorageHeader,
StorageMap,
StorageSlotHeader,
StorageSlotName,
StorageSlotType,
};
use miden_objects::asset::{Asset, AssetVault};
use miden_objects::block::{AccountWitness, BlockNumber};
use miden_objects::block::BlockNumber;
use miden_objects::block::account_tree::AccountWitness;
use miden_objects::crypto::merkle::SparseMerklePath;
use miden_objects::note::{NoteExecutionMode, NoteTag};
use miden_objects::utils::{Deserializable, DeserializationError, Serializable};
Expand Down Expand Up @@ -167,18 +169,18 @@ impl TryFrom<proto::account::AccountStorageHeader> for AccountStorageHeader {
fn try_from(value: proto::account::AccountStorageHeader) -> Result<Self, Self::Error> {
let proto::account::AccountStorageHeader { slots } = value;

let items = slots
let slot_headers = slots
.into_iter()
.map(|slot| {
let slot_name = StorageSlotName::new(slot.slot_name)?;
let slot_type = storage_slot_type_from_raw(slot.slot_type)?;
let commitment =
slot.commitment.ok_or(ConversionError::NotAValidFelt)?.try_into()?;
Ok((slot_name, slot_type, commitment))
Ok(StorageSlotHeader::new(slot_name, slot_type, commitment))
})
.collect::<Result<Vec<_>, ConversionError>>()?;

Ok(AccountStorageHeader::new(items)?)
Ok(AccountStorageHeader::new(slot_headers)?)
}
}

Expand Down Expand Up @@ -333,12 +335,10 @@ impl From<AccountStorageHeader> for proto::account::AccountStorageHeader {
fn from(value: AccountStorageHeader) -> Self {
let slots = value
.slots()
.map(|(slot_name, slot_type, slot_value)| {
proto::account::account_storage_header::StorageSlot {
slot_name: slot_name.to_string(),
slot_type: storage_slot_type_to_raw(*slot_type),
commitment: Some(proto::primitives::Digest::from(*slot_value)),
}
.map(|slot_header| proto::account::account_storage_header::StorageSlot {
slot_name: slot_header.name().to_string(),
slot_type: storage_slot_type_to_raw(slot_header.slot_type()),
commitment: Some(proto::primitives::Digest::from(slot_header.value())),
})
.collect();

Expand Down
9 changes: 2 additions & 7 deletions crates/proto/src/domain/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ use std::collections::BTreeMap;
use std::ops::RangeInclusive;

use miden_objects::account::AccountId;
use miden_objects::block::{
BlockHeader,
BlockInputs,
BlockNumber,
FeeParameters,
NullifierWitness,
};
use miden_objects::block::nullifier_tree::NullifierWitness;
use miden_objects::block::{BlockHeader, BlockInputs, BlockNumber, FeeParameters};
use miden_objects::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature};
use miden_objects::note::{NoteId, NoteInclusionProof};
use miden_objects::transaction::PartialBlockchain;
Expand Down
37 changes: 29 additions & 8 deletions crates/rpc/src/server/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::Arc;
use std::time::Duration;

use anyhow::Context;
use miden_node_proto::clients::{BlockProducerClient, Builder, StoreRpcClient};
use miden_node_proto::clients::{BlockProducerClient, Builder, StoreRpcClient, ValidatorClient};
use miden_node_proto::errors::ConversionError;
use miden_node_proto::generated::rpc::MempoolStats;
use miden_node_proto::generated::rpc::api_server::{self, Api};
Expand Down Expand Up @@ -34,19 +34,19 @@ use tracing::{debug, info, instrument, warn};
use url::Url;

use crate::COMPONENT;
use crate::server::validator;

// RPC SERVICE
// ================================================================================================

pub struct RpcService {
store: StoreRpcClient,
block_producer: Option<BlockProducerClient>,
validator: ValidatorClient,
genesis_commitment: Option<Word>,
}

impl RpcService {
pub(super) fn new(store_url: Url, block_producer_url: Option<Url>) -> Self {
pub(super) fn new(store_url: Url, block_producer_url: Option<Url>, validator_url: Url) -> Self {
let store = {
info!(target: COMPONENT, store_endpoint = %store_url, "Initializing store client");
Builder::new(store_url)
Expand All @@ -73,9 +73,25 @@ impl RpcService {
.connect_lazy::<BlockProducerClient>()
});

let validator = {
info!(
target: COMPONENT,
validator_endpoint = %validator_url,
"Initializing validator client",
);
Builder::new(validator_url)
.without_tls()
.without_timeout()
.without_metadata_version()
.without_metadata_genesis()
.with_otel_context_injection()
.connect_lazy::<ValidatorClient>()
};

Self {
store,
block_producer,
validator,
genesis_commitment: None,
}
}
Expand Down Expand Up @@ -384,21 +400,26 @@ impl api_server::Api for RpcService {
let tx_inputs = TransactionInputs::read_from_bytes(tx_inputs_bytes).map_err(|err| {
Status::invalid_argument(err.as_report_context("Invalid transaction inputs"))
})?;
// Re-execute the transaction.
match validator::re_execute_transaction(tx_inputs).await {
Ok(_executed_tx) => {
// Re-execute the transaction via the Validator.
let validator_request = proto::transaction::ProvenTransaction {
transaction: tx.to_bytes(),
transaction_inputs: Some(tx_inputs.to_bytes()),
};

match self.validator.clone().submit_proven_transaction(validator_request).await {
Ok(_) => {
debug!(
target = COMPONENT,
tx_id = %tx.id().to_hex(),
"Transaction re-execution successful"
"Transaction validation successful"
);
},
Err(e) => {
warn!(
target = COMPONENT,
tx_id = %tx.id().to_hex(),
error = %e,
"Transaction re-execution failed, but continuing with submission"
"Transaction validation failed, but continuing with submission"
);
},
}
Expand Down
8 changes: 6 additions & 2 deletions crates/rpc/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use crate::server::health::HealthCheckLayer;
mod accept;
mod api;
mod health;
mod validator;

/// The RPC server component.
///
Expand All @@ -32,6 +31,7 @@ pub struct Rpc {
pub listener: TcpListener,
pub store_url: Url,
pub block_producer_url: Option<Url>,
pub validator_url: Url,
/// Server-side timeout for an individual gRPC request.
///
/// If the handler takes longer than this duration, the server cancels the call.
Expand All @@ -44,7 +44,11 @@ impl Rpc {
/// Note: Executes in place (i.e. not spawned) and will run indefinitely until
/// a fatal error is encountered.
pub async fn serve(self) -> anyhow::Result<()> {
let mut api = api::RpcService::new(self.store_url.clone(), self.block_producer_url.clone());
let mut api = api::RpcService::new(
self.store_url.clone(),
self.block_producer_url.clone(),
self.validator_url,
);

let genesis = api
.get_genesis_header_with_retry()
Expand Down
Loading