<?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: Youngjoon Lee</title>
    <description>The latest articles on DEV Community by Youngjoon Lee (@oudwud).</description>
    <link>https://dev.to/oudwud</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%2F1031072%2F37868060-1c5b-41d0-8098-7a4783ec2791.jpeg</url>
      <title>DEV Community: Youngjoon Lee</title>
      <link>https://dev.to/oudwud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oudwud"/>
    <language>en</language>
    <item>
      <title>Exploring rust-libp2p</title>
      <dc:creator>Youngjoon Lee</dc:creator>
      <pubDate>Wed, 10 May 2023 04:43:39 +0000</pubDate>
      <link>https://dev.to/oudwud/exploring-rust-libp2p-4pd4</link>
      <guid>https://dev.to/oudwud/exploring-rust-libp2p-4pd4</guid>
      <description>&lt;h2&gt;
  
  
  Connectivity Tests
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://libp2p.io"&gt;libp2p.io&lt;/a&gt;, &lt;a href="https://libp2p.io/implementations/"&gt;the current state of Transport implementations&lt;/a&gt; in each programming language is already written. But, I’ve seen there have been so many changes in rust-libp2p, as described in the &lt;a href="https://libp2p.io/2023-01-12-rust-libp2p-in-2022/"&gt;rust-libp2p in 2022&lt;/a&gt; blog post. &lt;/p&gt;

&lt;p&gt;After reading the &lt;a href="https://connectivity.libp2p.io/"&gt;libp2p Connectivity&lt;/a&gt; document, I've tested if 'dialing' works for each of the following scenarios using &lt;a href="https://github.com/libp2p/rust-libp2p"&gt;rust-libp2p&lt;/a&gt; v0.51.3.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Dialing&lt;/th&gt;
&lt;th&gt;Transports tested&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standalone -&amp;gt; Standalone&lt;/td&gt;
&lt;td&gt;Successful&lt;/td&gt;
&lt;td&gt;TCP, WebSocket, &lt;cite&gt;WebRTC&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/cite&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WASM browser -&amp;gt; Standalone&lt;/td&gt;
&lt;td&gt;Successful&lt;/td&gt;
&lt;td&gt;&lt;cite&gt;WebSocket&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/cite&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WASM browser &amp;lt;- Standalone&lt;/td&gt;
&lt;td&gt;&lt;cite&gt;Failed&lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/cite&gt;&lt;/td&gt;
&lt;td&gt;WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WASM browser -&amp;gt; WASM browser&lt;/td&gt;
&lt;td&gt;&lt;cite&gt;Failed&lt;sup id="fnref3"&gt;3&lt;/sup&gt;&lt;/cite&gt;&lt;/td&gt;
&lt;td&gt;WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;cite&gt;JS browser&lt;sup id="fnref4"&gt;4&lt;/sup&gt;&lt;/cite&gt; -&amp;gt; Standalone&lt;/td&gt;
&lt;td&gt;Successful&lt;/td&gt;
&lt;td&gt;WebRTC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Private -&amp;gt; (&lt;cite&gt;Relay&lt;sup id="fnref5"&gt;5&lt;/sup&gt;&lt;/cite&gt;) -&amp;gt; Private&lt;/td&gt;
&lt;td&gt;Successful&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;cite&gt;Private&lt;sup id="fnref6"&gt;6&lt;/sup&gt;&lt;/cite&gt; -&amp;gt; (&lt;cite&gt;Relay&lt;sup id="fnref5"&gt;5&lt;/sup&gt;&lt;/cite&gt;) -&amp;gt; Private with &lt;a href="https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html"&gt;Hole-punching&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;&lt;cite&gt;Failed&lt;sup id="fnref7"&gt;7&lt;/sup&gt;&lt;/cite&gt;&lt;/td&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  WASM Limitations
&lt;/h2&gt;

