Skip to content

feat: upgrade to protocol 0.17.0-rc.3 - #2530

Open
sofiazcoaga wants to merge 13 commits into
nextfrom
update-protocol-0.17-rc
Open

feat: upgrade to protocol 0.17.0-rc.3#2530
sofiazcoaga wants to merge 13 commits into
nextfrom
update-protocol-0.17-rc

Conversation

@sofiazcoaga

@sofiazcoaga sofiazcoaga commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Dependencies changes

  • Protocol crates to 0.17.0-rc.3 and VM crates to 0.32.
  • miden-debug to 0.15.
  • miden-node-proto-build to be pinned to d4062e64.

About Protocol Config

The block header no longer carries the transaction kernel commitment or the fee faucet. It carries a commitment to a ProtocolConfig holding both, plus the batch and block kernels and the proof verification policy. Execution and note screening need those values, and a commitment is one way, so the client has to be given the configuration and keep it.
Added:

  • New protocol_config module with Client::add_protocol_config, get_protocol_config and ClientBuilder::protocol_config. DataStore::get_transaction_inputs returns the configuration alongside the header.
  • Configurations are stored in the settings table, keyed by their commitment, so several can be held at once. A transaction selects the one its reference block names, which is what lets a protocol upgrade happen without a cutover.

@bitwalker

Copy link
Copy Markdown
Collaborator

You'll want to update to 0.17.0-rc.4

@igamigo

igamigo commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

You'll want to update to 0.17.0-rc.4

Yeah, we were tracking this. AFAIK it should not be too much extra work. The main reason why we need the 0.17 RC is to be able to implement the canonical objects work which is already merged, and also the allowlist changes that are coming to the node.
Was this about the type signature changes?

@sofiazcoaga
sofiazcoaga force-pushed the update-protocol-0.17-rc branch from eca2348 to 10f0223 Compare September 11, 2026 13:57

@juan518munoz juan518munoz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I'll do a second review round later today.

I only have one question about how we are storing the protocol config, as far as I understand the only thing this struct takes is the faucet ID, so why don't we just store the hex representation in a plain form instead of the serialization of the struct?

Comment on lines +203 to +207
let fee_faucet_id = client
.get_protocol_config(genesis.protocol_config_commitment())
.await?
.fee_asset_id()
.faucet_id();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do this in four different parts of the codebase, maybe we could abstract it into a helper?

Comment on lines +63 to +67
if let Some(path) = std::env::var_os("MIDEN_PROTOCOL_CONFIG") {
let bytes = std::fs::read(path)?;
let config = ProtocolConfig::read_from_bytes(&bytes)?;
client.add_protocol_config(config).await?;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like with integration test, should we fallback to the .bin config file as well?

Comment on lines +631 to 635
let account_component = AccountComponent::from_package(package.clone(), &init_data)
.map_err(|e| {
CliError::Account(
e,
format!("error instantiating component from Package {}", package.name),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: if we get the package.name beforehand we can avoid cloning the whole package:

Suggested change
let account_component = AccountComponent::from_package(package.clone(), &init_data)
.map_err(|e| {
CliError::Account(
e,
format!("error instantiating component from Package {}", package.name),
let package_name = package.name.clone();
let account_component = AccountComponent::from_package(package, &init_data)
.map_err(|e| {
CliError::Account(
e,
format!("error instantiating component from Package {}", package_name),

// The `account-id` core type as the compiler records it: a named record of two field elements.
// Its name is what the CLI's `account-id` codec matches against.
let account_id = Type::Struct(Arc::new(StructType::named(
let account_id = Type::Struct(midenc_hir_type::StructRef::Plain(Arc::new(StructType::named(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the import upwards to:

use midenc_hir_type::{CallConv, FunctionType, StructType, Type};

effective_from: config.effective_from().as_u32(),
protocol_config: Some(config.protocol_config().into()),
}
}),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can implement From for validator config and next protocol config for clarity:

// VALIDATOR CONFIG
// ================================================================================================

impl From<&ValidatorConfig> for proto::blockchain::ValidatorConfig {
    fn from(config: &ValidatorConfig) -> Self {
        Self {
            keys: config
                .keys()
                .iter()
                .map(|key| proto::blockchain::ValidatorPublicKey { validator_key: key.to_bytes() })
                .collect(),
            quorum: config.quorum().into(),
        }
    }
}

// NEXT PROTOCOL CONFIG
// ================================================================================================

impl From<&NextProtocolConfig> for proto::blockchain::NextProtocolConfig {
    fn from(config: &NextProtocolConfig) -> Self {
        Self {
            effective_from: config.effective_from().as_u32(),
            protocol_config: Some(config.protocol_config().into()),
        }
    }
}

.await?;
```

## Protocol configuration

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add to this section how to set up the config deriving it from the native faucet id?

A network that runs the standard protocol parameters needs only one network value: the account ID of the native fee faucet. This ID is a public network parameter. The operator publishes it together with the network endpoints:

```rust
use miden_client::account::AccountId;
use miden_client::asset::AssetId;
use miden_client::protocol_config::ProtocolConfig;

let fee_faucet_id = AccountId::from_hex("0x...")?;
let config = ProtocolConfig::current(AssetId::new_fungible(fee_faucet_id))?;
client.add_protocol_config(config).await?;
`` `

Comment thread CHANGELOG.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entries need to carry the PR they are related with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants