Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add functions in support of new ndaujs package for exchange integrators #3

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 198 additions & 2 deletions cmd/keyaddr/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ package main
// https://www.apache.org/licenses/LICENSE-2.0.txt
// - -- --- ---- -----


import (
"encoding/hex"
"fmt"
"math"
"regexp"
"syscall/js"

"github.com/ndau/ndaumath/pkg/address"
"github.com/ndau/ndaumath/pkg/keyaddr"
"github.com/ndau/ndaumath/pkg/signature"
)

// exit will quit the go program, causing the application to no longer respond to function calls.
Expand Down Expand Up @@ -72,6 +74,136 @@ func newKey(this js.Value, args []js.Value) interface{} {
return nil
}

// JS Usage: newEdKey(cb) --> no args
func newEdKey(this js.Value, args []js.Value) interface{} {
go func(args []js.Value) {
logDebug("newEdKey")

// clean args
callback, _, err := handleArgs(args, 0, "newEdKey")
if err != nil {
return
}

// do work
public, private, err := signature.Generate(signature.Ed25519, nil)
if err != nil {
jsLogReject(callback, "error creating new ed key: %s", err)
return
}

pubkeyText, err := public.MarshalText()
if err != nil {
jsLogReject(callback, "error marshalling new public ed key: %s", err)
return
}

privkeyText, err := private.MarshalText()
if err != nil {
jsLogReject(callback, "error marshalling new private ed key: %s", err)
return
}

// Make an map[string]interface{} so syscall will turn it into a js object.
obj := make(map[string]interface{})
obj["pubkey"] = string(pubkeyText)
obj["privkey"] = string(privkeyText)

// return result
callback.Invoke(nil, js.ValueOf(obj))
return
}(args)
return nil
}

