<?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>DEV Community: 이관호(Gwanho LEE)</title>
    <description>The latest articles on DEV Community by 이관호(Gwanho LEE) (@_56d7718cea8fe00ec1610).</description>
    <link>https://dev.to/_56d7718cea8fe00ec1610</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%2F3014905%2F6e49ee67-f436-491e-b814-4732ec126a40.jpeg</url>
      <title>DEV Community: 이관호(Gwanho LEE)</title>
      <link>https://dev.to/_56d7718cea8fe00ec1610</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_56d7718cea8fe00ec1610"/>
    <language>en</language>
    <item>
      <title>Backend Architecture Fundamentals_part1</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Wed, 11 Mar 2026 09:57:16 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/backend-architecture-fundamentalspart1-10ih</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/backend-architecture-fundamentalspart1-10ih</guid>
      <description>&lt;p&gt;In this article, I summarize the core backend architecture concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load Balancing&lt;/li&gt;
&lt;li&gt;Asynchronous Concurrency&lt;/li&gt;
&lt;li&gt;Caching (Redis)&lt;/li&gt;
&lt;li&gt;Database Scaling (Sharding &amp;amp; Replicas)&lt;/li&gt;
&lt;li&gt;API Design&lt;/li&gt;
&lt;li&gt;API Security&lt;/li&gt;
&lt;li&gt;Monolithic vs Microservices Architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to understand &lt;strong&gt;why these patterns exist&lt;/strong&gt; and &lt;strong&gt;how they help systems scale&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. Load Balancing
&lt;/h1&gt;

&lt;p&gt;When an application receives many user requests, sending all requests to a single server can quickly overwhelm it. A &lt;strong&gt;load balancer&lt;/strong&gt; distributes incoming traffic across multiple servers so that no single server becomes overloaded.&lt;/p&gt;

&lt;p&gt;This improves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reliability&lt;/li&gt;
&lt;li&gt;scalability&lt;/li&gt;
&lt;li&gt;fault tolerance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If one server fails, the load balancer routes traffic to other healthy servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Architecture
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Users
            |
            v
        Load Balancer
             |
    |        |         |
|Server A|  |Server B|  |Server|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Example (NGINX Load Balancer)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;backend_servers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;app1.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;app2.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="s"&gt;app3.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend_servers&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  2. Asynchronous Concurrency
&lt;/h1&gt;

&lt;p&gt;Modern backend systems must handle thousands of requests simultaneously. Blocking threads while waiting for database queries or network calls reduces performance.&lt;/p&gt;

&lt;p&gt;Instead, many systems use &lt;strong&gt;asynchronous execution&lt;/strong&gt;, allowing other tasks to run while waiting for I/O operations.&lt;/p&gt;

&lt;p&gt;Rust commonly uses the &lt;strong&gt;Tokio runtime&lt;/strong&gt; for asynchronous programming.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (Rust Async Server)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;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;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;TcpListener&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1:8080"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="nf"&gt;.accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;move&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;"Handling new request"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  3. Caching (Redis)
&lt;/h1&gt;

&lt;p&gt;Many backend systems repeatedly fetch the same data (for example: product details or user sessions). Querying the database every time increases latency.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;cache&lt;/strong&gt; stores frequently accessed data in memory, allowing extremely fast reads.&lt;/p&gt;

&lt;p&gt;Redis is a popular &lt;strong&gt;in-memory key-value store&lt;/strong&gt; used as a cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typical Data Flow
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        Client Request
              |
              v
         Redis Cache
              |
            (Miss)
              |
           Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If the data exists in Redis, the system returns it immediately without querying the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (Redis in Rust)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RedisResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&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="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"redis://127.0.0.1/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&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;con&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.get_connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="nf"&gt;.set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user:1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tony"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;con&lt;/span&gt;&lt;span class="nf"&gt;.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user:1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&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;"User name: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;Redis dramatically reduces latency because &lt;strong&gt;data is stored in memory instead of disk&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Database Scaling
&lt;/h1&gt;

&lt;p&gt;As applications grow, a single database may become a bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read Replicas
&lt;/h2&gt;

&lt;p&gt;One primary database handles writes, while multiple replicas handle read requests.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Write
     App --------------&amp;gt; Primary DB
                  |
               Replication
                  |
         ---------------------
         |        |         |
    Replica1   Replica2   Replica3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This reduces load on the primary database.&lt;/p&gt;




&lt;h2&gt;
  
  
  Database Sharding
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Sharding&lt;/strong&gt; means splitting a large database into smaller databases called shards.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Shard 1 → Users 1 - 1,000,000&lt;br&gt;&lt;br&gt;
Shard 2 → Users 1,000,001 - 2,000,000&lt;br&gt;&lt;br&gt;
Shard 3 → Users 2,000,001 - 3,000,000  &lt;/p&gt;

&lt;p&gt;This distributes the workload across multiple database servers.&lt;/p&gt;


&lt;h1&gt;
  
  
  5. API Design Principles
&lt;/h1&gt;

&lt;p&gt;A well-designed API is predictable and easy to use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Resource-Based Endpoints
&lt;/h2&gt;

&lt;p&gt;Use nouns instead of verbs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET    /users
GET    /users/1
POST   /users
DELETE /users/1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  API Versioning
&lt;/h2&gt;

&lt;p&gt;Versioning allows backward compatibility when APIs evolve.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/v1/users
/api/v2/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  6. API Security
&lt;/h1&gt;

&lt;p&gt;Security is critical in backend systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limiting
&lt;/h3&gt;

&lt;p&gt;Limit the number of requests a user can make in a given time period.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;100 requests per minute per IP&lt;/p&gt;




&lt;h3&gt;
  
  
  Firewalls
&lt;/h3&gt;

&lt;p&gt;Firewalls act as &lt;strong&gt;traffic filters&lt;/strong&gt; and block suspicious traffic before it reaches the server.&lt;/p&gt;




&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;p&gt;Authentication ensures only authorized users access the system.&lt;/p&gt;

&lt;p&gt;Common methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Keys&lt;/li&gt;
&lt;li&gt;OAuth&lt;/li&gt;
&lt;li&gt;JWT (JSON Web Tokens)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example concept:&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;validate_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"valid_token"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  7. Monolithic vs Microservices Architecture
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Monolithic Architecture
&lt;/h2&gt;

&lt;p&gt;All application features exist in a single codebase.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simple architecture&lt;/li&gt;
&lt;li&gt;easier initial development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;harder to scale&lt;/li&gt;
&lt;li&gt;difficult deployments&lt;/li&gt;
&lt;li&gt;tightly coupled code&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Microservices Architecture
&lt;/h2&gt;

&lt;p&gt;Microservices divide the system into independent services.&lt;/p&gt;

&lt;p&gt;Example services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User Service&lt;/li&gt;
&lt;li&gt;Payment Service&lt;/li&gt;
&lt;li&gt;Order Service&lt;/li&gt;
&lt;li&gt;Notification Service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each service can scale and deploy independently.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final keywords
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;high traffic&lt;/li&gt;
&lt;li&gt;reliability&lt;/li&gt;
&lt;li&gt;&lt;p&gt;scalability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load balancing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Async concurrency&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redis caching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database sharding&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secure API design&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microservice architecture&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>microservices</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deep Dive into `mithril-aggregator`: Core Responsibilities, HTTP Boundaries, and Certificate/Artifact Production</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Sat, 28 Feb 2026 13:59:58 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/deep-dive-into-mithril-aggregator-core-responsibilities-http-boundaries-and-3ip5</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/deep-dive-into-mithril-aggregator-core-responsibilities-http-boundaries-and-3ip5</guid>
      <description>&lt;h2&gt;
  
  
  Why I Studied &lt;code&gt;mithril-aggregator&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;After reading the Mithril client modules and contributing small fixes, I realized that the &lt;strong&gt;aggregator&lt;/strong&gt; is the center of the whole Mithril system. The signer produces individual signatures, and the client verifies certificates and consumes artifacts, but the aggregator is where everything converges: it coordinates signers, collects signatures, produces Mithril certificates, and serves certified artifacts through HTTP endpoints.&lt;/p&gt;

&lt;p&gt;From an engineering perspective, the aggregator is a great module to study because it contains many real-world infrastructure concerns: state machines, persistence, API boundaries, resource limits, and the “correctness glue” that ensures protocol outputs are verifiable. This post summarizes what I learned about the aggregator’s role, its internal structure, and the practical points where reliability and security matters the most.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Aggregator Does (High-level Responsibility)
&lt;/h2&gt;

&lt;p&gt;The aggregator’s job can be summarized in one sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Collect enough stake-backed signer signatures for an open message and produce a certificate + artifacts that clients can verify.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More concretely, the aggregator does the following:&lt;/p&gt;

&lt;p&gt;1) Maintains &lt;strong&gt;epoch context&lt;/strong&gt; (epoch settings, stake distribution, protocol parameters).&lt;br&gt;&lt;br&gt;
2) Accepts &lt;strong&gt;signer registration&lt;/strong&gt; and signature submissions through HTTP APIs.&lt;br&gt;&lt;br&gt;
3) Selects or computes &lt;strong&gt;open messages&lt;/strong&gt; that must be certified (snapshots, stake distributions, transactions, etc.).&lt;br&gt;&lt;br&gt;
4) Verifies incoming signatures and checks quorum/threshold conditions.&lt;br&gt;&lt;br&gt;
5) Aggregates individual signatures into a &lt;strong&gt;multi-signature&lt;/strong&gt; and seals it into a &lt;strong&gt;Mithril certificate&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
6) Builds and publishes certified &lt;strong&gt;artifacts&lt;/strong&gt; (snapshots, proofs, metadata).&lt;br&gt;&lt;br&gt;
7) Serves data to clients via a stable HTTP API: certificates, artifact listings, artifact downloads, protocol configuration, metrics, and status.&lt;/p&gt;

&lt;p&gt;A crucial design property is: the aggregator is often described as “trustless.” That does not mean “it can’t cause trouble,” but it means the correctness of its outputs can be checked by clients using cryptography and certificate chains.&lt;/p&gt;




&lt;h2&gt;
  
  
  Aggregator Architecture (Key Internal Areas)
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;mithril-aggregator&lt;/code&gt; crate is large, but it becomes manageable when you group it into a few major responsibilities:&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Runtime and state machine
&lt;/h3&gt;

&lt;p&gt;The aggregator runs continuously. It typically uses a state machine loop to drive epoch transitions, open message creation, signature collection, and maintenance tasks. This is where liveness and correctness meet: the aggregator must progress through states safely without getting stuck.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) HTTP server boundary (trust boundary)
&lt;/h3&gt;

&lt;p&gt;The aggregator exposes routes for signers and clients. This is a major trust boundary because request bodies and inputs are untrusted. Good engineering requires early validation, strict parsing, and resource safety (limits, timeouts, and predictable error behavior).&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Persistence layer (SQLite and repositories)
&lt;/h3&gt;

&lt;p&gt;Certificates, open messages, signer registrations, stake pools, signatures, and artifact metadata are stored in a database. Persistence is critical because the aggregator must survive restarts and maintain a consistent view of protocol history.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Artifact pipeline and proof generation
&lt;/h3&gt;

&lt;p&gt;The aggregator can certify multiple kinds of data. It builds artifacts (snapshots, stake distributions, transactions sets), computes their digests deterministically, and publishes them in a way clients can verify.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Data Moves Through the Aggregator?
&lt;/h2&gt;

&lt;p&gt;The aggregator receives different classes of data from different actors.&lt;/p&gt;

&lt;h3&gt;
  
  
  From signers (SPOs)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Signer registration payloads (identity, verification key material, version metadata)&lt;/li&gt;
&lt;li&gt;Signature submissions for signing rounds&lt;/li&gt;
&lt;li&gt;“won indexes” from the lottery system (justification of eligibility)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  To clients (end users / infra tools)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Certificates (including certificate chain)&lt;/li&gt;
&lt;li&gt;Artifact listings (available snapshots, stake distributions, transaction artifacts)&lt;/li&gt;
&lt;li&gt;Artifact downloads (snapshot archive, proof data, metadata)&lt;/li&gt;
&lt;li&gt;Protocol configuration and status endpoints (for diagnostics)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A key engineering insight: signer-facing endpoints are often write-heavy and must handle bursts; client-facing endpoints are read-heavy and must scale for downloads. These have very different performance and security concerns.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Aggregator Happy Path (End-to-End)
&lt;/h2&gt;