&lt;p&gt;I've found that the following features of rust-libp2p cannot be enabled for WASM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gossipsub, mdns, dns, tokio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If WASM codes import those features, the following error occurs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;error[E0432]: unresolved import &lt;span class="sb"&gt;`&lt;/span&gt;libp2p::gossipsub&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; core/src/p2p.rs:20:5
   |
20 |     gossipsub, identity,
   |     ^^^^^^^^^ no &lt;span class="sb"&gt;`&lt;/span&gt;gossipsub&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;the root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In regard to gossipsub especially, the gossipsub has been disabled for the &lt;code&gt;wasm32-unknown-unknown&lt;/code&gt; target by &lt;a href="https://github.com/libp2p/rust-libp2p/pull/2506#issuecomment-1036448620"&gt;rust-libp2p/pull/2506#issuecomment-1036448620&lt;/a&gt;&lt;br&gt;
because of the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The custom &lt;code&gt;Interval&lt;/code&gt; implementation in rust-libp2p wasn't performant: &lt;a href="https://github.com/libp2p/rust-libp2p/issues/2497"&gt;rust-libp2p/issues/2497&lt;/a&gt;. So, they decided to revert back to &lt;a href="https://github.com/tomaka/wasm-timer"&gt;wasm-timer&lt;/a&gt; by &lt;a href="https://github.com/libp2p/rust-libp2p/pull/2506"&gt;rust-libp2p/pull/2506&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;However, the &lt;code&gt;rust-libp2p&lt;/code&gt; with &lt;code&gt;wasm-timer&lt;/code&gt; cannot be compiled for &lt;code&gt;wasm32-unknown-unknown&lt;/code&gt; with the following error:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;wasm-pack build

&lt;span class="o"&gt;[&lt;/span&gt;INFO]: 🎯  Checking &lt;span class="k"&gt;for &lt;/span&gt;the Wasm target...
&lt;span class="o"&gt;[&lt;/span&gt;INFO]: 🌀  Compiling to Wasm...
   Compiling libp2p-gossipsub v0.45.0 &lt;span class="o"&gt;(&lt;/span&gt;https://github.com/libp2p/rust-libp2p.git?branch&lt;span class="o"&gt;=&lt;/span&gt;master#14938043&lt;span class="o"&gt;)&lt;/span&gt;
error[E0599]: no method named &lt;span class="sb"&gt;`&lt;/span&gt;checked_add&lt;span class="sb"&gt;`&lt;/span&gt; found &lt;span class="k"&gt;for &lt;/span&gt;struct &lt;span class="sb"&gt;`&lt;/span&gt;wasm_timer::Instant&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;the current scope
   &lt;span class="nt"&gt;--&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /Users/yjlee/.cargo/git/checkouts/rust-libp2p-98135dbcf5b63918/1493804/protocols/gossipsub/src/peer_score.rs:872:34
    |
871 |   ...                   &lt;span class="nb"&gt;let &lt;/span&gt;window_time &lt;span class="o"&gt;=&lt;/span&gt; validated_time
    |  _________________________________________-
872 | | ...                       .checked_add&lt;span class="o"&gt;(&lt;/span&gt;topic_params.mesh_message_deliveries_window&lt;span class="o"&gt;)&lt;/span&gt;
    | |                           -^^^^^^^^^^^ method not found &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;Instant&lt;span class="sb"&gt;`&lt;/span&gt;
    | |___________________________|
    |
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;br&gt;
rust&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fortunately, it seems that we can use the &lt;a href="https://github.com/sebcrozet/instant"&gt;instant&lt;/a&gt; crate instead of &lt;code&gt;wasm_timer::Instant&lt;/code&gt;. This try had been done by &lt;a href="https://github.com/libp2p/rust-libp2p/pull/2320"&gt;rust-libp2p/pull/2320&lt;/a&gt;, but has been reverted by &lt;a href="https://github.com/libp2p/rust-libp2p/pull/2506"&gt;rust-libp2p/pull/2506&lt;/a&gt; as above. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But the one remaining problem was that the gossipsub needs the &lt;code&gt;Interval&lt;/code&gt; struct which is also dependant on the &lt;code&gt;Instant&lt;/code&gt;. To resolve this, the libp2p team is thinking of contributing an &lt;code&gt;Interval&lt;/code&gt; implementation to the &lt;code&gt;futures-timer&lt;/code&gt; crate: &lt;a href="https://github.com/libp2p/rust-libp2p/issues/2497#issuecomment-1038923700"&gt;rust-libp2p/issues/2497#issuecomment-1038923700&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;But, I think the easier solution would be just implementing the missing &lt;code&gt;wasm_imter::Instant.checked_add()&lt;/code&gt; function above into the &lt;code&gt;wasm_timer&lt;/code&gt; because the &lt;code&gt;wasm_timer&lt;/code&gt; already provides the &lt;code&gt;Interval&lt;/code&gt; struct which is being used by &lt;code&gt;rust-libp2p&lt;/code&gt; in production. However, it seems that the libp2p the doesn't want to keep maintaining the &lt;code&gt;wasm-timer&lt;/code&gt; crate.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://github.com/libp2p/rust-libp2p/blob/libp2p-v0.51.3/transports/webrtc/examples/listen_ping.rs"&gt;WebRTC example&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://github.com/vincev/wasm-p2p-chat"&gt;vincev/wasm-p2p-chat&lt;/a&gt; based on &lt;a href="https://github.com/vincev/libp2p-websys-transport"&gt;vincev/libp2p-websys-transport&lt;/a&gt; that &lt;a href="https://github.com/libp2p/rust-libp2p/issues/3611"&gt;will be included in the rust-libp2p offically&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;&lt;a href="https://docs.libp2p.io/concepts/transports/webrtc/#webrtc-private-to-private"&gt;Browser nodes cannot listen for incoming conns.&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://github.com/libp2p/js-libp2p-webrtc/tree/main/examples/browser-to-server"&gt;js-libp2p-webrtc browser-to-server example&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://github.com/libp2p/rust-libp2p/blob/libp2p-v0.51.3/examples/relay-server"&gt;Relay-server example&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;&lt;a href="https://github.com/libp2p/rust-libp2p/blob/libp2p-v0.51.3/examples/dcutr"&gt;dCUtR example&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn7"&gt;
&lt;p&gt;It seems that the hole-punching is &lt;a href="https://github.com/libp2p/rust-libp2p/discussions/3458#discussioncomment-5015353"&gt;not always successful&lt;/a&gt;. Used AWS for relayer and listener (in private subnet with NAT), and my laptop for dialer. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>libp2p</category>
      <category>p2p</category>
      <category>web3</category>
      <category>network</category>
    </item>
    <item>
      <title>Why prevote in Tendermint</title>
      <dc:creator>Youngjoon Lee</dc:creator>
      <pubDate>Wed, 10 May 2023 04:41:53 +0000</pubDate>
      <link>https://dev.to/oudwud/why-prevote-in-tendermint-338l</link>
      <guid>https://dev.to/oudwud/why-prevote-in-tendermint-338l</guid>
      <description>&lt;p&gt;Tendermint Byzantine Fault Tolerance (hereafter BFT) consensus algorithm has two stages of voting before committing a block to the state,&lt;br&gt;
while Raft consensus algorithm (that doesn't cover the Byzantine problem) has a single stage of preparation (aka. log replication) for committing a transaction.&lt;br&gt;
When I first met Tendermint, I was most curious why Tendermint has the two-stage voting (prevote-precommit).&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://atrium.lib.uoguelph.ca/xmlui/handle/10214/9769"&gt;Ethan Buchman 2016&lt;/a&gt;, he mentioned as below:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In asynchronous environments with Byzantine validators, a single stage&lt;br&gt;
of voting, where each validator casts only one vote, is not sufficient to ensure&lt;br&gt;
safety. In essence, because validators can act fraudulently, and because there&lt;br&gt;
are no guarantees on message delivery time, a rogue validator can co-ordinate&lt;br&gt;
some validators to commit a value while others, having not seen the commit,&lt;br&gt;
go to a new round, within which they commit a different value.&lt;br&gt;
&lt;br&gt; &lt;br&gt;
A single stage of voting allows validators to tell each other what they&lt;br&gt;
know about the proposal. But to tolerate Byzantine faults (which amounts,&lt;br&gt;
essentially to lies, fraud, deceit, etc.), they must also tell each other what&lt;br&gt;
they know about what other validators have professed to know about the&lt;br&gt;
proposal. In other words, a second stage ensures that enough validators&lt;br&gt;
witnessed the result of the first stage. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sounds reasonable, but I wanted to see a specific counterexample that explains why only precommit without prevote is not sufficient.&lt;/p&gt;

&lt;p&gt;Fortunately, I found a counterexample from a &lt;a href="https://www.reddit.com/r/cosmosnetwork/comments/8zwais/comment/e2nyg92/?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3"&gt;Reddit post&lt;/a&gt;.&lt;br&gt;
Below, I am going to go into details on this counterexample.&lt;/p&gt;

&lt;p&gt;Let's assume that Tendermint has only single stage of voting (aka. precommit), and the network consists of the following validator nodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 validator nodes in the network

&lt;ul&gt;
&lt;li&gt;28 offline nodes (e.g. due to network partitioning)&lt;/li&gt;
&lt;li&gt;65 honest nodes&lt;/li&gt;
&lt;li&gt;1 honest node (aka. &lt;code&gt;H&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;1 Byzantine node (aka. &lt;code&gt;B&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's say the current round is &lt;code&gt;n&lt;/code&gt;. A "valid" block is proposed by one of the validators.&lt;br&gt;
Then, all 66 (= 65 + 1) honest nodes broadcast a precommit for this valid block.&lt;br&gt;
But, let's imagine the case when the Byzantine node &lt;code&gt;B&lt;/code&gt; sends &lt;code&gt;nil&lt;/code&gt; to 65 honest nodes and itself, but a precommit to the honest node &lt;code&gt;H&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this case, &lt;code&gt;H&lt;/code&gt; has 67 precommits (&lt;code&gt;&amp;gt; 100 * 2/3&lt;/code&gt;) with its own vote. Then, &lt;code&gt;H&lt;/code&gt; will commit the block.&lt;br&gt;
However, all other nodes (65 honest + &lt;code&gt;B&lt;/code&gt;) move to the next round &lt;code&gt;n+1&lt;/code&gt; because they have only 66 precommits (&lt;code&gt;&amp;lt; 100 * 2/3&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This result is a breach of safety because the honest node &lt;code&gt;H&lt;/code&gt; committed the block that all other honest nodes didn't commit.&lt;/p&gt;

&lt;p&gt;If Tendermint has the prevote-precommit mechanism, the above example can be resolved safely.&lt;br&gt;
Let's replace all precommits in the above example with prevotes.&lt;br&gt;
Then, &lt;code&gt;H&lt;/code&gt; will broadcast a precommit to all other nodes instead of committing the block to its state,&lt;br&gt;
but it won't receive 2/3+ precommit from other nodes because all other nodes except &lt;code&gt;H&lt;/code&gt; won't broadcast a precommit since they didn't receive 2/3+ prevotes.&lt;br&gt;
As a result, all nodes will move to the next round &lt;code&gt;n+1&lt;/code&gt; without committing the block.&lt;br&gt;
Then, the consensus remains safe, even if any new block never be committed due to &lt;code&gt;B&lt;/code&gt; in subsequent rounds.&lt;/p&gt;

</description>
      <category>tendermint</category>
      <category>consensus</category>
      <category>blockchain</category>
      <category>p2p</category>
    </item>
  </channel>
</rss>
