Skip to content

Instantly share code, notes, and snippets.

@lingqingmeng
Created February 16, 2019 20:09
Show Gist options
  • Save lingqingmeng/13abfbfa133a7739993a7dcfdd6de0ca to your computer and use it in GitHub Desktop.
Save lingqingmeng/13abfbfa133a7739993a7dcfdd6de0ca to your computer and use it in GitHub Desktop.
NYC Blockchain Center Materials

NYC BLOCKCHAIN CENTER WORKSHOP

Workshop files used for Blockchain Developer Seminar: Applied Rust for Protocol Development

We will send out finished projects after each tutorial. Code demonstration will be given live. If you prefer following along more than welcome to. We will release a video and a finalized codebase later this week.

Overview

To run this project, make sure we have the latest rustc version, which is the official compiler for Rust.

Dependency: Rustc

Update to the latest version by running

rustup update

Dependency: Python

A python client is located in the client folder. It will be our means of interacting with our rust server.

To run the client, install request package from pip and locate to the client folder.

pip install request
cd ./client/

and run the python code.

python client.py

// should print "true"

Body

I. Topic 1

for Topic 1,

Take a look of how ECDSA works

Build a simple web authentication server with jsonrpc and secp256k1

Bring it together by combining our modules in steps I and II

Projects

II. Topic 2

Build and run a WASM module in react web app

Build and run a runtime (analogous to Smart Contract in the Polkadot ecosystem)

Deploy it on Substrate

Projects

III. Topic 3

Future implications to the blockchain ecosystem that Rust and WASM brings

Projects

Topic 1-1: simple_web_server

This tutorial instructs how to build a simple web RPC server and test it with clients, and it uses JSON-RPC 2.0 specification to exchange data.

Why JSON-RPC 2.0?

JSON-RPC is a light-weight remote procedure call (RPC) protocol. Its lightness attracted many blockchain projects to adopt this to their protocol.

Blockchain projects using this specification are:

  • Parity(they even implemented this specification by themselves in Rust)
  • Ethereum
  • Bitcoin
  • Ripple
    ...and many more

Setup

If the project cannot be compiled, update rust with rust version manager rustup

rustup update

Navigate to the directory of this project from the cloned repository on terminal and build the project

cd ./Topic1/01_simple_web_server/
cargo build

then run the project.

cargo run

afterwards, to run executable

 ./target/debug/rust_crypto

Client

Client sends request to RPC server and it is implemented in blockchain and wallets.

It sends two types of params

or as an object:

{
	"jsonrpc": "2.0",
	"method": "say_hello",
	"params": {"name": "Hyungsuk Kang"},
	"id":1
}

Make API with the interface to send corresponding json to RPC endpoints then you get:

  • web3.js
  • web3.py
  • web3j
  • web3swift
  • polkadot-api

For tutorial we will use Postman, but you can also test your server with the client file built here

Once you install postman set the request options as shown as below:

postman setting1

postman setting2

Press send button and you have now finished a RPC-JSON server development!

Appendix: Rust Keywords

as - perform primitive casting, disambiguate the specific trait containing an item, or rename items in use and extern crate statements
break - exit a loop immediately
const - define constant items or constant raw pointers
continue - continue to the next loop iteration
crate - link an external crate or a macro variable representing the crate in which the macro is defined
dyn - dynamic dispatch to a trait object
else - fallback for if and if let control flow constructs
enum - define an enumeration
extern - link an external crate, function, or variable
false - Boolean false literal
fn - define a function or the function pointer type
for - loop over items from an iterator, implement a trait, or specify a higher-ranked lifetime
if - branch based on the result of a conditional expression
impl - implement inherent or trait functionality
in - part of for loop syntax
let - bind a variable
loop - loop unconditionally
match - match a value to patterns
mod - define a module
move - make a closure take ownership of all its captures
mut - denote mutability in references, raw pointers, or pattern bindings
pub - denote public visibility in struct fields, impl blocks, or modules
ref - bind by reference
return - return from function
Self - a type alias for the type implementing a trait
self - method subject or current module
static - global variable or lifetime lasting the entire program execution
struct - define a structure
super - parent module of the current module
trait - define a trait
true - Boolean true literal
type - define a type alias or associated type
unsafe - denote unsafe code, functions, traits, or implementations
use - bring symbols into scope
where - denote clauses that constrain a type
while - loop conditionally based on the result of an expression

Topic 1-2: ECDSA

This tutorial teaches how ECDSA works and builds ring signatures based on rust bindings of secp256k1 C++ library which is used in Bitcoin.

Background on Cryptography

RSA

RSA is an asymmetric algorithm that can be used for encryption and signing. The related algorithm for creating a shared secret symmetric key (key exchange) is Diffie-Hellman. RSA bases its security on the difficulty of integer factorization, while Diffie-Hellman uses the difficulty of finding discrete logarithms. Using RSA directly is often impossible, it works on integers and the operations are quite slow. That creates a need for padding (making messages the right size) and makes it impractical to encrypt or sign large amounts of data directly. These issues (and some others) make RSA fragile: it's easy to screw up the implementation of the padding system or the actual encryption/signing to leak data. Bleichenbacher's Oracle (found in 1998) was an attack on RSA with bad padding implementations. A few days ago it was found to still be present in some major implementations.

DSA

DSA uses a very similar process to RSA signing internally, but specifies the particular key generation and hashing steps needed to create signatures properly. More importantly it bases its security not over the difficulty of integer factorization but on the difficulty of the discrete logarithm problem. DSA is only for signatures, not for encryption or key exchange. Unfortunately DSA and ECDSA are fragile: it requires a value to be chosen at random for each signature created. Failure to do this properly results in leaking the private key. The leak of the Sony Playstation 3 DRM key was due to this failure. There are also some easy ways to accidentally leak timing information.

ECDSA

ECDSA is very similar to DSA, but uses elliptic curve cryptography (ECC). ECC uses a different trapdoor function than RSA. Its security is based on the difficulty of the elliptic curve discrete logarithm problem. It allows for smaller key sizes than DSA, and is a good bit faster, but suffers from the same fragility as DSA (and RSA). This ECDSA type of cryptography is what we will primarily cover in this tutorial. It also the standard for almost all blockchains

EdDSA

EdDSA is an alternative to ECDSA designed not to have the fragility issues that DSA/ECDSA/RSA have. It's also faster. If you have a choice of signature algorithms this is the one to use.

X25519

X25519 is a form of Elliptic-Curve Diffie-Hellman (ECDH) algorithm. It's used for key exchange. It's very fast and quite robust. If you have a choice of key exchange algorithms this is the one to use.Due to the very slow speed of even the very fast asymmetric systems compared to current symmetric systems it's pretty rare to need to encrypt something directly with an asymmetric system. Instead it's common to use a key exchange algorithm and then a symmetric cryptosystem to send the actual message. For example use EdDSA to prove identity, X25519 to exchange keys, and ChaCha20-Poly1305 for the actual encrypted messages.

Asymmetric Cryptography

Two of the best-known uses of public key cryptography are:

Public key encryption, in which a message is encrypted with a recipient's public key. The message cannot be decrypted by anyone who does not possess the matching private key, who is thus presumed to be the owner of that key and the person associated with the public key. This is used in an attempt to ensure confidentiality.

Digital signatures, in which a message is signed with the sender's private key and can be verified by anyone who has access to the sender's public key. This verification proves that the sender had access to the private key, and therefore is likely to be the person associated with the public key. This also ensures that the message has not been tampered with, as a signature is mathematically bound to the message it originally was made with, and verification will fail for practically any other message, no matter how similar to the original message.

Symmetric cryptography is often compared to lock and key as

key : lock :: secret key : encryped data

This secures data from others it also certifies that the data belongs to a person.

However, on a network protocol where nodes are sharing data between blockchain nodes, it is meaningless to use the cryptography since everyone is able to reproduce with the shared keys.

