<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ameer Abdulaleem</title>
    <description>The latest articles on Forem by Ameer Abdulaleem (@ameer_0699).</description>
    <link>https://forem.com/ameer_0699</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3849973%2Ffb074fd5-b17c-4584-86e8-8deae996da99.jpg</url>
      <title>Forem: Ameer Abdulaleem</title>
      <link>https://forem.com/ameer_0699</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ameer_0699"/>
    <language>en</language>
    <item>
      <title>Selective Disclosure Patterns in Compact: A Developer's Guide</title>
      <dc:creator>Ameer Abdulaleem</dc:creator>
      <pubDate>Mon, 27 Apr 2026 12:14:42 +0000</pubDate>
      <link>https://forem.com/ameer_0699/selective-disclosure-patterns-in-compact-a-developers-guide-3lel</link>
      <guid>https://forem.com/ameer_0699/selective-disclosure-patterns-in-compact-a-developers-guide-3lel</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiq5u8ksgc1c2zc1g2boq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiq5u8ksgc1c2zc1g2boq.jpg" alt="Selective Disclosure Patterns in Compact: A Developer's Guide"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  INTRODUCTION
&lt;/h2&gt;

&lt;p&gt;Blockchain transparency is a double edged sword. Every transaction, every state change, and every interaction sits on a public ledger for anyone to inspect. For many applications this is a feature. For applications handling sensitive data it is a dealbreaker.&lt;/p&gt;

&lt;p&gt;Midnight solves this with a dual state architecture. Your DApp maintains both public state visible on chain and private state stored locally with users. The bridge between these two worlds is selective disclosure: the ability to prove something is true about your private data without revealing the data itself.&lt;/p&gt;

