<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joe Miyamoto</title>
    <description>The latest articles on DEV Community by Joe Miyamoto (@joemphilips).</description>
    <link>https://dev.to/joemphilips</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F204905%2F3bea83b8-3a9f-4312-acff-0d6c67adffc3.jpeg</url>
      <title>DEV Community: Joe Miyamoto</title>
      <link>https://dev.to/joemphilips</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joemphilips"/>
    <language>en</language>
    <item>
      <title>Building c-lightning plugin with .NET</title>
      <dc:creator>Joe Miyamoto</dc:creator>
      <pubDate>Sun, 27 Mar 2022 10:53:58 +0000</pubDate>
      <link>https://dev.to/joemphilips/building-c-lightning-plugin-with-net-3162</link>
      <guid>https://dev.to/joemphilips/building-c-lightning-plugin-with-net-3162</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Update 2022/05/20: Based on the methodology described in this article, I have created a package for building your own plugin. please check out &lt;a href="https://github.com/joemphilips/DotNetLightning/"&gt;DotNetLightning.ClnRpc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently, I have been modifying &lt;a href="https://github.com/bitbankinc/NLoop"&gt;my own Lapps&lt;/a&gt; to work as a &lt;a href="https://github.com/ElementsProject/lightning/blob/master/doc/PLUGINS.md"&gt;c-lightning plugin&lt;/a&gt; in order to make them work with not only with &lt;a href="https://github.com/lightningnetwork/lnd"&gt;LND&lt;/a&gt; but also with &lt;a href="(https://github.com/ElementsProject/lightning)"&gt;c-lightning&lt;/a&gt; (&lt;a href="https://blockonomi.com/what-are-lapps/"&gt;What are Lapps?&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I couldn't find someone doing it with .NET/C#/F#, so I will leave here a guideline for how to.&lt;/p&gt;

&lt;p&gt;I also made &lt;a href="https://github.com/joemphilips/HelloWorldPlugin"&gt;a sample application&lt;/a&gt;, so if you are more interested in the sample than the explanation, please go there. My application is in F#, but this sample is written in C#. The language is different, but the basic approach is the same in both cases.&lt;/p&gt;

&lt;p&gt;In this case, we will assume that there is a single class named &lt;code&gt;MyAwesomeRpcServer&lt;/code&gt;, that has method handlers for RPC invocation. It starts out like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Logging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;StreamJsonRpc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;HelloWorldPlugin.Server&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyAwesomeRpcServerOptions&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;GreeterName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsInitiated&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyAwesomeRpcServer&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;MyAwesomeRpcServerOptions&lt;/span&gt; &lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyAwesomeRpcServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyAwesomeRpcServerOptions&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_opts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;JsonRpcMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;HelloAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;$"hello!! &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;! This is &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreeterName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; !!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The requirements are&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We want to expose an rpc method called hello.&lt;/li&gt;
&lt;li&gt;We want to return a message containing &lt;code&gt;GreeterName&lt;/code&gt; passed as a command line argument&lt;/li&gt;
&lt;li&gt;We want to return a message that includes the name passed as an RPC parameter from the User.&lt;/li&gt;
&lt;li&gt;The number of exposed RPC may increase in the future.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Create a JsonRPCServer using StreamJsonRPC.
&lt;/h3&gt;

&lt;p&gt;First, create an application that acts as an ordinary JsonRPC 2.0 server.&lt;br&gt;
The standard way to do this is to use the &lt;a href="https://github.com/microsoft/vs-streamjsonrpc"&gt;StreamJsonRpc&lt;/a&gt; library authored by MS.&lt;/p&gt;

&lt;p&gt;If you want to use it as a normal web server over HTTP, &lt;a href="https://github.com/tpeczek/Demo.AspNetCore.StreamJsonRpc"&gt;this sample&lt;/a&gt; is a good reference.&lt;br&gt;
However, the c-lightning plugin communicates with &lt;code&gt;lightningd&lt;/code&gt; itself via standard input/output, so this time we will use &lt;code&gt;Console.In&lt;/code&gt; and &lt;code&gt;Console.Out&lt;/code&gt; for transport.&lt;/p&gt;