// JS Usage: newEdKey(seed, cb)
func newEdKeyFromSeed(this js.Value, args []js.Value) interface{} {
go func(args []js.Value) {
logDebug("newEdKeyFromSeed")

// clean args
callback, remainder, err := handleArgs(args, 1, "newEdKeyFromSeed")
if err != nil {
return
}

seedString := remainder[0].String()
seed, err := hex.DecodeString(seedString)
if err != nil {
jsLogReject(callback, "error decoding data from hex: %s", err)
return
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check for correct seed length here? I don't think it's necessary, since a bad key length will just cause GenerateFromSeed to return an error.

// do work
public, private, err := signature.GenerateFromSeed(signature.Ed25519, seed)
if err != nil {
jsLogReject(callback, "error creating new ed key: %s", err)
return
}

pubkeyText, err := public.MarshalText()
if err != nil {
jsLogReject(callback, "error marshalling new public ed key: %s", err)
return
}

privkeyText, err := private.MarshalText()
if err != nil {
jsLogReject(callback, "error marshalling new private ed key: %s", err)
return
}

// Make an map[string]interface{} so syscall will turn it into a js object.
obj := make(map[string]interface{})
obj["pubkey"] = string(pubkeyText)
obj["privkey"] = string(privkeyText)

// return result
callback.Invoke(nil, js.ValueOf(obj))
return
}(args)
return nil
}

// JS Usage: addrFromPublicKey(pubKey, cb)
func addrFromPublicKey(this js.Value, args []js.Value) interface{} {
go func(args []js.Value) {
logDebug("addrFromPublicKey")

// clean args
callback, remainder, err := handleArgs(args, 1, "addrFromPublicKey")
if err != nil {
return
}

pubKeyString := remainder[0].String()

// do work
key, err := signature.ParseKey(pubKeyString)
if err != nil {
jsLogReject(callback, "error parsing public key: %s", err)
return
}

_, ok := key.(*signature.PublicKey)
if !ok {
jsLogReject(callback, "addresses can only be generated from public keys")
return
}

addr, err := address.Generate(address.KindExchange, key.KeyBytes())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is for general ndaujs usage we shouldn't hard-code this as an Exchange-type key.

if err != nil {
jsLogReject(callback, "error generating address from key: %s", err)
return
}

// return result
callback.Invoke(nil, addr.String())
return
}(args)
return nil
}

// JS Usage: wordsToBytes(language, words, cb)
// language defaults to en if not specified.
func wordsToBytes(this js.Value, args []js.Value) interface{} {
Expand Down Expand Up @@ -370,7 +502,71 @@ func sign(this js.Value, args []js.Value) interface{} {
msg := remainder[1].String()

// do work
sig, err := k.Sign(msg)
sig, err := k.SignSecP(msg)
if err != nil {
logError(fmt.Sprintf("error creating signature: key length: %s, msg: %s, err: %s", len(k.Key), msg, err.Error()))
jsLogReject(callback, "error creating signature: %s", err)
return
}

// return result
callback.Invoke(nil, sig.Signature)
return
}(args)
return nil
}

// JS Usage: signEdB64(privateKey, base64Message, cb)
func signEdB64(this js.Value, args []js.Value) interface{} {
js.Global().Get("console").Call("log", "sign starting")
go func(args []js.Value) {
logDebug("signEdB64")
// clean args
callback, remainder, err := handleArgs(args, 2, "signEdB64")
if err != nil {
return
}

k := keyaddr.Key{
Key: remainder[0].String(),
}

msg := remainder[1].String()

// do work
sig, err := k.SignEdB64(msg)
if err != nil {
logError(fmt.Sprintf("error creating signature: key length: %s, msg: %s, err: %s", len(k.Key), msg, err.Error()))
jsLogReject(callback, "error creating signature: %s", err)
return
}

// return result
callback.Invoke(nil, sig.Signature)
return
}(args)
return nil
}

// JS Usage: signEdText(privateKey, textMessage, cb)
func signEdText(this js.Value, args []js.Value) interface{} {
js.Global().Get("console").Call("log", "sign starting")
go func(args []js.Value) {
logDebug("signEdText")
// clean args
callback, remainder, err := handleArgs(args, 2, "signEdText")
if err != nil {
return
}

k := keyaddr.Key{
Key: remainder[0].String(),
}

msg := remainder[1].String()

// do work
sig, err := k.SignEdText(msg)
if err != nil {
logError(fmt.Sprintf("error creating signature: key length: %s, msg: %s, err: %s", len(k.Key), msg, err.Error()))
jsLogReject(callback, "error creating signature: %s", err)
Expand Down
34 changes: 18 additions & 16 deletions cmd/keyaddr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package main
// https://www.apache.org/licenses/LICENSE-2.0.txt
// - -- --- ---- -----


/*

Notes:
Expand All @@ -35,25 +34,28 @@ import (
var waitChannel chan struct{}

func main() {
js.Global().Get("console").Call("log", "WASM Keyaddr starting")

waitChannel = make(chan struct{})

// put go functions in a javascript object
obj := map[string]interface{}{
"newKey": js.FuncOf(newKey),
"wordsToBytes": js.FuncOf(wordsToBytes),
"deriveFrom": js.FuncOf(deriveFrom),
"ndauAddress": js.FuncOf(ndauAddress),
"toPublic": js.FuncOf(toPublic),
"child": js.FuncOf(child),
"sign": js.FuncOf(sign),
"hardenedChild": js.FuncOf(hardenedChild),
"wordsFromPrefix": js.FuncOf(wordsFromPrefix),
"isPrivate": js.FuncOf(isPrivate),
"wordsFromBytes": js.FuncOf(wordsFromBytes),
"fromString": js.FuncOf(fromString),
"exit": js.FuncOf(exit),
"newKey": js.FuncOf(newKey),
"wordsToBytes": js.FuncOf(wordsToBytes),
"deriveFrom": js.FuncOf(deriveFrom),
"ndauAddress": js.FuncOf(ndauAddress),
"toPublic": js.FuncOf(toPublic),
"child": js.FuncOf(child),
"sign": js.FuncOf(sign),
"signEdB64": js.FuncOf(signEdB64),
"signEdText": js.FuncOf(signEdText),
"hardenedChild": js.FuncOf(hardenedChild),
"wordsFromPrefix": js.FuncOf(wordsFromPrefix),
"isPrivate": js.FuncOf(isPrivate),
"wordsFromBytes": js.FuncOf(wordsFromBytes),
"fromString": js.FuncOf(fromString),
"newEdKey": js.FuncOf(newEdKey),
"newEdKeyFromSeed": js.FuncOf(newEdKeyFromSeed),
"addrFromPublicKey": js.FuncOf(addrFromPublicKey),
"exit": js.FuncOf(exit),
}

// Register all functions globally under KeyaddrNS. Either `window` in browsers, or
Expand Down
2 changes: 1 addition & 1 deletion cmd/keyaddr/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ describe('simple memory test', () => {
const key = await Keyaddr.newKey(bytes)
const oldLogLevel = global.KeyaddrLogLevel // save previous log level
global.KeyaddrLogLevel = global.KeyaddrLogLevelError // turn off excessive logs
for (let i = 1; i < 1000; i++) {
for (let i = 1; i < 500; i++) {
const newKey = await Keyaddr.deriveFrom(key, '/', `/44'/20036'/100/${i}`)
const addy = await Keyaddr.ndauAddress(newKey)
}
Expand Down
Loading