<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[The FireAcademy.io Blog]]></title><description><![CDATA[Posts about the Chia blockchain with a focus on Chialisp. Written with love by Yak.]]></description><link>https://blog.fireacademy.io</link><image><url>https://substackcdn.com/image/fetch/$s_!J7qa!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb49289d7-fe15-4094-b450-6c730b08a990_955x955.png</url><title>The FireAcademy.io Blog</title><link>https://blog.fireacademy.io</link></image><generator>Substack</generator><lastBuildDate>Sat, 02 May 2026 10:22:59 GMT</lastBuildDate><atom:link href="https://blog.fireacademy.io/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[yakuhito]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[fireacademy@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[fireacademy@substack.com]]></itunes:email><itunes:name><![CDATA[yakuhito]]></itunes:name></itunes:owner><itunes:author><![CDATA[yakuhito]]></itunes:author><googleplay:owner><![CDATA[fireacademy@substack.com]]></googleplay:owner><googleplay:email><![CDATA[fireacademy@substack.com]]></googleplay:email><googleplay:author><![CDATA[yakuhito]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[A dApp Developer’s Perspective on Rue v. Chialisp]]></title><description><![CDATA[A comparison between Chialisp and Rue based on my experience adapting 39 puzzles from Chialisp to Rue and benchmarking the results]]></description><link>https://blog.fireacademy.io/p/rue-vs-chialisp</link><guid isPermaLink="false">https://blog.fireacademy.io/p/rue-vs-chialisp</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Thu, 19 Feb 2026 13:49:02 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fcd9fd10-8602-4af1-944e-441a2ef6ad40_1280x720.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of Chia&#8217;s biggest advantages over Bitcoin is its programmability: each coin&#8217;s logic is expressed as a set of ChiaLisp Virtual Machine (CLVM) instructions, allowing Chia coins to operate in ways that turn them into vaults, tokens (CATs/NFTs), and even dApps (e.g., TibetSwap). That said, CLVM is more like assembly code - designed for machines to understand first, then for humans, which is why higher-order programming languages such as Chialisp are used to code puzzles. </p><p>Last year, I was extremely excited to hear about the launch of Rue, a new programming language for Chia puzzles. Like Chialisp, Rue has a compiler that transforms &#8216;human-friendly&#8217; code into CLVM bytecode, which is what gets executed when coins are spent on Chia. If you&#8217;re interested in more of the inner workings of the compiler, <a href="https://blog.rigidity.dev/">Rigidity&#8217;s blog</a> has some great articles on the topic.</p><p>I am always looking to improve the quality (and timeline) of my Chia projects, so I decided to give Rue a try for the three main initiatives that I was working on: the Reward Distributor, XCHandles, and CATalog. All of them were already pretty far along, which allowed me to compare the existing Chialisp code directly to its Rue equivalent. Below, I (quite subjectively) compare the two languages in terms of the features I consider to be the most important: efficiency, developer experience, and security. While I tried noting the biggest nuances/caveats in the differences, I believe it&#8217;s best to take this with a grain of salt and form your own opinion - let me know your take in the comments!</p><h3>Efficiency</h3><p>It&#8217;s usually difficult to quantify the efficiency of programs in a way that captures all dimensions, but, thankfully, the Chia blockchain provides a &#8216;standard&#8217; way through execution cost. Put simply, cost quantifies the computational resources - storage, execution, and changes to the blockchain - required to spend some coins. It is synonymous with a transaction&#8217;s size, and has a direct role in determining which transactions are prioritized (farmers essentially try to maximize fee-per-cost when building blocks). You can learn more about cost <a href="https://chialisp.com/costs/">here</a> and <a href="https://docs.chia.net/chia-blockchain/coin-set-model/costs/">here</a>.</p><p>As I had been working on the Reward Distributor/XCHandles/CATalog for a while, all projects already had tests covering all their features set up. In fact, one of the classes I added to the Chia wallet SDK is the benchmarker, which allows developers to easily label spends sent to the simulator during tests and later see statistics about spends with the same labels - to be more specific, their number and average/median/maximum/minimum costs. I added <code>Benchmark</code> specifically for action layer dApps, as I was curious about the throughput they support - the number of interactions in a block is inversely related to the cost of said interactions. </p><p>Here, I think the numbers speak for themselves. For each tested action (except setup, which was used as a control), bytecode generated by the Rue compiler had less cost than the Chialisp-generated equivalent. To quantify, all values were in the 93.13%-98.21% range, with an average relative cost of 95.91% and a median of 95.92%. Put another way, on average, using Rue saved 4.09% of the final bundle&#8217;s size, and in all examples Rue generated less costly (&#8216;more efficient&#8217;) programs than Chialisp. The full data can be found <a href="https://docs.google.com/spreadsheets/d/1nqCbU9qlaFnRqIPJaSPdogLCGBsFFhyIduAuk9ZiJK4/edit?gid=535196585#gid=535196585">here</a>.</p><p>While 4.09% may seem like a low number, keep in mind that this cost difference is for fundamentally equivalent puzzles. Users of these dApps would pay, on average, 4.09% less in fees under fee pressure conditions. To me, this is an impressive improvement, as the Chialisp puzzles used for comparison have gone through multiple rounds of (sometimes esoteric) optimizations. What&#8217;s more, testing bundles were made to be similar to user interactions, which means they contain adjacent coin operations such as NFT transfers and offers - this makes relative cost decreases look worse than they actually are. If we are to believe the <a href="https://docs.chia.net/chia-blockchain/coin-set-model/costs/#estimated-transaction-costs">official cost estimates table</a>, each spend bundle had almost the equivalent of one standard transaction removed from it in terms of cost (on average).</p><p>So, where does the cost difference come from? The Rue and Chialisp puzzles I compared are functionally equivalent, so they will have the same condition cost, as they output the same conditions. Thus, the difference comes from a mix of storage and execution cost. While future compression initiatives will minimize cost due to on-chain storage for puzzles, I can confidently say that, right now, a puzzle&#8217;s size makes up for a majority of its cost, and I predict that will be the case in the short and medium terms as well. A nice property of size is that you can record it directly from puzzles without any noise (coming, for example, from other puzzles running in the same spend bundle).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gv3A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gv3A!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 424w, https://substackcdn.com/image/fetch/$s_!gv3A!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 848w, https://substackcdn.com/image/fetch/$s_!gv3A!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 1272w, https://substackcdn.com/image/fetch/$s_!gv3A!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gv3A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png" width="690" height="427.719298245614" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:742,&quot;width&quot;:1197,&quot;resizeWidth&quot;:690,&quot;bytes&quot;:69242,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.fireacademy.io/i/188485517?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gv3A!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 424w, https://substackcdn.com/image/fetch/$s_!gv3A!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 848w, https://substackcdn.com/image/fetch/$s_!gv3A!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 1272w, https://substackcdn.com/image/fetch/$s_!gv3A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c9fb244-e243-458c-864e-61b234eda11f_1197x742.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Figure 1</em> - Graph created by plotting the sizes of the CLVM bytecode generated by the Rue compiler against the CLVM bytecode generated by the Chialisp compiler for each of the 39 puzzles used for this test. Regression R^2 is 0.989, indicating that the regression line explains the data very well.</figcaption></figure></div><p>The Rue compiler removed 10 to 231 bytes from each of the 39 puzzles used in this small experiment. As a percentage, the range is 6.08% to 29.59%. The average number of bytes saved per puzzle is 110.72 (14.84%), and the median is 117 bytes (13.58%). You can find the raw data on the &#8216;Bytes&#8217; tab of the spreadsheet linked above.</p><p>The regression line in the graph above suggests that the savings from switching to Rue can be approximated quite well using the equation of a line. There is an absolute saving, which I believe comes from Rue&#8217;s implementation of a frequently used Chialisp function, <code>curry_tree_hash</code>. Rue&#8217;s standard library uses an implementation that is significantly smaller but has a higher runtime cost, while the version used in Chialisp prioritizes runtime at the expense of a much larger storage footprint. An absolute saving of 32.2 bytes (387.600 cost) is indeed very close to the differences observed in the <a href="https://github.com/Rigidity/curry-benchmarks">Chialisp vs. Rue curry benchmarks</a>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts right in your inbox.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The slope of the regression line suggests that the Rue compiler also has a proportional advantage: each byte produced by Chialisp &#8216;corresponds&#8217; to 0.9 bytes produced by Rue. This number likely comes from a few of the compiler optimizations Rue has that Chialisp hasn&#8217;t implemented, such as:</p><ul><li><p>Type checking (&#8216;is&#8217;) simplification: If the type of a checked variable is already known, the check will be evaluated and replaced with the resulting boolean at compile time</p></li><li><p>Symbol grouping: If multiple bindings (&#8216;let&#8217;) are declared in the same code branch, the compiler tries to group definitions together to minimize the number of apply operators used in the resulting bytecode </p></li><li><p>Symbol inlining: If a variable or constant is used a single time, its value will be inlined. Similarly, if a function is called a single time and its arguments are used a single time as well, it will be inlined automatically.</p></li><li><p>Superpaths: The compiler detects when two or more references being concatenated could be replaced by a reference to an intermediary tree node (e.g., <code>(c 2 3) -&gt; 5</code>) <em>(hey, I suggested this one!)</em></p></li><li><p>Binary tree arguments: The compiler structures the arguments of some functions as trees instead of lists, which makes referencing them take fewer bytes in some cases <em>(hey, I suggested this one as well!)</em></p></li></ul><p><strong>Verdict</strong>: Rue &gt; Chialisp, for now. There is no magical reason why the Chialisp compiler can&#8217;t implement Rue&#8217;s optimizations, but so far it hasn&#8217;t.</p><p><em>Note</em>: All the puzzles in this benchmark use the &#8216;standard&#8217; version of Chialisp for efficiency purposes. Puzzles in modern Chialisp, while easier to write due to QoL improvements such as &#8216;let,&#8217; tend to take up a lot more bytes. There are plans to adapt the normal optimizer for modern Chialisp as well once it is &#8216;properly&#8217; released; for this comparison, I used using the version that generates the most efficient puzzles.</p><h3>Developer Experience</h3><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-T1B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-T1B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 424w, https://substackcdn.com/image/fetch/$s_!-T1B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 848w, https://substackcdn.com/image/fetch/$s_!-T1B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 1272w, https://substackcdn.com/image/fetch/$s_!-T1B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-T1B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png" width="1456" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:647197,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.fireacademy.io/i/188485517?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-T1B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 424w, https://substackcdn.com/image/fetch/$s_!-T1B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 848w, https://substackcdn.com/image/fetch/$s_!-T1B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 1272w, https://substackcdn.com/image/fetch/$s_!-T1B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F64fafb5e-1779-4961-8a44-348e15fb21ee_2184x945.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Figure 2</em> - Selected code section from <a href="https://github.com/DIG-Network/reward-distributor-clsp/blob/main/puzzles/actions/reward_distributor/commit_incentives.clsp">commit_incentives.clsp</a> (left) and <a href="https://github.com/DIG-Network/reward-distributor-clsp/blob/main/rue-puzzles/actions/reward_distributor/commit_incentives.rue">commit_incentives.rue</a> (right). Rue uses less parentheses, and allows replacing if statements with one raising branch with &#8220;assert.&#8221; Stager functions are not needed thanks to &#8216;let&#8217;, chain prepend operations &#8220;(c 1 (c 2 &#8230;))&#8221; can be replaced with a list and the spread operator &#8220;[1, 2, &#8230;base]&#8221;, and structs offer a great way to use packed data.</figcaption></figure></div><p>I believe one of Rue&#8217;s biggest advantages is readability - the ability of another developer to scan the code and understand what it does easily. Not only does this make collaboration and audits faster, but it also accelerates the development process itself. Particularly, I find Chialisp&#8217;s parenthesis structure to take <em>some</em> cognitive load during development, which Rue eliminates through the use of Rust-like syntax. Another thing I had to keep in mind during the experiment is that &#8216;standard&#8217; Chialisp does not have <code>let</code>, but that is fixed in modern Chialisp, so I won&#8217;t take it as a factor. </p><p>Speaking of cognitive load, formatting code is also something that could be automated. This is not available for any of the two languages, but brings us to another category: tooling. Both languages have syntax highlighting, but I found the Chialisp extension to be extremely unreliable while modifying the code live (to the point where I just disable it since it&#8217;s better than seeing some portions highlighted while others aren&#8217;t). Rue, on the other hand, has an extension that works great and is mostly stable (works consistently, with only rare, non-reproducible edge cases). Another nice feature of Rue is that you can write test functions in the same file with Rue code - this is similar to what <a href="https://www.getfoundry.sh/">foundry</a> does, and I expect it will become a very popular method of testing functions. Still, because the 3 apps I used were initially written in Chialisp (which does not have such features out-of-the-box), the benchmark code was written in the wallet SDK, which has greatly improved developer experience on Chia but is not part of the Rue language itself. One integration worth mentioning is <code>compile_rue!</code>, which allows developers to test the latest version of their code without having to compile, then copy the bytecode and hash during development (it&#8217;s similar to fast refresh for Next - change the code, and, the next time you run your test, the new bytecode/hash will be used).</p><p>Lastly, this post wouldn&#8217;t be complete if this section didn&#8217;t talk a bit about AI. In general, I am opposed to using AI as the primary way of writing on-chain code, which is responsible for managing user funds - if we want this industry to be taken seriously, we should treat critical code much more carefully than we treat UI code controlling how round an edge is. That said, I am all for using AI to complement reviews/audits/bug bounties/contests/etc. Generally, AI models were able to generate Rue completions very well, with the worst suggestions being in the places where they needed to rely heavily on Chia blockchain specifics (e.g., output conditions such as SEND_MESSAGE). For Chialisp, my usual workflow is to disable suggestions entirely - even with many puzzles in the codebase giving the models some of the syntax, suggestions are still terrible, and many times models try to use LISP operators. Ultimately, I think you can finetune models to be better for either language, but their current comprehension and ability to suggest good completions indicate that Rue may be much more &#8216;intuitive&#8217; for programmers transitioning to Chia on-chain programming. That is, model performance on completions is a good proxy for how beginner friendly a programming language is.</p><p><strong>Verdict</strong>: Rue &gt;&gt; Chialisp. Rue&#8217;s readability and beginner-friendliness cannot be easily copied by Chialisp, unlike its nice chia-wallet-sdk integration and testing suite.</p><h3>Security</h3><p>When it comes to on-chain programs, security is, in my opinion, the most important consideration. An easy way to compare languages is to ask, &#8220;How used is this in production?&#8221; Here, Chialisp takes the lead, but I predict Rue will quickly catch up due to it beating Chialisp in the other two categories (and stl agrees, see #6 <a href="https://xch.today/2026/02/09/top-10-chia-predictions-for-2026/">here</a>).</p><p>Another aspect is how syntax makes developers think and consider attack scenarios. An example from other ecosystems is Solidity, where re-entrancy vulnerabilities are easy to introduce if you&#8217;re not aware of them. I think that the architecture of the Chia blockchain inherently makes developers consider side-effects the same way for both languages, as they&#8217;re are all determined in the output condition list (e.g., create a coin).</p><p>A more nuanced question to ask is, &#8220;How likely is it that the code that I&#8217;m reading is doing what I think it&#8217;s doing?&#8221; Here, I think Chialisp has an advantage, as it seems a lot closer to CLVM than Rue, especially when it comes to the type system. For example, Rue&#8217;s type checks (e.g., <code>assert var is Bytes32</code>) rely on the compiler&#8217;s inferred types, which are not always enforced strictly in the final bytecode (for the arguments of the <code>main</code> function, for example). While I understand why Rue avoids the storage/runtime overhead for these checks, not understanding how the compiler handles types may create issues. That said, I believe Rue&#8217;s type system prevents a lot of errors, some of which may result in security vulnerabilities - while not ideal, I am convinced this is better than Chialisp&#8217;s lack of a type system.</p><p>Lastly, I&#8217;d like to point out that both compilers are well-tested in some way or another, and, while there&#8217;s always the chance the compiler introduces vulnerabilities by mis-translating code to bytecode, I think the chances for both Rue and Chialisp are minimal given the teams&#8217; attention to security and the precautions in place.</p><p><strong>Verdict</strong>: Chialisp &gt; Rue, for now. I believe the gap between Rue and Chialisp will mostly disappear as more puzzles written in Rue reach production deployment.</p><h3>Conclusion</h3><p>There are two types of differences between Rue and Chialisp. Some of them are addressable - although Rue has an upper hand despite being more recent, Chialisp tooling and its optimizer can be improved. Likewise, Rue can (and likely will) get more &#8216;real-world&#8217; testing as the protocols using it go live and grow in TVL.</p><p>The remaining differences go deeper. In my mind, there is one root cause for them: Rue is &#8216;further away&#8217; from CLVM than Chialisp is. This makes it beginner friendly and generally much easier to read, but introduces the risk that developers might misinterpret the behavior of the compiler in some places, as Rue&#8217;s compiler has to make more complex decisions.</p><p>Personally, I think Rue&#8217;s advantages currently make it a better choice than Chialisp, and I predict this will be the case in the short/medium-term as well. I&#8217;m confident that Rue is well-tested, and my code was ultimately reviewed by the creator to ensure no compiler &#8216;edge cases&#8217; were triggered by the puzzles. Still, it remains as important as ever to follow the latest developments in Chia tooling and programming languages, which may tilt the balance quite rapidly.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/p/rue-vs-chialisp?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Enjoyed this post? Share it!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/p/rue-vs-chialisp?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.fireacademy.io/p/rue-vs-chialisp?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p><p><em>Special thanks to Rigidity and stl for making suggestions on a draft of this article.</em></p>]]></content:encoded></item><item><title><![CDATA[Too Discrete to Handle: How Low CAT Precision Can Become an Issue]]></title><description><![CDATA[A few days ago, an NFT Reward Distributor test was released as part of the DIG alpha deployment.]]></description><link>https://blog.fireacademy.io/p/too-discrete-to-handle-how-low-cat</link><guid isPermaLink="false">https://blog.fireacademy.io/p/too-discrete-to-handle-how-low-cat</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Tue, 02 Sep 2025 15:32:05 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9b8d1f24-10bc-4f5a-be55-9f42e11c3b69_1312x945.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few days ago, an <a href="https://github.com/Chia-Network/chips/pull/165">NFT Reward Distributor</a> test <a href="https://x.com/digdotnet/status/1961449065574441198">was released</a> as part of the DIG alpha deployment. The NFT distributor allows anyone to stake DataLayer Minion NFTs to continuously receive a share from a DIG token stream. This deployment is intended to test the capabilities of the reward distributor before it gets used as a means to allocate DIG mirror rewards. Fortunately (and unfortunately), the alpha test has uncovered a design flaw that leads to an uneven token distribution rate over time. This article will describe the issue, as well as what it means for minion stakers, how new puzzles will address it, and how to catch similar issues earlier in the future.</p><h2>CAT Precision</h2><p>On Ethereum, ERC-20 tokens usually have 18 decimals, likely taking inspiration from Ether (1 ether = 10^18 wei). Chia&#8217;s designers have chosen 12 decimals for XCH, but were met with a small issue when developing the Chia Asset Token (CAT) standard: for CATs to work in the coinset model, they would have to lock up small amounts of XCH (usually measured in mojos, 1 XCH = 10^12 mojos). The precision tradeoff they faced can be put as follows: giving CATs too many decimals means significant XCH needs to be locked up to mint the said CATs. If you give your CAT a precision of 12, you need to lock up a whole XCH to mint one CAT token. Giving your CAT too few decimals, on the other hand, might make it harder to use as the CAT can be broken down into fewer pieces. Ultimately, CATs now have 3 decimals, meaning the smallest non-zero CAT unit you can hold is 0.001.</p><p><em>Note that this is more of a social convention for UIs: in reality, every CAT you hold is a coin with a special puzzle and a value of cat_amount * 1000 mojos.</em></p><h2><strong>Reward Distributors and Precision</strong></h2><p>As I <a href="https://blog.fireacademy.io/p/reward-distributors-101">previously mentioned</a>, reward distributors were heavily inspired by the math behind liquidity farms. In short, the distributor syncs when someone interacts with it and calculates how many tokens should be distributed for the last period based on state data. Given the title and introduction of the article, it&#8217;s natural to ask what happens with the &#8216;remainder&#8217; that can&#8217;t be distributed for a period. For example, if 10,000 NFTs are staked and the distributor needs to allocate 10.001 DIG, what happens with the 0.001 DIG?</p><p>The worst fate the 0.001 DIG could have is to be discarded, as that means no one will ever get it. This has, of course, been the main concern around the formulas during puzzle development and review - and can&#8217;t happen for reward distributors. In the current puzzle, the distributor, like liquidity farms, allocates the 0.001 DIG to the remainder of the epoch. Essentially, the reward rate is slightly boosted so the 0.001 DIG is allocated to someone <em>eventually</em>.</p><p>This approach works fine for ERC-20 tokens because they have so many decimals that the remainder is an extremely small error that&#8217;s irrelevant in practice. On Chia, however, this becomes a relevant issue because the smallest unit is 0.001 DIG. In practice, 87,500 DIG per year means that roughly 0.001 DIG will be given to every staked NFT <em>every hour</em>. If someone syncs the distributor every few minutes - like everyone did during the first days, when users rushed to stake their NFTs - the 0.001 DIG per NFT will be pushed later and later into the epoch. Staked NFTs then had a reward rate of around 0 DIG per day during high-activity days, a relatively normal reward rate for low-activity periods that spanned hours, and will have a much higher reward rate towards the end of the epoch, when all the accumulated &#8216;postponed&#8217; rewards will get distributed.</p><p>More generally, the smallest unit of distribution takes a while to be assigned to every NFT, and syncing smaller intervals leads to rewards being &#8216;postponed.&#8217; Done often enough, someone can make the reward allocation rate slower over some periods. In turn, other periods will have a higher rate to compensate.</p><h2><strong>What This Means for Minion Holders</strong></h2><p>Extreme care was put into ensuring that rewards are not lost. Stakers will still get the 8.750 DIG per minion per year they&#8217;re owed (assuming all NFTs are staked - otherwise, the number will be higher). However, the rate at which DIG is assigned will vary based on how often people interact with the distributor.</p><h2><strong>Next Steps</strong></h2><p>The current reward distributor puzzles will be updated to fix this issue. At a high level, the new version of the distributor will have a higher internal precision for CATs. This precision will be &#8216;stripped&#8217; just before payouts. The update will allow the correct distribution of small fractions of 0.001 DIG if sync operations are done for short time intervals, effectively leading to the same behavior observed on Ethereum, where the postponed reward amounts are so small they are not practically relevant.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts right in your inbox.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>Lessons Learned</strong></h2><p>This design flaw was still caught during testing, but I believe there are ways to catch these kinds of limitations earlier. A few suggestions include:</p><ul><li><p>When <strong>designing puzzles</strong>, continuously ask yourself how the differences between Chia and the other systems where the mechanism was implemented may lead to unexpected behavior. Note that &#8216;behavior&#8217; extends past security issues such as the loss of funds.</p></li></ul><ul><li><p><strong>Test under real conditions</strong>. As part of early development, the distributor puzzles were tested on a simulator. The tests included scenarios with one or a few NFTs staked over short periods of time. The problematic precision behavior would&#8217;ve been detected if the tests included more realistic or extreme scenarios (e.g., test distribution when 10,000 NFTs are staked and 50,000 test CATs are distributed over 10 years, with someone interacting with a distributor every few minutes).</p></li><li><p><strong>Broader reviews/audits</strong>: Instead of strictly looking for ways funds could be lost, the main question in a review or audit should be &#8220;What can someone do to make the behavior of the system deviate from what&#8217;s expected?&#8221;. This requires the purpose of the system to be well-defined in advance, and for the specification to be very verbose.</p></li><li><p><strong>Documenting common issues</strong>: By posting about this issue, the hope is that other developers will have it on top of their mind when designing similar systems in the future.</p></li></ul><h2>Conclusion</h2><p>Lastly, let me extend a big thank you to everyone that has helped with testing so far. As you can see, these tests provide vital feedback that will improve the final version of the DIG Network.</p><p>You can find more about the DIG Network at <a href="https://dig.net/">dig.net</a>.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/p/too-discrete-to-handle-how-low-cat?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Enjoyed this post? Share it!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/p/too-discrete-to-handle-how-low-cat?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.fireacademy.io/p/too-discrete-to-handle-how-low-cat?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[Reward Distributors 101]]></title><description><![CDATA[The cool trick powering liquidity farms, NFT staking, and, soon, DIG Network rewards]]></description><link>https://blog.fireacademy.io/p/reward-distributors-101</link><guid isPermaLink="false">https://blog.fireacademy.io/p/reward-distributors-101</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Wed, 23 Jul 2025 16:56:12 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/313367cb-f385-417a-93dc-eb22a6c888cf_1532x749.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;ve been in crypto for some time, you&#8217;re familiar with the concept of liquidity farms - contracts where users lock liquidity tokens to continuously receive rewards for every second the assets are stored, all while being able to withdraw the underlying assets at any time. In this post, I&#8217;d like to shine some light on how they work and how the main trick is used in a new app that will soon be live on Chia.</p><h2>How to Avoid a Lot of Transactions</h2><p>Believe it or not, there was a time when the concept of staking tokens did not exist at all. The naive approach to distributing tokens to stakers - calculating and sending rewards every second or block - required a lot of transactions to be made very frequently. Implementing a liquidity farm with this approach was simply too expensive for any protocol, even with relatively few users. Scaling would also be impossible, as the transactions from only one farm would probably exceed block size limits after reaching thousands of users. That number is orders of magnitude less than the number of liquidity providers a top AMM may reasonably expect.</p><p>The naive approach had no chance of working, which makes the existence of liquidity farms so much more impressive. At some point, someone ran with the idea and came up with an optimization that opened up the &#8216;staking era&#8217; of DeFi. The main insight needed for reward distribution is to realize that payout transactions are, for most blocks, the same - which allows a contract to group them together.</p><p>Let&#8217;s take an example. Alice and Bob are the only two users to stake their tokens in a farm (one LP token each). Thus, they each earn the same share of rewards. If the reward rate is 9 REW (reward tokens) per second, Alice and Bob will each get 4.5 REW per second. To avoid making a transaction every block, a contract can just keep track of each participant&#8217;s earning rate and calculate how much REW they&#8217;re owed when they request a payout or unstake their tokens. More specifically, if Alice requests her rewards 100 seconds after she staked her LP token, and she is supposed to receive 4.5 REW per second, the contract would just send her 100 * 4.5= 450 REW in a single transaction. Simple, yet powerful math!</p><p>What happens if Bob deposits another LP token? The farm would now have, in total, 3 LP tokens staked, one from Alice and two from Bob. Given the same total distribution rate of 9 REW per second, Alice should earn 3 REW per second, and Bob would get 6 REW per second. Additionally, when the change happens, the contract could pay Alice and Bob for the last period (where they each got 4.5 tokens per second).</p><p>There is still a major way to improve the contract further. Note that, in the method above, when the reward weights are changed, we need to recompute the reward rate for every user. If you&#8217;re aiming for many entries, that recalculation is the main scalability bottleneck. Triggering payouts for everyone every time someone stakes or unstakes some tokens is also pretty inefficient.</p><p>The solution is to keep track of a reward accumulator. This is the REW one token of LP would earn if it was staked at the very beginning of the reward distributor. Let&#8217;s take another example. Say Bob staked an LP token when the accumulator was 200 (thanks to things that happened beforehand and are irrelevant) and the distribution rate was 1 REW per second. Bob is a pretty indecisive guy, so he unstakes his LP just 50 seconds later. Given the rate, the accumulator&#8217;s value is now 200 + 50 * 1 = 250 REW. Bob receives the difference between the current value of the accumulator and the value when he first staked his token: 250 - 200 = 50 REW tokens paid. If he staked 2 LP tokens, the amount would double.</p><p>This might seem like a step backward at first - we&#8217;ve gone up in complexity only to get the same result. However, this method is far better because we now only care about the accumulator, not direct reward rates to individual users. There can be thousands or millions of rate adjustments between a stake and unstake operation - user-specific data (namely, the number of LP tokens Bob staked and the value of the REW accumulator when Bob staked them) is only accessed when rewards need to be paid out. This decoupling also means the liquidity farm has a compact state that is modified frequently - cumulative reward per share (the accumulator) and total deposited shares (LP tokens), along with epoch information (e.g., how many rewards to distribute and until when). Bob&#8217;s actions will not lead to Alice&#8217;s or any other user&#8217;s particular data being updated, but rather only change the small state in a way that&#8217;s easy to compute.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts right in your inbox.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>If you&#8217;d prefer a more academic format, you can check out the paper that nicely presents the idea <a href="https://uploads-ssl.webflow.com/5ad71ffeb79acc67c8bcdaba/5ad8d1193a40977462982470_scalable-reward-distribution-paper.pdf">here</a>.</p><h2>What DIG is Doing</h2><p>Last year, <a href="https://x.com/digdotnet">Michael Taylor</a> reached out to me looking to build an on-chain solution for DIG mirror rewards. The system at the time involved the validators (reward managers) sending payouts at fixed intervals of time. Its main issue was throughput - the fewer payments per week, the more trust mirrors put into validators, as users are not certain they&#8217;ll receive rewards until they see them in their wallet. However, more frequent payments would bring more network activity, which means more fees paid for distribution. If you&#8217;ve made it to this part of the post, you probably have a good idea of what a good solution to the problem looks like.</p><p>With the design presented above, the ideal (trust-minimizing) number of payments goes from &#8220;once every second&#8221; to &#8220;one when a user requests it or the mirror goes offline&#8221; - no matter what happens, mirrors get paid for the time when they have active shares in the rewards distributor.</p><p>Minimizing the number of on-chain payments is a goal in itself, but putting all active mirrors into a singleton lets us remove even more trust. For example, DIG rewards don&#8217;t necessarily need to come from the validator - anyone can add them to the current reward period or commit them to a future epoch. What&#8217;s more, if the validator misbehaves, sponsors (people who contributed rewards to future epochs) can claw back a percentage of the rewards, disincentivizing bad behavior. This opens the gates to a decentralized content network, where people interested in making some data accessible can contribute to the reward pot that gets distributed to mirrors that store and serve the data.</p><p>More recently, Michael asked me how hard it would be to turn the reward distributor into an NFT farm. Essentially, the code that allowed a trusted validator to add/remove entries was replaced by code that accepted any NFT minted by a particular DID for one share of the rewards. This makes NFT distributors an exciting way to reward NFT collection holders. The NFT reward distributor is now included in the official <a href="https://github.com/Chia-Network/chips/pull/165/files">CHIP</a>, which was just published for public review.</p><p>In a way, DIG - much like liquidity farms that came before - needed a very specific scaling solution. By optimizing based on transaction patterns, reward recipients can get the same assurance as they would get from payout transactions every second, all while not clogging the Chia blockchain. Reward distributors scale extremely well, making DIG prepared for its upcoming testing deployments, mainnet release, and eventual world domination. My hope is that, with this post, you&#8217;ve seen some of the magic that makes them possible.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/p/reward-distributors-101?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Enjoyed the post? Share it!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/p/reward-distributors-101?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.fireacademy.io/p/reward-distributors-101?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[Top 3 Vulnerabilities I Found in the CircuitDAO Codebase]]></title><description><![CDATA[Would you have spotted them?]]></description><link>https://blog.fireacademy.io/p/top-3-vulnerabilities-i-found-in</link><guid isPermaLink="false">https://blog.fireacademy.io/p/top-3-vulnerabilities-i-found-in</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Tue, 22 Jul 2025 17:46:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!2E4A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://circuitdao.com/">CircuitDAO</a>, a CDP protocol for Chia, recently held a <a href="https://cantina.xyz/competitions/7d650b99-8a40-49d1-9b65-2b060accfbb7">public bug bounty competition</a>. CDP protocols - like MakerDAO, for those familiar with the Ethereum DeFi landscape - allow users to borrow an asset (BYC) based on collateral deposited in another asset (XCH). Users pay interest on their loans, part of which is distributed to BYC holders who stake it in savings vaults. Whenever the collateral value goes below a certain threshold, the assets are liquidated in an auction, ensuring BYC stays overcollateralized and maintains its $1 peg.</p><p>The Cantina competition took place after the CircuitDAO codebase went through an audit from <a href="https://github.com/Zellic/publications/blob/master/Circuit%20DAO%20-%20Zellic%20Audit%20Report.pdf">Zellic</a> and an <a href="https://drive.google.com/file/d/1BqpVegztIFXDZL0VHmy1e5L5rEjuzn9B/view">Immunefy</a> private competition. For one month, anyone could analyze CircuitDAO&#8217;s Chialisp puzzles on Cantina and file vulnerability reports. The prize pot was distributed according to the severity of confirmed reports (valid vulnerabilities), as well as a report&#8217;s number of duplicates (the more people find the same bug, the less weight it has in distribution, incentivizing unique findings). For more information about competitions - which nicely complement security audits - check out <a href="https://docs.cantina.xyz/cantina-docs/cantina-competitions">this section of the Cantina docs</a>.</p><p>Even though I joined toward the competition&#8217;s end, I found 3 critical bugs and 2 medium vulnerabilities, ranking 1st across all participants. I curated the list below not only because the findings are interesting, but also because they show things Chialisp programmers should be careful about when designing and writing puzzles. I was the only one to report the vulnerabilities below. This article is not intended to raise any doubts about CircuitDAO (see the end of this post for more about this). I&#8217;m publishing these findings with the permission of the CircuitDAO team. Without further ado (or disclaimers), let&#8217;s dive right in!</p><h2>Finding One: Liquidating Everyone</h2><p>As previously mentioned, CircuitDAO has a simple yet efficient mechanism to keep all loans overcollaterized: when the value of the collateral goes below a percentage of the value borrowed (e.g., 200%), a<a href="https://docs.circuitdao.com/user-guide/liquidation"> liquidation process</a> is started. But, to value an XCH deposit in terms of BYC (1 BYC = 1 USD), the CircuitDAO protocol needs a trusted, on-chain XCH-USD price feed - where do they get that from?</p><p>The answer is the protocol <a href="https://docs.circuitdao.com/user-guide/price-oracle">oracle</a>, which consumes multiple price feeds, calculates the current XCH price, and then announces it on-chain. Feeds are approved by governance and represented on-chain by <a href="https://docs.circuitdao.com/technical-manual/announcers">announcers</a>.</p><p>Each announcer is a custom singleton that multiple stakeholders can call. Its owner can, for example, update the announcer&#8217;s custody puzzle hash or add a price. Meanwhile, keepers - entities keeping the CircuitDAO protocol working while pocketing some profit - can slash the capital locked in the announcer if the price is stale (was not updated for a while). They can also make the singleton announce the most recent price along with the announcer&#8217;s approval status, allowing the oracle to access it. Governance is the only entity that can set an announcer&#8217;s `APPROVED` parameter to 1 (true), allowing it to send data to the price oracle. Anyone can create and operate an unapproved announcer, but only approved announcers contribute to the price feed used by the CircuitDAO protocol.</p><p>My internal alarm bells went off when I noticed that anyone can exit an unapproved announcer (i.e., not only the announcer&#8217;s owner). The functionality was originally intended as a way for announcer owners to recover the funds they provide as a guarantee for their announcers (which can be slashed when the announcer is active). Due to a missing permission check, however, anyone can make an announcer exit into its owner puzzle (i.e., create a coin with a puzzle hash of `INNER_PUZZLE_HASH`) through <a href="https://cantina.xyz/code/7d650b99-8a40-49d1-9b65-2b060accfbb7/circuit_puzzles/programs/announcer_configure.clsp?lines=125,132">this path</a> as long as the announcer is not approved by governance (`APPROVED=0`). By itself, this finding has low severity at best, as the worst someone can do is exit announcers pending approvals in some cases. What makes this finding much more severe is that it breaks lineage. At a high level, an announcer custom singletons coin checks it is valid through the following checks:</p><ul><li><p>My top (outer) layer is an announcer custom singleton with my state</p></li><li><p>My parent is either the launcher or another announcer custom singleton</p></li></ul><p>By requiring the parent to also be an announcer, the protocol ensures there are no invalid state transitions. For example, no one can just create an approved announcer, as the launcher asserts `APPROVED=0` and further spends only set `APPROVED=1` if governance passes a bill that says so.</p><p>However, through the exit path, an announcer coin produces a child with an arbitrary puzzle that automatically satisfies the second condition! This is only possible because the inner puzzle only runs when the owner of the announcer runs a puzzle - if a keeper uses the previous bug to initiate the exit and create the new coin, the inner puzzle doesn&#8217;t get executed at all. If the proper permission check was in place, an additional constraint was placed on the inner puzzle (i.e., that it had to run inside an unapproved announcer), which would invalidate this attack path.</p><p>That leads us to our attack. An attacker creates an unapproved announcer - an action that anyone can do. In subsequent coin spends, they act as the owner to update the inner puzzle hash to one corresponding to the hash of an announcer outer layer with `APPROVED=1`, then act as a keeper to &#8216;exit&#8217; the current announcer top layer without revealing/executing the inner puzzle. Even though the parent performed an exit operation, the child&#8217;s puzzle hash will correspond to an announcer outer layer, which satisfies the first condition above. The second condition (parent is announcer) is also satisfied, meaning the attacker just turned an unapproved announcer into an approved one without involving governance at all. Ouch!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2E4A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2E4A!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 424w, https://substackcdn.com/image/fetch/$s_!2E4A!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 848w, https://substackcdn.com/image/fetch/$s_!2E4A!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 1272w, https://substackcdn.com/image/fetch/$s_!2E4A!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2E4A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png" width="1456" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:165848,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.fireacademy.io/i/166145155?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2E4A!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 424w, https://substackcdn.com/image/fetch/$s_!2E4A!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 848w, https://substackcdn.com/image/fetch/$s_!2E4A!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 1272w, https://substackcdn.com/image/fetch/$s_!2E4A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26a86fd8-2cd2-4995-9719-27deda6c33f7_2689x931.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Attack plan, as described above.</figcaption></figure></div><p>Given the last sentence, proving severity isn&#8217;t hard. If an attacker can create one approved announcer out of nothing, they can create a majority of announcers. Using those, the attacker would be able to fully control the XCH-USD price feed. By setting the price of XCH to, say, 0.001 USD, all loans would become undercollateralized, triggering mass liquidations.</p><p>In general, Chialisp developers should be careful when it comes to state transitions. While formal verification - a type of audit that translates code and assumptions to logical proofs and shows those are consistent and valid - is ideal, just thinking about how an attacker can lead a coin to a state it shouldn&#8217;t be able to achieve can sometimes uncover critical vulnerabilities.</p><h2>Finding Two: Bricking Auctions</h2><p>The CircuitDAO protocol has a<a href="https://docs.circuitdao.com/technical-manual/treasury"> treasury</a>, which is the place where loan interest payments (stability fees) go, and also the source of BYC paid as interest for locking up BYC in savings vaults. When the treasury has too much BYC, a <a href="https://docs.circuitdao.com/technical-manual/surplus-auction/">surplus auction</a> can be started, where people bid CRT (governance tokens, which will be burned) to buy the excess BYC. When the treasury balance dips below the minimum set by governance, <a href="https://docs.circuitdao.com/technical-manual/recharge-auction/">recharge auctions</a> start, where people bid to sell BYC and get freshly minted CRT in return.</p><p>Both auctions work over the span of multiple blocks. Bids are accepted from anyone as long as the amount is higher than the last bid, in which case the last bid is refunded. An auction ends when the current bid hasn&#8217;t been outbid for a certain amount of time (3 days, for example).</p><p>The bug that breaks the auction mechanism is a seemingly innocent lack of validation. When a user bids, they supply a puzzle hash (an address) where funds should be sent (either the bid refund or the auctioned asset). This parameter is kept in the auction&#8217;s state and used in a subsequent spend. It is not, however, sanitized at all. That seems fine at first - even though a puzzle hash is 32 bytes long, providing a value that&#8217;s another length (33 bytes long, for example) is not a problem, as the CAT layer will wrap whatever bytes are provided and generate an output hash. The new coin would be unspendable, but this would just be the equivalent of providing a wrong puzzle hash to the auction - which is user error, not a vulnerability.</p><p>The trick to break the auction is to provide a list as the puzzle hash. Whether you win the auction or get a refund (because you were outbid), a CREATE_COIN condition with a puzzle hash that&#8217;s a list instead of bytes will be emitted. When the CAT layer tries to wrap the list in a CAT outer puzzle, it will raise an error, making the whole bundle invalid. But that is not the bid bundle - instead, it&#8217;s the next user&#8217;s, who&#8217;s trying to outbid you or settle the auction. What&#8217;s worse, you can bid any amount - so, if you get lucky, you may be able to place a malicious .001 CRT bid on a 100.000 BYC auction and brick it forever. Surplus auctions store the BYC in a payout coin that would become unspendable after such an attack, meaning that the excess BYC would be lost forever.</p><p>Generally, always make sure to check all user input - the spend should fail if a wrong value (or a wrong type) is passed. This is especially important since Chialisp is not a typed language. As the vulnerability above shows, a failure in subsequent spends might be the reason there is an issue in the first place.</p><h2>Finding Three: Stealing Bids</h2><p>While writing a report for the last vulnerability, I also realized that the target puzzle hash is only used to set/update the last bid state. That means it didn&#8217;t appear in any other place in the code - so bidders had no way to assert the value is set correctly, as the solution of a bid coin is not signed, and no announcements contain the target puzzle hash. A malicious farmer could simply parse the original bundle and replace the included puzzle hash with theirs - that way, if someone outbid the current user, the funds would be sent to the farmer. And, if the user won the auction, the farmer would get the pot. Essentially, a user pays for the bid, but the farmer gets all the rewards.</p><p>This is bad on paper, but it&#8217;d take a lot of effort to set up a significant number of malicious farmers in practice due to Chia&#8217;s decentralization. There is, however, a trick to make this a critical vulnerability - enter <a href="https://docs.chia.net/chia-blockchain/architecture/mempool/#replace-by-fee">Replace-by-Fee</a>, a mechanism used by the bridge when another operation is already pending, TibetSwap when someone else is interacting with the same pair, the Dexie &#8216;bump fee&#8217; feature, and probably most apps in the future. Pending spend bundles cannot just be replaced since that would open the mempool to several attacks. However, you can replace mempool items with new ones if the new bundle meets a few constraints:</p><ul><li><p>All coins in the original bundle are still spent (superset rule)</p></li><li><p>The fee-per-cost of the bundle increases (more specific rules are irrelevant)</p></li></ul><p>This opens up another possibility for the attack, where a malicious actor can steal all bids by simply watching the mempool. Whenever a spend bundle is detected, the attacker can take the original bundle, change the target puzzle hash, attach a higher fee, and send the new mempool item to the network. The old mempool item will be replaced by the &#8216;malicious&#8217; one through Replace-by-Fee, as both the superset and fee increase constraints have been satisfied. The user paid to make a bid, but the attacker gets all the proceeds (refund or won lot).</p><p>In general, dApps should always provide a way for users to assert that they&#8217;re doing what they want to do. This can be more lax than just announcing all input parameters - offers, for example, allow you to assert that assets are sent to a puzzle hash without enforcing which coins need to be used, and their flexibility is what gives them power. The proposed security measure often comes in the form of extra output conditions, which will consume additional cost (&#8216;make transactions bigger&#8217;) - but the alternative, as you can see above, is not a secure option. While Cantina&#8217;s rules would consider this bug family to be one vulnerability only, the attack above led to CitcuitDAO revising multiple areas of the code.</p><h2>Should Security Be a Concern?</h2><p>Security should always be a concern. On blockchains, the problem of security is even worse, as money locked in a protocol usually incentivizes hackers to exploit rather than report security issues. As a user, the real question is whether the probability of a hack is low enough to justify putting money in the protocol. In other words, <strong>yield is never risk-free, but users can weigh it against the protocol&#8217;s perceived risk</strong>.</p><p>Having said this, we should applaud the CircuitDAO team. Organizing and going through multiple audits/competitions is a time and capital-intensive process, even if you&#8217;re not using a lesser-known language such as Chialisp. Still, they&#8217;ve been audited by Zellic (one of my favorite top audit firms), held a private Immunefy competition, and just wrapped up a huge open competition on Cantina (where I participated for a week and reported the bugs above - and a few others). They&#8217;ll also soon launch a public bug bounty program a Cantina - if you know how to read Chialisp and would like a challenge, I highly encourage you to check it out!</p><p>Each bug reported before mainnet means a fix can be applied before the protocol goes into production. Users and community members should create strong incentives for protocols to go through thorough testing before launching instead of just &#8220;winging it&#8221; and needlessly putting funds at risk. While the instinctual reaction to hearing that critical bugs were uncovered is to be concerned, remember some protocols just choose to not perform any kind of security assessment. CircuitDAO, a very complex protocol with many moving parts, is undoubtedly on the right path to mainnet - the one with many security reviews.</p><p>So, as an end user, how do you know if the yield justifies the risk? I personally (not legal or any other kind of advice!)  look for two things in highly secure protocols:</p><ul><li><p>Multiple audits from reputable firms, with published reports</p></li><li><p>Few severe bugs in recent audit(s)/competition(s)</p></li></ul><p>Security assessments can never guarantee there is no bug left - but I think the indicators above make it unlikely that the protocol has unresolved severe vulnerabilities.</p><p>Given the nature of this article, it&#8217;s fitting to end it the way I wrapped up posts on my old <a href="https://blog.kuhi.to/">cybersecurity blog</a>:</p><p>Until next time, hack the world.</p><p>yakuhito, over.</p>]]></content:encoded></item><item><title><![CDATA[Announcing CATalog and XCHandles]]></title><description><![CDATA[Decentralized registries on Chia have been needed for a while]]></description><link>https://blog.fireacademy.io/p/announcing-catalog-and-xchandles</link><guid isPermaLink="false">https://blog.fireacademy.io/p/announcing-catalog-and-xchandles</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Mon, 23 Dec 2024 14:48:09 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d760ad3b-d9c4-4de7-9a2a-7a09ce95d01d_2095x1568.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Note: This is the third post of a 3-part series. <a href="https://blog.fireacademy.io/p/uniqueness-on-chain">Part 1</a>. <a href="https://blog.fireacademy.io/p/solving-the-problem-of-uniqueness">Part 2</a>.</em></p><p>In the previous blog posts, I explained the problem of uniqueness, as well as a great nice solution for it. This post&#8217;s main theme is: now that such a primitive exists, what dApps does the ecosystem need the most? Without further ado, let&#8217;s jump right in.</p><h2>The needs</h2><p>The first obvious need is names. I want to tell people to send me money at &#8216;yakuhito&#8217; instead of an XCH address. I have tremendous respect for the services that have attempted to do that, some of which have also used the proceeds to support the ecosystem. That said, a decentralized option is better - it gives users confidence that the names will be available in 10 years and the service will continue to follow the same rules. After a lot of thinking, I have decided to name this service XCHandles.</p><p><em>Side-note</em>: While it&#8217;s harder to build and launch, the maintenance of XCHandles is actually easier - there&#8217;s no registration key you have to be careful not to leak. Even if the main API/website goes down, wallets can have code that still allows them to resolve names and register them on-chain. XCHandles only goes down when Chia goes down. Worst-case scenario is that you lose control of the address where registration fees go - in which case, the name service continues to live on without any issue. </p><p>The second one - also suggested by Ken - is a CAT registry. If you&#8217;re a Chia user, you probably aren&#8217;t aware of any problems with CATs. But issuers and owners of sites displaying CATs have been battling with it for a long time. In essence, there is no &#8216;one place&#8217;/source of truth where you can go and put the details of your CATs so other sites - like Dexie or TibetSwap - pull them. A decentralized CAT registry - which I will refer to as CATalog from now on - is the best solution, as CAT issuers can own their entries and update them whenever they see fit.</p><p>There&#8217;s, of course, more to both XCHandles and CATalog than this. Let&#8217;s dive in!</p><h2>Designing XCHandles</h2><p>I like to think about XCHandles as a decentralized address book - but, in reality, it was designed taking a lot of inspiration from DNS. The Domain Name System (DNS, for short) is the collection of systems responsible for offering and managing domains - such as fireacademy[.]io. The reason XCHandles should be similar to them is that they&#8217;re fundamentally offering the same things: names that resolve to dynamic things (be it IP addresses or wallet addresses) and can be registered by anyone (add &#8216;mostly&#8217; to the last part when talking about DNS).</p><p>The first major design decision was to let XCHandles expire. To understand why, let me take the example of my twitter handle - which is &#8216;yakuh1t0,&#8217; not &#8216;yakuhito.&#8217; In 2013 - years before I joined Twitter - someone registered as 'yakuhito&#8217; and then left the site - no follows, posts or any activity since then. I would argue that the &#8216;yakuhito&#8217; handle should come with a mechanism that ensures it&#8217;s being used - and the best way to get to that is to make people pay for the time they own handles. At a higher level, if you leave Chia for good or lose access to your handle, there should be a mechanism that eventually allows someone that really wants the handle to get it without having to get in touch with you. This is also, to a certain extent, a great way to prevent &#8216;squatters&#8217; - people who would register a lot of handles only to offer them at much better prices when someone wants one - since they would have to pay to maintain their collection of handles. DNS has been doing this successfully since around 1983.</p><p>The other design decision was to make some handles more expensive. There&#8217;s a lot of factors that make some domains more valuable than others - the one I put into XCHandles is based on name length. A 3-letter handle (e.g., &#8216;yak&#8217;) will be more expensive than an 8-letter one (e.g., &#8216;yakuhito&#8217;) since less 3-letter handles are available overall. Since XCHandles are tradeable, a secondary market for handles with other properties (e.g., keywords) will probably establish itself.</p><p>That&#8217;s pretty much it - in all other major ways, XCHandles will work like most name services on other blockchains. Names are represented as NFTs that the users control - and are free to update and trade as they see fit.</p><h2>Designing CATalog</h2><p>CATalog is very interesting in a lot of ways. But, first, let&#8217;s talk about how you can build a decentralized CAT registry.</p><p>In essence, the goal is to have CAT issuers (&#8216;owners&#8217;) control entries in a decentralized registry. This brings up the question: how do you check if someone is the issuer of a new CAT in a decentralized way? We have to keep in mind that CATs can have all kinds of issuance rules - from single issuance, where the owner is obvious, to liquidity CATs on TibetSwap, where the &#8216;owner&#8217; is not necessarily the user that the funds came from. </p><p>The solution is to consider knowledge/information asymmetry. An issuer is a person who came up with the CAT - they&#8217;re the first ones to know about the CAT.  CATalog can award the CAT entry to the first person that committed the CAT&#8217;s asset id on-chain (in most cases, before the CAT was actually issued).</p><p>This means that CATalog ensures the uniqueness of TAIL hashes to prevent double-registration - not CAT tickers. The problem with CAT details other than the asset id is that a Chialisp program can&#8217;t verify that their values - such as tickers, names, and images - are not misleading. Moreover, sites using CATs would want some vetting power over the CATs they display anyway.  Site owners should be able to decide whether the CAT is appropriate for the site or not.</p><p>To fix this issue, we must see the registry as &#8216;PVP-enabled&#8217; - scam attempts are a given. The singleton&#8217;s sole purpose is to give CAT creators the power to update the entries for their CATs on-chain - it&#8217;s a decentralized CAT database with no regards for the content of the entries. Content &#8216;filtering&#8217; comes from a layer on top: site owners create on-chain verifications from their DIDs to actively flag CATs as not being misleading. These verifications can include other data (such as the CAT&#8217;s specific category on the site). Verifications can also be revoked at any point.</p><p>With this new &#8216;layer,&#8217; CATalog becomes a collection of on-chain resources describing CATs. Issuers register entries and update values. Site owners - and any other DIDs - then create verifications for the values, saying that the content is ok from their perspective. Some dApps might choose to trust someone else - such as Dexie or SpaceScan - to curate CATs for them. This is, in my opinion, the best solution for a token registry that I&#8217;ve seen or thought about.</p><p>Lastly, CAT registrations last forever. A CAT owner can disappear while the CAT itself is still valid - if that is no longer the case, verifications can be revoked so CATs are no longer listed on websites that wish to hide them.</p><h2>Wrapping up</h2><p>If you&#8217;ve ever thought that launching a dApp is hard, try launching two! Jokes aside, while XCHandles and CATalog would be easy to launch on an EVM blockchain, a lot of work is needed to get them up and running on Chia.</p><p>Along with this post, I&#8217;ve also made <a href="https://github.com/Yakuhito/slot-machine/">this repository</a> public. It contains Chialisp code that powers these new dApps, along with draft driver code and working tests. This series didn&#8217;t talk about a lot of other stuff - from a new, specialized layer for dApps to the drivers being implemented in Rust instead of Python. A bit more testing under real-world conditions is needed before I&#8217;m comfortable with releasing CHIPs and a plan for mainnet. Stay tuned for more news - coming next year!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><em>Special thanks to stl and (or, maybe, a.k.a. &#128521; ) Bob for reviewing this article.</em></p>]]></content:encoded></item><item><title><![CDATA[Solving the Problem of Uniqueness]]></title><description><![CDATA[There is a solution - but we need to look at one that doesn't work first]]></description><link>https://blog.fireacademy.io/p/solving-the-problem-of-uniqueness</link><guid isPermaLink="false">https://blog.fireacademy.io/p/solving-the-problem-of-uniqueness</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Sun, 22 Dec 2024 13:14:30 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/61f162b1-df7d-4ccb-a600-43d404cb765f_1024x768.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Note: This is the second post of a 3-part series. <a href="https://blog.fireacademy.io/p/uniqueness-on-chain">Part 1</a>. <a href="https://blog.fireacademy.io/p/announcing-catalog-and-xchandles">Part 3</a>.</em></p><p>In the previous blog post, I presented the problem of uniqueness. As a short recap: there&#8217;s no way for singletons to check that a value (e.g., a name) hasn&#8217;t been used (e.g., registered) before. In this post, I&#8217;ll explain a previously proposed solution - and why it doesn&#8217;t work - as well as a solution that does work.</p><p>But first, back to the basics: let&#8217;s talk about hashing.</p><h2>Hashing 101</h2><p>There are many ways to describe hashing - but let me invent a new one based on AI&#8217;s rising popularity. Let&#8217;s imagine we have a robot that labels things - you give it an object, and it puts a label on it. Let&#8217;s also imagine that it&#8217;s 2100 - so the robot is powered by a combination of GPT-313, Gemini-7, and Grok-42. At this point, no one has any idea what the labels mean - but they&#8217;ve observed the robot puts the same labels for identical objects (i.e., two apples will have the same label). The robot also never uses the same labels for different objects (apples and pears will have different labels).</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gYN7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gYN7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 424w, https://substackcdn.com/image/fetch/$s_!gYN7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 848w, https://substackcdn.com/image/fetch/$s_!gYN7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 1272w, https://substackcdn.com/image/fetch/$s_!gYN7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gYN7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png" width="1456" height="595" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:595,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:283120,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gYN7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 424w, https://substackcdn.com/image/fetch/$s_!gYN7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 848w, https://substackcdn.com/image/fetch/$s_!gYN7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 1272w, https://substackcdn.com/image/fetch/$s_!gYN7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd7abdbcd-742a-451a-b3d8-3a5ca0ec8fc6_2187x894.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Labeler 3000 is the state-of-the-art labeling robot. Warehouse employees reported that apple labels always start with &#8216;101011&#8217; and that pear labels start with &#8216;100001.&#8217; </figcaption></figure></div><p>Hashing is just the digital equivalent of the Labeler 3000 robot:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Z2nf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Z2nf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 424w, https://substackcdn.com/image/fetch/$s_!Z2nf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 848w, https://substackcdn.com/image/fetch/$s_!Z2nf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 1272w, https://substackcdn.com/image/fetch/$s_!Z2nf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Z2nf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png" width="1456" height="569" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:569,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:567639,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Z2nf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 424w, https://substackcdn.com/image/fetch/$s_!Z2nf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 848w, https://substackcdn.com/image/fetch/$s_!Z2nf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 1272w, https://substackcdn.com/image/fetch/$s_!Z2nf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9ccb701-7272-486e-a241-0e0ab9ed986c_2138x835.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Putting the strings &#8220;apple&#8221; and &#8220;pear&#8221; through hashing algorithms (SHA256 in this case) leads to different outputs.</figcaption></figure></div><p>Hashing algorithms (yes, there&#8217;s more than one - although SHA256 is arguably the most popular) take a piece of data (of any size!) and output a fixed-size &#8216;fingerprint&#8217; of that data. They have two properties that make them special:</p><ul><li><p><strong>Deterministic</strong>: Given a piece of data, its hash is the same no matter the time or computer I run the hashing algorithm on. In other words, getting the same input through the same algorithm should produce the same output. Intuitively, it makes sense for a fingerprint to remain the same for a given object.</p></li><li><p><strong>Not Reversible</strong>: Given an output - a hash value - it&#8217;s really hard to determine an input string that produces that output. More specifically, if I give you the hash &#8216;e378e72a75855c08d49b6421b04374a1c16d36f4f1cec3d06a3da38053a8fdcd,&#8217; your best bet to determine what value produces it is to go through many values, hash them, and see if the outputs match (that string is the SHA256 of &#8216;yak&#8217; - not that it matters).</p></li></ul><p>The latter property leads to the comparison between hashing and a blender being frequently used. Blended apples would look the same (and differently from a blended oranges) - but good luck reversing the blender&#8217;s effect on the apple. Algorithms such as SHA256 have been carefully built to act like a digital blender. They take data in batches, and mix it into the output value in a very complicated way.</p><p>Now that we got that out of the way, let&#8217;s talk about one very cool use of hashing!</p><h2>Merkle Trees</h2><p>For every spend, the TibetSwap singleton has to run one of the following puzzles: add liquidity, remove liquidity, swap XCH to CATs, swap CATs to XCH. The goal is to make this mechanism take as little space as possible on-chain in order to minimize transaction cost.</p><p>The first place where hashing can be used is to &#8216;compress&#8217; puzzles. Instead of storing the whole puzzle, we can store a hash (a &#8216;unique fingerprint&#8217;) of each puzzle in a list. When the singleton is spent, a full puzzle is given - we can hash that and see if the fingerprint is in the list of hashes that are allowed to run. It&#8217;s like implementing perfect biometric security for access into a building - if you have the wrong fingerprint, you&#8217;re not getting in.</p><p>However, we can do even better. Merkle Trees let us &#8216;compress&#8217; the whole list via hashing. Here&#8217;s how this would be done for a list with 8 items:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Fj26!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Fj26!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 424w, https://substackcdn.com/image/fetch/$s_!Fj26!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 848w, https://substackcdn.com/image/fetch/$s_!Fj26!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 1272w, https://substackcdn.com/image/fetch/$s_!Fj26!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Fj26!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png" width="1456" height="952" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:952,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:92561,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Fj26!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 424w, https://substackcdn.com/image/fetch/$s_!Fj26!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 848w, https://substackcdn.com/image/fetch/$s_!Fj26!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 1272w, https://substackcdn.com/image/fetch/$s_!Fj26!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef59175b-2627-48b2-9464-072720e49a5e_1595x1043.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Example binary Merkle Tree (every 2 elements are hashed at each level)</figcaption></figure></div><p>The method to build a Merkle Tree is simple: you take every 2 items from the list and hash them together. That gets you from the bottom level (1, 2, &#8230;) to the second level (12, 34, 56, and 78). You can repeat this procedure until you only have one hash left - 12345678 in the image above. This &#8216;top&#8217; hash is usually called the Merkle root. You have now stored the data in a very clever way: when you want to prove that an item is part of the original list, you only have to provide a few intermediary hashes, like below:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CXxY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CXxY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 424w, https://substackcdn.com/image/fetch/$s_!CXxY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 848w, https://substackcdn.com/image/fetch/$s_!CXxY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 1272w, https://substackcdn.com/image/fetch/$s_!CXxY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CXxY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png" width="1456" height="961" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b458a117-c2ec-4198-9696-858782c29d66_1573x1038.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:961,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:86966,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CXxY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 424w, https://substackcdn.com/image/fetch/$s_!CXxY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 848w, https://substackcdn.com/image/fetch/$s_!CXxY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 1272w, https://substackcdn.com/image/fetch/$s_!CXxY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb458a117-c2ec-4198-9696-858782c29d66_1573x1038.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Merkle proof visualization.</figcaption></figure></div><p> Let&#8217;s say you want to prove 3 is in the original list. By providing 4, 12, and 5678, someone can get at the Merkle root (top hash) from &#8216;3&#8217; - all without knowing or using the whole list! The really elegant thing here is that nodes 1,2,5,6,7,8 are not included in the proof - instead, intermediary values such as 12 and 5678 &#8216;cover&#8217; more than one node.</p><p>Let&#8217;s compare this to the &#8216;naive&#8217; solution of hashing the list and accepting a reveal. In that case, you would have to provide all 8 hash values (1-8) to check if a puzzle is allowed to run. With Merkle Trees, you provide the puzzle hash (3) and 2 intermediary values (12, 5678) to compare against the Merkle Root. More generally, with Merkle Trees, you&#8217;re looking at log2(n) items instead of n for proofs of inclusion - which makes them a really great tool!</p><h2>Previously Proposed Solution</h2><p>We&#8217;re now in a good place to understand the best solution proposed for the problem of uniqueness so far. Back in 2023, Ken (also known as fizpawiz - a great Chialisp developer) published <a href="https://medium.com/@fizpawiz/decentralized-names-on-the-chia-public-blockchain-823adb6cc2af">&#8220;Decentralized Names on the Chia Public Blockchain&#8221;</a>. He suggested that we can use a Merkle Tree of sorted values to prove a name hasn&#8217;t been registered before - like the one below:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xv9P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xv9P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 424w, https://substackcdn.com/image/fetch/$s_!xv9P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 848w, https://substackcdn.com/image/fetch/$s_!xv9P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 1272w, https://substackcdn.com/image/fetch/$s_!xv9P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xv9P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png" width="1456" height="1095" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1095,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:85117,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!xv9P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 424w, https://substackcdn.com/image/fetch/$s_!xv9P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 848w, https://substackcdn.com/image/fetch/$s_!xv9P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 1272w, https://substackcdn.com/image/fetch/$s_!xv9P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb56957b0-9806-4adc-a647-78cefdc7eaa8_1588x1194.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">A sorted Merkle Tree is just a Merkle Tree based on a sorted list</figcaption></figure></div><p>The idea is very elegant: to prove that 7 hasn&#8217;t been registered, prove that 5 and 10 have been registered, and that they&#8217;re next to each other in the current Merkle Tree. Because the list is sorted, you know for certain that 7 hasn&#8217;t been registered.</p><p>This idea has apparently <a href="https://cardano.ideascale.com/c/cardano/idea/105122">also been proposed as a solution for the name service of Cardano</a>. Unfortunately, it won&#8217;t work - while they&#8217;re good for proofs-of-inclusion, Merkle Trees are not practical for proofs-of-exclusion.</p><p>Let&#8217;s first assume we want to keep the new item - 7 - on the same &#8216;level&#8217; of the tree. After the name is registered, the dApp will have to calculate the Merkle root of the new tree (i.e., one where 7 is part of the list) so future registrations can be processed as well. What intermediary hashes will have to be recomputed after 7 is inserted?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uMIm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uMIm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 424w, https://substackcdn.com/image/fetch/$s_!uMIm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 848w, https://substackcdn.com/image/fetch/$s_!uMIm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 1272w, https://substackcdn.com/image/fetch/$s_!uMIm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uMIm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png" width="1456" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:79580,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uMIm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 424w, https://substackcdn.com/image/fetch/$s_!uMIm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 848w, https://substackcdn.com/image/fetch/$s_!uMIm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 1272w, https://substackcdn.com/image/fetch/$s_!uMIm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F201f8b64-00a4-4097-a8d1-5346ebb2df98_1808x1118.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Red: intermediary nodes that have to be re-computed after 7 is inserted</figcaption></figure></div><p>The answer is: most of them. When you&#8217;re inserting 7, you&#8217;re shifting the nodes on its right by one. Because you always hash nodes in pairs, all pairs on the right will change, and a lot of rehashing will need to be done. In practice, you end up having to reveal a majority of the initial list in many cases. That&#8217;s not practical because of size constraints - the more data your transaction contains, the more expensive it is. Additionally, blocks have a limited maximum size - at some point, you won&#8217;t be able to register some values because the data that needs to be revealed to register them doesn&#8217;t fit in a block.</p><p>There is, of course, another alternative to insert 7 - the one which Ken thought of when proposing the solution. What if, instead of keeping everything on the same level, we create a new one? When we insert 7, we can just turn the &#8216;5&#8217; node into &#8216;5,7&#8217;. This sounds much better, as you only have to recompute log2(n) nodes, and you no longer have to reveal most of the tree.</p><p>Indeed, the problem in that scenario is smaller - but it&#8217;s still there. If your tree grows differently in different locations, it will become unbalanced. Assume someone also registers 5.1, 5.2, 5.3, 5.4, and so on. When I want to register 6, I&#8217;ll have to reveal all those values, plus 5 and 7. The 6 item would be added to a very &#8216;long&#8217; root in an otherwise pretty shallow tree. This ruins the nice property of Merkle Trees that we&#8217;ve talked about - proofs are no longer log2(n). Moreover, this is a shared application - so someone could in theory &#8216;attack&#8217; the dApp by registering 5.1, 5.2, etc. in order to annoy the person who&#8217;ll want to register 6.</p><p>There are, of course, other types of trees as well. Specifically, B-trees, which were created for databases, are very good at &#8216;auto-balancing&#8217; the tree so insertions/deletions are still done in logarithmic time. But they also reveal another weakness: as we add more fixes on top of the tree idea, the code is getting more and more complex. That increases transaction cost, development time, and attack surface - isn&#8217;t there a much simpler alternative?</p><h2>Trees are not the solution</h2><p>I have myself been stuck down the rabbit hole of trees for a very long time - that&#8217;s why I know what a B-tree is in the first place.  However, it&#8217;s important to keep in mind there are other data structures that could be used in our battle against the problem of uniqueness. So let&#8217;s go back to the basics. </p><p>We want something that ensures an item is unique - and we&#8217;ve seen that sorted lists are great because they allow us to prove uniqueness by looking at two neighboring items only (recall that, if we see 5 next to 10 in an ordered list, we can say for certain 7 hasn&#8217;t been registered before). However, we also want to insert new items into the list as easily as possible (ideally, O(1)). Allow me to introduce the data structure that can solve the problem of uniqueness: sorted, doubly-linked lists:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mnB4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mnB4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 424w, https://substackcdn.com/image/fetch/$s_!mnB4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 848w, https://substackcdn.com/image/fetch/$s_!mnB4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 1272w, https://substackcdn.com/image/fetch/$s_!mnB4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mnB4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png" width="1456" height="605" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:605,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:64633,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mnB4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 424w, https://substackcdn.com/image/fetch/$s_!mnB4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 848w, https://substackcdn.com/image/fetch/$s_!mnB4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 1272w, https://substackcdn.com/image/fetch/$s_!mnB4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F78b0a9ac-cb31-4828-8828-c8c74c53ad29_2449x1017.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Inserting a 7 in a sorted, doubly-linked list</figcaption></figure></div><p>Doubly-linked lists are a known programming data structure with a simple idea: each node (item) also knows - aside from its own value - its neighbors. So, for example, node 5 will also contain the information that its left neighbor is 1 and its neighbor on the right is 10. What&#8217;s really cool is that, when you want to insert 7, you only have two update two nodes, which will be his future neighbors: 5 and 10. Specifically, you&#8217;ll &#8216;break&#8217; the link between 5 and 10 by setting 5&#8217;s right neighbor to 7 and 10&#8217;s left neighbor to 7. Moreover, if you check 5 &lt; 7 &lt; 10, you can verify 7 hasn&#8217;t been registered before at the same time!</p><p>This is nice and would be a great way to solve the problem of uniqueness - if we properly store the list on-chain. Recall that each node contains 3 values (its own value + its two neighbors), and that we don&#8217;t want to have to reveal the whole list every spend. Let me give you a graphical hint on how we can do it:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wa19!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wa19!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 424w, https://substackcdn.com/image/fetch/$s_!Wa19!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 848w, https://substackcdn.com/image/fetch/$s_!Wa19!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 1272w, https://substackcdn.com/image/fetch/$s_!Wa19!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wa19!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png" width="1456" height="174" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:174,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:53681,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Wa19!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 424w, https://substackcdn.com/image/fetch/$s_!Wa19!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 848w, https://substackcdn.com/image/fetch/$s_!Wa19!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 1272w, https://substackcdn.com/image/fetch/$s_!Wa19!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbddf2241-e86b-46a0-a4a7-2e527655b169_2428x290.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a><figcaption class="image-caption">A list of coins</figcaption></figure></div><p>The essential idea that makes it all work is to have each element be a coin. The registry singleton only interacts with node coins when they&#8217;re used - i.e., when they&#8217;re the future neighbor of a value being inserted. The user/wallet provides the relevant coins when registering - remember, just looking at two nodes is enough to make sure the value hasn&#8217;t been registered before. And that&#8217;s how you (simply) solve the problem of uniqueness.</p><p>One last thing to note is just how much sense this solution makes. After you register a value - say 20 - you only need to access it when one of its neighbors will change (i.e., to prove a value next to it hasn&#8217;t been registered before - and insert it). When it&#8217;s not needed, however, the coin containing 20 will remain unspent - which doesn&#8217;t increase the cost of a transaction on the underlying registry singleton at all. In other words, proving a value is not part of a list of 100 items is the same as proving uniqueness in a list of 1,000,000 items - which solves a huge concern of dApp developers (&#8220;will it scale?&#8221; - yes, this part of the dApp will).</p><h2>Up next</h2><p>When I presented this solution to other people (I had to make sure I wasn&#8217;t crazy), their initial reaction was &#8220;Wow! That&#8217;s clever!,&#8221; followed by &#8220;It&#8217;s so much simpler than I expected.&#8221; In my book, the simpler you can make a dApp, the better.</p><p>I started calling the coins that store the list items &#8220;slots&#8221;. I think slots will have much broader functionality beyond what I initially used them for, as singletons can essentially &#8216;save data for later.&#8217; For example, slots would give a liquidity farm the ability to not only store the amount of liquidity tokens you added to the farm, but also the cumulative rewards at the time of deposit - making liquidity farms finally possible on Chia. Slots can do that without using a doubly-linked list structure - in a way, they become &#8216;tickets&#8217; that liquidity depositors can later redeem for their tokens and accrued rewards.</p><p>Taking a step back, I do think this concept has lifted the final barrier to more advanced Chia dApps. I&#8217;m really excited for what&#8217;s next - so join me in <a href="https://blog.fireacademy.io/p/announcing-catalog-and-xchandles">Part 3</a> to see the PoCs I built to test out this new primitive&#8217;s capabilities.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><em>Special thanks to stl and (or, maybe, a.k.a. &#128521; ) Bob for reviewing this article.</em></p>]]></content:encoded></item><item><title><![CDATA[The Problem of Uniqueness]]></title><description><![CDATA[Why Chia dApps couldn't be as complex as Ethereum ones.]]></description><link>https://blog.fireacademy.io/p/uniqueness-on-chain</link><guid isPermaLink="false">https://blog.fireacademy.io/p/uniqueness-on-chain</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Sat, 21 Dec 2024 14:03:01 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b5be3147-93eb-418e-a7b4-917c54d2b34c_1024x768.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Note: This is the first post of a 3-part series. <a href="https://blog.fireacademy.io/p/solving-the-problem-of-uniqueness">Part 2</a>. <a href="https://blog.fireacademy.io/p/announcing-catalog-and-xchandles">Part 3</a>.</em></p><p>Chia is very different from account-based blockchains like Ethereum. The &#8216;fundamental&#8217; unit on Chia is a coin - which has a parent (i.e., source that created it), an amount of mojos, and a puzzle - which contains the &#8216;rules&#8217; that control the value locked in the coin. This change from &#8220;there are smart accounts and a JavaScript-like language is used to control them&#8221; means that a lot of basic stuff is wildly different from Ethereum or other cryptocurrencies.</p><p>There have been two major breakthroughs that allow dApps today to exist on Chia. First, singletons allowed a lineage of coins to maintain an &#8216;identity&#8217; through spends. A coin can only be spent once - but the singleton primitive allows one of the coin&#8217;s children to be marked as a &#8216;successor.&#8217; This makes it possible for NFTs to exist - the unspent (latest) coin holding the NFT itself changes each time you do a transfer, trade, or metadata update. But the underlying NFT id and state (metadata) are preserved through spends.</p><p>Second, the launch of TibetSwap provided a &#8216;sketch&#8217; for simple dApps. Besides showing the community that dApps were possible on Chia (many community members thought they weren&#8217;t), TibetSwap had a &#8216;structure&#8217; that showed one way of:</p><ul><li><p>Holding state variables that change frequently inside a singleton (e.g., the amount of XCH locked in a pair, which changes with each trade)</p></li><li><p>Emulating Solidity&#8217;s function selectors, which allow different ways to interact with accounts based on what you want to do. For example, when you add liquidity to a TibetSwap pair, some of the code that runs is different than the code that runs when you do a XCH &#8594; CAT swap.</p></li></ul><p>Even with the two advancements, a small issue still prevented complex dApps from being built on-chain. I call it the problem of uniqueness, and this post is intended to explain it.</p><h2>Why don&#8217;t we have a fully decentralized name service on Chia?</h2><p>The easiest way to demonstrate the issue is to show a place where it heavily influenced how solutions were designed: name services.</p><p>As most crypto users know, a name service is mainly responsible for translating a human-readable string - such as &#8216;yakuhito&#8217; - to a blockchain address. It&#8217;s a decentralized address book. Currently, there are multiple such services on Chia - from the <a href="https://xch.cool/">Chia Name Service</a> and <a href="https://namesdao.org/">NamesDAO</a>, which offer on-chain name NFTs, to sites such as <a href="https://x.com/go4mebot">go4me</a> and <a href="https://myxch.space/">MyXCH.space</a>. However, unlike their Ethereum counterparts, they are not fully decentralized - someone&#8217;s key is used to create your &#8216;domain&#8217;, and that someone can also register the same name twice or refuse your registration request. The question is: why is there a &#8216;private key&#8217; in the image below?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MOt0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MOt0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 424w, https://substackcdn.com/image/fetch/$s_!MOt0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 848w, https://substackcdn.com/image/fetch/$s_!MOt0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 1272w, https://substackcdn.com/image/fetch/$s_!MOt0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MOt0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png" width="1233" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1233,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:350240,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MOt0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 424w, https://substackcdn.com/image/fetch/$s_!MOt0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 848w, https://substackcdn.com/image/fetch/$s_!MOt0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 1272w, https://substackcdn.com/image/fetch/$s_!MOt0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1dce6b6d-87d4-4e19-b660-14a34947964d_1233x900.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Chia Name Service - Technical Architecture. <a href="https://sutulabs.github.io/CNSWhitepaper/Architecture.html">Source</a>.</figcaption></figure></div><p>No one wants the responsibility of being an admin - it adds complexity and a lot of responsibility to a system that should be unstoppable, uncensorable, and available 24/7. Teams like CNS have very deep knowledge of the Chia blockchain - so why settle for something less than ideal?</p><p>The core issue is that, while singletons allow you to hold some values that change over time, they come with limitations. Too many values will make your transactions more expensive - less can fit in a block, and users will have to pay more fees. Moreover, there&#8217;s no &#8216;direct&#8217; way of proving something is unique (a list of registered names would get too big after just &#8216;a few&#8217; registrations). Combined, these issues mean that a registry singleton has no way of checking whether &#8216;yakuhito&#8217; is an active name when someone makes a request to register it.</p><p>A lot of people have been thinking - directly or indirectly - about a solution for more than two years now. I call this the problem of uniqueness - and it shows up almost every time you want to design a complex dApp.</p><p><em>Side-note:</em> <em>Those that know a bit of Solidity will notice that the problem is trivial to solve on Ethereum - just use a &#8216;mapping&#8217; structure! That&#8217;s not available on Chia.</em></p><h2>Where does the problem show up?</h2><p>Aside from name services, there are several apps where the problem shows up. Each time, the solution is highly specific and present several drawbacks.</p><h4><strong>NFT</strong></h4><p>NFTs - actually, singletons - were the first puzzles to face this issue. The way you ensure only one unspent coin exists at a time is by having an id - when a coin is spent, it passes that id to one of its children (or, in special cases, it doesn&#8217;t - a process that destroys the singleton which we call &#8216;melting&#8217;).  The clever solution the creators of the puzzle came up with is to use the first singleton parent&#8217;s id as the singleton id. In other words, singletons distinguish themselves by the coin id of the  &#8216;creator&#8217; coin - which is usually called the singleton launcher. This is a great idea because it uses a consensus rule - the one saying that all coins must have a unique id - to give singletons their ids. The major drawback of this design is that it relies on coin ids - which depend on parent ids, making it impossible to use the same system to store custom values. Think of it this way: you can prove uniqueness, but the entries of the list are all random 32-byte values - not &#8216;yakuhito&#8217; or other names.</p><h4>TibetSwap</h4><p>In TibetSwap, a singleton called the &#8216;router&#8217; launches new pairs. One of its main purposes is to allow people to &#8216;index&#8217; pools, which are always XCH-CAT and currently only have one fee tier. Ideally, the router would assert a pair for the same assets has not been created before when deploying it - which would allow other dApps to do a lot of cool things. However, as stated above, that wasn&#8217;t quite possible when TibetSwap launched - so the second best alternative is to have the router launch pairs for any assets and then make the driver code only mark the first pair valid. This mechanism is off-chain - you can&#8217;t prove it on-chain.</p><h4>warp.green</h4><p>The bridge had a similar issue - given the id of a message, the singleton would ideally be able to assert that it hasn&#8217;t been relayed before. Because, if you bridge 40 USDC to Chia, you should not be allowed to claim it twice under any circumstances. The solution I came up with is to embed the previously bridged message ids in the singleton&#8217;s puzzle. When validators sign a message, they also sign the id of the [singleton] coin that can relay that message - which depends on the ids of the messages that were relayed last spend. The id also depends on the parent&#8217;s id, which in turn depends on the messages that were relayed two spends ago. Essentially, a &#8216;message id chain&#8217; is created with each coin id containing the messages that were relayed previously (in a recursive manner). There are two limitations with this approach:</p><ul><li><p>Validators need to sync the relayer singleton&#8217;s full history to assert that a message hasn&#8217;t been relayed before - and actually perform the check before signing a message</p></li><li><p>This approach needs a centralized party that does this indexing off-chain. In this case, bridge validators were already there for other reasons - but a lot of dApps will probably not want to insert a centralized component just for uniqueness checks</p></li></ul><h2>Up Next</h2><p>I hope you enjoyed this primer on the problem of uniqueness. As a recap, the problem is that puzzles (or rather, singletons) can&#8217;t check that a certain value hasn&#8217;t been used before for something. In the next post, I&#8217;m going to walk you through the most promising solution that has been put forward - and why it doesn&#8217;t work that well. With that said, join me for <a href="https://blog.fireacademy.io/p/solving-the-problem-of-uniqueness">Part 2</a>. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><em>Special thanks to stl and (or, maybe, a.k.a. &#128521; ) Bob for reviewing this article.</em></p>]]></content:encoded></item><item><title><![CDATA[A Path to Chia Hardware Wallet Support]]></title><description><![CDATA[Chia goes hard(ware): Ledger, Trezor, and other hardware wallets coming soon to a green blockchain near you]]></description><link>https://blog.fireacademy.io/p/a-path-to-chia-hardware-wallet-support</link><guid isPermaLink="false">https://blog.fireacademy.io/p/a-path-to-chia-hardware-wallet-support</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Sun, 03 Nov 2024 00:14:29 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7b047a5f-242e-4a64-bbfc-0678fdfd6f4f_1024x576.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I managed to sign Chia transactions with my Ledger, Trezor, and Tangem cards yesterday. Here&#8217;s how.</p><p>Chia community members have been asking for Ledger support for quite some time. That being said, making a Ledger app is not easy. From what I&#8217;ve heard, the coding part is difficult just by itself. There&#8217;s limited space - Ledger Nano X has 2 MB of storage, which is advertised as being sufficient for &#8216;up to 100 apps&#8217; - and very limited computing power. Within these constraints, building an application that can parse Chia transactions might not even be possible - and we haven&#8217;t even considered issues such as application verification requirements, limited screen size, and possible delays in getting support for new primitives.</p><p>If developing a Ledger app is so difficult, why not find an alternative path? To understand how that&#8217;s possible, we first need to take a step back and talk about a popular Ethereum standard.</p><h1>EIP-712</h1><p>When people say &#8220;signing&#8221; in crypto, they usually refer to signing transactions. But the cryptographic primitives powering blockchains mostly allow signing *any* data. At some point, some websites/dApps started asking users to sign messages off-chain - the signatures would either be used for logins (i.e., proving the user owns an address) or later submitted on-chain to custom contracts.</p><p>There was, however, one big problem: users didn&#8217;t know what they were signing. They only saw a final hash - with no way to tell if they were signing into a website or approving a malicious actor to drain all their funds on another dApp. The signing requests looked like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!33lg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!33lg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 424w, https://substackcdn.com/image/fetch/$s_!33lg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 848w, https://substackcdn.com/image/fetch/$s_!33lg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 1272w, https://substackcdn.com/image/fetch/$s_!33lg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!33lg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png" width="1430" height="1661" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1661,&quot;width&quot;:1430,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:438622,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!33lg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 424w, https://substackcdn.com/image/fetch/$s_!33lg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 848w, https://substackcdn.com/image/fetch/$s_!33lg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 1272w, https://substackcdn.com/image/fetch/$s_!33lg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff80627ae-031a-478f-915d-4b5e0e155d9a_1430x1661.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Signature request before EIP-712 on Ethereum. Image taken from the &#8216;Motivation&#8217; section of <a href="https://eips.ethereum.org/EIPS/eip-712">the EIP-712 specification</a></figcaption></figure></div><p>The <a href="https://eips.ethereum.org/EIPS/eip-712">EIP-712</a> standard was proposed to solve this problem by specifying a way to convert structured data into a hash to sign. Websites could then pass the structured data to wallets, which parse it and display a much nicer request to the user:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zVD6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zVD6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 424w, https://substackcdn.com/image/fetch/$s_!zVD6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 848w, https://substackcdn.com/image/fetch/$s_!zVD6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!zVD6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zVD6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png" width="710" height="1024" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:710,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;eth_signTypedData screenshot&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="eth_signTypedData screenshot" title="eth_signTypedData screenshot" srcset="https://substackcdn.com/image/fetch/$s_!zVD6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 424w, https://substackcdn.com/image/fetch/$s_!zVD6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 848w, https://substackcdn.com/image/fetch/$s_!zVD6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!zVD6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F882c2900-38b5-4bc9-879c-71edf4fb3ff0_710x1024.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">EIP-712 signature request. Image taken from the &#8216;Motivation&#8217; section of the <a href="https://eips.ethereum.org/EIPS/eip-712">EIP-712 specification</a></figcaption></figure></div><p>Most wallets currently support the EIP-712 standard (including hardware ones), which made it an interesting avenue to explore. A Chia wallet could just prompt users to sign a message to &#8216;prove&#8217; they want to spend a coin in a specific way. Indeed, the <a href="https://github.com/Yakuhito/hermes/blob/ee8fbea32919a4e20453ed8f029c97bac36d6757/clsp/p2_eip712_message.clsp">demo puzzle</a> I used last Friday verifies the signature of such a message on-chain. Here&#8217;s how the signing request looked like in my Tangem app:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oEkZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oEkZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 424w, https://substackcdn.com/image/fetch/$s_!oEkZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 848w, https://substackcdn.com/image/fetch/$s_!oEkZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 1272w, https://substackcdn.com/image/fetch/$s_!oEkZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!oEkZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png" width="696" height="918" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/df932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:918,&quot;width&quot;:696,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:246578,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!oEkZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 424w, https://substackcdn.com/image/fetch/$s_!oEkZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 848w, https://substackcdn.com/image/fetch/$s_!oEkZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 1272w, https://substackcdn.com/image/fetch/$s_!oEkZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf932172-eebb-4c3f-a625-e3418dc7d7ee_696x918.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Request for the signature needed to spend a demo coin. Note that the request contains the genesis challenge of the simulator network (&#8216;salt&#8217;), coin id, and delegated puzzle hash.</figcaption></figure></div><p>The puzzle was made to act as a replacement for the standard puzzle - meaning that hardware wallets should be able to hold CATs, NFTs, DIDs, and any other primitives we invent. Because EIP-712 is so widely supported, this approach allows integrating Chia with pretty much all wallets that support Ethereum and EIP-712.</p><h1>CHIPs</h1><p>There was one critical barrier in adopting EIP-712 for Chia: Ethereum uses keccak256 for hashing EIP-712 data, while Chia relies on sha256. The keccak256 operator isn&#8217;t currently available in chialisp.</p><p>Thankfully, there is a process through wich new operators can be added: CHia Improvement Proposals (CHIPs). Community members can propose standards or operational changes, which undergo a feedback phase. Some proposals end up being withdrawn (such as the <a href="https://github.com/Chia-Network/chips/pull/13">one</a> proposing a minimum transaction fee), while others pass (such as the <a href="https://github.com/Chia-Network/chips/blob/main/CHIPs/chip-0035.md">one</a> defining an upgrade to the datalayer standard).</p><p>After my request, the keccak256 operator now has <a href="https://github.com/Chia-Network/chips/pull/131">an associated CHIP</a> that will eventually add it to chialisp.</p><h1>What&#8217;s Next</h1><p>Now that we have a clear use case, the keccak256 CHIP will proceed at full speed. Since it&#8217;s a new operator, a &#8216;soft fork&#8217; will be needed, meaning nodes will need to be updated to support keccak256. In practice, this involves a transition period - typically 2-3 months - before the operator is enabled, giving farmers and other node operators time to upgrade their software.</p><p>While the CHIP process is in motion (follow it <a href="https://github.com/Chia-Network/chips/pull/131">here</a>), there&#8217;s more groundwork to lay for hardware wallet integration. <a href="https://github.com/Rigidity/">Rigidity</a> has been working hard on an impressive Chia SDK I&#8217;ve had the pleasure of using many times (including in this project), as well as a new wallet called Sage, which plans to support the new puzzle. This is a complex undertaking, so <strong>if you&#8217;d like to help, consider supporting Sage development, either by donating <a href="https://github.com/sponsors/xch-dev">here</a> or by spreading the word about Sage (available in beta <a href="https://github.com/xch-dev/sage/">here</a>)</strong>.</p><h1>Special Thanks</h1><ul><li><p><a href="https://blog.bbjubjub.fr/">Julie</a> for first suggesting using EIP-712 <a href="https://x.com/0xbbjubjub/status/1792566358548345276">in this thread</a> with me. The previous solution involved signing &#8216;fake&#8217; Ethereum transactions and was much more convoluted.</p></li><li><p>CNI for going through with my CHIP request even tho it wasn&#8217;t clear if the idea would work or how it would work (the latter being a communication problem on my side).</p></li><li><p><a href="https://github.com/Rigidity/">Rigidity</a> and Indigo for quickly getting keccak256 PRs set up, thus enabling the development environment I needed. Also for going through the softfork operator with me.</p></li></ul><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading The FireAcademy.io Blog! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Hello, Chia World!]]></title><description><![CDATA[This is The FireAcademy.io Blog.]]></description><link>https://blog.fireacademy.io/p/hello-chia-world</link><guid isPermaLink="false">https://blog.fireacademy.io/p/hello-chia-world</guid><dc:creator><![CDATA[yakuhito]]></dc:creator><pubDate>Mon, 26 Aug 2024 14:45:01 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a2b4f197-44b0-4d9d-8439-16662f19e277_1100x825.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is The FireAcademy.io Blog.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.fireacademy.io/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.fireacademy.io/subscribe?"><span>Subscribe now</span></a></p>]]></content:encoded></item></channel></rss>