&lt;p&gt;It looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rpcServer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MyAwesomeRpcServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonMessageFormatter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NewLineDelimitedMessageHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenStandardOutput&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenStandardInput&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rpc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonRpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddLocalRpcTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rpcServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;JsonRpcTargetOptions&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExceptionStrategy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ExceptionProcessing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommonErrorData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartListening&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Json RPC 2.0 specification does not specify the way of separating each messages as well as transports, so we must choose a suitable one.&lt;br&gt;
Since the c-lightning plugin uses newlines to delimit messages, we use &lt;code&gt;NewLineDelimitedMessageHandler&lt;/code&gt; as a message handler.&lt;br&gt;
Also, if the communication partner is not C# (which is not in our case), it is a good to specify &lt;code&gt;ExceptionStrategy&lt;/code&gt; as &lt;code&gt;ExceptionProcessing.CommonErrorData&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Make read/write operations thread-safe.
&lt;/h3&gt;

&lt;p&gt;Normally, the RPC server runs in multi-threaded mode, but writing to stdin/output in parallel will result in message corruption.&lt;br&gt;
The easiest way to deal with this problem is to process requests sequentially.&lt;/p&gt;

&lt;p&gt;In this case, the easiest way is to use &lt;code&gt;AsyncSemaphore&lt;/code&gt;, as &lt;a href="https://github.com/microsoft/vs-streamjsonrpc/blob/master/doc/resiliency.md"&gt;described in the official guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the case of plugins, performance issues related to rpc calls are rare, so we decided to limit writes by acquiring the semaphore for all methods.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Automatic generation of methods
&lt;/h3&gt;

&lt;p&gt;The c-lightning plugin must expose two RPC methods: &lt;code&gt;getmanifest&lt;/code&gt; and &lt;code&gt;init&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The former is to pass information from the plugin to c-lightning, and the latter is to pass information other way around when c-lightning is launched.&lt;/p&gt;

&lt;p&gt;Much of the processing logic can be generated automatically from other plugin method definitions, so we use reflection to keep things generic enough.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;getmanifest&lt;/code&gt; looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;JsonRpcMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"getmanifest"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ManifestDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetManifestAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;allowDeprecatedApis&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;otherParams&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;releaser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnterAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userDefinedMethodInfo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMethods&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BindingFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Public&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;BindingFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instance&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;BindingFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeclaredOnly&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSpecialName&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"initasync"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrdinalIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"getmanifestasync"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrdinalIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;userDefinedMethodInfo&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;argSpec&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetParameters&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;numDefaults&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
              &lt;span class="n"&gt;argSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasDefaultValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;keywordArgsStartIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;numDefaults&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
              &lt;span class="n"&gt;argSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrdinalIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrdinalIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;keywordArgsStartIndex&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$"[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;]"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLowerInvariant&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EndsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"async"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;[..^&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;RPCMethodDTO&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;Usage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_rpcDescriptions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Item1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="n"&gt;LongDescription&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_rpcDescriptions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;Item2&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ManifestDto&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
          &lt;span class="c1"&gt;// translate `System.CommandLine` to c-lightning compatible style.&lt;/span&gt;
          &lt;span class="n"&gt;CommandLines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetOptions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CliOptionsToDto&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;RpcMethods&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;Notifications&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;NotificationsDTO&lt;/span&gt;&lt;span class="p"&gt;[]{},&lt;/span&gt;
        &lt;span class="n"&gt;Subscriptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]{},&lt;/span&gt;
        &lt;span class="n"&gt;Hooks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
        &lt;span class="n"&gt;Dynamic&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;FeatureBits&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;init is as follows. This is more difficult to automate than getmanifest, and the process varies depending on the requirements of the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;JsonRpcMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"init"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;InitAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LnInitConfigurationDTO&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;releaser&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_semaphore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnterAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;maybeProp&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
          &lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;GetProperties&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrdinalIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;maybeProp&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;op&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;_opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsInitiated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;init passes method arguments as objects.&lt;br&gt;