&lt;p&gt;This tutorial covers the patterns that make selective disclosure work in Compact. You will learn how to use &lt;code&gt;disclose()&lt;/code&gt; correctly, understand what information is safe to expose, implement domain separated hashing to prevent user tracking across different properties, and apply a systematic privacy audit to your own contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you continue, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Compact toolchain installed (follow the &lt;a href="https://docs.midnight.network/getting-started/installation" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A basic understanding of Compact syntax (review the &lt;a href="https://docs.midnight.network/getting-started/hello-world" rel="noopener noreferrer"&gt;Hello World tutorial&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://www.npmjs.com/package/midnight-mcp" rel="noopener noreferrer"&gt;Midnight MCP&lt;/a&gt; tool available for validating your code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Is Selective Disclosure?
&lt;/h2&gt;

&lt;p&gt;In traditional smart contract development every input to a function becomes public the moment a transaction is submitted. There is no privacy. The contract sees everything and so does everyone else.&lt;/p&gt;

&lt;p&gt;Compact changes this. Circuit parameters are private by default. Consider this simple function signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;circuit&lt;/span&gt; &lt;span class="nf"&gt;storeMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Opaque&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// newMessage is private here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Opaque&amp;lt;"string"&amp;gt;&lt;/code&gt; type tells the compiler that &lt;code&gt;newMessage&lt;/code&gt; is a private input. It exists in the user's local execution environment but never appears on chain in its raw form.&lt;/p&gt;

&lt;p&gt;Selective disclosure happens when you decide to move data from the private context to the public ledger. You do this with the &lt;code&gt;disclose()&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export circuit storeMessage(newMessage: Opaque&amp;lt;"string"&amp;gt;): [] {
    message = disclose(newMessage);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single line makes a deliberate choice. The message content becomes public state stored in the &lt;code&gt;message&lt;/code&gt; ledger variable. Everyone can now read it.&lt;/p&gt;

&lt;p&gt;But selective disclosure is about more than just toggling visibility. It is about revealing proofs instead of raw data. You can disclose that a condition is met without disclosing the condition itself. You can disclose a hash commitment now and reveal the preimage later. You can disclose aggregated results while keeping individual inputs hidden.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;disclose()&lt;/code&gt; Usage Patterns
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;disclose()&lt;/code&gt; function is the only mechanism for moving data from private context to public state. Understanding its patterns is fundamental to building privacy preserving DApps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 1: Direct Disclosure
&lt;/h3&gt;

&lt;p&gt;The simplest pattern. You have private data and you want it on chain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version 0.22;

export ledger publicCounter: Counter;

export circuit increment(amount: Opaque&amp;lt;Uint&amp;lt;32&amp;gt;&amp;gt;): [] {
    let increment_by = disclose(amount);
    publicCounter.increment(increment_by);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the user provides a private &lt;code&gt;amount&lt;/code&gt;. The circuit discloses it and increments the public counter. The amount becomes visible to everyone. Use this pattern only when the data is intentionally non sensitive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 2: Conditional Disclosure with Assertions
&lt;/h3&gt;

&lt;p&gt;Often you want to disclose something only after verifying it meets certain conditions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version 0.22;

export ledger allowedAmount: Uint&amp;lt;32&amp;gt;;

export circuit submitAmount(amount: Opaque&amp;lt;Uint&amp;lt;32&amp;gt;&amp;gt;): [] {
    let value = disclose(amount);
    assert(value &amp;lt;= allowedAmount, "Amount exceeds allowed limit");
    // Proceed with business logic using the disclosed value
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assertion runs in the ZK circuit. If it fails the entire transaction reverts. The amount is disclosed but only after proving it satisfies the constraint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 3: Disclosing Derived Values
&lt;/h3&gt;

&lt;p&gt;This is where selective disclosure becomes powerful. Instead of disclosing raw inputs you disclose a computed result that reveals only what is necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version 0.22;
import CompactStandardLibrary;

export ledger userEligibility: Map&amp;lt;Bytes&amp;lt;32&amp;gt;, bool&amp;gt;;

export circuit proveEligibility(
    birthYear: Opaque&amp;lt;Uint&amp;lt;16&amp;gt;&amp;gt;,
    currentYear: Uint&amp;lt;16&amp;gt;
): [] {
    let age = currentYear as Uint&amp;lt;32&amp;gt; - (birthYear as Uint&amp;lt;32&amp;gt;);
    let isAdult = age &amp;gt;= 18;

    const _sk = localSk();
    let pubKey = getDappPublicKey(_sk);

    userEligibility.insert(disclose(pubKey), disclose(isAdult));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user provides their birth year as a private input. The circuit computes their age and determines adulthood status. Only the boolean result &lt;code&gt;isAdult&lt;/code&gt; is disclosed. The actual birth year never leaves the private context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 4: Commit Now, Reveal Later
&lt;/h3&gt;

&lt;p&gt;This two phase pattern is essential for auctions, voting, and any scenario requiring a commitment period.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version 0.22;
import CompactStandardLibrary;

export ledger commitment: Bytes&amp;lt;32&amp;gt;;
export ledger revealedValue: Uint&amp;lt;32&amp;gt;;

export circuit commit(value: Opaque&amp;lt;Uint&amp;lt;32&amp;gt;&amp;gt;, salt: Opaque&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;): [] {
    let hash = persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        value as Bytes&amp;lt;32&amp;gt;,
        salt
    ]);
    commitment = disclose(hash);
}

export circuit reveal(value: Opaque&amp;lt;Uint&amp;lt;32&amp;gt;&amp;gt;, salt: Opaque&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;): [] {
    let computedHash = persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        value as Bytes&amp;lt;32&amp;gt;,
        salt
    ]);
    assert(computedHash == commitment, "Commitment mismatch");

    revealedValue = disclose(value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the commit phase the user submits a hash of their value and a salt. In the reveal phase they provide both original inputs. The circuit verifies the hash matches before disclosing the value. This prevents front running and ensures users cannot change their submission after seeing others.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Safe to Disclose vs What Leaks Privacy
&lt;/h2&gt;

&lt;p&gt;The line between safe and unsafe disclosure is not always obvious. Here is a framework for evaluating your disclosure decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safe to Disclose
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Aggregates and counts.&lt;/strong&gt; The total number of participants in an event reveals nothing about individual identities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Boolean results of private checks.&lt;/strong&gt; Knowing that someone is over 18 does not reveal their exact age.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Public keys derived with DApp specific hashing.&lt;/strong&gt; See the domain separation section below for why this matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hashes and commitments.&lt;/strong&gt; A hash without its preimage reveals nothing about the underlying data assuming sufficient entropy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enumerated states.&lt;/strong&gt; Disclosing that an auction is &lt;code&gt;OPEN&lt;/code&gt; or &lt;code&gt;CLOSED&lt;/code&gt; is necessary for coordination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unsafe to Disclose
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Direct personal identifiers.&lt;/strong&gt; Names, email addresses, government ID numbers. Never put these on chain even in encrypted form without careful consideration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linkable pseudonyms.&lt;/strong&gt; If you disclose the same public key across multiple interactions within the same DApp you create a linkage profile. Always use DApp specific key derivation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Precise numeric values when only a range is needed.&lt;/strong&gt; Disclosing an exact salary of 84750 when you only need to prove it exceeds 50000 leaks unnecessary information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correlatable timestamps.&lt;/strong&gt; The exact block height of a user's interaction combined with other disclosed data can create timing correlation attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Raw private keys or seeds.&lt;/strong&gt; This should be obvious but it bears repeating. Never write &lt;code&gt;disclose(localSk())&lt;/code&gt; in your contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Linkability Problem
&lt;/h3&gt;

&lt;p&gt;Consider this vulnerable pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// DO NOT USE - Vulnerable to cross interaction tracking
export circuit registerUser(): [] {
    const _sk = localSk();
    let pubKey = publicKey(_sk);  // Standard public key derivation
    registeredUsers.insert(disclose(pubKey));
}

export circuit submitVote(): [] {
    const _sk = localSk();
    let pubKey = publicKey(_sk);
    // Same pubKey used across circuits
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the same public key appears in multiple contracts or even multiple circuits within the same contract, an observer can link all of that user's activity together. This defeats the privacy guarantees you are trying to provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Separated Hashing for Cross Property Unlinkability
&lt;/h2&gt;

&lt;p&gt;Domain separation is the technique of generating different identifiers for the same user across different contexts. It ensures that an observer cannot link a user's activity in one part of your DApp to their activity in another.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pattern
&lt;/h3&gt;

&lt;p&gt;The Midnight example contracts demonstrate this pattern consistently. Here is the implementation from the Private Guest List contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export circuit getDappPublicKey(_sk: Bytes&amp;lt;32&amp;gt;): Bytes&amp;lt;32&amp;gt; {
    return persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        pad(32, "guest-list:pk:"),
        _sk
    ]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user's private key is hashed with a domain specific string. The resulting public key is unique to this DApp. Even if the same user interacts with another DApp their identifier will be completely different because the domain string differs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Domains Within a Single DApp
&lt;/h3&gt;

&lt;p&gt;You can extend this pattern to create separate unlinkable identities for different features within the same DApp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version 0.22;
import CompactStandardLibrary;

export circuit getVoterPublicKey(_sk: Bytes&amp;lt;32&amp;gt;): Bytes&amp;lt;32&amp;gt; {
    return persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        pad(32, "election:voter:"),
        _sk
    ]);
}

export circuit getCandidatePublicKey(_sk: Bytes&amp;lt;32&amp;gt;): Bytes&amp;lt;32&amp;gt; {
    return persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        pad(32, "election:candidate:"),
        _sk
    ]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A user who is both a voter and a candidate in the same election DApp will have two different unlinkable public keys. Their voting activity cannot be correlated with their candidate registration.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Battleship Example
&lt;/h3&gt;

&lt;p&gt;The Battleship contract uses domain separation to prevent cross game tracking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;circuit getDappPubKey(_sk: Bytes&amp;lt;32&amp;gt;): Bytes&amp;lt;32&amp;gt; {
    return persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        pad(32, "battleship:pk:"),
        _sk
    ]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each game instance could further extend this by incorporating a game ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;circuit getGameSpecificPubKey(_sk: Bytes&amp;lt;32&amp;gt;, gameId: Bytes&amp;lt;32&amp;gt;): Bytes&amp;lt;32&amp;gt; {
    return persistentHash&amp;lt;Vector&amp;lt;3, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        pad(32, "battleship:game:"),
        gameId,
        _sk
    ]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the same player has a different unlinkable identity in every game they play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy Audit Checklist for Developers
&lt;/h2&gt;

&lt;p&gt;Before deploying a Compact contract conduct this systematic privacy audit. Each question forces you to examine a specific aspect of your disclosure patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Disclosure Inventory
&lt;/h3&gt;

&lt;p&gt;List every occurrence of &lt;code&gt;disclose()&lt;/code&gt; in your contract. For each one answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What specific data is being disclosed?&lt;/li&gt;
&lt;li&gt;Why must this data be public?&lt;/li&gt;
&lt;li&gt;Could a proof of a property replace the raw data?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you cannot justify why something must be public reconsider whether it belongs on chain at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Linkability Analysis
&lt;/h3&gt;

&lt;p&gt;For each disclosed identifier ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this identifier appear in multiple circuits within the same contract?&lt;/li&gt;
&lt;li&gt;Does this identifier appear in other contracts deployed by this DApp?&lt;/li&gt;
&lt;li&gt;Could an observer correlate this identifier with activity in other DApps?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any answer is yes implement domain separation using &lt;code&gt;persistentHash&lt;/code&gt; with a unique domain string.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Timing Attack Surface
&lt;/h3&gt;

&lt;p&gt;Examine your contract for timing sensitive disclosures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are there state transitions that reveal when specific users act?&lt;/li&gt;
&lt;li&gt;Do you disclose counts or sizes that change in predictable ways based on user behavior?&lt;/li&gt;
&lt;li&gt;Could block height combined with other disclosures create a timing fingerprint?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consider adding random delays or batching operations where appropriate.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Commitment Scheme Validation
&lt;/h3&gt;

&lt;p&gt;If your contract uses commit reveal patterns verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is a salt or nonce included in the commitment hash?&lt;/li&gt;
&lt;li&gt;Does the salt have sufficient entropy? Hardcoded or predictable salts offer no protection.&lt;/li&gt;
&lt;li&gt;Is the reveal phase protected against replay attacks?&lt;/li&gt;
&lt;li&gt;What prevents a user from refusing to reveal after the commitment period?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Aggregation Check
&lt;/h3&gt;

&lt;p&gt;When disclosing aggregate data verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the aggregate sufficiently large to provide k anonymity? A group of two is not private.&lt;/li&gt;
&lt;li&gt;Could an attacker manipulate inputs to isolate a specific user's contribution?&lt;/li&gt;
&lt;li&gt;Are you disclosing the aggregate before all contributions are finalized?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Cross Circuit Information Flow
&lt;/h3&gt;

&lt;p&gt;Consider what an observer learns by comparing the public outputs of different circuits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does circuit A disclose something that circuit B later proves about the same user?&lt;/li&gt;
&lt;li&gt;Could timing analysis across circuits create a linkage?&lt;/li&gt;
&lt;li&gt;Do different circuits use the same derived public key?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  7. Emergency Stop Consideration
&lt;/h3&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a privacy vulnerability is discovered can the contract be paused?&lt;/li&gt;
&lt;li&gt;Do users have a way to withdraw or nullify their private data if needed?&lt;/li&gt;
&lt;li&gt;Is there a mechanism for users to rotate their identifiers?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Documentation Completeness
&lt;/h3&gt;

&lt;p&gt;Finally verify that your contract includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comments explaining what each disclosed value represents&lt;/li&gt;
&lt;li&gt;Documentation of the privacy guarantees and limitations&lt;/li&gt;
&lt;li&gt;Clear warnings about what information becomes public and when&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Complete Example: Private Age Verification
&lt;/h2&gt;

&lt;p&gt;Let us put these patterns together into a complete contract that demonstrates selective disclosure principles correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma language_version 0.22;
import CompactStandardLibrary;

export ledger verifiedAdults: Set&amp;lt;Bytes&amp;lt;32&amp;gt;&amp;gt;;
export ledger verificationCount: Counter;

witness localSk(): Bytes&amp;lt;32&amp;gt;;

constructor() {
    // No constructor initialization needed
}

export circuit verifyAge(
    birthYear: Opaque&amp;lt;Uint&amp;lt;16&amp;gt;&amp;gt;,
    currentYear: Uint&amp;lt;16&amp;gt;
): [] {
    // Compute age without disclosing birth year
    let age = currentYear as Uint&amp;lt;32&amp;gt; - (birthYear as Uint&amp;lt;32&amp;gt;);
    let isAdult = age &amp;gt;= 18;

    // Only disclose the boolean result
    assert(disclose(isAdult), "You must be 18 or older");

    // Generate DApp specific public key for unlinkability
    const _sk = localSk();
    let dappPubKey = getDappPublicKey(_sk);

    // Record verification without linking to other DApps
    verifiedAdults.insert(disclose(dappPubKey));
    verificationCount.increment(1);
}

export circuit getDappPublicKey(_sk: Bytes&amp;lt;32&amp;gt;): Bytes&amp;lt;32&amp;gt; {
    return persistentHash&amp;lt;Vector&amp;lt;2, Bytes&amp;lt;32&amp;gt;&amp;gt;&amp;gt;([
        pad(32, "age-verification:pk:"),
        _sk
    ]);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This contract demonstrates several best practices:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user's birth year is private and never disclosed&lt;/li&gt;
&lt;li&gt;Only the boolean adulthood status is disclosed through the assertion&lt;/li&gt;
&lt;li&gt;The user is recorded using a DApp specific public key preventing cross DApp tracking&lt;/li&gt;
&lt;li&gt;The verification count is public allowing transparency about total verifications without revealing who was verified&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Follow-up the clear further explanation README of my commit and gets your code compiled easily:  &lt;a href="https://github.com/Ameerabdulaleem/midnight_network_selective_disclosure_patterns.git" rel="noopener noreferrer"&gt;https://github.com/Ameerabdulaleem/midnight_network_selective_disclosure_patterns.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selective disclosure is a skill that improves with practice. Here are concrete ways to deepen your understanding:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Study the official examples.&lt;/strong&gt; The &lt;a href="https://docs.midnight.network/examples/contracts/private-guest-list" rel="noopener noreferrer"&gt;Private Guest List&lt;/a&gt;, &lt;a href="https://docs.midnight.network/examples/contracts/election" rel="noopener noreferrer"&gt;Election&lt;/a&gt;, and &lt;a href="https://docs.midnight.network/examples/contracts/private-reserve-auction" rel="noopener noreferrer"&gt;Private Reserve Auction&lt;/a&gt; contracts all demonstrate sophisticated disclosure patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use the Midnight MCP tool.&lt;/strong&gt; Before submitting any work, run your Compact code through &lt;code&gt;midnight-mcp&lt;/code&gt; to validate compilation and catch common mistakes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Join the community.&lt;/strong&gt; The &lt;a href="https://discord.com/invite/midnightnetwork" rel="noopener noreferrer"&gt;Midnight Discord&lt;/a&gt; and &lt;a href="https://forum.midnight.network/" rel="noopener noreferrer"&gt;Developer Forum&lt;/a&gt; are active with developers working through the same privacy challenges you are.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Apply the audit checklist to your own contracts.&lt;/strong&gt; The best way to internalize these patterns is to critically examine your own code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Selective disclosure is what makes Midnight uniquely suited for real world applications that require both decentralization and data protection. Master these patterns and you will build DApps that are not just functional but genuinely private.&lt;/p&gt;

</description>
      <category>midnight</category>
      <category>compact</category>
      <category>zeroknowledge</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Rust Ownership Explained for Solidity Developers: The Mindset Shift That Changes Everything in Web3</title>
      <dc:creator>Ameer Abdulaleem</dc:creator>
      <pubDate>Mon, 30 Mar 2026 14:37:34 +0000</pubDate>
      <link>https://forem.com/ameer_0699/rust-ownership-explained-for-solidity-developers-the-mindset-shift-that-changes-everything-in-web3-4j68</link>
      <guid>https://forem.com/ameer_0699/rust-ownership-explained-for-solidity-developers-the-mindset-shift-that-changes-everything-in-web3-4j68</guid>
      <description>&lt;p&gt;If you have been writing smart contracts in Solidity and now want to learn Rust for Solana, Polkadot, or NEAR, you will feel a big change. The syntax is different, but the real challenge is how you think about memory.&lt;/p&gt;

&lt;p&gt;In Solidity the Ethereum Virtual Machine handles memory for you. Rust asks you to manage memory yourself with a simple but powerful system called &lt;strong&gt;Ownership&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This one concept is the biggest mindset shift. Once you understand it, the rest of Rust feels natural and safe. Let me explain it step by step in plain English.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 3 Key Things About Rust Ownership
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ownership Rules&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Every piece of data has exactly one owner. When that owner goes out of scope, Rust automatically drops the data and frees the memory. No garbage collector needed. This keeps your program fast and predictable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Borrowing&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You do not always need to move ownership. You can borrow the data instead.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;T&lt;/code&gt; is an immutable borrow – many people can read it at the same time.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;amp;mut T&lt;/code&gt; is a mutable borrow – only one person can change it at a time.
The compiler checks these rules before your code runs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lifetimes&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Rust tracks how long a reference stays valid. It does this at compile time so you never use data that has already been dropped. This stops dangerous bugs like “use after free”.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Simple Code Examples You Can Try Right Now
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Ownership Move&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Solana is fast"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// ownership moves to s2&lt;/span&gt;
    &lt;span class="c1"&gt;// println!("{}", s1);          // This line will not compile&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// Only s2 can use the data now&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2: Borrowing in Action&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;Rustfn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Rust for Web3"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reader1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// anyone can read&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;reader2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// multiple readers are fine&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// only one writer allowed&lt;/span&gt;
    &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="nf"&gt;.push_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" developers"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 3: Lifetimes (easy version)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;Rustfn&lt;/span&gt; &lt;span class="n"&gt;longest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;'a&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;first&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;second&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Think of Memory Like a Library Book&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine every piece of data is a book in a library.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ownership = only one library card per book. When you finish with the book, it goes back on the shelf automatically.&lt;/li&gt;
&lt;li&gt;Borrowing = you can read the book (&amp;amp;T) or write notes in it (&amp;amp;mut T). Many people can read at once, but only one person can write.&lt;/li&gt;
&lt;li&gt;Lifetimes = the due date on the card. The librarian (Rust compiler) checks the date before you leave so the book never disappears while someone is still using it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This system feels strict at first, but it protects you. You get memory safety without slowing down your code – perfect for high-speed blockchains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Matters for Real Web3 Projects&lt;/strong&gt;&lt;br&gt;
In blockchain, one small memory bug can lose millions of dollars. Rust’s ownership rules catch those bugs before your contract even runs. That is why Solana, Polkadot, and NEAR chose Rust. Companies building serious infrastructure want developers who understand this safety mindset.&lt;br&gt;
How to Practice Ownership Today&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Write a small Rust program that moves ownership and see the compiler error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change it to use borrowing and watch the error disappear.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try the longest function above with strings of different lengths.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do this for 15 minutes and you will feel the shift.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
Learning Rust ownership is like learning to drive a manual car after years of automatic. It feels harder at first, but once you get it, you have much more control and confidence.&lt;/p&gt;

&lt;p&gt;This is only the second article in my Rust for Web3 series. &lt;/p&gt;

&lt;p&gt;Next we will cover Traits and how they let you build reusable DeFi components.&lt;/p&gt;

&lt;p&gt;If this helped you understand the mindset shift, drop a comment below. Tell me what part was confusing before and clear now. I read every comment and I love helping new Web3 developers.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ownership</category>
      <category>web3</category>
      <category>solidity</category>
    </item>
    <item>
      <title>The Three Reasons RUST is Winning Web3 in 2026: Safety, Performance, and Fearless Concurrency</title>
      <dc:creator>Ameer Abdulaleem</dc:creator>
      <pubDate>Sun, 29 Mar 2026 20:02:22 +0000</pubDate>
      <link>https://forem.com/ameer_0699/why-rust-is-taking-over-web3-development-in-2026-memory-safety-zero-cost-abstractions-and-8bl</link>
      <guid>https://forem.com/ameer_0699/why-rust-is-taking-over-web3-development-in-2026-memory-safety-zero-cost-abstractions-and-8bl</guid>
      <description>&lt;p&gt;If you've been following blockchain development lately, you've probably noticed a clear trend: major projects like Solana, Polkadot, and NEAR are all built using Rust. &lt;/p&gt;

&lt;p&gt;This is not just hype. Rust solves fundamental challenges when building secure, high-performance decentralized systems where a single bug can cost millions.&lt;/p&gt;

&lt;p&gt;At its core, Rust brings two revolutionary features that make it perfect for blockchain infrastructure.&lt;/p&gt;

&lt;p&gt;First, Rust delivers guaranteed memory safety without a garbage collector. This means the compiler catches dangerous bugs like null pointer dereferencing and data races at compile time, before your code ever runs. In blockchain, where security is non-negotiable, this protection is essential.&lt;/p&gt;

&lt;p&gt;Second, Rust offers zero-cost abstractions. You can write clean, high-level code that feels modern and readable, yet it compiles down to performance that rivals hand-written C or C++. For blockchains that need to handle thousands of transactions per second, this combination of readability and raw speed is a game-changer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Three Core Advantages of Rust
&lt;/h3&gt;

&lt;p&gt;Here are the three pillars that make Rust stand out for Web3:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory Safety Guarantees&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Rust's ownership system and borrow checker ensure that common catastrophic bugs (null pointers, data races) are impossible at runtime. The compiler acts like a strict security auditor, stopping these issues before deployment. This is why teams building critical infrastructure trust Rust.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero-Cost Abstractions&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You get high-level features like iterators and pattern matching without any performance penalty. The code you write reads beautifully but runs as efficiently as low-level C. This lets developers focus on logic instead of micro-optimizations while still hitting the speed blockchains demand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fearless Concurrency&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Writing safe parallel code is notoriously error-prone in most languages. Rust's type system enforces thread safety at compile time, so you can confidently use modern multi-core processors for validators, indexers, and high-throughput nodes without subtle bugs that are hard to debug.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Think of It Like Building a Championship Race Car
&lt;/h3&gt;

&lt;p&gt;Building a blockchain is like engineering a high-stakes race car. You need blazing speed (performance) but zero tolerance for mechanical failure (security).  &lt;/p&gt;

&lt;p&gt;Other languages often force a trade-off: build something fast that might crash, or something safe that is too slow.  &lt;/p&gt;

&lt;p&gt;Rust lets you have both. Its memory safety provides an unbreakable chassis, zero-cost abstractions deliver advanced aerodynamics for top speed, and fearless concurrency ensures perfect engine synchronization. You get maximum performance without compromising reliability.&lt;/p&gt;

&lt;p&gt;This is exactly why Solana, Polkadot, NEAR, and many other high-performance chains chose Rust for their core infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started with Rust for Web3
&lt;/h3&gt;

&lt;p&gt;If you're coming from JavaScript, Python, or Solidity, the biggest mindset shift is embracing ownership and borrowing. Once that clicks, the rest (Cargo, traits, error handling with Result and Option) builds on a solid, safe foundation.&lt;/p&gt;

&lt;p&gt;Rust is not just another language trend. It is an architectural upgrade for building the next generation of scalable, secure blockchains.&lt;/p&gt;

&lt;p&gt;What has been your experience learning Rust for Web3? Are you building on Solana, Polkadot, NEAR, or another ecosystem? Share your thoughts or questions in the comments.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;: rust, web3, blockchain, solana, polkadot, programming, rustlang, systemsprogramming&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cover Image Suggestion&lt;/strong&gt;: Use one of your existing carousels or race car analogy visuals (dark theme works great on Dev.to). If you need a new one generated, let me know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Series Note&lt;/strong&gt;: This is the first article in a series on Rust for Web3 developers. &lt;br&gt;
Next up: Deep dive into Rust Ownership explained like a library.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>web3</category>
      <category>webdev</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
