Files
MESH2/docs/specs/MESH-Security-Addendum-v0.1.1.md
anthonyrawlins f2d62fa03d Initial workspace: scaffold + constitution + spec documents
Rust workspace with 5 crates (mesh-types, mesh-crypto, mesh-network,
mesh-validator, mesh-wallet), PROJECT_CONSTITUTION.md for CHORUS
automated ingestion, and the full MESH protocol specification suite.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 20:49:44 +11:00

634 lines
28 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**MESH PROTOCOL**
*Security Addendum*
Attack Vector Analysis and Formal Mitigations
Errata and amendments to SPEC-003, SPEC-007, SPEC-008, SPEC-010
Version 0.1.1-draft \| March 2026
**Introduction**
This document identifies seven attack vectors against the MESH protocol
as specified in the v0.1.0 specification suite. For each attack, we
provide: the threat description, the root cause in the existing
specification, the formal mitigation, the specification amendments
required, and the mandatory test assertions.
All mitigations in this document are MANDATORY amendments to the
referenced specifications. An implementation that passes all v0.1.0 test
vectors but does not implement these mitigations is NON-CONFORMANT. The
version number of the specification suite is incremented to v0.1.1 upon
adoption of this addendum.
**Severity Classification**
-------------- ----------- -----------------------------------------------
**Severity** **Label** **Definition**
S1 CRITICAL Allows direct theft of funds or creation of
value from nothing. Protocol is broken without
mitigation.
S2 HIGH Allows economic griefing, denial of service
against specific users, or degrades privacy
guarantees.
S3 MEDIUM Allows minor economic advantage or information
leakage under specific conditions.
-------------- ----------- -----------------------------------------------
**AV-001: Free Option PTLC Griefing Attack**
**Severity: S2 (HIGH)**
**1.1 Threat Description**
A malicious sender initiates a multi-hop payment via PTLCs (SPEC-008
§8.4) with a long expiry. The Prepare packet locks the connector's
liquidity for the duration of the expiry. The sender then monitors the
market and decides whether to fulfill or abandon the payment based on
whether the exchange rate has moved in their favour.
This creates a free financial option: the connector bears the full
market risk (their liquidity is locked at a fixed rate) while the sender
has the optionality to walk away at zero cost. Over millions of
transactions, a systematic attacker could extract significant value from
connectors.
**1.2 Root Cause**
SPEC-008 §8.2.1 defines an expiry field on MeshPacket but imposes no
constraint on its maximum value and no cost for locking connector
liquidity. The specification is silent on the relationship between
expiry duration and economic cost.
**1.3 Mitigation**
Three complementary mechanisms:
**1.3.1 Maximum Expiry Decay Per Hop**
Each connector along a payment path MUST reduce the expiry by at least a
minimum decrement. This limits the total lock-up time and ensures that
senders cannot impose arbitrarily long lock-ups.
> **SPEC-008 AMENDMENT §8.4.5 (NEW):** Each connector MUST set the
> outgoing Prepare packet's expiry to at most: outgoing_expiry =
> incoming_expiry - T_hop, where T_hop is a per-connector configuration
> parameter with a RECOMMENDED minimum of 30 seconds. A connector MUST
> reject an incoming Prepare if incoming_expiry - current_time \< T_hop
> (insufficient time to complete the hop). This creates a hard ceiling
> on total path expiry: max_total_expiry = T_hop × max_path_length. With
> T_hop = 30s and max_path_length = 10 hops, the maximum lock-up is 5
> minutes.
**1.3.2 Locking Fee**
Connectors MAY charge a time-value locking fee that is deducted from the
payment regardless of whether it is fulfilled or rejected. This converts
the free option into a priced option.
> **SPEC-008 AMENDMENT §8.5.1 (NEW):** A connector MAY specify a
> locking_fee_rate in its published rate information, expressed as basis
> points per second of lock-up time. The locking fee is: locking_fee =
> amount × locking_fee_rate × (expiry - current_time) / 10000. The
> locking fee is deducted from the transferred amount. If the payment is
> fulfilled, the connector receives the locking fee plus the spread. If
> the payment expires, the connector retains the locking fee. The
> sender's wallet MUST account for locking fees when calculating the
> total cost of a payment.
**1.3.3 Sender Reputation**
Connectors SHOULD maintain a local reputation score for senders based on
their fulfillment rate. Senders who frequently let payments expire
receive lower priority and wider spreads.
> **SPEC-008 AMENDMENT §8.5.2 (NEW):** Connectors SHOULD track the ratio
> of fulfilled to expired Prepare packets per sender public key. A
> connector MAY reject Prepare packets from senders whose fulfillment
> rate falls below a configurable threshold (RECOMMENDED: 80% over the
> last 1000 packets).
**1.4 Test Assertions**
1. Assert that a connector rejects an incoming Prepare with expiry \>
current_time + T_hop × max_path_length.
2. Assert that each hop reduces the outgoing expiry by at least T_hop.
3. Assert that a payment path with 10 hops and T_hop = 30s has a
maximum total lock-up of 300 seconds.
4. Assert that the locking fee is correctly deducted from the amount
when the payment expires without fulfillment.
5. Assert that a sender with a 50% fulfillment rate is rejected by a
connector with an 80% threshold.
**AV-002: Negative Fee Range Proof Bypass**
**Severity: S1 (CRITICAL)**
**2.1 Threat Description**
A sender constructs a transition where the amount commitment is valid
(positive value with valid range proof), but the fee commitment encodes
a negative value. If the conservation check only verifies that
Σ(recipient amounts) + fee = debit amount on the commitment points, and
the fee range proof is missing or weak, the sender effectively increases
their balance by the absolute value of the negative fee.
Example: Sender has balance 1000. Sender creates a transfer of 1000 to
recipient, with fee = -500. Conservation check passes: 1000 + (-500) =
500. But the sender has only been debited 500 from a balance of 1000, so
they retain 500 extra. The recipient gets 1000. 500 units of value have
been created from nothing.
**2.2 Root Cause**
SPEC-002 §2.4.3 specifies RANGE_CHECK (rule 6) and CONSERVATION_CHECK
(rule 7) as separate steps. However, the specification text for
RANGE_CHECK states: "All range proofs MUST verify. This proves all
amounts are non-negative and within the valid range \[0, 2⁶⁴)." The word
"amounts" is ambiguous --- it could be read as referring only to the
recipient amounts, not the fee. This ambiguity is the attack surface.
**2.3 Mitigation**
Eliminate the ambiguity with an explicit enumeration of every commitment
that requires a range proof.
> **SPEC-002 AMENDMENT §2.4.3 Rule 6 (REVISED):** RANGE_CHECK: The
> following range proofs MUST be present and MUST verify: (a)
> transition.range_proof proves transition.amount is in \[0, 2⁶⁴). (b)
> transition.fee_proof proves transition.fee is in \[0, 2⁶⁴). (c) For
> each recipient r in transition.recipients: r.range_proof proves
> r.amount is in \[0, 2⁶⁴). If ANY of these proofs is absent, malformed,
> or fails verification, the validator MUST reject the transition with
> ERR_INVALID_RANGE_PROOF. There are no exceptions. A transition with
> zero fee MUST still include a valid range proof for the zero-value fee
> commitment.
>
> **SPEC-002 AMENDMENT §2.4.3 Rule 7 (CLARIFIED):** CONSERVATION_CHECK:
> The sum of all output commitments MUST equal the input commitment.
> Formally: C_amount = Σ(C_recipient_i) + C_fee. This is verified on the
> commitment points (elliptic curve point addition). The validator MUST
> verify this equation AFTER all range proofs have passed. The
> combination of range proofs (all values non-negative) and conservation
> (inputs = outputs) together guarantee that no value is created or
> destroyed.
**2.4 Test Assertions**
6. Assert that a transition with a valid amount range proof but a
missing fee range proof is rejected with ERR_INVALID_RANGE_PROOF.
7. Assert that a transition with a fee commitment to a negative value
(commitment point C_fee where opening reveals v \< 0) is rejected.
8. Assert that a transition with fee = 0 still requires a valid range
proof for the zero commitment.
9. Assert that a transition where Σ(outputs) + fee = input but fee is
negative is rejected (the range proof on fee catches this before the
conservation check).
10. Assert that crafting a Bulletproofs+ proof for a value outside \[0,
2⁶⁴) produces a proof that fails verification.
**AV-003: Causal Dependency Orphan Exploit**
**Severity: S1 (CRITICAL)**
**3.1 Threat Description**
A Byzantine account references a hash in causal_deps that is a
syntactically valid SHA3-256 digest but does not correspond to any
settlement certificate the validator has seen. If the validator only
checks the hash format (32 bytes, non-zero) without verifying that it
corresponds to a real, certified transition, the Byzantine account could
spend funds it never received.
Worse: if the "ghost" dependency references a fabricated certificate
that credits the attacker with value, the attacker creates money from
nothing by spending against a fictional incoming payment.
**3.2 Root Cause**
SPEC-002 §2.4.3 Rule 8 (CAUSAL_CHECK) states: "Every hash in causal_deps
MUST reference a transition that the validator has already processed and
certified." This is correct in intent but insufficiently precise about
what "processed and certified" means. The specification does not mandate
how the validator performs this lookup or what happens during network
partition when a validator may be behind.
**3.3 Mitigation**
> **SPEC-002 AMENDMENT §2.4.3 Rule 8 (REVISED):** CAUSAL_CHECK: For
> every hash h in transition.causal_deps, the validator MUST verify
> that: (a) h exists in the validator's local certificate store (a hash
> map keyed by transition hash, populated only when a valid
> SettlementCertificate is received and verified per SPEC-003 §3.3.2),
> AND (b) the referenced transition's effects (credit to the current
> sender) have been applied to the sender's AccountState. If any hash is
> not found in the certificate store, the validator MUST return
> ERR_UNKNOWN_DEPENDENCY. The validator MUST NOT attempt to fetch the
> missing certificate from the network during validation. If a
> dependency is genuinely missing (e.g., due to network delay), the
> sender must retry after the dependency has been disseminated to the
> validator.
Additionally, the specification must prevent the case where a sender
references a certified transition that does not actually credit them:
> **SPEC-002 AMENDMENT §2.4.3 Rule 8a (NEW):**
> DEPENDENCY_RELEVANCE_CHECK: For every hash h in
> transition.causal_deps, the validator MUST verify that the referenced
> transition either: (a) has the current sender as a recipient, OR (b)
> is a prior transition by the current sender (same sender public key).
> A transition that references an unrelated third-party certificate as a
> causal dependency MUST be rejected with ERR_IRRELEVANT_DEPENDENCY.
> This prevents an attacker from padding causal_deps with arbitrary
> valid hashes to confuse causal ordering analysis.
**3.4 Test Assertions**
11. Assert that a transition referencing a non-existent hash in
causal_deps is rejected with ERR_UNKNOWN_DEPENDENCY.
12. Assert that a transition referencing a real certificate hash that
does not credit the sender is rejected with
ERR_IRRELEVANT_DEPENDENCY.
13. Assert that a transition referencing a valid, relevant certificate
is accepted.
14. Assert that a validator does NOT fetch missing dependencies from the
network during the validation path (no side-effects during
validation).
**AV-004: Cross-Shard Double-Spend Race**
**Severity: S1 (CRITICAL) if sharding is incorrectly implemented;
MITIGATED BY DESIGN if spec is followed**
**4.1 Threat Description**
A Byzantine sender sends two conflicting transitions (same sequence
number, different recipients) to two different validator shards
simultaneously, hoping that each shard independently certifies a
different transition before the equivocation is detected.
**4.2 Root Cause**
SPEC-003 §3.6 defines the sharding function as shard_id =
hash(account_pubkey) mod num_shards. This is correct and ensures all
transitions for a given account go to the same shard. However, the
specification does not explicitly state that this is a SAFETY-CRITICAL
invariant, and does not specify what happens if an implementation uses a
different sharding function.
**4.3 Mitigation**
This attack is already mitigated by design in the specification, but the
safety-critical nature of the sharding invariant must be made explicit:
> **SPEC-003 AMENDMENT §3.6 (REVISED):** SHARDING SAFETY INVARIANT: All
> transitions for a given account MUST be validated by the same set of
> validators/shards. The shard assignment function is: shard_id =
> SHA3-256(account_pubkey)\[0..4\] mod num_shards, where \[0..4\] takes
> the first 4 bytes of the hash as a little-endian u32. This function
> MUST be deterministic, stateless, and identical across all validators.
> A validator MUST reject a VOTE_REQUEST if the sender's account does
> not map to a shard it is responsible for. An implementation that uses
> a different sharding function, or that allows a transition to be
> processed by a non-responsible shard, is NON-CONFORMANT and UNSAFE.
>
> **SPEC-003 AMENDMENT §3.6.1 (NEW):** CROSS-SHARD VERIFICATION: When a
> validator receives a SettlementCertificate for a recipient that maps
> to a different shard, it MUST verify the certificate (signatures,
> quorum) before crediting the recipient. The certificate provides proof
> that the sender's shard has validated and certified the debit. The
> receiving shard does not re-validate the sender's balance or sequence
> number --- it trusts the certificate as proof that the sender's shard
> has done so. This is safe because the sender's shard is the sole
> authority for the sender's account state.
**4.4 Test Assertions**
15. Assert that a validator rejects a VOTE_REQUEST if
hash(sender_pubkey) mod num_shards does not match the validator's
shard_id.
16. Assert that two conflicting transitions from the same sender (same
sequence, different content) sent to the correct shard produce an
equivocation proof.
17. Assert that a conflicting transition sent to the WRONG shard is
rejected before equivocation detection (at the shard routing check).
18. Assert that the sharding function is deterministic: the same public
key always produces the same shard_id regardless of when or where it
is computed.
**AV-005: Multi-Hop Dust Shaving**
**Severity: S3 (MEDIUM)**
**5.1 Threat Description**
A malicious connector in a multi-hop payment path exploits integer
division rounding to pocket small amounts of value ("dust") from each
transaction. When converting between asset types, the exchange
calculation amount_out = amount_in × rate.numerator / rate.denominator
produces a non-integer result that must be truncated. The connector
keeps the fractional remainder.
At 1 cent per transaction and 1 million transactions per day, this
yields \$10,000/day in stolen dust.
**5.2 Root Cause**
SPEC-002 §2.7 defines the Value Semiring's exchange operation as (a,
id₁) ⊗ rate = (a × rate.numerator / rate.denominator, id₂) but does not
specify the rounding rule or what happens to the remainder.
**5.3 Mitigation**
> **SPEC-002 AMENDMENT §2.7.1 (NEW):** EXCHANGE ROUNDING RULE: All
> exchange calculations MUST use the following formula: amount_out =
> floor(amount_in × rate.numerator / rate.denominator). The remainder
> is: remainder = amount_in × rate.numerator mod rate.denominator. The
> remainder MUST be returned to the sender (not retained by the
> connector). The sender's wallet MUST verify that amount_out +
> remainder (converted back to the source asset) exactly equals the
> original amount_in. This is enforced at the PTLC fulfillment stage:
> the sender only fulfills the PTLC if the received amount matches
> expectations within a sender-specified tolerance (max_slippage).
>
> **SPEC-008 AMENDMENT §8.2.1 (REVISED):** The MeshPacket Prepare
> message MUST include a new field: min_destination_amount (u128). The
> recipient (or the recipient-side connector) MUST reject the Prepare
> with ERR_BELOW_MINIMUM if the actual delivered amount is less than
> min_destination_amount. This shifts control to the sender: the sender
> specifies the minimum acceptable output, and if any connector along
> the path shaves more than the sender is willing to tolerate, the
> payment fails rather than succeeding with missing value.
**5.4 Test Assertions**
19. Assert that for an exchange with rate 3/7 and amount_in = 100, the
result is amount_out = floor(300/7) = 42, remainder = 300 mod 7 = 6.
20. Assert that the remainder is returned to the sender, not retained by
the connector.
21. Assert that a Prepare packet with min_destination_amount = 42 and
actual delivery of 41 is rejected with ERR_BELOW_MINIMUM.
22. Assert that integer overflow in the multiplication amount_in ×
rate.numerator is handled (use u256 intermediate or checked
arithmetic). If overflow would occur, the operation MUST fail with
ERR_OVERFLOW rather than silently truncating.
**AV-006: Epoch-Boundary Replay Attack**
**Severity: S1 (CRITICAL)**
**6.1 Threat Description**
A user collects VOTE_RESPONSE messages from validators in Epoch N but
does not broadcast the SettlementCertificate until Epoch N+1 (or later).
If validators in the new epoch accept certificates signed by the old
epoch's validators, the user could exploit a situation where: (a) a
validator was removed from the set in Epoch N+1 (perhaps for
misbehaviour), and its votes are now suspect, or (b) the validator set
has changed and the "2f+1 quorum" calculated against the new set may not
hold against the old set.
**6.2 Root Cause**
SPEC-002 §2.5.1 defines the SettlementCertificate with an epoch field
and states votes must be from validators in that epoch's set. However,
the specification does not define a grace period or cutoff for
cross-epoch certificate acceptance. The specification is silent on what
happens when a certificate arrives after an epoch boundary.
**6.3 Mitigation**
> **SPEC-003 AMENDMENT §3.3.2 (REVISED):** EPOCH VALIDATION FOR
> CERTIFICATES: When a validator receives a SettlementCertificate, it
> MUST perform the following epoch check: (a) If certificate.epoch ==
> current_epoch: accept and verify votes against the current validator
> set. (b) If certificate.epoch == current_epoch - 1: accept and verify
> votes against the PREVIOUS epoch's validator set. This provides a
> one-epoch grace period for certificates that were assembled just
> before an epoch transition. (c) If certificate.epoch \<
> current_epoch - 1: REJECT with ERR_CERTIFICATE_EXPIRED. Certificates
> more than one epoch old are not accepted. (d) If certificate.epoch \>
> current_epoch: REJECT with ERR_FUTURE_EPOCH. The validator does not
> accept certificates from future epochs.
>
> **SPEC-010 AMENDMENT §10.2.1 (REVISED):** EPOCH STATE RETENTION:
> Validators MUST retain the validator set (public keys) of the
> immediately previous epoch until the end of the current epoch. This
> means at any given time, a validator stores exactly two validator
> sets: the current epoch's and the previous epoch's. Upon transitioning
> to epoch N+1, the validator set for epoch N-1 is discarded.
**6.4 Test Assertions**
23. Assert that a certificate from the current epoch is accepted.
24. Assert that a certificate from epoch N-1 is accepted during epoch N
(grace period).
25. Assert that a certificate from epoch N-2 is rejected with
ERR_CERTIFICATE_EXPIRED during epoch N.
26. Assert that a certificate from epoch N+1 is rejected with
ERR_FUTURE_EPOCH during epoch N.
27. Assert that votes are verified against the CORRECT epoch's validator
set, not the current epoch's set, when the certificate's epoch
differs from the current epoch.
28. Assert that a certificate assembled with votes from a validator that
was present in epoch N but removed in epoch N+1 is still accepted
during epoch N+1 (grace period) because the votes are valid for
epoch N.
**AV-007: Stealth Address Unlinkability Breach via Ephemeral Key Reuse**
**Severity: S2 (HIGH)**
**7.1 Threat Description**
If a sender reuses an ephemeral key r when constructing stealth
addresses for two different payments to the same recipient, the
resulting stealth addresses P_stealth_1 and P_stealth_2 will be computed
from the same shared secret S, making them linkable. An observer who
sees the same ephemeral public key R in two different transaction memos
can conclude that both payments went to the same recipient.
More subtly, even if the ephemeral key is not reused, patterns in the
memo field (identical encrypted payload sizes, timing correlations, or
metadata leakage) could allow statistical linkability analysis.
**7.2 Root Cause**
SPEC-007 §7.4.1 step 1 states "Sender generates an ephemeral key pair:
(r, R = r·G)" but does not explicitly mandate that r MUST be fresh
randomness for every payment. The specification assumes correct
implementation but does not defend against implementation errors or
deliberate shortcuts.
**7.3 Mitigation**
> **SPEC-007 AMENDMENT §7.4.1 Step 1 (REVISED):** Sender generates an
> ephemeral key pair: r = CSPRNG(32 bytes), R = r·G. The value r MUST be
> generated from a cryptographically secure random number generator for
> EVERY payment. The value r MUST NOT be derived deterministically from
> the payment amount, recipient, or any other predictable input. After
> the Fulfill is received (or the payment expires), the value r MUST be
> securely erased from memory using zeroize. An implementation MUST NOT
> cache, reuse, or persist ephemeral keys across payments.
>
> **SPEC-007 AMENDMENT §7.4.2 (NEW):** EPHEMERAL KEY UNIQUENESS
> ENFORCEMENT: The sender's wallet MUST maintain a Bloom filter (or
> equivalent probabilistic set) of recently used ephemeral public keys
> R. Before using a new R, the wallet MUST check that R is not in the
> filter. If a collision is detected (which should only occur due to a
> CSPRNG failure), the wallet MUST generate a new r and retry. The Bloom
> filter SHOULD retain entries for at least 10,000 recent payments. This
> provides defence-in-depth against CSPRNG failures.
>
> **SPEC-007 AMENDMENT §7.4.3 (NEW):** MEMO PADDING: The encrypted memo
> field MUST be padded to a fixed length before encryption, regardless
> of the actual payload size. The padded length MUST be one of: 64, 128,
> 256, 512, 1024, or 2048 bytes (the smallest size that fits the
> payload). This prevents an observer from correlating transactions by
> memo ciphertext length. Padding MUST use random bytes (not
> zero-padding) to prevent distinguishing padding from payload without
> the decryption key.
**7.4 Test Assertions**
29. Assert that two payments to the same recipient produce different
stealth addresses (P_stealth_1 ≠ P_stealth_2).
30. Assert that two payments to the same recipient produce different
ephemeral public keys (R_1 ≠ R_2).
31. Assert that an observer with access to all SettlementCertificates
but without any view_key cannot determine if two stealth addresses
belong to the same recipient, with advantage ≤ negligible (formal:
advantage \< 2⁻¹²⁸).
32. Assert that the Bloom filter detects a deliberately reused ephemeral
key and forces regeneration.
33. Assert that the encrypted memo is padded to a fixed size: a 10-byte
payload and a 100-byte payload to the same recipient produce memos
of the same ciphertext length.
34. Assert that the ephemeral secret r is zeroed from memory after use
(test via memory inspection in debug mode).
**Summary of Specification Amendments**
------------ -------------- ---------------------- -------------------------------
**Attack** **Severity** **Amended Spec** **Key Change**
AV-001 S2 SPEC-008 §8.4.5, Maximum expiry decay per hop,
§8.5.1, §8.5.2 locking fee, sender reputation
scoring.
AV-002 S1 SPEC-002 §2.4.3 Rules Explicit enumeration of all
6--7 commitments requiring range
proofs, including fee.
Zero-value fee requires proof.
AV-003 S1 SPEC-002 §2.4.3 Rules Certificate store lookup
8--8a mandatory; new relevance check
prevents referencing unrelated
certificates.
AV-004 S1\* SPEC-003 §3.6, §3.6.1 Sharding invariant made
explicit as safety-critical.
Cross-shard credit via
certificate verification.
AV-005 S3 SPEC-002 §2.7.1, Rounding rule: floor +
SPEC-008 §8.2.1 remainder to sender.
min_destination_amount field in
Prepare packets.
AV-006 S1 SPEC-003 §3.3.2, One-epoch grace period for
SPEC-010 §10.2.1 certificates. Strict rejection
of certificates more than one
epoch old.
AV-007 S2 SPEC-007 §7.4.1--7.4.3 Mandatory fresh CSPRNG
ephemeral key, Bloom filter
uniqueness check, random-padded
memo to fixed lengths.
------------ -------------- ---------------------- -------------------------------
*\* AV-004 is mitigated by design if the specification is followed. The
severity rating reflects the consequence of non-conformant
implementation, not a flaw in the protocol.*
**Formal Verification Additions**
The following properties MUST be added to the formal verification
requirements in SPEC-010 §10.6:
------------------------- ----------------- ----------------------------
**Property** **Tool** **Scope**
Fee commitment range TLA+ Verify that no state is
(AV-002) reachable where a transition
with negative fee commitment
passes all validation rules.
Causal dependency TLA+ Verify that no state is
integrity (AV-003) reachable where an account
spends value credited by an
uncertified or irrelevant
transition.
Sharding safety (AV-004) TLA+ Verify that no state is
reachable where two
conflicting transitions for
the same account are
certified by different
shards.
Epoch-boundary TLA+ Verify that a certificate
certificate validity from epoch N-2 cannot be
(AV-006) applied in epoch N under any
message ordering.
Stealth address ProVerif Verify the PRIVACY-2
unlinkability (AV-007) property: an observer
without the view_key has
negligible advantage in
linking two stealth
addresses to the same
recipient.
------------------------- ----------------- ----------------------------
**Document Control**
------------- ------------ --------------- -------------------------------
**Version** **Date** **Author** **Description**
0.1.1 2026-03-11 MESH Foundation Security addendum. Mitigations
for 7 identified attack vectors
(AV-001 through AV-007).
------------- ------------ --------------- -------------------------------