<?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: Oghenovo Usiwoma</title>
    <description>The latest articles on DEV Community by Oghenovo Usiwoma (@eunovo).</description>
    <link>https://dev.to/eunovo</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%2F412282%2F08ce5404-e1c1-482b-9d05-459512f4e143.jpg</url>
      <title>DEV Community: Oghenovo Usiwoma</title>
      <link>https://dev.to/eunovo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eunovo"/>
    <language>en</language>
    <item>
      <title>Elliptic Curve Concepts for Bitcoin Developers</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Sat, 05 Oct 2024 14:22:17 +0000</pubDate>
      <link>https://dev.to/eunovo/elliptic-curve-concepts-for-bitcoin-developers-18h5</link>
      <guid>https://dev.to/eunovo/elliptic-curve-concepts-for-bitcoin-developers-18h5</guid>
      <description>&lt;p&gt;Elliptic Curve Cryptography (ECC) plays a crucial role in securing digital assets like Bitcoin. Unlike traditional cryptographic methods, ECC provides a high level of security with smaller key sizes, making it more efficient and suitable for modern needs. This article explores the fundamentals of elliptic curves and their properties. By understanding ECC, you gain insight into the backbone of Bitcoin technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definition of Elliptic Curves
&lt;/h2&gt;

&lt;p&gt;An Elliptic Curve is a smooth curve in a two-dimensional plane which consists of the points satisfying the equation:&lt;br&gt;
&lt;code&gt;y^2 = x^3 + ax + b&lt;/code&gt; &lt;br&gt;
and a &lt;em&gt;point at infinity&lt;/em&gt;. We get different curves by varying the coefficients &lt;code&gt;a,b&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbu0w68qfzwcb7e5vuwl.png" alt="Two Elliptic Curves" width="800" height="453"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Curves for (a=-1, b=0) and (a=-1, b=1) &lt;a href="https://commons.wikimedia.org/w/index.php?curid=3112726" rel="noopener noreferrer"&gt;By GYassineMrabetTalk&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Finite Fields
&lt;/h2&gt;

&lt;p&gt;In cryptography, we define the Elliptic Curve over a &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Finite_field" rel="noopener noreferrer"&gt;finite field&lt;/a&gt;&lt;/em&gt;. This means that the values of &lt;code&gt;x&lt;/code&gt; in the curve equation are taken from a special set called a &lt;em&gt;finite field&lt;/em&gt;. The &lt;em&gt;Finite Field&lt;/em&gt; is a finite set of elements that satisfy the following rules under multiplication, addition, subtraction, and division operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Closure: The set is closed under addition and multiplication, meaning that if you add or multiply any two elements in the field, the result is also an element in the field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Associativity: Addition and multiplication in the field are associative, meaning that the grouping of operations does not change the result. For any elements a, b, and c, this means (a + b) + c = a + (b + c) and (a * b) * c = a * (b * c).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commutativity: Addition and multiplication are commutative in the field, which means the order of elements does not matter. For any elements a and b, a + b = b + a and a * b = b * a.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identity Elements:&lt;br&gt;
There is an additive identity (often denoted as 0), which means for any element a, a + 0 = a.&lt;br&gt;
There is a multiplicative identity (often denoted as 1), which means for any element a, a * 1 = a.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inverses:&lt;br&gt;
For every element a in the field, there is an additive inverse -a such that a + (-a) = 0.&lt;br&gt;
For every non-zero element a, there is a multiplicative inverse a^(-1) such that a * a^(-1) = 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Distributivity: Multiplication distributes over addition, meaning for any elements a, b, and c, the equation a * (b + c) = (a * b) + (a * c) holds true.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flund7piom7rqs0uovg1d.png" alt="A plot of an Elliptic Curve over a finite field" width="800" height="494"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;A plot of an Elliptic Curve over a finite field &lt;a href="https://commons.wikimedia.org/w/index.php?curid=34097328" rel="noopener noreferrer"&gt;By Trshaffer&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It is a closed system for numbers where we can only use a certain limited set of values. Think of it like the numbers on a clock. If you add 9 hours to 5 o'clock, you get 2 o'clock. This is because, after 12, the numbers "wrap around." A finite field is similar: it has a fixed set of numbers, and whenever an operation exceeds this range, it wraps around, just like on a clock.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why can't we define the curve over &lt;em&gt;Real Numbers&lt;/em&gt;?
&lt;/h3&gt;

&lt;p&gt;We could, but that would make the curve unsuitable for cryptography. Real Numbers are &lt;em&gt;infinite&lt;/em&gt; and &lt;em&gt;continuous&lt;/em&gt;. We cannot use this for cryptography because we want a finite set of keys, and we want each key to be discrete. Discrete values are easier to represent and operate on in binary.&lt;/p&gt;

&lt;p&gt;In ECC, the &lt;em&gt;Public key&lt;/em&gt; is a point on the Elliptic curve. It has x and y coordinates which look like real numbers, but they are part of a defined finite field for the curve.&lt;/p&gt;
&lt;h3&gt;
  
  
  Order of a Finite Field
&lt;/h3&gt;

&lt;p&gt;The order of a set is the number of elements in that set. A Finite field of order &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;GF(n)&lt;/code&gt;, has n elements:&lt;br&gt;
&lt;code&gt;{0, 1, ..., n-1}&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Modular Arithmetic
&lt;/h3&gt;