The object has fields named &lt;code&gt;configurations&lt;/code&gt; and &lt;code&gt;options&lt;/code&gt;, So the method handler on the C# side must have a same name to automatically bind.&lt;/p&gt;

&lt;p&gt;In this case, we only bind the startup options givin by the c-lightning side to &lt;code&gt;_opts&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;LnInitConfigurationDto&lt;/code&gt;'s information on the c-lightning side (e.g. is an user using tor? What lightning feature bits are supported? ) can be used to freely perform the initialization process.&lt;/p&gt;

&lt;p&gt;We set &lt;code&gt;IsInitiated&lt;/code&gt; at the completion of the initialization process.&lt;br&gt;
This is used later to suspend the server startup process until the init message is received.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. JsonRPCLogger
&lt;/h3&gt;

&lt;p&gt;The fact that c-lightning and the plugin communicate via standard input/output means that logs cannot be sent to standard output at will.&lt;/p&gt;

&lt;p&gt;The existing c-lightning plugin sends a message to the c-lightning's &lt;code&gt;log&lt;/code&gt; rpc method as an rpc notification and leaves the rest of the processing to the c-lightning side.&lt;br&gt;
In this way, the logs are unified on the c-lightning side, making them easier to read.&lt;/p&gt;

&lt;p&gt;.NET is bundled with &lt;code&gt;ConsoleLogger&lt;/code&gt;, but this performs the writing process as a background task, so the aforementioned thread race may occur if we implement the logging logic in the same way.&lt;/p&gt;

&lt;p&gt;To solve these problem, &lt;a href="https://github.com/joemphilips/HelloWorldPlugin/blob/master/HelloWorldPlugin.Server/PluginLogger.cs"&gt;I have created my own ILoggerProvider&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. startup process
&lt;/h3&gt;

&lt;p&gt;c-lightning starts the plugin specified by the user at startup, passing the environment variable &lt;code&gt;LIGHTNINGD_PLUGIN=1&lt;/code&gt; when launching.&lt;/p&gt;

&lt;p&gt;Thus, the presence or absence of this environment variable can be used to determine in the program whether the application should be run as a plugin or not.&lt;/p&gt;

&lt;p&gt;In my case, I refer to this variable in two places&lt;br&gt;
The first is where you configure the host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IHostBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;configureHostBuilder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hostBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;isPluginMode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LIGHTNINGD_PLUGIN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isPluginMode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;hostBuilder&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddJsonRpcNotificationLogger&lt;/span&gt;&lt;span class="p"&gt;();})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceCollection&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;serviceCollection&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyAwesomeRpcServerOptions&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyAwesomeRpcServer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// configuration for running as a normal webserver.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other is during Host execution.&lt;br&gt;
We delay the execution of &lt;code&gt;IHost.RunAsync()&lt;/code&gt; as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hostBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;isPluginMode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LIGHTNINGD_PLUGIN"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isPluginMode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartJsonRpcServerForInitAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;/// initialize only rpc server and listen to `init` call.&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will delay the startup of &lt;code&gt;BackgroundService&lt;/code&gt; and log output until the init message is received from lightningd.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. compile as a single binary
&lt;/h3&gt;

&lt;p&gt;Finally, the plugin must be compiled as an executable single binary.&lt;br&gt;
Therefore, we utilize the &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file/overview"&gt;Single file Executable Compilation&lt;/a&gt; feature of .NET&lt;/p&gt;

&lt;p&gt;And that's it!&lt;br&gt;
You can specify the &lt;code&gt;--plugin&lt;/code&gt; or &lt;code&gt;--plugin-dir&lt;/code&gt; of c-lightning to launch the plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  publish as a library?
&lt;/h3&gt;

&lt;p&gt;At first, I thought about converting what I have done this time into a library and releasing it to the public, but since it is not that hard to do it, and the init process is difficult to automate, I will just leave the document and examples here.&lt;/p&gt;

&lt;p&gt;If you want to make it into a library, probably the best way is to use the &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview"&gt;Source Generator&lt;/a&gt;&lt;/p&gt;

</description>
      <category>lightningnetwork</category>
      <category>programming</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Prototyping generic Bitcoin Smart contract</title>
      <dc:creator>Joe Miyamoto</dc:creator>
      <pubDate>Fri, 11 Dec 2020 11:11:46 +0000</pubDate>
      <link>https://dev.to/joemphilips/prototyping-generic-bitcoin-smart-contract-26jl</link>
      <guid>https://dev.to/joemphilips/prototyping-generic-bitcoin-smart-contract-26jl</guid>
      <description>&lt;p&gt;While ago, I’ve been building &lt;a href="https://github.com/joemphilips/DotNetLightning" rel="noopener noreferrer"&gt;F# library for the Bitcoin Lightning Network (LN), DotNetLightning&lt;/a&gt;.&lt;br&gt;
After (barely) finishing my first iteration, I’ve noticed that there is a more matured &lt;a href="https://github.com/rust-bitcoin/rust-lightning" rel="noopener noreferrer"&gt;library called rust-lightning&lt;/a&gt; for doing the same for the rustlang, and I’ve switched my efforts to its &lt;a href="https://github.com/joemphilips/NRustLightning" rel="noopener noreferrer"&gt;.NET binding with C#&lt;/a&gt;&lt;br&gt;
After working for both F# and C# for a decent amount of time, I noticed that it both has goodies and baddies for different domains. &lt;br&gt;
One particular domain I think that F# is a clear winner is for prototyping a new idea.&lt;/p&gt;

&lt;p&gt;So today, I will sketch out my recent idea about Bitcoin and how I use F# to organize my thoughts in my head.&lt;/p&gt;

&lt;p&gt;But before that, I have to describe the overview about bitcoin smart contract and my thoughts about it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is a Smart contract?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Smart contract as a scripting language
&lt;/h3&gt;

&lt;p&gt;The word “Smart contract” is mostly used to refer to a byte code which is executed on the blockchain as a part of the consensus mechanism, and sometimes including a programming environment to write that byte code.&lt;br&gt;
One example of this is Solidity on Ethereum which compiles to the EVM byte code.&lt;/p&gt;

&lt;p&gt;The bitcoin has a similar construction (bitcoin script) which is intentionally made less descriptive than the EVM byte code. and there is a proposal for a high level language which compiles down to the actual bitcoin script, namely &lt;a href="http://bitcoin.sipa.be/miniscript/" rel="noopener noreferrer"&gt;Miniscript&lt;/a&gt; and its predecessor &lt;a href="https://github.com/ivy-lang/ivy-bitcoin" rel="noopener noreferrer"&gt;ivy-bitcoin&lt;/a&gt; &lt;a href="https://eprint.iacr.org/2018/122.pdf" rel="noopener noreferrer"&gt;BitML&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, at the same time at least in the Bitcoin community there is a consensus that writing a secure byte code is just a very little part of building the secure multi-party protocol.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Smart contract as a multi-party procedure
&lt;/h3&gt;

&lt;p&gt;Recently, the trend is to bring the statefulness to outside of the blockchain, and use the blockchain as a “dumb” settlement layer. Which makes sense in terms of privacy and scalability.&lt;/p&gt;

&lt;p&gt;In other words, the "smartness" of the contract is not in the blockchain but in the procedure among related party.&lt;/p&gt;