To overcome this, we apply asymmetric cryptography, which there is one key to only encrypt the data, and the other to decrypt only.

Signing key is called private key, and verifying key for decryption is called public key.

Eliptic Curve Digital Signature Algorithm

Eliptic Curve Digital Signature Algorithm(ECDSA) is one of asymmetric cryptography. ECDSA uses two systems to encrypt the data; eliptic curve and finite field(Galois field).

Eliptic curve arithmetic is one-way and multiplication can be applied with repeating addition only. This makes it hard to undo operations to find the original value, which is the private key.

Rust Keywords

as - perform primitive casting, disambiguate the specific trait containing an item, or rename items in use and extern crate statements
break - exit a loop immediately
const - define constant items or constant raw pointers
continue - continue to the next loop iteration
crate - link an external crate or a macro variable representing the crate in which the macro is defined
dyn - dynamic dispatch to a trait object
else - fallback for if and if let control flow constructs
enum - define an enumeration
extern - link an external crate, function, or variable
false - Boolean false literal
fn - define a function or the function pointer type
for - loop over items from an iterator, implement a trait, or specify a higher-ranked lifetime
if - branch based on the result of a conditional expression
impl - implement inherent or trait functionality
in - part of for loop syntax
let - bind a variable
loop - loop unconditionally
match - match a value to patterns
mod - define a module
move - make a closure take ownership of all its captures
mut - denote mutability in references, raw pointers, or pattern bindings
pub - denote public visibility in struct fields, impl blocks, or modules
ref - bind by reference
return - return from function
Self - a type alias for the type implementing a trait
self - method subject or current module
static - global variable or lifetime lasting the entire program execution
struct - define a structure
super - parent module of the current module
trait - define a trait
true - Boolean true literal
type - define a type alias or associated type
unsafe - denote unsafe code, functions, traits, or implementations
use - bring symbols into scope
where - denote clauses that constrain a type
while - loop conditionally based on the result of an expression

Setup

If the project cannot be compiled, update rust with rust version manager rustup

rustup update

Navigate to the directory of this project from the cloned repository on terminal and build the project

cd ./Topic1/01_simple_web_server/
cargo build

then run the project.

cargo run

afterwards, to run executable

 ./target/debug/rust_crypto

In this project, we have managed bits and bytes for you to easily generate private(secret)/public keys and sha256 hash from struct.

Usage

ecdsa

mod ecdsa;


let (sk, pk) = ecdsa::generate();
println!("secret_key: {}, public_key:{}", sk, pk);
/* prints secret_key: 3397b8b6faba3f83925dcffb51773a28f59530dd3cb6fccf6e3518094040ff70, public_key:022da9ebc229b9436ae89781e12b5787c5e26c3bf555e522b500443df637a9a873 */

let signature = sign_raw(&sk, txhash);
println!("{}", signature);
/* prints 304402207eaa99cac098aed4cfd7779aae6fd5e547cfaefda81383b83cc4b3a4b01defeb02201b7dc1f51093896301a674a70e0cd037567a65aa3a89066efaf1d64eea7e8d840000 */

transaction

let data = "Bob sends Alice to 5 eth";
let mut tx: Transaction = Transaction::new(&alice_pk, &bob_pk, 5, data);
/* returns Transaction { timestamp: 1549893371, to: "022337a6ba0c0229fb48469bd49745b200f4cdb35459e7033dbd846bee66ee87be", sender: "02a03b99517daf92dd3925eaf02cc5b6e9a90314a70baaa22e7e5383b1580df730", amount: 5, signature: "304402202f8046faf00d945a74c0f42e7e05c7a8360ff4681d57b524c5da79bc2d2058f80220456fe85f731fa07a17361963198c47f2dfd4ee5b6ea9d9932d8a6626ba53d4fe0000", data: "Bob sends Alice to 5 eth" } */