&lt;p&gt;Modular arithmetic is a system of arithmetic for integers, where numbers "wrap around" after reaching a certain value called the &lt;em&gt;modulus&lt;/em&gt;. It can be thought of like a clock, where after reaching 12, it wraps around to 1 again. If we have two integers &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt;, the modulus &lt;code&gt;n&lt;/code&gt; divides &lt;code&gt;a&lt;/code&gt; and leaves a remainder &lt;code&gt;r&lt;/code&gt;, and we say that &lt;code&gt;r&lt;/code&gt; is &lt;code&gt;a modulo n&lt;/code&gt; or &lt;code&gt;a mod n&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;a≡r (mod n)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can perform arithmetic operations by finding the result of the operation in &lt;code&gt;mod n&lt;/code&gt;. See the following examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5 + 4 = 9
9 ≡ 4 (mod 5)
therefore: 5 + 4 ≡ 4 (mod 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Simple n-modulo Finite Fields
&lt;/h3&gt;

&lt;p&gt;We can create a finite field using &lt;em&gt;modular arithmetic&lt;/em&gt;. An n-modulo finite field is a set of n numbers where all operations like addition, subtraction, multiplication, and division (except by zero) are performed "modulo n"—meaning that the results are taken as the remainder after division by n. An n-modulo finite field, &lt;code&gt;GF(n)&lt;/code&gt;, where n is a prime number, satisfies the rules of a field defined above. If n is not a prime number, the set will not have multiplicative inverses for all elements which breaks the requirements for a valid field.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Elliptic Curve Group
&lt;/h2&gt;

&lt;p&gt;A group is a set with a binary operation that satisfies the &lt;em&gt;closure&lt;/em&gt; property, &lt;em&gt;associativity&lt;/em&gt;, every element in the set has an &lt;em&gt;inverse&lt;/em&gt; element and it has an &lt;em&gt;identity&lt;/em&gt; element.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;closure&lt;/em&gt; property means that passing any two elements of the set, through the group binary operation, will produce a result also in the set. Consider our Finite field above under the addition operator as an example.   &lt;/p&gt;

&lt;p&gt;Associativity means that in the expression &lt;code&gt;a . b . c&lt;/code&gt; where a, b, and c are elements of the group and &lt;code&gt;.&lt;/code&gt; is the group operator, it doesn't matter where we put parenthesis so we can freely move it around.&lt;br&gt;
&lt;code&gt;(a . b) . c = a . (b . c)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The identity element, &lt;code&gt;O&lt;/code&gt;, of the group is the element that has no effect when applied to another element using the group operator:&lt;br&gt;
&lt;code&gt;a . O = a&lt;/code&gt;&lt;br&gt;
For example, in basic addition, &lt;code&gt;1 + 0 = 1&lt;/code&gt;, adding &lt;code&gt;0&lt;/code&gt; to any real number has no effect. &lt;code&gt;0&lt;/code&gt; is the identity element for real numbers under addition.&lt;/p&gt;

&lt;p&gt;The inverse of an element is its opposite and cancels it out in the group operation:&lt;br&gt;
&lt;code&gt;a . a^-1 = O&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The Elliptic Curve points, together with the &lt;em&gt;point at infinity&lt;/em&gt;(the identity element) form a group under the addition operator. This allows us to apply other theories from groups to Elliptic Curves. Note that the order of the group does not have to be the order of the finite field. The finite field can have elements that are not on the elliptic curve.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inverting an Elliptic Curve Point
&lt;/h3&gt;

&lt;p&gt;Given a point, &lt;code&gt;P(x, y)&lt;/code&gt;, the inverse, &lt;code&gt;-P&lt;/code&gt; is &lt;code&gt;(x, -y)&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Addition of Elliptic Curve Points
&lt;/h3&gt;

&lt;p&gt;The addition of points in EC is geometrically based. We:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add two points by drawing a straight line between them and finding the third point where the line intersects the curve then inverting this point. We invert the points to preserve the group axioms of the curve.&lt;/li&gt;
&lt;li&gt;When the two points are the same, we draw a tangent to the curve at this point, the inverse of the point where the tangent intersects the curve again is the result.&lt;/li&gt;
&lt;li&gt;Adding a point to its inverse results in the &lt;em&gt;point at infinity&lt;/em&gt;. This is because the line between &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;-P&lt;/code&gt; is vertical and will only intersect the curve at the &lt;em&gt;point at inifinity&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Adding a point to the &lt;em&gt;point at infinity&lt;/em&gt; results in the original point.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3hwru42aszst21m1gk3.png" alt="Addition of Elliptic Curve Points" width="680" height="206"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Addition of Elliptic Curve Points &lt;a href="https://commons.wikimedia.org/w/index.php?curid=2970559" rel="noopener noreferrer"&gt;By SuperManu&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Scalar Multiplication
&lt;/h3&gt;

&lt;p&gt;In linear algebra, a "scalar" is a single number used to "scale" a vector. In the context of Elliptic Curve Group theory, the scalar is a single number that scales a point on the elliptic curve. We do this by adding the point, P to itself n times where &lt;code&gt;n&lt;/code&gt; is the scalar. This is represented as &lt;code&gt;n.P&lt;/code&gt; or &lt;code&gt;nP&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Elliptic Curve Subgroups
&lt;/h2&gt;

&lt;p&gt;A subgroup is a subset of elements taken from a larger group that itself forms a group under the same operation as the larger group. We can form a subgroup by taking an element, G, of the group and repeatedly scaling that element G until we reach a scalar, &lt;code&gt;n&lt;/code&gt;, where:&lt;br&gt;
&lt;code&gt;nG = O (the identity element)&lt;/code&gt;&lt;br&gt;
Trying to scale &lt;code&gt;G&lt;/code&gt; with &lt;code&gt;n + 1&lt;/code&gt; will return &lt;code&gt;1G&lt;/code&gt;. Hence, there is a "wrap-around" at &lt;code&gt;nG&lt;/code&gt;. The scalar &lt;code&gt;n&lt;/code&gt; is the order of the subgroup because the subgroup has &lt;code&gt;n&lt;/code&gt; elements and scaling beyond &lt;code&gt;n&lt;/code&gt; results in elements we have already seen.&lt;br&gt;
A subgroup generated with an element G, contains the following elements:&lt;br&gt;
&lt;code&gt;{O, 1G, 2G, 3G, ..., nG}&lt;/code&gt;&lt;br&gt;
This theory applies to Elliptic Curves too. We can create an Elliptic Curve subgroup from a generator point, &lt;code&gt;G&lt;/code&gt;, with order &lt;code&gt;n&lt;/code&gt;. Note that a subgroup can also contain all the elements of the supergroup. &lt;/p&gt;
&lt;h2&gt;
  
  
  Elliptic Curve Parameters
&lt;/h2&gt;

&lt;p&gt;We describe an Elliptic Curve Subgroup with the following parameters:&lt;/p&gt;
&lt;h3&gt;
  
  
  Order of the field, &lt;code&gt;p&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This refers to the number of elements of the field. Recall from our discussion on Finite Fields that our simple finite field which uses &lt;em&gt;modular arithmetic&lt;/em&gt; must have a &lt;em&gt;prime&lt;/em&gt; order. Therefore, when choosing the order of the field, it must be a prime number.&lt;/p&gt;
&lt;h3&gt;
  
  
  Generator Point, &lt;code&gt;G&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Recall from our discussion on "Elliptic Curve Subgroups", that, by scaling a generator element, we can create a subgroup. The Generator Point, &lt;code&gt;G&lt;/code&gt;, is the generator for the elliptic curve subgroup. &lt;/p&gt;
&lt;h3&gt;
  
  
  Order of the subgroup, &lt;code&gt;n&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This the number of points in the elliptic curve subgroup. It is the scalar, &lt;code&gt;n&lt;/code&gt;, where:&lt;br&gt;
&lt;code&gt;nG = O (identity element)&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The Coefficients of the curve, &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Recall the curve equation for elliptic curves:&lt;br&gt;
&lt;code&gt;y^2 = x^3 + ax + b&lt;/code&gt;&lt;br&gt;
The coefficients &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are important parameters that affect the shape of the curve.&lt;/p&gt;
&lt;h3&gt;
  
  
  The cofactor, h
&lt;/h3&gt;

&lt;p&gt;This is the ratio of the order of the group to the order of the subgroup. It tells you how much bigger the group is than the subgroup. &lt;code&gt;h&lt;/code&gt; cannot be less than &lt;code&gt;1&lt;/code&gt; because this would mean that the subgroup does not fit inside the group. When &lt;code&gt;h&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;, it means that all the elements in the group are in the subgroup. When &lt;code&gt;h&lt;/code&gt; is greater than &lt;code&gt;1&lt;/code&gt;, it means there are elements in the group that are not in the subgroup. In EC, for &lt;code&gt;h &amp;gt; 1&lt;/code&gt;, we must check that a given point, &lt;code&gt;P&lt;/code&gt; is in our desired subgroup before working with it. &lt;code&gt;h = 1&lt;/code&gt; simplifies things and we do not need to check that the point is in our subgroup.&lt;/p&gt;
&lt;h2&gt;
  
  
  Projected Coordinates
&lt;/h2&gt;

&lt;p&gt;Some implementations of ECC, do not represent the EC point coordinates as (x, y), instead, they may use projected coordinates like the &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Jacobian_curve" rel="noopener noreferrer"&gt;Jacobian&lt;/a&gt;&lt;/em&gt; system &lt;code&gt;(X, Y, Z, T)&lt;/code&gt;.&lt;br&gt;
This allows the addition of points in a more efficient way than in affine coordinates.&lt;/p&gt;
&lt;h2&gt;
  
  
  The secp256k1 Curve
&lt;/h2&gt;

&lt;p&gt;Bitcoin uses the secp256k1 Curve. The parameters are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
G = (55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424)
a = 0
b = 7
n = 115792089237316195423570985008687907852837564279074904382605163141518161494337
h = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;n&lt;/code&gt; is a large prime number. This ensures a large cyclical subgroup and makes it difficult to solve the &lt;em&gt;Discrete Logarithm&lt;/em&gt; problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discrete Logarithm Problem
&lt;/h3&gt;

&lt;p&gt;The discrete logarithm problem is like knowing a blender recipe for a smoothie but not being able to figure out the exact ingredients just by tasting it. Imagine you have a secret recipe where you combine a certain number of berries, but after blending, it's hard to reverse-engineer how many berries were used without trying every possibility.&lt;/p&gt;

&lt;p&gt;In the case of elliptic curves, if you scale a point, it’s easy to get the new point. But if someone sees the result (the "smoothie") and wants to figure out what number you multiplied by (how many berries you used), it’s incredibly hard to do. This protects our secret keys in cryptography.&lt;/p&gt;

&lt;p&gt;For any element, &lt;code&gt;a&lt;/code&gt;, in our finite field of order p, &lt;code&gt;GF(p)&lt;/code&gt;, we can multiply &lt;code&gt;a&lt;/code&gt; by itself &lt;code&gt;n&lt;/code&gt; times to get a new number &lt;code&gt;x&lt;/code&gt; which will be in our field:&lt;br&gt;
&lt;code&gt;x = a^n mod p&lt;/code&gt;&lt;br&gt;
But given &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt;, it is difficult to find &lt;code&gt;n&lt;/code&gt;.&lt;br&gt;
For example, In GF(5) above, we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4^5 (mod 5)
4 * 4 * 4 * 4 * 4 = 1024
1024 / 5 = 204 remainder 4
4^5 = 4 (mod 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can't reverse the operation and find &lt;code&gt;n&lt;/code&gt; without checking all the possible values for &lt;code&gt;n&lt;/code&gt;. For a large group, the possible values of &lt;code&gt;n&lt;/code&gt; are too many, making this problem practically infeasible.&lt;/p&gt;

&lt;p&gt;In Elliptic Curves, the problem becomes finding the scalar &lt;code&gt;k&lt;/code&gt; such that:&lt;br&gt;
&lt;code&gt;Q = k.P&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret and Public Keys
&lt;/h2&gt;

&lt;p&gt;We generate pairs of keys in &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Public-key_cryptography" rel="noopener noreferrer"&gt;Public Key cryptography&lt;/a&gt;&lt;/em&gt;. Each key pair contains a public key and a secret key. A public key encrypts a message, producing a &lt;em&gt;Cyphertext&lt;/em&gt; that can only be decrypted by the corresponding secret key. The public key can be distributed openly for anyone to use for encryption.&lt;/p&gt;

&lt;p&gt;In Elliptic Curve Cryptography, we choose a large random scalar as our secret key, &lt;code&gt;k&lt;/code&gt;, and generate a public key by scaling the curve's generator, &lt;code&gt;G&lt;/code&gt;, with &lt;code&gt;k&lt;/code&gt;. The public key is therefore a point on the curve given by:&lt;br&gt;
&lt;code&gt;K = k.G&lt;/code&gt;&lt;br&gt;
With carefully selected curve parameters, we can release &lt;code&gt;K&lt;/code&gt; to the public and the secret key, &lt;code&gt;k&lt;/code&gt;, will remain secret, thanks to the intractability of the &lt;em&gt;Discrete Logarithm Problem&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In a future article, we will discuss the signatures used in Bitcoin, how they are generated and verified.&lt;/p&gt;

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

&lt;p&gt;In conclusion, elliptic curves provide a powerful mathematical framework for cryptographic applications, especially in systems like Bitcoin. Understanding the group structure, the importance of finite fields, and how elliptic curve points are manipulated through addition and scalar multiplication is crucial to understanding Bitcoin technology and its underlying security mechanisms.&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>programming</category>
    </item>
    <item>
      <title>What I missed about BIP143's scriptCode</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Mon, 10 Jul 2023 15:10:54 +0000</pubDate>
      <link>https://dev.to/eunovo/what-i-missed-about-bip143s-scriptcode-15mb</link>
      <guid>https://dev.to/eunovo/what-i-missed-about-bip143s-scriptcode-15mb</guid>
      <description>&lt;p&gt;I recently tried to create a Transaction to spend from a P2WPKH address. I couldn't get this to work. The &lt;code&gt;sendrawtransaction&lt;/code&gt; command kept failing with the error &lt;code&gt;non-mandatory-script-verify-flag (Signature must be zero for failed CHECK(MULTI)SIG operation) (code -26)&lt;/code&gt;. I narrowed the problem down to incorrectly hashing the sighash. I did not create the sighash as specified by the &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification" rel="noopener noreferrer"&gt;BIP143 Specification&lt;/a&gt;. I'll share my experience navigating this problem here.&lt;/p&gt;

&lt;p&gt;A P2WPKH address is Segwit's version of a P2PKH address (See &lt;a href="https://en.wikipedia.org/wiki/SegWit" rel="noopener noreferrer"&gt;SegWit on Wikipedia&lt;/a&gt;). A P2PKH address uses the scriptPubKey shown below:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;It requires the spender to provide the following scriptSig:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://learnmeabitcoin.com/technical/p2pkh" rel="noopener noreferrer"&gt;Here's a good article explaining p2pkh addresses&lt;/a&gt;. My (apparently flawed) understanding of P2WPKH was that it does the same thing but with SegWit so I assumed that it had the same &lt;code&gt;scriptPubKey&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Spending from a P2WPKH address requires an &lt;a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm" rel="noopener noreferrer"&gt;ecdsa signature&lt;/a&gt;. The message that will be signed is the &lt;strong&gt;SigHash&lt;/strong&gt;. The &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification" rel="noopener noreferrer"&gt;BIP143 Specification&lt;/a&gt; outlined the following items to be serialized into the SigHash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     1. nVersion of the transaction (4-byte little endian)
     2. hashPrevouts (32-byte hash)
     3. hashSequence (32-byte hash)
     4. outpoint (32-byte hash + 4-byte little endian) 
     5. scriptCode of the input (serialized as scripts inside CTxOuts)
     6. value of the output spent by this input (8-byte little endian)
     7. nSequence of the input (4-byte little endian)
     8. hashOutputs (32-byte hash)
     9. nLocktime of the transaction (4-byte little endian)
    10. sighash type of the signature (4-byte little endian)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I found item 5, the &lt;code&gt;scriptCode of the input&lt;/code&gt; to be confusing. I thought this might be referring to the &lt;code&gt;scriptPubKey&lt;/code&gt; of the input UTXO but this led to wrong SigHash messages and wrong signatures, hence, my transactions were rejected. After hours of debugging, I discovered that further down in BIP143, there is a section that specifies what the &lt;code&gt;scriptCode&lt;/code&gt; is for spending from a &lt;code&gt;P2WPKH&lt;/code&gt; address, shown below.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For &lt;code&gt;P2WPKH&lt;/code&gt; witness program, the &lt;code&gt;scriptCode&lt;/code&gt; is &lt;code&gt;0x1976a914{20-byte-pubkey-hash}88ac&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;0x19&lt;/code&gt; indicates the number of bytes in the script. &lt;code&gt;0x19&lt;/code&gt; is &lt;code&gt;25&lt;/code&gt; in decimal. This indicates that the script has &lt;code&gt;25&lt;/code&gt; bytes. &lt;br&gt;
&lt;code&gt;0x76a9&lt;/code&gt; is code for &lt;code&gt;OP_DUP OP_HASH160&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;0x14&lt;/code&gt; is &lt;code&gt;20&lt;/code&gt; in decimal and it is interpreted as &lt;code&gt;OP_PUSHBYTES20&lt;/code&gt; which pushes the next &lt;code&gt;20&lt;/code&gt; bytes into the stack.&lt;br&gt;
&lt;code&gt;0x88ac&lt;/code&gt; is code for &lt;code&gt;OP_EQUALVERIFY OP_CHECKSIG&lt;/code&gt;.&lt;br&gt;
See the analysis of a Transaction with a similar output &lt;a href="https://developer.bitcoin.org/reference/transactions.html#txout-a-transaction-output" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;scriptCode&lt;/code&gt; seemed to be the &lt;code&gt;P2WPKH&lt;/code&gt; address &lt;code&gt;scriptPubKey&lt;/code&gt;, but the signatures were wrong, why?&lt;/p&gt;

&lt;p&gt;After logging the actual &lt;code&gt;utxo.scriptPubKey&lt;/code&gt;, I discovered that it was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OP_0 OP_PUSHBYTES_20 &amp;lt;pubkey_hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wasn't what I expected. I had forgotten something crucial about &lt;code&gt;P2WPKH&lt;/code&gt;. SegWit only requires that you specify the segwit version, which is &lt;code&gt;0&lt;/code&gt; in this case and the 20-byte &lt;code&gt;pubkey_hash&lt;/code&gt;. See &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh" rel="noopener noreferrer"&gt;the P2WPKH section on BIP141&lt;/a&gt;. This is called a &lt;em&gt;forwarding script&lt;/em&gt;. See this excerpt from &lt;a href="https://github.com/Xekyo/bips/blob/730a813124680a417f44bfe8117afbc89fd1ea6c/bip-tx-terminology.mediawiki" rel="noopener noreferrer"&gt;bip-tx-terminology&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;forwarding script&lt;br&gt;
[Concept] A collective term for scripts that redirect input validation to another script or data structure. Witness programs and P2SH Programs are forwarding scripts. Forwarding scripts make use of script templates that imply additional evaluation steps beyond the explicitly expressed conditions. In the case of P2SH, the output script in verbatim only implies that the redeem script must be the preimage of the hash in the output script, but the template prescribes that the redeem script must additionally be satisfied. For witness programs, the output script is even less verbose with more implied meaning.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;DISCLAIMER: This terminology is still pending and it's not widely used yet. See &lt;a href="https://github.com/Xekyo/bips/pull/1" rel="noopener noreferrer"&gt;https://github.com/Xekyo/bips/pull/1&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The nodes in the Bitcoin network understand that this &lt;code&gt;scriptPubKey&lt;/code&gt; is a &lt;code&gt;Segwit_v0_P2WPKH&lt;/code&gt; &lt;code&gt;scriptPubKey&lt;/code&gt; and they know the script template to use. All I had to do was create a new script following the &lt;code&gt;scriptCode&lt;/code&gt; template and use that to make my sighash.&lt;/p&gt;

&lt;p&gt;In Rust, using the &lt;a href="https://docs.rs/crate/bitcoin/latest" rel="noopener noreferrer"&gt;bitcoin crate&lt;/a&gt;, the &lt;code&gt;scriptCode&lt;/code&gt; and &lt;code&gt;sighash&lt;/code&gt; can be made like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let script_code = bitcoin::script::Builder::new()
        .push_opcode(OP_DUP)
        .push_opcode(OP_HASH160)
        .push_slice(&amp;amp;pub_key.wpubkey_hash().unwrap())
        .push_opcode(OP_EQUALVERIFY)
        .push_opcode(OP_CHECKSIG)
        .into_script();

let message = SighashCache::new(unsigned_tx)
        .segwit_signature_hash(input_index, script_code, value, sighash_type);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Bitcoin crate also provides a function to do this for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let mut sighash = SighashCache::new(unsigned_tx);
let (message, _) = psbt.sighash_ecdsa(0, &amp;amp;mut sighash).unwrap();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;While the &lt;code&gt;scriptCode&lt;/code&gt; looks like it should be the &lt;code&gt;scriptPubKey&lt;/code&gt; for &lt;code&gt;P2PWPKH&lt;/code&gt; addresses, it is not. &lt;code&gt;P2WPKH&lt;/code&gt; uses a forwarding script specified by BIP141 and the actual &lt;code&gt;scriptCode&lt;/code&gt; must be constructed using the defined script template.&lt;/p&gt;

</description>
      <category>bitcoin</category>
    </item>
    <item>
      <title>The PSBT Standard</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Mon, 29 May 2023 06:27:57 +0000</pubDate>
      <link>https://dev.to/eunovo/the-psbt-standard-i0d</link>
      <guid>https://dev.to/eunovo/the-psbt-standard-i0d</guid>
      <description>&lt;p&gt;PSBT is short for Partially Signed Bitcoin Transaction. It is a standard for defining transactions that can be signed by multiple signers across different clients. It contains the necessary information for a signer to produce a signature for a transaction. This is specifically beneficial for offline signers as they cannot fetch additional information about a transaction. The original PSBT format was specified in &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki" rel="noopener noreferrer"&gt;BIP 174&lt;/a&gt; and a Version 2 in progress in &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0370.mediawiki" rel="noopener noreferrer"&gt;BIP 370&lt;/a&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  The PSBT Binary format
&lt;/h2&gt;

&lt;p&gt;The PSBT format consists of key-value maps separated by a &lt;code&gt;0x00&lt;/code&gt; byte. It supports the following maps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Global Map&lt;/strong&gt; contains key-value pairs that apply to the entire transaction&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Input Map&lt;/strong&gt; contains key-value pairs that apply to individual inputs&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Output Map&lt;/strong&gt; contains key-value pairs that apply to individual outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key-value pairs in each map all follow this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;keylen&amp;gt; &amp;lt;keytype&amp;gt; &amp;lt;keydata&amp;gt; &amp;lt;valuelen&amp;gt; &amp;lt;valuedata&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;keylen&lt;/code&gt;, &lt;code&gt;keytype&lt;/code&gt; and &lt;code&gt;valuelen&lt;/code&gt; are specified as a &lt;a href="https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer" rel="noopener noreferrer"&gt;compact size unsigned integer&lt;/a&gt; which ensures values that can be specified in one byte will be specified in one byte, for example, the decimal number ten is specified as &lt;code&gt;0x0a&lt;/code&gt; instead of &lt;code&gt;0x000a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;keydata&lt;/code&gt; is not always available. Some key types like &lt;code&gt;PSBT_GLOBAL_UNSIGNED_TX = 0x00&lt;/code&gt; do not have &lt;code&gt;keydata&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To see the full list of key types supported, go to &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki" rel="noopener noreferrer"&gt;BIP 174&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's look at a few examples:&lt;/p&gt;

&lt;p&gt;We'll start by breaking down this PSBT which is an unsigned tx with 0 inputs and 0 outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;70736274ff01000a0000000000000000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;magic&amp;gt; 0x70736274ff // used to identify PSBT data
&amp;lt;global-map&amp;gt; // contains global transaction data
&amp;lt;keylen&amp;gt; 0x01 // Key length is one byte
&amp;lt;keytype&amp;gt; 0x00 // PSBT_GLOBAL_UNSIGNED_TX
&amp;lt;valuelen&amp;gt; 0x0a // 10 bytes
&amp;lt;valuedata&amp;gt; 0x00000000000000000000 // The Tx hex
&amp;lt;separator&amp;gt; 0x00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's breakdown another simple unsigned PSBT data with 1 input and 1 output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x70736274ff0100550200000001eb63366191dbaf74d30c6de8cbb7208de3fb65ad266b41c56990a5a7e6a2eac90000000000ffffffff010017a804000000001976a914c1752bf5bffbd320ab2ab625b32b9fe48337dce488ac00000000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;magic&amp;gt; 0x70736274ff
&amp;lt;global-map&amp;gt;
&amp;lt;keylen&amp;gt; 0x01 // Key length is one byte
&amp;lt;keytype&amp;gt; 0x00 // PSBT_GLOBAL_UNSIGNED_TX
&amp;lt;valuelen&amp;gt; 0x55 // 85 bytes
&amp;lt;valuedata&amp;gt; 0x0200000001eb63366191dbaf74d30c6de8cbb7208de3fb65ad266b41c56990a5a7e6a2eac90000000000ffffffff010017a804000000001976a914c1752bf5bffbd320ab2ab625b32b9fe48337dce488ac00000000 // The Unsigned Tx hex
&amp;lt;separator&amp;gt; 0x00
&amp;lt;input-map&amp;gt;
&amp;lt;separator&amp;gt; 0x00
&amp;lt;output-map&amp;gt;
&amp;lt;separator&amp;gt; 0x00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Signing a PSBT
&lt;/h2&gt;

&lt;p&gt;The Signer uses the UTXOs provided in the PSBT to produce signatures for inputs. The signer performs some checks before signing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For non-witness inputs, the signer verifies that the &lt;code&gt;txid&lt;/code&gt; of the non-witness utxo matches the &lt;code&gt;txid&lt;/code&gt; specified in the unsigned transaction.&lt;/li&gt;
&lt;li&gt;For witness-inputs, the signer verifies that the &lt;code&gt;witnessScript&lt;/code&gt; (if provided) matches the hash specified in the UTXO or the &lt;code&gt;redeemScript&lt;/code&gt;, and the &lt;code&gt;redeemScript&lt;/code&gt; (if provided) matches the hash in the UTXO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any signatures created by the Signer must be added as a &lt;code&gt;PSBT_IN_PARTIAL_SIG = 0x02&lt;/code&gt; key-value pair for the respective input it relates to. If a Signer cannot sign a transaction, it must not add a Partial Signature.&lt;/p&gt;

&lt;p&gt;Our previous PSBT spends from a non-witness utxo. Before we sign it, we must add the &lt;code&gt;PSBT_IN_NON_WITNESS_UTXO = 0x00&lt;/code&gt; key-value pair for that input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0100b6020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402bd0300ffffffff02c817a804000000002321035b4a568361af71783c22a6c9d9a13e3d5f32d9a7278c0e8325e4bc29b0090825ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000000000000000000000000000000000000000000000000000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The global map is unchanged but new data has been added to the input map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;input map&amp;gt;
&amp;lt;keylen&amp;gt; 0x01 // 1 byte
&amp;lt;keytype&amp;gt; 0x00 // PSBT_IN_NON_WITNESS_UTXO, requires no keydata
&amp;lt;valuelen&amp;gt; 0xb6 // 182 bytes
&amp;lt;valuedata&amp;gt; // the transaction in network serialization format the current input spends from
0x020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402bd0300ffffffff02c817a804000000002321035b4a568361af71783c22a6c9d9a13e3d5f32d9a7278c0e8325e4bc29b0090825ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000
&amp;lt;separator&amp;gt; 0x00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sign, we add the following &lt;code&gt;PSBT_IN_PARTIAL_SIG = 0x02&lt;/code&gt; key-value pair to the input pair:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;keylen&amp;gt; 0x22 //
&amp;lt;keytype&amp;gt; 0x02 // PSBT_IN_PARTIAL_SIG keytype
&amp;lt;keydata&amp;gt; 0x035b4a568361af71783c22a6c9d9a13e3d5f32d9a7278c0e8325e4bc29b0090825
&amp;lt;valuelen&amp;gt; 0x47
&amp;lt;valuedata&amp;gt;
3044022063179cb0f91d2b1d2c45d8112a527e4491ec771befb62c5717afac69f42345d9022035b3c00d8cb2f6309e0c0f6df03f54ae3e0bd6c4cae68061a714b57cf4f8cd8c01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Finalizing a PSBT
&lt;/h2&gt;

&lt;p&gt;The Finalizer validates each input, removes the partial sigs and constructs the &lt;code&gt;PSBT_IN_FINAL_SCRIPTSIG = 0x07&lt;/code&gt; and &lt;code&gt;PSBT_IN_FINAL_SCRIPTWITNESS = 0x08&lt;/code&gt; for each input and places them in the Input Map.&lt;/p&gt;

&lt;p&gt;Our finalized PSBT looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x70736274ff0100550200000001eb63366191dbaf74d30c6de8cbb7208de3fb65ad266b41c56990a5a7e6a2eac90000000000ffffffff010017a804000000001976a914c1752bf5bffbd320ab2ab625b32b9fe48337dce488ac0000000000
// Global map is unchanged

0100b6020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402bd0300ffffffff02c817a804000000002321035b4a568361af71783c22a6c9d9a13e3d5f32d9a7278c0e8325e4bc29b0090825ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000
// PSBT_IN_NON_WITNESS_UTXO is unchanged

// PSBT_IN_PARTIAL_SIG has been removed

&amp;lt;keylen&amp;gt; 0x01
&amp;lt;keyvalue&amp;gt; 0x07 // PSBT_IN_FINAL_SCRIPT_SIG
&amp;lt;valuelen&amp;gt; 0x48
&amp;lt;value&amp;gt; 0x473044022063179cb0f91d2b1d2c45d8112a527e4491ec771befb62c5717afac69f42345d9022035b3c00d8cb2f6309e0c0f6df03f54ae3e0bd6c4cae68061a714b57cf4f8cd8c01
0000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Extracting a serialized transaction
&lt;/h2&gt;

&lt;p&gt;The Extractor uses the unsigned transactions and signatures provided in the PSBT to construct a serialized transaction.&lt;/p&gt;

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

&lt;p&gt;The PSBT standard is a key innovation in the world of Bitcoin transactions. We have only scratched its surface, if you want to read the full specification, go to &lt;a href="https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki" rel="noopener noreferrer"&gt;BIP 174&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>bitcoinjs</category>
      <category>web3</category>
      <category>bitcoin</category>
    </item>
    <item>
      <title>NodeJS Stream Processing: Build a Simple multipart/form-data parser</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Wed, 03 May 2023 06:40:11 +0000</pubDate>
      <link>https://dev.to/eunovo/nodejs-stream-processing-build-a-simple-multipartform-data-parser-lmn</link>
      <guid>https://dev.to/eunovo/nodejs-stream-processing-build-a-simple-multipartform-data-parser-lmn</guid>
      <description>&lt;p&gt;&lt;strong&gt;TLDR:&lt;/strong&gt; I build a simple multipart/form-data parser in TypeScript to demonstrate how stream processing works. &lt;a href="https://github.com/Eunovo/parsing-multipart-requests-in-nodejs" rel="noopener noreferrer"&gt;You can checkout the github repo here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Streams are integral to Node.js, empowering developers to handle data in a more resource-efficient and scalable manner. In essence, a stream is an abstract interface within Node.js designed for the management of streaming data. It offers a mechanism for reading or writing data progressively over a certain period, instead of loading all data simultaneously into memory. This makes streams instrumental in efficiently processing massive data volumes without obstructing the event loop or overwhelming the memory. Node.js features four distinct stream types: Readable, Writable, Duplex, and Transform. Each stream type is equipped with its unique set of methods and events for seamless streaming data manipulation.&lt;/p&gt;

&lt;p&gt;The NodeJS &lt;a href="https://nodejs.org/api/http.html#class-httpincomingmessage" rel="noopener noreferrer"&gt;http.IncomingMessage&lt;/a&gt; extends &lt;a href="https://nodejs.org/api/stream.html#class-streamreadable" rel="noopener noreferrer"&gt;stream.Readable&lt;/a&gt; which means we can read incoming request data using the Readable stream API. We can read data calling its "read" method or listening for its "data" event. We will be using &lt;a href="https://www.npmjs.com/package/through2" rel="noopener noreferrer"&gt;through2&lt;/a&gt; to transform this &lt;code&gt;IncomingMessage&lt;/code&gt; stream into one that outputs the form data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The multipart/form-data format
&lt;/h2&gt;

&lt;p&gt;"Multipart" refers to a type of message that contains multiple parts of pieces of data that are combined into a single message. HTTP clients use the media type "multipart/form-data" to send &lt;br&gt;
files and data to an HTTP Server. &lt;/p&gt;

&lt;p&gt;Each part of the multipart message is separated by a &lt;strong&gt;boundary&lt;/strong&gt;. The boundary is a string of characters, and it is provided by the HTTP client in the &lt;code&gt;content-type&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;See an example of a &lt;code&gt;multipart/form-data&lt;/code&gt; request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /upload HTTP/1.1
Host: reqbin.com
Content-Type: multipart/form-data; boundary=0000
Content-Length: 526

--0000
Content-Disposition: form-data; name="username"

[Username]
--0000
Content-Disposition: form-data; name="file"; filename="image1.jpg"
Content-Type: image/jpeg

[image data]
--0000
Content-Disposition: form-data; name="file"; filename="image2.jpg"
Content-Type: image/jpeg

[image data]
--0000--
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our case, each part of the multipart message is a field from a form. The Content Disposition header gives us information about the field. We can identify file-type fields by checking for a &lt;code&gt;filename&lt;/code&gt; in the disposition header. &lt;/p&gt;

&lt;h2&gt;
  
  
  The plan
&lt;/h2&gt;

&lt;p&gt;Extracting fields from the request stream is way harder than it seems (at least to me it was). There are some key ideas that I employed to eventually achieve this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Split data processing into multiple stages
&lt;/h3&gt;

&lt;p&gt;Trying to identify the field boundaries and then processing each field data at the same time was difficult. I couldn't get it working perfectly.&lt;br&gt;
In contrast, separating the problem into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;identifying field boundaries&lt;/li&gt;
&lt;li&gt;parsing field data
was surprisingly easy.
I decided to implement this as two different streams:&lt;/li&gt;
&lt;li&gt;The first stream detects field boundaries, collects the data between the boundaries and outputs that data&lt;/li&gt;
&lt;li&gt;The second stream processes the field data and outputs a Javascript object. 
I used &lt;a href="https://www.npmjs.com/package/through2" rel="noopener noreferrer"&gt;through2&lt;/a&gt; to create the two streams and combine them into one "form" stream.
### Sliding Windows
Detecting boundary and new line characters required another breakthrough. The input stream provides data in chunks. A chunk of data is an array of bytes. In each chunk, you may have partial or full boundary or new line characters. To reliably detect these strings of characters, I &lt;strong&gt;slide&lt;/strong&gt; each character in each chunk through a buffer of length &lt;strong&gt;n&lt;/strong&gt; from the right. Eventually, the buffer will get full and the oldest character in the buffer will be shifted out for the next character.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;After I shift the buffer left for each new character, I compare the contents of the buffer to see if it matches my target string&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This acts like a &lt;strong&gt;sliding window&lt;/strong&gt; for detecting strings of characters of length, &lt;strong&gt;n&lt;/strong&gt;. See a pseudo code below;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;boundary = 'boudary...chars...'
slidingBuffer = createFixedLengthBuffer(boudary.length)
stream.on((chunk) =&amp;gt; {
  data = []
  for (byte in chunk) {
     shiftedOutChar = shiftLeft(slidingBuffer, byte)
     data.push(shiftedOutChar)
     if (equals(slidingBuffer, boundary)) {
       // Boundary detected
     }
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Implementation
&lt;/h2&gt;

&lt;p&gt;Let's create a quick &lt;code&gt;http&lt;/code&gt; server to receive our &lt;code&gt;multipart/form-data&lt;/code&gt; request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createFormStream&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./create-form-stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IMakeServerProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;onText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;onFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;onText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;onFile&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;IMakeServerProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&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="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Method Not Allowed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;multipart/form-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;415&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unsupported Media Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;boundary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;boundary=&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// Extract boundary characters&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFormStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;onText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&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="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;onFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;server&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;In &lt;code&gt;create-form-stream.ts&lt;/code&gt;, we define the &lt;code&gt;createFormStream(stream, boundary)&lt;/code&gt; which starts by defining some buffers that we will need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;boundarySlidingBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fieldBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create our first stream to output each field data in one chunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;through2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Detect boundaries and output each field chunk&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shiftLeft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boundarySlidingBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Shift into our sliding buffer&lt;/span&gt;
                    &lt;span class="nx"&gt;fieldBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;fieldBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Concat shifted out data with existing field data in fieldBuffer&lt;/span&gt;
                    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boundarySlidingBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// Boundary detected&lt;/span&gt;
                        &lt;span class="c1"&gt;// Remove "\r\n" from the beginning and end then push&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;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fieldBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="nx"&gt;fieldBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Clear fieldBuffer&lt;/span&gt;
                        &lt;span class="nx"&gt;boundarySlidingBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boundary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Clear sliding buffer&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nf"&gt;callback&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 second stream processes each field data chunk:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;through2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dataStartIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newLineSlidingBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shiftLeft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newLineSlidingBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
                    &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&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="nx"&gt;newLineSlidingBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newLine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// New line detected&lt;/span&gt;
                        &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="c1"&gt;// Break at first empty line. Time for data!&lt;/span&gt;
                            &lt;span class="nx"&gt;dataStartIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;

                        &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="nx"&gt;newLineSlidingBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FieldBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;disposition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseDisposition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
                &lt;span class="nx"&gt;builder&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disposition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filename&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="nx"&gt;lines&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="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseContentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lines&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="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;);&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;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nx"&gt;builder&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataStartIndex&lt;/span&gt;&lt;span class="p"&gt;))&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="p"&gt;);&lt;/span&gt;

                &lt;span class="nf"&gt;callback&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope that this article has given you a better understanding of how to work with streams in Node.js and how your favorite multipart/form-data parser library works.&lt;br&gt;
The code for this article can be found &lt;a href="https://github.com/Eunovo/parsing-multipart-requests-in-nodejs" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Introduction to Miniscript</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Wed, 03 May 2023 06:06:44 +0000</pubDate>
      <link>https://dev.to/eunovo/introduction-to-miniscript-4im4</link>
      <guid>https://dev.to/eunovo/introduction-to-miniscript-4im4</guid>
      <description>&lt;p&gt;&lt;a href="https://bitcoin.sipa.be/miniscript/" rel="noopener noreferrer"&gt;Miniscript&lt;/a&gt; is a representation for Bitcoin scripts that allows composition, analysis, and compilation from spending policies. It has a structure that enables various properties such as correctness, security, and malleability. It translates into Bitcoin Script, the language used to specify spending conditions on the Bitcoin network.&lt;/p&gt;

&lt;p&gt;Miniscript offers benefits over the traditional Bitcoin scripting language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It allows developers to create complex Bitcoin transactions without having to write custom scripts from scratch. This can save developers a lot of time and effort, and also reduce the risk of errors in the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It uses a simpler and more predictable syntax that makes it easier to audit and verify the code. This can help reduce the risk of bugs and vulnerabilities in the code, which can help improve the overall security of Bitcoin transactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article assumes that you have an understanding of the Bitcoin Scripting language, that you understand how it uses the Stack and that you are familiar with the major opcodes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Policies and Fragments
&lt;/h2&gt;

&lt;p&gt;Miniscript policies are written in the Miniscript Policy language, they specify spending conditions for Bitcoin Transaction Outputs. Miniscript policies are made up of fragments, which are building blocks that can be combined to create more complex policies.&lt;br&gt;
These polices are compiled into Miniscript which is then compiled into Bitcoin Script.&lt;/p&gt;

&lt;p&gt;To create a simple pay-to-pubkey script in Miniscript policy language, you can use the &lt;code&gt;pk(key)&lt;/code&gt; fragment. This fragment allows you to create an output that can only be spent by the owner of the specified public key (pk). The &lt;code&gt;pk(key)&lt;/code&gt; policy compiles into &lt;code&gt;pk(key)&lt;/code&gt; in Miniscript which compiles into &lt;code&gt;&amp;lt;key&amp;gt; OP_CHECKSIG&lt;/code&gt; in Bitcoin Script. This was a simple scenario where the policy language and miniscript script are the same but as we will see, this is not always the case.&lt;/p&gt;

&lt;p&gt;Some of the most commonly used Miniscript fragments include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt;: This fragment resolves to &lt;code&gt;0&lt;/code&gt; in Bitcoin script.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt;: This fragment resolves to &lt;code&gt;1&lt;/code&gt; in Bitcoin script.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pk(key)&lt;/code&gt;: This fragment allows you to create an output that can only be spent by the owner of the specified public key (pk).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pkh(key)&lt;/code&gt;: This fragment allows you to create an output that can only be spent by the owner of the private key associated with the specified public key hash (pkh).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;older(n)&lt;/code&gt;: This fragment allows you to create an output that can only be spent after a certain number of blocks have been mined (n).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;after(n)&lt;/code&gt;: This fragment allows you to create an output that can only be spent after a certain date and time (n).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hash160(h)&lt;/code&gt;: This fragment allows you to create an output that can only be spent by providing a signature that hashes to the specified hash value (h).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;and_b(x, y)&lt;/code&gt;: This fragment allows you to create an output that can only be spent if both x and y are satisfied.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;or_b(x, y)&lt;/code&gt;: This fragment allows you to create an output that can be spent if either x or y is satisfied.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;thresh(k, pol_1,…, pol_n)&lt;/code&gt;: This fragment allows you to create an output that can only be spent if k of the n policies are satisfied.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;multi(k, key_1, …, key_n)&lt;/code&gt;: This fragment allows you to create an output that can only be spent if k of the n specified public keys (keys) sign the transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These fragments can be combined in various ways to create more complex spending conditions for Bitcoin transactions. See the full list of fragments &lt;a href="https://bitcoin.sipa.be/miniscript/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's create a policy that allows an output to be spent by &lt;code&gt;key1&lt;/code&gt; or &lt;code&gt;key2&lt;/code&gt;. We use the &lt;code&gt;or_b&lt;/code&gt; and &lt;code&gt;pk(key)&lt;/code&gt; fragments to achieve this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;or_b(pk(key1),pk(key2))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This Miniscript policy compiles to&lt;br&gt;
&lt;code&gt;or_b(pk(key_1),s:pk(key_2))&lt;/code&gt;&lt;br&gt;
in Miniscript which is &lt;br&gt;
&lt;code&gt;&amp;lt;key_1&amp;gt; OP_CHECKSIG OP_SWAP &amp;lt;key_2&amp;gt; OP_CHECKSIG OP_BOOLOR&lt;/code&gt;&lt;br&gt;
in Bitcoin Script.&lt;/p&gt;

&lt;p&gt;This will create an output that can be spent by providing a signature that matches either of the specified public keys (key1 or key2). The signature would be verified against the public key using the &lt;code&gt;OP_CHECKSIG&lt;/code&gt; opcode.&lt;/p&gt;

&lt;p&gt;Let's take a look at a slightly more complicated policy: &lt;code&gt;thresh(3,pk(key_1),pk(key_2),pk(key_3),older(12960))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It compiles into:&lt;br&gt;
&lt;code&gt;thresh(3,pk(key_1),s:pk(key_2),s:pk(key_3),sln:older(12960))&lt;/code&gt;&lt;br&gt;
in Miniscript.&lt;/p&gt;

&lt;p&gt;This policy specifies a spending condition that requires 3 signatures before 90 days but only require 2 signatures subsequently. It is a 3-of-3 multisig that turns into a 2-of-3 multisig after 90 days.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of how this policy works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The “thresh” fragment specifies that at least 3 of the specified conditions must be satisfied to spend the output.&lt;/li&gt;
&lt;li&gt;The “pk” fragments specify the public keys that can be used to spend the output.&lt;/li&gt;
&lt;li&gt;The “older” fragment specifies that after 12960 blocks (about 90 days), the script will change to a 2-of-3 multisig.&lt;/li&gt;
&lt;li&gt;Before 90 days, the &lt;code&gt;older(12960)&lt;/code&gt; policy cannot be satisfied, hence, you need the signatures for &lt;code&gt;key_1, key_2 and key_3&lt;/code&gt; to meet the &lt;code&gt;thresh&lt;/code&gt; requirement.&lt;/li&gt;
&lt;li&gt;After 90 days, the &lt;code&gt;older(12960)&lt;/code&gt; policy is satisfied and you only need two signatures to meet the &lt;code&gt;thresh&lt;/code&gt; requirement. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://bitcoin.sipa.be/miniscript/" rel="noopener noreferrer"&gt;https://bitcoin.sipa.be/miniscript/&lt;/a&gt; has a Miniscript policy to Miniscript compiler. It also shows the resulting Bitcoin Script.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Miniscript Type System
&lt;/h2&gt;

&lt;p&gt;Miniscript uses a type system to ensure that the scripts are safe and secure to use. The type system enables static analysis and runtime checks that ensure the scripts are well-formed and that they do not contain any errors or vulnerabilities.&lt;/p&gt;

&lt;p&gt;There are four basic types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"&lt;strong&gt;B&lt;/strong&gt;" B-type expressions are "Base Expressions". They push a nonzero value onto the stack when satisfied and exact zero when dissatisfied.&lt;/li&gt;
&lt;li&gt;"&lt;strong&gt;V&lt;/strong&gt;" V-type expressions are "Verify Expressions". They abort script execution when dissatisfied but do no push any value to the stack when satisfied.&lt;/li&gt;
&lt;li&gt;"&lt;strong&gt;K&lt;/strong&gt;" K-type expressions are "Key Expressions". They take inputs from the top of the stack, and they push a key onto the stack. A signature is still required to satisfy the expression.&lt;/li&gt;
&lt;li&gt;"&lt;strong&gt;W&lt;/strong&gt;" W-type expressions are "Wrapped Expressions". They take inputs from &lt;em&gt;one below the top of the stack&lt;/em&gt;. They push their result either &lt;em&gt;on top of the stack or one below&lt;/em&gt;. In case of satisfaction, they push a nonzero value and a zero value in case of dissatisfaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apart from the basic types, there are also type modifiers: &lt;code&gt;z&lt;/code&gt;, &lt;code&gt;o&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;u&lt;/code&gt;. Each of them guarantees additional properties, for example:&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;Bz&lt;/code&gt; describes an expression that &lt;strong&gt;pushes a nonzero value to the stack when satisfied and a zero otherwise&lt;/strong&gt; because it is a Base expression but it also &lt;strong&gt;consumes exactly zero elements&lt;/strong&gt; because it has the "&lt;strong&gt;z&lt;/strong&gt;" modifier.&lt;/p&gt;

&lt;p&gt;An expression can be converted from one type to another by applying wrappers. Wrappers look like this &lt;code&gt;v:&lt;/code&gt; and they are applied to expressions like this:&lt;br&gt;
&lt;code&gt;v:&amp;lt;Expression&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are rules that specify what wrappers can be applied to what expression types and what the type of the resulting expression will be. For example;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;v:&lt;/code&gt; can only be applied to an expression of type "B" and the resulting expression will have a type "V". Observe:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;v:older(n)&lt;/code&gt; is valid because &lt;code&gt;older(n)&lt;/code&gt; is a "B" expression.&lt;br&gt;
&lt;code&gt;older(n)&lt;/code&gt; compiles to &lt;code&gt;&amp;lt;n&amp;gt; OP_CHECKSEQUENCEVERIFY&lt;/code&gt; but&lt;br&gt;
&lt;code&gt;v:older(n)&lt;/code&gt; compiles to &lt;code&gt;&amp;lt;n&amp;gt; OP_CHECKSEQUENCEVERIFY OP_VERIFY&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can also combine wrappers like this:&lt;br&gt;
&lt;code&gt;dv:older(n)&lt;/code&gt;&lt;br&gt;
The &lt;code&gt;d:&lt;/code&gt; wrapper is applied to the &lt;code&gt;v:&lt;/code&gt; wrapper which is applied to the &lt;code&gt;older(n)&lt;/code&gt; fragment. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;v:&lt;/code&gt; wrapper converts &lt;code&gt;older(n)&lt;/code&gt; to a "V" type&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;d:&lt;/code&gt; wrapper converts &lt;code&gt;v:older(n)&lt;/code&gt; to a "B" type
Hence the type of the resulting expression is "B".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This &lt;a href="https://bitcoin.sipa.be/miniscript/" rel="noopener noreferrer"&gt;page&lt;/a&gt; also has the complete list of wrappers, their requirements, types and properties.&lt;/p&gt;

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

&lt;p&gt;In conclusion, Miniscript is a powerful scripting language that allows for complex Bitcoin transactions to be created with ease. It's simple syntax and modular design make it easy to use and understand, even for those who are new to Bitcoin scripting. Additionally, Miniscript’s flexibility and extensibility make it a great choice for developers who want to create custom Bitcoin transactions that meet their specific needs.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>bitcoinjs</category>
    </item>
    <item>
      <title>Minimalizing Witness weight for Taproot spend script paths with Huffman's Algorithm</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Sun, 26 Mar 2023 05:54:22 +0000</pubDate>
      <link>https://dev.to/eunovo/minimalizing-witness-weight-for-taproot-spend-script-paths-with-huffmans-algorithm-1j74</link>
      <guid>https://dev.to/eunovo/minimalizing-witness-weight-for-taproot-spend-script-paths-with-huffmans-algorithm-1j74</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;I implement a Huffman Taptree constructor in Typescript for Bitcoinjs-lib. Find the code &lt;a href="https://github.com/Eunovo/bitcoinjs-huffman-constructor" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Taproot is a recent upgrade to Bitcoin that enhances the privacy and efficiency of complex transactions by introducing a new type of output that can be spent either by providing a signature for the public key (keypath spend) or by satisfying a script contained within the hidden "script-tree". A script-tree is a kind of &lt;a href="https://en.wikipedia.org/wiki/Merkle_tree" rel="noopener noreferrer"&gt;Merkle tree&lt;/a&gt; that encodes a hierarchy of scripts that represent different spending scenarios, each with a unique path from the root. Spending any of these scripts requires a proof that the script is present in the tree. The length of the proof depends on the position of the script in the tree. Longer proofs incur more transaction fees because they create larger transactions.&lt;/p&gt;

&lt;p&gt;One way to reduce transaction fees is to arrange your script-tree such that the scripts that are more likely to be used for spending, require shorter proof. These scripts need to be closer to the root of the tree. We can use &lt;a href="https://en.wikipedia.org/wiki/Huffman_coding" rel="noopener noreferrer"&gt;Huffman's Algorithm&lt;/a&gt; to arrange the script-tree so that the most likely or frequent spend paths are shorter and incur less transaction fees.&lt;/p&gt;

&lt;p&gt;Bitcoinops' &lt;a href="https://colab.research.google.com/github/bitcoinops/taproot-workshop/blob/Colab/2.5-huffman.ipynb#scrollTo=NQldp2NExVC3" rel="noopener noreferrer"&gt;Schnorr Taproot workshop&lt;/a&gt; has a great section on "Huffman TapTree Constructors". I'll show how to implement this in Typescript for bitcoinjs-lib. You can find the github repo for this article, &lt;a href="https://github.com/Eunovo/bitcoinjs-huffman-constructor" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What we are trying to minimize is the &lt;code&gt;Expected-witness-weight&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expected-witness-weight =
      Probability-of-A * Witness-weight-A
    + Probability-of-B * Witness-weight-B
    + Probability-of-C * Witness-weight-C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can minimize the expected witness weight by putting those scripts with higher probability closer to the root of the tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Method
&lt;/h2&gt;

&lt;p&gt;Suppose we have three spend scripts represented by A, B and C. We determine that B is twice as likely to be spent as A and C, so we assign the scripts the following weights:&lt;br&gt;
&lt;code&gt;A: 1, B: 2, C: 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We want to arrange our script-tree such that B is much closer to the root than A and C. We will use Huffman's algorithm and take the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sort the scripts A, B and C by weight in ascending order and put them in a queue.&lt;/li&gt;
&lt;li&gt;Pick the first two nodes in the queue and create a new branch from the two of them. Set the weight of this new node to be the sum of the weights of its children. &lt;/li&gt;
&lt;li&gt;Put this new node back into the queue with sorting order maintained. That is, we must find the correct position for the new node given its weight and put it there.&lt;/li&gt;
&lt;li&gt;Repeat steps 2 and 3 until there's only one node left in the queue. This node is the root node for the script-tree.&lt;/li&gt;
&lt;/ol&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%2Fuploads%2Farticles%2Fc1qq6ma5pc3aisbbjj8x.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%2Fuploads%2Farticles%2Fc1qq6ma5pc3aisbbjj8x.png" alt="Huffman taptree constructor example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Let's define types to be used in the implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tapleaf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Taptree&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bitcoinjs-lib/src/types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;leaf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Tapleaf&lt;/span&gt; &lt;span class="p"&gt;}[];&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Taptree&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use bitcoinjs-lib's &lt;code&gt;Tapleaf&lt;/code&gt; and &lt;code&gt;Taptree&lt;/code&gt; because we want to be able to use our resulting script-tree with bitcoinjs-lib.&lt;/p&gt;

&lt;p&gt;This is our function definition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sortScriptsIntoTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Taptree&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Create a sorted list of nodes from our inputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leaf&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SortedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Create a list sorted in ascending order of frequency&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;I've created a &lt;code&gt;SortedList&lt;/code&gt; class to handle creating and maintaining a sorted list. See the code, &lt;a href="https://github.com/Eunovo/bitcoinjs-huffman-constructor/blob/main/src/utils.ts" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Pick the first two nodes in the queue and create a new branch from the two of them. Set the weight of this new node to be the sum of the weights of its children.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Construct a new node from the two nodes with the least frequency&lt;/span&gt;
&lt;span class="nx"&gt;nodeA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// There will always be an element to pop&lt;/span&gt;
&lt;span class="nx"&gt;nodeB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// because loop ends when length &amp;lt;= 1&lt;/span&gt;
&lt;span class="nx"&gt;newNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&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;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Put this new node back into the queue with sorting order maintained. That is, we must find the correct position for the new node given its weight and put it there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The &lt;code&gt;SortedList&lt;/code&gt; class will use binary search to find the correct index for the new node in the sorted list&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Repeat steps 2 and 3 until there's only one node left in the queue. This node is the root node for the script-tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Construct a new node from the two nodes with the least frequency&lt;/span&gt;
    &lt;span class="nx"&gt;nodeA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// There will always be an element to pop&lt;/span&gt;
    &lt;span class="nx"&gt;nodeB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// because loop ends when length &amp;lt;= 1&lt;/span&gt;
    &lt;span class="nx"&gt;newNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// Place newNode back into sorted list&lt;/span&gt;
    &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Last node in sortedNodes is the root node&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete &lt;code&gt;sortScriptsIntoTree&lt;/code&gt; function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sortScriptsIntoTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Inputs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Taptree&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leaf&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SortedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;nodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Create a list sorted in ascending order of frequency&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Construct a new node from the two nodes with the least frequency&lt;/span&gt;
        &lt;span class="nx"&gt;nodeA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// There will always be an element to pop&lt;/span&gt;
        &lt;span class="nx"&gt;nodeB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// because loop ends when length &amp;lt;= 1&lt;/span&gt;
        &lt;span class="nx"&gt;newNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;nodeA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nodeB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="c1"&gt;// Place newNode back into sorted list&lt;/span&gt;
        &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Last node in sortedNodes is the root node&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sortedNodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;node&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;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/Eunovo/bitcoinjs-huffman-constructor/tree/main/tests" rel="noopener noreferrer"&gt;tests folder&lt;/a&gt; contains tests for the huffman constructor and the SortedList class. I check that the huffman constructor works when scripts are provided with equal weights, negative weights, infinity etc. I encourage you to take a look as this is the only way you can tell that the huffman constructor is doing what you expect it to do.&lt;/p&gt;

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

&lt;p&gt;Thank you for reading, if you need help understanding how to spend taproot script paths, check out my article on &lt;a href="https://dev.to/eunovo/a-guide-to-creating-taproot-scripts-with-bitcoinjs-lib-4oph"&gt;creating taproot scripts&lt;/a&gt;.&lt;br&gt;
You can find the github repo for this article, &lt;a href="https://github.com/Eunovo/bitcoinjs-huffman-constructor" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>taproot</category>
      <category>javascript</category>
    </item>
    <item>
      <title>More on Taproot</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Sun, 26 Mar 2023 05:49:06 +0000</pubDate>
      <link>https://dev.to/eunovo/more-on-taproot-41g8</link>
      <guid>https://dev.to/eunovo/more-on-taproot-41g8</guid>
      <description>&lt;p&gt;In a &lt;a href="https://dev.to/eunovo/a-guide-to-creating-taproot-scripts-with-bitcoinjs-lib-4oph"&gt;previous article&lt;/a&gt;, I gave a brief intro Taproot and shared some examples utilizing Taproot addresses.&lt;br&gt;
In this article, I intend to share more information about taproot addresses and share one more example which I neglected in my &lt;a href="https://dev.to/eunovo/a-guide-to-creating-taproot-scripts-with-bitcoinjs-lib-4oph"&gt;previous article&lt;/a&gt;. I'll share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Public Key Tweaking, what it is, why we do it and how we do it&lt;/li&gt;
&lt;li&gt;How Taproot addresses are created&lt;/li&gt;
&lt;li&gt;How to generate the private key required to sign a spending transaction from a Taproot address.&lt;/li&gt;
&lt;li&gt;How to spend a Taproot output that has a script-tree without using any leaf scripts with bitcoinjs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Public Key Tweaking
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What is Public key Tweaking
&lt;/h3&gt;

&lt;p&gt;According to a &lt;a href="https://github.com/bitcoinops/taproot-workshop/blob/master/2.2-taptweak.ipynb" rel="noopener noreferrer"&gt;workshop on taproot by Bitcoin Optech&lt;/a&gt;, you can tweak a public key by adding a value (the tweak) to it. This way, you can still spend the tweaked public key if you know the original private key and the tweak. It is used in taproot to commit data or scripts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why do we tweak keys
&lt;/h3&gt;

&lt;p&gt;We tweak keys in taproot to commit to data or scripts that can be used for different spending conditions. This way, we can make complex transactions look like simple ones and save space and fees.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why didn't we tweak before Taproot
&lt;/h3&gt;

&lt;p&gt;Before taproot, we used a different type of digital signatures called ECDSA. ECDSA did not allow for easy tweaking. Taproot uses a new type of signatures called Schnorr that enable tweaking and other benefits.&lt;/p&gt;
&lt;h3&gt;
  
  
  How does a tweak work under the hood
&lt;/h3&gt;

&lt;p&gt;A tweak is positive scalar value &lt;code&gt;t&lt;/code&gt; where:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0 &amp;lt; t &amp;lt; SECP256K1_ORDER&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In bitcoin cryptography, we use the elliptic curve secp256k1 and &lt;code&gt;SECP256K1_ORDER&lt;/code&gt; is the number of points on the curve&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A point, the Tweak point, is obtained from this tweak scalar value by multiplying it by the generator point:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;T = t * G&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The generator point is a special point that can produce any other point in its subgroup by multiplying it by some integer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This tweak point is added to the x-coordinate of the original public key to get the tweaked public key. Prepend a parity bit to this tweaked public key to indicate if it is positive or negative.&lt;/p&gt;

&lt;p&gt;In taproot, we get the tweak value by concatenating the x-coordinate of the public key and a commitment to the script path to spend and hashing it. To spend a taproot output, you can sign with the tweaked private key (private key + tweak value) or provide a proof of the script path spend.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a Taproot address
&lt;/h2&gt;

&lt;p&gt;Taproot allows you to create addresses that can be spent by a single public key or by scripts. It does this by allowing you to add data to a public key by tweaking it.&lt;/p&gt;

&lt;p&gt;To create a P2TR (Pay-to-Taproot) address for a single public key, you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check that the y-coordinate of your public key is even, if not, negate the public key. Taproot requires that the y coordinate of the public key is even.&lt;/li&gt;
&lt;li&gt;extract the x-coordinate (bytes 1 to 33) of your public key (which is a point on an Elliptic Curve)&lt;/li&gt;
&lt;li&gt;tweak the public key with this x-only part of the public key.&lt;/li&gt;
&lt;li&gt;hash the x-coordinate of the tweaked public key with SHA256 and RIPEMD to get a 20-byte address.&lt;/li&gt;
&lt;li&gt;Prepend the version byte 0x51(indicates that the taproot address is a native SegWit output with version 1) to the address to get a 21-byte witness program.&lt;/li&gt;
&lt;li&gt;Encode the witness program with Bech32m encoding.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To create an address with multiple spending conditions (in the form of scripts), we arrange our scripts into a Merkle Tree, where each node is a hash of its children. The root of this tree is then used to tweak a public key and an address can be generated from this tweaked public key in the same steps (from step 4) defined above.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Even if you don't need multiple spending conditions for your address, BIP341 requires that you tweak the original public key with an unspendable script path which is what we do in step 3&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tweaking private keys for signing
&lt;/h2&gt;

&lt;p&gt;To sign a transaction input spending a Taproot output, you need to tweak the private key for the original public key using the same tweak value that generated the address. If the public key was negated (see step 1 above) you must also negate the private key. The tweaked private key will create a valid Schnorr signature for the tweaked public key. This works because of the mathematical properties of Schnorr signatures and elliptic curves.&lt;/p&gt;
&lt;h2&gt;
  
  
  Spending a Taproot output with a script tree via the key path using bitcoinjs
&lt;/h2&gt;

&lt;p&gt;In the Taptree example from my &lt;a href="https://dev.to/eunovo/a-guide-to-creating-taproot-scripts-with-bitcoinjs-lib-4oph"&gt;previous article&lt;/a&gt;. It is possible to spend the Taproot output without using the script tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script_p2tr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2tr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;internalPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;scriptTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;network&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key_spend_psbt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Psbt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;key_spend_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;vout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;witnessUtxo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;script_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;tapInternalKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;tapMerkleRoot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;script_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;key_spend_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addOutput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mohjSavDdQYHRYXcS3uS6ttaHP8amyvX78&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// faucet address&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// We need to create a signer tweaked by script tree's merkle root&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweakedSigner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweakSigner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tweakHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;script_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;key_spend_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tweakedSigner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;key_spend_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalizeAllInputs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;key_spend_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Broadcasting Transaction Hex: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;txid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Success! Txid is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>bitcoinjs</category>
      <category>bitcoin</category>
      <category>taproot</category>
    </item>
    <item>
      <title>HODL Invoices vs BOLT11 Invoices; A comparison</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Thu, 02 Mar 2023 07:16:17 +0000</pubDate>
      <link>https://dev.to/eunovo/hodl-invoices-vs-bolt11-invoices-a-comparison-f4</link>
      <guid>https://dev.to/eunovo/hodl-invoices-vs-bolt11-invoices-a-comparison-f4</guid>
      <description>&lt;p&gt;Lightning is a second layer for Bitcoin that uses micropayment channels to scale the blockchain’s capability to conduct transactions more efficiently. This layer consists of multiple nodes that can open and close payment channels with each other, without having to broadcast every transaction to the Bitcoin network. This way, Lightning can enable faster and cheaper transactions, while still maintaining the security and decentralization of Bitcoin.&lt;/p&gt;

&lt;p&gt;A Lightning invoice is a request for payment that contains the amount, destination, expiry time, and a cryptographic signature of the recipient. A payer can scan or copy a Lightning invoice and use it to initiate a payment through their Lightning wallet. A Lightning invoice can also include additional information such as a description or an image.&lt;/p&gt;

&lt;p&gt;A Lightning HODL invoice is a special type of Lightning invoice that allows the recipient to delay the settlement of the payment until they reveal a preimage (a secret piece of data) that matches a hash (a unique fingerprint) embedded in the invoice. This feature can be useful for scenarios where the recipient wants to provide some service or proof before accepting the payment, such as delivering goods, verifying identity, or completing a task.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create a Bolt11 invoice with LND's API
&lt;/h2&gt;

&lt;p&gt;See &lt;a href="https://lightning.engineering/api-docs/api/lnd/lightning/add-invoice" rel="noopener noreferrer"&gt;lnd's add-invoice API&lt;/a&gt;. You will need to specify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The amount you want to receive in satoshis&lt;/li&gt;
&lt;li&gt;The expiry time in milliseconds&lt;/li&gt;
&lt;li&gt;The description (optional)&lt;/li&gt;
&lt;li&gt;The preimage (optional, LND will generate one for you)
Your invoice will be valid only for the expiry time you set. After it expires, it cannot be paid anymore. It can also be paid only once.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to create a lightning HODL invoice with LND's API
&lt;/h2&gt;

&lt;p&gt;See &lt;a href="https://lightning.engineering/api-docs/api/lnd/invoices/add-hold-invoice" rel="noopener noreferrer"&gt;lnd's add-hodl-invoice API&lt;/a&gt;. A HODL invoice is very similar to a Bolt11 invoice but because the preimage is not released immediately on payment, you can &lt;a href="https://lightning.engineering/api-docs/api/lnd/invoices/cancel-invoice" rel="noopener noreferrer"&gt;cancel the invoice&lt;/a&gt; or &lt;a href="https://lightning.engineering/api-docs/api/lnd/invoices/settle-invoice" rel="noopener noreferrer"&gt;settle it by releasing the preimage for the invoice&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even if you don't release the preimage in a Bolt11 invoice, the invoice will not be canceled. The payer can keep trying to pay until the invoice expires or fails with incorrect_or_unknown_payment_details. LND also requires the preimage to generate a BOLT11 invoice, so you have no control over when it is revealed.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;HODL invoices are good for situations where you want to receive payments only after fulfilling some condition or providing some service. For example,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can use them for escrow services where you hold funds until both parties agree on releasing them&lt;/li&gt;
&lt;li&gt;You can use them for atomic swaps where you exchange one cryptocurrency for another without trusting intermediaries&lt;/li&gt;
&lt;li&gt;You can use them for pay-per-view content where you charge users only after they watch your video or read your article&lt;/li&gt;
&lt;li&gt;You can use them for crowdfunding campaigns where you collect funds only after reaching your goal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HODL invoices are also good for enhancing privacy and security on the Lightning Network. By delaying payments until they are needed, you reduce the risk of losing funds due to channel closures, hacks, or thefts. You also reduce the amount of information that is exposed on the network, such as balances, fees, or routes.&lt;/p&gt;

&lt;p&gt;HODL invoices are one of many innovations that make the Lightning Network more powerful and versatile. They demonstrate how Bitcoin’s native smart-contract scripting language can enable new possibilities for peer-to-peer transactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.investopedia.com/terms/l/lightning-network.asp" rel="noopener noreferrer"&gt;https://www.investopedia.com/terms/l/lightning-network.asp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lightning.network/" rel="noopener noreferrer"&gt;https://lightning.network/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Lightning_Network" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Lightning_Network&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/suredbits/lightning-101-what-is-a-lightning-invoice-d527db1a77e6" rel="noopener noreferrer"&gt;https://medium.com/suredbits/lightning-101-what-is-a-lightning-invoice-d527db1a77e6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lightningwiki.net/index.php/HODL_Invoice" rel="noopener noreferrer"&gt;https://lightningwiki.net/index.php/HODL_Invoice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gaminghardware</category>
      <category>cloudgaming</category>
      <category>gamedeals</category>
      <category>marketing</category>
    </item>
    <item>
      <title>A Guide to creating TapRoot Scripts with bitcoinjs-lib</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Sun, 19 Feb 2023 21:31:40 +0000</pubDate>
      <link>https://dev.to/eunovo/a-guide-to-creating-taproot-scripts-with-bitcoinjs-lib-4oph</link>
      <guid>https://dev.to/eunovo/a-guide-to-creating-taproot-scripts-with-bitcoinjs-lib-4oph</guid>
      <description>&lt;p&gt;Taproot and Schnorr are upgrades to the Bitcoin protocol designed to enhance the privacy, efficiency and flexibility of Bitcoin transactions.&lt;/p&gt;

&lt;p&gt;Taproot introduces Taptrees, a feature that reduces the size of transaction data and ensures only necessary information is revealed on the blockchain, thereby preserving privacy. With Taproot, multisig transactions are also more private as unused spending conditions are hidden.&lt;/p&gt;

&lt;p&gt;Schnorr signatures are 64 bytes long instead of the 72 bytes used by current ECDSA signature scheme. Taproot also use only x-values of public keys for signature creation which saves 1 byte. &lt;/p&gt;

&lt;p&gt;With the adoption of Taproot and Schnorr, Bitcoin transactions can be more efficient, flexible, and private.&lt;/p&gt;

&lt;p&gt;We'll go over two examples. In our first example, we will create a pay-to-taproot(p2tr) address that will lock funds to a key and create a spend transaction for it. In our second example, we will jump straight into taproot script-spend transactions, we will create a &lt;code&gt;Taptree&lt;/code&gt; consisting of two script-spend paths, a hash-lock script spend path and a pay-to-pubkey script spend path. We will create transactions that spend from both paths.&lt;/p&gt;

&lt;p&gt;The full code for this article can be found on github at &lt;a href="https://github.com/Eunovo/taproot-with-bitcoinjs" rel="noopener noreferrer"&gt;taproot-with-bitcoinjs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Taproot Key-spend transaction
&lt;/h2&gt;

&lt;p&gt;For illustration purposes, we'll use a random keypair&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ECPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeRandom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We tweak this keypair with our pubkey.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweakedSigner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tweakSigner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bitcoinjs-lib&lt;/code&gt; provides a &lt;code&gt;p2tr&lt;/code&gt; function to generate p2tr outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pktr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2tr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tweakedSigner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;network&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pktr_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p2pktr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p2pktr_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;toXOnly&lt;/code&gt; function extracts the x-value of our public key.&lt;/p&gt;

&lt;p&gt;You can use any testnet faucet that supports taproot addresses. I used &lt;a href="https://testnet-faucet.com/btc-testnet/" rel="noopener noreferrer"&gt;testnet-faucet.com/btc-testnet&lt;/a&gt; while testing.&lt;/p&gt;

&lt;p&gt;Creating a spend-transaction for this address with bitcoinjs-lib is straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Psbt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;vout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;witnessUtxo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pktr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;tapInternalKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addOutput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mohjSavDdQYHRYXcS3uS6ttaHP8amyvX78&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// faucet address&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tweakedSigner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalizeAllInputs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extract the transaction and broadcast the transaction hex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Broadcasting Transaction Hex: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Success! Txid is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Taproot Script-spend transaction
&lt;/h2&gt;

&lt;p&gt;We'll create a Tap tree with two spend paths, a hash-lock spend path and a pay-to-pubkey spend path.&lt;/p&gt;

&lt;p&gt;The hash-lock script-spend path will require the spender to include a preimage that will produce the hash specified in the script.&lt;/p&gt;

&lt;p&gt;Let's make another random keypair for our hash-lock script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ECPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeRandom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we will construct our hash-lock script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;secret_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SECRET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash160&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret_bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Construct script to pay to hash_lock_keypair if the correct preimage/secret is provided&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash_script_asm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`OP_HASH160 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; OP_EQUALVERIFY &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash_lock_keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; OP_CHECKSIG`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromASM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash_script_asm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that script still requires a signature to unlock funds.&lt;/p&gt;

&lt;p&gt;The pay-to-pubkey spend path is much simpler&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pk_script_asm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; OP_CHECKSIG`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pk_script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromASM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p2pk_script_asm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now create our Taptree and p2tr address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptTree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Taptree&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="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_script&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_script&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script_p2tr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2tr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;internalPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;scriptTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;network&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;script_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can deposit some test btc into the address using a testnet faucet like &lt;a href="https://testnet-faucet.com/btc-testnet/" rel="noopener noreferrer"&gt;testnet-faucet.com/btc-testnet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To spend on any of the leaf scripts, you must present the leafVersion, script and controlBlock for that leaf script. The control block is data required to prove that the leaf script exists in the script tree(merkle proof).&lt;/p&gt;

&lt;p&gt;bitcoinjs-lib will generate the control block for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_redeem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redeemVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pk_redeem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redeemVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pk_p2tr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2tr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;internalPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;scriptTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redeem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_redeem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;network&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_p2tr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2tr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;internalPubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toXOnly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;scriptTree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;redeem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_redeem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;network&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Waiting till UTXO is detected at this Address: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;script_addr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitUntilUTXO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Trying the P2PK path with UTXO &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;vout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2pk_psbt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Psbt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;p2pk_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;vout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;witnessUtxo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;tapLeafScript&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="na"&gt;leafVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_redeem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redeemVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_redeem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;controlBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2pk_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witness&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;p2pk_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witness&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="c1"&gt;// extract control block from witness data&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="nx"&gt;p2pk_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addOutput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mohjSavDdQYHRYXcS3uS6ttaHP8amyvX78&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// faucet address&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;p2pk_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;p2pk_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalizeAllInputs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;p2pk_psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Broadcasting Transaction Hex: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;txid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Success! Txid is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To spend using the hash-lock leaf script, we have to create a custom finalizer function. In our custom finalizer, we will create our witness stack of &lt;code&gt;signature, preimage, original hash-lock script and our control block&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tapLeafScript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;leafVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_redeem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redeemVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_redeem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;controlBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witness&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hash_lock_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witness&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Psbt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;vout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;witnessUtxo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_p2tr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;tapLeafScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;tapLeafScript&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addOutput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mohjSavDdQYHRYXcS3uS6ttaHP8amyvX78&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// faucet address&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hash_lock_keypair&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// We have to construct our witness script in a custom finalizer&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customFinalizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_inputIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptSolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tapScriptSig&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;secret_bytes&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;witness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;scriptSolution&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tapLeafScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tapLeafScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controlBlock&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;finalScriptWitness&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;witnessStackToScriptWitness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;witness&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="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalizeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customFinalizer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Broadcasting Transaction Hex: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;txid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;broadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Success! Txid is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;txid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;By reading this article, you should now have a better understanding of how to use bitcoinjs-lib to create and spend P2TR (Pay to Taproot) payments. With this knowledge, you are one step closer to leveraging the benefits of Taproot in your Bitcoin transactions, such as improved privacy, scalability, and the ability to create more complex smart contracts.&lt;br&gt;
You can find more examples in &lt;a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/test/integration/taproot.spec.ts" rel="noopener noreferrer"&gt;bitcoinjs-lib's repo&lt;/a&gt;. The full code for this article can be found on github at &lt;a href="https://github.com/Eunovo/taproot-with-bitcoinjs" rel="noopener noreferrer"&gt;taproot-with-bitcoinjs&lt;/a&gt;.&lt;br&gt;
If you need some help understanding taproot, you can check this out &lt;a href="https://dev.to/eunovo/more-on-taproot-41g8"&gt;More on Taproot&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Unlocking the Power of P2WSH: A Step-by-Step Guide to Creating and Spending Coins with Bitcoin Scripts using bitcoinjs-lib</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Mon, 13 Feb 2023 11:19:08 +0000</pubDate>
      <link>https://dev.to/eunovo/unlocking-the-power-of-p2wsh-a-step-by-step-guide-to-creating-and-spending-coins-with-bitcoin-scripts-using-bitcoinjs-lib-a7o</link>
      <guid>https://dev.to/eunovo/unlocking-the-power-of-p2wsh-a-step-by-step-guide-to-creating-and-spending-coins-with-bitcoin-scripts-using-bitcoinjs-lib-a7o</guid>
      <description>&lt;p&gt;In the world of Bitcoin, addresses are used to specify how you want to receive coins. There are several types of addresses, each with its own properties and capabilities.&lt;/p&gt;

&lt;p&gt;The simplest type is Pay-to-Pubkey-Hash (P2PKH), which is generated from a public key hash and is secure but lacks advanced features. The Pay-to-Witness-Public-Key-Hash (P2WPKH) address, introduced by the SegWit upgrade, is more efficient and has lower fees. Another type, Pay-to-Script-Hash (P2SH), supports complex scripts and the Pay-to-Witness-Script-Hash (P2WSH) address is a SegWit-upgraded version of P2SH. Both P2WPKH and P2WSH use the bech32 format, an efficient address format with a checksum to detect and correct errors. Bech32 addresses start with "bcrt" on the Regtest network, "tb" on the testnet network, and "bc" on the mainnet network.&lt;/p&gt;

&lt;p&gt;The P2WSH (Pay-to-Witness-Script-Hash) format embeds a witness program that includes a hash of a script, instead of just a simple public key hash as in the case of P2PKH (Pay-to-Pubkey-Hash) addresses. The witness program acts as a placeholder for the actual script, which can be more complex and larger in size, but this complexity is hidden from the sender. When a transaction is made to a P2WSH address, the sender only needs to provide the witness program, and the actual script complexity is only processed when a transaction spending from the p2wsh address is validated by the network. This makes sending transactions to P2WSH addresses simple and easy for the sender, while the receiver bears the burden of handling the increased script complexity and transaction fees associated with more complex scripts.&lt;/p&gt;

&lt;p&gt;In this article, we'll be focusing on the P2WSH address type and how to create and use them in transactions using the bitcoinjs-lib library. By the end of this article, you'll have a solid understanding of how to create, send, and spend coins locked with a witness script using P2WSH addresses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This article assumes that you have a solid understanding of how bitcoin and bitcoin-scripting works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The complete code for this article can be found &lt;a href="https://github.com/Eunovo/scripting-with-bitcoinjs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating a Pay-to-Witness-Script-Hash (P2WSH) address in bitcoin is a bit more complex than a standard Pay-to-Witness-Pubkey-Hash (P2WPKH) address, but it opens up a whole new world of possibilities for specifying complex scripts. In this article, we'll be using the bitcoinjs-lib library, which is a popular JavaScript library for working with Bitcoin transactions. We'll be using TypeScript for our code samples, but the same concepts apply to JavaScript as well.&lt;/p&gt;

&lt;p&gt;We'll start by installing bitcoinjs-lib:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install bitcoinjs-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll import the modules we need from the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Psbt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bitcoinjs-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testnet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we'll start with a simple example. In this example, we'll use a  very simple locking script. The locking script will POP 2 numbers from the stack and check that they sum up to 5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OP_ADD 5 OP_EQUAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can create a P2WSH address for this script using bitcoinjs-lib.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locking_script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_ADD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_EQUAL&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we'll create our P2WSH address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const p2wsh = payments.p2wsh({ redeem: { output: locking_script, network }, network });
console.log(p2wsh.address);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The P2WSH address will be logged to the console. Sending coins to this address will secure them with a hash of a script, instead of the script itself. The sender does not need to know the details of the script as the coins are locked with a simple &lt;code&gt;scriptPubKey&lt;/code&gt;. The coins can only be unlocked by someone with the full &lt;code&gt;redeemScript&lt;/code&gt;, which, when hashed, will match the hash value to which the coins are locked. You can now send coins to this address, which will be locked by the script. You can use a &lt;a href="https://testnet-faucet.com/btc-testnet/" rel="noopener noreferrer"&gt;testnet faucet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's create a transaction to spend from our Psbt.&lt;br&gt;
We'll use the Psbt (Partially Signed Bitcoin Transaction) class from bitcoinjs-lib. The Psbt class allows us to create, update and finalize partially signed transactions.&lt;/p&gt;

&lt;p&gt;We'll create a new instance of the Psbt class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Psbt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we'll add the input to the transaction. This is the P2WSH transaction that we want to spend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;txid&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;vout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;witnessUtxo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p2wsh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;witnessScript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;locking_script&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;txid&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;vout&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;amount&amp;gt;&lt;/code&gt; with the corresponding values of the P2WSH transaction.&lt;/p&gt;

&lt;p&gt;Next, we'll add an output to the transaction. This is where we'll send the coins to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;address&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addOutput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toAmount&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to leave a small amount to pay for transaction fees.&lt;/p&gt;

&lt;p&gt;To spend from our address, we need to present any two numbers that add up to 5, so any of the following scripts will work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 4
2 3
3 2
4 1
0 5
5 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to add our unlocking script to the input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalizeInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_inputIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redeemPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2wsh&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;redeem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
          &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&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="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witnessScript&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalScriptWitness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;witnessStackToScriptWitness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;redeemPayment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witness&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;finalScriptSig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;finalScriptWitness&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalizeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;finalizeInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we don't need to sign the p2swh input because our locking script doesn't require a signature.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;witnessStackToScriptWitness&lt;/code&gt; takes our witness stack(which is an array of our locking script and witness script) and serializes it(coverts it into a single stream of bytes returned as a Buffer).&lt;/p&gt;

&lt;p&gt;Now we can extract the transaction using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then broadcast it to the network using any method you prefer.&lt;/p&gt;

&lt;p&gt;Let's create a slightly more complex script, where we can demonstrate how to add a signature to the unlocking script.&lt;br&gt;
This time, we'll pay to an address(the script will be a standard p2pkh script) but we will require a secret to be presented along with the signature before the funds can be unlocked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is only an example, simple enough that I can use demonstrate adding signatures. In practice, I'm not sure why you would use a script like this without adding a conditional flow so that the coins can be spent in a different way if the secret is not provided&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Take a look at our locking script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OP_HASH160 &amp;lt;HASH160(&amp;lt;secret&amp;gt;)&amp;gt; OP_EQUALVERIFY OP_DUP OP_HASH160 &amp;lt;recipient_address&amp;gt; OP_EQUALVERIFY OP_CHECKSIG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our unlocking script will take the form:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We'll use the &lt;code&gt;crypto&lt;/code&gt; module from 'bitcoinjs-lib' to hash our secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bitcoinjs-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;preimage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash160&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;preimage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a bech32 address, you will need to decode the address using the &lt;code&gt;address&lt;/code&gt; module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bitcoinjs-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recipientAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromBech32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;bech32 address&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The address module can also decode standard p2pkh addresses or p2sh address encoded in base58check format.&lt;br&gt;
Or you can make a random keypair and get the pubkey and address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ECPairFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ECPairAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TinySecp256k1Interface&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ecpair&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tinysecp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TinySecp256k1Interface&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tiny-secp256k1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ECPair&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ECPairAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ECPairFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tinysecp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ECPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeRandom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recipAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash160&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's compile the locking script and create our p2wsh address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locking_script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_HASH160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_EQUALVERIFY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_DUP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_HASH160&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;recipAddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_EQUALVERIFY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opcodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OP_CHECKSIG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;p2wsh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2wsh&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;redeem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;locking_script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p2wsh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can send some coins to this address for testing.&lt;/p&gt;

&lt;p&gt;To spend from this address, we'll perform the same steps we performed before but with a little twist; after adding the input and outputs, we'll need to create a signature for the p2wsh input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keypair&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll construct the unlocking script and add it to the input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalizeInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_inputIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redeemPayment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2wsh&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;redeem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
          &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;partialSig&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;preimage&lt;/span&gt;
        &lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witnessScript&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalScriptWitness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;witnessStackToScriptWitness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;redeemPayment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;witness&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;finalScriptSig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;finalScriptWitness&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalizeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;finalizeInput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can extract the transaction hex and broadcast it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;psbt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! We've successfully created a P2WSH address, sent coins to it, and spent the coins locked with the witness script using bitcoinjs-lib. Keep in mind that this is just a simple example and there are many other ways to use P2WSH and scripts to lock and unlock coins in Bitcoin.&lt;/p&gt;

&lt;p&gt;The complete code for this article can be found &lt;a href="https://github.com/Eunovo/scripting-with-bitcoinjs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>deployment</category>
      <category>ci</category>
      <category>cicd</category>
      <category>devops</category>
    </item>
    <item>
      <title>A good reason to create a Service Layer in your application</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Mon, 17 Oct 2022 09:44:29 +0000</pubDate>
      <link>https://dev.to/eunovo/a-good-reason-to-create-a-service-layer-in-your-application-3678</link>
      <guid>https://dev.to/eunovo/a-good-reason-to-create-a-service-layer-in-your-application-3678</guid>
      <description>&lt;p&gt;Many developers are accustomed to the design pattern in which we break our application code into the models/entities layer, the repository layer, the service layer, and the controllers.&lt;/p&gt;

&lt;p&gt;The reason for the entities layer is pretty straightforward: you must declare the fields(and their types) of entities in your application. In some applications, you can also describe the database schema in your entity class. You place your queries in the repository layer and use them to retrieve data, while your controllers contain handlers for each route and HTTP method. But what about Services?&lt;/p&gt;

&lt;p&gt;I occasionally have service classes that appear to have no use other than to satisfy the need to have a service layer before my repositories.&lt;/p&gt;

&lt;p&gt;I recently discovered a great reason to have service layer classes. A project I was working on had no clearly defined service layer. I needed to write code to pull data from different repos, process it and return the result. For the sake of this article, let's assume that I first wrote this code in the controller class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const repo1 = new Repo1()
const repo2 = new Repo2()

@rest('/demo')
class DemoController {

  @get('/result')
  getResult(req) {
    // handler for GET /demo/result

    const stuff = repo1.findById(req.body.id)
    const moreStuff = repo2.findAllCreatedBefore(req.body.time)
    // do some processing here
    return { result } 
  }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I realized I needed it somewhere else, so I transferred it to a different file and wrapped the code in a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// process-data file
const repo1 = new Repo1()
const repo2 = new Repo2()

export function processData(id, time) {
  const stuff = repo1.findById(id)
  const moreStuff = repo2.findAllCreatedBefore(time)
  // do some processing here
  return result;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that I can use it everywhere, isn't my job done? No, not exactly. There is only one problem: How will I test this function?&lt;/p&gt;

&lt;p&gt;The function has dependencies (the repositories) that are not part of its parameters which will make testing difficult. This function needs to use a set of mocked dependencies in my test cases. How do I go about doing this? Wouldn't a class be appropriate here?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// process-data file

export class DataProcessor {
  private repo1
  private repo2

  constructor(repo1, repo2) {
    this.repo1 = repo1
    this.repo2 = repo2
  }

  processDataByIdCreatedBeforeTime(id, time) {
    const stuff = this.repo1.findById(id)
    const moreStuff = this.repo2.findAllCreatedBefore(time)
    // do some processing here
    return result;
  }

}

export const processor = new DataProcessor(new Repo1(), new Repo2())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// test DataProcessor

it('should process the data correctly', () =&amp;gt; {
  const processor = new DataProcessor(mock1, mock2)
  // ...some testing code
  const result = processor.processDataByIdCreatedBeforeTime(id, time)
  assert.equal(result, expectedResult)
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, doesn't the DataProcessor class look like a Service layer class? The need to test the data processing logic eventually led to the creation of the service layer class. So, what should we take away?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need the Service layer separate from your repositories and controllers so you can unit-test your business logic code&lt;/li&gt;
&lt;li&gt;You also need the Service layer so that your business logic code can be reused in other parts of your application&lt;/li&gt;
&lt;li&gt;Consider using Test Driven Development?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my opinion. I suspect that there may be contrary ideas or I may have missed something, in that case, feel free to share in the comments.&lt;br&gt;
Thank you for reading.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
      <category>cleancode</category>
      <category>backend</category>
    </item>
    <item>
      <title>A better way to create Swagger Docs for Koa APIs using decorators?</title>
      <dc:creator>Oghenovo Usiwoma</dc:creator>
      <pubDate>Mon, 20 Jun 2022 10:35:06 +0000</pubDate>
      <link>https://dev.to/eunovo/a-better-way-to-create-swagger-docs-for-koa-apis-with-decorators-e3m</link>
      <guid>https://dev.to/eunovo/a-better-way-to-create-swagger-docs-for-koa-apis-with-decorators-e3m</guid>
      <description>&lt;p&gt;Hello there!👋 I just did something to ease documentation for Koa APIs and I'm going to share it with you. If you are a fan of typescript's decorators or you are figuring out how to use them then you'll probably love this.&lt;/p&gt;

&lt;p&gt;So, I had to setup swagger docs for a Koa API recently and I had to cram a lot of information and definitions into comments for the &lt;a href="https://www.npmjs.com/package/swagger-jsdoc" rel="noopener noreferrer"&gt;swagger-jsdoc&lt;/a&gt; tool to extract. As a developer who has used &lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;NestJS&lt;/a&gt; and is familiar with the ease at which you can create Swagger docs, I disliked this experience. I did check for some alternatives and found one notable package &lt;a href="https://www.npmjs.com/package/koa-swagger-decorator" rel="noopener noreferrer"&gt;koa-swagger-decorator&lt;/a&gt; but why not re-invent the wheel 😃? I just wanted to code this myself... Thankfully, I got something usable without too much effort but this could easily have turned into a bad situation where I just wasted time and effort instead of using an existing solution.&lt;/p&gt;

&lt;p&gt;Alright, let's get started!&lt;br&gt;
So, I wanted something similar to what NestJS offers; I wanted to create classes to represent my various definitions and I wanted to use decorators to add &lt;a href="https://swagger.io/docs/specification/2-0/basic-structure/" rel="noopener noreferrer"&gt;swagger specific information&lt;/a&gt; to it's properties, Piece of cake...&lt;/p&gt;

&lt;p&gt;This is an example of what I had in mind for Definitions...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Definition()
export class CreateUser {
    @ApiProperty({
        required: true,
        type: 'string'
    })
    createdBy!: string

    @ApiProperty({
        required: true,
        type: 'string'
    })
    username!: string

    @ApiProperty({
        required: true,
        type: 'string'
    })
    city!: string
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will have to do some work at the Controller level too but let's start here.&lt;br&gt;
Creating the decorators is easy enough, you only need peruse the &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.htm" rel="noopener noreferrer"&gt;Typescript documentation&lt;/a&gt; but I mostly skipped that step and that came back to haunt me later but let's proceed.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Decorators work
&lt;/h2&gt;

&lt;p&gt;A decorator is a function that can be attached to classes, methods, properties etc, and get's called at runtime with details about the declaration it is attached to(let's call this the decorated entity). You can also modify said decorated entity at runtime. A couple of things to note about decorators;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you have multiple decorators in a class, the parameter decorators, the method/property decorators, and the class decorators are evaluated serially in that order&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you have multiple decorators attached to the same entity, they are evaluated top-to-bottom and the results are passed bottom-to-top&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A bit oversimplified but checkout &lt;a href="https://www.typescriptlang.org/docs/handbook/decorators.html#decorator-evaluation" rel="noopener noreferrer"&gt;Decorator composition&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating the "ApiProperty" and "Definition" decorators
&lt;/h2&gt;

&lt;p&gt;We need to store information like required fields, property types, examples if any for each Definition. I decided that a single "@ApiProperty" will suffice for this and "@Definition" will be added to the class to compile all the collected information into one definition and added to our definitions list... See the code snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const DEFINITIONS: any = {}; // to hold all definitions
let DEFINITION: any = {}; // current definition details

// class decorator
export function Definition() {
    return function &amp;lt;T extends { new(...args: any[]): {} }&amp;gt;(constructor: T) {
        DEFINITIONS[constructor] = {
            name: constructor.name,
            type: "object",
            ...DEFINITION
        };
        DEFINITION = {}; // prepare for next class
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why am I using the class constructor as key for the Definition object? well, we will see that in the next section...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface ApiPropertyProps {
    required?: boolean
    type: string
    example?: string
    items?: { $ref?: any }
}

// A function that returns the actual decorator, A decorator factory
export function ApiProperty(props: ApiPropertyProps) {
    return function (_target: any, propertyKey: string) {
        if (!DEFINITION.required) DEFINITION.required = [];
        if (!DEFINITION.properties) DEFINITION.properties = {};

        if (props.required) DEFINITION.required.push(propertyKey);
        if (props.items?.$ref) props.items.$ref = toSwaggerRef(props.items.$ref); // convert ref to swagger ref format

        DEFINITION.properties = { ...DEFINITION.properties, [propertyKey]: props };
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Controllers
&lt;/h2&gt;

&lt;p&gt;Now, we can't just define routes using &lt;a href="https://www.npmjs.com/package/koa-router" rel="noopener noreferrer"&gt;koa-router&lt;/a&gt; because we can only use decorators in classes. So, we need to make Controller classes and also create decorators to add path, parameters and response definitions. I ended with something this..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserController {
    @ApiParameter({ in: 'body', schema: { $ref: CreateUser } })
    @ApiResponse({ status: 200, type: 'application/json', schema: { $ref: CreateUser } })
    @ApiOperation({ path: '/user/create', method: 'post' })
    async createUser(ctx: Context) {
        const body: CreateGroup = ctx.request.body;
        console.log(body);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are worried about adding middleware, it's easy enough to create a "Middleware" decorator for this purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notice here, that &lt;code&gt;$ref&lt;/code&gt; points to the actual &lt;code&gt;CreateUser&lt;/code&gt; class. I did this to ensure that the decorators applied to &lt;code&gt;CreateUser&lt;/code&gt; actually get executed at runtime. Without this limitation, I'd have to find other ways to make sure &lt;code&gt;CreateUser&lt;/code&gt; actually gets added to the Definitions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;toSwaggerRef&lt;/code&gt; function as is shown below will be responsible for converting these class references to "#/definitions/CreateUser" strings for swagger to interpret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function toSwaggerRef(ref: any) {
    if (ref.charAt) return ref; // quick check if ref is a string
    const definition = DEFINITIONS[ref];
    return `#/definitions/${definition.name}`;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code for the "ApiParameter" and "ApiResponse" decorators are pretty standard and you can take a look at them in the &lt;a href="https://gist.github.com/Eunovo/8b3ef97b1c88dcf0ae6d773ab713dbe3" rel="noopener noreferrer"&gt;github gist&lt;/a&gt;. For "@ApiOperation", I modified the decorated method's instance a little bit to make it easier to add the routes to koa using koa-router.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface ApiOperationProps {
    path: string, // Api Path
    method: Methods, // Http Methods
    description?: string
    consumes?: string[]
}

export function ApiOperation(props: ApiOperationProps) {
    const swaggerPath = props.path.split('/')
        .map(token =&amp;gt; {
            if (!token.startsWith(':')) return token;
            return `{${token.slice(1)}}`;
        })
        .join('/'); // convert all ':param' to '{param}' for swagger

    PATHS[swaggerPath] = {
        [props.method]: {
            description: props.description,
            consumes: props.consumes,
            parameters: PARAMETERS,
            responses: RESPONSES
        }
    }
    PARAMETERS = [];
    RESPONSES = {};

    return (target: any, propertyKey: string, _descriptor: PropertyDescriptor) =&amp;gt; {
        // target is the instance with decorated property
        if (!target._paths) target._paths = [];
        target._paths.push({
            path: props.path,
            method: props.method, // method as in Http Method
            propertyKey
        });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;So, let's add our routes to koa and then generate our swagger doc...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function applyRoutes(controller: any, router: Router) {
    if (!controller._paths) return;

    // Remember the paths we added in the @ApiOperation decorator?
    controller._paths.forEach((pathObj: any) =&amp;gt; {
        const { path, method, propertyKey } = pathObj;
        router[method as Methods](path, controller[propertyKey]); // Register route
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our controller file, after defining our controller class, we just need to do this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const router = new Router();
const users = new UserController();
applyRoutes(users, router);

export default router; // add this to the koa app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get our swagger page, I used this tool, &lt;a href="https://www.npmjs.com/package/swagger2-koa" rel="noopener noreferrer"&gt;swagger2-koa&lt;/a&gt; which accepts any object following the &lt;a href="https://swagger.io/specification/" rel="noopener noreferrer"&gt;swagger specification&lt;/a&gt;...&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;swaggerDoc&lt;/code&gt; function compiles the paths and definitions into one object following the swagger specification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface SwaggerProps {
    info: {
        title: string,
        version: string,
        description: string
    }
}

export function swaggerDoc(props: SwaggerProps) {
    const definitions = getDefinitions(); // Parse our DEFINITIONS object into the swagger format

    return {
        swagger: "2.0",
        info: props.info,
        paths: PATHS,
        definitions,
        responses: {},
        parameters: {},
        securityDefinitions: {},
        tags: {}
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and finally...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ui } from 'swagger2-koa';
import { swaggerDoc } from './utils/swagger';

let swaggerSpec: any = swaggerDoc({
    info: {
        title: `Test API`,
        version: '1.0.0',
        description: `Test API`
    }
});

const swagger = ui(swaggerSpec, "/swagger");

// add to koa app
app.use(swagger);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This was mostly fun... I like to do things like this from time-to-time to prove that I'm still an "okay" programmer 💀. The full code is available &lt;a href="https://gist.github.com/Eunovo/8b3ef97b1c88dcf0ae6d773ab713dbe3" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>node</category>
      <category>koa</category>
      <category>swagger</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
