Merge pull request #41 from status-im/feat/nim-hashmessage

feat: introduce Nim impl of hashMessage in reorganized library
This commit is contained in:
Michael Bradley 2020-08-31 14:02:07 -05:00 committed by GitHub
commit 9fb5c560f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 738 additions and 469 deletions

8
.gitignore vendored
View File

@ -1,14 +1,16 @@
.idea
.vscode
bin/
/bottles/
build/
vendor/.nimble
tmp
nimcache
.DS_Store
TODO
nim_status
test/test
/nim_status
data/
keystore/
noBackup/
noBackup/
tests/c/build
tests/nim/build

115
Makefile
View File

@ -19,10 +19,19 @@ BUILD_SYSTEM_DIR := vendor/nimbus-build-system
bottles-dummy \
bottles-macos \
clean \
clean-build-dirs \
clean-data-dirs \
create-data-dirs \
deps \
nim_status \
update \
tests
status-go \
test \
test-shims-c \
test-login-c \
tests \
tests-c \
tests-nim \
update
ifeq ($(NIM_PARAMS),)
# "variables.mk" was not included, so we update the submodules.
@ -50,7 +59,7 @@ else
detected_OS := $(strip $(shell uname))
endif
ifeq ($(detected_OS), Darwin)
ifeq ($(detected_OS),Darwin)
BOTTLES_TARGET := bottles-macos
MACOSX_DEPLOYMENT_TARGET := 10.13
export MACOSX_DEPLOYMENT_TARGET
@ -89,8 +98,11 @@ $(BOTTLE_PCRE):
bottles-macos: | $(BOTTLE_OPENSSL) $(BOTTLE_PCRE)
rm -rf bottles/Downloads
deps: | deps-common bottles
ifeq ($(detected_OS), Darwin)
update: | update-common
ifeq ($(detected_OS),Darwin)
NIM_PARAMS := $(NIM_PARAMS) -L:"-framework Foundation -framework Security -framework IOKit -framework CoreServices"
endif
@ -98,55 +110,82 @@ endif
# We need `-d:debug` to get Nim's default stack traces.
NIM_PARAMS += -d:debug
deps: | deps-common
update: | update-common
STATUSGO := vendor/status-go/build/bin/libstatus.a
status-go: $(STATUSGO)
$(STATUSGO): | deps
echo -e $(BUILD_MSG) "status-go"
+ cd vendor/status-go && \
$(MAKE) statusgo-library $(HANDLE_OUTPUT)
clean: | clean-common clean-build-dir
rm -rf $(STATUSGO)
rm -rf keystore
rm -rf data
rm -rf noBackup
clean-build-dir:
rm -rf build/*
NIMSTATUS := build/nim_status.a
$(NIMSTATUS): | build deps
nim_status: | $(NIMSTATUS)
$(NIMSTATUS): | deps
echo -e $(BUILD_MSG) "$@" && \
$(ENV_SCRIPT) nim c $(NIM_PARAMS) --app:staticLib --header --noMain --nimcache:nimcache/nim_status -o:$@ src/nim_status.nim
cp nimcache/nim_status/nim_status.h build/.
mv nim_status.a build/.
$(ENV_SCRIPT) nim c $(NIM_PARAMS) --app:staticLib --header --noMain --nimcache:nimcache/nim_status -o:$@ src/nim_status/c/nim_status.nim
cp nimcache/nim_status/nim_status.h build/nim_status.h
mv nim_status.a build/
nim_status: | clean-build-dir $(NIMSTATUS)
SHIMS := tests/c/build/shims.a
tests: | $(NIMSTATUS) $(STATUSGO)
rm -Rf keystore
rm -Rf data
rm -Rf noBackup
mkdir -p data
mkdir -p noBackup
mkdir -p keystore
echo "Compiling 'test/test'"
ifeq ($(detected_OS), Darwin)
$(ENV_SCRIPT) $(CC) -I"$(CURDIR)/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" test/test.c $(NIMSTATUS) $(STATUSGO) -framework CoreFoundation -framework CoreServices -framework IOKit -framework Security -lm -pthread -o test/test
shims: | $(SHIMS)
$(SHIMS): | deps
echo -e $(BUILD_MSG) "$@" && \
$(ENV_SCRIPT) nim c $(NIM_PARAMS) --app:staticLib --header --noMain --nimcache:nimcache/nim_status -o:$@ tests/c/shims.nim
cp nimcache/nim_status/shims.h tests/c/build/shims.h
mv shims.a tests/c/build/
test-shims-c: | $(STATUSGO) clean-data-dirs create-data-dirs $(SHIMS)
mkdir -p tests/c/build
echo "Compiling 'tests/c/shims'"
ifeq ($(detected_OS),Darwin)
$(ENV_SCRIPT) $(CC) -I"$(CURDIR)/tests/c/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" tests/c/shims.c $(SHIMS) $(STATUSGO) -framework CoreFoundation -framework CoreServices -framework IOKit -framework Security -lm -pthread -o tests/c/build/shims
else
$(ENV_SCRIPT) $(CC) -I"$(CURDIR)/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" test/test.c $(NIMSTATUS) $(STATUSGO) -lm -pthread -o test/test
$(ENV_SCRIPT) $(CC) -I"$(CURDIR)/tests/c/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" tests/c/shims.c $(SHIMS) $(STATUSGO) -lm -pthread -o tests/c/build/shims
endif
echo "Executing 'test/test'"
$(ENV_SCRIPT) ./test/test
echo "Executing 'tests/c/build/shims'"
$(ENV_SCRIPT) ./tests/c/build/shims
test-login-c: | $(STATUSGO) clean-data-dirs create-data-dirs $(NIMSTATUS)
mkdir -p tests/c/build
echo "Compiling 'tests/c/login'"
ifeq ($(detected_OS),Darwin)
$(ENV_SCRIPT) $(CC) -I"$(CURDIR)/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" tests/c/login.c $(NIMSTATUS) $(STATUSGO) -framework CoreFoundation -framework CoreServices -framework IOKit -framework Security -lm -pthread -o tests/c/build/login
else
$(ENV_SCRIPT) $(CC) -I"$(CURDIR)/build" -I"$(CURDIR)/vendor/nimbus-build-system/vendor/Nim/lib" tests/c/login.c $(NIMSTATUS) $(STATUSGO) -lm -pthread -o tests/c/build/login
endif
echo "Executing 'tests/c/build/login'"
$(ENV_SCRIPT) ./tests/c/build/login
tests-c:
$(MAKE) test-shims-c
$(MAKE) test-login-c
tests-nim: | $(STATUSGO)
$(ENV_SCRIPT) nimble test
nim-tests: | $(NIMSTATUS) $(STATUSGO)
rm -Rf build/*
$(ENV_SCRIPT) nimble test
tests: tests-nim tests-c
test: tests
clean: | clean-common clean-build-dirs clean-data-dirs
rm -rf $(STATUSGO)
rm -rf bottles
clean-build-dirs:
rm -rf build/*
rm -rf tests/c/build/*
rm -rf tests/nim/build/*
clean-data-dirs:
rm -rf data
rm -rf keystore
rm -rf noBackup
create-data-dirs:
mkdir -p data
mkdir -p keystore
mkdir -p noBackup
endif # "variables.mk" was not included

View File

@ -1,6 +1,3 @@
when defined(macosx):
import algorithm, strutils
if defined(release):
switch("nimcache", "nimcache/release/$projectName")
else:
@ -9,10 +6,10 @@ else:
--threads:on
--opt:speed # -O3
--debugger:native # passes "-g" to the C compiler
--dynliboverrideall # don't use dlopen()
--define:ssl # needed by the stdlib to enable SSL procedures
if defined(macosx):
--dynliboverrideall # don't use dlopen()
--tlsEmulation:off
switch("passL", "-lstdc++")
# statically linke these libs
@ -23,7 +20,11 @@ if defined(macosx):
switch("passL", "-Wl,-no_compact_unwind")
# set the minimum supported macOS version to 10.13
switch("passC", "-mmacosx-version-min=10.13")
elif defined(windows):
--tlsEmulation:off
switch("passL", "-Wl,-as-needed")
else:
--dynliboverrideall # don't use dlopen()
# dynamically link these libs, since we're opting out of dlopen()
switch("passL", "-lcrypto")
switch("passL", "-lssl")

View File

@ -1,5 +1,4 @@
# Package
### Package
version = "0.1.0"
author = "Status Research & Development GmbH"
description = "Nim implementation of the Status protocol"
@ -8,21 +7,26 @@ srcDir = "src"
bin = @[""]
skipDirs = @["test"]
# Deps
### Deps
requires "nim >= 1.0.0"
### Helper functions
proc buildAndRunBinary(name: string, srcDir = "./", params = "", cmdParams = "", lang = "c") =
if not dirExists "build":
mkDir "build"
rmDir "data"
rmDir "keystore"
rmDir "noBackup"
mkDir "data"
mkDir "keystore"
mkDir "noBackup"
if not dirExists "tests/nim/build":
mkDir "tests/nim/build"
# allow something like "nim test --verbosity:0 --hints:off beacon_chain.nims"
var extra_params = params
for i in 2..<paramCount():
extra_params &= " " & paramStr(i)
exec "nim " & lang & " --out:./build/" & name & " -r " & extra_params & " " & srcDir & name & ".nim" & " " & cmdParams
exec "nim " & lang & " --out:./tests/nim/build/" & name & " -r " & extra_params & " " & srcDir & name & ".nim" & " " & cmdParams
### tasks
### Tasks
task test, "Run all tests":
buildAndRunBinary "test1", "tests/"
buildAndRunBinary "shims", "tests/nim/"
buildAndRunBinary "login", "tests/nim/"

View File

@ -1,268 +1,113 @@
import status_go
import types
from nim_status/types import
SignalCallback
# All procs start with lowercase because the compiler will also need to import status-go,
# and it will complain of duplication of function names
from nim_status/lib/shim as nim_shim import
hashMessage
export SignalCallback
export GoString
from nim_status/go/shim as go_shim import
initKeystore,
openAccounts,
multiAccountGenerateAndDeriveAddresses,
multiAccountStoreDerivedAccounts,
multiAccountImportMnemonic,
multiAccountImportPrivateKey,
multiAccountDeriveAddresses,
saveAccountAndLogin,
callRPC,
callPrivateRPC,
addPeer,
setSignalEventCallback,
sendTransaction,
generateAlias,
identicon,
login,
logout,
verifyAccountPassword,
validateMnemonic,
recoverAccount,
startOnboarding,
saveAccountAndLoginWithKeycard,
hashTransaction,
extractGroupMembershipSignatures,
connectionChange,
multiformatSerializePublicKey,
multiformatDeserializePublicKey,
validateNodeConfig,
loginWithKeycard,
recover,
writeHeapProfile,
importOnboardingAccount,
removeOnboarding,
hashTypedData,
resetChainData,
signMessage,
signTypedData,
stopCPUProfiling,
getNodesFromContract,
exportNodeLogs,
chaosModeUpdate,
signHash,
createAccount,
sendTransactionWithSignature,
startCPUProfile,
appStateChange,
signGroupMembership,
multiAccountStoreAccount,
multiAccountLoadAccount,
multiAccountGenerate,
multiAccountReset
proc hashMessage*(message: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.HashMessage(message)
tearDownForeignThreadGc()
proc initKeystore*(keydir: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.InitKeystore(keydir)
tearDownForeignThreadGc()
proc openAccounts*(datadir: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.OpenAccounts(datadir)
tearDownForeignThreadGc()
proc multiAccountGenerateAndDeriveAddresses*(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountGenerateAndDeriveAddresses(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountStoreDerivedAccounts*(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountStoreDerivedAccounts(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountImportMnemonic*(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountImportMnemonic(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountImportPrivateKey*(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountImportPrivateKey(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountDeriveAddresses*(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountDeriveAddresses(paramsJSON)
tearDownForeignThreadGc()
proc saveAccountAndLogin*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SaveAccountAndLogin(accountData, password, settingsJSON, configJSON, subaccountData)
tearDownForeignThreadGc()
proc callRPC*(inputJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.CallRPC(inputJSON)
tearDownForeignThreadGc()
proc callPrivateRPC*(inputJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.CallPrivateRPC(inputJSON)
tearDownForeignThreadGc()
proc addPeer*(peer: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.AddPeer(peer)
tearDownForeignThreadGc()
proc setSignalEventCallback*(callback: SignalCallback) {.exportc.} =
setupForeignThreadGc()
status_go.SetSignalEventCallback(callback)
tearDownForeignThreadGc()
proc sendTransaction*(jsonArgs: cstring, password: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SendTransaction(jsonArgs, password)
tearDownForeignThreadGc()
proc generateAlias*(pk: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.GenerateAlias(pk)
tearDownForeignThreadGc()
proc identicon*(pk: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.Identicon(pk)
tearDownForeignThreadGc()
proc login*(accountData: cstring, password: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.Login(accountData, password)
tearDownForeignThreadGc()
proc logout*(): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.Logout()
tearDownForeignThreadGc()
proc verifyAccountPassword*(keyStoreDir: cstring, address: cstring, password: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.VerifyAccountPassword(keyStoreDir, address, password)
tearDownForeignThreadGc()
proc validateMnemonic*(mnemonic: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ValidateMnemonic(mnemonic)
tearDownForeignThreadGc()
proc recoverAccount(password: cstring, mnemonic: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.RecoverAccount(password, mnemonic)
tearDownForeignThreadGc()
proc startOnboarding(n: cint, mnemonicPhraseLength: cint): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.StartOnboarding(n, mnemonicPhraseLength)
tearDownForeignThreadGc()
proc saveAccountAndLoginWithKeycard(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring, keyHex: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SaveAccountAndLoginWithKeycard(accountData, password, settingsJSON, configJSON, subaccountData, keyHex)
tearDownForeignThreadGc()
proc hashTransaction(txArgsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.HashTransaction(txArgsJSON)
tearDownForeignThreadGc()
proc extractGroupMembershipSignatures(signaturePairsStr: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ExtractGroupMembershipSignatures(signaturePairsStr)
tearDownForeignThreadGc()
proc connectionChange(typ: cstring, expensive: cstring) {.exportc.} =
setupForeignThreadGc()
status_go.ConnectionChange(typ, expensive)
tearDownForeignThreadGc()
proc multiformatSerializePublicKey(key: cstring, outBase: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiformatSerializePublicKey(key, outBase)
tearDownForeignThreadGc()
proc multiformatDeserializePublicKey(key: cstring, outBase: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiformatDeserializePublicKey(key, outBase)
tearDownForeignThreadGc()
proc validateNodeConfig(configJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ValidateNodeConfig(configJSON)
tearDownForeignThreadGc()
proc loginWithKeycard(accountData: cstring, password: cstring, keyHex: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.LoginWithKeycard(accountData, password, keyHex)
tearDownForeignThreadGc()
proc recover(rpcParams: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.Recover(rpcParams)
tearDownForeignThreadGc()
proc writeHeapProfile(dataDir: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.WriteHeapProfile(dataDir)
tearDownForeignThreadGc()
proc importOnboardingAccount(id: cstring, password: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ImportOnboardingAccount(id, password)
tearDownForeignThreadGc()
proc removeOnboarding() {.exportc.} =
setupForeignThreadGc()
status_go.RemoveOnboarding()
tearDownForeignThreadGc()
proc hashTypedData(data: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.HashTypedData(data)
tearDownForeignThreadGc()
proc resetChainData(): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ResetChainData()
tearDownForeignThreadGc()
proc signMessage(rpcParams: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SignMessage(rpcParams)
tearDownForeignThreadGc()
proc signTypedData(data: cstring, address: cstring, password: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SignTypedData(data, address, password)
tearDownForeignThreadGc()
proc stopCPUProfiling(): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.StopCPUProfiling()
tearDownForeignThreadGc()
proc getNodesFromContract(rpcEndpoint: cstring, contractAddress: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.GetNodesFromContract(rpcEndpoint, contractAddress)
tearDownForeignThreadGc()
proc exportNodeLogs(): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ExportNodeLogs()
tearDownForeignThreadGc()
proc chaosModeUpdate(on: cint): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.ChaosModeUpdate(on)
tearDownForeignThreadGc()
proc signHash(hexEncodedHash: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SignHash(hexEncodedHash)
tearDownForeignThreadGc()
proc createAccount(password: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.CreateAccount(password)
tearDownForeignThreadGc()
proc sendTransactionWithSignature(txtArgsJSON: cstring, sigString: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SendTransactionWithSignature(txtArgsJSON, sigString)
tearDownForeignThreadGc()
proc startCPUProfile(dataDir: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.StartCPUProfile(dataDir)
tearDownForeignThreadGc()
proc appStateChange(state: cstring) {.exportc.} =
setupForeignThreadGc()
status_go.AppStateChange(state)
tearDownForeignThreadGc()
proc signGroupMembership(content: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.SignGroupMembership(content)
tearDownForeignThreadGc()
proc multiAccountStoreAccount(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountStoreAccount(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountLoadAccount*(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountLoadAccount(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountGenerate(paramsJSON: cstring): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountGenerate(paramsJSON)
tearDownForeignThreadGc()
proc multiAccountReset(): cstring {.exportc.} =
setupForeignThreadGc()
result = status_go.MultiAccountReset()
tearDownForeignThreadGc()
export
SignalCallback,
hashMessage,
initKeystore,
openAccounts,
multiAccountGenerateAndDeriveAddresses,
multiAccountStoreDerivedAccounts,
multiAccountImportMnemonic,
multiAccountImportPrivateKey,
multiAccountDeriveAddresses,
saveAccountAndLogin,
callRPC,
callPrivateRPC,
addPeer,
setSignalEventCallback,
sendTransaction,
generateAlias,
identicon,
login,
logout,
verifyAccountPassword,
validateMnemonic,
recoverAccount,
startOnboarding,
saveAccountAndLoginWithKeycard,
hashTransaction,
extractGroupMembershipSignatures,
connectionChange,
multiformatSerializePublicKey,
multiformatDeserializePublicKey,
validateNodeConfig,
loginWithKeycard,
recover,
writeHeapProfile,
importOnboardingAccount,
removeOnboarding,
hashTypedData,
resetChainData,
signMessage,
signTypedData,
stopCPUProfiling,
getNodesFromContract,
exportNodeLogs,
chaosModeUpdate,
signHash,
createAccount,
sendTransactionWithSignature,
startCPUProfile,
appStateChange,
signGroupMembership,
multiAccountStoreAccount,
multiAccountLoadAccount,
multiAccountGenerate,
multiAccountReset

View File

@ -0,0 +1,108 @@
import ../../types
# All procs start with lowercase because the compiler will also need to import
# status-go, and it will complain of duplication of function names
proc hashMessage*(message: cstring): cstring {.importc: "HashMessage".}
proc initKeystore*(keydir: cstring): cstring {.importc: "InitKeystore".}
proc openAccounts*(datadir: cstring): cstring {.importc: "OpenAccounts".}
proc multiAccountGenerateAndDeriveAddresses*(paramsJSON: cstring): cstring {.importc: "MultiAccountGenerateAndDeriveAddresses".}
proc multiAccountStoreDerivedAccounts*(paramsJSON: cstring): cstring {.importc: "MultiAccountStoreDerivedAccounts".}
proc multiAccountImportMnemonic*(paramsJSON: cstring): cstring {.importc: "MultiAccountImportMnemonic".}
proc multiAccountImportPrivateKey*(paramsJSON: cstring): cstring {.importc: "MultiAccountImportPrivateKey".}
proc multiAccountDeriveAddresses*(paramsJSON: cstring): cstring {.importc: "MultiAccountDeriveAddresses".}
proc saveAccountAndLogin*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring): cstring {.importc: "SaveAccountAndLogin".}
proc callRPC*(inputJSON: cstring): cstring {.importc: "CallRPC".}
proc callPrivateRPC*(inputJSON: cstring): cstring {.importc: "CallPrivateRPC".}
proc addPeer*(peer: cstring): cstring {.importc: "AddPeer".}
proc setSignalEventCallback*(callback: SignalCallback) {.importc: "SetSignalEventCallback".}
proc sendTransaction*(jsonArgs: cstring, password: cstring): cstring {.importc: "SendTransaction".}
proc generateAlias*(pk: cstring): cstring {.importc: "GenerateAlias".}
proc identicon*(pk: cstring): cstring {.importc: "Identicon".}
proc login*(accountData: cstring, password: cstring): cstring {.importc: "Login".}
proc logout*(): cstring {.importc: "Logout".}
proc verifyAccountPassword*(keyStoreDir: cstring, address: cstring, password: cstring): cstring {.importc: "VerifyAccountPassword".}
proc validateMnemonic*(mnemonic: cstring): cstring {.importc: "ValidateMnemonic".}
proc recoverAccount*(password: cstring, mnemonic: cstring): cstring {.importc: "RecoverAccount".}
proc startOnboarding*(n: cint, mnemonicPhraseLength: cint): cstring {.importc: "StartOnboarding".}
proc saveAccountAndLoginWithKeycard*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring, keyHex: cstring): cstring {.importc: "SaveAccountAndLoginWithKeycard".}
proc hashTransaction*(txArgsJSON: cstring): cstring {.importc: "HashTransaction".}
proc extractGroupMembershipSignatures*(signaturePairsStr: cstring): cstring {.importc: "ExtractGroupMembershipSignatures".}
proc connectionChange*(typ: cstring, expensive: cstring) {.importc: "ConnectionChange".}
proc multiformatSerializePublicKey*(key: cstring, outBase: cstring): cstring {.importc: "MultiformatSerializePublicKey".}
proc multiformatDeserializePublicKey*(key: cstring, outBase: cstring): cstring {.importc: "MultiformatDeserializePublicKey".}
proc validateNodeConfig*(configJSON: cstring): cstring {.importc: "ValidateNodeConfig".}
proc loginWithKeycard*(accountData: cstring, password: cstring, keyHex: cstring): cstring {.importc: "LoginWithKeycard".}
proc recover*(rpcParams: cstring): cstring {.importc: "Recover".}
proc writeHeapProfile*(dataDir: cstring): cstring {.importc: "WriteHeapProfile".}
proc importOnboardingAccount*(id: cstring, password: cstring): cstring {.importc: "ImportOnboardingAccount".}
proc removeOnboarding*() {.importc: "RemoveOnboarding".}
proc hashTypedData*(data: cstring): cstring {.importc: "HashTypedData".}
proc resetChainData*(): cstring {.importc: "ResetChainData".}
proc signMessage*(rpcParams: cstring): cstring {.importc: "SignMessage".}
proc signTypedData*(data: cstring, address: cstring, password: cstring): cstring {.importc: "SignTypedData".}
proc stopCPUProfiling*(): cstring {.importc: "StopCPUProfiling".}
proc getNodesFromContract*(rpcEndpoint: cstring, contractAddress: cstring): cstring {.importc: "GetNodesFromContract".}
proc exportNodeLogs*(): cstring {.importc: "ExportNodeLogs".}
proc chaosModeUpdate*(on: cint): cstring {.importc: "ChaosModeUpdate".}
proc signHash*(hexEncodedHash: cstring): cstring {.importc: "SignHash".}
proc createAccount*(password: cstring): cstring {.importc: "CreateAccount".}
proc sendTransactionWithSignature*(txtArgsJSON: cstring, sigString: cstring): cstring {.importc: "SendTransactionWithSignature".}
proc startCPUProfile*(dataDir: cstring): cstring {.importc: "StartCPUProfile".}
proc appStateChange*(state: cstring) {.importc: "AppStateChange".}
proc signGroupMembership*(content: cstring): cstring {.importc: "SignGroupMembership".}
proc multiAccountStoreAccount*(paramsJSON: cstring): cstring {.importc: "MultiAccountStoreAccount".}
proc multiAccountLoadAccount*(paramsJSON: cstring): cstring {.importc: "MultiAccountLoadAccount".}
proc multiAccountGenerate*(paramsJSON: cstring): cstring {.importc: "MultiAccountGenerate".}
proc multiAccountReset*(): cstring {.importc: "MultiAccountReset".}

8
src/nim_status/c/lib.nim Normal file
View File

@ -0,0 +1,8 @@
import ../lib
import sys
proc hashMessage*(message: cstring): cstring =
let hash = lib.hashMessage($message)
result = cast[cstring](c_malloc(csize_t hash.len + 1))
copyMem(result, hash.cstring, hash.len)
result[hash.len] = '\0'

View File

@ -0,0 +1,8 @@
import ../../lib/shim as nim_shim
import ../sys
proc hashMessage*(message: cstring): cstring =
let hash = nim_shim.hashMessage($message)
result = cast[cstring](c_malloc(csize_t hash.len + 1))
copyMem(result, hash.cstring, hash.len)
result[hash.len] = '\0'

View File

@ -0,0 +1,61 @@
import lib/shim as nim_shim
let hashMessage {.exportc.} = nim_shim.hashMessage
import go/shim as go_shim
let initKeystore {.exportc.} = go_shim.initKeystore
let openAccounts {.exportc.} = go_shim.openAccounts
let multiAccountGenerateAndDeriveAddresses {.exportc.} = go_shim.multiAccountGenerateAndDeriveAddresses
let multiAccountStoreDerivedAccounts {.exportc.} = go_shim.multiAccountStoreDerivedAccounts
let multiAccountImportMnemonic {.exportc.} = go_shim.multiAccountImportMnemonic
let multiAccountImportPrivateKey {.exportc.} = go_shim.multiAccountImportPrivateKey
let multiAccountDeriveAddresses {.exportc.} = go_shim.multiAccountDeriveAddresses
let saveAccountAndLogin {.exportc.} = go_shim.saveAccountAndLogin
let callRPC {.exportc.} = go_shim.callRPC
let callPrivateRPC {.exportc.} = go_shim.callPrivateRPC
let addPeer {.exportc.} = go_shim.addPeer
let sendTransaction {.exportc.} = go_shim.sendTransaction
let generateAlias {.exportc.} = go_shim.generateAlias
let identicon {.exportc.} = go_shim.identicon
let login {.exportc.} = go_shim.login
let logout {.exportc.} = go_shim.logout
let verifyAccountPassword {.exportc.} = go_shim.verifyAccountPassword
let validateMnemonic {.exportc.} = go_shim.validateMnemonic
let recoverAccount {.exportc.} = go_shim.recoverAccount
let startOnboarding {.exportc.} = go_shim.startOnboarding
let saveAccountAndLoginWithKeycard {.exportc.} = go_shim.saveAccountAndLoginWithKeycard
let hashTransaction {.exportc.} = go_shim.hashTransaction
let extractGroupMembershipSignatures {.exportc.} = go_shim.extractGroupMembershipSignatures
let connectionChange {.exportc.} = go_shim.connectionChange
let multiformatSerializePublicKey {.exportc.} = go_shim.multiformatSerializePublicKey
let multiformatDeserializePublicKey {.exportc.} = go_shim.multiformatDeserializePublicKey
let validateNodeConfig {.exportc.} = go_shim.validateNodeConfig
let loginWithKeycard {.exportc.} = go_shim.loginWithKeycard
let recover {.exportc.} = go_shim.recover
let writeHeapProfile {.exportc.} = go_shim.writeHeapProfile
let importOnboardingAccount {.exportc.} = go_shim.importOnboardingAccount
let removeOnboarding {.exportc.} = go_shim.removeOnboarding
let hashTypedData {.exportc.} = go_shim.hashTypedData
let resetChainData {.exportc.} = go_shim.resetChainData
let signMessage {.exportc.} = go_shim.signMessage
let signTypedData {.exportc.} = go_shim.signTypedData
let stopCPUProfiling {.exportc.} = go_shim.stopCPUProfiling
let getNodesFromContract {.exportc.} = go_shim.getNodesFromContract
let exportNodeLogs {.exportc.} = go_shim.exportNodeLogs
let chaosModeUpdate {.exportc.} = go_shim.chaosModeUpdate
let signHash {.exportc.} = go_shim.signHash
let createAccount {.exportc.} = go_shim.createAccount
let sendTransactionWithSignature {.exportc.} = go_shim.sendTransactionWithSignature
let startCPUProfile {.exportc.} = go_shim.startCPUProfile
let appStateChange {.exportc.} = go_shim.appStateChange
let signGroupMembership {.exportc.} = go_shim.signGroupMembership
let multiAccountStoreAccount {.exportc.} = go_shim.multiAccountStoreAccount
let multiAccountLoadAccount {.exportc.} = go_shim.multiAccountLoadAccount
let multiAccountGenerate {.exportc.} = go_shim.multiAccountGenerate
let multiAccountReset {.exportc.} = go_shim.multiAccountReset
type SignalCallback {.exportc: "SignalCallback".} = proc(eventMessage: cstring): void {.cdecl.}
proc setSignalEventCallback(callback: SignalCallback) {.exportc.} =
go_shim.setSignalEventCallback(callback)

1
src/nim_status/c/sys.nim Normal file
View File

@ -0,0 +1 @@
proc c_malloc*(size: csize_t): pointer {.importc: "malloc", header: "<stdlib.h>".}

163
src/nim_status/go/shim.nim Normal file
View File

@ -0,0 +1,163 @@
import ../c/go/shim as go_shim
import ../types
export SignalCallback
# All procs start with lowercase because the compiler will also need to import
# status-go, and it will complain of duplication of function names
proc hashMessage*(message: string): string =
$go_shim.hashMessage(message.cstring)
proc initKeystore*(keydir: string): string =
$go_shim.initKeystore(keydir.cstring)
proc openAccounts*(datadir: string): string =
$go_shim.openAccounts(datadir.cstring)
proc multiAccountGenerateAndDeriveAddresses*(paramsJSON: string): string =
$go_shim.multiAccountGenerateAndDeriveAddresses(paramsJSON.cstring)
proc multiAccountStoreDerivedAccounts*(paramsJSON: string): string =
$go_shim.multiAccountStoreDerivedAccounts(paramsJSON.cstring)
proc multiAccountImportMnemonic*(paramsJSON: string): string =
$go_shim.multiAccountImportMnemonic(paramsJSON.cstring)
proc multiAccountImportPrivateKey*(paramsJSON: string): string =
$go_shim.multiAccountImportPrivateKey(paramsJSON.cstring)
proc multiAccountDeriveAddresses*(paramsJSON: string): string =
$go_shim.multiAccountDeriveAddresses(paramsJSON.cstring)
proc saveAccountAndLogin*(accountData: string, password: string, settingsJSON: string, configJSON: string, subaccountData: string): string =
$go_shim.saveAccountAndLogin(accountData.cstring, password.cstring, settingsJSON.cstring, configJSON.cstring, subaccountData.cstring)
proc callRPC*(inputJSON: string): string =
$go_shim.callRPC(inputJSON.cstring)
proc callPrivateRPC*(inputJSON: string): string =
$go_shim.callPrivateRPC(inputJSON.cstring)
proc addPeer*(peer: string): string =
$go_shim.addPeer(peer.cstring)
proc setSignalEventCallback*(callback: SignalCallback) =
go_shim.setSignalEventCallback(callback)
proc sendTransaction*(jsonArgs: string, password: string): string =
$go_shim.sendTransaction(jsonArgs.cstring, password.cstring)
proc generateAlias*(pk: string): string =
$go_shim.generateAlias(pk)
proc identicon*(pk: string): string =
$go_shim.identicon(pk)
proc login*(accountData: string, password: string): string =
$go_shim.login(accountData.cstring, password.cstring)
proc logout*(): string =
$go_shim.logout()
proc verifyAccountPassword*(keyStoreDir: string, address: string, password: string): string =
$go_shim.verifyAccountPassword(keyStoreDir.cstring, address.cstring, password.cstring)
proc validateMnemonic*(mnemonic: string): string =
$go_shim.validateMnemonic(mnemonic.cstring)
proc recoverAccount*(password: string, mnemonic: string): string =
$go_shim.recoverAccount(password.cstring, mnemonic.cstring)
proc startOnboarding*(n: int, mnemonicPhraseLength: int): string =
$go_shim.startOnboarding(n.cint, mnemonicPhraseLength.cint)
proc saveAccountAndLoginWithKeycard*(accountData: string, password: string, settingsJSON: string, configJSON: string, subaccountData: string, keyHex: string): string =
$go_shim.saveAccountAndLoginWithKeycard(accountData.cstring, password.cstring, settingsJSON.cstring, configJSON.cstring, subaccountData.cstring, keyHex.cstring)
proc hashTransaction*(txArgsJSON: string): string =
$go_shim.hashTransaction(txArgsJSON.cstring)
proc extractGroupMembershipSignatures*(signaturePairsStr: string): string =
$go_shim.extractGroupMembershipSignatures(signaturePairsStr.cstring)
proc connectionChange*(typ: string, expensive: string) =
go_shim.connectionChange(typ.cstring, expensive.cstring)
proc multiformatSerializePublicKey*(key: string, outBase: string): string =
$go_shim.multiformatSerializePublicKey(key.cstring, outBase.cstring)
proc multiformatDeserializePublicKey*(key: string, outBase: string): string =
$go_shim.multiformatDeserializePublicKey(key.cstring, outBase.cstring)
proc validateNodeConfig*(configJSON: string): string =
$go_shim.validateNodeConfig(configJSON.cstring)
proc loginWithKeycard*(accountData: string, password: string, keyHex: string): string =
$go_shim.loginWithKeycard(accountData.cstring, password.cstring, keyHex.cstring)
proc recover*(rpcParams: string): string =
$go_shim.recover(rpcParams.cstring)
proc writeHeapProfile*(dataDir: string): string =
$go_shim.writeHeapProfile(dataDir.cstring)
proc importOnboardingAccount*(id: string, password: string): string =
$go_shim.importOnboardingAccount(id.cstring, password.cstring)
proc removeOnboarding*() =
go_shim.removeOnboarding()
proc hashTypedData*(data: string): string =
$go_shim.hashTypedData(data.cstring)
proc resetChainData*(): string =
$go_shim.resetChainData()
proc signMessage*(rpcParams: string): string =
$go_shim.signMessage(rpcParams.cstring)
proc signTypedData*(data: string, address: string, password: string): string =
$go_shim.signTypedData(data.cstring, address.cstring, password.cstring)
proc stopCPUProfiling*(): string =
$go_shim.stopCPUProfiling()
proc getNodesFromContract*(rpcEndpoint: string, contractAddress: string): string =
$go_shim.getNodesFromContract(rpcEndpoint.cstring, contractAddress.cstring)
proc exportNodeLogs*(): string =
$go_shim.exportNodeLogs()
proc chaosModeUpdate*(on: int): string =
$go_shim.chaosModeUpdate(on.cint)
proc signHash*(hexEncodedHash: string): string =
$go_shim.signHash(hexEncodedHash.cstring)
proc createAccount*(password: string): string =
$go_shim.createAccount(password.cstring)
proc sendTransactionWithSignature*(txtArgsJSON: string, sigString: string): string =
$go_shim.sendTransactionWithSignature(txtArgsJSON.cstring, sigString.cstring)
proc startCPUProfile*(dataDir: string): string =
$go_shim.startCPUProfile(dataDir.cstring)
proc appStateChange*(state: string) =
go_shim.appStateChange(state.cstring)
proc signGroupMembership*(content: string): string =
$go_shim.signGroupMembership(content.cstring)
proc multiAccountStoreAccount*(paramsJSON: string): string =
$go_shim.multiAccountStoreAccount(paramsJSON.cstring)
proc multiAccountLoadAccount*(paramsJSON: string): string =
$go_shim.multiAccountLoadAccount(paramsJSON.cstring)
proc multiAccountGenerate*(paramsJSON: string): string =
$go_shim.multiAccountGenerate(paramsJSON.cstring)
proc multiAccountReset*(): string =
$go_shim.multiAccountReset()

20
src/nim_status/lib.nim Normal file
View File

@ -0,0 +1,20 @@
import lib/util
import nimcrypto
import strutils
import unicode
const END_OF_MEDIUM = Rune(0x19).toUTF8
const prefix = END_OF_MEDIUM & "Ethereum Signed Message:\n"
proc hashMessage*(message: string): string =
## hashMessage calculates the hash of a message to be safely signed by the keycard
## The hash is calulcated as
## keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
## This gives context to the signed message and prevents signing of transactions.
var msg = message
if isHexString(msg):
try:
msg = parseHexStr(msg[2..^1])
except:
discard
"0x" & toLower($keccak_256.digest(prefix & $(msg.len) & msg))

View File

@ -0,0 +1,6 @@
import strformat
import ../lib
proc hashMessage*(message: string): string =
let hash = lib.hashMessage(message)
fmt("{{\"result\":\"{hash}\"}}")

View File

@ -0,0 +1,2 @@
proc isHexString*(str: string): bool =
str.len > 2 and str[0..1] == "0x"

1
src/nim_status/types.nim Normal file
View File

@ -0,0 +1 @@
type SignalCallback* = proc(eventMessage: cstring): void {.cdecl.}

View File

@ -1,105 +0,0 @@
import types
proc HashMessage*(message: cstring): cstring {.importc: "HashMessage".}
proc InitKeystore*(keydir: cstring): cstring {.importc: "InitKeystore".}
proc OpenAccounts*(datadir: cstring): cstring {.importc: "OpenAccounts".}
proc MultiAccountGenerateAndDeriveAddresses*(paramsJSON: cstring): cstring {.importc: "MultiAccountGenerateAndDeriveAddresses".}
proc MultiAccountStoreDerivedAccounts*(paramsJSON: cstring): cstring {.importc: "MultiAccountStoreDerivedAccounts".}
proc MultiAccountImportMnemonic*(paramsJSON: cstring): cstring {.importc: "MultiAccountImportMnemonic".}
proc MultiAccountImportPrivateKey*(paramsJSON: cstring): cstring {.importc: "MultiAccountImportPrivateKey".}
proc MultiAccountDeriveAddresses*(paramsJSON: cstring): cstring {.importc: "MultiAccountDeriveAddresses".}
proc SaveAccountAndLogin*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring): cstring {.importc: "SaveAccountAndLogin".}
proc CallRPC*(inputJSON: cstring): cstring {.importc: "CallRPC".}
proc CallPrivateRPC*(inputJSON: cstring): cstring {.importc: "CallPrivateRPC".}
proc AddPeer*(peer: cstring): cstring {.importc: "AddPeer".}
proc SetSignalEventCallback*(callback: SignalCallback) {.importc: "SetSignalEventCallback".}
proc SendTransaction*(jsonArgs: cstring, password: cstring): cstring {.importc: "SendTransaction".}
proc GenerateAlias*(pk: cstring): cstring {.importc: "GenerateAlias".}
proc Identicon*(pk: cstring): cstring {.importc: "Identicon".}
proc Login*(accountData: cstring, password: cstring): cstring {.importc: "Login".}
proc Logout*(): cstring {.importc: "Logout".}
proc VerifyAccountPassword*(keyStoreDir: cstring, address: cstring, password: cstring): cstring {.importc: "VerifyAccountPassword".}
proc ValidateMnemonic*(mnemonic: cstring): cstring {.importc: "ValidateMnemonic".}
proc RecoverAccount*(password: cstring, mnemonic: cstring): cstring {.importc: "RecoverAccount".}
proc StartOnboarding*(n: cint, mnemonicPhraseLength: cint): cstring {.importc: "StartOnboarding".}
proc SaveAccountAndLoginWithKeycard*(accountData: cstring, password: cstring, settingsJSON: cstring, configJSON: cstring, subaccountData: cstring, keyHex: cstring): cstring {.importc: "SaveAccountAndLoginWithKeycard".}
proc HashTransaction*(txArgsJSON: cstring): cstring {.importc: "HashTransaction".}
proc ExtractGroupMembershipSignatures*(signaturePairsStr: cstring): cstring {.importc: "ExtractGroupMembershipSignatures".}
proc ConnectionChange*(typ: cstring, expensive: cstring) {.importc: "ConnectionChange".}
proc MultiformatSerializePublicKey*(key: cstring, outBase: cstring): cstring {.importc: "MultiformatSerializePublicKey".}
proc MultiformatDeserializePublicKey*(key: cstring, outBase: cstring): cstring {.importc: "MultiformatDeserializePublicKey".}
proc ValidateNodeConfig*(configJSON: cstring): cstring {.importc: "ValidateNodeConfig".}
proc LoginWithKeycard*(accountData: cstring, password: cstring, keyHex: cstring): cstring {.importc: "LoginWithKeycard".}
proc Recover*(rpcParams: cstring): cstring {.importc: "Recover".}
proc WriteHeapProfile*(dataDir: cstring): cstring {.importc: "WriteHeapProfile".}
proc ImportOnboardingAccount*(id: cstring, password: cstring): cstring {.importc: "ImportOnboardingAccount".}
proc RemoveOnboarding*() {.importc: "RemoveOnboarding".}
proc HashTypedData*(data: cstring): cstring {.importc: "HashTypedData".}
proc ResetChainData*(): cstring {.importc: "ResetChainData".}
proc SignMessage*(rpcParams: cstring): cstring {.importc: "SignMessage".}
proc SignTypedData*(data: cstring, address: cstring, password: cstring): cstring {.importc: "SignTypedData".}
proc StopCPUProfiling*(): cstring {.importc: "StopCPUProfiling".}
proc GetNodesFromContract*(rpcEndpoint: cstring, contractAddress: cstring): cstring {.importc: "GetNodesFromContract".}
proc ExportNodeLogs*(): cstring {.importc: "ExportNodeLogs".}
proc ChaosModeUpdate*(on: cint): cstring {.importc: "ChaosModeUpdate".}
proc SignHash*(hexEncodedHash: cstring): cstring {.importc: "SignHash".}
proc CreateAccount*(password: cstring): cstring {.importc: "CreateAccount".}
proc SendTransactionWithSignature*(txtArgsJSON: cstring, sigString: cstring): cstring {.importc: "SendTransactionWithSignature".}
proc StartCPUProfile*(dataDir: cstring): cstring {.importc: "StartCPUProfile".}
proc AppStateChange*(state: cstring) {.importc: "AppStateChange".}
proc SignGroupMembership*(content: cstring): cstring {.importc: "SignGroupMembership".}
proc MultiAccountStoreAccount*(paramsJSON: cstring): cstring {.importc: "MultiAccountStoreAccount".}
proc MultiAccountLoadAccount*(paramsJSON: cstring): cstring {.importc: "MultiAccountLoadAccount".}
proc MultiAccountGenerate*(paramsJSON: cstring): cstring {.importc: "MultiAccountGenerate".}
proc MultiAccountReset*(): cstring {.importc: "MultiAccountReset".}

View File

@ -1,6 +0,0 @@
type
GoString* {.exportc:"GoString".} = object
str*: cstring
length*: cint
type SignalCallback* {.exportc:"SignalCallback"} = proc(eventMessage: cstring): void {.cdecl.}

View File

@ -1,82 +1,98 @@
#include <stdio.h>
#include <string.h>
#include "nim_status.h"
#include "nxjson.c"
#include <unistd.h>
#include "nim_status.h"
#include "nxjson.c"
void eventCallback(const char *event) {
void eventCallback(char *event) {
printf("SIGNAL RECEIVED:\n%s\n", event);
}
int main(int argc, char* argv[]) {
// NimMain initializes Nim's garbage collector and runs top level statements
// in the compiled library
NimMain();
const char* theMessage = hashMessage("Hello World!");
printf("HashMessage: %s\n\n", theMessage);
char* pubKey = "0x0441ccda1563d69ac6b2e53718973c4e7280b4a5d8b3a09bb8bce9ebc5f082778243f1a04ec1f7995660482ca4b966ab0044566141ca48d7cdef8b7375cd5b7af5";
struct GoString p1 = {pubKey, strlen(pubKey)};
const char* theIdenticon = identicon(p1);
const char* theIdenticon = identicon(pubKey);
printf("Identicon: %s\n\n", theIdenticon);
printf("Creating an account, login and receive signals:\n");
printf("Create an account, login and receive signals:\n");
char* initKeystoreResult = initKeystore("./data");
printf("1. InitKeystore:\n%s\n\n", initKeystoreResult);
char* openAccountsResults = openAccounts("./noBackup");
printf("2. OpenAccounts:\n%s\n\n", openAccountsResults);
char* multiAccountGenerateAndDeriveAddressesResult = multiAccountGenerateAndDeriveAddresses("{\"n\":5,\"mnemonicPhraseLength\":12,\"bip39Passphrase\":\"\",\"paths\":[\"m/43'/60'/1581'/0'/0\",\"m/44'/60'/0'/0/0\"]}");
printf("3. MultiAccountGenerateAndDeriveAddresses:\n%s\n\n", multiAccountGenerateAndDeriveAddressesResult);
const nx_json* MultiAccountGenerateAndDeriveAddresses = nx_json_parse(multiAccountGenerateAndDeriveAddressesResult, 0);
char* accountID = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "id")->text_value;
char p2[300];
char* password = "0x2cd9bf92c5e20b1b410f5ace94d963a96e89156fbe65b70365e8596b37f1f165"; // qwerty
sprintf(p2, "{\"accountID\": \"%s\", \"paths\": [\"m/44'/60'/0'/0\", \"m/43'/60'/1581'\", \"m/43'/60'/1581'/0'/0\", \"m/44'/60'/0'/0/0\"], \"password\": \"%s\"}", accountID, password);
char* multiAccountStoreDerivedAccountsResult = multiAccountStoreDerivedAccounts(p2);
printf("4. MultiAccountStoreDerivedAccounts:\n%s\n\n", multiAccountStoreDerivedAccountsResult);
const nx_json* MultiAccountStoreDerivedAccounts = nx_json_parse(multiAccountStoreDerivedAccountsResult, 0);
char* m4460publicKey = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/44'/60'/0'/0/0"), "publicKey")->text_value;
char* m4460address = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/44'/60'/0'/0/0"), "address")->text_value;
char* m4360publicKey = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/43'/60'/1581'/0'/0"), "publicKey")->text_value;
char* m4360address = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/43'/60'/1581'/0'/0"), "address")->text_value;
char accountsData[2000];
sprintf(accountsData, "[{\"public-key\":\"%s\",\"address\":\"%s\",\"color\":\"#4360df\",\"wallet\":true,\"path\":\"m/44'/60'/0'/0/0\",\"name\":\"Status account\"},{\"public-key\":\"%s\",\"address\":\"%s\",\"name\":\"Delectable Overjoyed Nauplius\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"path\":\"m/43'/60'/1581'/0'/0\",\"chat\":true}]",
m4460publicKey, m4460address, m4360publicKey, m4360address);
char* finalConfig = "{\"BrowsersConfig\":{\"Enabled\":true},\"ClusterConfig\":{\"BootNodes\":[\"enode://23d0740b11919358625d79d4cac7d50a34d79e9c69e16831c5c70573757a1f5d7d884510bc595d7ee4da3c1508adf87bbc9e9260d804ef03f8c1e37f2fb2fc69@47.52.106.107:443\",\"enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@178.128.140.188:443\",\"enode://6e6554fb3034b211398fcd0f0082cbb6bd13619e1a7e76ba66e1809aaa0c5f1ac53c9ae79cf2fd4a7bacb10d12010899b370c75fed19b991d9c0cdd02891abad@47.75.99.169:443\",\"enode://5405c509df683c962e7c9470b251bb679dd6978f82d5b469f1f6c64d11d50fbd5dd9f7801c6ad51f3b20a5f6c7ffe248cc9ab223f8bcbaeaf14bb1c0ef295fd0@35.223.215.156:443\"],\"Enabled\":true,\"Fleet\":\"eth.prod\",\"RendezvousNodes\":[\"/ip4/34.70.75.208/tcp/30703/ethv4/16Uiu2HAm6ZsERLx2BwVD2UM9SVPnnMU6NBycG8XPtu8qKys5awsU\",\"/ip4/178.128.140.188/tcp/30703/ethv4/16Uiu2HAmLqTXuY4Sb6G28HNooaFUXUKzpzKXCcgyJxgaEE2i5vnf\",\"/ip4/47.52.106.107/tcp/30703/ethv4/16Uiu2HAmEHiptiDDd9gqNY8oQqo8hHUWMHJzfwt5aLRdD6W2zcXR\"],\"StaticNodes\":[\"enode://887cbd92d95afc2c5f1e227356314a53d3d18855880ac0509e0c0870362aee03939d4074e6ad31365915af41d34320b5094bfcc12a67c381788cd7298d06c875@178.128.141.0:443\",\"enode://fbeddac99d396b91d59f2c63a3cb5fc7e0f8a9f7ce6fe5f2eed5e787a0154161b7173a6a73124a4275ef338b8966dc70a611e9ae2192f0f2340395661fad81c0@34.67.230.193:443\"],\"TrustedMailServers\":[\"enode://2c8de3cbb27a3d30cbb5b3e003bc722b126f5aef82e2052aaef032ca94e0c7ad219e533ba88c70585ebd802de206693255335b100307645ab5170e88620d2a81@47.244.221.14:443\",\"enode://ee2b53b0ace9692167a410514bca3024695dbf0e1a68e1dff9716da620efb195f04a4b9e873fb9b74ac84de801106c465b8e2b6c4f0d93b8749d1578bfcaf03e@104.197.238.144:443\",\"enode://8a64b3c349a2e0ef4a32ea49609ed6eb3364be1110253c20adc17a3cebbc39a219e5d3e13b151c0eee5d8e0f9a8ba2cd026014e67b41a4ab7d1d5dd67ca27427@178.128.142.94:443\",\"enode://7aa648d6e855950b2e3d3bf220c496e0cae4adfddef3e1e6062e6b177aec93bc6cdcf1282cb40d1656932ebfdd565729da440368d7c4da7dbd4d004b1ac02bf8@178.128.142.26:443\",\"enode://c42f368a23fa98ee546fd247220759062323249ef657d26d357a777443aec04db1b29a3a22ef3e7c548e18493ddaf51a31b0aed6079bd6ebe5ae838fcfaf3a49@178.128.142.54:443\",\"enode://30211cbd81c25f07b03a0196d56e6ce4604bb13db773ff1c0ea2253547fafd6c06eae6ad3533e2ba39d59564cfbdbb5e2ce7c137a5ebb85e99dcfc7a75f99f55@23.236.58.92:443\"]},\"DataDir\":\"./data\",\"EnableNTPSync\":true,\"KeyStoreDir\":\"./keystore\",\"ListenAddr\":\":30304\",\"LogEnabled\":true,\"LogFile\":\"./geth.log\",\"LogLevel\":\"INFO\",\"MailserversConfig\":{\"Enabled\":true},\"Name\":\"StatusIM\",\"NetworkId\":1,\"NoDiscovery\":false,\"PermissionsConfig\":{\"Enabled\":true},\"Rendezvous\":true,\"RequireTopics\":{\"whisper\":{\"Max\":2,\"Min\":2}},\"ShhExtConfig\":{\"BackupDisabledDataDir\":\"./\",\"DataSyncEnabled\":true,\"InstallationID\":\"aef27732-8d86-5039-a32e-bdbe094d8791\",\"MailServerConfirmations\":true,\"MaxMessageDeliveryAttempts\":6,\"PFSEnabled\":true,\"VerifyENSContractAddress\":\"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e\",\"VerifyENSURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\",\"VerifyTransactionChainID\":1,\"VerifyTransactionURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"},\"ShhextConfig\":{\"BackupDisabledDataDir\":null,\"DataSyncEnabled\":true,\"InstallationID\":\"aef27732-8d86-5039-a32e-bdbe094d8791\",\"MailServerConfirmations\":true,\"MaxMessageDeliveryAttempts\":6,\"PFSEnabled\":true,\"VerifyENSContractAddress\":\"0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e\",\"VerifyENSURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\",\"VerifyTransactionChainID\":1,\"VerifyTransactionURL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"},\"StatusAccountsConfig\":{\"Enabled\":true},\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"},\"WakuConfig\":{\"BloomFilterMode\":null,\"Enabled\":true,\"LightClient\":true,\"MinimumPoW\":0.001},\"WalletConfig\":{\"Enabled\":true}}";
char* multiAccountGenerateAndDeriveAddresses0address = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "address")->text_value;
char* multiAccountGenerateAndDeriveAddresses0keyUid = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "keyUid")->text_value;
char multiAccountData[2000];
sprintf(multiAccountData, "{\"name\":\"Delectable Overjoyed Nauplius\",\"address\":\"%s\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"key-uid\":\"%s\",\"keycard-pairing\":null}", multiAccountGenerateAndDeriveAddresses0address, multiAccountGenerateAndDeriveAddresses0keyUid);
sprintf(multiAccountData, "{\"name\":\"Delectable Overjoyed Nauplius\",\"address\":\"%s\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"key-uid\":\"%s\",\"keycard-pairing\":null}", multiAccountGenerateAndDeriveAddresses0address, multiAccountGenerateAndDeriveAddresses0keyUid);
// multiAccountGenerateAndDeriveAddresses0keyUid
char* multiAccountGenerateAndDeriveAddresses0mnemonic = nx_json_get(nx_json_item(MultiAccountGenerateAndDeriveAddresses, 0), "mnemonic")->text_value;
// m4360publicKey
// multiAccountGenerateAndDeriveAddresses0address
// multiAccountGenerateAndDeriveAddresses0address
char* eip1581Address = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/43'/60'/1581'"), "address")->text_value;
// m4460address
char* walletRootAddress = nx_json_get(nx_json_get(MultiAccountStoreDerivedAccounts, "m/44'/60'/0'/0"), "address")->text_value;
char settings[5000];
sprintf(settings, "{\"key-uid\":\"%s\",\"mnemonic\":\"%s\",\"public-key\":\"%s\",\"name\":\"Delectable Overjoyed Nauplius\",\"address\":\"%s\",\"eip1581-address\":\"%s\",\"dapps-address\":\"%s\",\"wallet-root-address\":\"%s\",\"preview-privacy?\":true,\"signing-phrase\":\"dust gear boss\",\"log-level\":\"INFO\",\"latest-derived-path\":0,\"networks/networks\":[{\"id\":\"testnet_rpc\",\"etherscan-link\":\"https://ropsten.etherscan.io/address/\",\"name\":\"Ropsten with upstream RPC\",\"config\":{\"NetworkId\":3,\"DataDir\":\"/ethereum/testnet_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a\"}}},{\"id\":\"rinkeby_rpc\",\"etherscan-link\":\"https://rinkeby.etherscan.io/address/\",\"name\":\"Rinkeby with upstream RPC\",\"config\":{\"NetworkId\":4,\"DataDir\":\"/ethereum/rinkeby_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://rinkeby.infura.io/v3/f315575765b14720b32382a61a89341a\"}}},{\"id\":\"goerli_rpc\",\"etherscan-link\":\"https://goerli.etherscan.io/address/\",\"name\":\"Goerli with upstream RPC\",\"config\":{\"NetworkId\":5,\"DataDir\":\"/ethereum/goerli_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://goerli.blockscout.com/\"}}},{\"id\":\"mainnet_rpc\",\"etherscan-link\":\"https://etherscan.io/address/\",\"name\":\"Mainnet with upstream RPC\",\"config\":{\"NetworkId\":1,\"DataDir\":\"/ethereum/mainnet_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a\"}}},{\"id\":\"xdai_rpc\",\"name\":\"xDai Chain\",\"config\":{\"NetworkId\":100,\"DataDir\":\"/ethereum/xdai_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://dai.poa.network\"}}},{\"id\":\"poa_rpc\",\"name\":\"POA Network\",\"config\":{\"NetworkId\":99,\"DataDir\":\"/ethereum/poa_rpc\",\"UpstreamConfig\":{\"Enabled\":true,\"URL\":\"https://core.poa.network\"}}}],\"currency\":\"usd\",\"photo-path\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=\",\"waku-enabled\":true,\"wallet/visible-tokens\":{\"mainnet\":[\"SNT\"]},\"appearance\":0,\"networks/current-network\":\"mainnet_rpc\",\"installation-id\":\"5d6bc316-a97e-5b89-9541-ad01f8eb7397\"}",
multiAccountGenerateAndDeriveAddresses0keyUid, multiAccountGenerateAndDeriveAddresses0mnemonic, m4360publicKey, multiAccountGenerateAndDeriveAddresses0address,
eip1581Address, m4460address, walletRootAddress);
char* loginResult = saveAccountAndLogin(multiAccountData, password, settings, finalConfig, accountsData);
printf("5. saveAccountAndLogin:\n%s\n\n", loginResult);
printf("5. saveAccountAndLogin:\n%s\n\n", loginResult);
setSignalEventCallback(&eventCallback);
@ -86,4 +102,4 @@ int main(int argc, char* argv[]) {
}
return 0;
}
}

48
tests/c/shims.c Normal file
View File

@ -0,0 +1,48 @@
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "shims.h"
void hashCmp(char* str1, char* str2, bool testSame) {
if (testSame) {
assert(strcmp(nim_hashMessage(str1), go_hashMessage(str2)) == 0);
} else {
assert(strcmp(nim_hashMessage(str1), go_hashMessage(str2)) != 0);
}
}
int main(int argc, char* argv[]) {
// NimMain initializes Nim's garbage collector and runs top level statements
// in the compiled library
NimMain();
hashCmp("", "", true);
hashCmp("a", "a", true);
hashCmp("ab", "ab", true);
hashCmp("abc", "abc", true);
hashCmp("aBc", "aBc", true);
hashCmp("Abc", "abC", false);
hashCmp("0xffffff", "0xffffff", true);
hashCmp("0xFFFFFF", "0xffffff", true);
hashCmp("0xffffff", "0xFFFFFF", true);
hashCmp("0x616263", "abc", true);
hashCmp("abc", "0x616263", true);
hashCmp("0xabc", "0xabc", true);
hashCmp("0xaBc", "0xaBc", true);
hashCmp("0xAbc", "0xabC", false);
hashCmp("0xabcd", "0xabcd", true);
hashCmp("0xaBcd", "0xaBcd", true);
hashCmp("0xAbcd", "0xabcD", true);
hashCmp("0xverybadhex", "0xverybadhex", true);
hashCmp("0Xabcd", "0Xabcd", true);
hashCmp("0xabcd", "0Xabcd", false);
hashCmp("0Xabcd", "0xabcd", false);
assert(strcmp(nim_hashMessage("0Xabcd"), nim_hashMessage("0xabcd")) != 0);
assert(strcmp(go_hashMessage("0Xabcd"), go_hashMessage("0xabcd")) != 0);
return 0;
}

7
tests/c/shims.nim Normal file
View File

@ -0,0 +1,7 @@
import ../../src/nim_status/c/lib/shim as nim_shim
let nim_hashMessage {.exportc.} = nim_shim.hashMessage
import ../../src/nim_status/c/go/shim as go_shim
let go_hashMessage {.exportc.} = go_shim.hashMessage

View File

@ -1,19 +1,20 @@
{.passL:"vendor/status-go/build/bin/libstatus.a"}
when defined(macosx):
{.passl: "-framework Foundation".}
{.passl: "-framework Security".}
{.passl: "-framework IOKit".}
{.passl: "-framework CoreServices".}
{.passL: "-framework Foundation".}
{.passL: "-framework Security".}
{.passL: "-framework IOKit".}
{.passL: "-framework CoreServices".}
import ../src/nim_status
import ../../src/nim_status
import utils
import chronicles
import os
var onSignal: SignalCallback = proc(message: cstring) {.cdecl.} =
var onSignal: SignalCallback = proc(message: cstring) {.cdecl.} =
setupForeignThreadGC()
echo message
tearDownForeignThreadGc()
setSignalEventCallback(onSignal)
resetDirectories() # Recreates the data and nobackup dir
@ -35,6 +36,3 @@ while true:
echo "..."
sleep(1000)

42
tests/nim/shims.nim Normal file
View File

@ -0,0 +1,42 @@
{.passL:"vendor/status-go/build/bin/libstatus.a"}
when defined(macosx):
{.passL: "-framework Foundation".}
{.passL: "-framework Security".}
{.passL: "-framework IOKit".}
{.passL: "-framework CoreServices".}
import ../../src/nim_status/lib/shim as nim_shim
import ../../src/nim_status/go/shim as go_shim
import strutils
proc hashCmp(str1: string, str2: string, testSame: bool): void =
if testSame:
assert nim_shim.hashMessage(str1) == go_shim.hashMessage(str2)
else:
assert nim_shim.hashMessage(str1) != go_shim.hashMessage(str2)
hashCmp("", "", true)
hashCmp("a", "a", true)
hashCmp("ab", "ab", true)
hashCmp("abc", "abc", true)
hashCmp("aBc", "aBc", true)
hashCmp("Abc", "abC", false)
hashCmp("0xffffff", "0xffffff", true)
hashCmp("0xFFFFFF", "0xffffff", true)
hashCmp("0xffffff", "0xFFFFFF", true)
hashCmp("0x" & "abc".toHex, "abc", true)
hashCmp("0x616263", "abc", true)
hashCmp("abc", "0x" & "abc".toHex, true)
hashCmp("abc", "0x616263", true)
hashCmp("0xabc", "0xabc", true)
hashCmp("0xaBc", "0xaBc", true)
hashCmp("0xAbc", "0xabC", false)
hashCmp("0xabcd", "0xabcd", true)
hashCmp("0xaBcd", "0xaBcd", true)
hashCmp("0xAbcd", "0xabcD", true)
hashCmp("0xverybadhex", "0xverybadhex", true)
hashCmp("0Xabcd", "0Xabcd", true)
hashCmp("0xabcd", "0Xabcd", false)
hashCmp("0Xabcd", "0xabcd", false)
assert nim_shim.hashMessage("0Xabcd") != nim_shim.hashMessage("0xabcd")
assert go_shim.hashMessage("0Xabcd") != go_shim.hashMessage("0xabcd")

View File

@ -1,5 +1,5 @@
import json
import ../src/nim_status
import ../../src/nim_status
import nimcrypto
import chronicles
import os
@ -21,7 +21,7 @@ proc init*() =
proc AndLogin(account0: JsonNode, pwd: string) =
let password = hashPassword(pwd)
let multiAccounts = parseJson($multiAccountStoreDerivedAccounts($ %* {
"accountID": account0["id"].getStr,
"paths": ["m/44'/60'/0'/0", "m/43'/60'/1581'", "m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"],
@ -137,9 +137,9 @@ proc AndLogin(account0: JsonNode, pwd: string) =
"networks/current-network": "mainnet_rpc",
"installation-id": "5d6bc316-a97e-5b89-9541-ad01f8eb7397",
}
let configJSON = %* {
"BrowsersConfig": {
"BrowsersConfig": {
"Enabled": true
},
"ClusterConfig": {
@ -221,7 +221,7 @@ proc AndLogin(account0: JsonNode, pwd: string) =
"Enabled": true
}
}
let subaccountData = %* [
{
"public-key": multiAccounts["m/44'/60'/0'/0/0"]["publicKey"],
@ -240,29 +240,29 @@ proc AndLogin(account0: JsonNode, pwd: string) =
"chat":true
}
]
let saveResult = parseJson($saveAccountAndLogin($accountData, password, $settingsJSON, $configJSON, $subaccountData))
assert saveResult["error"].getStr == ""
debug "Login successful"
proc createAccountAndLogin*(password: string = "qwerty"):string =
proc createAccountAndLogin*(password: string = "qwerty"):string =
debug "Creating an account"
let generatedAddresses = parseJson($multiAccountGenerateAndDeriveAddresses($ %* {
"n": 5,
"mnemonicPhraseLength": 12,
"bip39Passphrase": "",
"bip39Passphrase": "",
"paths": ["m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"]
}))
result = generatedAddresses[0]["publicKey"].getStr
debug "Account created", result
AndLogin(generatedAddresses[0], password)
proc restoreAccountAndLogin*(mnemonic: string, password: string = "qwerty"):string =
let importedAddress = parseJson($ multiAccountImportMnemonic($ %* {
"mnemonicPhrase": mnemonic,