let txhash = tx.defunc_hash();
println!("{:?}", txhash);
/* prints 32 byte array [97, 47, 223, 9, 131, 127, 59, 167, 82, 210, 232, 206, 47, 113,230, 43, 242, 9, 8, 35, 210, 158, 74, 51, 112, 152, 225, 162, 70, 229, 186, 88] */

Topic 1-3: Putting it all together

In this topic, we will build a transaction authentication/authorization server with ECDSA and json-rpc 2.0. We already built interfaces from Topic 1-2 for you to avoid going through bits and bytes so don't worry.

API endpoints

The authentication server has only one endpoint which verifies transaction.

  • verify_transaction

verify_transaction

Returns whether transaction is valid or not with boolean value.

Parameters

timestamp: the time when the transaction was processed

to: recipient(in public key/ encoded address) of the asset

sender: sender of the asset and prover of the transaction

amount: amount of the asset to send

signature: signature generated from the sender's private(secret) key

data: message or reference for the transaction

Returns

bool - whether the transaction is valid(true) or not(false)

Example

// Request
curl -X POST \
  http://localhost:3031/ \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: 9e701109-5663-4b24-91d5-183d7a72019c' \
  -H 'cache-control: no-cache' \
  -d '{
	"jsonrpc": "2.0",
	"method": "verify_transaction",
	"params": {"timestamp": 1549893371, "to": "022337a6ba0c0229fb48469bd49745b200f4cdb35459e7033dbd846bee66ee87be", "sender": "02a03b99517daf92dd3925eaf02cc5b6e9a90314a70baaa22e7e5383b1580df730", "amount": 5, "signature": "304402202f8046faf00d945a74c0f42e7e05c7a8360ff4681d57b524c5da79bc2d2058f80220456fe85f731fa07a17361963198c47f2dfd4ee5b6ea9d9932d8a6626ba53d4fe0000", "data": "Bob sends Alice to 5 eth" },
	"id":1
}'

// Result
{
    "jsonrpc": "2.0",
    "result": "true",
    "id": 1
}

Client

A python client is located in the client folder.

To run the client, install request package from pip and locate to the client folder.

pip install request
cd ./client/

and run the python code.

python client.py

//should print "true"

Topic 2-1. What is WebAssembly(WASM)?

WebAssembly is a new assembly language close to metal which is shared all types of major browsers.

It started as an upgrade to javascript, which is the only programming language on the web browser to be compiled on native level. However, all programming languages now try to support it to be compiled in the assembly language so that they can be compiled to the web without using javascript.

Rust is one of them but has more advantages than other languages with its memory-safe compiler without garbage collection. Compiled wasm from Rust has less wasm code and memory-safe on development.

To witness the power of WebAssembly in rust, check out

https://github.com/rustwasm/awesome-rust-and-webassembly

How to use wasm in rust

In this topic, we will make node package with wasm.

  • Set nightly version as default
rustup default nightly
  • Start new rust project with Cargo new wasm-tutorial

  • Set Cargo.toml as below:

[package]
name = "wasm-tutorial"
version = "0.1.0"
authors = ["hskang9 <[email protected]>"]
edition = "2018"


[lib]
crate-type = ["cdylib"] // only static library is supported on wasm for now


[dependencies]
wasm-bindgen="0.2"  
   

Bind wasm code to javascript

Building Javascript wrapper interface

To enable the functions created from the rust on browser, we need to build a wrapper interface to be run on js file. You can think of this as importing javascript function to rust file.

extern create wasm_bindgen;
use wasm_bindgen::prelude::*;

// Wrapper interface
#[wasm_bindgen]
extern {
    fn alert(s: &str);
}

Producing Rust functions that Javascript can call

With wasm-bindgen, you can also export rust code with javascript functions.

#[wasm_bindgen]
pub fn hello_world(name: &str) {
    alert(&format!("Hello, {}!", name));
}

Building wasm into node package that can be published

Now javascript is a compiled language with the wasm. build the package by running this command.

wasm-pack build 

Then go to pkg folder and you can use npm commands for this.

cd pkg/

npm publish --access=public
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment