0xMiden / 0xMiden/protocol

bug(multisig): adding a signer to a 1-of-1 account fails STARK verification

Abierto
#3,113 14 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Rust
Estrellas
132
Forks
167
Merge medio
1 d 23 h
PR fusionados (30 d)
110

Descripción

### Packages versions

miden-protocol = "0.15.3"
miden-standards = "=0.15.3"
miden-tx = "0.15.3"
miden-node-proto ="0.15.0"
miden-testing = "0.15.3"
miden-client = "0.15.0"
miden-client-sqlite-store = "0.15.0"

### Bug description

## Summary

`update_signers_and_threshold` produces a STARK-invalid proof when adding a
signer to a single-signer multisig (a 1-of-1 account). The transaction
executes fine, but proving/verifying it fails with:

constraint mismatch: quotient * vanishing != folded constraints

This affects both the standard (`auth::multisig`) and smart
(`auth::multisig_smart`) multisig auth components.

## Root cause

After `update_signers_and_threshold` rotates the signer set, it
unconditionally calls `cleanup_pubkey_and_scheme_id_mapping` to clear any
approver slots that are no longer used. When the approver map holds exactly
one entry (e.g. adding a signer to a 1-of-1 multisig), the proc's internal
loop guard already short-circuits and the body never runs - nothing is
cleared. However, *entering* the proc at all perturbs the prover trace enough
to fail node-side STARK verification.

The cleanup only ever has work to do when the signer set shrinks
(`init_num_of_approvers > new_num_of_approvers`). Add-signer and
threshold-only updates should skip it entirely.


## Proposed fix

Gate the cleanup call on the signer set actually shrinking
(`init_num_of_approvers > new_num_of_approvers`) in both:

- `crates/miden-standards/asm/standards/auth/multisig.masm`
- `crates/miden-standards/asm/standards/auth/multisig_smart/mod.masm`

Add-signer and threshold-only updates skip the call; remove-signer behavior is
unchanged.

Add regression tests that grow a 1-of-1 multisig to 2 signers and verify a
real STARK proof, for both the standard and smart variants.

### How can this be reproduced?

1. Create a 1-of-1 multisig account.
2. Execute `update_signers_and_threshold` to grow the signer set to 2
(threshold 2), signed by the single existing approver.
3. Generate and verify a real STARK proof for the transaction (e.g.
`prove_and_verify_transaction`).

The proof fails verification with `constraint mismatch: quotient * vanishing
!= folded constraints`. Note that a dummy block proof
(`MockChain::add_pending_executed_transaction` + `prove_next_block`) uses
`prove_dummy` and does **not** exercise this path, so the bug is invisible
there - it only surfaces under real transaction proving.

### Relevant log output

```shell
Invalid proof for transaction 0x7c212267a3f17a17dbfd431272a7516e5eb11663f0064217509c6e58e2fd2341: failed to verify transaction\ncaused by: failed to verify STARK proof for program with hash0xcdd0a81d45597a6099f138fc997d0a3f886e9553d819063559afe0cdfbe2a5d2\ncaused by: constraint mismatch: quotient * vanishing != folded constraints"
```

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.