<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Casey Rodarmor&apos;s Blog</title>
    <link>https://rodarmor.com/blog/</link>
    <description>smoods</description>
    <language>en</language>
    <copyright>Copyright and related rights waived via CC0</copyright>
    <lastBuildDate>Tue, 5 May 2026 15:38:56 -0700</lastBuildDate>
    <item>
      <title>Declarative Programming</title>
      <link>https://rodarmor.com/blog/declarative-programming</link>
      <guid>https://rodarmor.com/blog/declarative-programming</guid>
      <pubDate>2008-03-07</pubDate>
      <content:encoded><![CDATA[<p>&quot;Well,&quot; he began, moving closer to her, &quot;declarative programming is when you tell the computer what you want, and then the computer figures out how to get it. Pretty sweet, huh?&quot;</p>
<p>&quot;What kinds of things can you tell the computer you want?&quot; she asked excitedly, her cheeks beginning to flush.</p>
<p>He thought for a moment, and began stroking her hair gently. &quot;All kinds of things. There's a language called Prolog you can use to ask about logical relationships. In SQL you can ask questions about huge quantities of data. With a program like bison you can declaratively describe a language, letting bison generate a program that recognizes it.&quot;</p>
<p>&quot;Oh,&quot; she said breathlessly, leaning her head on his shoulder, &quot;so I don't have to worry about choosing an algorithm--the computer will pick one for me?&quot;</p>
<p>He began caressing her breasts.</p>
<p>She took his silence as an affirmation. &quot;That's so cool that it just does it--it must be really smart to pick the right algorithm!&quot; she enthused.</p>
<p>&quot;Well...&quot; he trailed off, still fondling her breasts.</p>
<p>&quot;What?&quot; She asked, nervously.</p>
<p>&quot;Um...&quot; he said, &quot;it's not quite like that.&quot; His hands stopped moving.</p>
<p>She sensed he was backpedaling. &quot;Well?&quot; she demanded.</p>
<p>He laughed awkwardly. &quot;Heh... You see, most declarative programming systems only know about one algori--&quot;</p>
<p>&quot;It must be a great algorithm!&quot; She interrupted, with renewed intellectual arousal. &quot;What is it?&quot;</p>
<p>He hesitated for as long as he could... &quot;Brute force search,&quot; he said, guiltily.</p>
<p>&quot;What the fuck!?!?&quot; She yelled, straightening and yanking his hands from her chest.</p>
<p>&quot;Wait, baby, it's not so bad!&quot; He begged.</p>
<p>&quot;I'm listening.&quot; She said, staring him straight in the eyes.</p>
<p>&quot;Well, if you're careful and you program in an idiomatic way, you ca--&quot;</p>
<p>A venomous glare silenced him mid-sentence. She stood suddenly, grabbing his hat from the night stand and moving towards the open window.</p>
<p>&quot;My Stetson!&quot; He shrieked, jumping to his feet, the spurs on his cowboy boots jangling feebly. &quot;But baby, didn't that parser generator thing sound cool?&quot; He pleaded.</p>
<p>She stopped. &quot;Well... yeah, that was pretty neat...&quot; she begrudgingly acknowledged, softening.</p>
<p>&quot;And that doesn't use a brute force algorithm. It builds an automaton for you, an LR parser,&quot; he said.</p>
<p>She smiled to herself, seeming to relent momentarily. He could see that she was touched by the idea of a program that could understand other programs.</p>
<p>&quot;See, declarative programming isn't all bad...&quot; he cajoled, slowly walking towards her, palms outstretched.</p>
<p>She started, as if waking from a dream. She looked at him. &quot;But what about in the case of an ambiguous grammar, for which an LR parser won't suffice?&quot;</p>
<p>&quot;Don't worry,&quot; he said, smiling, &quot;bison can use a technique called generalized LR parsing, which allows it to follow all possible parses simultaneously, eventually finding a successful parse.&quot;</p>
<p>She thought for a moment. &quot;But if we're following all possible paths simultaneously and discarding the ones which don't lead to successful parses, isn't that just brute force search?!?&quot; She asked, her voice ringing with betrayal.</p>
<p>Her words were damning. Nothing he could say would placate her. He stood in embarrassed silence, eyeing his cowboy hat anxiously.</p>
<p>She turned away from him, her emotions a mixture of pity and rage. He moved towards her, reaching for her hands, but it was too late. She had already hurled his hat from the window, as hard as she could. They watched silently as it flew into the night, lofted through the cool air as if by the breath of angels.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Transcript</title>
      <link>https://rodarmor.com/blog/transcript</link>
      <guid>https://rodarmor.com/blog/transcript</guid>
      <pubDate>2010-10-24</pubDate>
      <content:encoded><![CDATA[<p>This is pretty nuts. I was poking around in the storage area of my house, and I found a huge cardboard box filled with letters and audio cassettes and dust. Everything was Danish, German, and English, but mostly Danish. The name Max Rasmussen was everywhere, so I think it was all his stuff. I had to get a tape player at best buy to play the tapes, but surprisingly, they all played fine. One of them was an interview, in English, between Max and a man named Hans. I listened to it a few times, and I don't even know what to say. It's transcribed below.</p>
<p>RASMUSSEN: Can you say your name and age for the recorder?</p>
<p>CSEMEGI: Hans Csemegi. 62.</p>
<p>RASMUSSEN: That's an unusual name.</p>
<p>CSEMEGI: Yes, it is, my parent were immigrants to Germany, and they wanted to give me a German sounding name.</p>
<p>RASMUSSEN: And where were they from?</p>
<p>CSEMEGI: Hungary.</p>
<p>RASMUSSEN: Can you tell me a little bit about your life before the war?</p>
<p>CSEMEGI: In many ways I had a very normal childhood. My father was an immigrant, but he was a natural with machines, so he found work easily. We lived very comfortably, all things considered. My mother's cousin and her family came to Germany around the same time, so I knew how other immigrants lived.</p>
<p>RASMUSSEN: Did you speak German growing up?</p>
<p>CSEMEGI: Yes, and Hungarian with my parents.</p>
<p>RASMUSSEN: When did you find out you were a Jew?</p>
<p>CSEMEGI: Not until I was seventeen. My parents kept it from me. But I found a box of letters in my mother's closet one day. I found out that my grandfather was actually a kosher butcher, imagine that...</p>
<p>RASMUSSEN: How did you feel when you found out?</p>
<p>CSEMEGI: I felt disgusted. I was a German, you know. I read the papers, I saw the newsreels, and I knew that Jews were the lowest of the low. I couldn't believe that I was one of them. I also knew right away that this was the worst thing that could happen to me. Kristallnacht was only a month away, and already the writing was on the wall.</p>
<p>RASMUSSEN: How were you sent to the camps?</p>
<p>CSEMEGI: One day they just found out. It was my father, someone had gotten suspicious where he worked, because he didn't look at all German. For that matter, I didn't look at all German, but I was so German in my manner that nobody gave me a second look. But he still had an accent. He was foreign. Our whole family; me, my sister, my mother, and my father; were told to report for processing one morning, and we were stuffed into trains to the camps that very afternoon.</p>
<p>RASMUSSEN: What happened to your family?</p>
<p>CSEMEGI: My father was killed before he even got onto the train. He was always a stubborn man. They divided the men and the women up, and my sister and my mother went to a different line. He started arguing with a soldier, and I think he put his hand on his soldier in anger, or something. And the soldier shot him. He was right to argue, I never saw my mother or my sister again.</p>
<p>RASMUSSEN: &lt;coughing&gt; Sorry.</p>
<p>CSEMEGI: After that I knew. I KNEW. That I was going to die like my father. I remember watching him fall, and I knew that one day soon I was going to hit the ground like he had, a corpse on the cobblestones. Eventually I was loaded onto a train. It was full of people, packed in like cordwood. I was screaming out, until I got tired. It was hot and wretched. Eventually we got to the camp, but some didn't even survive the train ride.</p>
<p>RASMUSSEN: And how was the camp?</p>
<p>CSEMEGI: At first it wasn't so bad. It was a prison, but the officer who was in charge of our division had just been reassigned. He had had sex with a female prisoner, another Jew, and it had gotten out. It was a scandal. So for weeks nobody was in charge, and we just sat around. It was terrible, but mostly because it was so boring. Eventually though they found someone to put in charge of us. His name was Göring, and everyone was afraid of him, even the other Nazis. He put us to work.</p>
<p>RASMUSSEN: What kind of work?</p>
<p>CSEMEGI: Carrying stones.</p>
<p>RASMUSSEN: Carrying stones?</p>
<p>CSEMEGI: Yes.</p>
<p>RASMUSSEN: Just that? Did you build anything?</p>
<p>CSEMEGI: No. Or... I don't know, we didn't, but some other prisoners might have. We just carried stones up a hill. I don't know what happened to them afterward. It was horrible. I didn't know what hell was like, before then. We only got a little soup and bread to eat, and even then only sometimes. We would have been starving to death anyway, but we starved more quickly because we were carrying stones for fourteen hours a day. We were so delicate, like baby birds that had fallen from the nest, and we just started to die.</p>
<p>RASMUSSEN: Did you think you were going to die there?</p>
<p>CSEMEGI: I was convinced. After I saw my father die, I knew my life was over. After two weeks of carrying stones, I thought it was just a matter of time before I fell down in the work line, never to get up again. But then the music started.</p>
<p>RASMUSSEN: Music?</p>
<p>CSEMEGI: Yes, music. I didn't know what to think. Every night when I lay down, I would hear music.</p>
<p>RASMUSSEN: Like, just in your ears? Could anybody else hear it?</p>
<p>CSEMEGI: No, only me.</p>
<p>RASMUSSEN: What kind of music was it?</p>
<p>CSEMEGI: It was, I don't know, songs, all different. No two nights were the same. Sometimes it was singing, sometimes it was from an orchestra, sometimes it was like beeps and blips, but musical. They have music like that these days, but I never heard it back then. I always called it technology music. But anyway... some nights it wasn't music at all, some times it was just noise, like static, or hissing, or just a strange alien drone. I didn't like that so much. The orchestral music was my favorite. I had always loved classical music, you see.</p>
<p>RASMUSSEN: How long would it go on?</p>
<p>CSEMEGI: At least a few hours. I didn't sleep much. But, I didn't sleep much even before the music started. I was so hungry, all the time. I used to just lie there at least half the night, feeling my body eat itself. I felt like I had already died, like a ghost. But with the music I was just in a trance, listening...</p>
<p>RASMUSSEN: Did you tell anyone else?</p>
<p>CSEMEGI: No. I was afraid that it would stop if I told anyone. The music brought color back to the world, and I knew I would die if it stopped.</p>
<p>RASMUSSEN: The music helped?</p>
<p>CSEMEGI: Yes. Every night, when it stopped for the night, I would dream about it. I would fall asleep right away, and just dream of the music. And then the next day, I would think about it, and about the night, when it would come again. Everyone else thought I was crazy.</p>
<p>RASMUSSEN: Why did they think you were crazy?</p>
<p>CSEMEGI: I didn't talk to anyone, I hardly took my eyes off the ground. Everyone else thought that I was one of the ones had died inside, and that soon I would die outside too. But I had this life in me, from the music.</p>
<p>RASMUSSEN: Where did you think the music came from?</p>
<p>CSEMEGI: I thought it was God. Singing to me.</p>
<p>RASMUSSEN: God?</p>
<p>CSEMEGI: Yes. Who else could it have been?</p>
<p>RASMUSSEN: Why was it only you that heard it?</p>
<p>CSEMEGI: I don't know why he didn't sing to the others.</p>
<p>RASMUSSEN: &lt;INDISTINCT&gt;</p>
<p>CSEMEGI: No. But, I wish he did. So many more would have survived.</p>
<p>RASMUSSEN: What do you do now?</p>
<p>CSEMEGI: Nothing, I'm retired.</p>
<p>RASMUSSEN: But after the war?</p>
<p>CSEMEGI: I moved to Denmark, to Apenrade, where they still speak German. Germany had betrayed me, you see. I worked as a stonemason. I was never clever with machines, like my father.</p>
<p>RASMUSSEN: Did you ever marry?</p>
<p>CSEMEGI: No. I was too busy with music. I had a record player. It was the first thing I bought after I found work. I didn't even have sheets on my bed, but I bought a record player. I wanted to have music. For years I would listen to records all night.</p>
<p>RASMUSSEN: Do you still listen to music?</p>
<p>CSEMEGI: Always. Less when my son came, since I couldn't afford a nanny, and had to take care of him.</p>
<p>RASMUSSEN: Your son?</p>
<p>CSEMEGI: Yes. I made love to a woman whose house I was working on. Just once, but she became pregnant, and didn't want him. I couldn't let her give him up, so I took him. She didn't want to have anything to do with us.</p>
<p>RASMUSSEN: So you raised him?</p>
<p>CSEMEGI: Yes. And he doesn't like music at all. &lt;laughs&gt; He would cry when I played my records. I hated him for that. But then I found out about headphones, and it was okay. Eventually, they even started making little tape players, that you could take with you. That was wonderful. I could work all day, listening to music.</p>
<p>&lt;tape ends&gt;</p>
]]></content:encoded>
    </item>
    <item>
      <title>Parsing</title>
      <link>https://rodarmor.com/blog/parsing</link>
      <guid>https://rodarmor.com/blog/parsing</guid>
      <pubDate>2016-07-16</pubDate>
      <content:encoded><![CDATA[<div class="center">
  Parse structure from the languageless void.
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Jumble</title>
      <link>https://rodarmor.com/blog/jumble</link>
      <guid>https://rodarmor.com/blog/jumble</guid>
      <pubDate>2016-09-07</pubDate>
      <content:encoded><![CDATA[
<div style="height: 1em; position: relative;" class="jumble-container">
  <script>
    let container = document.getElementsByClassName('jumble-container')[0];
    let letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    function pick_letter() {
      return letters[Math.floor(Math.random() * letters.length)];
    }
    for (let i = 0; i < 100; i++) {
      let letter = document.createElement('div');
      letter.textContent = pick_letter();
      letter.style.position = 'absolute';
      letter.style.transform = 'rotate(' + Math.random() + 'turn)';
      letter.style.marginLeft = '' + Math.random() * 100 + '%';
      container.appendChild(letter);
    }
  </script>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Delinearization</title>
      <link>https://rodarmor.com/blog/delinearization</link>
      <guid>https://rodarmor.com/blog/delinearization</guid>
      <pubDate>2016-09-14</pubDate>
      <content:encoded><![CDATA[<p>Programs first crawled from the murky oceans as simple lists of instructions that executed in sequence. From these humble beginnings they have since evolved an astonishing number of ways of delinearizing.</p>
<p>In fact, most programming paradigms simply amount to different ways to transform a linear source file into a program with nonlinear behavior.</p>
<p>Some examples:</p>
<ul>
<li>gotos that unconditionally jump to another point in the program</li>
<li>an abort instruction that stops the program at some point other than the end</li>
<li>a macro facility that substitutes one instruction for one or more other instructions</li>
<li>a source file concatenation facility that concatenates multiple source files</li>
<li>an include directive that is substituted for the contents of a source file</li>
<li>structured repetition and selection, a la for, while, if, and switch</li>
<li>subroutines and functions</li>
<li>array oriented programming that replace explicit repetition with implicit repetition</li>
<li>first class functions which delegation of behavior to the caller</li>
<li>object oriented programming with dynamic dispatch, which allow the runtime type of an object to determine which instructions to execute</li>
<li>aspect oriented programming, pattern matching against the structure of the call stack to execute instructions when functions are called or return</li>
<li>event driven programming, executing instructions in response to external events</li>
<li>declarative programming, which essentially delegates execution of one program to another</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Based</title>
      <link>https://rodarmor.com/blog/based</link>
      <guid>https://rodarmor.com/blog/based</guid>
      <pubDate>2016-09-16</pubDate>
      <content:encoded><![CDATA[<div class="center">
I only program in PL/I because I'm BASED.
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Structural Heterogeneity</title>
      <link>https://rodarmor.com/blog/structural-heterogeneity</link>
      <guid>https://rodarmor.com/blog/structural-heterogeneity</guid>
      <pubDate>2017-07-18</pubDate>
      <content:encoded><![CDATA[<p>Investing in cryptocurrencies is not the same as buying simple equity in a company.</p>
<p>Although each company has a different business model, they and the equity they issue are largely structurally homogeneous. They hold their monies in banks, pay for their expenses with wire transfers and cheques, follow prescribed rules of accounting, and issue stock that operates according to well understood rules. This is not to say that said practices are good or bad. They are simply a known factor.</p>
<p>Cryptocurrencies and tokens, however, are structurally heterogeneous. They have different codebases, modes of operation, levels of complexity, and security models. Although broadly lumped into the same category, they can, by the nature of these differences, have almost nothing in common.</p>
<p>Investing in one is like buying stock in a company with novel business models, banking practices, and accounting methods, and furthermore whose stock is issued under a bespoke scheme and follows unique trading rules.</p>
<p>Accordingly, a much, much greater level of care is required when making such investments. If any one of these novel mechanisms fail, your investment may go up in billowing smoke and flames overnight.</p>
<p>This is not to say that you should completely avoid cryptocurrencies and tokens, just, you know, do your homework.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Exchange Traded Mutant</title>
      <link>https://rodarmor.com/blog/exchange-traded-mutant</link>
      <guid>https://rodarmor.com/blog/exchange-traded-mutant</guid>
      <pubDate>2017-08-22</pubDate>
      <content:encoded><![CDATA[
<div class="center">
  <p>
    <em>
      <a href="https://sixfigureinvesting.com/2016/10/is-shorting-uvxy-tvix-vxx-the-perfect-trade">VXX</a> is a dangerous chimeric creature; it is structured like a bond, trades like a stock, follows VIX futures and decays like an option. Handle with care.
    </em>
  </p>

  <p>
    And, currently being <a href="https://www.reddit.com/r/wallstreetbets/comments/6v7ser/pissed_off_at_myself_need_to_vent_want_to_punch/">algo traded</a> by <a href="https://streamable.com/b4sfj">a program written in Excel VBA.</a>
  </p>

  <p>
    Strange times indeed.
  </p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Actuality Films</title>
      <link>https://rodarmor.com/blog/actuality-films</link>
      <guid>https://rodarmor.com/blog/actuality-films</guid>
      <pubDate>2017-10-09</pubDate>
      <content:encoded><![CDATA[<ul>
<li>
<p><a href="https://vimeo.com/160106895"><em>Glas</em></a>, 1958
Glass-blowing, automation and all that jazz.</p>
</li>
<li>
<p><a href="https://vimeo.com/127605643"><em>Farewell, Etaoin shrdlu</em></a>, 1978
The last day of linotype at the New York Times.</p>
</li>
<li>
<p><a href="https://youtu.be/CwuMY-_V4dc"><em>National Disintegrations</em></a>, 2017
On the Geneva Freeport.</p>
</li>
<li>
<p><a href="https://youtu.be/GdUScE7VZq8"><em>What Happens Just Before Show Time At the Met Opera</em></a>, 2017
Behind the scenes at the Met, scored with inspired percussion.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Iota</title>
      <link>https://rodarmor.com/blog/iota</link>
      <guid>https://rodarmor.com/blog/iota</guid>
      <pubDate>2018-02-22</pubDate>
      <content:encoded><![CDATA[<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>IOTA is a cryptocurrency targeting the internet of things. It purports to be scalable, decentralized, and feeless. Unfortunately it is none of those things.</p>
</div>
<div class="paragraph">
<p>In this article I attempt to summarize the numerous technical, social, and ethical problems surrounding the IOTA project, The IOTA Foundation, and the IOTA developers.</p>
</div>
<h2 id="_issues" class="discrete">Issues</h2>
<div id="toc" class="toc">
<div id="toctitle" class="title"></div>
<ul class="sectlevel1">
<li><a href="#_centralization">Centralization</a></li>
<li><a href="#_tip_selection_attack_vectors">Tip Selection Attack Vectors</a></li>
<li><a href="#_ternary_overhead">Ternary Overhead</a></li>
<li><a href="#_non_fungible_tokens">Non-fungible Tokens</a></li>
<li><a href="#_broken_custom_hash_function">Broken Custom Hash Function</a></li>
<li><a href="#_intentional_vulnerabilities">Intentional Vulnerabilities</a></li>
<li><a href="#_no_recourse_against_spam">No Recourse Against Spam</a></li>
<li><a href="#_non_zero_transaction_fees">Non-zero Transaction Fees</a></li>
<li><a href="#_the_internet_of_things_does_not_exist">The Internet of Things Does Not Exist</a></li>
<li><a href="#_premature_use_of_post_quantum_cryptography">Premature Use of Post-Quantum Cryptography</a></li>
<li><a href="#_poor_wallet_security">Poor Wallet Security</a></li>
<li><a href="#_unusable_network_and_wallet">Unusable Network and Wallet</a></li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_centralization"><a class="anchor" href="#_centralization"></a>Centralization</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IOTA is fully centralized. All IOTA transactions must be approved by a server run by The IOTA Foundation called "The Coordinator". <sup class="footnote" id="_footnote_iota-is-centralized">[<a id="_footnoteref_1" class="footnote" href="#_footnotedef_1" title="View footnote.">1</a>]</sup></p>
</div>
<div class="paragraph">
<p>The Coordinator exists to prevent denial-of-service attacks and double spends. The IOTA Foundation claims that at some point the coordinator can be phased out, but these claims are not credible due to the intractable nature of these issues. <sup class="footnote" id="_footnote_iota-doesnt-scale">[<a id="_footnoteref_2" class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup></p>
</div>
<div class="paragraph">
<p>Since all transactions must be approved by a single server, run by a single entity, IOTA is not decentralized. Additionally, The Coordinator is a single point of failure, and has been shut down intentionally by The IOTA Foundation to halt activity on the network. <sup class="footnote" id="_footnote_iota-shutdown">[<a id="_footnoteref_3" class="footnote" href="#_footnotedef_3" title="View footnote.">3</a>]</sup></p>
</div>
<div class="paragraph">
<p>The source code of The Coordinator has not been released, making it impossible to audit it for vulnerabilities, correctness, or fairness. <sup class="footnote" id="_footnote_coordinator-source">[<a id="_footnoteref_4" class="footnote" href="#_footnotedef_4" title="View footnote.">4</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tip_selection_attack_vectors"><a class="anchor" href="#_tip_selection_attack_vectors"></a>Tip Selection Attack Vectors</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IOTA transactions are arranged in a directed acyclic graph, with each transaction referencing two previous transactions by hash. <sup class="footnote" id="_footnote_iota-whitepaper">[<a id="_footnoteref_5" class="footnote" href="#_footnotedef_5" title="View footnote.">5</a>]</sup></p>
</div>
<div class="paragraph">
<p>The choice of which transactions to reference is a matter of local policy, and thus nodes have enormous leeway in the shape of the graph that they construct, and which tips they select.</p>
</div>
<div class="paragraph">
<p>The functionality of the network depends on transactions getting confirmed in a timely fashion, even in the presence of malicious or selfish nodes. The IOTA developers claim that nodes will converge on a tip-selection strategy which confirms new transactions quickly, however this has not been proven to be the case. <sup class="footnote" id="_footnote_iota-alarming">[<a id="_footnoteref_6" class="footnote" href="#_footnotedef_6" title="View footnote.">6</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_ternary_overhead"><a class="anchor" href="#_ternary_overhead"></a>Ternary Overhead</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Several algorithms in IOTA are implemented using balanced ternary, as opposed to binary. Balanced ternary is slightly more efficient, in theory, than binary, due to <a href="https://en.wikipedia.org/wiki/Radix_economy">radix economy</a>.</p>
</div>
<div class="paragraph">
<p>However, in practice this gain in efficiency is more than offset by the overhead incurred by the need to translate ternary into binary for execution on commodity hardware and software.</p>
</div>
<div class="paragraph">
<p>And, since vast majority of hardware fabrication facilities and technology are based on binary logic, a ternary computer more efficient than its binary counterpart will likely never materialize.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_non_fungible_tokens"><a class="anchor" href="#_non_fungible_tokens"></a>Non-fungible Tokens</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A transaction&#8217;s position within the DAG, and other factors, may make that transaction&#8217;s outputs more or less valuable than other transactions.</p>
</div>
<div class="paragraph">
<p>Because of this, nodes will likely have to enforce additional local policies on which transactions to accept, which negatively impacts the fungibility of IOTA transaction outputs.</p>
</div>
<div class="paragraph">
<p>Outputs that have been included in a Coordinator milestone are more valuable than those that haven&#8217;t, since The Coordinator is the current arbiter of truth in the IOTA system. Thus, if The Coordinator refuses to approve a transaction, its outputs are effectively worthless.</p>
</div>
<div class="paragraph">
<p>Similarly, transaction outputs that appear in a snapshot <sup class="footnote" id="_footnote_iota-snapshot">[<a id="_footnoteref_7" class="footnote" href="#_footnotedef_7" title="View footnote.">7</a>]</sup> are more valuable than those that do not. Additionally, whatever entities control what transactions are included in a snapshot have enormous power are an additional centralization factor. For an example, if transactions are deemed to be "spam" and are not included in an snapshot, their outputs will be worthless.</p>
</div>
<div class="paragraph">
<p>If IOTA adopts some kind of sharding mechanism, outputs will be more or less valuable on the basis of whether or not they are known to a particular shard. Outputs may have value within a shard, but be worthless outside of that shard.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_broken_custom_hash_function"><a class="anchor" href="#_broken_custom_hash_function"></a>Broken Custom Hash Function</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IOTA used a custom hash function called Curl, which was later found to be insecure. <sup class="footnote" id="_footnote_curl-vulnerability-report">[<a id="_footnoteref_8" class="footnote" href="#_footnotedef_8" title="View footnote.">8</a>]</sup> <sup class="footnote" id="_footnote_breaking-curl">[<a id="_footnoteref_9" class="footnote" href="#_footnotedef_9" title="View footnote.">9</a>]</sup></p>
</div>
<div class="paragraph">
<p>Although this vulnerability was patched, the choice to use a custom hash function was grossly incompetent, and reflecting extremely poorly on the judgment of the IOTA developers.</p>
</div>
<div class="paragraph">
<p>Creating a cryptographically secure hash function is extremely difficult and furthermore unnecessary, as good hash functions are freely available. That Curl was eventually found to be vulnerable was an entirely predictable and avoidable outcome.</p>
</div>
<div class="paragraph">
<p>The vulnerability in Curl required The IOTA Foundation to take custody of user funds, requiring users to to follow a byzantine reclamation process to get them back, with many users still unable to access their funds. <sup class="footnote" id="_footnote_reclaim-process">[<a id="_footnoteref_10" class="footnote" href="#_footnotedef_10" title="View footnote.">10</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_intentional_vulnerabilities"><a class="anchor" href="#_intentional_vulnerabilities"></a>Intentional Vulnerabilities</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The IOTA developers have intentionally injected vulnerabilities into their open source code in an attempt to discourage copying. <sup class="footnote" id="_footnote_intentional-vulnerability">[<a id="_footnoteref_11" class="footnote" href="#_footnotedef_11" title="View footnote.">11</a>]</sup></p>
</div>
<div class="paragraph">
<p>The code that they released was represented to be complete and free of known issues. The intentional inclusion of severe vulnerabilities in such code is plainly fraud. <sup class="footnote" id="_footnote_open-source-fraud">[<a id="_footnoteref_12" class="footnote" href="#_footnotedef_12" title="View footnote.">12</a>]</sup> <sup class="footnote" id="_footnote_iota-issues">[<a id="_footnoteref_13" class="footnote" href="#_footnotedef_13" title="View footnote.">13</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_no_recourse_against_spam"><a class="anchor" href="#_no_recourse_against_spam"></a>No Recourse Against Spam</h2>
<div class="sectionbody">
<div class="paragraph">
<p>No global transaction limit is enforced in IOTA, making it vulnerable to malicious participants generating a high enough volume of transactions to overwhelm the network. If the network becomes popular, nodes will likely be overwhelmed by non-malicious participants that simply generate a high volume of transactions. <sup class="footnoteref">[<a class="footnote" href="#_footnotedef_2" title="View footnote.">2</a>]</sup></p>
</div>
<div class="paragraph">
<p>IOTA is intended to be run on nodes with low power, compute, memory, disk, and network bandwidth, and such nodes will be easily overwhelmed by even a modest number of transactions. <sup class="footnote" id="_footnote_infinite-scalability">[<a id="_footnoteref_14" class="footnote" href="#_footnotedef_14" title="View footnote.">14</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_non_zero_transaction_fees"><a class="anchor" href="#_non_zero_transaction_fees"></a>Non-zero Transaction Fees</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IOTA transactions do not pay an explicit fee. <sup class="footnoteref">[<a class="footnote" href="#_footnotedef_5" title="View footnote.">5</a>]</sup> However, this does not mean that IOTA transactions are free.</p>
</div>
<div class="paragraph">
<p>IOTA nodes must dedicate significant power, compute resources, and die space to perform the proof-of-work needed to generate transactions and process incoming transactions.</p>
</div>
<div class="paragraph">
<p>Also, since the incentive for a transaction to be confirmed is unclear, a node may be required to pay a permanode, a node in another shard, or a central issuer of snapshots to confirm a transaction.</p>
</div>
<div class="paragraph">
<p>Thus, even if a node pays no explicit fee for its transactions, it may pay significant implicit fees, and thus the claim that IOTA transactions are free of fees is only superficially true, and false in every sense that matters. <sup class="footnote" id="_footnote_iota-response">[<a id="_footnoteref_15" class="footnote" href="#_footnotedef_15" title="View footnote.">15</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_internet_of_things_does_not_exist"><a class="anchor" href="#_the_internet_of_things_does_not_exist"></a>The Internet of Things Does Not Exist</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IOTA is built for a global network of embedded devices communicating over mesh networks. This network does not currently exist and does not seem likely to exist. Currently manufactured IoT devices connect through the internet, and no compelling reason to believe that this may change exists.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_premature_use_of_post_quantum_cryptography"><a class="anchor" href="#_premature_use_of_post_quantum_cryptography"></a>Premature Use of Post-Quantum Cryptography</h2>
<div class="sectionbody">
<div class="paragraph">
<p>IOTA uses cryptography that cannot be broken by quantum computers. <sup class="footnoteref">[<a class="footnote" href="#_footnotedef_5" title="View footnote.">5</a>]</sup> The use of such cryptography, specifically Winternitz signatures, leaves IOTA users vulnerable to loss of funds if they ever reuse an address. This attack has already been seen in practice, with one user reportedly losing $30,000 USD worth of IOTA. <sup class="footnote" id="_footnote_iota-stolen">[<a id="_footnoteref_16" class="footnote" href="#_footnotedef_16" title="View footnote.">16</a>]</sup></p>
</div>
<div class="paragraph">
<p>As quantum computers large enough to threaten existing cryptosystems do not exist and may not exist for many decades, this use of post-quantum cryptography comes with no tangible benefit.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_poor_wallet_security"><a class="anchor" href="#_poor_wallet_security"></a>Poor Wallet Security</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The IOTA wallet requires users to manually enter an 81 character seed, instead of securely generating one. This led users to use malicious online seed generators, leading to the theft of almost $4 million of user funds. <sup class="footnote" id="_footnote_seed-generators">[<a id="_footnoteref_17" class="footnote" href="#_footnotedef_17" title="View footnote.">17</a>]</sup></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_unusable_network_and_wallet"><a class="anchor" href="#_unusable_network_and_wallet"></a>Unusable Network and Wallet</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Users have reported numerous issues with the IOTA network and wallet software. These include unusable software, a slow and unusable network, loss of funds, and an inability to move funds. <sup class="footnote" id="_footnote_a-tangled-mess">[<a id="_footnoteref_18" class="footnote" href="#_footnotedef_18" title="View footnote.">18</a>]</sup> <sup class="footnote" id="_footnote_iota-cannot-be-used-for-iot">[<a id="_footnoteref_19" class="footnote" href="#_footnotedef_19" title="View footnote.">19</a>]</sup> <sup class="footnote" id="_footnote_iota-disappointment">[<a id="_footnoteref_20" class="footnote" href="#_footnotedef_20" title="View footnote.">20</a>]</sup> <sup class="footnote" id="_footnote_iota-wallet-is-terrible">[<a id="_footnoteref_21" class="footnote" href="#_footnotedef_21" title="View footnote.">21</a>]</sup> <sup class="footnote" id="_footnote_iota-scam">[<a id="_footnoteref_22" class="footnote" href="#_footnotedef_22" title="View footnote.">22</a>]</sup> <sup class="footnote" id="_footnote_light-wallet-unusable">[<a id="_footnoteref_23" class="footnote" href="#_footnotedef_23" title="View footnote.">23</a>]</sup> <sup class="footnote" id="_footnote_money-trapped">[<a id="_footnoteref_24" class="footnote" href="#_footnotedef_24" title="View footnote.">24</a>]</sup> <sup class="footnote" id="_footnote_network-dead">[<a id="_footnoteref_25" class="footnote" href="#_footnotedef_25" title="View footnote.">25</a>]</sup> <sup class="footnote" id="_footnote_network-unusable">[<a id="_footnoteref_26" class="footnote" href="#_footnotedef_26" title="View footnote.">26</a>]</sup></p>
</div>
</div>
</div>
<div id="footnotes">
<hr>
<div class="footnote" id="_footnotedef_1">
<a href="#_footnoteref_1">1</a>. <a href="https://medium.com/@ercwl/iota-is-centralized-6289246e7b4d">IOTA is centralized</a>, <a href="https://twitter.com/ercwl">Eric Wall</a>
</div>
<div class="footnote" id="_footnotedef_2">
<a href="#_footnoteref_2">2</a>. <a href="https://medium.com/@kaykurokawa/iota-doesnt-scale-fff54f56e975">IOTA Doesn&#8217;t Scale</a>, <a href="https://twitter.com/kaykurokawa">Kay Kurokawa</a>
</div>
<div class="footnote" id="_footnotedef_3">
<a href="#_footnoteref_3">3</a>. <a href="https://blog.iota.org/gui-v2-5-2-latest-release-with-iota-reclaim-tool-32d364d6241a">GUI v2.5.2: Latest Release with IOTA Reclaim Tool</a>, <a href="https://twitter.com/DomSchiener">Dominik Schiener</a>
</div>
<div class="footnote" id="_footnotedef_4">
<a href="#_footnoteref_4">4</a>. <a href="https://www.reddit.com/r/Iota/comments/6z04yn/why_is_the_coordinator_source_code_not_public/">Why is the coordinator source code not public?</a>
</div>
<div class="footnote" id="_footnotedef_5">
<a href="#_footnoteref_5">5</a>. <a href="https://iota.org/IOTA_Whitepaper.pdf">IOTA Whitepaper</a>, <a href="https://blog.iota.org/@serguei.popov">Serguei Papov</a>
</div>
<div class="footnote" id="_footnotedef_6">
<a href="#_footnoteref_6">6</a>. <a href="https://medium.com/@weka/why-i-find-iota-deeply-alarming-934f1908194b">Why I find Iota deeply alarming</a>, <a href="https://www.linkedin.com/in/nicksdjohnson/">Nick Johnson</a>
</div>
<div class="footnote" id="_footnotedef_7">
<a href="#_footnoteref_7">7</a>. <a href="https://medium.com/@ralf/prepare-for-the-january-28-2018-iota-snapshot-10f565b371ab">Prepare for the January 28, 2018 IOTA Snapshot (updated)</a>, <a href="https://twitter.com/ralf">Ralf Rottmann</a>
</div>
<div class="footnote" id="_footnotedef_8">
<a href="#_footnoteref_8">8</a>. <a href="https://github.com/mit-dci/tangled-curl/blob/master/vuln-iota.md">IOTA Vulnerability Report: Cryptanalysis of the Curl Hash Function Enabling Practical Signature Forgery Attacks on the IOTA Cryptocurrency</a>, <a href="https://www.linkedin.com/in/ethan-heilman-39896934/">Ethan Heilman</a>, <a href="http://nehanarula.org/">Neha Narula</a>, <a href="https://twitter.com/tdryja">Thaddeus Dryja</a>, and <a href="https://madars.org/">Madars Virza</a>
</div>
<div class="footnote" id="_footnotedef_9">
<a href="#_footnoteref_9">9</a>. <a href="https://www.youtube.com/watch?v=7a96MHqND0g">Breaking IOTA&#8217;s Curl Hash Function</a>, <a href="http://cs-people.bu.edu/heilman/">Ethan Heilman</a>
</div>
<div class="footnote" id="_footnotedef_10">
<a href="#_footnoteref_10">10</a>. <a href="https://blog.iota.org/gui-wallet-phase-two-of-the-reclaim-process-f5913109cf46">GUI Wallet: Phase Two of the Reclaim process</a>, <a href="https://twitter.com/DomSchiener">Dominik Schiener</a>
</div>
<div class="footnote" id="_footnotedef_11">
<a href="#_footnoteref_11">11</a>. <a href="https://gist.github.com/Come-from-Beyond/a84ab8615aac13a4543c786f9e35b84a">CFB&#8217;s letters to Neha Narula&#8217;s team during their analysis of Curl-P hash function</a>, <a href="https://twitter.com/c___f___b">Sergey Ivancheglo</a>
</div>
<div class="footnote" id="_footnotedef_12">
<a href="#_footnoteref_12">12</a>. <a href="https://twitter.com/peterktodd/status/907837055715172352">Tweet</a>, <a href="https://petertodd.org/">Peter Todd</a>
</div>
<div class="footnote" id="_footnotedef_13">
<a href="#_footnoteref_13">13</a>. <a href="https://www.reddit.com/r/CryptoCurrency/comments/72l7kp/why_i_find_iota_deeply_alarming_eth_core_dev/">Issue with IOTA, Reddit Comment</a>, <a href="https://twitter.com/VitalikButerin">Vitalik Buterin</a>
</div>
<div class="footnote" id="_footnotedef_14">
<a href="#_footnoteref_14">14</a>. <a href="https://twitter.com/nicksdjohnson/status/964036549162790912">Tweet</a>, <a href="https://www.linkedin.com/in/nicksdjohnson/">Nick Johnson</a>
</div>
<div class="footnote" id="_footnotedef_15">
<a href="#_footnoteref_15">15</a>. <a href="https://www.media.mit.edu/posts/iota-response/">Our response to "A Cryptocurrency Without a Blockchain Has Been Built to Outperform Bitcoin"</a>, <a href="https://joi.ito.com/">Joi Ito</a>
</div>
<div class="footnote" id="_footnotedef_16">
<a href="#_footnoteref_16">16</a>. <a href="https://www.reddit.com/r/CryptoCurrency/comments/7gwl38/hello_guys_i_have_lost_30k_in_iota_and_i_would/">User reports $30,000 worth of IOTA stolen due weakness of IOTA&#8217;s post-quantum signature scheme to address reuse</a>
</div>
<div class="footnote" id="_footnotedef_17">
<a href="#_footnoteref_17">17</a>. <a href="https://twitter.com/nic__carter/status/954950774534090752">Tweet</a>, <a href="https://cryptofundamental.com/@nic__carter">Nic Carter</a>
</div>
<div class="footnote" id="_footnotedef_18">
<a href="#_footnoteref_18">18</a>. <a href="http://codesuppository.blogspot.com/2017/12/iota-tangled-mess.html?m=1">IOTA: A Tangled Mess</a>, <a href="https://github.com/jratcliff63367">John Ratcliff</a>
</div>
<div class="footnote" id="_footnotedef_19">
<a href="#_footnoteref_19">19</a>. <a href="https://shitcoin.com/iota-cannot-be-used-for-iot-loss-of-funds-may-occur-e45b1ed9dd6b">IOTA: Cannot be used for IoT. Loss of funds may occur</a>, <a href="https://twitter.com/abrkn">Andreas Brekken</a>
</div>
<div class="footnote" id="_footnotedef_20">
<a href="#_footnoteref_20">20</a>. <a href="https://github.com/iotaledger/wallet/issues/734">My IOTA disappointment and a warning to others</a>, <a href="https://github.com/UnitTwopointZero">UnitTwopointZero</a>
</div>
<div class="footnote" id="_footnotedef_21">
<a href="#_footnoteref_21">21</a>. <a href="https://www.reddit.com/r/Iota/comments/6y19n2/iota_wallet_is_terribleunusable/">IOTA Wallet is terrible/unusable</a>, <a href="https://www.reddit.com/user/winghaven">winghaven</a>
</div>
<div class="footnote" id="_footnotedef_22">
<a href="#_footnoteref_22">22</a>. <a href="https://medium.com/supercryptocurrency/iota-cryptocurrency-is-a-scam-heres-10-reasons-why-ca111de0f19a">IOTA cryptocurrency is a scam, here’s 10 good reasons why</a>, <a href="https://medium.com/@AndroidAdvance">Android Advance</a>
</div>
<div class="footnote" id="_footnotedef_23">
<a href="#_footnoteref_23">23</a>. <a href="https://forum.iota.org/t/light-wallet-2-3-1-unusable-invalid-transaction-hash-after-every-transfer-attempt/2689">Light Wallet 2.3.1 unusable</a>, <a href="https://forum.iota.org/u/portman/">Fabrizio Ranieri</a>
</div>
<div class="footnote" id="_footnotedef_24">
<a href="#_footnoteref_24">24</a>. <a href="https://www.cryptocompare.com/coins/iot/post/p_554737">Iota light wallet is completely unusable</a>, <a href="https://www.cryptocompare.com/profile/mindblown/">mindblown</a>
</div>
<div class="footnote" id="_footnotedef_25">
<a href="#_footnoteref_25">25</a>. <a href="https://twitter.com/jratcliff/status/939578638432985088">Tweet</a>, <a href="https://github.com/jratcliff63367">John Ratcliff</a>
</div>
<div class="footnote" id="_footnotedef_26">
<a href="#_footnoteref_26">26</a>. <a href="https://twitter.com/maxekaplan/status/939916284967444480">Tweet</a>, <a href="https://twitter.com/maxekaplan">Max Kaplan</a>
</div>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Lightning Exchange</title>
      <link>https://rodarmor.com/blog/lightning-exchange</link>
      <guid>https://rodarmor.com/blog/lightning-exchange</guid>
      <pubDate>2018-03-01</pubDate>
      <content:encoded><![CDATA[<div class="paragraph">
<p>The <a href="https://en.wikipedia.org/wiki/Lightning_Network">Lightning Network</a> has the potential to greatly improve cryptocurrency exchanges.</p>
</div>
<div class="paragraph">
<p>Lighting Network payment channels could be established between users and exchanges to speed the transfer of funds.</p>
</div>
<div class="paragraph">
<p>This would be a huge boon, moving many on-chain deposit and withdrawal transactions off-chain, but is possibly only the beginning.</p>
</div>
<div class="paragraph">
<p>Since Lightning Network payments can span different blockchains, an exchange could use a cross-chain Lightning node to expose its internal order book to external entities.</p>
</div>
<div class="paragraph">
<p>As an example, imagine that an exchange has an LTC/BTC trading pair and wants to allow non-exchange users to fill the orders in their order book.</p>
</div>
<div class="paragraph">
<p>The exchange runs a lightning node with a BTC channel and an LTC channel:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>x:   exchange node
a:   third party node
b:   third party node
&lt;-&gt;: payment channel

   BTC     LTC
a &lt;---&gt; x &lt;---&gt; b</code></pre>
</div>
</div>
<div class="paragraph">
<p>The exchange dynamically sets the exchange rates across the channels based on their current best bid, best ask, and fee schedule.</p>
</div>
<div class="paragraph">
<p>With a best ask of 0.6 and a 1% fee, the exchange sets the BTC&#8594;LTC exchange rate like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>   BTC     LTC
a ----&gt; x ----&gt; b
  0.606   1.000</code></pre>
</div>
</div>
<div class="paragraph">
<p>When a payment is routed across the channels in this direction, LTC sell orders are filled.</p>
</div>
<div class="paragraph">
<p>With a best bid of 0.4 and a 1% fee, the exchange sets the exchange rate on the channel in the LTC&#8594;BTC direction like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>   BTC     LTC
a &lt;---- x &lt;---- b
  0.400   1.010</code></pre>
</div>
</div>
<div class="paragraph">
<p>A payment routed in this direction fills LTC buy orders.</p>
</div>
<div class="paragraph">
<p>In this way, exchanges can expose their internal order book externally and trustlessly. Anyone who wishes to make cross-chain Lightning Network payments will discover and travel over these routes with no special effort required by the exchange, assuming that their rates are competitive. Also, it&#8217;s likely that third parties will appear whose sole purpose is to search the Lightning Network for arbitrage loops and travel them until they are exhausted, thus bridging multiple exchanges when their order books cross.</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Mushrooms</title>
      <link>https://rodarmor.com/blog/mushrooms</link>
      <guid>https://rodarmor.com/blog/mushrooms</guid>
      <pubDate>2018-07-15</pubDate>
      <content:encoded><![CDATA[<p>I woke up last night after only a few hours of sleep, sweaty and disoriented.</p>
<p>Maybe it was miasmatic vapors rising up from beneath South of Market streets. Maybe it was the widening gyre opening up under the world. Maybe it was nothing at all. I don't know.</p>
<p>It felt like the world had ended, but I was still there. And the lights of the city glimmered through the window, so, it was still there too.</p>
<p>I rose, dressed, and walked out the front door, into the hallway. For air, I guess. And movement. Try to walk it off.</p>
<p>I walked over immaculately carpeted floors and beside newly painted walls, past the elevator landing, and through the door with the emergency exit sign. I started down the unfinished throat of the building, through which it gasps for air. Down metal stairs. Past primer-painted walls.</p>
<p>I felt like the thirty flights would do me good, maybe shake loose the static fuzz that buzzed in my head.</p>
<p>My mind wandered. The fugue of interrupted sleep gave way to visions of a gossamer fabric, stretching off over the earth in all directions, a network of networks, with nodes like points of light shot through it, streams of data passing between them.</p>
<p>The stairs ended abruptly. I had passed the ground floor. The door ahead of me was marked B5. I tried the handle. It was unlocked. I opened it and walked through.</p>
<p>It was dark. Dim light streamed through from above. I imagined that it was from the lobby, shining from the light fixtures above the marble front desk, through the pile carpet, between cracks in the floor, and down into this subterranean space.</p>
<p>It was huge. A deep hollow between wide supporting columns of concrete. The air was cool and still, down here in the guts of the building.</p>
<p>The floor was covered with moist brown soil. It was carefully raked, and before me stretched neat rows of… something. Of dark shapes.</p>
<p>I walked forward and hunched over, squinting, trying to resolve  out the shapes in the darkness.</p>
<p>They were rows of fat black mushrooms. The size of a man's fist. Oozing a sticky red treacle down their stems.</p>
<p>They smelled sweet. I imagined overripe mangos, cleft open to reveal insides not of fruit but of charred animal flesh.</p>
<p>Crouching on my heels, the odor washed over me. Memories that weren't mine came to me unbidden. From deep in my blood.</p>
<p>I saw my great uncle, who, according to whispers within the family was once a zionist terrorist known as the Lion of Bethlehem. He was in his youth, not the old man that I knew from pictures. A pale-faced and red-haired Ashkenazi, he had a knife in his hand, but it cut the dark skin of an arab neck. The knife was a shechita blade. Even though human meat is not kosher, no matter how it is cut.</p>
<p>I saw a swede with green eyes like mine, butchering a snapphane in some muddy Scanian town square. It was a brutal show, to scare other rebels into submission.</p>
<p>I saw a welsh bowman in a field wreathed with fog, nocking an arrow after the one before it had flown straight through an Anglo-Norman's chest. He squinted down the shaft, aiming to take a second life.</p>
<p>More violence committed by men in my line glinted before my eyes, further and further back. The last was a glimpse of a spry homo sapian bringing a huge rock down on a neanderthal's skull, braining him. I started, and focused on the mushrooms in front of me.</p>
<p>I pawed at one, its sap like venous fluid, thick and red, sticking to my fingers.</p>
<p>It looked and smelled disgusting, but I wanted to eat it.</p>
<p>I started to bring my fingers to my mouth, to lick them clean. But there was a thump, off in the distance, past pairs of huge columns of concrete that shot into the darkness and the rows of mushrooms at their feet.</p>
<p>A shadow detached from the far wall and moved in my direction. Fear took me. The stench of the mushrooms was suddenly revolting. I stumbled backwards, wiping my hand on my jeans. I rushed towards door and the stairs beyond, up to the surface, back to the light.</p>
]]></content:encoded>
    </item>
    <item>
      <title>New Rustacean Resources</title>
      <link>https://rodarmor.com/blog/new-rustacean-resources</link>
      <guid>https://rodarmor.com/blog/new-rustacean-resources</guid>
      <pubDate>2018-07-22</pubDate>
      <content:encoded><![CDATA[<ul>
<li>
<p><a href="https://rustup.rs"><em>obtain</em></a></p>
<p>Rustup is the rust toolchain manager. It can install Rust and keep it up-to-date.</p>
</li>
<li>
<p><a href="https://code.visualstudio.com"><em>write</em></a></p>
<p>Visual Studio Code is easy to use and has great Rust integration.</p>
</li>
<li>
<p><a href="https://doc.rust-lang.org/book/"><em>read</em></a></p>
<p>The Rust Book is a comprehensive guide to the entire language.</p>
</li>
<li>
<p><a href="https://play.rust-lang.org"><em>play</em></a></p>
<p>The Rust Playground allows you to quickly try out and share code snippets.</p>
</li>
<li>
<p><a href="https://github.com/rustlings/rustlings"><em>exercise</em></a></p>
<p>Rustlings are bite-sized exercises for learning rust.</p>
</li>
<li>
<p><a href="https://discord.gg/bGugdPp"><em>chat</em></a></p>
<p>The Rust-Lang discord instance is a great place to chat about rust.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Cabal</title>
      <link>https://rodarmor.com/blog/cabal</link>
      <guid>https://rodarmor.com/blog/cabal</guid>
      <pubDate>2018-11-18</pubDate>
      <content:encoded><![CDATA[<p>We all stood, gathered our things, walked down the cafe stairs and out to the dark and bustling Berlin street.</p>
<p>After a few goodbyes and handshakes, everyone headed off in different directions, for different destinations.</p>
<p>The meeting had felt momentous to me, a marker of strange and interesting times to come. I headed to the U-Bahn, alone.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Kademlion</title>
      <link>https://rodarmor.com/blog/kademlion</link>
      <guid>https://rodarmor.com/blog/kademlion</guid>
      <pubDate>2019-03-12</pubDate>
      <content:encoded><![CDATA[<p>A <a href="https://en.wikipedia.org/wiki/Kademlia">Kademlia</a>-inspired modification of <a href="https://arxiv.org/abs/1701.04439">Dandelion</a> for use in <a href="https://grin-tech.org/">Grin</a>.</p>
<h3><em>What</em></h3>
<p>On boot and restart, Grin nodes pick a random 256-bit <em>node id</em> which is broadcast to their peers.</p>
<p>Upon receiving a block, a new <em>epoch</em> begins if <code>block_height % 10 == 0</code>. The <em>epoch id</em> is the 256-bit blake2b hash of the block hash of the block that started the epoch. (I.E. the double blake2b hash of the block header.)</p>
<p>At the start of each epoch, every node:</p>
<ul>
<li>
<p>Calculates the <em>relay weight</em> of itself and all peers using the formula: <code>relay_weight = peer_id xor epoch_id</code>. Relay weight is interpreted as a 256 bit unsigned integer.</p>
</li>
<li>
<p>Selects the node among itself and all peers with the highest relay weight as the <em>relay target</em>.</p>
</li>
<li>
<p>Determines that it is in <em>stem mode</em> if the relay target is a peer, and in <em>fluff mode</em> if the relay target is itself.</p>
</li>
</ul>
<p>Then, for every stem transaction received:</p>
<ul>
<li>
<p>If it is in stem mode, it immediately relays it to its relay target.</p>
</li>
<li>
<p>If it is in fluff mode, it aggregates transactions until its next patience timer expires, then broadcast them.</p>
</li>
</ul>
<h3><em>Why</em></h3>
<p>&quot;Heavy&quot; peers will naturally be chosen for relay targets, creating agreed-upon stem paths and fluff sinks, and leading to more opportunities for transaction aggregation.</p>
<h3><em>Notes</em></h3>
<ul>
<li>
<p>In a well-connected network, one node may be the sink for all transactions during a given epoch, and thus see all unaggregated transactions during the epoch. It may thus be desirable to stick to random mode selection as in Dandelion++, so as to break up stem paths with randomly selected fluff sinks.</p>
</li>
<li>
<p>If block hashes are used directly as the epoch ID, peers could select peer IDs with a large number of leading 1s, thus biasing relay target selection towards themselves. Thus, we take the double blake2b hash of the block header as the epoch ID.</p>
</li>
<li>
<p>Since the epoch ID is known by all, a node could pick node IDs that had high relay weight during that epoch. To provent this, if a node connects to a new peer it should use a randomly assigned peer ID for the current epoch.</p>
</li>
<li>
<p>Should this modification be called <em>Kademlion</em>, or <em>Objective-Dandelion</em>?</p>
</li>
<li>
<p>Thanks to Antioch Peverell for the <a href="https://github.com/mimblewimble/grin/issues/2176">clear description of Dandelion++</a> whose language I shamelessly copied.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Unix Utilities in Rust for Great Success</title>
      <link>https://rodarmor.com/blog/unix-utilities-in-rust-for-great-success</link>
      <guid>https://rodarmor.com/blog/unix-utilities-in-rust-for-great-success</guid>
      <pubDate>2019-03-12</pubDate>
      <content:encoded><![CDATA[<p>I've often been asked for suggestions for an appropriate first project in Rust, and I think that writing a version of a unix utility is a great choice, for a bunch of reasons!</p>
<ul>
<li>
<p>There is a diverse and colorful cast of characters to choose from that all provide an appropriate scope and difficulty level, such as:</p>
</li>
<li>
<p><code>tree</code>: Print a graphical representation tree in visual form</p>
</li>
<li>
<p><code>strings</code>: Extract plaintext strings from binary files</p>
</li>
<li>
<p><code>wc</code>: Count the lines, characters, and bytes in a file</p>
</li>
<li>
<p><code>ls</code>: List the contents of a directory</p>
</li>
<li>
<p><code>nc</code>: Read and write bytes to network sockets</p>
</li>
<li>
<p><code>cal</code>: Print a cute text calendar</p>
</li>
<li>
<p><code>cat</code>: Copy streams to stdout</p>
</li>
<li>
<p><code>cut</code>: Extract delimited fields from linewise text records</p>
</li>
<li>
<p><code>sort</code>: Sort lines</p>
</li>
<li>
<p><code>uniq</code>: Print only unique lines</p>
</li>
<li>
<p>The existing implementation provided by your system serves as a specification, giving you an idea of how the tool works and whether or not your implementation has the same behavior.</p>
</li>
<li>
<p>The core functionality of these utilities is very simple, allowing a learner to quickly build something useful. And, many have additional features, allowing a learner to add and build if they wish. <code>ls</code> is simple, but <code>ls -l</code> is quite the project!</p>
</li>
<li>
<p>Many creative additions are possible, like colorful output, expressive configuration, and fun and useful new features.</p>
</li>
<li>
<p>IO and error handling are often front-and-center when writing these utilities, which provides a great chance to get used to explicit error handling.</p>
</li>
<li>
<p><a href="https://github.com/TeXitoi/structopt">structopt</a> makes argument parsing a breeze. And, by leveraging the type system and custom-derive, it provides a nice example of a situation where Rust has enormous advantages over other languages, allowing you to do more with less code.</p>
</li>
<li>
<p>Rust binaries are fast to load and run, so performance is on par with native C implementations, and often much better than implementations in slower languages.</p>
</li>
<li>
<p>Rust binaries are self-contained, so packaging and distribution is manageable, so you can share your work with the world.</p>
</li>
<li>
<p>It's fun to use utilities that you wrote in your day-to-day workflow!</p>
</li>
<li>
<p>There are lots of fabulous examples of utilities in the rust ecosystem, like <a href="https://github.com/BurntSushi/ripgrep">ripgrep</a>, <a href="https://github.com/sharkdp/fd">fd</a>, <a href="https://github.com/sharkdp/bat">bat</a>, <a href="https://github.com/ogham/exa">exa</a>, and <a href="https://github.com/sharkdp/hexyl">hexyl</a>. (Damn, David Peter is a beast.)</p>
</li>
<li>
<p>If you're teaching others, a simple utility like <code>strings</code> makes for a great demonstration of the basics of the language.</p>
</li>
</ul>
<p>I think whether you start with the book or a project like this depends on the learner.</p>
<p>I much prefer to jump in and struggle mightily, so I started with a project like this (what eventually became <a href="https://github.com/casey/just/">just</a>), but I think a lot of people might prefer to start with <a href="https://doc.rust-lang.org/book/">the book</a>, or at least parts of the book.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Fractal</title>
      <link>https://rodarmor.com/blog/fractal</link>
      <guid>https://rodarmor.com/blog/fractal</guid>
      <pubDate>2019-09-29</pubDate>
      <content:encoded><![CDATA[<p>I saw a janitor sweeping dirt from the fronds of his enormous push broom with a normal-sized broom.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Stack</title>
      <link>https://rodarmor.com/blog/the-stack</link>
      <guid>https://rodarmor.com/blog/the-stack</guid>
      <pubDate>2019-09-30</pubDate>
      <content:encoded><![CDATA[<p>Computering is a party. The stack is best visualized as a bunch of Jenga
blocks on the floor, and the heap as a bunch of balloons floating
around bumping into each other on the ceiling. The fact that the stack
usually grows downwards in memory is a travesty.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Popcorn Time Should Become a Browser</title>
      <link>https://rodarmor.com/blog/popcorn-time-should-become-a-browser</link>
      <guid>https://rodarmor.com/blog/popcorn-time-should-become-a-browser</guid>
      <pubDate>2020-01-22</pubDate>
      <content:encoded><![CDATA[<p><em>I am not a lawyer. This is not legal advice.</em></p>
<p>Popcorn Time-style video streaming apps seem to be vulnerable to legal
action by rightsholders.</p>
<p>For example, the
<a href="https://torrentfreak.com/registrar-suspends-popcorn-time-domain-name-following-complaint-200121/">popcorntime.sh domain was recently suspended</a>,
and <a href="https://torrentfreak.com/operator-of-popcorn-time-info-site-is-liable-for-piracy-supreme-court-rules-200115/">the operator of a site which merely provided information about how to obtain and use Popcorn Time was sentenced to prison</a>.</p>
<p>Although given that Popcorn Time's servers do not themselves host
infringing content this may seem a bit unfair, it is simply the reality
of the world we live in.</p>
<p>It is interesting to note, however, that although web browsers can be
used in exactly the same way as Popcorn Time, namely searching for and
viewing copyrighted movies, the developers of web browsers have thus far
not faced successful legal challenges.</p>
<p>I believe that there are two major factors that differentiate Popcorn
Time from web browsers, and contribute to Popcorn Time's legal
vulnerability:</p>
<ol>
<li>
<p>Upon opening a web browser, the user must supply the URL of the site
they wish to visit. Compare this to Popcorn Time, where upon opening
the application for the first time, the user is immediately presented
with a selection of unlicensed Hollywood movies to download.</p>
<p>This difference greatly weakens Popcorn Time's claims against
contributory copyright infringement. The developers of Popcorn Time
cannot credibly claim to be ignorant to the types of movies that
their users are downloading, whereas a web browser developer can
credibly claim that the choice of website to visit is always left to
the end user.</p>
</li>
<li>
<p>Web browsers have substantial non-infringing uses. &quot;Substantial
non-infringing use&quot; is jargon for a legal test used in the United
States which protects the creator or purveyor of a piece of technology
from liability for its use in infringement by users if that technology
has &quot;substantial non-infringing uses&quot;. For the canonical example, see
<a href="https://en.wikipedia.org/wiki/Sony_Corp._of_America_v._Universal_City_Studios,_Inc."><em>Sony Corp. of America v. Universal City Studios, Inc.</em></a>.</p>
</li>
</ol>
<p>Whereas a web browser provider can rightly claim that there are many
websites,
<a href="https://youtu.be/2JO3oJybBTw">and it's possible an infringing one might slip in, there would be no way of knowing</a>,
the popcorn time developers cannot claim the same. There is a single,
fixed Popcorn Time backend, run by the Popcorn Time team, serving the
same search results to every user.</p>
<p>Fortunately, even given the above, I believe that Popcorn Time could
implement a small number of strategic changes that would allow it to
withstand future legal aggression:</p>
<ul>
<li>Add a URL bar, like a web browser's, to the top of the current GUI.</li>
<li>Make the URL bar empty when opening the app for the first time, and
display no default search results to the user.</li>
<li>When the user enters a URL, use the existing Popcorn Time API protocol
to contact the backend at that URL, and begin displaying search
results from that backend to the user.</li>
<li>If the app is closed and re-opened, keep the URL bar and the search
results populated from the last run of the app.</li>
</ul>
<p>These changes would be simple, have a minimal impact on the current
(quite excellent!) user experience, and leverage interaction flows, i.e.
a URL bar, that users already understand.</p>
<p>Additionally, the Popcorn Time team should create an official default
search backend which focuses exclusively on free, non-infringing,
user-created content.</p>
<p>These steps would, I believe, nicely protect the developers and
distributors of Popcorn Time from further legal challenges:</p>
<ul>
<li>
<p>Popcorn Time, when first opened, would display no search results by
default, and would require the user to direct the app with the URL of
a site that they would like to visit. This would avoid the current
situation where a litigator sitting in front of a judge can open the
Popcorn Time application, and it will by immediately display a choice
selection of infringing content, which makes for a terrible first
impression.</p>
</li>
<li>
<p>Users of the Popcorn Time application could use it to access both
infringing and non-infringing content, providing a nice argument that
the application does in fact have <em>substantial non-infringing uses</em>.</p>
</li>
<li>
<p>Infringement via the application would be entirely at the direction of
the end-user, and not directly assisted by the default search results
provided by the developers.</p>
</li>
<li>
<p>Developers wouldn't be running a search back end with infringing
content, which is the only component of the current Popcorn Time
system that stores problematic metadata about infringing content.</p>
</li>
<li>
<p>I suspect that the official free-content focused search backend would
be successful and useful in its own right.</p>
</li>
<li>
<p>Since the search backend could now be switched by end users, a very
large number of third-party backends would likely appear, serving
content that might not be otherwise available from the current Popcorn
Time backend.</p>
</li>
</ul>
<p>In short, Popcorn Time should become a browser, and then all those
lawyers and their handlers can go pound sand.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Decentralize Messaging</title>
      <link>https://rodarmor.com/blog/decentralize-messaging</link>
      <guid>https://rodarmor.com/blog/decentralize-messaging</guid>
      <pubDate>2020-01-29</pubDate>
      <content:encoded><![CDATA[<p>Twitter is <a href="https://twitter.com/jack/status/1204766078468911106">funding a team</a> to decentralize social media. I think they should start with messaging.</p>
<h2>TL;DR</h2>
<h3>Why</h3>
<ul>
<li>Messaging is a subset of social media.</li>
<li>Users are tired of the wild proliferation of messaging apps.</li>
<li>Social networks are all different, making them hard targets for standardization; messaging apps are all the same, making them easy targets for standardization and interoperability.</li>
<li>Messaging is easier to scale.</li>
</ul>
<h3>How</h3>
<ul>
<li>Build on the matrix protocol.</li>
<li>Extend email.</li>
<li>Or maybe both.</li>
</ul>
<p><em>Update: I no longer believe Matrix is fit for use.</em></p>
<h2>Why</h2>
<h3>messaging is a subset of social media</h3>
<p>Messaging is a key feature of all social media platforms; decentralizing messaging is a prerequisite to decentralizing social media. And, even though it is a subset of social media, it still captures many of social media's central challenges: spam, moderation, and, most importantly, identity.</p>
<h3>users are tired of the wild proliferation of messaging apps</h3>
<p>The average user is more negatively impacted by the proliferation of messaging apps than they are by the proliferation of social networks.</p>
<p>I have heard many people express irritation that they must use an inordinate number of messaging apps to communicate.</p>
<p>I haven't heard the same complaints regarding the proliferation of social media platforms. My best as to why this is the case is that the need to communicate one-on-one with an individual has no substitute. If I'm meeting Bob for lunch, being able to message anyone but Bob is completely useless. So, I must use whichever app Bob uses, or get Bob to use whatever app I use, and, if we don't have a common messaging app, one of us will need to install a new one, furthering the proliferation problem.</p>
<h3>social network distinctiveness</h3>
<p>It's tempting to think that decentralizing social media should be begin with the features that we most readily associate with social media platforms, like posts, news feeds, and liking. However, the implementations of these features differ, and different social media platforms provide very different experiences.</p>
<p>This makes these features of social media a hard target for standardization. However, the messaging features of these platforms are all nearly identical, making messaging an easy target for standardization.</p>
<p>The goal is to decentralize social media as a whole, not just messaging, but messaging can be used as an initial step, with further extensions tackling the various individual features of social media platforms.</p>
<h3>messaging is easier to scale</h3>
<p>At the upper end, tens of millions of users may engage with an individual tweet, whereas group messages are limited to no more than fifty users. This makes messaging a more attractive initial target for decentralization, since it avoids needing to hit massive scale on day one.</p>
<h3>a clear target</h3>
<p>So, to summarize all the above, decentralized messaging has an obvious target feature set to aim for, a strong benefit to end users that will drive adoption, puts off hard scaling challenges, and can be extended in the future to all the features we associate with social media.</p>
<h2>How</h2>
<p>I see two promising and complementary paths to decentralized messaging: building on the new and shiny <a href="https://matrix.org">Matrix protocol</a>, and gradually extending email.</p>
<p>The Matrix protocol has the huge advantage of being modern. It already supports many, if not most, of the features of modern messaging apps.</p>
<p>Email, on the other hand, is ancient, weird, and has no support for modern luxuries like end-to-end encryption or user-presence notifications. However, email is extremely widely adopted, and a broadly supported and popular &quot;Email 2.0&quot; might receive a great deal of support.</p>
<p>Although it would be a challenging process to navigate, email could be extended with features until it reaches parity with modern messaging apps, and further extended to support the features of existing social media networks. These extensions can be added in backwards compatible ways that allow mail agents to negotiate upgrades, falling back to plain email when extensions are not available.</p>
<p>These extensions could include:</p>
<ul>
<li>delivery receipts</li>
<li>optional read receipts</li>
<li>user presence information</li>
<li>binary serialization for efficiency and extensibility</li>
<li>end-to-end encryption</li>
<li>WebRTC signalling for negotiating VOIP and video chat</li>
<li>signed introduction tokens to reduce spam</li>
<li>a standard extension mechanism</li>
</ul>
<p>A hybrid approach might be to design an email-to-matrix protocol upgrade negotiation mechanism, allowing legacy email addresses to seamlessly upgrade to a modern messaging protocol.</p>
<p>Whatever the approach, building a decentralized messaging protocol and integrating it into twitter would serve as an excellent foot in the door for decentralizing the entire social media landscape.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Intermodal</title>
      <link>https://rodarmor.com/blog/intermodal</link>
      <guid>https://rodarmor.com/blog/intermodal</guid>
      <pubDate>2020-03-09</pubDate>
      <content:encoded><![CDATA[<h2>TL;DR</h2>
<p>Intermodal is a new command-line BitTorrent metainfo<sup class="footnote-reference"><a href="#metainfo">1</a></sup> utility
for Linux, Windows, and macOS. The binary is called <code>imdl</code>.</p>
<p>It can create, display, and verify <code>.torrent</code> files, as well as generate
magnet links.</p>
<p><img src="/blog/intermodal/index.gif" alt="demonstration animation" /></p>
<p>It has lots of features and niceties, is easy to install and run, and is
hopefully just the beginning of an ambitious project to make
decentralized content sharing better.</p>
<p>Features include:</p>
<ul>
<li>Attractive progress bars that display hashing throughput.</li>
<li>Automatic piece length picker that uses the size of the torrent to
pick a good piece length.</li>
<li>Ignores junk files, like <code>.DS_Store</code>, by default.</li>
<li>Detailed error messages.</li>
<li>Warnings for common issues, like non power-of-two piece lengths.</li>
<li>Support for all commonly used metadata fields, like <code>info.source</code> and
<code>info.private</code>.</li>
<li>File inclusion and exclusion with <code>--glob PATTERN</code> and
<code>--glob !PATTERN</code>.</li>
<li>Torrent verification with <code>imdl torrent verify</code>.</li>
<li>Torrent display with <code>imdl torrent show</code>.</li>
</ul>
<p>You can install the latest version of <code>imdl</code> to <code>~/bin</code> with:</p>
<pre><code>curl --proto '=https' --tlsv1.2 -sSf https://imdl.io/install.sh | bash
</code></pre>
<p>Development is hosted on <a href="https://github.com/casey/intermodal">GitHub</a>,
where you can find the code, the issue tracker, and more installation
options.</p>
<p>Give it a try and let me know what you think!</p>
<p>I'm eager to hear what works, what doesn't, and what features you'd like
to see added. I'll be working on novel functionality—more on that
below—and I'd love to hear your critical feedback and ideas.</p>
<p>You can get in touch by
<a href="https://github.com/casey/intermodal/issues/new">open an issue</a>, joining
<a href="https://discord.gg/HaaT5Qz">the discord server</a>, or
<a href="mailto:casey@rodarmor.com">sending me an email</a>.</p>
<p>Happy sharing!</p>
<p><sup class="footnote-reference"><a href="#metainfo">1</a></sup> A BitTorrent <code>.torrent</code> file, also known as a metainfo file,
contains information that allows peers to locate and retrieve the
contents of a torrent. Creating and publishing this metainfo is required
to make the contents of a torrent available to peers.</p>
<p><em>Mentioning BitTorrent always carries the risk of prompting discussions
of the unauthorized sharing of copyrighted or censored content.
Intermodal is not intended to facilitate such unauthorized sharing.
Discussion of unauthorized sharing is not permitted in any project
space, including GitHub and Discord.</em></p>
<h2>What happened to your personal library?</h2>
<p>Rows of LPs, shelves of VHS tapes, binders of CDs and DVDs, or maybe
hard drives stuffed to overflowing.</p>
<p>It used to be common to maintain a personal content library, but in the
last decade, most of us stopped. We ditched the tedium of tagging and
sorting for Netflix, Spotify, and YouTube.</p>
<p>Whenever I think about this I feel a wistful longing for the past. And I
don't think it's just nostalgia.</p>
<p>Modern content channels are usually designed around a feed and automatic
recommendations, and don't make a strong distinction between things that
are in your library and everything else. This makes it too easy to
consume content compulsively and replaces active search and curation
with guzzling down what's on tap, biasing you away from what <em>you</em> like
and towards what <em>everyone else</em> likes.</p>
<p>Beyond that, once-accessible items often disappear due to obscure legal
and contractual machinations out of one's control.</p>
<p>Worse still, content that is below an invisible popularity threshold is
hard to find, not available, or doesn't appear in recommendation
streams. One of my favorite tracks from my old music library was a song
from a collection of music by people on Usenet called &quot;It's Six AM and
Gary's Refrigerator Plays a Raga&quot;. Definitely not available on Spotify.</p>
<p>And, if you make something yourself, you can't just put it into your own
library, or send it to a friend so they can throw it in theirs.</p>
<p>This is profoundly saddening.</p>
<h2>Why did we stop curating our own libraries?</h2>
<p>Centralized apps have replaced decentralized content networks due to
ease of use, user experience, and incentives.</p>
<p>These factors have pushed people away from BitTorrent, store-bought CDs
mixtapes, and personal libraries, and towards apps like Spotify and
Netflix.</p>
<h3>Ease of Use</h3>
<p>For all their flaws, centralized apps are incredibly easy to use. Just
open a browser tab and press play.</p>
<p>To get content into your own library and play it, you need to use a
number of applications in concert: a web browser to search, another app
to download, a file browser to organize, and finally a player to listen
or watch. A chore, even for technically adept users, and impossible for
the non-technical majority.</p>
<h3>Features</h3>
<p>Centralized apps maintain large, proprietary databases of metadata, so
features like search, recommendation, and preview work flawlessly.</p>
<p>Most desirable features are only as good as the metadata they're built
on, so if you're curating a personal library, you have to curate the
metadata along with it.</p>
<p>This is the primary reason I gave up on my personal music library: I
spent endless amounts of time making sure that metadata was uniform and
correct, and although I found some great tools to help, it still felt
like a part-time job.</p>
<h3>Incentives</h3>
<p>Centralized apps usually have built-in monetization mechanisms. If you
like content you find through decentralized channels and want to support
the creator or publisher, there is no easy means to do so.</p>
<p>Because of this, first-party releases on decentralized content networks
are rare, and resources are instead lavished on centralized apps.</p>
<h2>Where do we go from here?</h2>
<p>The feature-gap between centralized apps and decentralized content
networks is vast.</p>
<p>Fortunately, there is a simple way to close that gap:</p>
<p>Developing standards for structured, machine-readable metadata in a
simple, universal format.</p>
<p>Existing content does contain metadata. However, this metadata is
limited to specific content types, for example MP3 tags; or modes of
transport, for example BitTorrent.</p>
<p>By developing a standard for metadata manifests that can accompany any
kind of content, across all modes of transportation, many desirable
features become more reliable and dramatically easier to implement:</p>
<ul>
<li>
<p>Newly downloaded releases can be integrated into a library
automatically, applying the user's preferred scheme for naming,
sorting, and tagging.</p>
</li>
<li>
<p>Content from a user's library can easily be exported for sharing in a
format that's appropriate for transport, for example as a torrent,
Usenet NZB file, or <code>.zip</code> archive.</p>
</li>
<li>
<p>By identifying the location and format of content, releases can be
transcoded for mobile devices and web browsers, either in advance or
on the fly, and made available to all a user's devices without manual
intervention.</p>
</li>
<li>
<p>Rich search indices can be built from collections of content, without
needing to resort to complex and error-prone heuristics.</p>
</li>
<li>
<p>Immutable identifiers, for example ISBN numbers, allow metadata to be
automatically updated from external sources.</p>
</li>
<li>
<p>Creators and publishers can include a Bitcoin tipping address in
releases, so end users can reward them directly.</p>
</li>
<li>
<p>Digital signatures over and alongside metadata manifests can allow
authenticity of releases to be verified, allow publishers to sign new
updates to old releases, and form the basis of a decentralized,
privacy-preserving reputation system.</p>
</li>
</ul>
<p>These features have the potential to not just bring the decentralized
content ecosystem to parity with centralized services, but to surpass
them.</p>
<h2>Intermodal</h2>
<p>The project for developing these metadata standards, as well as tools
and apps to make these standards useful, is called &quot;Intermodal&quot;.</p>
<p>Seamless intermodal transportation, enabled by containerization, has led
to enormous efficiency gains in the transport of physical goods.</p>
<p>Before the invention of the humble 40' shipping container, and the
intermodal transportation network that it enabled, the majority of the
world's goods were transported as so-called
<a href="https://en.wikipedia.org/wiki/Break_bulk_cargo">bulk break cargo</a>.</p>
<p>Bulk break cargo is packed in bags, barrels, boxes, crates, and drums of
varying sizes. Loading such cargo onto a truck, cargo ship, or train
took labor and time, and was a major source of friction and cost in the
shipping of goods from place to place.</p>
<p>The invention and standardization of intermodal containers, the 20' and
40' shipping containers of today, changed all that. Cargo could now be
packed into uniformly sized containers of known strength and weight, of
a size suitable for transportation by train, truck, or ship. This
standardization made the once back-breaking work of moving cargo through
multiple transportation modes easy and fast. What once required teams of
stout men could now be done with cranes and other equipment.</p>
<p>In many ways, when it comes to decentralized digital content, we are
very much living in an era of bulk break cargo. Painstaking effort is
required to prepare content for transportation across different modes,
e.g. BitTorrent, the web, or Usenet; and it is either impossible or
takes complex heuristics to answer simple questions, like what <em>is</em> a
piece of content, anyways?</p>
<p>By standardizing metadata, we can make more efficient the conveyance of
digital content across different modes of transportation, and build rich
services on top of that content.</p>
<p>Thus, &quot;Intermodal&quot;.</p>
<h2><code>imdl</code></h2>
<p>I've been thinking about how to move the decentralized content ecosystem
forward for a long time, and until recently I've been stuck on the
question of what, exactly, to build first.</p>
<p>I've decided to start with a BitTorrent metainfo (that is to say,
<code>.torrent</code> file) creator. The first version is full of features and
niceties, and is ready for users today.</p>
<p>The binary is called <code>imdl</code>, and development is hosted
<a href="https://github.com/casey/intermodal">on GitHub</a>.</p>
<p>BitTorrent is widely used, and a torrent creator is much simpler than a
torrent client, tracker, or index, making it a good place to start.</p>
<p>Although <code>imdl</code> does not today have any groundbreaking new features, and
no functionality for creating metadata manifests, it is a natural place
to start adding such features.</p>
<p><code>imdl</code> is written in Rust. Rust is fast, correct, and makes it easy to
distribute self-contained binaries to users. Additionally, Rust can be
compiled to <a href="https://webassembly.org/">WebAssembly</a>, so bits of <code>imdl</code>
might eventually be adapted to run in the browser.</p>
<p>Over time, <code>imdl</code> will be extended with all manner of useful features,
so torrent-creation functionality lives under the <code>torrent</code> subcommand:
<code>imdl torrent create</code>, <code>imdl torrent verify</code>, <code>imdl torrent show</code>, and
so on.</p>
<p>I owe a huge debt of gratitude to the
<a href="https://imdl.io/book/bittorrent/metainfo-utilities.html">many existing open-source torrent creators</a>,
which have been a font of inspiration and good ideas. As part of the
process of developing this first release of <code>imdl</code>, I combed through
them for useful and requested features, and implemented all of them.</p>
<h2>What's next?</h2>
<p>First and foremost, I want <code>imdl</code> to be a useful torrent creator
<em>today</em>. If you find any bugs, or have feature requests, don't hesitate
to <a href="https://github.com/casey/intermodal/issues/new">open an issue</a> or
hop on <a href="https://discord.gg/HaaT5Qz">the discord</a>!</p>
<p>Contributions of code, documentation, clean up, tests, ideas, and
discussion are all welcome!</p>
<p>Many features, such as
<a href="https://github.com/casey/intermodal/issues/324">integrity checking</a>,
<a href="https://github.com/casey/intermodal/issues/325">signing</a>,
<a href="https://github.com/casey/intermodal/issues/323">timestamping</a>, and
<a href="https://github.com/casey/intermodal/issues/177">release metadata</a>
are gated on the basic design and implementation of the manifest, so
that will be the next major area of work.</p>
<p>Your feedback on the design and implementation of the manifest would be
very valuable.</p>
<p>Additionally, there are a bunch of more concrete
<a href="https://github.com/casey/intermodal/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22">good first issues</a>
on GitHub, some large, some small:</p>
<ul>
<li><a href="https://github.com/casey/intermodal/issues/9">Setting up code coverage on CI.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/92">Adding web seeds to torrents.</a>.</li>
<li><a href="https://github.com/casey/intermodal/issues/93">Adding another kind of web seeds to torrents.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/23">Supporting the addition of arbitrary keys to created torrents.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/36">Adding a config file containing profiles to use for torrent file creation.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/99">Adding support for generating file padding.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/124">Adding a  whole new subcommand to edit existing <code>.torrent</code> files.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/344">Fixing a no-doubt silly bug causing tests to leave behind <code>.torrent</code> files in <code>/tmp</code>.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/245">Adding file selections to magnet links.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/255">Creating <code>.torrent</code> files from magnet links.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/165">Verifying multiple <code>.torrent</code> files at a time.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/168">Showing nonstandard fields in <code>imdl torrent show</code>.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/174">Adding a <code>--quiet</code> flag to <code>imdl torrent create</code>.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/192">Showing corrupted piece information during verification.</a></li>
<li><a href="https://github.com/casey/intermodal/issues/101">Supporting BitTorrent V2 torrents.</a></li>
</ul>
<h2>And finally…</h2>
<p>Thank you so much for reading this rather long-winded blog post!</p>
<p><code>imdl</code>, modest though it may be, is a love letter to the Internet, to
sharing, and to BitTorrent. I hope you find it useful, and it becomes
even more useful in the future.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Css Box Model</title>
      <link>https://rodarmor.com/blog/css-box-model</link>
      <guid>https://rodarmor.com/blog/css-box-model</guid>
      <pubDate>2020-04-02</pubDate>
      <content:encoded><![CDATA[<p>This is the 200th time I have Googled &quot;CSS Box Model&quot; and I have become exceedling efficient at it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Monkey Dong</title>
      <link>https://rodarmor.com/blog/monkey-dong</link>
      <guid>https://rodarmor.com/blog/monkey-dong</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/monkey-dong/"><img src="/blog/monkey-dong/index.png" alt="monkey-dong" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Punished Jones</title>
      <link>https://rodarmor.com/blog/punished-jones</link>
      <guid>https://rodarmor.com/blog/punished-jones</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/punished-jones/"><img src="/blog/punished-jones/index.jpg" alt="punished-jones" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Programmer Art</title>
      <link>https://rodarmor.com/blog/programmer-art</link>
      <guid>https://rodarmor.com/blog/programmer-art</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/programmer-art/"><img src="/blog/programmer-art/index.gif" alt="programmer-art" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Yubikey Translation</title>
      <link>https://rodarmor.com/blog/yubikey-translation</link>
      <guid>https://rodarmor.com/blog/yubikey-translation</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/yubikey-translation/"><img src="/blog/yubikey-translation/index.png" alt="yubikey-translation" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Ethereum Development Process</title>
      <link>https://rodarmor.com/blog/ethereum-development-process</link>
      <guid>https://rodarmor.com/blog/ethereum-development-process</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/ethereum-development-process/"><img src="/blog/ethereum-development-process/index.png" alt="ethereum-development-process" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Democracy</title>
      <link>https://rodarmor.com/blog/democracy</link>
      <guid>https://rodarmor.com/blog/democracy</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p>All democracy gives you is this: People convince themselves that the best way to get what they want is by voting, lobbying, and running for office, and not with AK-47s in the streets.</p>
<p>Which, all things considered, is probably better than nothing.</p>
<p>But don't suck democracy's dick and expect good decisions, wise governance, and functional laws to shoot out of it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>No There There</title>
      <link>https://rodarmor.com/blog/no-there-there</link>
      <guid>https://rodarmor.com/blog/no-there-there</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/no-there-there/"><img src="/blog/no-there-there/index.png" alt="no-there-there" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Bonded Matzot</title>
      <link>https://rodarmor.com/blog/bonded-matzot</link>
      <guid>https://rodarmor.com/blog/bonded-matzot</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p>I happened to visit these pages one after the other:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=IvcPSImWxJA">Making Shmurah Matzah</a></li>
<li><a href="https://en.wikipedia.org/wiki/Bonded_warehouse">Bonded warehouse</a></li>
</ul>
<p>The similarity is striking.</p>
<p>In a matzoh factory, batches of matzot are prepared within 18 minute
time periods, after which all implements used to prepare the matzot are
meticulously cleaned. This is because, in order to be halachically
correct, matzot must not undergo fermentation, and 18 minutes is the
time after which fermentation is presumed to have occurred.</p>
<p>In a bonded warehouse, goods may,</p>
<blockquote>
<p>under supervision by the customs authority, be manipulated by
cleaning, sorting, repacking, or otherwise changing their condition by
processes that do not amount to manufacturing.</p>
</blockquote>
<p>In both spaces, strict rules limit activities to arbitrary thresholds.</p>
<p>Water and flour may be mixed, but must be baked within 18 minutes,
otherwise fermentation will be deemed to have occurred.</p>
<p>Goods may be cleaned, sorted, and repacked, but not more, otherwise
manufacturing will be deemed to have occurred.</p>
<p>Both spaces exist to satisfy rules ostensibly handed down by higher
powers, namely God and The State.</p>
<p>Hopefully such cursed spaces can be contained within their current
boundaries, and further superstitious contamination can be avoided.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Anarcho Catbus Peacetime Flag</title>
      <link>https://rodarmor.com/blog/anarcho-catbus-peacetime-flag</link>
      <guid>https://rodarmor.com/blog/anarcho-catbus-peacetime-flag</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/anarcho-catbus-peacetime-flag/"><img src="/blog/anarcho-catbus-peacetime-flag/index.png" alt="anarcho-catbus-peacetime-flag" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Mars Surface Composite</title>
      <link>https://rodarmor.com/blog/mars-surface-composite</link>
      <guid>https://rodarmor.com/blog/mars-surface-composite</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/mars-surface-composite/"><img src="/blog/mars-surface-composite/index.jpg" alt="mars-surface-composite" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Cyberpunk Rust</title>
      <link>https://rodarmor.com/blog/cyberpunk-rust</link>
      <guid>https://rodarmor.com/blog/cyberpunk-rust</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/cyberpunk-rust/"><img src="/blog/cyberpunk-rust/index.png" alt="cyberpunk-rust" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Anarcho Catbus Wartime Flag</title>
      <link>https://rodarmor.com/blog/anarcho-catbus-wartime-flag</link>
      <guid>https://rodarmor.com/blog/anarcho-catbus-wartime-flag</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/anarcho-catbus-wartime-flag/"><img src="/blog/anarcho-catbus-wartime-flag/index.png" alt="anarcho-catbus-wartime-flag" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Ideal Male Body</title>
      <link>https://rodarmor.com/blog/ideal-male-body</link>
      <guid>https://rodarmor.com/blog/ideal-male-body</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/ideal-male-body/"><img src="/blog/ideal-male-body/index.jpg" alt="ideal-male-body" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Ixr</title>
      <link>https://rodarmor.com/blog/ixr</link>
      <guid>https://rodarmor.com/blog/ixr</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<video controls>
  <source src="/blog/ixr/index.mp4" type="video/mp4">
</video>
]]></content:encoded>
    </item>
    <item>
      <title>Gibberabberator</title>
      <link>https://rodarmor.com/blog/gibberabberator</link>
      <guid>https://rodarmor.com/blog/gibberabberator</guid>
      <pubDate>2020-04-04</pubDate>
      <content:encoded><![CDATA[<audio controls="controls">
  <source type="audio/mp3" src="/blog/gibberabberator/index.mp3">
</audio>
]]></content:encoded>
    </item>
    <item>
      <title>Spicy Chart</title>
      <link>https://rodarmor.com/blog/spicy-chart</link>
      <guid>https://rodarmor.com/blog/spicy-chart</guid>
      <pubDate>2020-04-06</pubDate>
      <content:encoded><![CDATA[<p>BTC chart lookin' spicy 👀👀👀</p>
<p><a href="/blog/spicy-chart/"><img src="/blog/spicy-chart/index.png" alt="spicy-chart" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Usg</title>
      <link>https://rodarmor.com/blog/usg</link>
      <guid>https://rodarmor.com/blog/usg</guid>
      <pubDate>2020-04-06</pubDate>
      <content:encoded><![CDATA[<p>USG was always this this incompetent, this inefficient, this craven, this
self-serving. It just needed external stresses requiring a competent response
to reveal the extent of its functional bankruptcy.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Just Hack</title>
      <link>https://rodarmor.com/blog/just-hack</link>
      <guid>https://rodarmor.com/blog/just-hack</guid>
      <pubDate>2020-04-06</pubDate>
      <content:encoded><![CDATA[<p><a href="https://github.com/casey/just/">Just</a> is a general-purpose command runner written in Rust with a
<a href="https://en.wikipedia.org/wiki/Make_(software)"><code>make</code></a>-like syntax.</p>
<p>If you're interested in hacking on <code>just</code>, I'd love to help!</p>
<p>Just is fun to work on, for a few reasons:</p>
<ul>
<li>
<p>It's a language! Languages are just inherantly fun, since they're an intersection of design,
aesthetics, UX, and engineering. Just has all sorts of the bits that you'd
expect:</p>
<ul>
<li>
<p>A nice, character at-a-time parser</p>
</li>
<li>
<p>A somewhat disgusting recursive descent parser</p>
</li>
<li>
<p>An abstract syntax tree</p>
</li>
<li>
<p>Bunches of static error checking and name resolution</p>
</li>
<li>
<p>Pretty error messages</p>
</li>
</ul>
</li>
<li>
<p>It has a ton of users! It's really fun to implement features, and then see them get used in
real justfiles written by real random internet people</p>
</li>
<li>
<p>It has a ton of tests! The copious amount of both unit and integration tests often save me
from shipping bugs, and make refactoring and feature work much easier.</p>
</li>
<li>
<p>There is always more work to do! Just users ask for crazy things all the time. Sometimes
someone will create an issue, and I'll think to myself, &quot;WTF this person is crazy for wanting
that.&quot;, and then eventually I'll start to accept the idea that it's a good feature, and then I'll
finally implement it and everyone will be hapy.</p>
</li>
</ul>
<p>Check out the
<a href="https://github.com/casey/just/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22">good first issues</a>
and hit me up on <a href="https://discord.gg/SK6f6ns">the discord</a>!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Intermodal Container Ship</title>
      <link>https://rodarmor.com/blog/intermodal-container-ship</link>
      <guid>https://rodarmor.com/blog/intermodal-container-ship</guid>
      <pubDate>2020-04-06</pubDate>
      <content:encoded><![CDATA[<p><a href="/blog/intermodal-container-ship/"><img src="/blog/intermodal-container-ship/index.jpg" alt="intermodal-container-ship" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Breath Of The Blank Banshee</title>
      <link>https://rodarmor.com/blog/breath-of-the-blank-banshee</link>
      <guid>https://rodarmor.com/blog/breath-of-the-blank-banshee</guid>
      <pubDate>2020-04-07</pubDate>
      <content:encoded><![CDATA[<iframe width="560" height="315" src="https://www.youtube.com/embed/yvO5JO5ReHY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
]]></content:encoded>
    </item>
    <item>
      <title>Discontinuity</title>
      <link>https://rodarmor.com/blog/discontinuity</link>
      <guid>https://rodarmor.com/blog/discontinuity</guid>
      <pubDate>2020-04-08</pubDate>
      <content:encoded><![CDATA[<div class="center">Nature abhors a discontinuity.</div>
]]></content:encoded>
    </item>
    <item>
      <title>2XXX: The Unknowable Future</title>
      <link>https://rodarmor.com/blog/2xxx</link>
      <guid>https://rodarmor.com/blog/2xxx</guid>
      <pubDate>2020-04-16</pubDate>
      <content:encoded><![CDATA[<iframe width="560" height="315" src="https://www.youtube.com/embed/NP7GFIUsIfw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
]]></content:encoded>
    </item>
    <item>
      <title>Mcmahon Durag</title>
      <link>https://rodarmor.com/blog/mcmahon-durag</link>
      <guid>https://rodarmor.com/blog/mcmahon-durag</guid>
      <pubDate>2020-04-19</pubDate>
      <content:encoded><![CDATA[<p><a href="https://rodarmor.com/blog/mcmahon-durag/"><img src="https://rodarmor.com/blog/mcmahon-durag/index.png" alt="mcmahon-durag" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Uninsurance</title>
      <link>https://rodarmor.com/blog/uninsurance</link>
      <guid>https://rodarmor.com/blog/uninsurance</guid>
      <pubDate>2020-04-21</pubDate>
      <content:encoded><![CDATA[<p>From Scott Alexander on
<a href="https://slatestarcodex.com/2020/04/20/the-amish-health-care-system/">the Amish health care system</a>:</p>
<blockquote>
<p>The Muslims claim Mohammed was the last of the prophets, and that after his
death God stopped advising earthly religions. But sometimes modern faiths
will make a decision so inspired that it could only have come from divine
revelation. This is how I feel about the Amish belief that health insurance
companies are evil, and that good Christians must have no traffic with them.</p>
</blockquote>
<p>The post is about the advantages of the Amish health care system, which seems
to have much lower costs and equal effectiveness when compared to conventional
American health insurance centered health care.</p>
<p>The post is gripping (well, at least if you're interested in why American
health care is so expensive), so I recommend reading it. But briefly, the Amish
seem to have much lower costs with the same quality of care due to:</p>
<ul>
<li>Bargaining collectively.</li>
<li>Getting a discount because they have a reputation for paying their bills on
time.</li>
<li>Not going to the doctor for little things.</li>
<li>Not suing doctors, and thus not getting excessive medical care because a
doctor is trying to avoid a malpractice lawsuit.</li>
<li>Aid and cost sharing being run as nonprofits.</li>
<li>Keeping administrative expenses low.</li>
<li>Not taking risks with their health.</li>
<li>Avoiding excessive spending, because costs are shared by the community.</li>
</ul>
<p>I wonder if much of this could be replicated with, not an insurance plan, but,
something else… an &quot;uninsurance plan&quot;:</p>
<ul>
<li>
<p>The uninsurance company would not directly or indirectly cover any medical
expenses. This would make it very cheap.</p>
</li>
<li>
<p>The uninsurance company would bargain collectively on behalf of its members.</p>
</li>
<li>
<p>Uninsurance members that did not pay their medical bills in a timely fashion
would be kicked from the plan and be ineligible to rejoin.</p>
</li>
<li>
<p>Uninsurance members would be forbidden from suing for medical malpractice
except in cases of gross negligence. (Unsure about this one, since it seems
to open up members to abuse, but if it's a net benefit, why not?)</p>
</li>
<li>
<p>Provide members with a health savings account. Health savings accounts are
tax-advantaged savings accounts that allow members to pay for qualifying
medical expenses from the account. Although the Amish don't have HSAs, giving
members access to an HSA should be cheap, and so shouldn't increase the cost
of uninsurance. Additionally, since it is the member's own money, it doesn't
introduce any perverse incentives.</p>
</li>
<li>
<p>Give members access to the negotiated price lists up-front, to allow and
encourage them to comparison shop. This might be tough, because health care
providers keep these prices secret, so they can play hard ball with insurance
companies that they negotiate with. But, being able to see what you're going
to pay for something is a prerequisite to trying to save money and shop
around, so this would be ideal.</p>
</li>
<li>
<p>The uninsurance company would be run as a nonprofit, or public benefit
company.</p>
</li>
<li>
<p>Since the uninsurance plan is not insurance, it would be uncomplicated to
supplement it with an additional insurance, cost-sharing, or risk pooling,
scheme to cover unexpected costs, similar to Amish Hospital Aid. This
additional scheme would not be run by or affiliated with the uninsurance
plan, in order to avoid increasing costs for non-participants.</p>
</li>
</ul>
<p>I suspect that such a plan would be very cheap, to make a number up, perhaps no
more than $10 per month. If it were only $10 per month, and members got an HSA,
they might want to join just for that. And, if they got insurance-negotiated
rates when paying out-of-pocket while being uninsured, the would almost
certainly be willing to pay for it.</p>
<p>Such an uninsurance plan would encourage consumers to plan ahead, shop around,
and save for medical expenses in their HSA, maybe giving them health care
approaching that of the Pennsylvania Dutch.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Lexiclean</title>
      <link>https://rodarmor.com/blog/lexiclean</link>
      <guid>https://rodarmor.com/blog/lexiclean</guid>
      <pubDate>2020-04-22</pubDate>
      <content:encoded><![CDATA[<p>I just published a simple crate that performs lexical path cleaning: <a href="https://github.com/casey/lexiclean">lexiclean</a>.</p>
<p>Lexical path cleaning simplifies paths by removing <code>.</code>, <code>..</code>, and double separators: <code>//</code>, without querying the filesystem. It is inspired by Go's <a href="https://golang.org/pkg/path/#Clean">Clean</a> function, and differs from the Go version by not removing <code>.</code> if that is the only path component left.</p>
<p>I implemented this for a <a href="https://github.com/casey/intermodal/">command line utility</a> I'm working on, but split it off so others could use it.</p>
<p>There are a few reasons I prefer lexical path cleaning to <code>fs::canonicalize</code>:</p>
<ul>
<li>
<p>If the input is a relative path, the output will be a relative path. This means that if the input is a path the user typed, and the output path is displayed in an error message, the message is more likely to make sense to the user, since it will more obviously relate to the input path.</p>
</li>
<li>
<p>It simplifies <code>some-file/..</code> to <code>.</code> without any fuss, even if <code>some-file</code> is not a directory.</p>
</li>
<li>
<p>It never returns an error, because it makes no system calls.</p>
</li>
</ul>
<p>There are some reasons you might prefer <code>fs::canonicalize</code>:</p>
<ul>
<li>
<p><code>fs::canonicalize</code> respects symlinks.</p>
</li>
<li>
<p><code>fs::canonicalize</code> always returns an absolute path. (Although you can do <code>std::env::current_dir().join(path).lexiclean()</code> if you want an absolute path.)</p>
</li>
</ul>
<p>Are there any other reasons to prefer one over the other? I'd love to hear them!</p>
<p>It is very lightly tested! If you intend to use it, I encourage you to submit additional tests containing paths you might encounter, if you think the existing tests don't cover them. In particular, I haven't thought about all the exotic prefixes that Windows paths might be adorned with, so there might be bugs there.</p>
<p>I don't expect to modify the crate or add features to it beyond what I need for my own purposes, so if there are additional features you want, please consider opening a PR! Of course, if you find a bug, I will happily fix it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Big Biscuit</title>
      <link>https://rodarmor.com/blog/big-biscuit</link>
      <guid>https://rodarmor.com/blog/big-biscuit</guid>
      <pubDate>2020-05-02</pubDate>
      <content:encoded><![CDATA[<p>GIMME THAT BIG BISCUIT SHREDDED WHEAT BOM BOM BOM THAT BIG BISCUIT SHREDDED WHEAT
<a href="https://rodarmor.com/blog/big-biscuit/"><img src="https://rodarmor.com/blog/big-biscuit/index.jpg" alt="big-biscuit" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Autonomous Consensus</title>
      <link>https://rodarmor.com/blog/autonomous-consensus</link>
      <guid>https://rodarmor.com/blog/autonomous-consensus</guid>
      <pubDate>2020-05-23</pubDate>
      <content:encoded><![CDATA[<p>I feel like BGP would be a great place to experiment with PKI systems, possibly
with some additional global consensus mechanism.</p>
<ul>
<li>
<p>BGP has well known security flaws that cause real problems. It is very common
that misconfigured or malicious route advertisements cause outages or
redirect traffic to an attacker. (C.f. BGP hijacking against Bitcoin miners.)</p>
<p>Some kind of PKI system which let AS operators associate one or more public
keys with their AS, and handled transfers of IP space between ASs, would
allow BGP updates to be signed by the AS owner's key and totally eliminate
this class of vulnerability.</p>
<p>Additionally, it would allow ASs to end-to-end encrypt and authenticate
BGP communications. BGP updates aren't exactly sensitive, but why not, ya
know?</p>
</li>
<li>
<p>There are around 60,000 ASs in existence, so a modest 7 tx/second message rate would
be enough to process an update to each one 10 times every day. If the purpose
of the network were just to handle public key updates, likely only a small
fraction of this would be needed for routine and emergency key updates.</p>
<p>There are 837,482 IP prefixes, so these could be turned over once every 1.5
days or so. IP blocks move relatively infrequently, like AS keys would, so
this is probably</p>
</li>
<li>
<p>AS operators are usually well funded, and have ready access to compute,
network, rackspace, and skilled humans. If running some kind of box with
not-totally-crazy resource and maintenance requirements marginally increased
their security, they would all do it.</p>
</li>
<li>
<p>AS operators have a high degree of control over their network peering
relationships, and many large networks have direct physical connections to
multiple other ASs. This mitigates the risk of partitioning and starvation
attacks somewhat.</p>
</li>
<li>
<p>There is a high degree of cooperation, goodwill, and existing relationships
between AS operators. This makes me wonder if schemes that I usually see as
not fit for use in cryptocurrency contexts, like Ripple-style consensus
systems, might actually work in the AS context. Ripple has no credible
mechanism to deal with consensus failure if network operators disagree on the
state of the network, and there are many incentives that might cause Ripple
network operators to disagree on network state. However, in the AS context,
there is little reason for network operators to disagree, and they are highly
motivated to such disagreements out of band.</p>
</li>
<li>
<p>Maybe no global consensus mechanism is necessary, and some kind of simple PKI
would be good enough! However, it would be very nice if the current network
consensus could be summed up in a small amount of data , such that it would be
easy and low-bandwidth to discover if you were out of sync with the network,
or being partitioned in the case of single-homed networks.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Just: How I Organize Large Rust Programs</title>
      <link>https://rodarmor.com/blog/tour-de-just</link>
      <guid>https://rodarmor.com/blog/tour-de-just</guid>
      <pubDate>2020-05-24</pubDate>
      <content:encoded><![CDATA[<p>One of the things that I personally struggled with when learning Rust was how
to organize large programs with multiple modules.</p>
<p>In this post, I'll explain how I organize the codebase of
<a href="https://github.com/casey/just/"><code>just</code></a>, a command runner that I wrote.</p>
<p><code>just</code> was the first large program I wrote in Rust, and its organization has
gone through many iterations, as I discovered what worked for me and what
didn't.</p>
<p>There are some things that could use improvement, and many of the choices I
made are somewhat strange, so definitely don't consider the whole project a
normative example of how to write rust.</p>
<h2>Overview</h2>
<p>Users mostly interact with <code>just</code> by running the main binary from the command
line.</p>
<p>However, the crate actually consists of an executable target, in
<a href="https://github.com/casey/just/blob/master/src/main.rs">src/main.rs</a>, and a
library in <a href="https://github.com/casey/just/blob/master/src/lib.rs">src/lib.rs</a>.
The <code>main</code> function in <code>main.rs</code> is a thin wrapper that calls the <code>run</code> function in
<a href="https://github.com/casey/just/blob/master/src/run.rs">src/run.rs</a>.</p>
<p>The reason that <code>just</code> is split into a executable target and a library target
is because there is a fuzz tester in
<a href="https://github.com/casey/just/tree/master/fuzz">fuzz</a>, and a regression
testing framework at <a href="https://github.com/casey/janus">janus</a>, and both of these
use testing functions exposed by the library.</p>
<h2>Submodule Organization</h2>
<p>I prefer to keep my module tree flat, so you'll notice that all my source files
are directly under <a href="https://github.com/casey/just/blob/master/src/">src</a>. I
find that this makes it easy to remember what's where, since I don't need to
remember what subdirectory each source file is in.</p>
<p>I use a fuzzy file searcher, <a href="https://github.com/junegunn/fzf">fzf</a>, to switch
between files, so having a ton of files in my <code>src</code> directory doesn't bother
me. If I used a tree-based file viewer in my editor, I might prefer to group
modules into directories by topic.</p>
<h2>Common Use Statements</h2>
<p>I prefer to group all my <code>use</code> statements together in a single file called
<a href="https://github.com/casey/just/blob/master/src/common.rs">src/common.rs</a>.</p>
<p>Then, at the top of every other file, I include them all with
<code>use crate::common::*;</code>.</p>
<p>I think this is somewhat uncommon, and most people prefer to put <code>use</code>
statements at the top of every file, with just those things used in that
particular file.</p>
<p>Both approaches are totally reasonable. I find that grouping use statements
into a single file saves a lot of duplication at the top of every file, and
makes it easy to start a new file, since you can just write <code>use crate::common::*;</code> and have everything you need in scope.</p>
<p>This does require that I pick unique names for everything that I want to put in
<code>common.rs</code>, but I haven't found that to be particularly burdensome.</p>
<h2>Submodule Names and Contents</h2>
<p>Most modules contain a single definition, either a function, trait, struct, or
enum, that is used in the rest of the codebase. These modules are all named
after the public definition, and that definition is exported in <code>common.rs</code>,
so <code>use crate::common::*;</code> will bring that definition into scope, without needing to
qualify it with the module name.</p>
<p>As an example, <code>just</code>'s lexer is called <code>Lexer</code>, and is in
<a href="https://github.com/casey/just/blob/master/src/lexer.rs">src/lexer.rs</a>.</p>
<p>In <code>common.rs</code>, it is exported with <code>pub(crate) use lexer::Lexer;</code>.</p>
<p>Since modules are always named after their sole export, it's pretty easy to
figure out where something comes just from the name. Since <code>Lexer</code> is a type
from <code>just</code>, and not a dependency, that means that it's probably defined in
<code>lexer.rs</code>.</p>
<p>A few modules, like
<a href="https://github.com/casey/just/blob/master/src/keyword.rs">src/keyword.rs</a>,
contain more than one thing. For modules like that, <code>common.rs</code> just exports
the module itself, with <code>pub(crate) use crate::keyword;</code>, and the module name
is used when referring to the definitions inside <code>keyword</code>, like
<code>keyword::EXPORT</code>.</p>
<p>If a name is from a dependency, then you can see where it comes from in
<code>common.rs</code>.</p>
<h2>Error Handling</h2>
<p>For testing purposes, I like to use error enums, instead of <code>Box&lt;dyn Error</code>, or
equivalent. I find that this makes it easy to write tests that look for
specific errors. Also, <code>just</code> has detailed error messages, and this lets me
separate error message formatting from error value generation.</p>
<p>There are two main kinds of errors, <code>CompilationError</code>, in
<a href="https://github.com/casey/just/blob/master/src/compilation_error.rs">src/compilation_error.rs</a>,
and <code>RuntimeError</code>, in
<a href="https://github.com/casey/just/blob/master/src/runtime_error.rs">runtime_error.rs</a>.</p>
<p>As you can guess, <code>CompilationError</code> is for problems related to compilation,
e.g. lexing, parsing, and analyzing a justfile, and <code>RuntimeError</code> is for
problems that occur when running a justfile, e.g. I/O errors and command
execution errors.</p>
<p>I currently don't use any of the many error handling helper crates, but in
other projects I use <a href="https://github.com/shepmaster/snafu/">snafu</a>, and if I
were to rewrite <code>just</code>, I would definitely use <code>snafu</code>.</p>
<h2>Clippy</h2>
<p>I use <a href="https://github.com/rust-lang/rust-clippy">clippy</a>, the animate
paperclip/rust linter, to automatically check the codebase for issues.</p>
<p>Clippy has many lints that are either pedantic, or which restrict things that
are totally reasonable in many contexts. I like a lot of these, but I didn't
want to go through all of them and decide which lints to enable, so I turned on
<em>all</em> the lints, even the annoying ones, and then just disable lints that I
don't like as I encounter them.</p>
<p>You can see this at the top of
<a href="https://github.com/casey/just/blob/master/src/lib.rs">src/lib.rs</a>.</p>
<h2>How does it work?</h2>
<p><code>just</code> does a lot of stuff! This makes it hard to give a concise overview of
how everything works, but I'll do my best!</p>
<h3>Run</h3>
<p>The <code>run</code> function is pretty short, so definitely check it out. It's in
<a href="https://github.com/casey/just/blob/master/src/run.rs">src/run.rs</a>. It does
some setup, like initializing Windows terminal color support and logging, then
parses the command line arguments.</p>
<h3>Configuration</h3>
<p>Just calls parsed command line arguments a <code>Config</code>. The command line arguments
are parsed with the venerable <a href="https://github.com/clap-rs/clap">clap</a>, and then
stored in a <code>Config</code> struct, which is passed around the rest of the program.</p>
<p>Everything related to setting up the clap parser, and parsing the command line
arguments is in
<a href="https://github.com/casey/just/blob/master/src/config.rs">src/config.rs</a>.</p>
<h3>Subcommand Running</h3>
<p><code>just</code> has a few distinct modes it can run in, e.g. actually running a recipe
in a justfile, listing the recipes in a justfile, or evaluating the variables
in a justfile. These are called subcommands, and you can see the different
subcommands in the <code>Subcommand</code> enum in
<a href="https://github.com/casey/just/blob/master/src/subcommand.rs">src/subcommand.rs</a>.</p>
<p>Once a config is parsed, the function <code>run_subcommand</code> in <code>config.rs</code> handles
executing the correct subcommand.</p>
<p>For the rest of this post, I'll cover <code>Subcommand::Run</code>, which is the
subcommand which is responsible for actually running a justfile.</p>
<h3>Compilation</h3>
<p>The justfile source is read and the compiler is invoked in the <code>run_subcommand</code>
function in <code>config.rs</code>. The <code>Compiler</code> is defined in
<a href="https://github.com/casey/just/blob/master/src/compiler.rs">src/compiler.rs</a>,
and has a single short method that calls the lexer, the parser, and the
analyzer.</p>
<p>There's no particular reason for having a <code>Compiler</code> struct, since it doesn't
have any fields, so it's really just for organization. I would be totally fine
with having a module <code>src/compile.rs</code>, and just exporting a single <code>compile</code>
function from that module.</p>
<h3>Lexing</h3>
<p>The first step of compilation is to split the source text into tokens, which is
done by the <code>Lexer</code> in
<a href="https://github.com/casey/just/blob/master/src/lexer.rs">src/lexer.rs</a>. The
lexer looks a lot like a recursive descent parser. It has a bunch of different
methods, and those methods call each other to produce the different tokens.</p>
<p>The entry-point to the lexer is <code>Lexer::lex</code>.</p>
<p><code>Lexer</code> is relatively well-commented, so please take a look if you're
interested!</p>
<h3>Tokens</h3>
<p>The lexer produces a <code>Vec</code> of <code>Token</code>s. The <code>Token</code> type is in
<a href="https://github.com/casey/just/blob/master/src/token.rs">src/token.rs</a>. Each
<code>Token</code> contains a <code>TokenKind</code>, defined in
<a href="https://github.com/casey/just/blob/master/src/token_kind.rs">src/token_kind.rs</a>.
A <code>Token</code> contains a reference to the soruce program, as well as information
about the offset, length, line, and column of the token. A <code>TokenKind</code> tells
you what kind of token it actually is.</p>
<h3>Parsing</h3>
<p>The <code>Token</code>s produced by the <code>Lexer</code> are passed to a <code>Parser</code>, defined in
<a href="https://github.com/casey/just/blob/master/src/parser.rs">src/parser.rs</a>, and
the main entry point is <code>Parser::parse</code>.</p>
<p>The parser is a recursive descent parser that walks over the tokens, figuring
out what kind of construct it's parsing as it goes.</p>
<h3>Modules</h3>
<p>The output of the parser is a <code>Module</code>, defined in
<a href="https://github.com/casey/just/blob/master/src/module.rs">src/module.rs</a>. A
<code>Module</code> represents a successful parse, but has not been fully validated. Just
does a lot of static analysis, like resolving names, inter-recipe dependencies,
and inter-variable dependencies, so not every <code>Module</code> is valid.</p>
<p>You can think of a <code>Module</code> as being like an
<a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a>, that still hasn't
been statically analyzed for correctness. Inside a <code>Module</code> are <code>Items</code>
(<a href="https://github.com/casey/just/blob/master/src/item.rs">src/item.rs</a>), which
contain the different source constructs, like <code>Alias</code>, <code>Assignment</code>,
<code>UnresolvedRecipe</code>, and <code>Set</code>.</p>
<h3>Analysis</h3>
<p>The next phase of compilation is analysis, performed by the <code>Analyzer</code>, defined
in
<a href="https://github.com/casey/just/blob/master/src/analyzer.rs">src/analyzer.rs</a>.</p>
<p>The <code>Analyzer</code> makes sure that all references to recipes and variables can be
resolved, and that there are no circular dependencies.</p>
<h3>Justfile</h3>
<p>The output of the <code>Analyzer</code> is a <code>Justfile</code>, defined in
<a href="https://github.com/casey/just/blob/master/src/justfile.rs">src/justfile.rs</a>.</p>
<p>A <code>Justfile</code> represents a parsed and analyzed justfile. It contains all the
recipes, variables, and expressions, all resolved and ready to run. It is the
<em>totus porcus</em>, as it were.</p>
<h3>Running</h3>
<p>A justfile is run with <code>Justfile::run</code>, which takes a <code>Config</code>, a <code>Search</code> with
information about where the justfile is and where the working directory is,
variable overrides passed on the command line, and a list of arguments.</p>
<p>The arguments are parsed into recipes and arguments to those recipes, and
finally those recipes are run with <code>Justfile::run_recipe</code>, which actually
executes each recipe, and all dependencies.</p>
<h3>Testing</h3>
<p><code>just</code> takes files, parses commands out of those files, and then runs them. I
am acutely aware of how this might go wrong, and would feel <em>real bad</em> if
<code>just</code> somehow got confused and ran a command that nuked someone's hard drive.</p>
<p>Because of this, I go pretty crazy with testing. There are four kinds of tests:
unit tests, integration tests, fuzz testing, and ecosystem-wide regression
testing.</p>
<h4>Unit Testing</h4>
<p>Unit tests are spread around the codebase, in submodules named <code>tests</code>. Each
<code>tests</code> submodule contains tests for whatever's in the containing module.</p>
<p>I'm not strict about covering everything with unit tests, but I do cover
everything with integration tests. If something doesn't seem to be tested in a
unit test, it's probably tested in an integration test.</p>
<h4>Integration Testing</h4>
<p>Integration tests are in the
<a href="https://github.com/casey/just/tree/master/tests">tests</a> subdirectory, roughly
organized by topic. The vast majority are in
<a href="https://github.com/casey/just/blob/master/tests/integration.rs">tests/integration.rs</a>,
which test a full run of the <code>just</code> binary, supplying standard input, args, and
a justfile, and checking that standard output, standard error, and the exit
code are correct.</p>
<h4>Fuzz Testing</h4>
<p>Fuzz testing was contributed to <code>just</code> by
<a href="https://github.com/RadicalZephyr">@RadicalZephyr</a>, and is located in the
<a href="https://github.com/casey/just/tree/master/fuzz">fuzz</a> directory. It generates
random strings and feeds them to the parser. (NOT THE RUNNER, DEFINITELY NOT
THE RUNNER.) If the parser succeeds or returns an error, that's a successful
run. If the fuzzer is able to trigger a panic, then it's found a bug that needs
to be fixed.</p>
<h4>Regression Testing</h4>
<p>Since a lot of people have written
<a href="https://github.com/search?o=desc&amp;q=filename%3Ajustfile&amp;s=indexed&amp;type=Code">a lot of justfiles</a>,
I want to make sure I don't break them when I update <code>just</code>.</p>
<p>To do this, I wrote a tool called <a href="https://github.com/casey/janus">janus</a>.
Janus is inspired by Rust's <a href="https://github.com/rust-lang/crater">crater</a>.</p>
<p>Janus downloads all the justfiles that it can find on GitHub, and then compares
how two versions of <code>just</code> compiles those justfiles. The two versions of <code>just</code>
are usually the latest release, and a new version with a big, scary change.</p>
<p>Janus compiles all justfiles with both versions, and then compares the result.
Ideally, every valid justfiles parses into the same <code>Justfile</code> with both
versions, and every justfile with an error produces the same error.</p>
<h3>Wrapping Up</h3>
<p>That's everything I can think of! Ultimately, much of how you organize your
Rust programs comes down to personal preference, so just start mashing the
keyboard, see what works, and iterate on whatever doesn't.</p>
<p>glhf!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Applescript</title>
      <link>https://rodarmor.com/blog/applescript</link>
      <guid>https://rodarmor.com/blog/applescript</guid>
      <pubDate>2020-11-17</pubDate>
      <content:encoded><![CDATA[<p>I wrote a
<a href="https://github.com/casey/local/blob/master/music/Merge.applescript">nontrivial AppleScript</a>
to merge duplicates in my iTunes library.</p>
<p>It is easily the most gruesome thing I have ever written.</p>
<p>Some things of notes:</p>
<ul>
<li>
<p>I had to write my own function to sort lists.</p>
</li>
<li>
<p>I had to write my own function to split strings.</p>
</li>
<li>
<p>AppleScript has records, which are like dictionaries, except they do not
support dynamic properties. Consider that. You can do <code>{foo: 1}</code> to create
something that is morally equivalent to <code>{&quot;foo&quot;: 1}</code>. But what do you do if
you want to use a property name that's in a variable?</p>
<p>In AppleScript, you cannot. You can only wail and gnash your teeth.</p>
<p>This lack of dynamic property access meant that I couldn't use records at all
in my script, for which I suffered greatly.</p>
</li>
<li>
<p>There are vast numbers of predefined symbols with names that invariably
conflict with your own variables and functions. Somehow, AppleScript appears
to implement reverse lexical scoping, and these predefined symbols override
your own.</p>
</li>
<li>
<p>On a Mac, there are a large number of characters that are easy to type with
the option key. So, of course, <code>!=</code>, <code>&gt;=</code>, and <code>&lt;=</code>  can be written as <code>≠</code>,
<code>≥</code>, and <code>≤</code>, and</p>
</li>
<li>
<p>The inscrutable raw property accessor is written with <code>«class NAME»</code>. Yes,
those are double chevrons.</p>
</li>
<li>
<p>There is a line continuation character, but it is <code>¬</code>. (Option + L on a Mac
keyboard.)</p>
</li>
<li>
<p>Property access, <code>bar.foo</code>, can be written as <code>foo of bar</code> or <code>bar's foo</code>.
Except in some contexts, where only <code>foo of bar</code> is accepted. I have run into
these contexts many times, but I am still unable to predict them.</p>
</li>
<li>
<p>There are wholly optional keywords that can be used but do nothing. You can
use the word <code>the</code> in front of any expression, which does nothing.
<code>set the x to the 1</code> is exactly the same as <code>set x to 1</code>.</p>
</li>
<li>
<p>There are multiple ways to do almost everything. For example, you can define
a function with <code>to function(…)</code> or <code>on function(…)</code>.</p>
</li>
</ul>
<p>The language's smatterings of levity are, sadly, quickly overwhelmed by how
dysfunction it is.</p>
<p>Here are actual snippets of actual code that I actually had to write:</p>
<pre><code class="language-applescript">set AppleScript's text item delimiters to d
</code></pre>
<pre><code class="language-applescript">set l to s's every text item
</code></pre>
<pre><code class="language-applescript">set i_track to (item i of l)'s track number
</code></pre>
<pre><code class="language-applescript">to trash_file(l)
  do shell script &quot;mv &quot; &amp; ¬
    quoted form of POSIX path of (l as string) &amp; ¬
    &quot; &quot; ¬
    &amp; quoted form of POSIX path of (path to trash as string)
end
</code></pre>
<pre><code class="language-applescript">to cancel(m)
  display dialog m
  error number -128
end
</code></pre>
<pre><code class="language-applescript">set i to my split(f, &quot;.&quot;)'s first item as number
</code></pre>
<pre><code class="language-applescript">if n's length ≠ o's length
</code></pre>
<pre><code class="language-applescript">if p's visible and ¬
   p's special kind = none and ¬
   not p's genius and ¬
   not p's smart and ¬
   index of last track of p &lt; 1500
  set normal to normal &amp; {p}
end
</code></pre>
<pre><code class="language-applescript">set old_plays to old's «class pPlC»
</code></pre>
<pre><code class="language-applescript">delete (some track of library playlist 1 whose database ID is old_dbid)
</code></pre>
<pre><code class="language-applescript">repeat with i from 1 to count of n
  set old to item i of o
  set new to item i of n
  set oldid to old's persistent ID

  repeat with j from 1 to count of normal
    set p to item j of normal
    set ts to tracks of p
    repeat with k from 1 to count of ts
      set t to item k of ts
      if t's persistent ID = oldid
        delete t
        duplicate new to p
      end
    end
  end
end
</code></pre>
<p>This script should run instantly, but takes more than a minute when 10 tracks
are selected. This is because of the above triply nested <code>repeat</code> loop, which
loops over all the tracks I want to merge, all the playlists in my music
library, and all the tracks in those playlists. I had to do it this way because
I don't have any form of random access or dictionaries.</p>
<p>Even though the script is pretty simple, it still fails nondeterministically. I
am unable to determine what could make such a simple script fail, and
nondeterministically at that.</p>
<p>If hell has a programming language, it is definitely AppleScript.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Equitable Auction</title>
      <link>https://rodarmor.com/blog/equitable-auction</link>
      <guid>https://rodarmor.com/blog/equitable-auction</guid>
      <pubDate>2020-11-25</pubDate>
      <content:encoded><![CDATA[<p>The PS5 was released about a week ago, and, predictably, it is impossible to
get one. All retailers, online and IRL, are sold out. Of course, consoles are
available on Ebay at ruinous prices, so at least the scalpers are doing well.</p>
<p>Economists, of course, are wringing their hands and mumbling about Vickrey
auctions. What Sony should do, they mutter, is to hold a daily auction for
PS5s, and let the market decide the price.</p>
<p>The economists are, of course, quite right. If Sony auctioned off PS5s there
would be no lines, no scalpers, and no uncertainty. You could put in a bid at
the price that you wanted to pay, and then simply wait until demand had died
down for your bid to be filled. As a bonus, Sony would make more money for
producing something that people wanted to buy, and more capital to ramp up
production.</p>
<p>Unfortunately, the economists don't get their say here, because of their arch
enemy, non-economists. Non-economists, or, normal people, as they are otherwise
known, as far as I can tell, don't understand that there is such a thing as an
inescapable trade-off. They want everyone to get a PS5, everyone to pay MSRP
for it, there to be no scalpers, nobody to ever make a profit from demand
exceeding supply, and all things to be fair, based on confused and
self-contradictory conceptions of unfairness.</p>
<p>So, companies can't hold auctions for scarce goods, and have to set an MSRP,
produce whatever they can, and hope for the best.</p>
<p>I wonder though, if there might be some way for a company to hold an auction
for their products, but in a way that would be perceived as fair.</p>
<p>Here is one possible setup for such an auction, using Sony as the example
company, and the PS5 as the example product:</p>
<ul>
<li>
<p>Sony sets the MSRP of the PS5, $499.</p>
</li>
<li>
<p>Sony produces PS5s, and every day holds an auction for that day's production.
Losing bids roll over to the next day's auction.</p>
</li>
<li>
<p>Every time a PS5 is sold for more than the MSRP, the difference is added to
a <em>reserve pool</em>.</p>
</li>
<li>
<p>Every time a PS5 sells for less than the MSRP, that difference is subtracted
from the reserve pool.</p>
</li>
<li>
<p>Auctions continue whenever the reserve pool has a positive balance, or demand
is higher than supply.</p>
</li>
</ul>
<p>Essentially, any time someone pays over MSRP for a PS5, they ensure that
eventually, someone will get a PS5 for less than MSRP. If someone rich or
impatient buys a PS5 for $1000, two less impatient  people can eventually buy
PS5s for $250.</p>
<p>I think, perhaps, this would be perceived as fair. But, with real people, you
never know.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Advice For Programmers</title>
      <link>https://rodarmor.com/blog/advice-for-programmers</link>
      <guid>https://rodarmor.com/blog/advice-for-programmers</guid>
      <pubDate>2020-12-01</pubDate>
      <content:encoded><![CDATA[<p>In an October 1935 article in Esquire. Hemingway offers this advice to a young writer:</p>
<blockquote>
<p>The best way is always to stop when you are going good and when you know what
will happen next. If you do that every day when you are writing a novel you
will never be stuck. That is the most valuable thing I can tell you so try to
remember it.</p>
</blockquote>
<p>Reformulated for programmers and equally valuable:</p>
<blockquote>
<p>The best way is aways to stop when you are going good and you have just
written a failing test. If you do that every day when you are writing a
program you will never be stuck. That is the most valuable thing I can tell
you so try to remember it.</p>
</blockquote>
<p>If you start programming for the day, a failing test to fix will get you right
back on track.</p>
<p>Instead of having to muster willpower to get started and brainpower to figure
out what you were doing and what to do next, you can mindlessly do whatever it
is that will fix the test.</p>
<p>After that, you'll be much more likely to be in the flow of things, and be able
to keep going in good spirits.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Sex Sells</title>
      <link>https://rodarmor.com/blog/sex-sells</link>
      <guid>https://rodarmor.com/blog/sex-sells</guid>
      <pubDate>2020-12-02</pubDate>
      <content:encoded><![CDATA[<p>As an unrepentant degenerate and fan of microeconomics, it should come as no
surprise that I find the online sexual economy endlessly fascinating.</p>
<p>Most of what happens there isn't surprising to me, with the exception of
pricing for online sexual services, which is much higher than I would have
expected.</p>
<p>As an example, take private, one-on-one cam shows. Browsing
<a href="http://reddit.com/r/sexsells">reddit.com/r/sexsells</a>, the going rate seems to
be between $2.50 and $5.00 per minute, or $150 to $300 per hour.</p>
<p>This is mysterious to me.</p>
<p>Looking at ads on <a href="https://www.eros.com/">eros.com</a>, offline prostitutes seem
to charge $300 an hour. This isn't the amount advertised for a one hour
session, but the marginal difference in price between a one hour and two hour
session, and thus a reasonable estimate of the hourly rate, when preparation
and travel are factored out.</p>
<p>Given that private cam shows are legal, can be done at home, and require
minimal equipment; while offline prostitution is physically dangerous, illegal,
unpleasant<sup class="footnote-reference"><a href="#1">1</a></sup>, and highly taboo, it seems strange that they are priced roughly
the same.</p>
<p>A priori, I would have expected a price difference of 10× or more, like $300
per hour offline and $30 per hour on cam.</p>
<p>Another interesting point is that girls often charge for things that are free
or cheap, like saying the customer's name, or teledildonics.</p>
<p>These are certainly things that customers are willing to pay for, but in a
competitive market, sellers that didn't offer them for free would lose business
to others that did.</p>
<p>So, what's going on? Who knows, but here are a theories, in order of most to
least dubious:</p>
<ul>
<li>
<p>Maybe men are so irrational when they're horny that all of microeconomics
immediately goes out the window?</p>
<p>Price theory, supply and demand, competition, production theory, all
obliterated by the inability of men to just, like, fucking <em>think</em> for one
god-damned second, and try to get a better deal.</p>
<p>I think this is appealing, but probably not true. Most of the time, if you
think that supply and demand don't matter in some market you're just wrong.</p>
</li>
<li>
<p>Customer service overhead. Communicating and handling logistics with
customers might take a lot of time. Also, if men only want short cam shows,
then the overhead of doing multiple 10 minute shows might be substantial.</p>
<p>This would be plausible, except discounts for longer cam shows are small to
non-existent. If scheduling, logistics, and costume changes contributed a
great deal of overhead, I'd expect steep discounts for longer shows.</p>
</li>
<li>
<p>Perhaps there's a supply shortage, because there aren't enough attractive
women to satisfy demand?</p>
<p>I don't think this is it either. From what I can tell, men are extremely
varied in their tastes, and there's demand for every age, body type, and
race. Demand is softer<sup class="footnote-reference"><a href="#2">2</a></sup> in some places than others, but it doesn't
drop off a cliff anywhere.</p>
<p>Also, if this were the case, I would suspect that less desirable women would
undercut more desirable women with budget services, but I haven't observed
this.</p>
</li>
<li>
<p>It also could be that the women on
<a href="http://reddit.com/r/sexsells">reddit.com/r/sexsells</a> are simply at the very
top of the game. They might be the most sophisticated, online, and educated,
and so the prices there just aren't representative of the rest of the market.</p>
<p>I would need to do more research, but this doesn't seem very likely, since I
think their prices are inline with those found elsewhere.</p>
</li>
<li>
<p>Another possibility is that I'm underestimating the social costs of online
sex work. It is very hard to prevent someone you know from finding your
onlyfans, the sex work taboo is strong, and the possible perpetual loss of
privacy is real.</p>
<p>I think this is definitely a factor. However, there are lots of ways to avoid
getting outed, and many women seem to successfully do online sex work
anonymously, for example by wearing masks, and they charge the same high
prices for their services.</p>
</li>
<li>
<p>The fact that online sex workers receive most of their income via digital
payment services probably has a number of nontrivial impacts.</p>
<p>Digital payment services leave a paper trail and are a potential target for
audits, might force online sex workers to pay taxes on their earnings when
offline sex workers don't.</p>
<p>Also, such services are fabulously prudish, and sex workers are deplatformed
regularly.</p>
<p>This all stems from extreme anti-competitive regulation in the underlying
finance, banking, and payments industries. There is little competition,
a high cost of entry, and ubiquitous fear of association with anything
&quot;icky&quot;.</p>
<p>This seems like it's definitely a factor, and I think we can actually
quantify its impact: Sex workers often list Bitcoin as their preferred
payment method, and offering a 20% discount for paying in BTC isn't uncommon.</p>
<p>So, perhaps digital payments being involved accounts for 20% of the high
prices.</p>
<p>(Of course, as an unironic ancap, I find all this regulatory interference
deeply distasteful. As great Murray Rothbard once said<sup class="footnote-reference"><a href="#3">3</a></sup>: &quot;If the state has
no right to the sweat of a man's brow, it surely has no right to the sweat of
an e-thot's ass.&quot;)</p>
</li>
<li>
<p>Custom sexual services might have an extremely high opportunity cost. An
obvious alternative to one-to-one activity like private camming, texting, and
making custom videos is one-to-many activities like making content for
OnlyFans, marketing on social media, and camming for multiple users.</p>
<p>This is a really one compelling for me. Posting content to a heavily
trafficked subreddit to drive users to an OnlyFans page potentially offers a
huge return on time and effort.</p>
<p>Top creators on OnlyFans can earn $100,000 per month, so camming with a
single man might not make economic sense in comparison.</p>
<p>An additional clue that this is a significant factor is that creators often
charge customers $15 or $25 dollars to say their name in a video. Initally
this confused me, but I realize now that it's because it makes it harder to
repurpose the video for OnlyFans and resale, indicating that minimizing
opportunity cost is a very real concern.</p>
</li>
</ul>
<p>None of these theories feel like they explain everything, but in combination
they likely explain a lot.</p>
<h2>Predictions</h2>
<p>I have some predictions about the online sex industry in general, and since
they might be of interest I'll include them here.</p>
<ul>
<li>
<p>I think that OnlyFans will let creators broadcast cam shows from the
platform. Existing cam sites charge usurious fees, up to 85% of what
performers earn.  Since OnlyFans has already undercut the rest of the
industry with its modest 20% fee, I look forward to existing cam sites
competing on price or being obliterated.</p>
</li>
<li>
<p>As the taboo around online sex work continues to fade, a supply glut will
lead to a price crash. Being an OnlyFans creator will be only slightly more
risque then being an instagram thot, attracting a huge number of new
creators.</p>
<p>Eventually, this will impact the price of both of content on OnlyFans, as
well as the cost of more personal sexual services, as creators who are
finding it difficult to succeed in efficient but competitive markets for
one-to-many content turn to less lucrative but less competitive one-to-one
services.</p>
</li>
<li>
<p>A service, again possibly OnlyFans, will become popular for custom sexual
content creators, but only if logistics, communication, and payment
is a significant source of friction.</p>
</li>
</ul>
<p><sup class="footnote-reference"><a href="#1">1</a></sup> I am basing this entirely on the number of times I've seen prostitutes on
Reddit entreat their customers to please wash their assholes before visiting
them.</p>
<p><sup class="footnote-reference"><a href="#2">2</a></sup> Lmaaaaaaao.</p>
<p><sup class="footnote-reference"><a href="#3">3</a></sup> Murray Rothbard did not say this.</p>
]]></content:encoded>
    </item>
    <item>
      <title>How To Debug Things</title>
      <link>https://rodarmor.com/blog/how-to-debug-things</link>
      <guid>https://rodarmor.com/blog/how-to-debug-things</guid>
      <pubDate>2020-12-13</pubDate>
      <content:encoded><![CDATA[<ol>
<li>
<p>What is happening?</p>
</li>
<li>
<p>What is a hypothesis that would explain why this is happening?</p>
</li>
<li>
<p>How can you test this hypothesis?</p>
</li>
<li>
<p>Test it! What did you do?</p>
</li>
<li>
<p>Did it work? If not, write down what happened and go back to step 2.</p>
</li>
<li>
<p>You're done! Nice work!</p>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>Haircut Numbers</title>
      <link>https://rodarmor.com/blog/haircut-numbers</link>
      <guid>https://rodarmor.com/blog/haircut-numbers</guid>
      <pubDate>2021-01-11</pubDate>
      <content:encoded><![CDATA[<p>I was trying to find an image reference for what different clipper guard lengths look like. Every single reference I found had different models with different hairstyles, or used illustrations instead of photographs.</p>
<p>After searching a bit, I found this video, which shows the same person with different hair lengths, with the hair uniformly short over the whole head.</p>
<p>I think it's quite interesting that a random YouTuber may have created a best-in-the-world reference, even if it's for something as mundane as haircut lengths.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/6M4ELqu_aGI" allowfullscreen></iframe>
]]></content:encoded>
    </item>
    <item>
      <title>Policy For Manufacture</title>
      <link>https://rodarmor.com/blog/policy-for-manufacture</link>
      <guid>https://rodarmor.com/blog/policy-for-manufacture</guid>
      <pubDate>2021-01-14</pubDate>
      <content:encoded><![CDATA[<p>The complex priority system that the state is using in many countries to roll out the covid vaccine is reminiscent of this plane boarding algorithm:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/oAHbLRjF0vo?start=313"></iframe>
<p>Yes, it is optimal. No, it won't work in real life.</p>
<p>The state, of course, ignores this. Its reach exceeds its grasp, and we are left with fragile, sub-optimal, poorly implemented plans that are, without exaggeration, worse than a free-for-all, and much worse than market allocation.</p>
<p>The state makes the same mistake in all spheres, because it makes no distinction between designing policy and implementing policy.</p>
<p>The opposite of this is design for manufacturing, where designers of a product modify a design with manufacturing constraints in mind, even if it makes the design worse on some axes. The final outcome, of course, is substantially better.</p>
<p>The product is subject to fewer delays, costs less, and can be made in higher quantities.</p>
<p>However, we cannot expect the state to grasp this simple wisdom, for it is utterly bereft of the incentive to do so.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Fuck Around And Find Out</title>
      <link>https://rodarmor.com/blog/fuck-around-and-find-out</link>
      <guid>https://rodarmor.com/blog/fuck-around-and-find-out</guid>
      <pubDate>2021-01-15</pubDate>
      <content:encoded><![CDATA[<p><a href="https://rodarmor.com/blog/fuck-around-and-find-out/"><img src="https://rodarmor.com/blog/fuck-around-and-find-out/index.png" alt="fuck-around-and-find-out" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Vacuum Debris</title>
      <link>https://rodarmor.com/blog/vacuum-debris</link>
      <guid>https://rodarmor.com/blog/vacuum-debris</guid>
      <pubDate>2021-01-24</pubDate>
      <content:encoded><![CDATA[<p>For some reason I'm fascinated by the debris in this vacuum product photo. If
you look closely, you can see that it's several specific kinds of debris.
Uncooked grains of rice, sunflower seeds, maybe coffee beans, and clumps of
hair. I'm imagining some intern getting just the right debris ready for the
photo.</p>
<p><a href="https://rodarmor.com/blog/vacuum-debris/"><img src="https://rodarmor.com/blog/vacuum-debris/index.jpg" alt="vacuum-debris" /></a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Symmetry</title>
      <link>https://rodarmor.com/blog/symmetry</link>
      <guid>https://rodarmor.com/blog/symmetry</guid>
      <pubDate>2021-02-04</pubDate>
      <content:encoded><![CDATA[<p>I don't do as much deep thinking as I used to. When I was a kid, I remember imagining what it would be like if the universe was symmetrical, mirrored right down the middle. I imagined a white room, floating in space, right on the plane that separates the two halves of the universe. If you parked your spaceship outside and opened the door, you would see yourself in front of you, opening the same door. It would be the you from the other side of the universe.</p>
<p>Unfortunately, you couldn't talk to each other. I thought about it a lot, so trust me on this. You would have a thought, and then that thought would trigger whatever process causes you to speak, but then at the exact same time you said something, the other you would say something, and you would both say &quot;No, please go ahead.&quot; but at the exact same time. You would probably both laugh and get a little red, but then you would feel silly for getting embarrassed in front of yourself.</p>
<p>And then, even though you couldn't communicate, you would have the most amazing experience together. You would walk towards the center of the room, your space shoes tapping out the same tempo on the white floor, stopping just a couple feet apart. Maybe you would take your space gloves and space helmet off so you could give each other Eskimo kisses and exchange the perfect high-five.</p>
<p>Then you would think for a minute, &quot;Should I?&quot; and you would both nod and sort of start to circle around each other. And then you would walk away from each other and leave through the other door, into the other half of the universe. You would get into her spaceship, with her mix CD in the CD player, and it would be the same as the mix CD in the spaceship that you had left behind (it would even start playing right where yours had stopped) and you would fly home.</p>
<p>Sometimes, at night, you might feel a little creepy about it. You would think about how you were sleeping in somebody else's bed, in somebody else's whole world. But that would only last for a second, and then you would think about how she was sleeping in <em>your</em> bed, and how nice the time you spent together was, and you would soon snuggle under the covers and fall asleep.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Bitcoin</title>
      <link>https://rodarmor.com/blog/bitcoin</link>
      <guid>https://rodarmor.com/blog/bitcoin</guid>
      <pubDate>2021-02-16</pubDate>
      <content:encoded><![CDATA[<p>Bitcoin will greatly reduce the power of the state, which rests entirely on its capacity for violence. This capacity is maintained by paying and equipping people to commit violence on its behalf, and it acquires the resources to do so by printing money, collecting taxes, and issuing debt.</p>
<p>Bitcoin hurts the ability of the state…</p>
<p>…to print money by forcing it to compete with a highly liquid deflationary asset.</p>
<p>…to collect taxes by providing individuals with the means to store wealth and transfer funds while avoiding regulated entities with mandatory reporting requirements.</p>
<p>…to issue debt, because the creditworthiness of the state is backstopped by its ability to print money and collect taxes.</p>
<p>I have been expecting for quite some time that USG would take decisive action against Bitcoin, and have been gobsmacked, on an ongoing basis, that this action has not come.</p>
<p>If I were a statist, I would be shouting from the rooftops that Bitcoin must be stopped. Or, more likely, I would be whispering into some politician's ear: <em>It is what you fear it could be.</em></p>
<p>But I am not. So I am gleeful.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Lightning Mints</title>
      <link>https://rodarmor.com/blog/lightning-mints</link>
      <guid>https://rodarmor.com/blog/lightning-mints</guid>
      <pubDate>2021-06-26</pubDate>
      <content:encoded><![CDATA[<p>Federated blind mints have attractive privacy, scaling, and security properties
that are highly complementary to those of Bitcoin and the Lightning Network.</p>
<p>I originally became interested in blind mints while thinking about Lightning
Network wallet usability issues. When Lightning works, it is fantastic, but
keeping a node running and managing a wallet present a number of challenges,
such as channel unavailability due to force closes, the unpredictability of the
on-chain fee environment, the complexity of channel backup, and the involved
and often subtle need to manage liquidity.</p>
<p>All of these problems <em>are</em> tractable for a skilled node operator, but may not
be soluble in the context of self-hosted wallets operated by non-technical
users, hereafter <em>normies</em>. If this is the case, then normies may have no
choice but to use hosted Lightning wallets, compromising their privacy and
exposing them to custodial risk.</p>
<p>Chaumian mints, also known as Chaumian banks, or blind mints, offer a
compelling solution to these problems, particularly when operation is
federated. Chaumian mints, through the use of <a href="https://en.wikipedia.org/wiki/Blind_signature">blind
signatures</a>, have extremely
appealing privacy properties. The mint operators do not know the number of
users, their identities, account balances, or transaction histories.
Additionally, mint transactions are cheap and can be performed at unlimited
scale.</p>
<p>Mint implementations, typified by <a href="https://en.wikipedia.org/wiki/Ecash">eCash</a>,
have hitherto been centralized, and thus, like all centralized, custodial
services, expose users to custodial risk in the form of operator absquatulation
and mismanagement. To fix this, mint operation can be federated, with all
operations performed by a quorum of nodes controlled by different parties.</p>
<p>Despite these interesting properties, Chaumian mints have largely been
forgotten. This <a href="https://opaque.link/post/digitalmoneydbc/">post</a> gives an
excellent overview of the phenomenon. I believe that Chaumian mints are
currently severely underrated in general, and in particular deserve
consideration as a potential avenue for improving custodial Lightning Network
wallets.</p>
<p>Compared to a naïve hosted Lightning Network wallet, a service operated as a
federated Chaumian mint offers excellent privacy, usability, security, and
scaling.</p>
<p><strong>Privacy:</strong> Privacy leaks from a Lightning mint come in two forms, <em>internal</em>
and <em>external</em>, when a mint operator or an outside actor, respectively,
observes sensitive information.</p>
<p>Blind signatures protect against internal privacy leaks, making them a strict
improvement in that respect over custodial Lightning wallets.</p>
<p>When compared to a single-user Lightning network wallet, Lightning mints also
protect against external privacy leaks. If the activity of a single-user
Lightning Network wallet can be observed, which is possible but non-trivial,
all such activity is preemptively that of the owner of the wallet. However,
similar to a standard custodial Lightning Network wallet, any observable
Lightning Network activity of a Lightning mint is the aggregate activity of its
users, who thus form an anonymity set. If the number of users, and thus the
anonymity set size, is large, external privacy leaks are also prevented.</p>
<p><strong>Usability:</strong> Compared to a self-managed Lightning Network wallet, and similar
to a standard custodial Lightning Network wallet, Lightning mint wallets offer
superior usability. A user need not be concerned with the details of node
operation or channel management, and can deposit to and withdraw from their
account with standard Lightning Network invoices.</p>
<p><strong>Security:</strong> The security of a Lightning mint is weaker than that of a
self-hosted wallet. A quorum of federation members can abscond with funds.
However, compared to a standard custodial Lightning Network wallet, security is
greatly improved. Additionally, federation members might be located in
different jurisdictions, making the mint robust to regulatory interference.
Furthermore, members might be entities with online reputations, such as
anonymous Bitcoin Twitter users with an established history of productive
shitposting, providing further assurances against mismanagement and fraud.</p>
<p><strong>Scaling:</strong> Mint operations are extremely lightweight, similar to Lightning
Network transactions, so scaling properties are similar to the Lightning
Network itself.  Additionally, users need not manage their own channels, so a
well-capitalized federation can open channels efficiently, lowering the
per-transaction channel management overhead.</p>
<p><strong>Interoperability and market dynamics:</strong> Additionally, my hope is that such
systems will be developed with a standardized protocol for communication
between wallet interfaces and mint backends. This would allow users to use
different backends with the same local wallet interface, encouraging
competition in the market.</p>
<p>For more discussion of Chaumian mints and their applicability to Bitcoin, see
<a href="https://fedimint.org">fedimint.org</a>. Elsirion, the author, is also at work on
MiniMint, a federated Chaumian mint with Bitcoin and eventually Lightning
Network support.</p>
<p>To close with a bit of speculation, I believe that Chaumian mints were never of
particular interest or importance because they were limited to interoperating
with the fiat currencies of the time. With the ascendance of Bitcoin, mints now
have access to a powerful, decentralized, and uncensorable currency , made
economical and fast by the Lightning Network.</p>
<p>I believe this layering of Chaumian mints on top of Bitcoin and the Lightning
Network will, in the fullness of time, be demonstrated to be enormously
powerful, and make Chaumian mints themselves worthy of renewed study and
consideration.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Wound Care</title>
      <link>https://rodarmor.com/blog/wound-care</link>
      <guid>https://rodarmor.com/blog/wound-care</guid>
      <pubDate>2021-07-13</pubDate>
      <content:encoded><![CDATA[<p>Got some minor cuts and scrapes while doing water sports (not the fetish kind
you perv), was curious about the optimal way to dress them, which lead to
reading at least a dozen papers and articles on wound care and dressing
selection.</p>
<p>It is a complex and interesting topic! Here is my probably-inaccurate summary:</p>
<p>The four stages of wound healing are hemostasis, inflammation, proliferation,
and maturation.</p>
<p>Hemostasis is the body's immediate reaction to and stabilization of the wound.
Blood clots and stops flowing from the wound. Or doesn't, in which case
hemostasis is the first and last stage of wound healing.</p>
<p>Inflammation comes next, which includes processes that prevent infection and
initiate healing. Injured blood vessels leak transudate (water, salt, and
protein) white blood cells head to the wound, tissue turns red and swells, and
bacteria and dead cells are removed from the wound.</p>
<p>Proliferation is the phase where the bulk of tissue reconstruction and healing
takes place. Lost tissue grows back, and the wound closes. In the final phase
of proliferation, epithelial cells regrow and cover the wound.</p>
<p>Maturation, also called remodeling, is the finalization and cleanup phase. The
plumbers, electricians, and carpenters leave the building site, and all the
loose ends are tied up. Temporary cells die off via apoptosis, and the new
tissue reorganizes and strengthens.</p>
<p>The appropriate dressing depends on the characteristics of the wound, and so,
as you might imagine, there exists a rich terminology for wound description.</p>
<p>A sloughy wound is with a layer of infected gunk, usually yellow, You've
probably noticed this when you've had an infected scrape.  Slough is dead
tissue that must be removed for the wound to heal, and a sloughy wound should
be covered with a moist dressing that allows the slough to liquefy. I gather
that mechanical debridement of slough, e.g. the use of wet-to-dry dressings,
although still widely used, is no longer a standard of care.</p>
<p>A necrotic wound has some amount of dead skin or flesh covering or surrounding
the wound, usually of a ghastly black color. If necrotic tissue is badly
infected, it should be surgically removed. However, since this is invasive and
destructive, the preferred alternative for the removal of non-infected necrotic
tissue is the use of a moist, occlusive dressing promoting autolytic
debridement, the natural separation of viable and non-viable tissue.</p>
<p>A granulating wound wound in the process of healing. It has a nice bright,
healthy red color, and should be covered in a moist occlusive dressing and left
to heal.</p>
<p>An epithelial wound is in the final stages of healing, with new skin growing
over and covering the wound.</p>
<p>Interesting tidbit, if a wound is deep, it should be packed with some kind of
dressing, to prevent premature wound closure before the wound void fills in
with new tissue.</p>
<p>For my own rather boring although mildly sloughy wounds, I went with
hydrocolloid dressings. Hydrocolloid dressings are occlusive dressings which
create a moist environment for wound healing. As they transition from sloughy
wounds to granulating wounds, I might switch to just using a film dressing,
which are more flexible, comfortable, and durable.</p>
<p>After all this, I'm a little bummed that I don't have much weirder, graver,
more complicated wounds that would demand more complex and interesting care. 😂</p>
]]></content:encoded>
    </item>
    <item>
      <title>Configuration</title>
      <link>https://rodarmor.com/blog/configuration</link>
      <guid>https://rodarmor.com/blog/configuration</guid>
      <pubDate>2021-10-02</pubDate>
      <content:encoded><![CDATA[<p>Conventional software configuration is backwards.</p>
<p>If you want an HTTP server to listen on port 80 and serve some directory full of
files, you tell the service to bind to port 80 and pass it the path of the files
to serve:</p>
<pre><code>$ http-server --port 80 --files /srv/www
Serving `/srv/www` via HTTP on port 80.
</code></pre>
<p>This is backwards. Let's call this kind of configuration &quot;internal
configuration&quot;, because it's configuration that happens inside programs.</p>
<p>Instead, processes should declare a namespace of resources that they consume or
produce:</p>
<pre><code>$ mount http-server /http
Mounted `http-server` instance at `/http`.
$ tree /http
/http
  /socket
    /listen
  /imports
    /files
</code></pre>
<p>After mounting, resources would be mapped as you see fit, from outside the
process, without having to stop or reconfigure the service:</p>
<pre><code>$ listen 80 /http/socket/listen
Connections to port 80 are being forwarded to socket `/http/socket/listen`.
$ export /srv/www /http/imports/files
Filesystem `/srv/www` exported to `/http/imports/files`.
</code></pre>
<p>Let's call this &quot;external configuration&quot;, because it's configuration that
happens outside programs.</p>
<p>External configuration has a number of benefits:</p>
<ul>
<li>
<p>Uniformity. Consistent configuration. Configure using system tools, not
binary-specific flags and configuration files. System tools can be featureful,
well documented, and universal.</p>
</li>
<li>
<p>Security. Processes have no permissions that they aren't specifically granted.
Processes cannot &quot;ask&quot; for permissions.</p>
</li>
<li>
<p>Dynamic reconfiguration. Processes can be reconfigured on the fly.</p>
</li>
<li>
<p>Faster development. Internal configuration requires developers of each program
to supply options for binding ports, consuming filesystem trees, exporting
filesystem trees, and dynamic reconfiguration. With external configuration,
developers export resources, and configuration and consumption of those
resources is handled externally.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Coin IDs</title>
      <link>https://rodarmor.com/blog/coin-ids</link>
      <guid>https://rodarmor.com/blog/coin-ids</guid>
      <pubDate>2021-11-01</pubDate>
      <content:encoded><![CDATA[<p>Good evening list,</p>
<p>This mail is inspired by Chia's coin IDs. Chia coin IDs consist of:</p>
<p><code>sha256(parent id, sha256(scriptpubkey), amount)</code></p>
<p>One consequence of this is that outputs in Chia have a dedicated textual ID.
This seems beneficial, separate from any larger technical consequences, and
made me wonder if we couldn't replicate that in Bitcoin.</p>
<p>Outputs, a.k.a. outpoints, are commonly represented as <code>TXID:INDEX</code>.  For
example, the first output of transaction
<code>c7dd35a4f81977feac0d235d0e77265cacd362bfc2f0246e384a80d3b0a53a9b</code> is represented
as <code>c7dd35a4f81977feac0d235d0e77265cacd362bfc2f0246e384a80d3b0a53a9b:0</code>.</p>
<p>I find this representation unsatisfying:</p>
<ul>
<li>It places outpoints hierarchically beneath transactions, even
though after a transaction is confirmed, the outpoint is relatively
independent.</li>
<li>It can't be double-clicked to be easily copied.</li>
<li>It isn't popular or widely used. I tried using it in searches in a few block
explorers[0], and none of them support it, even though they do support direct
searches by transaction ID, block hash, and block height.</li>
</ul>
<p>I propose a dedicated representation of outputs using Bech32m. Bech32m is
especially legible, due to its human-readable part, and is compact, and easy to
type and verify. Although having error correction doesn't seem absolutely
necessary, it doesn't seem like a downside. The representation uses &quot;coin&quot; as
the human-readable part, with the payload being the transaction ID, followed by
the 4 byte index.</p>
<p>For example:</p>
<p><code>c7dd35a4f81977feac0d235d0e77265cacd362bfc2f0246e384a80d3b0a53a9b:A0</code></p>
<p>Becomes:</p>
<p><code>coin1clwntf8cr9mlatqdydwsuaextjkdxc4lctczgm3cf2qd8v9982dsqqqqqqqenjt7</code></p>
<p>Anacdotally, I find that many non-expert users I talk to think and talk about
Bitcoin as if it were an account-based system, and tend to think in terms of
transactions. I wonder if having coin IDs, in the form I propose or in some
other form, would help remedy this, similar to how transaction ids, block
hashes, and addresses help reify those concepts. The particulars of the
representation are of secondary importance.</p>
<p>Best regards,<br />
Casey Rodarmor</p>
<p>[0] blockstream.info, blockchain.com, mempool.space, blockcypher.com, and
blockchair.com</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Terrestrial Dividend</title>
      <link>https://rodarmor.com/blog/the-terrestrial-dividend</link>
      <guid>https://rodarmor.com/blog/the-terrestrial-dividend</guid>
      <pubDate>2021-11-09</pubDate>
      <content:encoded><![CDATA[<p><em>Tax the land, pay the people.</em></p>
<p>The Terrestrial Dividend consists of a tax and a dividend. Revenue is generated with a tax on the unimproved value of land and distributed as a cash dividend to all citizens.</p>
<h2>Why?</h2>
<h3>If You're in Favor of Wealth Redistribution</h3>
<p>If you are in favor of wealth redistribution, you should want to raise as much money as possible, as fairly as possible, and get as much as possible into the hands of those who need it.</p>
<p>The Terrestrial Dividend accomplishes all of these goals.</p>
<h3>If You are Against Wealth Redistribution</h3>
<p>If you are not in favor of wealth redistribution, you should want revenue generation to be as efficient as possible, and to minimize the negative economic impact of distribution. Additionally, you should want wealth redistribution to be done in such a way that if it is harmful, incentives align to reduce it.</p>
<p>The Terrestrial Dividend accomplishes all of these goals.</p>
<h2>The Terrestrial Tax</h2>
<p>The Terrestrial Tax is economically efficient. The supply of land is fixed, so a tax on the unimproved value of land does not prevent the production of more land. A tax on widgets, on the other hand, reduces the incentive to produce widgets.</p>
<p>The Terrestrial Tax is progressive. Land is owned by the wealthy, so the wealthy would pay a much greater share of the tax. Due to the fixed supply of land, the tax cannot be passed on to tenants.</p>
<p>The Terrestrial Tax respects privacy. The government does not need to know who owns what land, or what they are doing with it. The tax can be collected with anonymous payments, and only in the case of non-payment must the government involve itself.</p>
<p>The Terrestrial Tax cannot be avoided. It is impossible to hide land or disguise use of land.</p>
<p>The Terrestrial Tax encourages productive economic activity. Since the tax is levied on the unimproved value of land, under-utilized land is a liability, and will be brought into productive use or sold, not held as a speculative asset.</p>
<p>The Terrestrial Tax is simple. Income, sales, value-added, and corporate taxes require enormously complex and err-prone reporting. The details of these taxes are the source of endless political litigation. Under the Terrestrial Tax, the only complexity is in fairly valuing the unimproved value of land, clearly an easier task.</p>
<p>The Terrestrial Tax is legible. The negative effects of a too-low or too-high tax rate can be observed and the rate corrected.</p>
<h2>The Terrestrial Dividend</h2>
<p>The Terrestrial Dividend is beneficial. Cash is more useful in all circumstances than in-kind payments of the same value. The people who need help will get the most benefit possible.</p>
<p>The Terrestrial Dividend is fair. All citizens receive equal-sized cash payments. There is no need to exclude certain recipients, since the wealthy will already pay more tax than they receive as dividend.</p>
<p>The Terrestrial Dividend is efficient. Cash payments avoid the overhead of defining the details of and administering in-kind benefits.</p>
<p>The Terrestrial Dividend is what people want. People prefer cash over in-kind benefits of the same value.</p>
<p>The Terrestrial Dividend is unobtrusive. It is not means tested, nor does it require an application. The poor are the least equipped to fill out applications and submit documentation of income, so this ensures that even the very worst off have the best chance of receiving benefits.</p>
<p>The Terrestrial Dividend is legible. The negative effects of a too-low or too-high dividend can be observed and the amount corrected.</p>
<h2>Together</h2>
<p>The Terrestrial Tax and Dividend are good policies on their own, but even better together due to aligning incentives.</p>
<p>If you want to increase the amount of the dividend, you should want to increase the value of all land, so that the dividend can be increased.</p>
<p>If you want to reduce the amount of the tax, you should want to increase the value of all land, so the tax rate can be reduced without reducing the divided.</p>
<p>Under the Terrestrial Dividend, everyone should care about reducing government overhead and waste, because it comes out of their own pockets.</p>
<p>Also, everyone should care about removing bad policies and implementing good ones, because they increase the value of all land and make everyone better off.</p>
<p>Tax the land, pay the people.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Path to Email World Domination</title>
      <link>https://rodarmor.com/blog/email</link>
      <guid>https://rodarmor.com/blog/email</guid>
      <pubDate>2021-11-19</pubDate>
      <content:encoded><![CDATA[<p><em>A letter to Maalika Manoharan, Product Manager, Gmail. Sent via LinkedIn Inmail, which is palpably ironic.</em></p>
<p>Hi Maalika,</p>
<p>My name is Casey Rodarmor, and I am a former Google SRE and SWE.</p>
<p>I am writing you today because you may be one of the few people that can deliver us from the multi-messenger hell that the human race finds itself in today. Everyone needs to use six or more messaging apps, and everyone hates it.</p>
<p>However, there is an easy way out of this. Email is a federated, decentralized, standards-based messaging platform that everyone already uses. The only reason people use other messaging protocols is because those messaging protocols have features that email doesn't have.</p>
<p>Here is the path to email world domination. It is very simple:</p>
<p>Add the features that email is missing, one by one, in a backwards compatible way.</p>
<p>These features include:</p>
<ul>
<li>Chat messages with low UI overhead and no subject line</li>
<li>Group chats</li>
<li>Read receipts</li>
<li>Voice calling</li>
<li>Video calling</li>
<li>Typing indicators</li>
<li>Message requests</li>
<li>Stickers</li>
<li>Better rich text support</li>
<li>End-to-end encryption</li>
<li>Faster message delivery</li>
<li>Pay money for guaranteed delivery</li>
</ul>
<p>These features can all be implemented in backwards compatible ways that gracefully degrade when they aren't supported.</p>
<p>These features should be designed and implemented in an open process, involving the internet community, public RFCs, and implementations by multiple clients and service providers.</p>
<p>This is a major undertaking, but the benefit is huge, both for Google, Gmail, and the internet community.</p>
<p>Every single non-email protocol will fall by the wayside, and we can return to a simpler, more productive, and more secure world, one where everyone just uses email to communicate, an open, standards-based, internet native protocol.</p>
<p>This could be, without exaggeration, the most important work of your life.</p>
<p>Do you have time to discuss this with me? I have no agenda, just someone who thinks that this is possible, and ultimately very achievable.</p>
<p>With best regards,
Casey Rodarmor</p>
]]></content:encoded>
    </item>
    <item>
      <title>Upgrading Email</title>
      <link>https://rodarmor.com/blog/upgrading-email</link>
      <guid>https://rodarmor.com/blog/upgrading-email</guid>
      <pubDate>2021-11-21</pubDate>
      <content:encoded><![CDATA[<h2>Why?</h2>
<p>Return email to its rightful place as the one true messaging protocol. It's this or use a dozen messaging apps for the rest of your life, there is no other realistic option.</p>
<h2>How?</h2>
<p>Add the features that make people use other messaging protocols to email.</p>
<h2>Which features?</h2>
<h3>Contacts</h3>
<p>Description: Chat, mobile notifications, read receipts, and other features, should not be available to arbitrary addresses. User approves addresses who can use these features.</p>
<p>Implementation: Add-to-contacts UI in client.</p>
<p>Degredation: N/A.</p>
<h3>Chat</h3>
<p>Description: Dedicated chat UI. No subject line. Return to send.</p>
<p>Implementation: Add dedicated chat UI to client. Messages sent from chat UI have header <code>chat: true</code>. Messages received with <code>chat: true</code> are shown in chat UI. Only chat from contacts appear in chat UI. Chat from non-contacts appears in message request UI.</p>
<p>Degradation: Message desplayed in inbox UI.</p>
<h3>Mobile Notifications</h3>
<p>Description: Some messages trigger mobile notification. User configurable.</p>
<p>Implementation: Mobile app has notification category for mail from contacts with header <code>urgent: true</code>.</p>
<p>Degradation: No mobile notification.</p>
<h3>Read Receipts and Typing Indicators</h3>
<p>Description: See read receipts and typing indicators on sent mail.</p>
<p>Implementation: Add <code>receipt-endpoint: &lt;URL&gt;</code> header to outgoing mail. Display read receipts and typing indicators sent to own <code>receipt-endpoint</code>. Only send read receipts and typing indicators to contacts.</p>
<p>Degredation: No read receipts or typing indicators.</p>
<h3>Voice Calling</h3>
<p>Description: Initiate voice calls from within client.</p>
<p>Implementation: Query MX server for voice call endpoint. Display voice call button next to conversations where MX server supports voice calls.</p>
<p>Degredation: No voice call button displayed when not supported.</p>
<h3>Video Calling</h3>
<p>Same as voice calling.</p>
<h3>Message Requests</h3>
<p>Description: Email from arbitrary senders should go into a message request folder, instead of in the inbox, to prevent phishing attacks, and encourage users to whitelist contacts which enables richer features.</p>
<p>Implementation: Email from senders who are not contacts goes into message request folder. Message request folder is distinct from spam folder.</p>
<p>Degredation: Email appears in main inbox.</p>
<h3>Emoji</h3>
<p>Description: Mail consisting of a small number of emoji is displayed in a larger font.</p>
<p>Implementation: Display mail consisting of a small number of emoji in a larger font.</p>
<p>Degredation: Emoji appear smol and sad.</p>
<h3>Stickers</h3>
<p>Description: Users can send &quot;stickers&quot; which are scaled appropriately.</p>
<p>Implementation: Display mail consisting of a single image scaled to UI.</p>
<p>Degredation: Images appear at fixed size.</p>
<h3>Improved Rich Text Support</h3>
<p>Description: Allow rich formatting without breaking plain text readers or using arbitrary HTML.</p>
<p>Implementation: Messages can indicate that they are formatted as markdown. Format messages for graphical clients and display with added line-breaks for plain text readers.</p>
<p>Degredation: Messages appear as plain text markdown, which is highly readable.</p>
<h3>End-to-end Encryption</h3>
<p>Description: Messages between users are end-to-end encrypted to avoid being read by third parties.</p>
<p>Implementation: Query MX server for public key of receipient, encrypt mail for recipient with pubkey.</p>
<p>Degredation: Messages are not encrypted. This is strict improvement to not encrypting any email. Once email E2EE is widespread enough, refuse to send mail to recipients that don't support it.</p>
<h3>Prevent Replies Leaking Information</h3>
<p>Description: Including messages in replies bloats messages, can accidentally leak information, and has is not necessary due to threaded clients.</p>
<p>Implementation: Don't include original message in reply by default. User may use dedicated quote reply UI to include quotes of original message.</p>
<p>Degredation: None.</p>
<h3>Faster Message Delivery</h3>
<p>Description: Deliver email instantly without any delay.</p>
<p>Implementation: Define mapping of email symantics over HTTP/3 as email/2, providing persistant connections and an efficient binary encoding. Query MX server email/2 support and use it if available, using persistant connections and binary encoding for instant message delivery.</p>
<p>Degredation: Messages are delivered at normal speed.</p>
<h3>Disappearing Messages</h3>
<p>Description: Messages can be configured to dissappear after some amount of time.</p>
<p>Implementation: Query if recipient MX server supports disappearing messages. If so, let sender set amount of time before messages disappear. Enforced by recipient, not sender, since sender enforcement is impossible.</p>
<p>Degredation: Option to turn on disappearing messages is not available when not supported by recipient.</p>
<h3>Group Chats</h3>
<p>Description: It should be possible to easily add and remove addresses from group chats.</p>
<p>Implementation: Email already supports group emails, but configuring adding and removing addresses from group chats is difficult. Query MX server for group chat support endpoint. Dedicated API for creating and updating group chats, referenced by ID. Group chat emails are associated with ID, instead of just being arbitrary lists of addresses, allowing any participant, if they have the permissions, to add and remove members from chat.</p>
<p>Degredation: Group chats are received as ordinary multi-address emails.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Standards-based Social Networking</title>
      <link>https://rodarmor.com/blog/standards-based-social-networking</link>
      <guid>https://rodarmor.com/blog/standards-based-social-networking</guid>
      <pubDate>2021-11-29</pubDate>
      <content:encoded><![CDATA[<p>Expanding on <a href="https://twitter.com/rodarmor/status/1465455734146011140">this tweet</a>: <em>You could launch a super fancy social networking site with all the features that everyone expects, but built entirely on existing open standards:</em></p>
<ul>
<li>Sign-up: Pick a domain. This is your username. Register domain through service. Can be transferred out at any time. $10 a year is nothing.</li>
<li>Profile: Hosted at <code>domain.tld</code>.</li>
<li>Messaging: Email at <code>whatever@domain.tld</code>. User can use whatever email app they want.</li>
<li>Social Graph: Contacts via CardDAV.</li>
<li>Authentication: Done with Oath.</li>
<li>Permission System: Entirely done with contacts. First pass filtering is done with spam filter. Email from non-contacts goes to message requests folder. Contacts can be marked using CardDAV groups and fields as &quot;friends&quot;, which enables bypassing spam filter and seeing private items.</li>
<li>Feed: RSS at <code>https://username.com/feed.xml</code>. Private items require authentication. Include email address in RSS metadata, and comment via email.</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Investable Desiderata</title>
      <link>https://rodarmor.com/blog/investable-desiderata</link>
      <guid>https://rodarmor.com/blog/investable-desiderata</guid>
      <pubDate>2021-12-06</pubDate>
      <content:encoded><![CDATA[<p>There are a lot of things that I wish would happen, but don't have the time to
actually do myself. I complain about such things all the time to basically
anyone who will listen. Such efforts are all well and good, and sometimes
actually pay off, but additionally, I'd like to materially support people who
might actually do these things.</p>
<p>This post, which I'll try to keep up-to-date, if I remember, documents the
projects which I wish some talented go-getter would take on, and in which I
would invest money in if given the opportunity.</p>
<p>If you are one of these aforementioned go-getters,
<a href="mailto:casey@rodarmor.com">email me</a>!</p>
<ul>
<li>
<p>Email-based messaging: The only reason we use anything but email to
communicate is because email is missing features that could easily be added.
Deliver us from multi-messaging app hell!</p>
</li>
<li>
<p>RSS-based social networking: RSS could easily serve as the basis for
standards-based social networking, and would be useful even without taking a
significant market share.</p>
</li>
<li>
<p>Bitcoin-based NFTs: NFTs are getting lots of creative people both excited and
paid. Let them suckle at mama Bitcoin's sweet and bountiful bosem instead of
Ethereum's shrivled, insecure, bitter, centralized tit. This can't be done on
the Bitcoin L1, so should be pursued as an L2. The key here is figuring out
how to avoid needing a new token.</p>
</li>
<li>
<p>Bitcoin-based smart contracts: Much like the NFT item above. Let the degens
feast at the Bitcoin board, not at the Ethereum kiddy table. Must avoid
needing a new token. The best path forward is to fork Liquid, add smart
contract functionality to Elements, and run it as Bitcoin-pegged federation.</p>
</li>
<li>
<p>Self-hosted block game: There should be a Minecraft-like game that can be
programmed and modded from within the game.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Multisig Is Probably Better Than Proof Of Stake</title>
      <link>https://rodarmor.com/blog/multisig-is-probably-better-than-proof-of-stake</link>
      <guid>https://rodarmor.com/blog/multisig-is-probably-better-than-proof-of-stake</guid>
      <pubDate>2021-12-08</pubDate>
      <content:encoded><![CDATA[<p>A large reputable member threshold multisig operating as functionaries for a Bitcoin-pegged deterministic replicated state machine sidechain with as-compatible-as-possible-with-mainchain semantics is probably more reliable and secure that most alternative chains.</p>
<ul>
<li>
<p>Large: The number of functionaries should be large enough to ensure geographic, jurisdictional, and administrative distribution.</p>
</li>
<li>
<p>Reputable members: Functionaries should be chosen who would suffer a reputational loss in the case of poor performance.</p>
</li>
<li>
<p>Threshold multisig: A M-of-N multisig. M should be at least ⌊N/2+1⌋, to reduce the chance of equivocation.</p>
</li>
<li>
<p>Deterministic, functionaries: Discretion is unpredictable and morally hazardous. The semantics enforced by the functionaries should be deterministic and predictable, not discretionary. Semantics should never change, and if they must, changes should be announced long enough in advance to make exit practical.</p>
</li>
<li>
<p>Bitcoin-pegged: If the currency of the sidechain isn't bitcoin, users of the sidechain cannot meaningfully exit. Ability to exit incentives the functionaries to be good stewards of the sidechain.</p>
</li>
<li>
<p>Replicated state machine: The state of all functionaries should be the same, and it should be able to recreate and run ones own copy of the state machine.</p>
</li>
<li>
<p>Sidechain: Functionaries should publish a sequence of block headers where each block header includes the hash of the current state, as well as the hash of the previous state. Previous states should also be made available by functionaries, in order to make the system auditable.</p>
</li>
<li>
<p>As-compatible-as-possible-with-mainchain semantics: The ability of users to exit should be maximized, and making the semantics of the sidechain as close as possible to those of the mainchain maximizes the ability to exit, by allowing users to destroy atomically destroy assets on the sidechain in exchange for mainchain assets which mimic the properties of the atomically destroyed assets.</p>
</li>
<li>
<p>Probably more reliable and secure than most alternative chains: Alternative chains suffer from many issues. Proof-of-work suffer from a large global pool of potential hashrate that can attack. Proof-of-stake chains suffer from byzantine consensus mechanisms of ever increasing complexity which must operate in a fully adversarial environment, and have economics which allow and incentivize centralization. A multisig chain operates with a far simpler and more understandable security model: the functionaries periodically agree on a new set of transactions, run the transactions on the old state to produce the new state, and sign and publish the result. Such a system should be more reliable, predictable, and secure.</p>
<p>And not only that, if the functionaries are chosen carefully, such that there is a huge number of them, perhaps greater than 50, and they are all reputable entities, they should be both incentivized to run the chain properly, and with limited latitude for malicious behavior.</p>
</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Hell Money Podcast Episode 8 Show Notes: Crypto is Trash</title>
      <link>https://rodarmor.com/blog/crypto-is-trash</link>
      <guid>https://rodarmor.com/blog/crypto-is-trash</guid>
      <pubDate>2022-07-16</pubDate>
      <content:encoded><![CDATA[<h2>Crypto History</h2>
<h3>Prehistory</h3>
<ul>
<li>Lots of interesting stuff here that nobody talks about</li>
<li>Digital Monetary Trust: Private, anonymous, digital bank</li>
<li>eGold</li>
<li>Liberty Trust</li>
</ul>
<h3>2009 - Bitcoin</h3>
<ul>
<li>Bitcoin launches and is the only cryptocurrency for a while</li>
</ul>
<h3>2011 - Early Altcoins</h3>
<ul>
<li>Pure clones of bitcoin with a few parameters tweaked</li>
<li>Changed supply, difficulty adjustment, PoW algorithm</li>
<li>Big lesson was that Bitcoin gets all these things mostly right, no strong advantage to changing them</li>
<li>A few projects tried to do something different and interesting, e.g., namecoin</li>
<li>I would actually include Ethereum in this latter category, however Ethereum has problems</li>
</ul>
<h3>2017 - ICO Boom</h3>
<ul>
<li>In the early altcoin period, launching a coin was relatively hard, because you had to deploy software to computer and get other people to run it</li>
<li>With Ethereum, you could just write an ERC20 contract and deploy it to Ethereum, so technical bar was very low</li>
<li>Ethereum normalized tokens, premines, and presales, so community couldn't fundamentally reject zero-value cash grabs</li>
</ul>
<h3>2020 - DeFi and NFTs</h3>
<ul>
<li>DeFi is basically repackaging of ponzi scheme economics</li>
<li>Huge NFT bubble as people overestimate what NFTs can do and what they'll become</li>
</ul>
<h2>Crypto Psychological Archetypes</h2>
<ul>
<li>Grifters: Incentivized to lie, hype, and overestimate what their projects can do</li>
<li>Astronauts: Underestimate technical complexity, assume all problems can be solved
<ul>
<li>Vitalik is an astronaut par excellence. People in this group underestimate need for security, simplicity, aligned incentives</li>
<li>Probably enthusiastic about complex large-scale social and economic interventions. Remind me of fringe political and economic theorists</li>
<li>Worst example is economic space agency</li>
</ul>
</li>
<li>The hoi polloi:
<ul>
<li>Unit bias (Bitcoin is too expensive!)</li>
<li>FOMB: fear that they missed the boat with bitcoin, must find new boat no matter how shitty</li>
<li>Zero technical understanding, ingest radical bullshit from grifters and astronauts alike</li>
<li>Think bitcoin is a prototype. No, bitcoin is like the internet, has problems but better to just deal with them</li>
</ul>
</li>
</ul>
<h2>What's wrong with…?</h2>
<h3>Ethereum</h3>
<ul>
<li>Solidity has terrible semantics</li>
<li>Terrible and insecure code, even in major projects, nobody actually audits contracts</li>
<li>Scaling comedy: State channels, plasma, plasma cash, sharding, roll ups. No good scaling story. Everything they're pursuing comes with massive costs.</li>
<li>Massive premime. Fine during PoW, leads to massive centralization post PoS transition</li>
<li>Security comedy: Solidity is phenomenally bad, everything big gets hacked, see rekt.news</li>
<li>Optimism has no fraud proofs yet has $X TVL</li>
<li>Community tolerates tokenization, so everything gets tokenized. Their lighting competitor got tokenized. This is serious karmic rot that infects everything.</li>
</ul>
<h3>DeFi</h3>
<ul>
<li>Almost all ponzi economics</li>
<li>No value creation</li>
<li>No underlying economic activity, all finance</li>
<li>Can't create credit, can only do collateralized lending, so can't serve most useful credit creation function</li>
<li>Insanely complex and insecure</li>
</ul>
<h3>Stable Coins</h3>
<ul>
<li>Actually often pretty high utility. People who want digital dollars can't access them</li>
<li>Algorithmic stablecoins are doomed</li>
<li>Best case scenario is digital, private, fully-collateralized bank on crypto rails</li>
</ul>
<h3>Solana</h3>
<ul>
<li>Wildly centralized</li>
<li>Insanely complex</li>
<li>Terrible incentives: Couldn't resist big blockers in same way bitcoin did</li>
<li>Insane costs to running a full node</li>
</ul>
<h3>NFTs</h3>
<ul>
<li>Most contracts are fully centralized</li>
<li>Contents are fully centralized, just point to some server somewhere</li>
<li>Nobody audits, so each is a special snowflake complexity</li>
<li>Massive overestimate of how useful NFTs are or what they'll become</li>
<li>Nothing actually wrong with making digital baubles and selling them</li>
</ul>
<h3>Cardano</h3>
<ul>
<li>Had a plane ride next to highly technical Cardano guy, very nice, very smart</li>
<li>Fully just following incentives</li>
<li>Technicals are terrible</li>
</ul>
<h3>Proof of Stake</h3>
<ul>
<li>Stake ratchet: Strong centralization pressure</li>
<li>Merges token holders and miners, in bitcoin these are separate groups who keep each other in check</li>
</ul>
<h3>Monero</h3>
<ul>
<li>Relatively non-awful. Fair launch, community driven.</li>
<li>Hard forks mean developers have a lot of power</li>
<li>Has on-chain privacy, but transactions are 8x larger than bitcoin, so 1/8 transaction throughput</li>
<li>Lighting is the way for privacy. Use lightning network to mix your coins. Make big channel with tainted coins, pay someone for inbound liquidity w/lightning, slosh your coins over to channel w/inbound liquidity, close back to BTC.</li>
</ul>
<h3>Grin</h3>
<ul>
<li>Fair launch privacy coin with interesting tech</li>
<li>Absolutely dead in the water because no VC marketing budget</li>
</ul>
<h3>zcash</h3>
<ul>
<li>Centralized, blocks just give money to core devs.</li>
<li>Moon math led to inflation bug. Probably not exploited, but no way to know.</li>
</ul>
<h3>Urbit</h3>
<ul>
<li>Urbit's okay</li>
<li>Some technical problems that make me worried</li>
<li>Noble effort to decentralize social media</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Ordinal Theory</title>
      <link>https://rodarmor.com/blog/ordinal-theory</link>
      <guid>https://rodarmor.com/blog/ordinal-theory</guid>
      <pubDate>2022-07-21</pubDate>
      <content:encoded><![CDATA[<p>I've been working on a numbering scheme for satoshis that allows tracking and transferring individual sats. These numbers are called <a href="https://ordinals.com">ordinals</a>, and constitute a numeric namespace for Bitcoin. Satoshis are numbered in the order in which they're mined, and transferred from transaction inputs to transaction outputs in first-in-first-out order. More details are available in <a href="https://github.com/casey/ord/blob/master/bip.mediawiki">the BIP</a>.</p>
<p>Ordinals don't require a separate token, another blockchain, or any changes to Bitcoin. They work right now.</p>
<p>Ordinals can be represented in a few ways:</p>
<p>With raw notation, like so 1905530482684727°. The number is the ordinal number, and the &quot;°&quot; is the Romance language ordinal symbol.</p>
<p>With decimal notation, like so 738848.482684727°. The first number is the block height, and the second is the index of the ordinal within the block.</p>
<p>With degree notation, like so 0°108848′992″482684727‴. We'll get to that in a moment.</p>
<p>A block explorer is available at <a href="https://ordinals.com">ordinals.com</a>. You can explore recent blocks, and look up ordinals by <a href="https://ordinals.com/ordinal/2099994106992659">number</a>, <a href="https://ordinals.com/ordinal/3891094.16797">decimal</a>, <a href="https://ordinals.com/ordinal/3%C2%B0111094%E2%80%B2214%E2%80%B316797%E2%80%B4">degree</a>, or <a href="https://ordinals.com/ordinal/satoshi">name</a>.</p>
<p>Arbitrary assets, such as NFTs, security tokens, accounts, or stablecoins can be attached to Ordinals.</p>
<p>Ordinals is an open-source project, developed <a href="https://github.com/casey/ord">on GitHub</a>. The project consists of a BIP describing the ordinal scheme, an index that communicates with a Bitcoin Core node to track the location of all ordinals, a wallet that allows making ordinal-aware transactions, a block explorer for interactive exploration of the blockchain, and functionality for minting ordinal NFTs.</p>
<h2>Rarity</h2>
<p>Since ordinals can be tracked and transferred, people will naturally want to collect them. Ordinal theorists can decide for themselves which sats are rare and desirable, but I wanted to provide some hints.</p>
<p>Bitcoin has periodic events, some frequent, some more uncommon, and these naturally lend themselves to a system of rarity. These periodic events are:</p>
<ul>
<li><em>Blocks</em>: A new block is mined approximately every 10 minutes, from now until the end of time.</li>
<li><em>Difficulty adjustments</em>: Every 2016 blocks, or approximately every two weeks, the Bitcoin network responds to changes in hashrate by adjusting the difficulty target which blocks must meet in order to be accepted.</li>
<li><em>Halvings</em>: Every 210,000 blocks, or roughly every four years, the amount of new sats created in every block is cut in half.</li>
<li><em>Cycles</em>: Every six halvings, something magical happens: the halving and the difficulty adjustment coincide. This is called a conjunction, and the time period between conjunctions a cycle. A conjunction occurs roughly every 24 years. The first conjunction should happen some time in 2032.</li>
</ul>
<p>This gives us the following rarity levels:</p>
<ul>
<li><code>common</code>: Any sat that is not the first sat of its block</li>
<li><code>uncommon</code>: The first sat of each block</li>
<li><code>rare</code>: The first sat of each difficulty adjustment period</li>
<li><code>epic</code>: The first sat of each halving epoch</li>
<li><code>legendary</code>: The first sat of each cycle</li>
<li><code>mythic</code>: The first sat of the genesis block</li>
</ul>
<p>Which brings us to degree notation, which unambiguously represents an ordinal in a way that makes rarity easy to see at a glance:</p>
<pre><code>A°B′C″D‴
│ │ │ ╰─ Index of sat in the block
│ │ ╰─── Index of block in difficulty adjustment period
│ ╰───── Index of block in halving epoch
╰─────── Cycle, numbered starting from 0
</code></pre>
<p>Ordinal theorists often use the terms &quot;hour&quot;, &quot;minute&quot;, &quot;second&quot;, and &quot;third&quot; for <em>A</em>, <em>B</em>, <em>C</em>, and <em>D</em>, respectively.</p>
<p>Now for some examples. This ordinal is common:</p>
<pre><code>1°1′1″1‴
│ │ │ ╰─ Not first sat in block
│ │ ╰─── Not first block in difficutly adjustment period
│ ╰───── Not first block in halving epoch
╰─────── Second cycle
</code></pre>
<p>This ordinal is uncommon:</p>
<pre><code>1°1′1″0‴
│ │ │ ╰─ First sat in block
│ │ ╰─── Not first block in difficutly adjustment period
│ ╰───── Not first block in halving epoch
╰─────── Second cycle
</code></pre>
<p>This ordinal is rare:</p>
<pre><code>1°1′0″0‴
│ │ │ ╰─ First sat in block
│ │ ╰─── First block in difficulty adjustment period
│ ╰───── Not the first block in halving epoch
╰─────── Second cycle
</code></pre>
<p>This ordinal is epic:</p>
<pre><code>1°0′1″0‴
│ │ │ ╰─ First sat in block
│ │ ╰─── Not first block in difficulty adjustment period
│ ╰───── First block in halving epoch
╰─────── Second cycle
</code></pre>
<p>This ordinal is legendary:</p>
<pre><code>1°0′0″0‴
│ │ │ ╰─ First sat in block
│ │ ╰─── First block in difficulty adjustment period
│ ╰───── First block in halving epoch
╰─────── Second cycle
</code></pre>
<p>And this ordinal is mythic:</p>
<pre><code>0°0′0″0‴
│ │ │ ╰─ First sat in block
│ │ ╰─── First block in difficulty adjustment period
│ ╰───── First block in halving epoch
╰─────── First cycle
</code></pre>
<p>If the block offset is zero, it may be omitted. This is the uncommon ordinal from above:</p>
<pre><code>1°1′1″
│ │ ╰─ Not first block in difficutly adjustment period
│ ╰─── Not first block in halving epoch
╰───── Second cycle
</code></pre>
<h3>Supply</h3>
<h4>Total Supply</h4>
<ul>
<li><code>common</code>: 2.1 quadrillion</li>
<li><code>uncommon</code>: 6,929,999</li>
<li><code>rare</code>: 3437</li>
<li><code>epic</code>: 32</li>
<li><code>legendary</code>: 5</li>
<li><code>mythic</code>: 1</li>
</ul>
<h4>Current Supply</h4>
<ul>
<li><code>common</code>: 1.9 quadrillion</li>
<li><code>uncommon</code>: 745,855</li>
<li><code>rare</code>: 369</li>
<li><code>epic</code>: 3</li>
<li><code>legendary</code>: 0</li>
<li><code>mythic</code>: 1</li>
</ul>
<p>At the moment, even uncommon ordinals are quite rare. As of this writing, 745,855 uncommon ordinals have been mined - one per 25.6 bitcoin in circulation.</p>
<h2>Names</h2>
<p>Each ordinal has a name, consisting of the letters <em>A</em> through <em>Z</em>, that get shorter the larger the ordinal is. They could start short and get longer, but then all the good, short names would be trapped in the unspendable genesis block.</p>
<p>As an example, 1905530482684727°'s name is &quot;iaiufjszmoba&quot;. The name of the last ordinal to be mined is &quot;a&quot;. Every combination of 10 characters or less is out there, or will be out there, some day.</p>
<h2>Exotics</h2>
<p>Ordinals may be prized for reasons other than their name or rarity. This might be due to a quality of the number itself, like having an integer square or cube root. Or it might be due to a connection to a historical event, such as ordinals from block 477,120, the block in which SegWit activated, or ordinal 2099999997689999°, the last ordinal that will ever be mined.</p>
<p>Such ordinals are termed &quot;exotic&quot;. Which ordinals are exotic and what makes them so is subjective. Ordinal theorists are are encouraged to seek out exotics based on criteria of their own devising.</p>
<h2>Archaeology</h2>
<p>A lively community of archaeologists devoted to cataloging and collecting early NFTs has sprung up. <a href="https://mirror.xyz/chainleft.eth/MzPWRsesC9mQflxlLo-N29oF4iwCgX3lacrvaG9Kjko">Here's a great summary of historical NFTs by Chainleft.</a></p>
<p>A commonly accepted cut-off for early NFTs is March 19th, 2018, the date the first ERC-721 contract, <a href="https://tenthousandsu.com/">SU SQUARES</a>, was deployed on Ethereum.</p>
<p>Whether or not ordinals are of interest to NFT archaeologists is an open question! In one sense, ordinals were created in early 2022, when I finalized the Ordinals specification. In this sense, they are not of historical interest.</p>
<p>In another sense though, ordinals were in fact created by Satoshi Nakamoto in 2009 when he mined the Bitcoin genesis block. In this sense, ordinals, and especially early ordinals, are certainly of historical interest.</p>
<p>I personally favor the latter view. This is not least because the ordinals were independently discovered on at least two separate occasions, long before the era of modern NFTs began.</p>
<p>On August 21st, 2012, Charlie Lee <a href="https://bitcointalk.org/index.php?topic=102355.0">posted a proposal to add proof-of-stake to Bitcoin to the Bitocin Talk forum</a>. This wasn't an asset scheme, but did use the ordinal algorithm, and was implemented but never deployed.</p>
<p>On October 8th, 2012, jl2012 <a href="https://bitcointalk.org/index.php?topic=117224.0">posted a scheme to the the same forum</a> which uses decimal notation and has all the important properties of ordinals. The scheme was discussed but never implemented.</p>
<p>These independent inventions of ordinals indicate in some way that ordinals were discovered, or rediscovered, and not invented. The ordinals are an inevitability of the mathematics of Bitcoin, stemming not from their modern documentation, but from their ancient genesis. They are the culmination of a sequence of events set in motion with the mining of the first block, so many years ago.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Sending Ordinals on Signet</title>
      <link>https://rodarmor.com/blog/sending-ordinals-on-signet</link>
      <guid>https://rodarmor.com/blog/sending-ordinals-on-signet</guid>
      <pubDate>2022-10-21</pubDate>
      <content:encoded><![CDATA[<p><a href="https://raph.ee/">Raph</a> and I have been working hard on
<a href="https://github.com/casey/ord">ord</a>, the
<a href="https://docs.ordinals.com/theory.html">ordinal</a> block explorer and wallet, and
have just finished the initial version of the <code>ord wallet send ORDINAL ADDRESS</code>
command, which makes a transaction sending <code>ORDINAL</code> to <code>ADDRESS</code>.</p>
<p>Ordinal-aware Bitcoin transactions are rather tricky, and must attend to a
number of considerations:</p>
<ul>
<li>Rare ordinals shouldn't accidentally be lost to the recipient or the fee.</li>
<li>The ordinal being sent should be aligned to the beginning of the output going
to the recipient.</li>
<li>Additional postage should be added so that the ordinal can be sent onward
without needing to merge in additional UTXOs.</li>
<li>Excess sats should be stripped from the recipient's output.</li>
<li>Inputs and outputs must be aligned so that the ordinal being sent actual
makes it to the recipient.</li>
</ul>
<p>This requires a great deal of stressful fiddling with transaction input and
output size and order, and a great deal of checks for edge cases. You can see
all the gory details in the <a href="https://github.com/casey/ord/blob/5182997618b623bec72c91adf011f3052381f870/src/subcommand/wallet/transaction_builder.rs">transaction
builder</a>.</p>
<p>All that fiddling has paid off, and today we made three transactions on signet:</p>
<ul>
<li>
<p>This transaction is simple send of <code>mvzwjdjcofe</code>. The first output is
change, added to ensure that <code>mvzwjdjcofe</code> is the first ordinal in the output
sent to the recipient:</p>
<p><a href="https://mempool.space/signet/tx/83ea1f9a13c8caaa7db7b06f5f6d9ff3608e2ff5636848a3f7b3af7298237de0"><code>ord wallet send mvzwjdjcofe tb1qaykcryeds0kmz3azv5tn46dyt3wu5l5qc3djz0</code></a></p>
</li>
<li>
<p>This transaction sends ordinal <code>nphhwymyrjx</code> to
<code>tb1qew25cz5603xqzkw66m5yq9ruflkkpgjyprcdc5</code>:</p>
<p><a href="https://mempool.space/signet/tx/23f2ab3fc469d6ac23984b386b04a4339863c579d87e97098c7cf8a2045f8186"><code>ord wallet send nphhwymyrjx tb1qew25cz5603xqzkw66m5yq9ruflkkpgjyprcdc5</code></a></p>
<p><code>nphhwymyrjx</code> is first in the input, so no alignment output is needed to make
it first in the recipient's output.</p>
<p>However, the input is quite large, so an additional output is added that
brings the size of the recipient's output down to 10,000 sats. We could
reduce the size of recipient's output to the dust limit, however in that
case, UTXOs would need to be merged in to pay for fees when sending the
ordinal onwards.</p>
</li>
<li>
<p>This transaction sends ordinal <code>139761296637063</code> to
<code>tb1q02yk08hkp9pkyhwdsdfd0ra437tjcdnrjs0sxv</code>:</p>
<p><a href="https://mempool.space/signet/tx/3dbc5adde2f15f0fb45a609ad16011f0e8305cd18240f2ccd08fa642ee77846d"><code>ord wallet send 139761296637063 tb1q02yk08hkp9pkyhwdsdfd0ra437tjcdnrjs0sxv</code></a></p>
<p>There's a lot going on here! Let's break down the inputs and outputs:</p>
<p>Inputs:</p>
<ol>
<li>Contains <code>139761296637063</code> at offset 7,500.</li>
<li>Needed to pay for all outputs</li>
</ol>
<p>Outputs:</p>
<ol>
<li>Change containing 7,500 sats to make <code>139761296637063</code> the first ordinal
of the recipient's output.</li>
<li>The recipient's output containing <code>139761296637063</code> at offset 0. Worth
10,000, so that the recipient can forward <code>139761296637063</code> without
needing to merge in additional UTXOs.</li>
<li>Change containing 16,006 sats, to reduce the recipient's output to 10,000
sats.</li>
</ol>
</li>
</ul>
<p><code>ord wallet send</code> will hopefully be much easier to use compared to <a href="https://docs.ordinals.com/hunting.html">using
<code>bitcoin-cli</code> to manually construct ordinal-aware
transactions</a>. Give it a shot and let
us know what you think!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Competitive Governance</title>
      <link>https://rodarmor.com/blog/competitive-governance</link>
      <guid>https://rodarmor.com/blog/competitive-governance</guid>
      <pubDate>2022-10-22</pubDate>
      <content:encoded><![CDATA[<p>I've been thinking about competitive governance, trying to dissect what,
exactly, its desirable properties might be, and how to achive them. It strikes
me that there are two separate desriable properties that governments have under
competition, which, for lack of a better word, I'll call incentives and
constraints.</p>
<p>Good incentives encourage governments to do useful things. Whereas constraints
prevent them from doing harmful things, or cause governments to cease to exist
if the do harmful things, or at least limit the harm that they can do.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Bitcoin Chaosnet</title>
      <link>https://rodarmor.com/blog/bitcoin-chaosnet</link>
      <guid>https://rodarmor.com/blog/bitcoin-chaosnet</guid>
      <pubDate>2022-10-22</pubDate>
      <content:encoded><![CDATA[<p>Ideas for a new Bitcoin testnet:</p>
<ul>
<li>
<p>Cool, cyberpunk branding and design, so people pay attention to it and want
to use it. I suggest &quot;The Bitcoin Chaos Network&quot; or &quot;Bitcoin Chaos&quot;, for
short. Black and white branding with no Bitcoin orange in sight.</p>
</li>
<li>
<p>Trading coins for money is encouraged.</p>
</li>
<li>
<p>Proof-of-work mining identical to mainnet. No testnet fast difficulty
adjustment.</p>
</li>
<li>
<p>Development policy of including anything that has a reasonable chance of
being merged into core.</p>
</li>
</ul>
<p>One of Bitcoin's core features is that coins have real-world value. A testnet
with coins that have no value doesn't reproduce dynamics essential to Bitcoin,
and doesn't encourage real-world use.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Ord Alpha</title>
      <link>https://rodarmor.com/blog/ord-alpha</link>
      <guid>https://rodarmor.com/blog/ord-alpha</guid>
      <pubDate>2022-10-25</pubDate>
      <content:encoded><![CDATA[<p>We just released <a href="https://github.com/casey/ord/releases/tag/0.1.0">ord version
0.1.0</a>!</p>
<p><code>ord</code> is an <a href="https://docs.ordinals.com/">ordinal number</a> wallet and the index
that serves <a href="https://ordinals.com">ordinals.com</a>.</p>
<p>This release of <code>ord</code> is by no means complete, but it now supports making
ordinal-aware transactions on mainnet using the <code>ord wallet send</code> command
thanks to <a href="https://twitter.com/raphjaph">@raphjaph</a>, and boasts much faster
indexing thanks to <a href="https://twitter.com/callmeier">@callmeier</a>.</p>
<h2><code>ord wallet send</code></h2>
<p>The <code>ord wallet</code> commands interact with an existing Bitcoin Core wallet using
Core's RPC interface, and this release features a new <code>send</code> subcommand that
constructs an ordinal-aware transaction to send a particular <code>ORDINAL</code> to a
recipient's <code>ADDRESS</code>:</p>
<pre><code>ord wallet send ORDINAL ADDRESS
</code></pre>
<p>We write extensive tests alongside every feature, but bugs can always slip
through, and the project as a whole is still immature, so restrictions apply
when using <code>ord wallet send</code> with Mainnet wallets.</p>
<p><code>ord wallet send</code> will refuse to interact with a Mainnet wallet with a name
other than <code>ord</code>, which does not start with <code>ord-</code>, to encourage users to
explicitly mark wallets as being intended for use with <code>ord</code>.</p>
<p>Using <code>bitcoin-cli</code> wallet commands with an <code>ord</code> wallet risks spending your
rarest and most exotic sats, and using <code>ord wallet</code> commands with your main
wallet risks doxing your main stash if you assocaite a spicy ordinal with your
identity.</p>
<h2>Index Optimization</h2>
<p><code>ord</code> must build and maintain an index that maps transaction outputs to ordinal
ranges. <code>ord</code> 0.1.0 now exploits the fact that many UTXOs are spent soon after
they're created, and uses an in-memory cache to avoid huge numbers of database
insertions and retrievals. <code>ord</code> uses the
<a href="https://github.com/cberner/redb/">redb</a> database, which is already quite fast,
but using an in-memory cache avoids reads from and writes to <code>redb</code>'s B-tree,
which are more expensive than the in-memory cache's hashmap.</p>
<h2>Backwards Compatibility</h2>
<p><code>ord</code> is still alpha-quality software, so breaking changes are inevitable, but
starting with version 0.1.0, we'll indicate when breaking changes are included
in a release by bumping the minor version number (0.x.0).</p>
<h2>Try it out!</h2>
<p>Check out <a href="https://github.com/casey/ord/releases/tag/0.1.0"><code>ord</code> 0.1.0</a> and let
us know what you think! <code>ord</code> is CC-0-licensed open-source software developed on
<a href="https://github.com/casey/ord">GitHub</a>.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Single Word Seed Phrases</title>
      <link>https://rodarmor.com/blog/single-word-seed-phrases</link>
      <guid>https://rodarmor.com/blog/single-word-seed-phrases</guid>
      <pubDate>2022-11-13</pubDate>
      <content:encoded><![CDATA[<ul>
<li>action action action action action action action action action action action action</li>
<li>agent agent agent agent agent agent agent agent agent agent agent agent</li>
<li>aim aim aim aim aim aim aim aim aim aim aim aim</li>
<li>all all all all all all all all all all all all</li>
<li>ankle ankle ankle ankle ankle ankle ankle ankle ankle ankle ankle ankle</li>
<li>announce announce announce announce announce announce announce announce announce announce announce announce</li>
<li>audit audit audit audit audit audit audit audit audit audit audit audit</li>
<li>awesome awesome awesome awesome awesome awesome awesome awesome awesome awesome awesome awesome</li>
<li>beef beef beef beef beef beef beef beef beef beef beef beef</li>
<li>believe believe believe believe believe believe believe believe believe believe believe believe</li>
<li>blue blue blue blue blue blue blue blue blue blue blue blue</li>
<li>border border border border border border border border border border border border</li>
<li>brand brand brand brand brand brand brand brand brand brand brand brand</li>
<li>breeze breeze breeze breeze breeze breeze breeze breeze breeze breeze breeze breeze</li>
<li>bus bus bus bus bus bus bus bus bus bus bus bus</li>
<li>business business business business business business business business business business business business</li>
<li>can can can can can can can can can can can can</li>
<li>cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon cannon</li>
<li>canyon canyon canyon canyon canyon canyon canyon canyon canyon canyon canyon canyon</li>
<li>carry carry carry carry carry carry carry carry carry carry carry carry</li>
<li>cave cave cave cave cave cave cave cave cave cave cave cave</li>
<li>century century century century century century century century century century century century</li>
<li>cereal cereal cereal cereal cereal cereal cereal cereal cereal cereal cereal cereal</li>
<li>chronic chronic chronic chronic chronic chronic chronic chronic chronic chronic chronic chronic</li>
<li>coast coast coast coast coast coast coast coast coast coast coast coast</li>
<li>convince convince convince convince convince convince convince convince convince convince convince convince</li>
<li>cute cute cute cute cute cute cute cute cute cute cute cute</li>
<li>dawn dawn dawn dawn dawn dawn dawn dawn dawn dawn dawn dawn</li>
<li>dilemma dilemma dilemma dilemma dilemma dilemma dilemma dilemma dilemma dilemma dilemma dilemma</li>
<li>divorce divorce divorce divorce divorce divorce divorce divorce divorce divorce divorce divorce</li>
<li>dry dry dry dry dry dry dry dry dry dry dry dry</li>
<li>elevator elevator elevator elevator elevator elevator elevator elevator elevator elevator elevator elevator</li>
<li>else else else else else else else else else else else else</li>
<li>embrace embrace embrace embrace embrace embrace embrace embrace embrace embrace embrace embrace</li>
<li>enroll enroll enroll enroll enroll enroll enroll enroll enroll enroll enroll enroll</li>
<li>escape escape escape escape escape escape escape escape escape escape escape escape</li>
<li>evolve evolve evolve evolve evolve evolve evolve evolve evolve evolve evolve evolve</li>
<li>exclude exclude exclude exclude exclude exclude exclude exclude exclude exclude exclude exclude</li>
<li>excuse excuse excuse excuse excuse excuse excuse excuse excuse excuse excuse excuse</li>
<li>exercise exercise exercise exercise exercise exercise exercise exercise exercise exercise exercise exercise</li>
<li>expire expire expire expire expire expire expire expire expire expire expire expire</li>
<li>fat fat fat fat fat fat fat fat fat fat fat fat</li>
<li>fetch fetch fetch fetch fetch fetch fetch fetch fetch fetch fetch fetch</li>
<li>fever fever fever fever fever fever fever fever fever fever fever fever</li>
<li>forward forward forward forward forward forward forward forward forward forward forward forward</li>
<li>fury fury fury fury fury fury fury fury fury fury fury fury</li>
<li>garment garment garment garment garment garment garment garment garment garment garment garment</li>
<li>gauge gauge gauge gauge gauge gauge gauge gauge gauge gauge gauge gauge</li>
<li>gym gym gym gym gym gym gym gym gym gym gym gym</li>
<li>half half half half half half half half half half half half</li>
<li>harsh harsh harsh harsh harsh harsh harsh harsh harsh harsh harsh harsh</li>
<li>hole hole hole hole hole hole hole hole hole hole hole hole</li>
<li>hybrid hybrid hybrid hybrid hybrid hybrid hybrid hybrid hybrid hybrid hybrid hybrid</li>
<li>illegal illegal illegal illegal illegal illegal illegal illegal illegal illegal illegal illegal</li>
<li>include include include include include include include include include include include include</li>
<li>index index index index index index index index index index index index</li>
<li>into into into into into into into into into into into into</li>
<li>invest invest invest invest invest invest invest invest invest invest invest invest</li>
<li>involve involve involve involve involve involve involve involve involve involve involve involve</li>
<li>jeans jeans jeans jeans jeans jeans jeans jeans jeans jeans jeans jeans</li>
<li>kick kick kick kick kick kick kick kick kick kick kick kick</li>
<li>kite kite kite kite kite kite kite kite kite kite kite kite</li>
<li>later later later later later later later later later later later later</li>
<li>layer layer layer layer layer layer layer layer layer layer layer layer</li>
<li>legend legend legend legend legend legend legend legend legend legend legend legend</li>
<li>life life life life life life life life life life life life</li>
<li>lyrics lyrics lyrics lyrics lyrics lyrics lyrics lyrics lyrics lyrics lyrics lyrics</li>
<li>margin margin margin margin margin margin margin margin margin margin margin margin</li>
<li>melody melody melody melody melody melody melody melody melody melody melody melody</li>
<li>mom mom mom mom mom mom mom mom mom mom mom mom</li>
<li>more more more more more more more more more more more more</li>
<li>morning morning morning morning morning morning morning morning morning morning morning morning</li>
<li>nation nation nation nation nation nation nation nation nation nation nation nation</li>
<li>neck neck neck neck neck neck neck neck neck neck neck neck</li>
<li>neglect neglect neglect neglect neglect neglect neglect neglect neglect neglect neglect neglect</li>
<li>never never never never never never never never never never never never</li>
<li>noble noble noble noble noble noble noble noble noble noble noble noble</li>
<li>novel novel novel novel novel novel novel novel novel novel novel novel</li>
<li>obvious obvious obvious obvious obvious obvious obvious obvious obvious obvious obvious obvious</li>
<li>ocean ocean ocean ocean ocean ocean ocean ocean ocean ocean ocean ocean</li>
<li>oil oil oil oil oil oil oil oil oil oil oil oil</li>
<li>orphan orphan orphan orphan orphan orphan orphan orphan orphan orphan orphan orphan</li>
<li>oxygen oxygen oxygen oxygen oxygen oxygen oxygen oxygen oxygen oxygen oxygen oxygen</li>
<li>pause pause pause pause pause pause pause pause pause pause pause pause</li>
<li>peasant peasant peasant peasant peasant peasant peasant peasant peasant peasant peasant peasant</li>
<li>permit permit permit permit permit permit permit permit permit permit permit permit</li>
<li>piano piano piano piano piano piano piano piano piano piano piano piano</li>
<li>proof proof proof proof proof proof proof proof proof proof proof proof</li>
<li>pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin pumpkin</li>
<li>question question question question question question question question question question question question</li>
<li>real real real real real real real real real real real real</li>
<li>report report report report report report report report report report report report</li>
<li>rough rough rough rough rough rough rough rough rough rough rough rough</li>
<li>rude rude rude rude rude rude rude rude rude rude rude rude</li>
<li>salad salad salad salad salad salad salad salad salad salad salad salad</li>
<li>scale scale scale scale scale scale scale scale scale scale scale scale</li>
<li>screen screen screen screen screen screen screen screen screen screen screen screen</li>
<li>sea sea sea sea sea sea sea sea sea sea sea sea</li>
<li>seat seat seat seat seat seat seat seat seat seat seat seat</li>
<li>sell sell sell sell sell sell sell sell sell sell sell sell</li>
<li>seminar seminar seminar seminar seminar seminar seminar seminar seminar seminar seminar seminar</li>
<li>seven seven seven seven seven seven seven seven seven seven seven seven</li>
<li>sheriff sheriff sheriff sheriff sheriff sheriff sheriff sheriff sheriff sheriff sheriff sheriff</li>
<li>siege siege siege siege siege siege siege siege siege siege siege siege</li>
<li>silver silver silver silver silver silver silver silver silver silver silver silver</li>
<li>soldier soldier soldier soldier soldier soldier soldier soldier soldier soldier soldier soldier</li>
<li>spell spell spell spell spell spell spell spell spell spell spell spell</li>
<li>split split split split split split split split split split split split</li>
<li>spray spray spray spray spray spray spray spray spray spray spray spray</li>
<li>stadium stadium stadium stadium stadium stadium stadium stadium stadium stadium stadium stadium</li>
<li>sugar sugar sugar sugar sugar sugar sugar sugar sugar sugar sugar sugar</li>
<li>sunny sunny sunny sunny sunny sunny sunny sunny sunny sunny sunny sunny</li>
<li>sure sure sure sure sure sure sure sure sure sure sure sure</li>
<li>tobacco tobacco tobacco tobacco tobacco tobacco tobacco tobacco tobacco tobacco tobacco tobacco</li>
<li>tongue tongue tongue tongue tongue tongue tongue tongue tongue tongue tongue tongue</li>
<li>track track track track track track track track track track track track</li>
<li>tree tree tree tree tree tree tree tree tree tree tree tree</li>
<li>trouble trouble trouble trouble trouble trouble trouble trouble trouble trouble trouble trouble</li>
<li>twelve twelve twelve twelve twelve twelve twelve twelve twelve twelve twelve twelve</li>
<li>twice twice twice twice twice twice twice twice twice twice twice twice</li>
<li>type type type type type type type type type type type type</li>
<li>uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform uniform</li>
<li>useless useless useless useless useless useless useless useless useless useless useless useless</li>
<li>valid valid valid valid valid valid valid valid valid valid valid valid</li>
<li>very very very very very very very very very very very very</li>
<li>vibrant vibrant vibrant vibrant vibrant vibrant vibrant vibrant vibrant vibrant vibrant vibrant</li>
<li>virtual virtual virtual virtual virtual virtual virtual virtual virtual virtual virtual virtual</li>
<li>vocal vocal vocal vocal vocal vocal vocal vocal vocal vocal vocal vocal</li>
<li>warrior warrior warrior warrior warrior warrior warrior warrior warrior warrior warrior warrior</li>
<li>word word word word word word word word word word word word</li>
<li>world world world world world world world world world world world world</li>
<li>yellow yellow yellow yellow yellow yellow yellow yellow yellow yellow yellow yellow</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Inscribing Mainnet</title>
      <link>https://rodarmor.com/blog/inscribing-mainnet</link>
      <guid>https://rodarmor.com/blog/inscribing-mainnet</guid>
      <pubDate>2023-01-20</pubDate>
      <content:encoded><![CDATA[<p><code>ord</code> version <a href="https://github.com/casey/ord/releases/tag/0.4.0">0.4.0</a> has been
released. Inscriptions are finally ready for Bitcoin mainnet.</p>
<h2>Inscriptions</h2>
<p>Inscriptions are digital artifacts native to the Bitcoin blockchain. They are
created by inscribing sats with content using
<a href="https://github.com/casey/ord">ord</a>, and can be viewed with the <a href="https://ordinals.com/inscriptions">ordinals
explorer</a>. They do not require a separate
token, a side chain, or changing Bitcoin.</p>
<p>Inscriptions are created by including content, like an image, text, SVG, or
HTML, in an inscription transaction. The content is included in the transaction
witness, which normally contains signatures and other data proving that a
transaction is authorized.</p>
<p>Along with the content, the inscription transaction contains a content type,
also known as a MIME type, identifying the type of content to be inscribed.</p>
<p>When mined, the inscription is made on the first sat of the first output of the
transaction, permanently and inexorably marking it, distinguishing it from its
fellows. It is no longer just a sat, it is an intertwined component of the long
and confusing tale that is human art and culture.</p>
<p>Using <a href="https://rodarmor.com/blog/ordinal-theory/">ordinal theory</a>, the unspent
output containing an inscribed sat can be found, and its movements and
ownership tracked across time and transactions, allowing inscriptions to
traded, gifted, bought, and sold.</p>
<p>This allows inscriptions quite native to Bitcoin. They can be sent to normal
bitcoin addresses, in normal bitcoin transactions, and benefit from timelocks,
multisig, and all the rest of Bitcoin's infrastructure. To avoid losing them, a
wallet that holds inscriptions must perform sat control, the sizing and
alignment of transaction inputs and outputs that controls the destination of
individual sats, but aside from that, transactions that transfer inscriptions
are quite mundane.</p>
<h2>Digital Artifacts</h2>
<p>Inscriptions are <a href="https://docs.ordinals.com/digital-artifacts.html">digital
artifacts</a>, and digital
artifacts are NFTs, but not all NFTs are digital artifacts. Digital artifacts
are NFTs held to a higher standard, closer to their ideal. For an NFT to be a
digital artifact, it must be decentralized, immutable, on-chain, and
unrestricted. The vast majority of NFTs are not digital artifacts. Their
content is stored off-chain and can be lost, they are on centralized chains,
and they have back-door admin keys. What's worse, because they are smart
contracts, they must be audited on a case-by-case basis to determine their
properties.</p>
<p>Inscriptions are unplagued by such flaws. Inscriptions are immutable and
on-chain, on the oldest, most decentralized, most secure blockchain in the
world. They are not smart contracts, and do not need to be examined
individually to determine their properties. They are true digital artifacts.</p>
<h2><code>ord</code> 0.4.0</h2>
<p><code>ord</code> is an open-source binary written in Rust, and developed on
<a href="https://github.com/casey/ord">GitHub</a>. It implements an ordinal wallet, which
can create and transfer inscriptions, and a block explorer. There are public
<a href="https://ordinals.com">mainnet</a>, <a href="https://signet.ordinals.com">signet</a>, and
<a href="https://testnet.ordinals.com">testnet</a> instances.</p>
<p><code>ord</code> is experimental software, and comes with no warranty or guarantees. <code>ord</code>
0.4.0, the latest release, has been tested carefully, and can now be used to
make inscriptions on mainnet, and that those inscriptions will not break due to
a future protocol change.</p>
<p>Three mechanisms exist to introduce opt-in changes to the protocol, without
breaking existing inscriptions: Versioning, optional fields, and mandatory
fields.</p>
<p>Inscriptions can contain a version field. The inscription parser will ignore
inscriptions with an unrecognized version. This allows introducing fundamental
changes to inscriptions, without disrupting existing inscriptions.</p>
<p>Additionally, fields can be marked as optional or mandatory, which determines
how an inscription parser treats an unrecognized field. Unrecognized optional
fields are ignored but the inscription is normally, while unrecognized
mandatory fields render the whole inscription invalid.</p>
<p>Individual features that can be safely ignored if unsupported can be introduced
as optional fields, while features that must be supported in order in order to
understand an inscription can be introduced as mandatory fields.</p>
<p>Inscriptions are not finished, but this flexibility gives us confidence that
future improvements can be made opt-in and non-disruptive.</p>
<p>Let markets and bazaars where rare sats and inscriptions are traded grow and
flourish, and may their wares never crack or vanish.</p>
<h2>What's missing?</h2>
<p>Inscriptions have many unique benefits and features, but they have not yet
reached feature parity with other NFT implementations.</p>
<p>Two key features are missing: provenance and decentralized markets.</p>
<p>Provenance is the ability to determine the author of an inscription, or its
membership in a set of inscriptions all created by the same person. We have a
design that accomplishes this, and its implementation is tracked in
<a href="https://github.com/casey/ord/issues/783">issue #783</a>. A transaction creating a new
inscription, <code>X</code>, may include an existing inscription, <code>P</code>, in its inputs,
which is returned back to the owner in its outputs. Since only the owner of P
could have made this transaction, this identifies <code>P</code> as the parent of <code>X</code>.
This mechanism is flexible, and can be used to identify an inscription as being
created by an individual, or to identify an inscription as being a member of a
larger collection. Furthermore, this mechanism is recursive. You can create in
inscription that represents your identity, and use that inscription as the
parent of an inscription that itself is used as the parent inscription for a
collection.</p>
<p>For inscriptions be valuable, there must be venues where they can be bought and
sold. We have a sketch for decentralized and trustless offers to buy and sell
using partially-signed transactions, and its implementation is tracked in
<a href="https://github.com/casey/ord/issues/802">issue #802</a>. The owner of an
inscription may offer it for sale by publishing a transaction that includes it
as an input, and containing an output that pays to them the sale price. Any
third party can take such a transaction, add their own input of at least the
sale price, add an output sending the inscription to themselves, and finalize
it by broadcasting it to be mined. Offers to buy are similar.</p>
<h2>What's next?</h2>
<p>Inscriptions have been designed to be native to the web. Inscriptions are byte
strings, identified with a content type, and so can be displayed in a browser.
HTML, CSS, JavaScript, SVG, MP3, PNG, and JPEG, are supported by the ordinals
explorer.</p>
<p>Inscription content is sandboxed so that it cannot make outgoing web requests.
However, in the future, this sandboxing will be relaxed to allow inscriptions
to use the content of other inscriptions. This will allow for the development
of an a modular, on-chain ecosystem of remixing and composition. This is
tracked in <a href="https://github.com/casey/ord/issues/1082">issue #1082</a>.</p>
<p>Inscriptions are unnamed and untitled, but we hope to give artificers the
ability to give their inscriptions globally unique, human-readable names. This
is tracked in <a href="https://github.com/casey/ord/issues/794">issue #794</a>.</p>
<p>The future of inscriptions is bright. We hope not only to reach feature parity
with other NFT implementations, but to surpass them.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Great Renumbering</title>
      <link>https://rodarmor.com/blog/the-great-renumbering</link>
      <guid>https://rodarmor.com/blog/the-great-renumbering</guid>
      <pubDate>2023-09-06</pubDate>
      <content:encoded><![CDATA[<p>Inscription numbers are numbers assigned to inscriptions in the order in which
they are created, starting at zero for the <a href="https://ordinals.com/inscription/6fb976ab49dcec017f1e201e84395983204ae1a7c2abf7ced0a85d692e442799i0">genesis
inscription</a>.</p>
<p>When inscription numbers were originally added to
<a href="https://github.com/ordinals/ord">ord</a>, the Ordinals wallet and explorer that
powers <a href="https://ordinals.com">ordinals.com</a>, they were intended to be stable
and never change.</p>
<p>However, now that we have more experience with the protocol, that seems less
tenable and has undesirable consequences, as maintaining stable inscription
numbers is a challenge in the face of changes to the inscription protocol.</p>
<p>Consider a simple case, an update that allows multiple inscriptions to be
created in a single transaction.</p>
<p>The inscription numbers assigned by an implementation that recognizes multiple
inscriptions in a single transaction would differ from those assigned by an
implementation that does not.</p>
<p>The former implementation would see T1, creating two new inscriptions, and T2,
creating a single new inscription, and assign inscription numbers N, N+1, and
N+2, the latter implementation would assign inscription number N to the first
and only inscription it recognized in T1, and N+1 to the inscription in T2.</p>
<p>There are many such updates that we would like to make or have made which would
introduce discrepancies like these, including:</p>
<ul>
<li>Multiple inscriptions per transaction</li>
<li>Inscriptions in reveal inputs other than the first</li>
<li>Inscriptions with new even fields</li>
<li>Multiple inscriptions on the same sat</li>
</ul>
<p>We've been able to make these changes and keep inscription numbers stable using
what I've now come to think of as a regrettable hack: cursed inscriptions.
Whenever <code>ord</code> indexes an inscription which would not be recognized by an
earlier version, it assigns a negative inscription number. This keeps old
inscription numbers stable, while still recognizing new inscriptions.</p>
<p>Cursed inscriptions and negative inscriptions numbers have a number of
downsides:</p>
<ul>
<li>An inscription number now does not tell you anything about the order in which
the inscription was made.</li>
<li>The logic required to keep track of which inscriptions are cursed is a source
of bugs and complexity.</li>
<li>&quot;Blessing&quot; cursed inscription types, i.e., collectively deciding that after a
certain block height, certain cursed inscription types will no longer be
assigned negative numbers, and be assigned positive numbers instead, requires
coordination.</li>
<li>Cursed inscription numbers are permanently unstable, so a substantial number
of inscription numbers are already unstable, even under the status quo.</li>
</ul>
<p>In light of the above, I propose that we make inscription numbers permanently
unstable, and bless all cursed inscriptions, both retroactively and on an
ongoing basis. Cursed inscription numbers would be folded into the main
sequence, and, going forward, inscription numbers should not be used in URLs,
which is already the case for <code>ord</code>, and inscription numbers would be
de-emphasized on <code>/inscription</code> pages.</p>
<p>This would substantially simplify the <code>ord</code> codebase, make it easier to produce
an implementation that assigns the same sequence numbers, and make future
protocol changes easier.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Runes</title>
      <link>https://rodarmor.com/blog/runes</link>
      <guid>https://rodarmor.com/blog/runes</guid>
      <pubDate>2023-09-25</pubDate>
      <content:encoded><![CDATA[<p>I'm not sure creating a new fungible token protocol for Bitcoin is a good idea.
Fungible tokens are 99.9% scams and memes. However, they don't appear to be
going away any time soon, similar to the way in which casinos don't appear to
be going away any time soon. Creating a good fungible token protocol for
Bitcoin might bring significant transaction fee revenue, developer mindshare,
and users to Bitcoin. Additionally, if this protocol had a small on-chain
footprint and encouraged responsible UTXO management, it might serve as harm
reduction compared to existing protocols. At least one of which, BRC-20, is
already quite popular, and has the undesirable consequence of UTXO
proliferation.</p>
<p>When comparing existing fungible token protocols, there are a few important
ways in which they differ:</p>
<ul>
<li>Complexity: How complex is the protocol? Is it easy to implement? Is it easy
to adopt?</li>
<li>User experience: Are there any implementation details which have a negative
effect on the user experience? In particular, protocols that rely on
off-chain data have a lighter on-chain footprint, but introduce a great deal
of complexity, and require users to either run their own servers, or discover
and interact with existing servers.</li>
<li>State model: Protocols that are UTXO-based fit more naturally into Bitcoin
and promote UTXO set minimization by avoiding the creation of &quot;junk&quot; UTXOs.</li>
<li>Native token: Protocols with a native token which is required for protocol
operations are cumbersome, extractive, and naturally less widely adopted.</li>
</ul>
<p>Comparing existing fungible token protocols for Bitcoin:</p>
<ul>
<li>BRC-20: Not UTXO-based and rather complex, since it requires use of ordinal
theory for some operations.</li>
<li>RGB: Very complicated, relies on off-chain data, has been in development for
a long time with no adoption.</li>
<li>Counterparty: Has a native token required for some operations, not
UTXO-based.</li>
<li>Omni Layer: Has a native token required for some operations, not UTXO-based.</li>
<li>Taproot Assets: Somewhat complicated, relies on off-chain data.</li>
</ul>
<p>What would a simple, UTXO-based fungible token protocol with a good user
experience for Bitcoin look like? Here's one, called &quot;runes&quot;, because it sounds
cool.</p>
<h2>Overview</h2>
<p>Rune balances are held by UTXOs. A UTXO can contain any amount of any number of
runes.</p>
<p>A transaction contains a protocol message if it contains an output whose script
pubkey contains an OP_RETURN followed by a data push of the ASCII uppercase
letter <code>R</code>. The protocol message is all data pushes after the first.</p>
<p>Runes input to a transaction with an invalid protocol message are burned. This
allows for future upgrades that change how runes are assigned or created from
creating situations where old clients erroneously assign rune balances.</p>
<p>Integers are encoded as prefix varints, where the number of leading ones in a
varint determines its length in bytes.</p>
<h2>Transfer</h2>
<p>The first data push in a protocol message is decoded as a sequence integers.</p>
<p>These integers are interpreted as a sequence of (ID, OUTPUT, AMOUNT) tuples. If
the number of decoded integers is not a multiple of three, the protocol message
message is invalid.</p>
<ul>
<li><code>ID</code> is the numeric ID of the run to assign</li>
<li><code>OUTPUT</code> is the index of the output to assign it to</li>
<li><code>AMOUNT</code> is the amount of the run to assign</li>
</ul>
<p><code>ID</code> is encoded as a delta. This allows multiple assignments of the same rune
to avoid repeating the full rune ID. For example, the tuples:</p>
<pre><code>[(100, 1, 20), (0, 2 10), (20, 1, 5)]
</code></pre>
<p>Make the following assignments:</p>
<ul>
<li>ID 100, output 1, 20 runes</li>
<li>ID 100, output 2, 10 runes</li>
<li>ID 120, output 1, 5 runes</li>
</ul>
<p>The <code>AMOUNT</code> 0 is shorthand for &quot;all remaining runes&quot;.</p>
<p>After processing all tuple assignments, any unassigned runes are assigned to
the first non-OP_RETURN output, if any.</p>
<p>Excess assignments are ignored.</p>
<p>Runes may be burned by assigning them to the OP_RETURN output containing the
protocol message.</p>
<h2>Issuance</h2>
<p>If the protocol message has a second data push, it is an issuance transaction.
The second data push is decoded as two integers, <code>SYMBOL</code>, <code>DECIMALS</code>. If
additional integers remain, the protocol message is invalid.</p>
<p>An issuance transaction may create any amount, up to <code>2^128 - 1</code> of the issued
rune, using the ID <code>0</code> in assignment tuples.</p>
<p><code>SYMBOL</code> is a base 26-encoded human readable symbol, similar to that used in
ordinal number sat names. The only valid characters are <code>A</code> through <code>Z</code>.</p>
<p><code>DECIMALS</code> is the number of digits after the decimal point that should be used
when displaying the issued rune.</p>
<p>If <code>SYMBOL</code> has not already been assigned, it is assigned to the issued rune,
and the issued rune receives the next available numeric rune ID, starting at
one.</p>
<p>If <code>SYMBOL</code> has already been assigned, or is <code>BITCOIN</code>, <code>BTC</code>, or <code>XBT</code>, then
no new rune is created. Issuance transaction assignments using the <code>0</code> rune ID
are ignored, but other assignments are still processed.</p>
<h2>Notes</h2>
<p>When displaying UTXO balances, the native bitcoin balance of a UTXO can be
displayed with rune ID zero and the symbol <code>BITCOIN</code>, <code>BTC</code>, or <code>XBT</code>.</p>
<p>No attempt is made to avoid symbol squatting, to keep the protocol simple. One
possible, but still simple, technique to avoid symbols squatting would be to
only allow assignment of symbols above a certain length, with that length
decreasing over time, before eventually reaching zero and allowing all symbols.
This would avoid short, desirable symbols being assigned in the early days of
the protocol, and encourage competition for desirable symbols later on, when
such competition might be meaningful.</p>
<h2>Hand Wringing</h2>
<p>Should such a thing exist? I don't know. It's about as simple as possible, does
not rely on off-chain data, does not have a native token, and fits nicely into
Bitcoin's native UTXO model. Such a scheme might draw users from other schemes
with worse on-chain footprints, and bring developer and user mindshare to
Bitcoin, encouraging them to adopt Bitcoin itself.</p>
<p>On the other hand, the world of fungible tokens is a near totally irredeemable
pit of deceit and avarice, so it might be a wash.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The Stable is the Aesthetic</title>
      <link>https://rodarmor.com/blog/the-stable-is-the-aesthetic</link>
      <guid>https://rodarmor.com/blog/the-stable-is-the-aesthetic</guid>
      <pubDate>2023-09-30</pubDate>
      <content:encoded><![CDATA[<p>When a dev tells you that something is weird and hard and they have to change
behavior that users rely on, the correct response is somewhere between &quot;Cool
story, bro.&quot; and &quot;Wah, wah, wah, are the bits being mean to you?&quot;. Developers
serve users, not the other way around.</p>
<p>For this and other reasons, the ord developers recommit to the stability and
predictability of inscription numbers, and will not pursue renumbering.</p>
<p>As someone who people in the ordinals community mysteriously pay a lot of
attention to, I see myself as having two distinct roles with regards to
proposals such as the great renumbering.</p>
<p>One is to have and propose things that I think are good ideas. This will
continue, and I don't see any particular reason to self-censor. In other words,
the unfettered blog posts will continue. The community needs to understand that
these are proposals only, and that I have had and will continue to have wacky
ideas.</p>
<p>The other role is as one of the people who helps make decisions about what to
implement in <code>ord</code>, the ordinals reference implementation. Raph, as lead
maintainer, has the final say, but he hasn't stopped listening to my wacky
ideas, so I still have some influence. Those decisions must be made with
respect to the userbase of <code>ord</code> and the greater ordinals community.</p>
<p>When I first decided to propose renumbering, I knew that it had to meet a very
high bar. Changes to <code>ord</code> and to ordinals must be Pareto improvements, changes
to the status quo that leave everyone better off, or extremely close to it.
Changes cannot create winners and losers, even if the benefit to the winners
might be greater than the harm to the losers.</p>
<p>After reading discussion on GitHub and Twitter, lurking in many a Twitter
space, and discussing it with many people, it's clear that the great
renumbering does not meet that very high bar, and is better off consigned to
the dustbin of history.</p>
<p>A couple of the arguments that I personally found most persuasive:</p>
<ul>
<li>
<p>Any public discussion will consist only of the most engaged users. Many less
engaged users simply won't be aware that a discussion is taking place, or
might not participate, regardless of their views. These voices simply won't
be heard. This includes people who aren't terminally online, many people who
don't speak English as their native language, and people who just don't
particularly like arguing online. This means that the bias must be strong
towards the status quo,</p>
</li>
<li>
<p>A programmer's job, fundamentally, is to drag his (or her!) balls through
miles of broken glass if it benefits the user. Unless the status quo is so
complex and unmentionable that it is untenable, disruptive changes must be
avoided. As a spirited GitHub commenter put it, &quot;Code and protocols get messy
as they age. That's reality. Purity is for virgins.&quot;</p>
</li>
</ul>
<p>What does this mean, practically?</p>
<ul>
<li>
<p><code>ord</code> will commit to the stability of positive inscription numbers. Negative,
or cursed, inscription numbers are subject to change at any time, if new
cursed inscriptions are recognized.</p>
</li>
<li>
<p>At some as-of-yet unannounced block height in the future, new inscriptions
which would previously have been cursed will be blessed, and will receive
positive inscription numbers as part of the main sequence of inscription
numbers. Hopefully, this kind of community wide coordination is not a common
occurrence, but it may happen again from time to time, if it is advantageous
to recognize new kinds of inscriptions which previously would have been
invalid.</p>
</li>
<li>
<p>The commitment to the stability of inscription numbers does not preclude the
fixing of bona fide bugs. If there is a legitimate bug, and the only
reasonable way to fix it proves disruptive to inscription numbers, we will
fix it.</p>
</li>
</ul>
<p>Inscriptions are both a technical artifact and an artistic technology.
Technical considerations must contend on equal footing with aesthetic
considerations.</p>
<p>Inscription numbers are here to stay.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Inscriptions: A Guide for the Ideological Maxi</title>
      <link>https://rodarmor.com/blog/inscriptions-a-guide-for-the-ideological-maxi</link>
      <guid>https://rodarmor.com/blog/inscriptions-a-guide-for-the-ideological-maxi</guid>
      <pubDate>2023-12-29</pubDate>
      <content:encoded><![CDATA[<p>If you ask me my views, they will be nearly indistinguishable from those of,
for lack of a better term, ideological Bitcoin maximalists. I loathe the state,
have no particular respect for authority, and believe that Bitcoin is the path
away from the debauched debasement of our lives and civilization that fiat
currency has wrought.</p>
<p>However, I do not consider myself an ideological Bitcoin maximalist, with the
primary reason being that ideology often does not survive contact with reality.</p>
<p>This is the unenviable position that ideological Bitcoin maximalism, and the
insipid culture accompanying it, finds itself in at the present moment: an
uncomfortable contact with a reality with which it does not comport.</p>
<p>Ideological Bitcoin maximalism has a lot of good things going for it. It is
because of those things that this blog post was written. This post contains
advice for ideological Bitcoin maximalists, advice which will hopefully help
them stop scoring own goals and committing unforced errors. In other words, how
they can stop being losers.</p>
<p>Let me start by saying that this post is not written to defend ordinals and
inscriptions. They do not need defending. The cat is out the bag, and nobody
can put it back in.</p>
<p>Now, for the advice.</p>
<p>My first piece of advice is that whining about inscriptions makes you, and
Bitcoin, look weak. Simultaneously believing that Bitcoin <em>is</em> unstoppable
internet money and thinking that a bunch of retards publishing JPEGs on-chain
is any kind of problem is a contradiction. We both know the truth that, push
come to shove, the former is true and the latter is false. Bitcoin is
unstoppable internet money, and the JPEGs are a non-issue. But, by espousing
both beliefs, you weaken any argument you might make that Bitcoin can resist
the state.</p>
<p>For all the whining on Twitter, nobody has been able to make so much as a dent
in ordinals and inscriptions. So, given that, and given that we have important
work to do in destroying fiat, maybe you should stop whining about something
you can't change, and adjust to the new, and possibly uncomfortable reality
that NFTs have come to Bitcoin? This will no doubt not be the last time that
people start doing unpleasant things on Bitcoin, so it would be a good exercise
to start accepting it now. You can then refocus your efforts on more important
things, like spreading Satoshi's good word and helping as many people as
possible learn how to use Bitcoin.</p>
<p>Also, strategically, all press is good press, and complaining about
inscriptions just makes more people learn about them, and makes the inscribers
extra keen to nakadashi JPEGs into the blockchain, just to make you look like
idiots. If normies like doing something, then you're not going to make any
friends, or make any headway on anything, by scolding them for doing it.</p>
<p>If you still insist on complaining about inscriptions, at least take a moment
to learn about them, so you can ditch your worst and least compelling
arguments. These include:</p>
<ul>
<li>
<p><em>Anyone can right-click save the JPEGs.</em> Literally every degenerate buying
inscriptions knows this. Literally every single one. Nobody is buying
inscriptions based on the delusion that they are buying access. Accepting
this and updating your worldview will bring it closer to reality, and less
likely to be destroyed by it.</p>
</li>
<li>
<p><em>Inscriptions aren't real, they're just a collective hallucination.</em> I've
been saying basically exactly this since day one, that ordinals and
inscriptions are an opt-in lens with which to view Bitcoin. Behaving as if
this is some kind of damning revelation makes you look like a moron.
Additionally, it shows that you misunderstand one of the most fundamental
things about humans, civilization, and culture: <em>Everything important is just
social conventions.</em> <em>Bitcoin</em> is, in fact, just a social convention. Or, put
another way, it's not the software or data that matter, it's the social
conventions around it. Inscriptions are no different.</p>
</li>
<li>
<p><em>You can just store the data off-chain.</em> People value on-chain data. It makes
inscriptions scarce, and dramatically improves reliability and user-safety.
Every other NFT ecosystem uses off-chain data, and uninformed users delegate
trust to whoever happens to be pinning the files on IPFS, and they might stop
at any time. On-chain data is a vast improvement in trustlessness, which, I
am told, is highly valued by ideological maxis.</p>
</li>
<li>
<p><em>Inscriptions are illegitimate.</em> There's an obvious difference between things
that are illegitimate, like state violence, and things that you just think
are stupid. Arguing that something is illegitimate because you don't like it
or don't see the purpose of it makes you look like a retard.</p>
</li>
<li>
<p><em>Inscriptions are a state attack.</em> Somehow, you see NFTs and shitcoins on
other chains, understand that they exist because of enthusiasm, demand,
grift, and degeneracy, don't think that these things are a state attack on
Ethereum, and somehow turn around and think that they're a state attack on
Bitcoin?</p>
</li>
</ul>
<p>Attempting to censor inscriptions is exactly identical to attempting censoring
other kinds of transactions. Any machinery you build or public support you
muster will immediately lend support to censorship on Bitcoin in general.
Fortunately, processing transactions that someone views as illegitimate is
exactly the thing Bitcoin was built for, so you will ultimately fail, but we
would all be better of if you didn't try to convince people that censoring
Bitcoin transactions was something they should bother trying. You've already
managed to confuse Ocean Mining into thinking that it's possible and a good
idea, and although they'll eventually bend the knee even further than they
already have, it would be nice if we just got another mining pool, instead of
having it needlessly gimped right out of the gate.</p>
<p>So, what should you do about inscriptions?</p>
<p>Just ignore them. More valuable use-cases will price out the majority of
inscriptions. There will always be some high-value inscriptions, but they don't
compete seriously with hard money and uncensorable transactions. Bitcoin's
destiny is high fees. Embrace it.</p>
<p>We have much bigger fish to fry, and if you're interested in doing more than
just pearl clutching and engagement farming, we can all get to frying them.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Light Pools</title>
      <link>https://rodarmor.com/blog/light-pools</link>
      <guid>https://rodarmor.com/blog/light-pools</guid>
      <pubDate>2024-04-12</pubDate>
      <content:encoded><![CDATA[<p>Bitcoin has inscriptions and will soon have runes, protocols for bitcoin-native
digital artifacts and tokens.</p>
<p>However, these assets still suffer from a lack of decentralized trading venues.</p>
<p>Assets on other chains are commonly traded using automatic market makers, or
AMMs. AMMs pool assets and use simple formulae to dynamically price swaps
between assets.</p>
<p>They are efficient from an on-chain transaction cost perspective, but they are
still on-chain, requiring additional transaction overhead compared to that
required for the swaps themselves.</p>
<p>They also produce inefficient prices, since AMM prices can only change as a
result of on-chain activities: deposits, withdrawals, and executions, which are
costly.</p>
<p>Bitcoin lacks the Turing-complete smart contracts necessary for implementing
AMMs. Fortunately, there is an alternative which is more efficient, both from a
transaction cost and pricing perspective.</p>
<p>The idea behind light pools is simple. Users who wish to offer swaps between
Bitcoin-native assets, like rare sats, inscriptions, or runes, run nodes which
quote prices for swaps.</p>
<p>These quotes are signed messages, gossiped between other light pool nodes.
Quotes must include
<a href="https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki">BIP-322</a>
signatures of the UTXOs that contains the asset offered in trade. Requiring
signed quotes eliminates spam, since quotes can be rate-limited on a per-UTXO
basis. Additionally, when UTXOs are spent, corresponding offers can be dropped.</p>
<p>When a market taker wants to accept the quote of a market maker, they use the
information in the quote to construct a PSBT which includes their signatures,
and broadcast it to the network. These messages can also be gossiped by the
network, and rate-limited based on the taker's UTXOs. The maker receives this
message, possibly asyncronously, countersigns, and broadcasts it to the Bitcoin
network to be mined.</p>
<p>These PSBTs and transactions are not vulnerable to mempool sniping, since
signatures commit to all inputs and outputs.</p>
<p>Light pools require more implementation work than an AMM. Someone will need to
write an implementation of the gossip network, quote message format, and PSBT
construction and finalization. However, these are all done with a little bit of
elbow grease, and don't require tilting at the quixotic open-research-problem
windmills that plague much of cryptocurrency. (And Bitcoin, to be fair.)</p>
<p>The user experience of light pools should be quite good. Users can run their
own node to accumulate an order book, or rely on a third party. Prices can
update in real time, between blocks, without any on-chain activity.</p>
<p>Little work has been done on decentralized asset trading on Bitcoin, simply
because the market cap of Bitcoin-native assets was small. With rare sats,
inscriptions, and soon runes, the table is set and the time is ripe, and light
pools seem like a promising avenue to explore.</p>
]]></content:encoded>
    </item>
    <item>
      <title>How Ordinals Came to Be</title>
      <link>https://rodarmor.com/blog/how-ordinals-came-to-be</link>
      <guid>https://rodarmor.com/blog/how-ordinals-came-to-be</guid>
      <pubDate>2024-09-05</pubDate>
      <content:encoded><![CDATA[<p>There have been words on Twitter, so I thought it would be useful to write down
how ordinals came to be.</p>
<p>Ordinals is a few things. Ordinals proper is made up of ordinal numbers, the
numbering and tracking of satoshis, designed ultimately as vehicles for NFTs;
inscriptions, the NFTs which ride on the backs of ordinals; runes, the
degenerate black sheep of the protocol family; and <code>ord</code>, the open-source
computer program which implements ordinals, inscriptions, and runes.</p>
<p>Along the way there have been a two ordinals-related entities that I've been
involved with. The first was Ordinals Corporation, a short-lived startup
founded when ordinals, the protocol, started taking off, which was dissolved
nearly as soon as it was created, and did exactly nothing. The second is the
non-profit Open Ordinals Institute, a going concern, which accepts donations,
pays for the <a href="https://ordinals.com/">ordinals.com</a> servers, and funds
open-source contributors to <code>ord</code>.</p>
<p>I first learned about NFTs back when they were taking off on Ethereum in 2017.
I wasn't initially very interested in them, but I did talk a bit with my friend
Parker Day, a photographer, about turning some of her portraits into NFTs,
although we didn't wind up pursuing it.</p>
<p>NFTs came on my radar again in mid-2021, when
<a href="https://www.artblocks.io/curated/collections/fidenza-by-tyler-hobbs">Fidenza</a>
by Tyler Hobbs was released. I had made generative art in the past, but there
was never a market for it, and suddenly beautiful generative NFTs were selling
for real money. I experimented with NFTs on Ethereum, but was turned off, to
put it mildly, by the reality of NFTs on Ethereum. The tooling was terrible,
the ERC-721 standard meant that each NFT had different semantics, and the
content was all stored off-chain.</p>
<p>This, combined with my existing dislike of Ethereum, made me decide to try to
figure out how to make NFTs on Bitcoin which didn't suffer from the issues
inherent to existing NFTs on Ethereum and earlier standards for NFTs on
Bitcoin.</p>
<p>I started noodling. From the start, I wanted the protocol to be UTXO-based, and
to use Bitcoin's native cryptography and script for transactions. Anything else
would have been much more complex, much less featureful, and would not have fit
in nicely with the rest of the ecosystem. However, UTXOs are ephemeral. The pop
into existence when created by a transaction, and pop just as suddenly out of
existence when spent.</p>
<p>I had the idea for &quot;atoms&quot;, one of which would be created in every block, and
which would subsequently hop from coin to coin with each transaction. I made
the first to commit to the repo, then called <code>bitcoin-atoms</code>, on 2021-12-12.</p>
<p>My friend Liam Scalzulli, who I had worked on other open-source projects with,
started working on the project with me, making his first commit to the repo on
2022-1-28.</p>
<p>I had some very helpful conversations about atoms with mconst, Eric Sirion,
Rijndael, and Jeremy Rubin, and eventually came up with ordinals, the numbering
and tracking of individual satoshis, as an alternative to atoms. On 2022-1-5 I
renamed the <code>bitcoin-atoms</code> repo to <code>ord</code>. On 2022-2-22 I posted a
<a href="https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-February/019975.html">draft</a>
of the ordinals BIP to the bitcoin-dev mailing list, and on 2022-3-9 I bought
<a href="https://ordinals.com/">ordinals.com</a>, <a href="https://ordinals.net/">ordinals.net</a>,
and <a href="https://ordinals.org/">ordinals.org</a>. The <code>.net</code> and <code>.org</code> were free, but
the <code>.com</code> was for sale for $2000. Easily the best money I've ever spent!</p>
<p>I came up with an off-chain NFT scheme, where the creator of an NFT would sign
a message assigning a piece of content to an ordinal without needing to make a
Bitcoin transaction, and gave a workshop at BTC++ in Austin 2022-6-8, where
participants got paper wallets loaded with sats and issued their own NFTs.</p>
<p>Around this time Raph started working on the project, and made his first commit
on 2022-9-6. You can see the major contributors to the project over time,
including Liam and Raph,
<a href="https://github.com/ordinals/ord/graphs/contributors">on GitHub</a>.</p>
<p>The off-chain NFT scheme had a lot of issues. Users would need to send NFTs
out-of-band, and it would be impossible to run a public server with all NFTs,
since there were no rate or content size limits.</p>
<p>I started trying to figure out where I could stuff content into the Bitcoin
blockchain. Bitcoin script, in the form of scriptpubkeys or scriptsigs, were
the obvious choice. Most script types were limited in size, ether by consensus
or standardness, but taproot scripts had no limit, so they became the vehicle.
Funnily enough, these script-based NFTs were originally called &quot;runes&quot;, but we
switched to &quot;inscriptions&quot; and it stuck.</p>
<p>We did a lot of work on the wallet, and on 2022-12-14 I made the
<a href="https://ordinals.com/inscription/0">first mainnet inscription</a>, followed
quickly thereafter by the
<a href="https://ordinals.com/inscription/1">second mainnet inscription</a> by Rijndael.</p>
<p>The <code>ord wallet inscribe</code> command was initially disabled on mainnet, and on
2023-1-9 we enabled it, and on 2023-1-20 I tweeted that
<a href="https://x.com/rodarmor/status/1616567899719860230">inscriptions were ready for mainnet</a>.</p>
<p>That same day I opened
<a href="https://github.com/bitcoin/bips/pull/1408">the now infamous PR requesting a BIP number for ordinals</a>,
which languishes open to this day.</p>
<p>There was a trickle of inscriptions, then more, and then a rush, filling every
block. It was clear: Ordinals had gone nuclear.</p>
<p>With the protocol a wild success, I started having vague ideas about a startup,
unrelated to the protocol, because that seemed like that's was what one does in
those circumstances. On 2023-2-3 I incorporated Ordinals Corporation,
co-founded by myself, Ordinally, Erin, and Rocktoshi. Ordinals Corporation
never had a clear line of business, issued any shares, held any assets, or
undertook any business activities. It was dissolved less than three months
later on 2023-4-30. May it rest in peace.</p>
<p>The next few months were an insane rush of attention and chaos, and ultimately
extremely personally stressful. I took a hiatus from everything, although in
reality I hadn't been particularly productive even before making it official.
Things eventually started to get back to normal, and in August I started
working on <code>ord</code> again.</p>
<p>On 2023-8-1, the Open Ordinals Institute was incorporated, a much more
unambitious entity whose sole purpose was to accept donations, pay for the
<a href="https://ordinals.com">ordinals.com</a> servers, and fund open source contributors
to <a href="https://github.com/ordinals/ord/">ord</a>, which it continues to do to this
day.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Whence &apos;\n&apos;?</title>
      <link>https://rodarmor.com/blog/whence-newline</link>
      <guid>https://rodarmor.com/blog/whence-newline</guid>
      <pubDate>2024-09-17</pubDate>
      <content:encoded><![CDATA[<p>If you do <code>just foo</code>, the following <a href="https://github.com/casey/just/">justfile</a>
will write a single byte <code>0x0A</code> to a file named bar:</p>
<pre><code>x := &quot;\n&quot;

foo:
  printf '{{x}}' &gt; bar
</code></pre>
<p>Let's find out where that <code>0x0A</code> byte comes from.</p>
<p><code>just</code> is written in Rust, and the <code>just</code> parser has a function called
<code>cook_string</code>, which transforms a <code>just</code> string token containing escape
sequences into a UTF-8 string.</p>
<p>The code is here
<a href="https://github.com/casey/just/blob/ab7105afceabf7c3346e72eeafdaaf53ecbc0aa6/src/parser.rs#L731">here</a>.</p>
<p>With some irrelevant details elided, it looks like this:</p>
<pre><code>for c in text.chars() {
  match state {
    …
    State::Backslash =&gt; {
      match c {
        'n' =&gt; cooked.push('\n'),
        …
      }
      …
    }
    …
  }
}
</code></pre>
<p>So <code>just</code> asks <code>rustc</code> to insert the result of evaluating the <em>Rust</em> <code>'\n'</code>
character escape. Let's take a look at how <code>rustc</code> handles <code>'\n'</code>.</p>
<p><code>rustc</code>'s escape code handling is in the lexer, in a function called
<code>scan_escape</code>, which is
<a href="https://github.com/rust-lang/rust/blob/e2dc1a1c0f97a90319181a721ab317210307617a/compiler/rustc_lexer/src/unescape.rs#L240">here</a>.</p>
<p>With some details removed:</p>
<pre><code>let res: char = match chars.next().ok_or(EscapeError::LoneSlash)? {
    …
    'n' =&gt; '\n',
    …
};
</code></pre>
<p><code>rustc</code> is written in Rust and compiles itself, so somehow <code>rustc</code> is
delegating to <code>rustc</code> to figure out what <code>'\n'</code> means, which seems odd, to say
the least, and we still haven't seen the naked <code>0x0A</code> byte we're looking for.</p>
<p><code>rustc</code> wasn't always written in Rust though. Before it was self-hosted, early
versions were written in OCaml.</p>
<p>GitHub has old versions of the OCaml version of <code>rustc</code>, which handled
character escapes in the lexer
<a href="https://github.com/rust-lang/rust/blob/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot/fe/lexer.mll#L342">here</a>.</p>
<pre><code>and char_escape = parse
  …
  | 'n' { end_char (Char.code '\n') lexbuf }
  …
</code></pre>
<p>So <code>rustc</code> asks the OCaml compiler to insert the result of evaluating the
<em>OCaml</em> character escape <code>'\n'</code>. Which is totally reasonable, but still not a
<code>0x0A</code> in sight.</p>
<p>Going one step deeper, let's look the OCaml lexer
<a href="https://github.com/ocaml/ocaml/blob/4d6ecfb5cf4a5da814784dee7363a15ea278f324/lex/lexer.mll#L37">here</a>.</p>
<p>And finally, some clarity:</p>
<pre><code>let char_for_backslash = function
    'n' -&gt; '\010'
  …
</code></pre>
<p>When the OCaml compiler sees <code>\n</code>, it inserts the result of evaluating the
OCaml character escape <code>\010</code>, which is a decimal character escape, and since
<code>0x0A</code> is 10, we finally have our byte value.</p>
<p>So when have a <code>\n</code> character escape in your justfile, the <code>just</code> binary
contains a <code>0x0A</code> byte in some form, which it will then write to your final
string.</p>
<p>That <code>0x0A</code> byte was put there by <code>rustc</code>, which contained it's <em>own</em> <code>0x0A</code>
byte somewhere in the binary, which was stuffed there by its <code>rustc</code> progenitor.</p>
<p><code>rustc</code> is currently at version 1.81.0, so this has happened at least 81 times
since <code>rustc</code> 1.0 was first released, and probably many more times than that
before 1.0, with <code>rustc</code>s furtively smuggling <code>0x0A</code> bytes from one to the
other, all the way back to when it was written in OCaml, when finally the first
<code>0x0A</code> byte was stuffed into a <code>rustc</code> binary by the OCaml compiler, which
evaluated it from a decimal character escape <code>'\010'</code>.</p>
<p><em>This post was inspired by another post about exactly the same thing. I
couldn't find it when I looked for it, so I wrote this. All credit to the
original author for noticing how interesting this rabbit hole is.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>A Mental Model For Stretch Mediated Hypertrophy</title>
      <link>https://rodarmor.com/blog/a-mental-model-for-stretch-mediated-hypertrophy</link>
      <guid>https://rodarmor.com/blog/a-mental-model-for-stretch-mediated-hypertrophy</guid>
      <pubDate>2024-11-25</pubDate>
      <content:encoded><![CDATA[<p>Lots of studies support stretch-mediated hypertrophy: muscles grow more when
put under tension while lengthened.</p>
<p>I have a mental model for why this might be the case.</p>
<p>The load on a muscle under tension is spread out over the cross section of the
muscle, perpendicular to the direction of the load.</p>
<p>When a muscle is shortened, it bunches, spreading out the load over a larger
cross section.</p>
<p>When a muscle is lengthened, it stretches, concentrating the load over a
smaller cross section.</p>
<p>Imagine two Muscles in your body, one shortened, one lengthened, lifting a 100
pound Load from the floor.</p>
<p>The shortened muscle is on the left, and the lengthened muscle is on the right:</p>
<pre><code>MM    M
MM    M
|     M
L     M
      |
      L
</code></pre>
<p>In this very unrealistic diagram, the cross section of the shortened muscle is
two M &quot;units&quot; and the cross section of the lengthened muscle is one M &quot;unit&quot;,
so the shortened units of muscle each experience 50 pounds of load, and the
lengthened units of muscle each experience the full 100 pound load.</p>
<p>If mechanical tension on muscles is the most significant cause of hypertrophy,
then we want to concentrate it by stretching the muscle, as opposed to
spreading it out by bunching the muscle.</p>
<p>I have no idea if this model is actually true, but it makes sense to me!</p>
]]></content:encoded>
    </item>
    <item>
      <title>The BIP</title>
      <link>https://rodarmor.com/blog/the-bip</link>
      <guid>https://rodarmor.com/blog/the-bip</guid>
      <pubDate>2026-03-16</pubDate>
      <content:encoded><![CDATA[<p>The <a href="https://github.com/bitcoin/bips/pull/1408">ordinals BIP pull request</a> was
<a href="https://github.com/bitcoin/bips/pull/1408#issuecomment-3999762125">closed</a> on
March 4th, 2026 after being open for over three years.</p>
<p>I tried to respond to all topical comments and criticisms, which was made
slightly challenging by the fact that the thread was nearly completely
unmoderated.</p>
<p>I received some basic feedback on formatting and style from the BIP editors,
but no feedback relating to why or why not the pull request might be merged.
Occasionally, the scope of the BIPs repository was mentioned, but never what
that scope actually was, and how it might relate to the pull request.</p>
<p>The pull request was finally closed by Bryan Bishop, seemingly unilaterally,
with the comment &quot;I am rejecting this proposal to merge Ordinals into the BIP
repository and will not be assigning a number.&quot; It was also locked, which is,
as far as I can tell, totally unprecedented for an extensively discussed and
revised pull request.</p>
<p>I started writing this blog post without actually having a clear idea of <em>why</em>,
exactly, I was writing it, but I think, in the end, the best reason I can give
is that the whole process was incredibly frustrating, and venting about
frustrating things feels good.</p>
<p>In the spirit of improving the BIPs process, I wanted to provide what is
hopefully actionable feedback for the BIP editors from the perspective of a BIP
author:</p>
<ul>
<li>
<p>BIP editors should provide specific feedback as to why a pull request isn't
being merged. Even if it is eventually closed, it is far preferable to know
why and to be able to understand and respond. It is deeply unsatisfying as a
contributor to have to ask in private for feedback, or hope that an editor
will explain their thinking in a Twitter thread.</p>
</li>
<li>
<p>BIP editors should moderate PR threads. Hundreds of duplicative and off-topic
comments make following discussion challenging. Additionally, without
moderation it is impossible for a BIP author to know which pieces of
third-party feedback are substantive and should be addressed, and which can
be ignored.</p>
</li>
<li>
<p>Create a process for resolving disputes. I suggest that if the BIP editors
cannot come to an agreement to merge or close a PR after three months, it
should be closed and the author should be invited to re-submit it after a
year.</p>
</li>
<li>
<p>The BIP editors should, whenever questions of the scope of the BIPs repo come
up with respect to a particular BIP, explain what they believe the scope of
the repo is, and how it relates to the BIP in question. Whenever there is
enough clarity and agreement, the scope of the repo should be codified in
writing in a process BIP. If BIPs which were previously accepted are later
decided to be out-of-scope going forward, this should be clearly documented,
since accepted BIPs are otherwise a reasonable way for an outsider to
determine the scope of the BIPs process.</p>
</li>
<li>
<p>The BIP editors should not act unilaterally in closing a controversial PR.
Unilateral action by a BIP editor does not clarify the scope of the
repository, is clearly undesirable in principle, and makes such action more
likely in the future.</p>
</li>
</ul>
<p>If BIP editors adhered to the above, it's still entirely possible that the
ordinals BIP would have been closed. However, I would have gotten feedback on
why, had the opportunity to respond, and the process would have served to help
clarify the scope of the BIPs repository.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>