Giter Site home page Giter Site logo

paritytech / schnorrkel-js Goto Github PK

View Code? Open in Web Editor NEW
16.0 7.0 12.0 196 KB

a Javascript wrapper for schnorrkel signatures on Ristretto using WebAssembly.

License: Apache License 2.0

Rust 60.06% HTML 5.90% JavaScript 32.35% Shell 1.69%
webassembly rust parity parity-substrate

schnorrkel-js's Introduction

Schnorrkel-js

Provides a Javascript wrapper for some of the high-level functionality provided by schnorrkel.

How to Use

Install

npm install @substrate/schnorrkel-js

API

The functions exposed via wasm are explained here(rust) or [here(js)]. You can clone the repo and run the following to see the details:

cargo docs --open 

Build

Current experimental setup is created using wasm-pack and webpack/node/npm. Make sure to have both of them, alongside the latest nightly version of Rust installed.

In the root of the project run:

wasm-pack build --target browser

A directory named pkg should be created. Then:

cd pkg
npm link 

This creates a local binding to npm, instructing it to use this folder whenever schnorrkel-js was imported as an npm module using require() or import.

Next, create head to the provided www folder (experimental test folder created via npm: npm init wasm-app www) and:

# Run just once
npm link schnorrkel-js
npm install
npm run start

The current index.js does absolutely nothing. It just binds the compiled wasm blob as a parsed object to the window object so that it can be easily tested in the console.

import * as schnorrkel from 'schnorrkel-js'

window.schnorrkel = schnorrkel

To make any further changes, given that the linking with npm link is correct, just re-compile with wasm-pack build and let the npm run start be running in a separate process. It should automatically reload.

The default webpage

Tests

Run the tests in Node.Js environment via

wasm-pack test --node 

or to run them directly in the browser:

add this line to the tests module in lib.rs

wasm_bindgen_test_configure!(run_in_browser);

Then

wasm-pack test --chrome  

schnorrkel-js's People

Contributors

amaury1093 avatar jacogr avatar kianenigma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

schnorrkel-js's Issues

Packaging, again...

... We cannot seem to win.

Works under Node, now breaks under Webpack.

Uncaught TypeError: TextDecoder is not a constructor
    at eval (schnorrkel_js.js?2cbf:179)
    at Object.../../node_modules/@parity/schnorrkel-js/schnorrkel_js.js (main.d8a8675f.js:351)

API change: Helper functions to combine/merge keys

Currently, one of the API functions returns a byte array which is the concatenation of the private and public key respectively.

pub fn keypair_from_seed(seed: &[u8]) -> [u8; KEYPAIR_LENGTH] { ... }

It is the user's duty to properly separate them as documented in the Rust code.

While there also exists another function which does almost the same but only returns the secret/private portion of the key.

pub fn secret_from_seed(seed: &[u8]) -> [u8; SECRET_KEY_LENGTH] { ... }

Consequently, the sign function is currently accepting the public and private key separately.

pub fn sign(public: &[u8], private: &[u8], message: &[u8]) -> [u8; SIGNATURE_LENGTH] { ... }

Based on the above, I see at least two improvements that could be made:

  • is the secret_from_seed even needed?
  • would a sign function that accepts the keypair instead be more handy?
  • a set of functions can be exposed to merge/separate keys to facilitate the progress. e.g. private_from_pair(keypair) etc.
    • Though, I believe adding them could be a downgrade of performance as they will 1) pass data back and forth between JS and wasm eventhough its a simple array slice. 2) slightly increase the size of the wasm blob.

Expose key derivation

Specifically derived_key_simple enabling us to do this logic from the JS side -

pub fn derive<Iter: Iterator<Item=DeriveJunction>>(&self, path: Iter) -> Option<Public> {
	let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?;
	for j in path {
		match j {
			DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0,
			DeriveJunction::Hard(_cc) => return None,
		}
	}
	Some(Self(acc.to_bytes()))
}

Build process

At least in the https://github.com/polkadot-js projects we need to support Browser/Node/React Native. wasm-pack is great, however the output options either creates something just for the browser or just for node.

Browser assumed webpack so does import * from 'schnorrkel_js_bg' - which is a WASM file, cannot be done on Node without webpack. The node output (--target nodejs) emits something where fs.readySync is used, once again, not quite usable in the Browser or RN.

Basically to get this working, I'm using the following scripts to support both environments.

build.sh -

#!/bin/sh

# install wasm-pack as required
if ! [ -x "$(command -v wasm-pack)" ]; then
  curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
fi

rm -rf ./pkg

rustup default nightly
wasm-pack build --target nodejs
rustup default stable

# make a backup of the original, use it, don't use it (useful for checking)
mv ./pkg/schnorrkel_js_bg.js ./pkg/schnorrkel_js_bg_node.js

./wasm2js.js

wasm2js.js -

#!/usr/bin/env node

const fs = require('fs');
const buffer = fs.readFileSync('./pkg/schnorrkel_js_bg.wasm');

fs.writeFileSync('./pkg/schnorrkel_js_bg.js', `const imports = {};\n
imports['./schnorrkel_js'] = require('./schnorrkel_js');\nconst bytes = Buffer.from('${buffer.toString('hex')}', 'hex');\nconst wasmModule = new WebAssembly.Module(bytes);\nconst wasmInstance = new WebAssembly.Instance(wasmModule, imports);\n\n
module.exports = wasmInstance.exports;`);

By far from the prettiest hack around, but it basically yields something that I can use as-is.

Circular dep in Wasm import

Basically webpack displays this -

    WARNING in /Users/jacogreeff/Projects/polkadot/apps/node_modules/@parity/schnorrkel-js/schnorrkel_js.js 232:25-39
    Critical dependency: the request of a dependency is an expression

Due to schnorrkel_js.js importing schnorrkel_js_bg.js and that requiring schnorrkel_js.js

Signing context may not be selected at runtime.

In an ideal world there would be sign and verify methods able to take a signing context from JS at runtime.

We've been scratching our heads over the current situation. The context is fixed to substrate, and the requirement seems to be that any signing context is defined at build time. Besides forking this repo and publishing a package with the signing contexts cennznet needs, are there any other methods that might work for us?

The underlying cause of the issue is a static lifetime requirement on the signing context that comes from the merlin crate, which is used by w3f's schnorrkel.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.