&lt;p&gt;To note a few keywords for such trend, there is a &lt;a href="https://github.com/ElementsProject/scriptless-scripts" rel="noopener noreferrer"&gt;Scriptless Scripts&lt;/a&gt;, &lt;a href="https://github.com/lightningnetwork/lightning-rfc" rel="noopener noreferrer"&gt;Lightning Network (LN)&lt;/a&gt; , &lt;a href="https://github.com/discreetlogcontracts/dlcspecs" rel="noopener noreferrer"&gt;Discreet Log Contract DLC&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;All these contracts are defined as a set of procedure among multi-party (in most case, two-party)&lt;br&gt;
For example something like&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Alice and Bob shares specific transaction and some of those signatures&lt;/li&gt;
&lt;li&gt;Both Verify signature and the shape of the transaction, if it is Ok Alice broadcast transaction XXX&lt;/li&gt;
&lt;li&gt;If Bob sees the transaction on the blockchain before timeout, he sends an Adapter Signature with the same key with XXX and Alice verifies it and… otherwise ...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Such a way of defining the contract is secure and fine. But can we achieve more generality somehow? If we could make some kind of universal language to describe the “shape” of the contract, it would be a good mental model for protocol developers to build/communicate new Smart contracts.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Smart contract as a Transaction graph
&lt;/h3&gt;

&lt;p&gt;At the same time, there is an old proposal by Jeremy Rubin called &lt;a href="https://rubin.io/projects/txgl/" rel="noopener noreferrer"&gt;TXGL&lt;/a&gt; , which defines not only the script for the contract but also the shape of whole transactions which could be involved in the contract. This is great as a mental model for the developers, but in reality it is not enough. Because, some transactions are related with each other outside of the shape (e.g. by &lt;a href="https://www.semanticscholar.org/paper/One-Time-Verifiably-Encrypted-Signatures-A.K.A.-Fournier/fdef41889571e22f86e95a6eb1838aaa06bb5737" rel="noopener noreferrer"&gt;Adaptor Signature&lt;/a&gt;) and those relations will affect how we communicate with each other in course of the contract.&lt;/p&gt;
&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;So, my hypothetical objective is&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Could we make a declarative Universal language (or DSL) to describe the “shape” of the contract? and&lt;/li&gt;
&lt;li&gt;Could we automatically compile that into an actual procedure describing what each party should do while executing the contract?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a very bold claim to make. And it might be impossible or overkill. But I have to try to make a PoC to see if it is really so.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The idea is affected by a proposal named  &lt;a href="https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-October/002222.html" rel="noopener noreferrer"&gt;Improv&lt;/a&gt;, which achieves something similar with the Miniscript but for a payment on the Lightning Network.&lt;br&gt;
It is supposed to look similar to the Miniscript but compiles down to a multi-party-procedure instead of the byte code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, let’s first survey existing proposed contracts, and try to abstract properties of those.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note for readers those familiar to the bitcoin protocol: I assume we are able to use &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki" rel="noopener noreferrer"&gt;Taproot&lt;/a&gt; and &lt;a href="https://bitcoinops.org/en/topics/ptlc/" rel="noopener noreferrer"&gt;PTLC&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  types of on-chain contracts
&lt;/h2&gt;

&lt;p&gt;It seems that most, if not every, on-chain contract has roughly three phases&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup: exchange transaction graph and some of its signatures, adaptor signatures&lt;/li&gt;
&lt;li&gt;Start: broadcast the root ancestor of those transactions (often called funding tx)&lt;/li&gt;
&lt;li&gt;Act: react to events which happen on the blockchain or through communication with another party.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My purpose here is to define the language to describe 1 and 2, and deterministically generate 3 from it. &lt;br&gt;
So, hopefully I can describe a contract with a set of transaction graphs. and the relation of the transactions in each graph.&lt;/p&gt;

