{"id":7749,"date":"2018-06-01T09:28:34","date_gmt":"2018-06-01T16:28:34","guid":{"rendered":"\/developerblog\/?p=7749"},"modified":"2020-03-19T13:28:12","modified_gmt":"2020-03-19T20:28:12","slug":"creating-private-ethereum-consortium-kubernetes","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/creating-private-ethereum-consortium-kubernetes\/","title":{"rendered":"Building a Private Ethereum Consortium"},"content":{"rendered":"<h2>Background<\/h2>\n<p>The travel industry estimates 3-5% of bookings are disputed due to discrepancies in the data held by each party and can take months to resolve.\u00a0Over the past two years, Microsoft and <a href=\"http:\/\/www.Webjetlimited.com\">Webjet <\/a>have collaborated to build a blockchain-based solution, Rezchain, that helps travel companies resolve data and avoid invoice reconciliation issues. You can read more about our previous work in the following code stories:<em> <a href=\"\/www.microsoft.com\/developerblog\/2017\/04\/18\/using-a-layer-7-proxy-for-ethereum-blockchain\">Using a Layer 7 proxy for Ethereum Blockchain<\/a>, <a href=\"https:\/\/www.microsoft.com\/developerblog\/2018\/02\/09\/using-helm-deploy-blockchain-kubernetes\">Using Helm to Deploy Blockchain to Kubernetes<\/a><\/em>.<\/p>\n<p>Earlier this year, <a href=\"https:\/\/www.webjetlimited.com\/wp-content\/uploads\/2018\/02\/Rezchain_Release.pdf\">Webjet announced<\/a> the expansion of <a href=\"http:\/\/www.rezchain.com\/\">Rezchain<\/a>. One of the challenges we faced in our recent <a href=\"http:\/\/www.zdnet.com\/article\/microsoft-takes-its-developer-outreach-beyond-the-traditional-hackathon\/\">hackfest<\/a> with Webjet was how to connect each party&#8217;s Ethereum network to form a consortium. For a consortium, Ethereum nodes should be distributed across the network and, optionally, each participating member of Rezchain will host their own Ethereum nodes. In this code story, we\u2019ll share some of the lessons we learned in creating the Rezchain consortium. In particular, we&#8217;ll focus on how we solved the challenges involved with enabling Ethereum nodes to peer inside and across virtual networks.<\/p>\n<p><!--more--><\/p>\n<h2>The Challenge<\/h2>\n<p>In <a href=\"https:\/\/blog.ethereum.org\/2015\/08\/07\/on-public-and-private-blockchains\/\">this article<\/a> by Vitalik Buterin, co-founder of Ethereum, blockchain applications generally fall into three categories based on their access privileges and who can participate in the consensus process: public, consortium, and private.<\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"156\"><strong><em>Transaction<\/em><\/strong><\/td>\n<td width=\"156\"><strong>Public<\/strong><\/td>\n<td width=\"156\"><strong>Consortium<\/strong><\/td>\n<td width=\"156\"><strong>Private<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"156\"><em>Send<\/em><\/td>\n<td width=\"156\">Anyone<\/td>\n<td width=\"156\">Limited<\/td>\n<td width=\"156\">Centralized<\/td>\n<\/tr>\n<tr>\n<td width=\"156\"><em>Approve<\/em><\/td>\n<td width=\"156\">Anyone<\/td>\n<td width=\"156\">Limited<\/td>\n<td width=\"156\">Centralized<\/td>\n<\/tr>\n<tr>\n<td width=\"156\"><em>Read<\/em><\/td>\n<td width=\"156\">Anyone<\/td>\n<td width=\"156\">Limited<\/td>\n<td width=\"156\">Limited<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In a public blockchain, anyone can read and send transactions to the chain and participate in the consensus process. On the other hand, with a private blockchain write permissions are centralized to a single organization and read permissions can be restricted to an arbitrary extent. Falling in the middle of the spectrum, a consortium blockchain has read and write permissions limited to a certain number of parties in the network.<\/p>\n<p>It is important that hotel booking transactions and any company-sensitive data remain private. Any data on the blockchain would be disclosed to all connected parties, and Webjet decided to store hash values to ensure sensitive details are not stored on the chain. As the blockchain eco-system is still evolving, Webjet has decided to run blockchain as consortium model at the moment. It also helps with efforts to maintain and support blockchain transaction nodes and miners. The Rezchain\u2019s consortium consists of Webjet subsidiary hotel distribution brands, such as Lots of Hotels and JacTravel, with each company controlling and hosting their own Ethereum nodes. The challenge is how to enable the Ethereum nodes from one network (Lots of Hotel) to connect and peer with Ethereum nodes of another (JacTravel) where these Ethereum nodes could be potentially located in various parts of the world and hosted under different network topologies and network constraints. Working in collaboration with Webjet, we arrived at a solution that will enable Ethereum nodes to connect over the public Internet and to form a blockchain consortium.<\/p>\n<h2>The Solution<\/h2>\n<p>Before presenting the final solution, background information of the methods that Ethereum employs to discover and peer with other Ethereum nodes is necessary.<\/p>\n<h2>Ethereum Peering<\/h2>\n<p>There are 3 different ways in which peers can be configured: bootnode, static nodes, and trusted nodes:<\/p>\n<table style=\"height: 147px;\" width=\"920\">\n<tbody>\n<tr>\n<td width=\"156\"><\/td>\n<td width=\"156\"><strong>Bootnode<\/strong><\/td>\n<td width=\"156\"><strong>Static Nodes\n<\/strong><\/td>\n<td width=\"156\"><strong>Trusted Nodes\n<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"156\"><em>Uses Node Discovery<\/em><\/td>\n<td width=\"156\">Yes<\/td>\n<td width=\"156\">No<\/td>\n<td width=\"156\">No<\/td>\n<\/tr>\n<tr>\n<td width=\"156\"><em>Transport Protocols Used<\/em><\/td>\n<td width=\"156\">UDP, TCP<\/td>\n<td width=\"156\">TCP<\/td>\n<td width=\"156\">TCP<\/td>\n<\/tr>\n<tr>\n<td width=\"156\"><em>Adheres to Max Peers<\/em><\/td>\n<td width=\"156\">Yes<\/td>\n<td width=\"156\">Yes<\/td>\n<td width=\"156\">No<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Bootnode<\/h3>\n<p><a href=\"https:\/\/github.com\/ethereum\/go-ethereum\/wiki\/Setting-up-private-network-or-local-cluster#setup-bootnode\">Bootnode<\/a> is a lightweight application used for the <a href=\"https:\/\/github.com\/ethereum\/devp2p\/blob\/master\/rlpx.md#node-discovery\">Node Discovery Protocol<\/a>. Bootnodes do not sync chain data. Using a UDP-based <a href=\"https:\/\/en.wikipedia.org\/wiki\/Kademlia\">Kademlia<\/a>-like RPC protocol, Ethereum will connect and interrogate these bootnodes for the location of potential peers. The Ethereum Foundation maintains several bootnodes for the public Ethereum networks; the endpoints of which are <a href=\"https:\/\/github.com\/ethereum\/go-ethereum\/blob\/master\/params\/bootnodes.go\">hard-coded in the Geth source code<\/a>. The default list can be configured using the <code>--bootnodes<\/code> option:<\/p>\n<pre class=\"\">geth --bootnodes [enode:\/\/pubkey1@ip1:port1,enode:\/\/pubkey2@ip2:port2,\u2026]<\/pre>\n<p>Given the list of potential peers, Geth will then attempt to connect to each peer over TCP to negotiate and ensure compatibility with protocol version, network IDs, and genesis blocks.<\/p>\n<h3>Static Nodes<\/h3>\n<p>Static Nodes are pre-configured connections which are always maintained and re-connected on disconnects by Ethereum nodes. As static nodes will be connected to directly, no UDP discovery is required. They can be configured at runtime through the JavaScript console:<\/p>\n<pre class=\"\">$ admin.addPeer(\"enode:\/\/f4642fa65af50cfdea8fa7414a5def7bb7991478b768e296f5e4a54e8b995de102e0ceae2e826f293c481b5325f89be6d207b003382e18a8ecba66fbaf6416c0@33.4.2.1:30303\")\r\n$ admin.addPeer(\"enode:\/\/pubkey@ip:port\")<\/pre>\n<p>Or by supplying a &#8220;static-nodes.json\u201d file in the Geth data directory:<\/p>\n<pre>$ cat GETH-DATA-DIR\/static-nodes.json\r\n[\r\n\"enode:\/\/f4642fa65af50cfdea8fa7414a5def7bb7991478b768e296f5e4a54e8b995de102e0ceae2e826f293c481b5325f89be6d207b003382e18a8ecba66fbaf6416c0@33.4.2.1:30303\",\r\n\"enode:\/\/pubkey@ip:port\"\r\n]<\/pre>\n<h3>Trusted Nodes<\/h3>\n<p>Similar to Static Nodes, Trusted Nodes are pre-configured peers which Geth <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"why? does this prevent an eclipse attach? or other issues?\" data-author=\"Shawn Cicoria\">will always try to stay connected to even after the peer limit has been reached.<\/span> The peer limit is a limit to the number of peers that a Geth node can connect to; the default value is 25, but it can be configured using the <code>--maxpeers<\/code> flag. Trusted Nodes can be configured by supplying a \u201ctrusted-nodes.json\u201d file in the Geth data directory:<\/p>\n<pre>$ cat GETH-DATA-DIR\/trusted-nodes.json\r\n[\r\n\"enode:\/\/f4642fa65af50cfdea8fa7414a5def7bb7991478b768e296f5e4a54e8b995de102e0ceae2e826f293c481b5325f89be6d207b003382e18a8ecba66fbaf6416c0@33.4.2.1:30303\",\r\n\"enode:\/\/pubkey@ip:port\"\r\n]<\/pre>\n<h2>Connecting the Consortium<\/h2>\n<p>In this section, we&#8217;ll present a generalized approach to connect the Ethereum nodes of each member to participate in the consensus process and form a consortium.<\/p>\n<p><a href=\"https:\/\/www.microsoft.com\/developerblog\/2018\/02\/09\/using-helm-deploy-blockchain-kubernetes\/\">Using Helm to Deploy Blockchain to Kubernetes<\/a> walks through deploying an Ethereum network to Kubernetes using Helm. In doing so, you will have an Ethereum network that looks like the following:<\/p>\n<p><figure id=\"attachment_7789\" aria-labelledby=\"figcaption_attachment_7789\" class=\"wp-caption aligncenter\" ><img decoding=\"async\" class=\"aligncenter size-full wp-image-10683\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2018\/06\/Geth-Single-Network.png\" alt=\"Image Geth Single Network\" width=\"802\" height=\"598\" srcset=\"https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2018\/06\/Geth-Single-Network.png 802w, https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2018\/06\/Geth-Single-Network-300x224.png 300w, https:\/\/devblogs.microsoft.com\/ise\/wp-content\/uploads\/sites\/55\/2018\/06\/Geth-Single-Network-768x573.png 768w\" sizes=\"(max-width: 802px) 100vw, 802px\" \/><figcaption id=\"figcaption_attachment_7789\" class=\"wp-caption-text\"><br \/>Private Ethereum Network<\/figcaption><\/figure><\/p>\n<p>In order to connect the Ethereum networks of each member, we applied a mixture of Ethereum&#8217;s peering strategies to enable the Ethereum nodes of one member&#8217;s network to peer and communicate with nodes from another <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"number the flows if you can. 1 on the first, then 2\/3 on both the right hand side.\" data-author=\"Shawn Cicoria\">network to form a consortium.<\/span><\/p>\n<p><!-- TODO - missing image --><\/p>\n<p><figure id=\"attachment_8426\" aria-labelledby=\"figcaption_attachment_8426\" class=\"wp-caption aligncenter\" ><img decoding=\"async\" class=\"wp-image-8426 size-large\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2020\/03\/Geth-Private-Network-1.png\" alt=\"\" width=\"1024\" height=\"657\" \/><figcaption id=\"figcaption_attachment_8426\" class=\"wp-caption-text\">Ethereum Consortium with 2 Members<\/figcaption><\/figure><\/p>\n<p>As shown in the diagram above, building upon the <a href=\"https:\/\/github.com\/kubernetes\/charts\/pull\/3220\">original Helm chart<\/a>, we made a couple of modifications to enable peering across virtual networks.<\/p>\n<p>Within a member&#8217;s network, we used bootnode for discovery and peering of Ethereum nodes. In doing so, this enables easier scaling in\/out of Ethereum nodes as each new node will be able to discover other peers using the Ethereum Node Discovery Protocol. For high availability, we deployed several replicas of bootnode. On start-up, each bootnode registers against a registrar (bootnode-registrar) that maintains a list of active bootnodes. Prior to an Ethereum node launching, an HTTP call is made to the bootnode-registrar service to retrieve the list of bootnodes and then passing the list of bootnodes to the Ethereum node using the <code>--bootnodes<\/code> flag. The <a href=\"https:\/\/github.com\/jpoon\/bootnode-registrar\">bootnode-registrar<\/a> is available on GitHub and an accompanying <a href=\"https:\/\/github.com\/jpoon\/kubernetes-ethereum-chart\/tree\/bootnode-registrar\">Helm chart<\/a> can be used to deploy the networks for one of the consortium members.<\/p>\n<p>To connect a member&#8217;s Ethereum network to another member, we exposed the P2P ports of one Ethereum node (Geth-Tx-Public) to the public internet. Following the same pattern as the bootnode-registrar, the public <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"This process isn't secure today. We probably should note that somewhere\" data-author=\"Eric Maino\">Ethereum node registers<\/span> with a registrar <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"This appears to be glossed over. It would be good to talk about it and share a pointer to the repo\" data-author=\"Eric Maino\">(staticnode-registrar)<\/span> and subsequently retrieves a list of nodes that have registered. The list is then passed to Geth through the static-nodes.json configuration. The <a href=\"https:\/\/github.com\/EthereumEx\/bootnode-registrar\">staticnode-registrar<\/a> is available on GitHub (note: the repository is named &#8216;bootnode-registrar&#8217;).<\/p>\n<p>Once the discovery and peering is complete, the Ethereum network will look like the following diagram:<\/p>\n<p><figure id=\"attachment_8427\" aria-labelledby=\"figcaption_attachment_8427\" class=\"wp-caption aligncenter\" ><img decoding=\"async\" class=\"wp-image-8427 size-large\" src=\"https:\/\/devblogs.microsoft.com\/cse\/wp-content\/uploads\/sites\/55\/2020\/03\/Geth-Private-Network-Simplified.png\" alt=\"\" width=\"1024\" height=\"344\" \/><figcaption id=\"figcaption_attachment_8427\" class=\"wp-caption-text\">Ethereum Consortium with 2 Members (Simplified view following discovery and peering)<\/figcaption><\/figure><\/p>\n<h2>Summary<\/h2>\n<p>As companies begin to explore scenarios to leverage blockchain, consortium blockchains are becoming increasingly popular. This code story has walked through the learnings of our collaboration with Webjet in building a blockchain consortium. One of the biggest challenges we faced in our engagement was how to enable Ethereum nodes to be able to discover and peer with one another \u2013 an obstacle we overcame using a <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"I'd say &quot;custom static.. &quot;custom boot...&quot; this was essentially solved through a custom service correct? that's the key set of bits that if I was reading this is what I'd be diving into right now.\" data-author=\"Shawn Cicoria\">mixture of Ethereum peering techniques and custom services (bootnode-registrar and staticnode-registrar).\n<\/span><\/p>\n<p>In order to deploy our network in a more highly available nature, we&#8217;ve developed <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"basic registrars. We know these are not secure today, but will evolve to locking them down.\" data-author=\"Eric Maino\">registrars <\/span>for the <a href=\"https:\/\/github.com\/jpoon\/bootnode-registrar\">bootnode<\/a> and <a href=\"https:\/\/github.com\/EthereumEx\/bootnode-registrar\">staticnodes<\/a> which we have made available on GitHub. Please note that the implementation of the registrars is incomplete and does not offer any level of security. If you have any questions or feedback on this code story, <span class=\"annotation\" style=\"background-color: #f0e465;\" data-annotation=\"can i file issues on the repo too?\" data-author=\"Shawn Cicoria\">please reach out in the comments below or through the respective GitHub repositories.\n<\/span><\/p>\n<h2>Resources<\/h2>\n<ul>\n<li><a href=\"http:\/\/www.zdnet.com\/article\/webjet-launches-blockchain-as-a-service-hotel-distribution-solution\/\">News Article: Webjet launches blockchain-as-a-service hotel distribution solution<\/a><\/li>\n<li><a href=\"https:\/\/www.microsoft.com\/developerblog\/2018\/02\/09\/using-helm-deploy-blockchain-kubernetes\/\">Using Helm to Deploy Blockchain to Kubernetes<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/jpoon\/kubernetes-ethereum-chart\/tree\/bootnode-registrar\">GitHub: Helm Chart to Deploy a Private Ethereum Network<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/jpoon\/bootnode-registrar\">GitHub: Bootnode-Registrar<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/EthereumEx\/bootnode-registrar\">GitHub: StaticNode-Registrar (Note: the repo is named &#8216;bootnode-registrar&#8217;)<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Over the past two years, Microsoft and Webjet have collaborated to build a blockchain-based solution, Rezchain, to help travel companies reduce payment disputes. In this code story, we\u2019ll share the lessons learned in creating the Rezchain consortium.  In particular, we&#8217;ll focus on how we solved the challenges involved with enabling Ethereum nodes to peer across virtual networks.<\/p>\n","protected":false},"author":21365,"featured_media":10682,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[12,15],"tags":[60,105,172,177,229],"class_list":["post-7749","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blockchain","category-containers","tag-azure","tag-blockchain","tag-ethereum","tag-featured","tag-kubernetes"],"acf":[],"blog_post_summary":"<p>Over the past two years, Microsoft and Webjet have collaborated to build a blockchain-based solution, Rezchain, to help travel companies reduce payment disputes. In this code story, we\u2019ll share the lessons learned in creating the Rezchain consortium.  In particular, we&#8217;ll focus on how we solved the challenges involved with enabling Ethereum nodes to peer across virtual networks.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/7749","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21365"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=7749"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/7749\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media\/10682"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=7749"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=7749"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=7749"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}