<?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: eric-capeprivacy</title>
    <description>The latest articles on DEV Community by eric-capeprivacy (@ericape).</description>
    <link>https://dev.to/ericape</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%2F952430%2F81c239d4-c913-4dab-8f2b-ce83c668efc2.jpeg</url>
      <title>DEV Community: eric-capeprivacy</title>
      <link>https://dev.to/ericape</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ericape"/>
    <language>en</language>
    <item>
      <title>Hide And Seek</title>
      <dc:creator>eric-capeprivacy</dc:creator>
      <pubDate>Thu, 24 Nov 2022 19:59:05 +0000</pubDate>
      <link>https://dev.to/ericape/hide-and-seek-mnh</link>
      <guid>https://dev.to/ericape/hide-and-seek-mnh</guid>
      <description>&lt;p&gt;A game that we all played when we were young is probably hide and seek. When we grow up, we come up with new variants like scavenger hunt. Did you ever want to play scavenger hunt in real life but too tired to set up props? Or perhaps you can make your friends guess where you are by posting a selfie and giving hints to your exact location. I present to you, the hide and seek game. Where your browser with access to your location data, can leverage Cape to enable sharing of your secret location, without anyone but you being any the wiser. &lt;/p&gt;

&lt;p&gt;This walkthrough shows how this application is developed using technology developed at Cape Privacy. It showcases the power of data encryption without the hassle of key management. After the walkthrough, you will have a web application that you can interact with anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Playing around with it
&lt;/h2&gt;

&lt;p&gt;A example of this app has already been deployed to &lt;a href="https://codesandbox.io/s/hide-and-seek-us7feb?file=/src/App.tsx" rel="noopener noreferrer"&gt;codesandbox&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82ttp03bufzajds7bfwj.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%2F82ttp03bufzajds7bfwj.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this web application you can click the &lt;strong&gt;hide&lt;/strong&gt; button. That will encrypt your current coordinates that you can send to your friend! &lt;/p&gt;

&lt;p&gt;Once your friend receives the coordinates, they can copy it into the destination text box and click the &lt;strong&gt;seek&lt;/strong&gt; button which will tell him how far or close they are to your current location. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Cape for this solution
&lt;/h2&gt;

&lt;p&gt;Through the use of Cape encrypt, we could encrypt your location and allow you to share your data with someone else without them knowing where it is. This data is only accessible for the function you intend it for and can’t be accessed by anyone else. All of the overhead of encryption and key management has been handled by the SDK, making it easy to leverage for the application. &lt;/p&gt;

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

&lt;p&gt;The python source code for this project can be seen here on &lt;a href="https://github.com/capeprivacy/functions/tree/main/hide_and_seek" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;br&gt;
This example is run using the &lt;a href="https://github.com/capeprivacy/cape-js" rel="noopener noreferrer"&gt;Cape-JS&lt;/a&gt; and the function is deployed using &lt;a href="https://github.com/capeprivacy/cli" rel="noopener noreferrer"&gt;Cape CLI&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setup Dependencies
&lt;/h3&gt;

&lt;p&gt;Make sure you have  CLI installed by running: &lt;br&gt;
&lt;code&gt;&lt;br&gt;
curl -fsSL https://raw.githubusercontent.com/capeprivacy/cli/main/install.sh | sh&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create the Function
&lt;/h3&gt;

&lt;p&gt;The function is relatively simple but showcases a couple of nuances in how it is invoked.&lt;/p&gt;

&lt;p&gt;What’s interesting about the current &lt;strong&gt;cape_handler&lt;/strong&gt; &lt;a href="https://github.com/capeprivacy/functions/blob/main/hide_and_seek/seek/app.py#L27" rel="noopener noreferrer"&gt;function&lt;/a&gt; is that the handler expects to take two user-provided inputs, one after the other. It will persist the first input on disk until the invocation is complete. &lt;br&gt;
This allows the handler function to take an encrypted input first and a non-encrypted input after. Achieving the desired result of mixed encrypted and unencrypted inputs. &lt;/p&gt;

&lt;p&gt;Calling this function from an external source would take on the form of: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect (connects to the enclave)&lt;/li&gt;
&lt;li&gt;Invoke (send first input)&lt;/li&gt;
&lt;li&gt;Invoke (send second input)&lt;/li&gt;
&lt;li&gt;Close (close the connection to the invocation, resetting the state of the function) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;app.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;unicodedata&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;geopy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;geopy.distance&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;geodesic&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;GD&lt;/span&gt;