&lt;p&gt;A simplified “happy path” flow looks like this:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Startup&lt;/strong&gt;&lt;br&gt;
The aggregator loads configuration, initializes database/repositories, and starts the HTTP server plus runtime loop.&lt;/p&gt;

&lt;p&gt;2) &lt;strong&gt;Epoch initialization&lt;/strong&gt;&lt;br&gt;
When a new epoch starts, it refreshes epoch settings and stake distribution and prepares for the next signing period.&lt;/p&gt;

&lt;p&gt;3) &lt;strong&gt;Signer registration&lt;/strong&gt;&lt;br&gt;
Signers register their keys and metadata. The aggregator stores and validates registrations.&lt;/p&gt;

&lt;p&gt;4) &lt;strong&gt;Open message creation&lt;/strong&gt;&lt;br&gt;
The aggregator determines the next “signed entity” to certify (for example, a snapshot digest). It stores this as an open message.&lt;/p&gt;

&lt;p&gt;5) &lt;strong&gt;Signature collection&lt;/strong&gt;&lt;br&gt;
Signers submit signatures for this open message. The aggregator validates and stores them.&lt;/p&gt;

&lt;p&gt;6) &lt;strong&gt;Quorum reached&lt;/strong&gt;&lt;br&gt;
Once enough stake-backed signatures are collected, the certifier aggregates them into a multi-signature.&lt;/p&gt;

&lt;p&gt;7) &lt;strong&gt;Certificate creation&lt;/strong&gt;&lt;br&gt;
The aggregator creates a new certificate that links to the previous certificate (certificate chain).&lt;/p&gt;

&lt;p&gt;8) &lt;strong&gt;Artifact publication&lt;/strong&gt;&lt;br&gt;
The aggregator builds/publishes the artifact and serves it, along with certificate chain data, to clients.&lt;/p&gt;

&lt;p&gt;Clients then download the artifact + certificate and verify it independently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security and Reliability Boundaries (Where Bugs Matter Most)
&lt;/h2&gt;

&lt;p&gt;Even if the protocol is “cryptographically trustless,” the aggregator is still an internet-facing service. A few practical engineering boundaries matter a lot:&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Unbounded request body sizes (DoS risk)
&lt;/h3&gt;

&lt;p&gt;If a route uses &lt;code&gt;warp::body::json()&lt;/code&gt; without a request size limit, a remote client can attempt to send arbitrarily large bodies. That can force the server to buffer large payloads and consume memory/CPU during parsing. This is why adding &lt;code&gt;warp::body::content_length_limit(...)&lt;/code&gt; before JSON parsing is a practical defense-in-depth improvement.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Ordering of validation
&lt;/h3&gt;

&lt;p&gt;A best practice is: reject quickly before doing heavy work. For example, validate headers/auth/limits before parsing large bodies and before expensive cryptographic checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) File and archive safety
&lt;/h3&gt;

&lt;p&gt;Artifacts and snapshots can be large and often involve compression and archives. Unpacking/packing must be safe against path traversal and tarbomb-style resource exhaustion in any path that touches untrusted archive content.&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Consistency invariants across epoch boundaries
&lt;/h3&gt;

&lt;p&gt;The aggregator must not accidentally mix epoch context, stake distribution, or open message state across epochs. This is a classic source of subtle bugs in state-machine-driven distributed systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important Invariants (What Must Always Be True)
&lt;/h2&gt;

&lt;p&gt;When reading the aggregator code, these invariants are useful for auditing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A certificate must link correctly to the previous certificate (certificate chain integrity).&lt;/li&gt;
&lt;li&gt;A certificate must only be issued when quorum conditions are satisfied for the open message.&lt;/li&gt;
&lt;li&gt;The artifact digest must match the message that was signed and certified.&lt;/li&gt;
&lt;li&gt;Signer registration must be validated and tied to the correct epoch context.&lt;/li&gt;
&lt;li&gt;The system must not panic or crash due to malformed inputs on public endpoints; it should return structured errors and remain operational.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Practical Engineering Takeaways
&lt;/h2&gt;

&lt;p&gt;Studying the aggregator teaches valuable “real systems” skills beyond cryptography:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to build and verify protocol outputs with durable persistence&lt;/li&gt;
&lt;li&gt;how to handle public HTTP boundaries safely&lt;/li&gt;
&lt;li&gt;how to manage long-running state machines without fragile defaults&lt;/li&gt;
&lt;li&gt;how to reason about correctness invariants across epochs and rounds&lt;/li&gt;
&lt;li&gt;how to implement defense-in-depth (application + infrastructure + protocol)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of this, auditing and contributing to the aggregator is high signal for hiring: it shows that you can work on production-grade distributed infrastructure, not just implement algorithms.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>blockchain</category>
      <category>mithril</category>
      <category>web3</category>
    </item>
    <item>
      <title>`mithril-signer`: State Machine Flow, KES Period, and Safe Registration</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Sat, 28 Feb 2026 13:58:13 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/mithril-signer-state-machine-flow-kes-period-and-safe-registration-2a5a</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/mithril-signer-state-machine-flow-kes-period-and-safe-registration-2a5a</guid>
      <description>&lt;h2&gt;
  
  
  Why I Studied &lt;code&gt;mithril-signer&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;After contributing to the Mithril project and reading the client/aggregator modules, I realized that the &lt;strong&gt;signer&lt;/strong&gt; is one of the most critical components in the whole protocol. The signer is operated by stake pool operators (SPOs) and is responsible for producing the &lt;strong&gt;individual signatures&lt;/strong&gt; that the aggregator later combines into a Mithril certificate. If signers crash or register incorrect data, then participation drops and certificate production can become slow or unstable. So understanding the signer is not only “reading code,” but understanding the real operational reliability of Mithril.&lt;/p&gt;

&lt;p&gt;In this post, I summarize how &lt;code&gt;mithril-signer&lt;/code&gt; works from an engineer’s point of view: the state machine (status) flow, how registration and signing rounds work, what kind of data moves between signer and aggregator, and why &lt;strong&gt;KES period&lt;/strong&gt; handling is a correctness-sensitive part of registration.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Signer Does (High-level Responsibility)
&lt;/h2&gt;

&lt;p&gt;You can think of the signer as a long-running daemon that repeats the following loop:&lt;/p&gt;

&lt;p&gt;1) Observe chain context from a Cardano node (epoch, chain tip / slot context, and other values needed by the protocol).&lt;br&gt;&lt;br&gt;
2) Register itself for the current epoch (publish its verification key material and metadata so it can participate).&lt;br&gt;&lt;br&gt;
3) When the aggregator opens a message to be certified, run the lottery locally to decide eligibility.&lt;br&gt;&lt;br&gt;
4) If eligible, produce one or more signatures and submit them to the aggregator.&lt;br&gt;&lt;br&gt;
5) Persist local “already signed” markers so it does not re-sign the same entity repeatedly.&lt;br&gt;&lt;br&gt;
6) Retry safely when the node is still syncing or any dependency is temporarily unavailable.&lt;/p&gt;

&lt;p&gt;The most important detail here is that the signer must behave safely under real-world conditions: node syncing, transient network failures, partial DB corruption, and other imperfect states. Reliability is part of the protocol’s real security because low signer participation affects liveness.&lt;/p&gt;




&lt;h2&gt;
  
  
  Signer Status / State Machine (How the Process Moves)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mithril-signer&lt;/code&gt; is implemented as a state machine. The exact enum names can vary by version, but the conceptual states are stable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;INIT&lt;/strong&gt;: signer starts, loads configuration, initializes DB, logger, and internal services.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UNREGISTERED&lt;/strong&gt;: signer is not registered for the current epoch. It should attempt registration (or wait if registration round is not open).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;READY_TO_SIGN&lt;/strong&gt;: signer is registered and eligible to participate in signing rounds.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REGISTERED_NOT_ABLE_TO_SIGN&lt;/strong&gt;: signer is registered but cannot sign for some reason (not eligible in this epoch/round, stake conditions, or protocol constraints).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A key engineering point is that the runtime should not crash for ordinary “not ready yet” situations. In many flows, the correct behavior is to keep state and retry later, not panic or register with fake data.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Data Moves Between Signer and Aggregator?
&lt;/h2&gt;

&lt;p&gt;The signer communicates with the aggregator through HTTP endpoints. The data exchange has two main categories:&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Registration data
&lt;/h3&gt;

&lt;p&gt;This usually includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;signer identity (pool id / party id),&lt;/li&gt;
&lt;li&gt;signer verification key material,&lt;/li&gt;
&lt;li&gt;protocol metadata (version, network),&lt;/li&gt;
&lt;li&gt;additional fields required by the protocol for the epoch (e.g., KES-related fields depending on the build path).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happens on startup and at epoch transitions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Signature submission data
&lt;/h3&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a signature (cryptographic bytes encoded in JSON),&lt;/li&gt;
&lt;li&gt;“won indexes” (the lottery results that justify why the signer can submit signatures),&lt;/li&gt;
&lt;li&gt;identifiers tying this signature to the current open message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happens repeatedly during the operations phase whenever the aggregator has an open message.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is “Beacon” and Why Do We Store It?
&lt;/h2&gt;

&lt;p&gt;In the signer code, “beacon” is a compact identifier for “what was signed.” You can treat it like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A unique key that represents a specific signed entity at a specific time/epoch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The signer stores signed beacons locally so it can answer this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Have I already signed this entity? If yes, do not sign again.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is idempotency and it protects both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;protocol correctness (avoid duplicates)&lt;/li&gt;
&lt;li&gt;operational health (avoid useless work)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When Does the Signer Check “Already Signed” Beacons?
&lt;/h2&gt;

&lt;p&gt;This check typically happens &lt;strong&gt;after&lt;/strong&gt; the signer has candidate messages to sign but &lt;strong&gt;before&lt;/strong&gt; it generates signatures and submits them. A simplified flow looks like:&lt;/p&gt;

&lt;p&gt;1) Determine which signed entities are candidates for this round.&lt;br&gt;&lt;br&gt;
2) Query local DB to filter out entities already signed (&lt;code&gt;filter_out_already_signed_entities&lt;/code&gt;).&lt;br&gt;&lt;br&gt;
3) Only sign entities that are not already signed.&lt;br&gt;&lt;br&gt;
4) Store the signed beacon and submit signature(s) to the aggregator.&lt;/p&gt;

&lt;p&gt;This is a critical control path. If this DB path crashes, the signer may repeatedly crash or repeatedly re-sign.&lt;/p&gt;




&lt;h2&gt;
  
  
  KES Period: What It Is and Why It Appears in Registration
&lt;/h2&gt;

&lt;p&gt;KES stands for &lt;strong&gt;Key Evolving Signature&lt;/strong&gt;, a Cardano mechanism where a node’s signing key evolves over time to limit the impact of long-term key compromise. The &lt;strong&gt;KES period&lt;/strong&gt; is an index derived from chain time (slot/epoch context). In Mithril signer registration, KES period may be used to compute a derived value like &lt;strong&gt;KES evolutions&lt;/strong&gt;, which indicates how far the current key period is from the start period encoded in the operational certificate.&lt;/p&gt;

&lt;p&gt;The key idea is that KES-related values represent real chain state. If they are unknown, it is safer to treat them as “not ready” and retry rather than sending incorrect values.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>mithril</category>
      <category>rust</category>
    </item>
    <item>
      <title>Mithril Network Overview</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Mon, 05 Jan 2026 22:17:00 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/mithril-network-overview-1m33</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/mithril-network-overview-1m33</guid>
      <description>&lt;h1&gt;
  
  
  Overview: Architecture, Protocol, and Security
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;Mithril network&lt;/strong&gt; is a decentralized system designed to provide &lt;strong&gt;secure and efficient validation of data on the Cardano blockchain&lt;/strong&gt; without requiring users to run a full node.&lt;/p&gt;

&lt;p&gt;By leveraging a &lt;strong&gt;Stake-based Threshold Multisignature (STM)&lt;/strong&gt; scheme, Mithril allows a subset of stakeholders to sign messages in a way that is &lt;strong&gt;proportionally weighted by their stake&lt;/strong&gt;. This enables fast verification while preserving Cardano’s economic security model.&lt;/p&gt;

&lt;p&gt;Below is a comprehensive overview of the network’s &lt;strong&gt;architecture, operation, and security&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Core Participants (Nodes)
&lt;/h2&gt;

&lt;p&gt;The Mithril network relies on four types of nodes. Each node operates as a &lt;strong&gt;state machine&lt;/strong&gt;, meaning its behavior depends on well-defined states.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mithril Signer
&lt;/h3&gt;

&lt;p&gt;Mithril Signers are operated by &lt;strong&gt;Cardano Stake Pool Operators (SPOs)&lt;/strong&gt;. Their role is to independently sign blockchain state data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;INIT&lt;/code&gt;: Initial setup when the node starts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UNREGISTERED&lt;/code&gt;: A new epoch has started, but the signer has not registered keys yet&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;READY TO SIGN&lt;/code&gt;: Successfully registered and eligible to sign&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;REGISTERED NOT ABLE TO SIGN&lt;/code&gt;: Registered, but not selected in the lottery for this round&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Mithril Aggregator
&lt;/h3&gt;

&lt;p&gt;The Aggregator is a &lt;strong&gt;trustless coordinator&lt;/strong&gt;. It does not need to be trusted by clients.&lt;/p&gt;

&lt;p&gt;Its responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collecting individual signatures from signers&lt;/li&gt;
&lt;li&gt;aggregating them into a multisignature&lt;/li&gt;
&lt;li&gt;issuing a Mithril certificate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IDLE&lt;/code&gt;: Updating parameters at the start of an epoch&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;READY&lt;/code&gt;: Computing a message for a new signing trigger&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SIGNING&lt;/code&gt;: Gathering signatures until the required quorum is reached&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Mithril Client
&lt;/h3&gt;

&lt;p&gt;The Client is used by &lt;strong&gt;end-users&lt;/strong&gt; (such as wallets or infrastructure tools).&lt;/p&gt;

&lt;p&gt;It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;downloads certified artifacts (snapshots, transaction sets, etc.)&lt;/li&gt;
&lt;li&gt;downloads the associated certificates&lt;/li&gt;
&lt;li&gt;verifies everything cryptographically, without trusting servers&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Mithril Relay
&lt;/h3&gt;

&lt;p&gt;The Relay is a &lt;strong&gt;security proxy&lt;/strong&gt; (similar to Squid) that protects communication between Signers and the Aggregator.&lt;br&gt;&lt;br&gt;
It improves network security and privacy but does not affect protocol correctness.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. How the Protocol Works (Phases)
&lt;/h2&gt;

&lt;p&gt;The Mithril protocol operates in three main phases:&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Establishment
&lt;/h3&gt;

&lt;p&gt;Protocol parameters are defined:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;m&lt;/strong&gt;: number of lottery attempts per signer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;k&lt;/strong&gt;: required number of signatures (threshold)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ϕ&lt;/strong&gt;: stake-weighted winning probability function&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2) Initialization
&lt;/h3&gt;

&lt;p&gt;At the start of each epoch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signers generate key pairs&lt;/li&gt;
&lt;li&gt;They submit a &lt;strong&gt;Proof of Possession (PoP)&lt;/strong&gt; to prevent rogue-key attacks&lt;/li&gt;
&lt;li&gt;Signers register with the Aggregator&lt;/li&gt;
&lt;li&gt;The Aggregator computes the &lt;strong&gt;Aggregate Verification Key (AVK)&lt;/strong&gt; as a Merkle tree root&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3) Operations
&lt;/h3&gt;

&lt;p&gt;This phase runs repeatedly during an epoch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signers participate in a lottery for each message&lt;/li&gt;
&lt;li&gt;Winning signers generate and send signatures&lt;/li&gt;
&lt;li&gt;The Aggregator collects signatures&lt;/li&gt;
&lt;li&gt;Once &lt;strong&gt;k valid signatures&lt;/strong&gt; are collected, it creates a &lt;strong&gt;final Mithril certificate&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Data Certification (Pluggable Modules)
&lt;/h2&gt;

&lt;p&gt;Mithril uses a &lt;strong&gt;pluggable framework&lt;/strong&gt; to certify different types of data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cardano Node Database (v1 / v2)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Enables node bootstrap in &lt;strong&gt;~20 minutes instead of 24+ hours&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v2&lt;/strong&gt; uses Merkle trees for incremental certification&lt;/li&gt;
&lt;li&gt;Clients can verify only specific ranges of database files&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Stake Distribution
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Certifies the amount of stake held by SPOs at a specific epoch&lt;/li&gt;
&lt;li&gt;Essential for &lt;strong&gt;sidechains, bridges, and cross-chain validation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Cardano Transactions
&lt;/h3&gt;

&lt;p&gt;To certify millions of transactions efficiently, Mithril uses a &lt;strong&gt;Merkle Forest&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blocks are grouped into ranges of 15&lt;/li&gt;
&lt;li&gt;Each range forms a Merkle tree&lt;/li&gt;
&lt;li&gt;Tree roots are combined into higher-level trees&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduces memory usage by &lt;strong&gt;about 100×&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Security and the Certificate Chain
&lt;/h2&gt;

&lt;p&gt;To prevent &lt;strong&gt;Eclipse Attacks&lt;/strong&gt; (where an attacker shows a fake blockchain view), Mithril uses a &lt;strong&gt;Certificate Chain&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Genesis Certificate
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The chain starts with a certificate signed by a special &lt;strong&gt;Genesis Key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;This acts as the &lt;strong&gt;root of trust&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Chain Validation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Each new certificate must reference a previous certificate&lt;/li&gt;
&lt;li&gt;A certificate is valid only if its AVK was signed in an earlier verified certificate&lt;/li&gt;
&lt;li&gt;Clients verify certificates by walking the chain back to the genesis certificate&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Attack Resistance
&lt;/h3&gt;

&lt;p&gt;Mithril defends against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long-range attacks&lt;/strong&gt; using epoch-based checkpoints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grinding attacks&lt;/strong&gt; via strong randomness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sybil attacks&lt;/strong&gt; through stake-weighted eligibility and Proof of Possession&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Engineering and Scalability Considerations
&lt;/h2&gt;

&lt;p&gt;From an engineering perspective, Mithril is designed for efficiency and safety:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Signing and verification costs grow as &lt;strong&gt;O(logN)&lt;/strong&gt;, not O(N)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trustlessness&lt;/strong&gt;: Even a malicious Aggregator cannot forge a valid certificate without k honest signatures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finality&lt;/strong&gt;: Transactions are certified only at a fixed offset (currently 100 blocks) from the chain tip to avoid rollbacks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Mithril replaces the need for full blockchain verification with a &lt;strong&gt;stake-backed cryptographic certificate&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
By combining lottery-based signer selection, multisignatures, Merkle structures, and certificate chaining, it provides a scalable and secure foundation for fast synchronization and trust-minimized data access in the Cardano ecosystem.&lt;/p&gt;

&lt;p&gt;ref(&lt;a href="https://mithril.network/doc/mithril/intro" rel="noopener noreferrer"&gt;https://mithril.network/doc/mithril/intro&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>cardano</category>
      <category>mithril</category>
      <category>rust</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Understanding Pallas and Mithril: Journey into Cardano Infrastructure</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Sun, 04 Jan 2026 05:00:24 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/understanding-pallas-and-mithril-journey-into-cardano-infrastructure-21f7</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/understanding-pallas-and-mithril-journey-into-cardano-infrastructure-21f7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this post, I want to summarize what I have learned so far about the &lt;strong&gt;Pallas&lt;/strong&gt; and &lt;strong&gt;Mithril&lt;/strong&gt; projects in the Cardano ecosystem.&lt;br&gt;&lt;br&gt;
Before deep diving into the Mithril codebase and starting to contribute, I felt it was important to organize my understanding and thoughts clearly.&lt;/p&gt;

&lt;p&gt;My goal is to become a blockchain engineer working on Cardano infrastructure, and this summary helps me confirm that I have the right mental model before moving forward.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the Pallas Project Exists
&lt;/h2&gt;

&lt;p&gt;Cardano’s mainnet and core node software are implemented in &lt;strong&gt;Haskell&lt;/strong&gt;. While Haskell is powerful, it creates a high barrier for developers who want to interact directly with Cardano using other languages, especially &lt;strong&gt;Rust&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If a developer wants to understand Cardano data formats, network protocols, or transaction structures at a low level, they usually need to read Haskell code and understand how &lt;code&gt;cardano-node&lt;/code&gt; works internally.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;Pallas&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;Pallas is a collection of Rust libraries that re-implement Cardano’s data formats and protocols in a Rust-friendly way. It allows developers to interact with the Cardano mainnet without writing or deeply understanding Haskell. Instead, developers can use Rust to decode blocks, inspect transactions, build transactions, and communicate with Cardano nodes.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Pallas Provides
&lt;/h2&gt;

&lt;p&gt;Pallas is not a single library, but a set of modules, each with a specific responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;primitives&lt;/strong&gt;: defines Cardano data types such as transactions, blocks, values, scripts, and metadata
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;codec&lt;/strong&gt;: handles serialization and deserialization (mainly CBOR)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;network&lt;/strong&gt;: implements Cardano node-to-node communication protocols
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;txbuilder&lt;/strong&gt;: helps construct Cardano transactions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;traverse&lt;/strong&gt;: provides era-agnostic ways to inspect blocks and transactions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;hardano&lt;/strong&gt;: interoperates with Cardano node storage formats
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;crypto&lt;/strong&gt;: cryptographic utilities used by Cardano
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;math / utxorpc&lt;/strong&gt;: supporting utilities and interoperability layers
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these modules focus on one core idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How to correctly represent, encode, decode, and interact with Cardano data and protocols in Rust.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because of Pallas, Rust developers can build useful tools such as wallets, indexers, explorers, analytics services, and other infrastructure components without relying on Haskell code. This significantly lowers the entry barrier for system-level development in the Cardano ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Mithril Exists
&lt;/h2&gt;

&lt;p&gt;While Pallas helps developers &lt;em&gt;interact&lt;/em&gt; with Cardano, another major challenge remains: &lt;strong&gt;verification and synchronization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To fully verify Cardano data from scratch, a client normally needs to download and validate a very large amount of blockchain data. In practice, this means many applications depend on full nodes or trusted servers to provide data, because downloading and validating everything locally is slow and resource-intensive.&lt;/p&gt;

&lt;p&gt;This is why &lt;strong&gt;Mithril&lt;/strong&gt; was created.&lt;/p&gt;

&lt;p&gt;Mithril provides a way to &lt;strong&gt;verify Cardano blockchain state efficiently&lt;/strong&gt;, without downloading the entire chain. It does this by using &lt;strong&gt;stake-weighted cryptographic certificates&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Snapshots and Certificates (Important Distinction)
&lt;/h2&gt;

&lt;p&gt;In Mithril, there are two different concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;snapshot&lt;/strong&gt; is a compressed representation of the Cardano chain state at a specific point in time.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;certificate&lt;/strong&gt; is a small cryptographic proof showing that this snapshot was approved by stake pool operators representing a large percentage of total ADA stake.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A client downloads &lt;strong&gt;both&lt;/strong&gt; the snapshot and its certificate.&lt;br&gt;&lt;br&gt;
The client then verifies the certificate locally. If the certificate is valid, the client can trust that the snapshot represents a chain state that the Cardano network agreed on at that time.&lt;/p&gt;

&lt;p&gt;It is important to note that Mithril does &lt;strong&gt;not&lt;/strong&gt; re-validate individual transactions or UTXOs. That work is already done by Cardano nodes. Mithril verifies &lt;strong&gt;agreement on the resulting state&lt;/strong&gt;, not the full transaction history.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Problem Mithril Solves
&lt;/h2&gt;

&lt;p&gt;Mithril reduces the need to trust a single server and removes the need to download massive amounts of historical data just to get started. By verifying a small certificate instead of the full chain, clients can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bootstrap much faster
&lt;/li&gt;
&lt;li&gt;reduce infrastructure and storage costs
&lt;/li&gt;
&lt;li&gt;rely on Cardano’s stake-based security model instead of centralized trust
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes Mithril especially useful for infrastructure tools, indexers, research systems, and future interoperability solutions.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Did Not Deep Dive Into (Yet)
&lt;/h2&gt;

&lt;p&gt;Topics such as &lt;strong&gt;bridges&lt;/strong&gt;, &lt;strong&gt;sidechains&lt;/strong&gt;, &lt;strong&gt;oracles&lt;/strong&gt;, and &lt;strong&gt;cross-chain interoperability&lt;/strong&gt; are closely related to Mithril, but they require a much deeper understanding of blockchain systems and security models.&lt;/p&gt;

&lt;p&gt;For now, I chose not to dive deeply into these topics. I understand that Mithril helps make these systems safer and more verifiable, but I plan to study them later in more detail.&lt;/p&gt;




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

&lt;p&gt;Deep dive into the &lt;strong&gt;Mithril project structure&lt;/strong&gt;, understand how each module works, why it exists, and how the system operates end to end. My goal is to contribute to the Mithril project and grow as a blockchain engineer.&lt;/p&gt;




</description>
      <category>cardano</category>
      <category>blockchain</category>
      <category>rust</category>
      <category>mithril</category>
    </item>
    <item>
      <title>➡️ Rust Dev's Pallas Journey: Cardano in Rust Intro</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Thu, 01 Jan 2026 10:43:55 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/rust-devs-pallas-journey-cardano-in-rust-intro-2dfi</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/rust-devs-pallas-journey-cardano-in-rust-intro-2dfi</guid>
      <description>&lt;p&gt;source code(&lt;a href="https://github.com/leepl37/Pallas-Explorer-Demo" rel="noopener noreferrer"&gt;https://github.com/leepl37/Pallas-Explorer-Demo&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;dive into Pallas, TxPipe's Rust toolkit for Cardano. &lt;/p&gt;

&lt;p&gt;Modular Rust for blockchain without Haskell.&lt;/p&gt;

&lt;p&gt;summary of pallas. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;pallas-codec&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CBOR serialization/deserialization foundation.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_codec&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_codec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;minicbor&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[derive(Encode,&lt;/span&gt; &lt;span class="nd"&gt;Decode)]&lt;/span&gt;
&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;MyEnum&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&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;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;MyEnum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&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;encoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="nf"&gt;.encode_to_vec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;decoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;encoded&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;decoded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MyEnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decoder&lt;/span&gt;&lt;span class="nf"&gt;.decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nn"&gt;MyEnum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decoded&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;"Decoded: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;pallas-primitives&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ledger data structs across eras.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_primitives&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MultiEraTx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;tx_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// CBOR bytes&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;MultiEraTx&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_cbor_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tx_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;"Fee: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="nf"&gt;.fees&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;ol&gt;
&lt;li&gt;pallas-crypto&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hashes, sigs, VRF for security.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_crypto&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Blake2b256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ed25519Bip32SecretKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ed25519Signature&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rngs&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;RngCore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;sk_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;OsRng&lt;/span&gt;&lt;span class="nf"&gt;.fill_bytes&lt;/span&gt;&lt;span class="p"&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;sk_bytes&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;sk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Ed25519Bip32SecretKey&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sk_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;b"test"&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;sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Ed25519Signature&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&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;"Sig valid: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="nf"&gt;.verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="nf"&gt;.public_key&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;data&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;ol&gt;
&lt;li&gt;pallas-addresses&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Address encoding/decoding.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_addresses&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_bech32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"addr1q..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nn"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Shelley&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addr&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;"Payment: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="py"&gt;.payment&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;pallas-txbuilder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tx construction builder.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_txbuilder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_primitives&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ProtocolParameters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ProtocolParameters&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;default&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;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&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;min_fee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="nf"&gt;.min_fee&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;"Min fee: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_fee&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;ol&gt;
&lt;li&gt;pallas-traverse&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Data analysis/traversal.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_traverse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MultiEraBlock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;block_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Bytes&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;MultiEraBlock&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="nf"&gt;.txs&lt;/span&gt;&lt;span class="p"&gt;()&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;"Inputs: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="nf"&gt;.inputs&lt;/span&gt;&lt;span class="p"&gt;()&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;pallas-network&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Node communication stack.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_network&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;n2c&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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;_mux&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"relay.example:3001"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;ol&gt;
&lt;li&gt;pallas-hardano&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Haskell node artifact interop.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_hardano&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ImmutableFile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;path&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PathBuf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;PathBuf&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;"chunk.file"&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;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;ImmutableFile&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="nf"&gt;.next&lt;/span&gt;&lt;span class="p"&gt;()&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;"Block: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="py"&gt;.header&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;pallas-math&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Math utils for ledger/consensus.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_math&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;slot_to_epoch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;epoch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;slot_to_epoch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;432000&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;"Epoch: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epoch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ~2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;pallas-utxorpc&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;UTxO-RPC querying.&lt;/p&gt;

&lt;p&gt;Example:&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;use&lt;/span&gt; &lt;span class="nn"&gt;pallas_utxorpc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grpc://node:50051"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;tip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="nf"&gt;.get_chain_tip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;"Tip: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tip&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;easy to remember.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: The Atoms
&lt;/h3&gt;

&lt;p&gt;These modules handle the low-level rules of the universe: math, serialization, and cryptography.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-codec&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Implements &lt;strong&gt;CBOR&lt;/strong&gt; (Concise Binary Object Representation) serialization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Cardano uses binary CBOR, not JSON. This module maps Rust Structs to raw bytes using efficient macros.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-crypto&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Handles hashing (&lt;strong&gt;Blake2b&lt;/strong&gt;) and signatures (&lt;strong&gt;Ed25519&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Bitcoin relies on SHA-256; Cardano relies on Blake2b-256 for performance and security.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-math&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Implements precise fixed-point arithmetic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Floating-point errors (e.g., &lt;code&gt;0.1 + 0.2 != 0.3&lt;/code&gt;) are forbidden in consensus. This ensures exact agreement on staking rewards.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Layer 2: The Data
&lt;/h3&gt;

&lt;p&gt;These modules define the data structures that populate the blockchain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-primitives&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Defines the Rust Structs for &lt;code&gt;TransactionBody&lt;/code&gt;, &lt;code&gt;Block&lt;/code&gt;, and &lt;code&gt;Header&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Concept:&lt;/strong&gt; &lt;strong&gt;Eras&lt;/strong&gt;. Because of Hard Forks, a "Block" has different shapes in different years (Byron, Shelley, Alonzo, Babbage).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-addresses&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Parses human-readable strings (&lt;code&gt;addr1...&lt;/code&gt;) into data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Concept:&lt;/strong&gt; &lt;strong&gt;Bech32&lt;/strong&gt;. It validates checksums and extracts the &lt;strong&gt;Payment Key&lt;/strong&gt; (Ownership) and &lt;strong&gt;Stake Key&lt;/strong&gt; (Voting Rights).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Layer 3: The Tools
&lt;/h3&gt;

&lt;p&gt;These are the libraries you use to read and write data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-traverse&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; The most essential tool for reading chain data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; It provides a &lt;code&gt;MultiEraBlock&lt;/code&gt; wrapper. This allows you to query data (e.g., &lt;code&gt;block.tx_count()&lt;/code&gt;) without writing complex &lt;code&gt;if/else&lt;/code&gt; logic for every hard fork era.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pallas-txbuilder&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; A helper to construct valid transaction binaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; It manages the complexity of UTXO inputs, fee calculation, and change addresses.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Layer 4: The Infrastructure
&lt;/h3&gt;

&lt;p&gt;These modules connect your code to the physical network.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;pallas-network&lt;/code&gt;:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Implements the &lt;strong&gt;Ouroboros&lt;/strong&gt; mini-protocols (Handshake, ChainSync, TxSubmission).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Allows Rust code to connect directly to Mainnet nodes via TCP.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;pallas-hardano&lt;/code&gt;:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; Reads raw &lt;strong&gt;ImmutableDB&lt;/strong&gt; files directly from the hard drive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Critical for high-performance local indexing (used heavily by Mithril).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;pallas-utxorpc&lt;/code&gt;:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What:&lt;/strong&gt; A modern gRPC bridge to access blockchain data without managing Ouroboros state machines.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The Transaction Lifecycle&lt;/p&gt;

&lt;p&gt;the life of a transaction on the Cardano Mainnet.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Creation:&lt;/strong&gt; A Wallet builds a Tx using &lt;code&gt;pallas-txbuilder&lt;/code&gt; (logic) and &lt;code&gt;pallas-primitives&lt;/code&gt; (structs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Submission:&lt;/strong&gt; The Wallet pushes the Tx to a local Relay Node using &lt;code&gt;pallas-network&lt;/code&gt; (TxSubmission protocol).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Propagation (Gossip):&lt;/strong&gt; Relay nodes check validity and "gossip" the Tx to the &lt;strong&gt;Slot Leader's&lt;/strong&gt; Mempool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consensus:&lt;/strong&gt; The Slot Leader checks its &lt;strong&gt;VRF&lt;/strong&gt; (Verifiable Random Function). If it wins the lottery, it mints a block.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distribution:&lt;/strong&gt; The Slot Leader broadcasts the new block using &lt;code&gt;pallas-network&lt;/code&gt; (ChainSync protocol).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Observation:&lt;/strong&gt; Your Pallas Client downloads the block and decodes it using &lt;code&gt;pallas-traverse&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>blockchain</category>
      <category>cardano</category>
      <category>rust</category>
      <category>txpipe</category>
    </item>
    <item>
      <title>How Rust's Future Type Guarantees Scalable, Safe Asynchronous I/O</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Thu, 04 Dec 2025 00:26:06 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/how-rusts-future-type-guarantees-scalable-safe-asynchronous-io-5c5g</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/how-rusts-future-type-guarantees-scalable-safe-asynchronous-io-5c5g</guid>
      <description>&lt;p&gt;Introduction:&lt;/p&gt;

&lt;p&gt;The Problem: Briefly explain why traditional thread-per-connection models struggle with high concurrency (too many threads cause high resource overhead and context-switching costs).&lt;/p&gt;

&lt;p&gt;The Rust Promise: Introduce the Rust solution: Asynchronous Programming using Futures, emphasizing that it delivers C-style performance with Rust's signature memory safety.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;🧱 Part I: The Foundation - The Future Trait
Focus on what a Future is and is not.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Definition: A Future is just a trait representing a value that might be ready at some point. It is the fundamental building block of Rust's async ecosystem.&lt;/p&gt;

&lt;p&gt;Lazy Execution: Explain the crucial concept: Futures are inert. They do nothing until they are actively polled by an executor (the runtime). This is the "compute when needed" principle.&lt;/p&gt;

&lt;p&gt;Code Example 1: A Simple (Manual) Future&lt;/p&gt;

&lt;p&gt;Show a basic custom Future implementation (e.g., a simple counter that increments on each poll or a future that resolves after a fixed number of polls). This is to illustrate the poll method directly, even if it's not a real-world scenario.&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="c1"&gt;// Example 1: A basic custom Future (for illustrative purposes)&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;future&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Pin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;task&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Poll&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;MyFuture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;MyFuture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Output&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;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// What this Future will produce&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Pin&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="k"&gt;Self&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;cx&lt;/span&gt;&lt;span class="p"&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;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Poll&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.start&lt;/span&gt;&lt;span class="nf"&gt;.elapsed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.duration&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;"MyFuture is ready!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nn"&gt;Poll&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ready&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done waiting!"&lt;/span&gt;&lt;span class="p"&gt;)&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="c1"&gt;// If not ready, register the current task to be woken up.&lt;/span&gt;
            &lt;span class="c1"&gt;// In a real async runtime, this would involve registering with an event loop.&lt;/span&gt;
            &lt;span class="n"&gt;cx&lt;/span&gt;&lt;span class="nf"&gt;.waker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.wake_by_ref&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// For this simple example, we'll just wake ourselves&lt;/span&gt;
                                    &lt;span class="c1"&gt;// or a real runtime would ensure this gets polled again.&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;"MyFuture is pending..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nn"&gt;Poll&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Pending&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;// How to create and run it (briefly, to show usage)&lt;/span&gt;
&lt;span class="c1"&gt;// Note: This won't run without an executor, but it shows the API.&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;demonstrate_my_future&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;fut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyFuture&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;Instant&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&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;fut&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This .await relies on an executor&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The poll Method: (Crucial detail for experts) Briefly explain the signature of the poll method:&lt;/p&gt;

&lt;p&gt;It returns Poll::Ready(T) (done) or Poll::Pending (not yet done).&lt;/p&gt;

&lt;p&gt;The Waker is passed to wake the task when it's ready to be polled again.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✨ Part II: The Syntactic Sugar - async and await
Explain how Rust makes the complex Future machinery easy to use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;async Block/Function: Explain that async fn is syntactic sugar for a function that returns an opaque type implementing the Future trait.&lt;/p&gt;

&lt;p&gt;Analogy: It packages your code into a state machine.&lt;/p&gt;

&lt;p&gt;await Operator: Explain that .await is the key mechanism. When you .await a Future:&lt;/p&gt;

&lt;p&gt;If the Future is not ready, the task is yielded back to the executor.&lt;/p&gt;

&lt;p&gt;This allows the single thread to go work on other tasks (Futures) instead of blocking.&lt;/p&gt;

&lt;p&gt;Code Example 2: async/await in Action (Simple Task)&lt;/p&gt;

&lt;p&gt;Show a basic async fn that does something simple, like tokio::time::sleep. This clearly demonstrates how await pauses execution without blocking the thread.&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="c1"&gt;// Example 2: Simple async/await using Tokio&lt;/span&gt;
&lt;span class="c1"&gt;// Requires: `tokio = { version = "1", features = ["full"] }` in Cargo.toml&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt; &lt;span class="c1"&gt;// This macro sets up the Tokio runtime&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello from main!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Call an async function&lt;/span&gt;
    &lt;span class="nf"&gt;say_hello_after_delay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&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;"Main function finished."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;say_hello_after_delay&lt;/span&gt;&lt;span class="p"&gt;()&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;"Inside async function: About to wait..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_secs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// .await pauses THIS task&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;"Inside async function: Waited for 1 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;ol&gt;
&lt;li&gt;⚙️ Part III: The Engine - The Asynchronous Runtime
Show the essential role of the Executor (the runtime).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Executor's Role: A Future needs an executor (like Tokio or async-std) to drive its state machine forward.&lt;/p&gt;

&lt;p&gt;The Event Loop: Describe how the runtime works: It takes pending Futures and efficiently schedules them onto a small pool of threads . When a task (Future) signals it's ready (via the Waker), the executor resumes polling that task.&lt;/p&gt;

&lt;p&gt;Benefit: This model provides non-blocking I/O without the overhead of creating one operating system thread per connection, leading to high throughput.&lt;/p&gt;

&lt;p&gt;Code Example 3: Concurrency with Multiple Async Tasks&lt;/p&gt;

&lt;p&gt;Demonstrate tokio::spawn to run multiple Futures concurrently on a single (or small number of) thread(s), showing how the runtime interleaves their execution. This highlights the "non-blocking" nature.&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="c1"&gt;// Example 3: Running multiple async tasks concurrently with Tokio&lt;/span&gt;
&lt;span class="c1"&gt;// Requires: `tokio = { version = "1", features = ["full"] }` in Cargo.toml&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Main starting..."&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;task1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Spawn creates a Future and adds it to the executor&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;3&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;"Task 1: {i}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="s"&gt;"Task 1 complete!"&lt;/span&gt; &lt;span class="c1"&gt;// Return value of the spawned future&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;task2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..=&lt;/span&gt;&lt;span class="mi"&gt;2&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;"  Task 2: {i}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;tokio&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;time&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_millis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="s"&gt;"Task 2 complete!"&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Await the results of the spawned tasks&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task1&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// .await on JoinHandle blocks current task until spawned task finishes&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;task2&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;"{result1}"&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;"{result2}"&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;"Main finished."&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;ol&gt;
&lt;li&gt;💻 Conclusion: Why Rust Async Shines
Summary: Reiterate how the Future trait, async/await syntax, and efficient runtimes combine to make Rust a powerhouse for async programming.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Real-World Impact: Emphasize why this is crucial for blockchain and network services:&lt;/p&gt;

&lt;p&gt;High Scalability: Handling thousands of concurrent connections efficiently.&lt;/p&gt;

&lt;p&gt;Resource Efficiency: Lower memory footprint compared to thread-heavy models.&lt;/p&gt;

&lt;p&gt;Rust's Safety Guarantees: All of this performance without data races or memory errors, thanks to the borrow checker and type system.&lt;/p&gt;

&lt;p&gt;Final Call to Action: Encourage readers to experiment with async/await and explore Rust's ecosyste&lt;/p&gt;

</description>
      <category>rust</category>
      <category>systems</category>
    </item>
    <item>
      <title>Understanding Bitcoin Fundamentals: From Transactions to Consensus</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Tue, 21 Oct 2025 04:26:35 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/understanding-bitcoin-fundamentals-from-transactions-to-consensus-1pkk</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/understanding-bitcoin-fundamentals-from-transactions-to-consensus-1pkk</guid>
      <description>&lt;p&gt;This post is part of my deep dive into Bitcoin’s core architecture — studying directly from the official &lt;a href="https://developer.bitcoin.org/devguide/" rel="noopener noreferrer"&gt;Bitcoin Developer Guide&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
It summarizes everything I’ve learned so far before moving on to advanced topics like wallet architecture, the P2P network, and Taproot.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 1. Bitcoin Overview
&lt;/h2&gt;

&lt;p&gt;Bitcoin is a &lt;strong&gt;decentralized ledger&lt;/strong&gt; that records all transactions without a central authority.&lt;br&gt;&lt;br&gt;
It achieves &lt;strong&gt;trustless consensus&lt;/strong&gt; through cryptography, distributed nodes, and the &lt;strong&gt;Proof-of-Work&lt;/strong&gt; mechanism.&lt;/p&gt;

&lt;p&gt;Each node maintains a full copy of the blockchain — a chain of blocks that reference one another using cryptographic hashes.&lt;/p&gt;




&lt;h2&gt;
  
  
  💸 2. Transactions: The Heart of Bitcoin
&lt;/h2&gt;

&lt;p&gt;Every Bitcoin transaction consists of &lt;strong&gt;inputs&lt;/strong&gt; and &lt;strong&gt;outputs&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Input&lt;/strong&gt;: References a previous unspent transaction output (UTXO).&lt;br&gt;&lt;br&gt;
It includes the &lt;strong&gt;public key&lt;/strong&gt; and &lt;strong&gt;signature&lt;/strong&gt; to unlock those funds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;: Defines the new recipient’s address (as a &lt;strong&gt;public key hash&lt;/strong&gt;) and the &lt;strong&gt;amount&lt;/strong&gt; being sent.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Alice sends Bitcoin to Bob:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Her wallet creates a transaction using her &lt;strong&gt;UTXOs&lt;/strong&gt; as inputs.
&lt;/li&gt;
&lt;li&gt;It generates an &lt;strong&gt;unlocking script (scriptSig)&lt;/strong&gt; with her public key and signature.
&lt;/li&gt;
&lt;li&gt;The output specifies Bob’s &lt;strong&gt;public key hash&lt;/strong&gt; — the new UTXO that only Bob can spend later.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧮 3. Validation and the Memory Pool
&lt;/h2&gt;

&lt;p&gt;When Alice’s transaction is broadcast:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Each &lt;strong&gt;node&lt;/strong&gt; verifies it by checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The referenced UTXOs exist and are unspent.&lt;/li&gt;
&lt;li&gt;The signature is valid.&lt;/li&gt;
&lt;li&gt;Inputs are larger than outputs.&lt;/li&gt;
&lt;li&gt;The fee is above the &lt;strong&gt;minimum relay fee&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once validated, it’s added to the &lt;strong&gt;mempool&lt;/strong&gt; (memory pool), where it waits to be mined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Miners then pick transactions from the mempool, prioritizing those with &lt;strong&gt;higher fees&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⛏️ 4. Mining and Block Creation
&lt;/h2&gt;

&lt;p&gt;Miners collect valid transactions into a &lt;strong&gt;block&lt;/strong&gt;, which contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version&lt;/strong&gt; – protocol version number
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Previous Block Hash&lt;/strong&gt; – reference to the last block
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merkle Root&lt;/strong&gt; – summary of all transaction hashes in the block
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp&lt;/strong&gt; – time when block was created
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Difficulty Target&lt;/strong&gt; – defines how hard the block is to mine
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce&lt;/strong&gt; – value miners adjust to find a valid hash&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Proof-of-Work (PoW)
&lt;/h3&gt;

&lt;p&gt;To add a new block, miners must find a &lt;strong&gt;nonce&lt;/strong&gt; that makes the block’s hash &lt;strong&gt;lower than the target difficulty&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
This ensures that creating blocks requires computational work and prevents tampering.&lt;/p&gt;

&lt;p&gt;If anyone changes even one transaction, the Merkle root changes →&lt;br&gt;&lt;br&gt;
the block hash changes → all subsequent blocks become invalid.&lt;/p&gt;




&lt;h2&gt;
  
  
  💰 5. Coinbase Transaction and Rewards
&lt;/h2&gt;

&lt;p&gt;Each block starts with a &lt;strong&gt;coinbase transaction&lt;/strong&gt;, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewards the miner with newly created bitcoins (block subsidy).&lt;/li&gt;
&lt;li&gt;Collects all transaction fees in that block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This coinbase transaction is mandatory under the &lt;strong&gt;consensus rules&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
As block subsidies halve every 210,000 blocks, miners will eventually rely solely on transaction fees.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 6. SegWit: Making Transactions More Efficient
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Segregated Witness (SegWit)&lt;/strong&gt; upgrade moved signatures and public keys&lt;br&gt;&lt;br&gt;
from the &lt;code&gt;scriptSig&lt;/code&gt; to a separate &lt;strong&gt;witness field&lt;/strong&gt;, reducing transaction size and cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Lower fees (because signatures no longer count fully toward byte size).
&lt;/li&gt;
&lt;li&gt;Fixed transaction malleability.
&lt;/li&gt;
&lt;li&gt;Enabled second-layer solutions like the &lt;strong&gt;Lightning Network&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ 7. Fee Policies and Mempool Rules
&lt;/h2&gt;

&lt;p&gt;Bitcoin nodes implement several &lt;strong&gt;fee and safety policies&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Policy&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Minimum Relay Fee&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reject transactions with fees below a certain threshold.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dust Limit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prevents outputs too small to be spent later.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ancestor/Descendant Limit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limits chains of unconfirmed transactions to avoid mempool flooding.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replace-By-Fee (RBF)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Allows resending the same transaction with a higher fee.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Child-Pays-for-Parent (CPFP)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A child transaction can pay a higher fee to help confirm its parent.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These rules maintain efficiency and fairness within the network.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ 8. Advanced Scripts: Multi-Signature and Timelocks
&lt;/h2&gt;

&lt;p&gt;Bitcoin’s scripting system allows conditional spending — making Bitcoin programmable.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧾 Multi-Signature
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;multisig&lt;/strong&gt; script requires multiple signatures to unlock funds, such as:&lt;br&gt;
This means &lt;strong&gt;2 of 3&lt;/strong&gt; participants must sign to spend the funds.&lt;br&gt;&lt;br&gt;
Used in &lt;strong&gt;Lightning Network channels&lt;/strong&gt; and &lt;strong&gt;escrow systems&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⏳ Timelocks
&lt;/h3&gt;

&lt;p&gt;Timelocks restrict when funds can be spent:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Opcode&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Absolute Timelock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CHECKLOCKTIMEVERIFY (CLTV)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Funds are locked until a specific block height or timestamp.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relative Timelock&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CHECKSEQUENCEVERIFY (CSV)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Funds are locked for a certain number of blocks &lt;em&gt;after confirmation&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These opcodes enable secure payment channels like &lt;strong&gt;Lightning Network&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ Lightning Network Connection
&lt;/h3&gt;

&lt;p&gt;In Lightning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CLTV&lt;/code&gt; sets an &lt;em&gt;absolute&lt;/em&gt; timeout for a channel.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CSV&lt;/code&gt; enforces a &lt;em&gt;relative&lt;/em&gt; delay when closing a channel.
This delay gives the honest party time to react if someone tries to cheat by broadcasting an old channel state.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 9. Consensus and Immutability
&lt;/h2&gt;

&lt;p&gt;Consensus ensures all nodes agree on the same blockchain state.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each node selects the &lt;strong&gt;longest valid chain&lt;/strong&gt; (most cumulative Proof-of-Work).
&lt;/li&gt;
&lt;li&gt;Any modification to old blocks changes their hashes, breaking the chain.
&lt;/li&gt;
&lt;li&gt;This immutability guarantees transparency and trust.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 10. What I’ve Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Bitcoin’s security comes from &lt;strong&gt;cryptography&lt;/strong&gt;, &lt;strong&gt;distributed consensus&lt;/strong&gt;, and &lt;strong&gt;Proof-of-Work&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Every transaction is traceable through &lt;strong&gt;UTXOs&lt;/strong&gt;, making the system auditable.
&lt;/li&gt;
&lt;li&gt;Scripts like &lt;strong&gt;multisig&lt;/strong&gt; and &lt;strong&gt;timelocks&lt;/strong&gt; add flexibility to Bitcoin’s functionality.
&lt;/li&gt;
&lt;li&gt;Understanding the &lt;strong&gt;mempool&lt;/strong&gt; and &lt;strong&gt;fee policies&lt;/strong&gt; explains why transactions confirm at different speeds.
&lt;/li&gt;
&lt;li&gt;SegWit and Lightning Network show how Bitcoin continues to evolve for scalability.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🌱 Reflection
&lt;/h2&gt;

&lt;p&gt;Studying these fundamentals taught me not just &lt;em&gt;how Bitcoin works&lt;/em&gt;,&lt;br&gt;&lt;br&gt;
but &lt;em&gt;why it works this way&lt;/em&gt; — how every rule, from UTXOs to CSV, builds a secure, decentralized network.&lt;br&gt;&lt;br&gt;
It’s the foundation for my next step: learning about &lt;strong&gt;wallet architecture&lt;/strong&gt; and &lt;strong&gt;P2P networking&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
to strengthen my Rust-based Bitcoin wallet project.&lt;/p&gt;




</description>
      <category>bitcoin</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>rust</category>
    </item>
    <item>
      <title>🚀 Understanding Proof-of-Work, Block Structure, Merkle Trees, and Consensus in Bitcoin</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Wed, 01 Oct 2025 02:04:14 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/understanding-proof-of-work-block-structure-merkle-trees-and-consensus-in-bitcoin-2emk</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/understanding-proof-of-work-block-structure-merkle-trees-and-consensus-in-bitcoin-2emk</guid>
      <description>&lt;p&gt;This post is part of my study journey following the &lt;a href="https://developer.bitcoin.org/devguide/block_chain.html" rel="noopener noreferrer"&gt;Bitcoin Developer Guide&lt;/a&gt;. In particular, this article focuses on the &lt;strong&gt;Block Chain&lt;/strong&gt; section.  &lt;/p&gt;

&lt;p&gt;As a developer preparing for a career in blockchain, I’m documenting what I’ve learned about how &lt;strong&gt;transactions, blocks, Merkle trees, consensus, and proof-of-work&lt;/strong&gt; all fit together in Bitcoin.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Transactions: The Building Blocks
&lt;/h2&gt;

&lt;p&gt;Every Bitcoin transaction is made up of:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unlocking script&lt;/strong&gt; (signature + public key): Proves the sender can spend a UTXO.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Locking script&lt;/strong&gt; (public key hash): Ensures only the recipient can spend later.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Example: Alice wants to send 0.6 BTC to Bob.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alice provides her &lt;strong&gt;public key + signature&lt;/strong&gt; to unlock her UTXOs.
&lt;/li&gt;
&lt;li&gt;She includes Bob’s &lt;strong&gt;public key hash&lt;/strong&gt; as the new locking script.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guarantees only Bob can later spend this Bitcoin.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 The Flow of a Transaction
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A[Alice Creates Transaction] --&amp;gt; B[Transaction Broadcasted]
    B --&amp;gt; C[Mempool: Waiting Room]
    C --&amp;gt; D[Miners Collect Transactions]
    D --&amp;gt; E[Transaction Packaged into Block]
    E --&amp;gt; F[Block Verified by Network]
    F --&amp;gt; G[Transaction Confirmed in Blockchain]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🌳 Merkle Trees: Efficient Transaction Summaries
&lt;/h2&gt;

&lt;p&gt;From the &lt;a href="https://developer.bitcoin.org/devguide/block_chain.html" rel="noopener noreferrer"&gt;Bitcoin Developer Guide: Block Chain section&lt;/a&gt;:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Copies of each transaction are hashed, and the hashes are then paired, hashed, paired again, and hashed again until a single hash remains, the merkle root of a merkle tree.”  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;👉 &lt;strong&gt;Merkle Trees allow Bitcoin to efficiently prove that a transaction is included in a block&lt;/strong&gt;.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each transaction is &lt;strong&gt;hashed&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Hashes are paired, combined, and hashed again.
&lt;/li&gt;
&lt;li&gt;Process repeats until one hash remains → the &lt;strong&gt;Merkle Root&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;The Merkle Root goes into the &lt;strong&gt;block header&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    T1[Tx1] --&amp;gt; H1[Hash1]
    T2[Tx2] --&amp;gt; H2[Hash2]
    T3[Tx3] --&amp;gt; H3[Hash3]
    T4[Tx4] --&amp;gt; H4[Hash4]

    H1 --&amp;gt; H12[Hash(H1+H2)]
    H2 --&amp;gt; H12
    H3 --&amp;gt; H34[Hash(H3+H4)]
    H4 --&amp;gt; H34

    H12 --&amp;gt; Root[Merkle Root]
    H34 --&amp;gt; Root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 &lt;strong&gt;Key property:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If &lt;strong&gt;any transaction changes&lt;/strong&gt;, its hash changes → which changes the Merkle Root → which changes the block header hash.&lt;br&gt;&lt;br&gt;
This makes tampering impossible without re-mining the entire chain.  &lt;/p&gt;


&lt;h2&gt;
  
  
  🧱 Block Structure
&lt;/h2&gt;

&lt;p&gt;According to the Bitcoin Developer Guide, each block header contains:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version number&lt;/strong&gt; → Identifies which set of consensus rules apply.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Previous Block Hash&lt;/strong&gt; → Links to the block before it.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merkle Root&lt;/strong&gt; → Summary of all transactions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp&lt;/strong&gt; → When the block was created.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Difficulty Target&lt;/strong&gt; → Mining difficulty.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce&lt;/strong&gt; → Random number miners adjust to find a valid solution.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure prevents tampering because &lt;strong&gt;every block depends on the hash of the block before it&lt;/strong&gt;.  &lt;/p&gt;


&lt;h2&gt;
  
  
  ⚡ Proof-of-Work
&lt;/h2&gt;

&lt;p&gt;Miners must find a &lt;strong&gt;nonce&lt;/strong&gt; so that the block header hash is &lt;strong&gt;below the difficulty target&lt;/strong&gt;.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On average, a block is mined every &lt;strong&gt;10 minutes&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Difficulty adjusts every &lt;strong&gt;2016 blocks (~2 weeks)&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Changing even one transaction would force re-mining of that block and all blocks after it.
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🤝 Consensus Rules
&lt;/h2&gt;

&lt;p&gt;From the &lt;a href="https://developer.bitcoin.org/devguide/block_chain.html" rel="noopener noreferrer"&gt;Consensus and Proof-of-Work section&lt;/a&gt;:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“When several nodes all have the same blocks in their blockchain, they are considered to be in consensus.”  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Key Rules:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Valid blocks&lt;/strong&gt; must meet all requirements (valid transactions, valid proof-of-work, correct structure).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Longest Chain Rule&lt;/strong&gt;: All nodes follow the chain with the most cumulative proof-of-work.
&lt;/li&gt;
&lt;li&gt;Invalid blocks are rejected automatically.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 This ensures &lt;strong&gt;all nodes converge&lt;/strong&gt; on the same blockchain history.  &lt;/p&gt;


&lt;h2&gt;
  
  
  🦀 Rust Example: Simple Merkle Root
&lt;/h2&gt;

&lt;p&gt;Here’s a small Rust snippet that shows how a Merkle Root is computed from a list of transactions (using &lt;code&gt;sha2&lt;/code&gt; crate).&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;use&lt;/span&gt; &lt;span class="nn"&gt;sha2&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Sha256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Digest&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;Sha256&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.to_vec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;merkle_root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;txs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;txs&lt;/span&gt;&lt;span class="nf"&gt;.is_empty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;txs&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="mi"&gt;1&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;new_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;txs&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.step_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;txs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&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;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;txs&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;txs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&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;txs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// duplicate if odd&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;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="nf"&gt;.extend_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="nf"&gt;.extend_from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="n"&gt;new_level&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;combined&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;txs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_level&lt;/span&gt;&lt;span class="nf"&gt;.iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.map&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="nf"&gt;.as_slice&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;txs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nf"&gt;.to_vec&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&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;txs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;b"tx1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"tx2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"tx3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"tx4"&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;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merkle_root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txs&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;"Merkle Root: {:x?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&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;h2&gt;
  
  
  🔐 Final Reflection
&lt;/h2&gt;

&lt;p&gt;This post covered what the &lt;a href="https://developer.bitcoin.org/devguide/block_chain.html" rel="noopener noreferrer"&gt;Bitcoin Developer Guide: Block Chain&lt;/a&gt; section describes:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Transactions (locking/unlocking scripts).
&lt;/li&gt;
&lt;li&gt;Mempool and transaction flow.
&lt;/li&gt;
&lt;li&gt;Block structure.
&lt;/li&gt;
&lt;li&gt;Merkle Trees.
&lt;/li&gt;
&lt;li&gt;Proof-of-Work.
&lt;/li&gt;
&lt;li&gt;Consensus rules (longest chain).
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;✨ Next Step: In the next post, I’ll explore the &lt;strong&gt;transaction lifecycle in detail&lt;/strong&gt;—from creation to confirmation—so we can see how wallets and nodes actually handle them.  &lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>bitcoin</category>
      <category>architecture</category>
      <category>learning</category>
    </item>
    <item>
      <title>🍎 From UTXOs to SegWit: How Bitcoin Fixed Transaction Malleability and Lowered Fees</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Fri, 26 Sep 2025 02:50:18 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/from-utxos-to-segwit-how-bitcoin-fixed-transaction-malleability-and-lowered-fees-358b</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/from-utxos-to-segwit-how-bitcoin-fixed-transaction-malleability-and-lowered-fees-358b</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you’re building Bitcoin or Lightning applications in Rust, understanding the difference between legacy transactions and SegWit is crucial.  &lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How &lt;strong&gt;UTXOs&lt;/strong&gt; and scripts work
&lt;/li&gt;
&lt;li&gt;The problems with legacy transactions
&lt;/li&gt;
&lt;li&gt;How &lt;strong&gt;SegWit&lt;/strong&gt; solved these problems
&lt;/li&gt;
&lt;li&gt;Why this matters for the Lightning Network
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Legacy Transactions (P2PKH)
&lt;/h2&gt;

&lt;p&gt;In Bitcoin’s original system, when Alice wants to send BTC to Bob, she must:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign the transaction with her &lt;strong&gt;private key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Provide her &lt;strong&gt;public key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Specify Bob’s &lt;strong&gt;public key hash&lt;/strong&gt; as the output
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Legacy Transaction Structure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input (scriptSig = Unlocking script):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;signature&amp;gt; &amp;lt;publicKey&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output (locking script):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OP_DUP OP_HASH160 &amp;lt;Bob’s publicKeyHash&amp;gt; OP_EQUALVERIFY OP_CHECKSIG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Diagram – Legacy Transaction
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Input ] -------------------------&amp;gt; [ Output ]
  scriptSig:                          locking script:
  &amp;lt;AliceSig&amp;gt; &amp;lt;AlicePubKey&amp;gt;            OP_DUP OP_HASH160 &amp;lt;BobPKH&amp;gt; OP_EQUALVERIFY OP_CHECKSIG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alice proves ownership with her signature + public key.
&lt;/li&gt;
&lt;li&gt;Miners hash Alice’s public key, compare it to the UTXO’s public key hash, and check the signature.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Problems With Legacy Transactions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Malleability:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Transaction IDs included the signature. If anyone slightly modified the signature, the txid changed. This caused big problems for advanced protocols like Lightning.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Fees:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Signatures and public keys are large. Bigger transactions → higher fees.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Enter SegWit (P2WPKH)
&lt;/h2&gt;

&lt;p&gt;SegWit (Segregated Witness) moved the unlocking data (signature + public key) out of the &lt;code&gt;scriptSig&lt;/code&gt; into a new structure called the &lt;strong&gt;witness&lt;/strong&gt;.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;scriptSig&lt;/code&gt; is now empty (or minimal).
&lt;/li&gt;
&lt;li&gt;Witness data is not included in the transaction ID calculation.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  SegWit Transaction Structure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input (scriptSig):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(empty or minimal)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Witness:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;signature&amp;gt; &amp;lt;publicKey&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output (locking script – unchanged):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OP_DUP OP_HASH160 &amp;lt;Bob’s publicKeyHash&amp;gt; OP_EQUALVERIFY OP_CHECKSIG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Diagram – SegWit Transaction
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Input ] -----&amp;gt; [ Output ] + [ Witness ]
  scriptSig:       locking script:      witness data:
  (empty)          OP_DUP OP_HASH160    &amp;lt;AliceSig&amp;gt; &amp;lt;AlicePubKey&amp;gt;
                   &amp;lt;BobPKH&amp;gt;
                   OP_EQUALVERIFY
                   OP_CHECKSIG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Why This Matters
&lt;/h2&gt;

&lt;p&gt;SegWit fixed two key issues:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No more malleability:&lt;/strong&gt;
Txids are stable because signatures aren’t included in the hash.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower fees:&lt;/strong&gt;
Witness data is discounted, making transactions smaller and cheaper.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Impact on Lightning Network
&lt;/h2&gt;

&lt;p&gt;SegWit wasn’t just a cleanup. It enabled:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lightning Network:&lt;/strong&gt; Needs stable txids to work.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; More transactions fit into each block.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future upgrades:&lt;/strong&gt; Like Taproot, which builds on SegWit.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Rust Code Example
&lt;/h2&gt;

&lt;p&gt;Here’s a &lt;strong&gt;simplified Rust example&lt;/strong&gt; showing how legacy and SegWit signatures differ when building transactions.&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;use&lt;/span&gt; &lt;span class="nn"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;blockdata&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;consensus&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;serialize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;util&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sighash&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SighashCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EcdsaSighashType&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Legacy P2PKH signing&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;sign_legacy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SecretKey&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;secp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SighashCache&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&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;sighash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="nf"&gt;.legacy_signature_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_pubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;EcdsaSighashType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sighash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secp&lt;/span&gt;&lt;span class="nf"&gt;.sign_ecdsa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privkey&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;"Legacy signature: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// SegWit P2WPKH signing&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;sign_segwit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nn"&gt;secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SecretKey&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;secp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;SighashCache&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&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;sighash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="nf"&gt;.p2wpkh_signature_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;script_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_sat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nn"&gt;EcdsaSighashType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;All&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;secp256k1&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sighash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;sig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secp&lt;/span&gt;&lt;span class="nf"&gt;.sign_ecdsa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;privkey&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;"SegWit signature: {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sig&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By moving signatures into the witness field, Bitcoin became &lt;strong&gt;cheaper, safer, and faster&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;As developers, understanding this transition is essential — not just for implementing wallets but also for building scalable Layer 2 solutions like Lightning.  &lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>blockchain</category>
      <category>security</category>
    </item>
    <item>
      <title>Mastering Multi-Signature Transactions in Bitcoin: Workflow, Optimizations, and Trends</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Wed, 24 Sep 2025 01:56:49 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/mastering-multi-signature-transactions-in-bitcoin-workflow-optimizations-and-trends-ono</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/mastering-multi-signature-transactions-in-bitcoin-workflow-optimizations-and-trends-ono</guid>
      <description>&lt;p&gt;Multi-signature (multisig) wallets are fundamental to securing digital assets in the blockchain ecosystem, particularly Bitcoin. Their applications range from institutional custody to secure DAO treasuries. This post provides an expert-level deep dive into the multi-signature transaction process, enriched with advanced features, optimization techniques, and the current trends shaping this domain.&lt;/p&gt;

&lt;p&gt;🔐 Phase 1: Wallet Setup&lt;/p&gt;

&lt;p&gt;The initial step involves preparing the multi-signature environment across all cosigners:&lt;br&gt;
    1.  Public Key Collection: All cosigners generate key pairs and exchange public keys securely.&lt;br&gt;
    2.  Wallet Configuration: A multisig wallet is constructed using M-of-N schema (e.g., 2-of-3), leveraging public keys.&lt;br&gt;
    3.  Shared Address Generation: The shared P2WSH (Pay-to-Witness-Script-Hash) address is derived.&lt;br&gt;
    4.  Configuration Export/Import: Each cosigner imports the multisig setup, typically via QR code or configuration files.&lt;/p&gt;

&lt;p&gt;📝 Phase 2: Transaction Creation &amp;amp; Signing&lt;/p&gt;

&lt;p&gt;Once the wallet is live, the process of sending funds involves:&lt;br&gt;
    1.  Transaction Drafting: One cosigner specifies recipient, amount, and fee — producing an unsigned PSBT (Partially Signed Bitcoin Transaction).&lt;br&gt;
    2.  Signature Collection:&lt;br&gt;
    • The PSBT is shared across cosigners.&lt;br&gt;
    • Each participant signs it using their private key.&lt;br&gt;
    • Signatures are validated and deduplicated.&lt;br&gt;
    3.  Threshold Checking: Once enough valid signatures are collected (e.g., 2 of 3), the transaction can be finalized.&lt;br&gt;
    4.  Broadcasting: Final transaction is pushed to the Bitcoin network.&lt;/p&gt;

&lt;p&gt;🧠 Tip: Always verify the transaction before finalizing — human errors or malware could alter recipients or fees.&lt;/p&gt;

&lt;p&gt;🔍 Phase 3: UTXO Management (The Hidden Complexity)&lt;/p&gt;

&lt;p&gt;While often abstracted by wallets, UTXO (Unspent Transaction Output) selection plays a critical role:&lt;br&gt;
    • Balance Updates: Wallets must scan the blockchain to update available UTXOs.&lt;br&gt;
    • Coin Selection: Efficient algorithms like Branch and Bound or Knapsack optimize which UTXOs to use.&lt;br&gt;
    • Fee Estimation: Depends on transaction size; SegWit discounts help reduce costs.&lt;/p&gt;

&lt;p&gt;💡 Advanced: Implement custom UTXO selection logic in Rust using bdk for full control over coin selection policies.&lt;/p&gt;

&lt;p&gt;🛡️ Phase 4: Signature Validation and Security Measures&lt;br&gt;
    • Partial Signature Collection: Ensure all cosigners sign independently, and only once.&lt;br&gt;
    • Duplicate Detection: Protects against accidental or malicious re-signing.&lt;br&gt;
    • Signature Verification: Use libraries like secp256k1 to validate signature authenticity.&lt;br&gt;
    • Threshold Confirmation: Confirm that the required M signatures are present before finalizing.&lt;/p&gt;

&lt;p&gt;🔐 Security Tip: Use hardware wallets and air-gapped devices to sign transactions safely.&lt;/p&gt;

&lt;p&gt;🌐 Phase 5: Transaction Broadcasting &amp;amp; Monitoring&lt;br&gt;
    • Network Validation: Ensure the mempool accepts the transaction (e.g., fee is sufficient).&lt;br&gt;
    • Transaction ID Tracking: Monitor confirmation status using tools like mempool.space.&lt;br&gt;
    • Failure Recovery: Handle cases where broadcast fails (e.g., replace-by-fee for stuck transactions).&lt;/p&gt;

&lt;p&gt;📡 Broadcast Methods: Via full node (bitcoind), public APIs, or P2P broadcast protocols.&lt;/p&gt;

&lt;p&gt;🧩 Optimization Techniques&lt;/p&gt;

&lt;p&gt;To streamline the process, especially in high-frequency environments:&lt;br&gt;
    • Pre-signing Logic: Pre-authorize blank transactions with defined policies for fast execution.&lt;br&gt;
    • Signature Aggregation (MuSig2): Shortens the process by aggregating keys and signatures, reducing size and improving privacy.&lt;br&gt;
    • Session Management: Cosigner daemons maintain active sessions to minimize latency.&lt;br&gt;
    • Batching: Aggregate multiple outputs in one transaction to save fees.&lt;/p&gt;

&lt;p&gt;📈 Trends and Future Directions&lt;br&gt;
    • Taproot &amp;amp; MuSig2: Enhances privacy and efficiency for multisig transactions.&lt;br&gt;
    • N-of-N with Scriptless Scripts: Removes script visibility, improving fungibility.&lt;br&gt;
    • Threshold Signature Schemes (TSS): Distributed signing without revealing full keys.&lt;br&gt;
    • Smart Contract Coordination: On chains like Bitcoin’s L2s (e.g., Lightning), multisig is increasingly coordinated via smart logic.&lt;/p&gt;

&lt;p&gt;🛠 Recommended Rust Crates for Multisig Workflows&lt;br&gt;
    • bdk: Bitcoin Development Kit&lt;br&gt;
    • rust-bitcoin: Core Bitcoin types and serialization&lt;br&gt;
    • secp256k1: Signature validation&lt;br&gt;
    • miniscript: Policy-based scripting for complex conditions&lt;/p&gt;

&lt;p&gt;📚 Conclusion&lt;/p&gt;

&lt;p&gt;Understanding and mastering the multi-signature transaction process is crucial for advanced blockchain developers. Beyond the simple wallet setup and signing, a robust grasp of UTXO management, signature security, and network dynamics can set apart elite developers — especially those working in Rust and protocol engineering roles.&lt;/p&gt;

&lt;p&gt;🚀 Pro Tip: Build your own multisig coordinator in Rust as a portfolio project. It demonstrates protocol-level understanding, cryptographic knowledge, and secure systems design.&lt;/p&gt;

&lt;p&gt;Stay tuned for future posts covering Taproot-enabled multisig and integrating MuSig2 in Rust ecosystems.&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>multisig</category>
      <category>wallet</category>
      <category>utxo</category>
    </item>
    <item>
      <title>From 404|1003 to the Green Lock: How I Fixed My Rust SMS Proxy on GCP with Caddy</title>
      <dc:creator>이관호(Gwanho LEE)</dc:creator>
      <pubDate>Fri, 19 Sep 2025 04:19:19 +0000</pubDate>
      <link>https://dev.to/_56d7718cea8fe00ec1610/from-4041003-to-the-green-lock-how-i-fixed-my-rust-sms-proxy-on-gcp-with-caddy-1i63</link>
      <guid>https://dev.to/_56d7718cea8fe00ec1610/from-4041003-to-the-green-lock-how-i-fixed-my-rust-sms-proxy-on-gcp-with-caddy-1i63</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: I was calling my Rust SMS proxy on a Google Cloud VM by &lt;strong&gt;IP:8080&lt;/strong&gt;, which caused Cloudflare &lt;strong&gt;1003&lt;/strong&gt; errors and browser warnings. I mapped a &lt;strong&gt;hostname&lt;/strong&gt; (&lt;code&gt;example-proxy.example.com&lt;/code&gt;) to the VM, opened &lt;strong&gt;ports 80/443&lt;/strong&gt;, put &lt;strong&gt;Caddy&lt;/strong&gt; in front of my Rust app, and let it auto-issue a &lt;strong&gt;Let’s Encrypt&lt;/strong&gt; certificate. Result: clean &lt;strong&gt;HTTPS&lt;/strong&gt; endpoint that “just works,” and an easy env var for my Cloudflare Worker: &lt;code&gt;SMS_API_URL=https://example-proxy.example.com/sms/send&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why this post?
&lt;/h2&gt;

&lt;p&gt;I built a Rust program that proxies SMS requests. It ran fine at &lt;code&gt;http://203.0.113.45:8080&lt;/code&gt;, but when I integrated it with a Cloudflare Worker and the frontend, I started seeing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;404 Not Found&lt;/code&gt; (from my origin on routes I hadn’t defined yet)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cloudflare 1003&lt;/code&gt; (when requests were made by &lt;strong&gt;IP&lt;/strong&gt; instead of a &lt;strong&gt;hostname&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post documents what the errors actually mean, how the web stack sees your request, and the exact commands/configs I used to fix it—&lt;strong&gt;for real production use&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack (before &amp;amp; after)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rust SMS proxy (Axum/Actix/Hyper) → &lt;strong&gt;listening on 0.0.0.0:8080&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Calls from Cloudflare Worker / browser sometimes used &lt;strong&gt;IP:8080&lt;/strong&gt; directly&lt;/li&gt;
&lt;li&gt;No HTTPS on origin → mixed content and proxy restrictions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS hostname: &lt;code&gt;example-proxy.example.com&lt;/code&gt; → &lt;strong&gt;A&lt;/strong&gt; record → &lt;code&gt;203.0.113.45&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caddy&lt;/strong&gt; on the VM listens on &lt;strong&gt;80/443&lt;/strong&gt;, terminates TLS with &lt;strong&gt;Let’s Encrypt&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Caddy &lt;strong&gt;reverse_proxies&lt;/strong&gt; to Rust at &lt;strong&gt;127.0.0.1:8080&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Worker ENV: &lt;code&gt;SMS_API_URL=https://example-proxy.example.com/sms/send&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The symptoms and what they actually mean
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;404 Not Found&lt;/strong&gt;: The origin (your Rust app or upstream server) doesn’t have a route for the path you requested (e.g., &lt;code&gt;/health&lt;/code&gt;). It’s not Cloudflare’s fault; it’s your app/router.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloudflare 1003&lt;/strong&gt;: Cloudflare does &lt;strong&gt;not&lt;/strong&gt; allow you to access its network by &lt;strong&gt;raw IP&lt;/strong&gt; or with a mismatched &lt;strong&gt;Host&lt;/strong&gt; header. If your code &lt;code&gt;fetch()&lt;/code&gt;es &lt;code&gt;http://203.0.113.45:8080/...&lt;/code&gt; through a CF zone, expect this. Cloudflare wants a &lt;strong&gt;domain&lt;/strong&gt; that the zone knows about.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mixed content / TLS issues&lt;/strong&gt;: If your frontend is &lt;strong&gt;HTTPS&lt;/strong&gt; but your API is &lt;strong&gt;HTTP&lt;/strong&gt;, browsers can block or warn. You want &lt;strong&gt;HTTPS → HTTPS&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key vocabulary (fast, practical definitions)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hostname / FQDN&lt;/strong&gt;: A human-readable name (e.g., &lt;code&gt;example-proxy.example.com&lt;/code&gt;) that maps to an IP via DNS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A record&lt;/strong&gt;: DNS record that maps a hostname to an IPv4 address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse proxy&lt;/strong&gt;: A public-facing server that forwards incoming requests to a private backend (our Rust app).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS (SSL)&lt;/strong&gt;: Encryption for HTTP. Gives you &lt;code&gt;https://&lt;/code&gt; and the browser’s green lock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Let’s Encrypt&lt;/strong&gt;: A free CA that issues certificates automatically. Caddy handles it for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SNI&lt;/strong&gt;: The TLS extension that lets one IP serve many hostnames by telling the server which cert to use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP-01 challenge&lt;/strong&gt;: Let’s Encrypt check that proves you control a domain by answering a request on &lt;strong&gt;port 80&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin&lt;/strong&gt;: Your actual application server (here: Rust on 127.0.0.1:8080).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge&lt;/strong&gt;: The public-facing entrypoint (here: Caddy on 80/443; sometimes Cloudflare or a load balancer).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CORS&lt;/strong&gt;: Browser security policy for cross-origin requests. If a Cloudflare Worker calls your origin server-to-server, you usually don’t need CORS on the origin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project ID (GCP)&lt;/strong&gt;: The string identifier for your Google Cloud project (not the numeric project number).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The fix — exact steps (copy/paste friendly)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Point a hostname to your VM
&lt;/h3&gt;

&lt;p&gt;I used &lt;strong&gt;DuckDNS&lt;/strong&gt; to create &lt;code&gt;example-proxy.example.com&lt;/code&gt; pointing to &lt;code&gt;203.0.113.45&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quick check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig +short example-proxy.example.com
&lt;span class="c"&gt;# Expect: 203.0.113.45&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Open ports 80 and 443 in Google Cloud
&lt;/h3&gt;

&lt;p&gt;We need &lt;strong&gt;80&lt;/strong&gt; for Let’s Encrypt (HTTP-01) and &lt;strong&gt;443&lt;/strong&gt; for real HTTPS traffic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud compute firewall-rules create allow-http  &lt;span class="nt"&gt;--allow&lt;/span&gt; tcp:80  &lt;span class="nt"&gt;--description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Allow HTTP"&lt;/span&gt;
gcloud compute firewall-rules create allow-https &lt;span class="nt"&gt;--allow&lt;/span&gt; tcp:443 &lt;span class="nt"&gt;--description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Allow HTTPS"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If &lt;code&gt;gcloud&lt;/code&gt; complains about your project, set it first:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud config &lt;span class="nb"&gt;set &lt;/span&gt;project YOUR_PROJECT_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3) Install Caddy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; debian-keyring debian-archive-keyring apt-transport-https
curl &lt;span class="nt"&gt;-1sLf&lt;/span&gt; &lt;span class="s1"&gt;'https://dl.cloudsmith.io/public/caddy/stable/gpg.key'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl &lt;span class="nt"&gt;-1sLf&lt;/span&gt; &lt;span class="s1"&gt;'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/caddy-stable.list
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; caddy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4) Configure Caddy as a reverse proxy to Rust
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;/etc/caddy/Caddyfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;example-proxy.example.com {
    reverse_proxy 127.0.0.1:8080
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reload Caddy and check status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload caddy
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status caddy &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens here&lt;/strong&gt;: Caddy automatically obtains a &lt;strong&gt;Let’s Encrypt&lt;/strong&gt; certificate for &lt;code&gt;example-proxy.example.com&lt;/code&gt; (using the HTTP-01 challenge on port 80), then starts serving HTTPS on port 443 with that cert.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5) Bind your Rust app to localhost
&lt;/h3&gt;

&lt;p&gt;Keep port 8080 private behind Caddy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./your_proxy_binary &lt;span class="nt"&gt;--host&lt;/span&gt; 127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you had previously opened 8080 to the internet, you can remove/disable that firewall rule for security.&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Test like a pro
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;If you have a health route:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://example-proxy.example.com/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If not, hit your real endpoint:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"content-type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"to":"+821012345678","text":"hello"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://example-proxy.example.com/sms/send
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a clean HTTPS response from your Rust service through Caddy.&lt;/p&gt;

&lt;h3&gt;
  
  
  7) Point your Cloudflare Worker / backend env to the hostname
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;In code:&lt;/strong&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SMS_API_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example-proxy.example.com/sms/send&lt;/span&gt;&lt;span class="dl"&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;In wrangler.toml:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[vars]&lt;/span&gt;
&lt;span class="py"&gt;SMS_API_URL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://example-proxy.example.com/sms/send"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy your Worker/Pages and you’re done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this works (the request flow explained)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;DNS&lt;/strong&gt; resolves &lt;code&gt;example-proxy.example.com → 203.0.113.45&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The browser (or Worker) connects to &lt;strong&gt;port 443&lt;/strong&gt; and says via &lt;strong&gt;SNI&lt;/strong&gt;: “I’m &lt;code&gt;example-proxy.example.com&lt;/code&gt;.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caddy&lt;/strong&gt; presents the valid Let’s Encrypt certificate for that hostname.&lt;/li&gt;
&lt;li&gt;Caddy &lt;strong&gt;reverse_proxies&lt;/strong&gt; the request to &lt;code&gt;http://127.0.0.1:8080&lt;/code&gt; (your Rust app).&lt;/li&gt;
&lt;li&gt;The response streams back over the secure TLS connection to the client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Result: a trusted green lock, no mixed content, no Cloudflare 1003, and a single stable URL for your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting &amp;amp; FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: Caddy failed to get a certificate.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure &lt;code&gt;example-proxy.example.com&lt;/code&gt; resolves to &lt;code&gt;203.0.113.45&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make sure &lt;strong&gt;ports 80/443&lt;/strong&gt; are open and reachable from the internet.&lt;/li&gt;
&lt;li&gt;Check logs: &lt;code&gt;journalctl -u caddy -n 100 --no-pager&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Confirm nothing else is already listening on port &lt;strong&gt;80&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q: I still get 404 on &lt;code&gt;/health&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;That’s your Rust router, not Caddy. Either add a route or test &lt;code&gt;/sms/send&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q: Do I need CORS?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the &lt;strong&gt;browser&lt;/strong&gt; calls your Rust origin directly, yes. If your &lt;strong&gt;Worker&lt;/strong&gt; calls the origin server-to-server, you typically don’t need CORS on the origin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q: Could I use a Google HTTPS Load Balancer instead?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yes. It’s managed TLS and scales nicely, but setup is heavier and may add cost. Caddy is a sweet spot for a single VM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Q: Could I avoid opening ports with Cloudflare Tunnel?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yes. A tunnel maps a public hostname to your private &lt;code&gt;127.0.0.1:8080&lt;/code&gt; without exposing ports. It’s also a good option.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security &amp;amp; production hardening
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bind Rust to 127.0.0.1&lt;/strong&gt; so only Caddy can reach it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close 8080&lt;/strong&gt; from the internet if you previously opened it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use env vars&lt;/strong&gt; for endpoints and secrets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limit / auth&lt;/strong&gt; your &lt;code&gt;/sms/send&lt;/code&gt; to prevent abuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor logs&lt;/strong&gt; (&lt;code&gt;journalctl&lt;/code&gt;, app logs) and set alerts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backups &amp;amp; updates&lt;/strong&gt;: keep Caddy and OS packages updated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bonus: Minimal health route in Rust
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Axum&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;use&lt;/span&gt; &lt;span class="nn"&gt;axum&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="nn"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;net&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SocketAddr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;health&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="k"&gt;'static&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"ok"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* your handler */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/sms/send"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;send_sms&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;addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SocketAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1:8080"&lt;/span&gt;&lt;span class="nf"&gt;.parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nn"&gt;axum&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="nf"&gt;.into_make_service&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&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;Actix‑web&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;use&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Responder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nd"&gt;#[get(&lt;/span&gt;&lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;health&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Responder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.finish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;#[actix_web::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&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="nn"&gt;HttpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nn"&gt;App&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;health&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/sms/send"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;actix_web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;web&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="nf"&gt;.bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] DNS: &lt;code&gt;example-proxy.example.com → 203.0.113.45&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] GCP Firewall: &lt;strong&gt;80/443&lt;/strong&gt; allowed&lt;/li&gt;
&lt;li&gt;[ ] Caddy installed and &lt;code&gt;reverse_proxy 127.0.0.1:8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Rust bound to &lt;strong&gt;127.0.0.1:8080&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;curl -I https://example-proxy.example.com/…&lt;/code&gt; works&lt;/li&gt;
&lt;li&gt;[ ] Worker env: &lt;code&gt;SMS_API_URL=https://example-proxy.example.com/sms/send&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don’t call your backend by &lt;strong&gt;raw IP&lt;/strong&gt;—use a &lt;strong&gt;hostname&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Put a &lt;strong&gt;reverse proxy&lt;/strong&gt; (Caddy/Nginx) at the edge to handle &lt;strong&gt;TLS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Keep your app private on &lt;strong&gt;localhost&lt;/strong&gt;; only expose 80/443.&lt;/li&gt;
&lt;li&gt;Prefer env-driven endpoints so deployments are clean.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now your Rust SMS proxy is production-ready with a proper HTTPS URL that your frontend and Workers can trust.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cloud</category>
      <category>caddy</category>
      <category>network</category>
    </item>
  </channel>
</rss>