&lt;p&gt;With that in mind, let’s make a graphical model for &lt;a href="https://github.com/ElementsProject/scriptless-scripts/blob/master/md/atomic-swap.md" rel="noopener noreferrer"&gt;Atomic swap with an adaptor signature&lt;/a&gt;. I won’t go into the details about the protocol.. The model will be something like&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxi443ap9ptmkpeq4iebx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxi443ap9ptmkpeq4iebx.png" alt="スクリーンショット 2020-12-11 19.51.32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, the model for &lt;a href="https://gist.github.com/RubenSomsen/8853a66a64825716f51b409be528355f" rel="noopener noreferrer"&gt;SAS: Succinct Atomic Swap&lt;/a&gt; will be&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fesfnvko9wxpcbzlgjqnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fesfnvko9wxpcbzlgjqnb.png" alt="スクリーンショット 2020-12-11 19.54.52"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Modeling with FSharp
&lt;/h3&gt;

&lt;p&gt;Then let’s model these relations using F# type. We are going to use &lt;a href="https://github.com/MetacoSA/NBitcoin" rel="noopener noreferrer"&gt;NBitcoin&lt;/a&gt; to represent Bitcoin specific classes, and my own &lt;a href="https://github.com/joemphilips/DotNetLightning" rel="noopener noreferrer"&gt;DotNetLightning&lt;/a&gt; off-chain specific types.&lt;/p&gt;

&lt;p&gt;Let’s say we call each node in the above graph &lt;code&gt;TxEntry&lt;/code&gt;,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;NBitcoin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;DotNetLightning&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// The object for describing the “Lock condition” of the on-chain payment.&lt;/span&gt;
&lt;span class="c1"&gt;/// It is not ready since the Miniscript is still in a research phase.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Miniscript&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NotYetReady&lt;/span&gt;
  &lt;span class="k"&gt;with&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;member&lt;/span&gt; &lt;span class="nc"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Miniscript&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;failwith&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nc"&gt;TODO&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;OnChainLock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Miniscript&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;EntryRelation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AtomicallySetup&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AtomicallyExecuted&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="c1"&gt;// each node in the graph.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt;
  &lt;span class="nc"&gt;Prev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;
  &lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;OnChainLock&lt;/span&gt;
  &lt;span class="nc"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;
  &lt;span class="nc"&gt;RelatedEntry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;EntryRelation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OnChain&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Contract is a set of graph of the &lt;code&gt;TxEntry&lt;/code&gt;, so let’s define it as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;TxTree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TxTree&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  types of off-chain contracts
&lt;/h2&gt;

&lt;p&gt;Bitcoin has two ways of payments, one is on-chain payment which must be recorded on the blockchain, and another is off-chain payment which is accomplished by the Lightning Network.&lt;/p&gt;

&lt;p&gt;The mechanism of off-chain payment is quite different from those of on-chain, but some operations are analogous.  (e.g. “we must commit to payment atomically to prevent &lt;a href="https://eprint.iacr.org/2019/896.pdf" rel="noopener noreferrer"&gt;option problem&lt;/a&gt;” or “Iff one payment is executed, another payment must be able to execute”).&lt;/p&gt;

&lt;p&gt;So we can use a similar terminology to describe the contract. &lt;br&gt;
See below table for how the “relation” of each entry is achieved in both on-chain and off-chain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3yugyfq2zjvmf7kwmq25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3yugyfq2zjvmf7kwmq25.png" alt="スクリーンショット 2020-12-11 19.58.27"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So for example, &lt;a href="https://blockonomi.com/submarine-swaps/" rel="noopener noreferrer"&gt;Submarine swap&lt;/a&gt; in the graphical representation could be.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgfg28yrjfvjbwq1k8z1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgfg28yrjfvjbwq1k8z1a.png" alt="スクリーンショット 2020-12-11 19.57.14"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Modeling in FSharp
&lt;/h3&gt;

&lt;p&gt;So next let’s include the concept of an “off-chain” entry into the above code. It will be like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;NBitcoin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;open&lt;/span&gt; &lt;span class="nc"&gt;DotNetLightning&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="c1"&gt;/// The object for describing the “Lock condition” of the on-chain payment.&lt;/span&gt;
&lt;span class="c1"&gt;/// It is not ready since the Miniscript is still in a research phase.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Miniscript&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NotYetReady&lt;/span&gt;
  &lt;span class="k"&gt;with&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;member&lt;/span&gt; &lt;span class="nc"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Miniscript&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;failwith&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="nc"&gt;TODO&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="c1"&gt;/// Same for off-chain Lock condition. Which also is not ready yet.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Improv&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NotYetReady&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;OnChainLock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Miniscript&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;OffChainLock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Improv&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;EntryRelation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AtomicallySetup&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;AtomicallyExecuted&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="c1"&gt;// each node in the graph.&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt;
  &lt;span class="nc"&gt;Prev&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;
  &lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;OnChainLock&lt;/span&gt;
  &lt;span class="nc"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt;
  &lt;span class="nc"&gt;RelatedEntry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;EntryRelation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;L2PaymentEntry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;EntryId&lt;/span&gt;
  &lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;OffChainLock&lt;/span&gt;
  &lt;span class="nc"&gt;RelatedEntry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EntryId&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;EntryRelation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;OnChain&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt;
  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;OffChain&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nc"&gt;L2PaymentEntry&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also update &lt;code&gt;Contract&lt;/code&gt; type to include both on-chain and off-chain concept&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;TxTree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TxEntry&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;PaymentTree&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;L2PaymentEntry&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TxTree&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;PaymentTree&lt;/span&gt; &lt;span class="kt"&gt;list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let’s define an actual Contract object for Submarine Swap.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;submarine_swap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alice_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount_to_bob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount_to_alice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;LNMoney&lt;/span&gt;&lt;span class="o"&gt;):&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;funding_tx_entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="nc"&gt;Prev&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;
        &lt;span class="nc"&gt;Lock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;  &lt;span class="nn"&gt;Miniscript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Parse&lt;/span&gt;&lt;span class="o"&gt;($&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pkh&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="n"&gt;alice_key&lt;/span&gt;&lt;span class="o"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;pkh&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="n"&gt;bob_key&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;pkh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alice_key&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;amount_to_bob&lt;/span&gt;
        &lt;span class="nc"&gt;Next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;Seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ofList&lt;/span&gt; &lt;span class="p"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;
        &lt;span class="nc"&gt;RelatedEntry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AtomicallySetup&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;swap_tx_entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="nc"&gt;Prev&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;funding_tx_entry&lt;/span&gt;
        &lt;span class="nc"&gt;Lock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Miniscript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Parse&lt;/span&gt;&lt;span class="o"&gt;($&lt;/span&gt;&lt;span class="s2"&gt;"pkh({bob_key})"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;amount_to_bob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Next&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;
        &lt;span class="nc"&gt;RelatedEntry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AtomicallyExecuted&lt;/span&gt;&lt;span class="o"&gt;);]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;off_chain_payment_entry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;lock_condition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bob_key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PubKey&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
            &lt;span class="nc"&gt;Lock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lock_condition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount_to_alice&lt;/span&gt;
            &lt;span class="nc"&gt;RelatedEntry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AtomicallyExecuted&lt;/span&gt;&lt;span class="o"&gt;)]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;funding_tx_entry&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;swap_tx_entry&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;off_chain_payment_entry&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is a very rough sketch of my recent thoughts, and it is still in an early phase.&lt;/p&gt;

&lt;p&gt;The next step will be to define the function to compile the &lt;code&gt;Contract&lt;/code&gt; object to an actual state machine to handle the procedure of an interaction with the another party (and the blockchain), that is, function with the type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight fsharp"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nc"&gt;ContractToProcedure&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Async&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the most difficult part, and I will probably change the definition of the &lt;code&gt;Contract&lt;/code&gt; on the way.&lt;/p&gt;

&lt;p&gt;What I want to point out here is that in the research phase like this, it is important for me to define an algebraic data type in a succinct way so that I can alter the definition while I go back and forward with an implementation.&lt;/p&gt;

&lt;p&gt;In other words, F# is very nice tool for &lt;a href="https://en.wikipedia.org/wiki/Exploratory_programming" rel="noopener noreferrer"&gt;Exploratory programming&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