&lt;span class="n"&gt;FILE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./secret.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;open_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FILE_PATH&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;FILE_PATH&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# Function needs to check if the coordinates match the one that was provided.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cape_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# use file cache instead
&lt;/span&gt;    &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open_secret&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Store the current input as secret
&lt;/span&gt;        &lt;span class="nf"&gt;store_secret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Calculate the difference between the user secret and the current input.
&lt;/span&gt;        &lt;span class="n"&gt;user_loco&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latitude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;longitude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;secret_loco&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latitude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;longitude&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secret_loco&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_loco&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Congrats you found the treasure!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Getting closer! still &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; meters away&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Not even close! still &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; meters away&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;requirements.txt&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;geographiclib==1.52
geopy==2.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;secret.json&lt;/strong&gt;&lt;br&gt;
Just an empty file that can be created by: &lt;br&gt;
&lt;code&gt;touch seek/secret.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At this point the &lt;strong&gt;seek&lt;/strong&gt; directory should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requirements.txt
seek/
   - app.py
   - secret.json (empty file)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before deploying this function, we have to install the dependencies with the function by calling (from the parent directory of [seek]):&lt;br&gt;
&lt;code&gt;pip install -r requirements.txt --target seek/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will install the dependencies required to run the function. &lt;br&gt;
Next step will be to deploy this function to Cape using the Cape CLI tool. &lt;/p&gt;
&lt;h3&gt;
  
  
  Deploy the Function
&lt;/h3&gt;

&lt;p&gt;To deploy the function use the cape binary that has been downloaded from the CLI step and run: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;cape login&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will give you a prompt to open up a browser and login to your github account. &lt;/p&gt;

&lt;p&gt;To deploy the function run: &lt;br&gt;
&lt;code&gt;cape deploy seek/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will see an output like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Function ID ➜  YmoDB35PKxZS9v6eaU84YR
Function Checksum ➜  6b6d1c8b21f896269554cf633da084b25b49706a8efb41463687f353e0395171
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;br&gt;
&lt;code&gt;cape token &amp;lt;FUNCTION_ID&amp;gt; --function-checksum &amp;lt;FUNCTION _CHECKSUM&amp;gt; -o json &amp;gt;  seek.json&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Interacting with the Function via the React App
&lt;/h3&gt;

&lt;p&gt;To use the deployed function, we will use &lt;a href="https://github.com/capeprivacy/cape-js" rel="noopener noreferrer"&gt;Cape-JS&lt;/a&gt; and use the &lt;strong&gt;encrypt&lt;/strong&gt; and &lt;strong&gt;invoke&lt;/strong&gt; methods defined through the Cape client.&lt;/p&gt;

&lt;p&gt;To call the function from the example &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; App, simply update the following file to reflect the &lt;strong&gt;functionID&lt;/strong&gt; and &lt;strong&gt;functionToken&lt;/strong&gt; from &lt;strong&gt;seek.json&lt;/strong&gt; obtained in the previous script to the file &lt;a href="https://codesandbox.io/s/hide-and-seek-us7feb?file=/src/App.tsx" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This project showcases the power of Cape to share data amongst different parties in a purely encrypted format. It also showcases a workaround for stateful execution and temporary data persistence from within the enclave. These methods allow the developer using Cape SDKs to expand the capabilities of their functions and interact with them from various platforms. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Leader election in the enclave</title>
      <dc:creator>eric-capeprivacy</dc:creator>
      <pubDate>Mon, 24 Oct 2022 18:54:32 +0000</pubDate>
      <link>https://dev.to/ericape/leader-election-in-the-enclave-3ho5</link>
      <guid>https://dev.to/ericape/leader-election-in-the-enclave-3ho5</guid>
      <description>&lt;h2&gt;
  
  
  Leader Election Problem
&lt;/h2&gt;

&lt;p&gt;In the no-longer-as-niche world of distributed systems, there is always a fundamental problem whose solution came to be the building block of modern day massively distributed computation platforms. Of course I'm talking about &lt;a href="https://www.geeksforgeeks.org/distributed-consensus-in-distributed-systems/"&gt;consensus&lt;/a&gt;. Past versions of achieving this include algorithms like &lt;a href="https://lamport.azurewebsites.net/pubs/paxos-simple.pdf"&gt;Paxos&lt;/a&gt; and &lt;a href="https://raft.github.io/raft.pdf"&gt;Raft&lt;/a&gt;, which have seen much adoption in today’s distributed services. Before we get any further though let’s get some term definitions out of the way. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction&lt;/strong&gt; - A state change that needs to be broadcasted throughout the distributed network&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peer&lt;/strong&gt; - A computer or server that participates either in generating a transaction (e.g. peer A sends some money to peer B) or validating the transaction&lt;/p&gt;

&lt;p&gt;These algorithms may not seem like much hype outside of the fact that they form the backbone of how applications are able to handle terabytes of concurrent data, but you may have heard about Bitcoin and their &lt;a href="https://www.ussc.gov/sites/default/files/pdf/training/annual-national-training-seminar/2018/Emerging_Tech_Bitcoin_Crypto.pdf"&gt;Proof-of-work&lt;/a&gt; (POW) algorithm. At the heart of Bitcoin is a very expensive and fault-tolerant solution to the consensus problem. It has often been the complaint of many that the Proof-of-work algorithm is too costly and woefully inefficient. As a result, new consensus algorithms like &lt;a href="https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/"&gt;Proof-of-stake&lt;/a&gt; (POS) have been invented to fundamentally alter how the consensus problem is solved in massively distributed open networks such as &lt;a href="https://ethereum.org/en/"&gt;Ethereum&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Even then the chance of misconduct still remains. Each view of the transactions may not match that of other peers in the network, giving opportunity for double spending attacks until the overall system reaches eventual consistency (majority of peers agree on a state change in the system) after a couple of blocks. Since the validators are less in number the question of correct and unbiased processing of transactions. &lt;/p&gt;

&lt;p&gt;With this adoption of POS come new challenges. The peer with more stake in the system that functions as a validator may still choose to bias against certain transactions without being penalized. One method to avoid this bias is to run part of the block generation process in a trusted execution environment, where the chosen transactions are guaranteed to be chosen fairly. We can show this via a simple leader election demo to showcase how easy it is to leverage Cape to do this. &lt;/p&gt;

&lt;p&gt;This demo is done as part of an internal hackathon and serves to showcase how a part of the protocol can be migrated into confidential computation for more trusted output. The goal is to have the secure execution environment decide on who is the leader of peers in a network. Currently in this example we did not add fault tolerance as there is no timeout value set. For each peer started in the demo, it will try to gossip with other peers in the network and rely on Cape for determining who is the leader amongst the peers. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Cape for this solution
&lt;/h2&gt;

&lt;p&gt;Cape brings the power of confidential computing alongside modern day encryption to keep the data confidential. In this use case, we focus on the confidential computing aspect that Cape offers. The deployed function with Cape is validated during invocation to make sure that the function is the one intended to be called. This guarantee in execution logic is what allows for trusted output.  An example of this is illustrated below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pQRtS-g5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lchu7a0rpdupyzdh0r01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pQRtS-g5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lchu7a0rpdupyzdh0r01.png" alt="Image description" width="397" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cape deploy returns the function checksum, if the checksum validation fails, the data is never submitted for running the function. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nm9t7sc---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lejhho95rs5wr58tiuy0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nm9t7sc---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lejhho95rs5wr58tiuy0.png" alt="Image description" width="507" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;A running example of this code can be seen here on &lt;a href="https://github.com/capeprivacy/functions/tree/main/leader-election"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This example is run using the &lt;a href="https://pydocs.capeprivacy.com/"&gt;PyCape&lt;/a&gt; and function is deployed using &lt;a href="https://github.com/capeprivacy/cli"&gt;CapeCLI&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Dependencies
&lt;/h4&gt;

&lt;p&gt;Make sure you have  CLI installed by running: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -fsSL https://raw.githubusercontent.com/capeprivacy/cli/main/install.sh | sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Make sure you have  PyCape installed by running: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install pycape&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Create the function
&lt;/h4&gt;

&lt;p&gt;The function is created with a public/private key pair and returns a result that is signed with the private key. &lt;/p&gt;

&lt;p&gt;In a python environment run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;key = RSA.generate(2048)
private_key_bytes = key.export_key('PEM')
public_key_bytes = key.publickey().exportKey('PEM')
with open("private.pem", "wb") as f:
    f.write(private_key_bytes)

