docs: mimd-0024 low-level design docs - #192
Conversation
📝 WalkthroughWalkthroughThis change adds a DLP v2 implementation document. The document defines the permission model, domain-separated hashes, PDA accounts, public enums, and public structs. It specifies commitment, state-buffer, challenge, dispute, payout, and finalization state. It also defines bootstrap and runtime instructions and their input schemas. The document adds validation rules, failure handling, lifecycle examples, actor responsibilities, FAQ items, and unresolved design points. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mimd-0025-impl.md`:
- Around line 625-626: Update the FinalizeCommitment happy-path rule wording by
replacing “requires closed window” with “requires the window to be closed,”
while preserving the other listed requirements unchanged.
- Around line 164-169: Validate verifier configuration before activation: ensure
the eligible verifier population, excluding the operator, is at least
selected_verifier_count, and require approval_threshold to be greater than zero
and no greater than selected_verifier_count. Add these checks to the activation
validation flow and reject invalid commitments before they enter Active.
- Around line 503-504: Update ProtocolConfig or the protocol’s immutable
configuration to define the configured withdrawal delay, then make WithdrawStake
enforce that delay using each bond’s withdraw_requested_slot before allowing
either operator or verifier stake withdrawal. Ensure RequestStakeWithdrawal
records the request slot consistently for both bond types and preserve existing
lock and slashing checks.
- Around line 232-235: Define explicit maximum sizes for
VerifierRegistry.entries, PendingCommitment.selected_verifiers, approval_bitmap,
and StateBuffer.data before implementing account storage. Document and enforce
allocation and reallocation rules, reject oversize inputs deterministically, and
ensure registry growth cannot exceed the account limits; use a bounded or
Merkleized/paged representation where the Vec cannot safely be bounded.
- Line 507: Update the CancelUnactivatedCommitment design and related
PendingCommitment/ProtocolConfig definitions to include a configured VRF
callback timeout and a per-commitment deadline snapshot. Ensure
CancelUnactivatedReason::VrfTimeout validates the current slot against that
stored deadline rather than relying on posted_slot alone, and document the
required configuration/account data wherever the commitment lifecycle is
specified.
- Around line 168-169: Update PendingCommitment to persist an explicit extension
counter rather than using challenge_window_id. In ExtendChallengeWindow,
atomically increment the counter and reject the request once
max_window_extensions is reached, while preserving the configured limit’s
behavior and updating any related serialization or initialization paths.
- Around line 185-198: Make commitment-local operator locking consistent across
all terminal paths: either add the operator bond account and exact locked amount
to PendingCommitment and CancelUnactivatedCommitment so every release updates
OperatorBond.locked_lamports, including multiple commitments and disputes, or
remove the commitment-local locking introduced by PostCommitment entirely.
Ensure each terminal path releases exactly its own unspent lock without
affecting other commitments.
- Line 517: Align the FinalizeCommitment specification with the process_finalize
handler’s account contract: document validator signer, delegated/committed/state
accounts, delegation metadata, and validator fees vault, and define how the
legacy commit state/account maps to PendingCommitment. Alternatively, update
process_finalize to enforce only the accounts listed by FinalizeCommitment,
keeping validation and finalization behavior consistent across the table and
handler.
- Around line 525-532: Update the PostCommitmentData shape so er_slot is either
actually carried into the commitment state used by
PendingCommitment/state_commitment_hash, or removed if it is not part of the
committed data. Use the existing FullStateBuffer::state_slot input as the source
of truth if the slot must be preserved, and keep PostCommitment,
PendingCommitment, and state_commitment_hash aligned so no field exists only in
PostCommitmentData.
- Around line 147-171: Update PendingCommitment and its creation path to
snapshot every protocol configuration value later read by lifecycle
instructions, including resolver, protocol_fee_vault, match_penalty_bps, and
max_window_extensions, alongside the existing approval_threshold and registry
revision. Ensure ResolveDispute, payout/penalty handling, and extension handling
use the commitment’s stored values so UpdateProtocolConfig cannot alter
already-committed transactions; alternatively, explicitly document each
intentionally dynamic field.
- Around line 619-624: Update the `ChallengerReveal` and `ResolveDispute` spec
text to separate the truly terminal outcomes (invalid hash and matching state)
from the timeout-driven mismatch path; use `AwaitingDisputeResolution` to
describe the post-`MarkOperatorTimeout` state where a valid reveal can proceed.
Make it explicit that, after `MarkOperatorTimeout`, a valid reveal enables the
configured `resolver` from `ProtocolConfig` to call `ResolveDispute` before
finalization, while preserving the existing invalid/matching terminal branches
unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: be495dcd-af5b-4baf-9a48-a9c9695a52d5
📒 Files selected for processing (1)
mimd-0025-impl.md
| pub resolver: Pubkey, | ||
| /// Vault receiving protocol fees, penalties, or slashed funds. | ||
| pub protocol_fee_vault: Pubkey, | ||
| /// Minimum stake required for an operator to register and stay active. | ||
| pub min_operator_bond: u64, | ||
| /// Minimum stake required for a verifier to register and stay active. | ||
| pub min_verifier_bond: u64, | ||
| /// Minimum stake locked by RaiseChallenge to prevent cheap spam. | ||
| pub min_challenger_stake: u64, | ||
| /// Slots available for approval/challenge after VRF activation. | ||
| pub challenge_window_slots: u64, | ||
| /// Slots the operator gets to open state after a challenge. | ||
| pub operator_response_timeout_slots: u64, | ||
| /// Slots the challenger gets to reveal after operator response or timeout. | ||
| pub challenger_reveal_timeout_slots: u64, | ||
| /// Delay before a winning challenger can claim payout. | ||
| pub payout_timelock_slots: u64, | ||
| /// Number of verifiers randomly picked from VerifierRegistry. | ||
| pub selected_verifier_count: u16, | ||
| /// Approvals required for happy-path finalization. | ||
| pub approval_threshold: u16, | ||
| /// Maximum under-approval extensions before the commitment expires. | ||
| pub max_window_extensions: u16, | ||
| /// Penalty for a valid reveal that matches the operator state. | ||
| pub match_penalty_bps: u16, |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and inspect the relevant design doc and referenced account/lifecycle sections.
if [ -f mimd-0025-impl.md ]; then
echo "== file exists =="
wc -l mimd-0025-impl.md
echo "== references to PendingCommitment / config fields =="
rg -n "PendingCommitment|approval_threshold|max_window_extensions|match_penalty_bps|protocol_fee_vault|resolver|vrf_program|vrf_request_id|registry_revision|configuration snapshot|copied values|Update" mimd-0025-impl.md
echo
echo "== sections around account definition and lifecycle references =="
sed -n '130,185p' mimd-0025-impl.md
echo "----"
sed -n '270,355p' mimd-0025-impl.md
echo "----"
sed -n '475,505p' mimd-0025-impl.md
echo "----"
sed -n '675,705p' mimd-0025-impl.md
else
echo "mimd-0025-impl.md not found"
git ls-files | rg 'mimd-0025-impl\.md|impl\.md|protocol|pending|registry|vrf|challenge'
fiRepository: magicblock-labs/delegation-program
Length of output: 19967
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== sections around Challenge / state buffer fields =="
sed -n '345,440p' mimd-0025-impl.md
echo
echo "== deterministic probe of pending config fields in PendingCommitment =="
python3 - <<'PY'
from pathlib import Path
p = Path("mimd-0025-impl.md")
text = p.read_text().splitlines()
def block(name, title=None):
in_block = False
for i, line in enumerate(text, 1):
if title:
if title in line and ("```" in "".join(text[max(0,i-3):i]) or "///" in "".join(text[max(0,i-3):i])):
in_block = True
j=i
continue
if in_block:
if line.lstrip().startswith("pub struct ") or (j and line.lstrip().startswith("///")):
yield line, i
# approximate PendingCommitment struct lines by sentinel range
start = next(i for i,l in enumerate(text,1) if "pub struct PendingCommitment {" in l)
end = start + next(i for i,l in enumerate(text[start:],2) if l == "}")
pending = set(l.strip().strip(",") for _,l in zip(range(start,end), text[start:end]) if l.strip() and l.lstrip().startswith("pub "))
fields = ["resolver", "protocol_fee_vault", "match_penalty_bps", "max_window_extensions", "approval_threshold"]
print("PendingCommitment contains:")
for f in fields:
print(f" {f}: {f in pending}")
# approximate Challenge struct lines by sentinel range
starts = [i for i,l in enumerate(text,1) if "pub struct Challenge {" in l]
end = next(i for i,l in enumerate(text[starts[0]-1:],1) if l.startswith("pub struct ")) + starts[0] - 1 if starts else None
challenge = set(l.strip().strip(",") for j,l in zip(range(starts[0],end), text[starts[0]-1:end-1]) if l.strip() and l.lstrip().startswith("pub "))
print("Challenge contains:")
for f in fields:
print(f" {f}: {f in challenge}")
PYRepository: magicblock-labs/delegation-program
Length of output: 4248
Snapshot configuration fields that affect committed lifecycles.
UpdateProtocolConfig says existing pending commitments keep copied values, and PendingCommitment stores only approval_threshold plus the registry revision. PendingCommitment still references resolver, protocol_fee_vault, match_penalty_bps, and max_window_extensions through ResolveDispute, payouts/penalties, and extension handling, so a later config update can change dispute authorization, penalties, or extension limits for an already-committed transaction. Store all configuration values that lifecycle instructions read, or explicitly document that these values remain dynamic.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 147 - 171, Update PendingCommitment and its
creation path to snapshot every protocol configuration value later read by
lifecycle instructions, including resolver, protocol_fee_vault,
match_penalty_bps, and max_window_extensions, alongside the existing
approval_threshold and registry revision. Ensure ResolveDispute, payout/penalty
handling, and extension handling use the commitment’s stored values so
UpdateProtocolConfig cannot alter already-committed transactions; alternatively,
explicitly document each intentionally dynamic field.
| /// Number of verifiers randomly picked from VerifierRegistry. | ||
| pub selected_verifier_count: u16, | ||
| /// Approvals required for happy-path finalization. | ||
| pub approval_threshold: u16, | ||
| /// Maximum under-approval extensions before the commitment expires. | ||
| pub max_window_extensions: u16, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Reject impossible verifier thresholds before activation.
The operator is excluded from selection, but the specification does not require enough eligible verifiers for selected_verifier_count. It also does not require approval_threshold to be positive and no greater than the selected set. Validate these conditions before activation. Otherwise a commitment can enter Active with no possible approval path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 164 - 169, Validate verifier configuration
before activation: ensure the eligible verifier population, excluding the
operator, is at least selected_verifier_count, and require approval_threshold to
be greater than zero and no greater than selected_verifier_count. Add these
checks to the activation validation flow and reject invalid commitments before
they enter Active.
| /// Maximum under-approval extensions before the commitment expires. | ||
| pub max_window_extensions: u16, |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Persist the extension count.
ExtendChallengeWindow must enforce max_window_extensions, but PendingCommitment has no extension counter. challenge_window_id is described as an identifier, not as a bounded count. Add an explicit counter, increment it atomically, and reject extensions after the configured maximum.
Also applies to: 690-692
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 168 - 169, Update PendingCommitment to
persist an explicit extension counter rather than using challenge_window_id. In
ExtendChallengeWindow, atomically increment the counter and reject the request
once max_window_extensions is reached, while preserving the configured limit’s
behavior and updating any related serialization or initialization paths.
| pub struct OperatorBond { | ||
| /// Operator identity this bond belongs to. | ||
| pub operator_identity: Pubkey, | ||
| /// Slashable stake currently credited to this operator. | ||
| pub stake_lamports: u64, | ||
| /// Stake temporarily unavailable for withdrawal. | ||
| pub locked_lamports: u64, | ||
| /// Whether this operator can post new commitments. | ||
| pub status: ActorStatus, | ||
| /// Slot when exit was requested; None means no pending withdrawal. | ||
| pub withdraw_requested_slot: Option<u64>, | ||
| } | ||
| // Review: `locked_lamports` needs exact lock/unlock rules when one operator has | ||
| // multiple pending commitments or disputes. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file location and relevant snippets =="
git ls-files | grep -F 'mimd-0025-impl.md' || true
wc -l mimd-0025-impl.md
sed -n '160,220p' mimd-0025-impl.md
sed -n '480,525p' mimd-0025-impl.md
sed -n '590,625p' mimd-0025-impl.md
echo "== search for lock/unlock terms =="
rg -n "locked_lamports|lock|unlock|PostCommitment|CancelUnactivatedCommitment|PendingCommitment|OperatorBond" mimd-0025-impl.mdRepository: magicblock-labs/delegation-program
Length of output: 21373
Make commitment-local operator locks explicit in all terminal paths.
OperatorBond.locked_lamports is aggregate, but PostCommitment can lock commitment-local stake while PendingCommitment stores no lock amount and CancelUnactivatedCommitment cannot update OperatorBond. Add the bond account and exact lock amount to every path that can release an unspent operator lock, or remove commitment-local operator locking entirely.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 185 - 198, Make commitment-local operator
locking consistent across all terminal paths: either add the operator bond
account and exact locked amount to PendingCommitment and
CancelUnactivatedCommitment so every release updates
OperatorBond.locked_lamports, including multiple commitments and disputes, or
remove the commitment-local locking introduced by PostCommitment entirely.
Ensure each terminal path releases exactly its own unspent lock without
affecting other commitments.
| pub entries: Vec<VerifierRegistryEntry>, | ||
| } | ||
| // Review: account size must be bounded before implementation. If the verifier | ||
| // set can grow large, replace this Vec with a Merkleized or paged registry. |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Set hard bounds for every variable-length account field.
VerifierRegistry.entries, PendingCommitment.selected_verifiers, approval_bitmap, and StateBuffer.data are Vec fields stored in accounts. Define maximum sizes, allocation/reallocation rules, and oversize failure behavior before implementation. Without these bounds, an attacker-controlled or registry-controlled size can make account creation or resizing fail.
Also applies to: 329-331, 365-386
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 232 - 235, Define explicit maximum sizes for
VerifierRegistry.entries, PendingCommitment.selected_verifiers, approval_bitmap,
and StateBuffer.data before implementing account storage. Document and enforce
allocation and reallocation rules, reject oversize inputs deterministically, and
ensure registry growth cannot exceed the account limits; use a bounded or
Merkleized/paged representation where the Vec cannot safely be bounded.
| | `WithdrawStake`<ul><li>ix-data: <code>actor_kind</code></li><li>accounts: <strong>actor signer, OperatorBond or VerifierBond, ProtocolConfig</strong></li></ul> | Operator or verifier | Withdraws unlocked stake after the exit delay. Slashed or locked stake stays in the protocol. | | ||
| | `PostCommitment`<ul><li>ix-data: <code>commitment</code></li><li>accounts: <strong>operator signer, OperatorBond, PendingCommitment, delegated account, DelegationRecord, ProtocolConfig, VerifierRegistry, DLP identity PDA, VRF queue/program</strong></li></ul> | Operator | Creates an `AwaitingRandomness` commitment, stores the current `registry_revision`, locks any commitment-local stake if needed, and requests VRF. | | ||
| | `ConsumeCommitmentRandomness`<ul><li>ix-data: <code>randomness</code></li><li>accounts: <strong>VRF identity signer, PendingCommitment, ProtocolConfig, VerifierRegistry</strong></li></ul> | VRF callback | Verifies the VRF caller and registry revision, selects verifiers from the registry excluding the commitment operator, and starts the challenge window. | | ||
| | `CancelUnactivatedCommitment`<ul><li>ix-data: <code>reason</code></li><li>accounts: <strong>cranker/operator signer, PendingCommitment, ProtocolConfig, VerifierRegistry</strong></li></ul> | Operator or cranker | Cancels a commitment that is still waiting for randomness but can no longer activate, such as after registry change or VRF timeout. | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Store a verifiable VRF timeout.
CancelUnactivatedReason::VrfTimeout requires a timeout check, but neither ProtocolConfig nor PendingCommitment supplies a VRF callback timeout or deadline. posted_slot alone cannot establish when cancellation becomes valid. Add a configured timeout and snapshot its resulting deadline in the pending record.
Also applies to: 605-608
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` at line 507, Update the CancelUnactivatedCommitment design
and related PendingCommitment/ProtocolConfig definitions to include a configured
VRF callback timeout and a per-commitment deadline snapshot. Ensure
CancelUnactivatedReason::VrfTimeout validates the current slot against that
stored deadline rather than relying on posted_slot alone, and document the
required configuration/account data wherever the commitment lifecycle is
specified.
| | `ChallengerReveal`<ul><li>ix-data: <code>state, salt</code></li><li>accounts: <strong>challenger signer, PendingCommitment, Challenge, optional StateBuffer, fee vault</strong></li></ul> | Challenger | Verifies the challenge preimage and opened state. It slashes invalid reveals, penalizes matching reveals, or moves mismatches to resolver decision. | | ||
| | `MarkChallengerRevealTimeout`<ul><li>ix-data: <code>empty</code></li><li>accounts: <strong>cranker, PendingCommitment, Challenge, fee vault</strong></li></ul> | Cranker | Slashes challenger stake when the reveal deadline passes without a valid reveal. | | ||
| | `ResolveDispute`<ul><li>ix-data: <code>decision</code></li><li>accounts: <strong>resolver signer, Challenge, PendingCommitment, OperatorBond, fee vault, optional PayoutTimelock</strong></li></ul> | Resolver multisig | Applies the multisig decision for a valid mismatch: operator correct or challenger correct. | | ||
| | `FinalizeCommitment`<ul><li>ix-data: <code>state_source</code></li><li>accounts: <strong>finalizer, PendingCommitment, delegated account, DelegationRecord/metadata, StateBuffer, optional Challenge, ProtocolConfig</strong></li></ul> | Finalizer or cranker | Applies the final state after the happy path or after dispute resolution. | |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg '(^|/)(mimd-0025-impl\.md|finalize\.rs|commit_state_from_buffer\.rs|processor)' | sed -n '1,200p'
echo
echo "== relevant outline for candidate source files =="
for f in src/processor/fast/finalize.rs src/processor/fast/commit_state_from_buffer.rs; do
if [ -f "$f" ]; then
echo "--- $f ($(wc -l < "$f") lines) ---"
ast-grep outline "$f" --view compact 2>/dev/null || true
sed -n '1,230p' "$f"
else
echo "missing $f"
fi
done
echo
echo "== relevant lines in mimd-0025-impl.md around 480-540 =="
sed -n '480,540p' mimd-0025-impl.md
echo
echo "== searches for FinalizeCommitment / finalizer / Commitment handling =="
rg -n "FinalizeCommitment|finalizer|CommitStateFromBuffer|commit_state_from_buffer|Commitment|DelegationRecord|metadata|fee vault|vault|StateBuffer|ProtocolConfig|Challenge|PendingCommitment" mimd-0025-impl.md src/processor/fast/mimd-0025-impl.md src 2>/dev/null | sed -n '1,240p'Repository: magicblock-labs/delegation-program
Length of output: 45418
Align FinalizeCommitment with the processor account contract.
The current process_finalize handler requires validator signer, delegated/committed/state accounts, delegation metadata, and the validator fees vault. The FinalizeCommitment table entry omits these accounts and does not define how the legacy commit state/account contract maps to the new pending-commitment model. Add the required account validation and behavior or update the handler to match the documented boundary before implementation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` at line 517, Align the FinalizeCommitment specification
with the process_finalize handler’s account contract: document validator signer,
delegated/committed/state accounts, delegation metadata, and validator fees
vault, and define how the legacy commit state/account maps to PendingCommitment.
Alternatively, update process_finalize to enforce only the accounts listed by
FinalizeCommitment, keeping validation and finalization behavior consistent
across the table and handler.
| pub struct PostCommitmentData { | ||
| pub commit_id: u64, | ||
| pub lamports: u64, | ||
| pub owner: Pubkey, | ||
| pub data_hash: [u8; 32], | ||
| pub da_pointer_hash: [u8; 32], | ||
| pub er_slot: Option<u64>, | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Files matching mimd-0025:"
fd -i 'mimd-0025' . || true
echo
echo "Relevant snippets around PostCommitmentData and state_commitment_hash:"
rg -n "PostCommitmentData|PendingCommitment|state_commitment_hash|er_slot" mimd-0025-impl.md -C 4 || true
echo
echo "Diff stat:"
git diff --stat || true
echo
echo "Line context in mimd-0025-impl.md:"
wc -l mimd-0025-impl.md || true
sed -n '480,560p' mimd-0025-impl.md
sed -n '560,640p' mimd-0025-impl.mdRepository: magicblock-labs/delegation-program
Length of output: 25069
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '288,340p' mimd-0025-impl.md
sed -n '65,90p' mimd-0025-impl.md
python3 - <<'PY'
from pathlib import Path
text = Path("mimd-0025-impl.md").read_text()
# Simulate PostCommitmentData hash inputs for the documented state_commitment_hash formula.
inputs_a = ["magicblock.state_commitment.v1", "op", "acc", "1", "delegation", "da", ["data_hash"]]
inputs_b = ["magicblock.state_commitment.v1", "op", "acc", "1", "delegation", "da", ["data_hash", "extra"]]
print("documented contains er_slot:", "er_slot" in text[text.find("### Key Instruction Data"):text.find("### Important Instruction Rules")])
print("PendingCommitment stores er_slot:", "pub er_slot" in text[text.find("pub struct PendingCommitment"):text.find("pub struct Challenge")])
print("state_commitment_hash contains er_slot:", "er_slot" in text[text.find("state_commitment_hash = H("):text.find("challenge_hash = H(")] if "state_commitment_hash = H(" in text and "challenge_hash = H(" in text else False)
print("same hash prefix produces same first hash:", hash(tuple(inputs_a)) == hash(tuple(inputs_b[:-1]) + (inputs_b[-1][0],)))
PYRepository: magicblock-labs/delegation-program
Length of output: 3348
Remove or bind er_slot.
PostCommitment stores the commitment in PendingCommitment, but neither PendingCommitment nor state_commitment_hash includes er_slot. FullStateBuffer accepts state_slot, which can serve as the ER slot at buffer creation. Move or hash the slot into the commitment state, or remove er_slot from PostCommitmentData.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 525 - 532, Update the PostCommitmentData
shape so er_slot is either actually carried into the commitment state used by
PendingCommitment/state_commitment_hash, or removed if it is not part of the
committed data. Use the existing FullStateBuffer::state_slot input as the source
of truth if the slot must be preserved, and keep PostCommitment,
PendingCommitment, and state_commitment_hash aligned so no field exists only in
PostCommitmentData.
| - `ChallengerReveal` has four terminal branches: | ||
| invalid hash, matching state, mismatch after operator response, valid reveal | ||
| after operator timeout. | ||
| - `ResolveDispute` requires the configured `resolver` signer from | ||
| `ProtocolConfig`. In DLP v2 this signer is expected to be a multisig-controlled | ||
| account. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- file list ---\n'
git ls-files | rg '(^|/)mimd-0025-impl\.md$|mimd-0025|protocol' || true
printf '\n--- relevant section 600-680 ---\n'
nl -ba mimd-0025-impl.md | sed -n '600,670p'
printf '\n--- search ChallengerReveal/ResolveDispute/timeout terms ---\n'
rg -n "ChallengerReveal|ResolveDispute|operator [Tt]imeout|timeout|valid reveal|valid mismatch|resolver" mimd-0025-impl.mdRepository: magicblock-labs/delegation-program
Length of output: 263
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- file list ---'
git ls-files | rg '(^|/)mimd-0025-impl\.md$|mimd-0025|protocol' || true
printf '%s\n' ''
printf '%s\n' '--- relevant section 600-680 ---'
nl -ba mimd-0025-impl.md | sed -n '600,670p'
printf '%s\n' ''
printf '%s\n' '--- search ChallengerReveal/ResolveDispute/timeout terms ---'
rg -n "ChallengerReveal|ResolveDispute|operator [Tt]imeout|timeout|valid reveal|valid mismatch|resolver" mimd-0025-impl.mdRepository: magicblock-labs/delegation-program
Length of output: 510
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- relevant section 600-680 ---'
awk 'NR>=600 && NR<=680 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.md
echo ''
echo '--- search ChallengerReveal/ResolveDispute/timeout terms ---'
rg -n "ChallengerReveal|ResolveDispute|operator [Tt]imeout|timeout|valid reveal|valid mismatch|resolver" mimd-0025-impl.md || true
echo ''
echo '--- nearby status/branch references 560-630 ---'
awk 'NR>=560 && NR<=630 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.md
echo ''
echo '--- all status definitions/usages ---'
rg -n "\b(status|Status)\b|ChallengerReveal|ResolveDispute|Mismatch|operator timeout|operator timeout\." mimd-0025-impl.md || trueRepository: magicblock-labs/delegation-program
Length of output: 16267
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- lines 230-445 ---'
awk 'NR>=230 && NR<=445 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.md
echo ''
echo '--- lines 670-700 ---'
awk 'NR>=670 && NR<=700 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.mdRepository: magicblock-labs/delegation-program
Length of output: 11856
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- status definitions 445-520 ---'
awk 'NR>=445 && NR<=520 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.md
echo ''
echo '--- line 255-261 plus 619-624 ---'
awk 'NR>=248 && NR<=262 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.md
awk 'NR>=619 && NR<=624 { printf "%4d %s\n", NR, $0 }' mimd-0025-impl.md
echo ''
echo '--- all PendingCommitmentStatus mentions ---'
rg -n "PendingCommitmentStatus|AwaitingDisputeResolution|AwaitingChallengerRevealAfterOperatorTimeout|ChallengerReveal" mimd-0025-impl.mdRepository: magicblock-labs/delegation-program
Length of output: 12115
Clarify the resolver-access transition for operator timeouts.
AwaitingDisputeResolution is already defined, but the spec still says ChallengerReveal branches are terminal and describes ResolveDispute only for a valid mismatch after operator response. Split the invalid/matching terminal outcomes from the timeout mismatch case, and say that a valid reveal after MarkOperatorTimeout lets the configured resolver call ResolveDispute before finalization.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 619 - 624, Update the `ChallengerReveal` and
`ResolveDispute` spec text to separate the truly terminal outcomes (invalid hash
and matching state) from the timeout-driven mismatch path; use
`AwaitingDisputeResolution` to describe the post-`MarkOperatorTimeout` state
where a valid reveal can proceed. Make it explicit that, after
`MarkOperatorTimeout`, a valid reveal enables the configured `resolver` from
`ProtocolConfig` to call `ResolveDispute` before finalization, while preserving
the existing invalid/matching terminal branches unchanged.
| - `FinalizeCommitment` on the happy path requires closed window, approval | ||
| threshold, no unresolved challenge, and full-state hash match. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use direct wording for the finalization rule.
Replace “requires closed window” with “requires the window to be closed.”
🧰 Tools
🪛 LanguageTool
[style] ~625-~625: The double modal “requires closed” is nonstandard (only accepted in certain dialects). Consider “to be closed”.
Context: ...eCommitment` on the happy path requires closed window, approval threshold, no unreso...
(NEEDS_FIXED)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@mimd-0025-impl.md` around lines 625 - 626, Update the FinalizeCommitment
happy-path rule wording by replacing “requires closed window” with “requires the
window to be closed,” while preserving the other listed requirements unchanged.
Source: Linters/SAST tools
|
discard as the branch is renamed and |
Stack created with GitHub Stacks CLI • Give Feedback 💬
Summary by CodeRabbit