Skip to content

Commit 8eebf8a

Browse files
committed
Merge branch 'next' of github.com:0xMiden/miden-node into sergerad-multi-validator
2 parents c64d937 + 317069e commit 8eebf8a

23 files changed

Lines changed: 558 additions & 190 deletions

File tree

.github/workflows/publish-crates.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: Publish crates
22

33
permissions:
44
contents: read
5+
id-token: write
56

67
on:
78
release:
@@ -26,7 +27,7 @@ jobs:
2627
name: Cargo publish release
2728
runs-on: warp-ubuntu-latest-x64-8x
2829
if: ${{ github.repository_owner == '0xMiden' }}
29-
environment: publish-crates
30+
environment: release
3031
steps:
3132
- name: Validate release tag
3233
run: |
@@ -61,9 +62,13 @@ jobs:
6162
- name: Rustup
6263
run: rustup toolchain install --no-self-update
6364

65+
- name: Authenticate with crates.io
66+
id: auth
67+
uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
68+
6469
- name: Publish unpublished crates
6570
env:
66-
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
71+
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
6772
run: |
6873
set -euo pipefail
6974

Cargo.lock

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ license = "MIT"
3131
readme = "README.md"
3232
repository = "https://github.com/0xMiden/node"
3333
rust-version = "1.96.1"
34-
version = "0.16.0-alpha.1"
34+
version = "0.16.0-alpha.2"
3535

3636
# Optimize the cryptography for faster tests involving account creation.
3737
[profile.test.package.miden-crypto]
@@ -42,16 +42,16 @@ debug = true
4242

4343
[workspace.dependencies]
4444
# Workspace crates.
45-
miden-node-block-producer = { path = "crates/block-producer", version = "0.16.0-alpha.1" }
46-
miden-node-db = { path = "crates/db", version = "0.16.0-alpha.1" }
47-
miden-node-grpc-error-macro = { path = "crates/grpc-error-macro", version = "0.16.0-alpha.1" }
48-
miden-node-proto = { path = "crates/proto", version = "0.16.0-alpha.1" }
49-
miden-node-proto-build = { path = "proto", version = "0.16.0-alpha.1" }
50-
miden-node-rpc = { path = "crates/rpc", version = "0.16.0-alpha.1" }
51-
miden-node-store = { path = "crates/store", version = "0.16.0-alpha.1" }
45+
miden-node-block-producer = { path = "crates/block-producer", version = "0.16.0-alpha.2" }
46+
miden-node-db = { path = "crates/db", version = "0.16.0-alpha.2" }
47+
miden-node-grpc-error-macro = { path = "crates/grpc-error-macro", version = "0.16.0-alpha.2" }
48+
miden-node-proto = { path = "crates/proto", version = "0.16.0-alpha.2" }
49+
miden-node-proto-build = { path = "proto", version = "0.16.0-alpha.2" }
50+
miden-node-rpc = { path = "crates/rpc", version = "0.16.0-alpha.2" }
51+
miden-node-store = { path = "crates/store", version = "0.16.0-alpha.2" }
5252
miden-node-test-macro = { path = "crates/test-macro" }
53-
miden-node-tracing-macro = { path = "crates/tracing-macro", version = "0.16.0-alpha.1" }
54-
miden-node-utils = { path = "crates/utils", version = "0.16.0-alpha.1" }
53+
miden-node-tracing-macro = { path = "crates/tracing-macro", version = "0.16.0-alpha.2" }
54+
miden-node-utils = { path = "crates/utils", version = "0.16.0-alpha.2" }
5555

5656
# miden-protocol dependencies. These should be updated in sync.
5757
miden-block-prover = { version = "=0.16.0-alpha.2" }

bin/network-monitor/src/assets/wallet_counter_program.masm

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
1-
# Wallet self-counter component for the network monitor.
1+
# Wallet self-counter + note-creation component for the network monitor.
22
#
3-
# The wallet increments this counter in the same transaction that emits an increment note to the
4-
# counter account, so the slot is an on-chain, atomically-committed count of *committed* increment
5-
# requests (the authoritative `expected` value). Unlike the counter contract, no note-sender
6-
# authorization is needed: the wallet increments its own storage from its own (signed) transaction.
3+
# A single account procedure atomically (a) creates the increment network note and (b) bumps the
4+
# wallet's own counter slot. Because both effects happen in one account procedure, a transaction can
5+
# never do one without the other, so the emitted note and the authoritative `expected` counter can
6+
# never diverge.
77
#
88
# Storage layout:
99
# - COUNTER_SLOT: counter value (u64)
1010

1111
use miden::core::sys
1212
use miden::protocol::active_account
1313
use miden::protocol::native_account
14+
use miden::protocol::output_note
1415

1516
const COUNTER_SLOT = word("miden::monitor::wallet_contract::counter")
1617

17-
# Increment the wallet's own counter slot.
18-
# => []
18+
# Create the increment network note and bump the wallet's own counter slot, atomically.
19+
#
20+
# Inputs: [tag, note_type, RECIPIENT, pad(10)]
21+
# Outputs: [note_idx, pad(15)]
22+
#
23+
# Invocation: call
1924
@account_procedure
20-
pub proc increment
25+
pub proc increment_and_create_note
26+
# Create the output note. `output_note::create` is only callable from the account context, so it
27+
# must run here inside an account procedure.
28+
exec.output_note::create
29+
# => [note_idx, pad(15)]
30+
31+
# Bump the wallet's own counter slot. These ops are self-contained and leave note_idx on top.
2132
push.COUNTER_SLOT[0..2] exec.active_account::get_item
22-
# => [count, 0, 0, 0]
33+
# => [count, 0, 0, 0, note_idx, pad(...)]
2334

2435
push.1 add
25-
# => [count+1, 0, 0, 0]
36+
# => [count+1, 0, 0, 0, note_idx, pad(...)]
2637

2738
push.COUNTER_SLOT[0..2] exec.native_account::set_item
28-
# => [OLD_VALUE]
39+
# => [OLD_VALUE, note_idx, pad(...)]
2940

3041
dropw
31-
# => []
42+
# => [note_idx, pad(15)]
3243
end
3344

3445
# Read the wallet's own counter slot (no auth required).

bin/network-monitor/src/counter.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,65 +1114,77 @@ pub(crate) fn create_increment_script() -> Result<NoteScript> {
11141114

11151115
/// Build the transaction script for one increment.
11161116
///
1117-
/// The script does two things atomically in the wallet's transaction:
1118-
/// 1. `call`s the wallet's own `increment` procedure, bumping the wallet's on-chain counter slot
1119-
/// 2. Emits the network note that targets the counter account (the `observed` value).
1117+
/// The whole transaction is a single `call` into the wallet's `increment_and_create_note` account
1118+
/// procedure, which atomically (1) creates the network note targeting the counter account (the
1119+
/// `observed` value) and (2) bumps the wallet's own on-chain counter slot (the authoritative
1120+
/// `expected` value).
11201121
///
1121-
/// The note-emission section mirrors `miden_standards`' `build_send_notes_script` for an
1122-
/// asset-less note with attachments; it is not reused directly because that builder produces a
1123-
/// complete, non-composable script. Keep it in sync with `miden-standards` on version bumps; the
1124-
/// `wallet_self_increment_tx` test exercises it end-to-end.
1122+
/// The note attachments (the `NetworkAccountTarget`) are added afterwards with
1123+
/// `output_note::add_attachment`, which is not account-restricted, mirroring `miden_standards`'
1124+
/// `SendNotesTransactionScript`. The `wallet_self_increment_tx` test exercises this end-to-end.
11251125
fn create_increment_tx_script(network_note: &Note) -> Result<TransactionScript> {
1126-
let wallet_program = include_str!(concat!(
1127-
env!("CARGO_MANIFEST_DIR"),
1128-
"/src/assets/wallet_counter_program.masm"
1129-
));
1126+
let wallet_component = crate::deploy::wallet::wallet_counter_component_code()
1127+
.context("failed to compile wallet counter component code")?;
11301128

11311129
let partial: PartialNote = network_note.clone().into();
11321130
let recipient = partial.recipient_digest();
11331131
let note_type = Felt::from(partial.metadata().note_type());
11341132
let tag = Felt::from(partial.metadata().tag());
11351133

1134+
// The wallet's own account procedure creates the note *and* bumps the counter atomically, so
1135+
// the whole transaction is a single `call` into the wallet component.
1136+
// `increment_and_create_note` shares `create_note`'s stack contract: it consumes `[tag,
1137+
// note_type, RECIPIENT, pad(10)]` and returns `[note_idx, pad(15)]`. We build the padded input
1138+
// explicitly and reduce the trailing pads back to `[note_idx]`, otherwise the extra pads
1139+
// survive on the overflow stack and `main` returns with the wrong depth ("stack depth must be
1140+
// 16, but was 21").
1141+
let increment_and_create_note = format!(
1142+
"::{}::increment_and_create_note",
1143+
crate::deploy::wallet::WALLET_COUNTER_COMPONENT_PATH
1144+
);
11361145
let mut note_section = format!(
11371146
"
1147+
padw padw push.0.0
11381148
push.{recipient}
11391149
push.{note_type}
11401150
push.{tag}
1141-
# => [tag, note_type, RECIPIENT, pad(16)]
1142-
exec.::miden::protocol::output_note::create
1143-
# => [note_idx, pad(16)]
1151+
# => [tag, note_type, RECIPIENT, pad(10)]
1152+
call.{increment_and_create_note}
1153+
# => [note_idx, pad(15)]
1154+
movdn.15 dropw dropw dropw drop drop drop
1155+
# => [note_idx]
11441156
"
11451157
);
11461158
for attachment in partial.attachments().iter() {
11471159
let scheme = attachment.attachment_scheme().as_u16();
11481160
let commitment = attachment.content().to_commitment();
1161+
// `add_attachment` consumes `[attachment_scheme, ATTACHMENT_COMMITMENT, note_idx]`, so dup
1162+
// the note index for it to consume and keep our own copy for the next attachment / drop.
11491163
write!(
11501164
note_section,
11511165
"
11521166
dup
11531167
push.{commitment}
11541168
push.{scheme}
1169+
# => [attachment_scheme, ATTACHMENT_COMMITMENT, note_idx, note_idx]
11551170
exec.::miden::protocol::output_note::add_attachment
1156-
# => [note_idx, pad(16)]
1171+
# => [note_idx]
11571172
"
11581173
)
11591174
.expect("writing to a String cannot fail");
11601175
}
11611176
note_section.push_str(" drop\n");
11621177

11631178
let script_src = format!(
1164-
"use external_contract::wallet_counter
1165-
1166-
@transaction_script
1179+
"@transaction_script
11671180
pub proc main
1168-
call.wallet_counter::increment
11691181
{note_section}
11701182
end"
11711183
);
11721184

11731185
let mut code_builder = CodeBuilder::new()
1174-
.with_linked_module("external_contract::wallet_counter", wallet_program)
1175-
.context("Failed to link wallet counter module")?;
1186+
.with_dynamically_linked_library(&wallet_component)
1187+
.context("Failed to dynamically link wallet counter component")?;
11761188

11771189
// The note's attachments (e.g. the network-account target) are resolved at runtime from the
11781190
// advice map keyed by their commitment, matching `build_send_notes_script`.

0 commit comments

Comments
 (0)