with open("public.pem", "wb") as f:
    f.write(public_key_bytes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the generated public and private key into a &lt;strong&gt;function&lt;/strong&gt; folder with the following files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
from unicodedata import name
from Crypto import Random
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

def cape_handler(arg):
    user_input = json.loads(arg)
    if "node_list" not in user_input:
        raise Exception("node list is missing")

    nodes = user_input.get("node_list")
    nodes.sort()
    message = str(nodes[-1])
    digest = SHA256.new()
    digest.update(message.encode("utf-8"))
    private_key = RSA.importKey(open("private.pem").read())
    signer = PKCS1_v1_5.new(private_key)
    sig = signer.sign(digest)
    return_val = {}
    return_val["message"] = message
    return_val["signature"] = sig.hex()
    return json.dumps(return_val)

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;requirements.txt&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pycryptodome==3.15.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;at this point the &lt;strong&gt;function&lt;/strong&gt; directory should look 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;function/
   - app.py
   - private.pem
   - public.pem (not necessary, included for convenience later)
   - requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before deploying this function, we have to install the dependencies with the function by calling (from the parent directory of &lt;strong&gt;function&lt;/strong&gt;)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install -r function/requirements.txt --target function/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will install the dependencies required to run the function. &lt;/p&gt;

&lt;h4&gt;
  
  
  Deploy the function
&lt;/h4&gt;

&lt;p&gt;To deploy the function use the cape binary that has been downloaded from the CLI step and run: &lt;br&gt;
&lt;code&gt;cape login&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will give you a prompt to open up a browser and login to your github account. &lt;/p&gt;

&lt;p&gt;To deploy the function run: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;cape deploy function/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You will see an output like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Function ID ➜  YmoDB35PKxZS9v6eaU84YR

Function Checksum ➜  6b6d1c8b21f896269554cf633da084b25b49706a8efb41463687f353e0395171`

Then run:

`cape token &amp;lt;FUNCTION_ID&amp;gt; --function-checksum &amp;lt;FUNCTION _CHECKSUM&amp;gt; -o json &amp;gt;  leader_election.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running
&lt;/h3&gt;

&lt;p&gt;Note the functionID and functionChecksum fields in the previous step as they will be important in getting the example working. &lt;/p&gt;

&lt;p&gt;In your local environment copy the folder &lt;strong&gt;gossip&lt;/strong&gt; from &lt;a href="https://github.com/capeprivacy/functions/tree/main/leader-election/gossip"&gt;here&lt;/a&gt; and make sure you have this &lt;a href="https://github.com/capeprivacy/functions/blob/main/leader-election/start_node.py"&gt;file&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now you are ready to try out running the example by calling in two separate terminals with your deployed functionID and functionChecksum: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;python start_node.py -p 5000 -n 5001 -f&lt;/code&gt;&lt;code&gt;-fh&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;python start_node.py -p 5001 -n 5000 -f &lt;code&gt;&amp;lt;FUNCTION_ID&amp;gt;&lt;/code&gt; -fh &lt;code&gt;&amp;lt;FUNCTION_CHECKSUM&amp;gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;This will start the gossip protocol between two peers in the local environment and have them send &lt;a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol"&gt;UDP&lt;/a&gt; packets with each other and print out who the leader is between the nodes. You can also add new peers and see how the algorithm works with more peers in the system.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;This is just a simple example of how to migrate a part of the consensus logic into a TEE for guaranteed correctness of execution. Bitcoin and Ethereum took this concept to a globally distributed peer system and found huge success. Fundamentally the value of these systems rely on generating trust. TEEs give you similar levels of execution guarantee without the need to have lots of graphics cards or lots of Ethereum. &lt;/p&gt;

&lt;p&gt;With a more complete example in the future we can devise a more efficient consensus algorithm using TEE and showcase that the number of messages can be reduced dramatically even under &lt;a href="https://en.wikipedia.org/wiki/Byzantine_fault"&gt;Byzantine&lt;/a&gt; conditions. &lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://docs.capeprivacy.com/getting-started/"&gt;Getting Started Docs&lt;/a&gt; to try Cape for free. We’d love to &lt;a href="https://forms.gle/5pBagHQRff5SN1wG8"&gt;hear what you think&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>distributedsystems</category>
    </item>
  </channel>
</rss>
