From 9e7e51b5b449164eb8b930e98a1fa61ae15c0ccc Mon Sep 17 00:00:00 2001 From: kdeme Date: Mon, 4 Nov 2019 16:34:02 +0100 Subject: [PATCH] Add private key parameter for nimbus_start() + additional checks --- wrappers/libnimbus.h | 10 +++-- wrappers/libnimbus.nim | 60 +++++++++++++++++++++++------ wrappers/wrapper_example.c | 2 +- wrappers/wrapper_example.go | 2 +- wrappers/wrapper_whisper_example.go | 14 ++++++- 5 files changed, 69 insertions(+), 19 deletions(-) diff --git a/wrappers/libnimbus.h b/wrappers/libnimbus.h index 804b439f4..5cb5f01f9 100644 --- a/wrappers/libnimbus.h +++ b/wrappers/libnimbus.h @@ -56,11 +56,13 @@ typedef void (*received_msg_handler)(received_message* msg, void* udata); */ void NimMain(); -/** Start Ethereum node with Whisper capability, optionally start discovery and - * connect to Status fleet. +/** Start Ethereum node with Whisper capability and connect to Status fleet. + * Optionally start discovery and listen for incoming connections. + * The minPow value is the minimum required PoW that this node will allow. + * When privkey is null, a new keypair will be generated. */ -void nimbus_start(uint16_t port, bool startListening, bool enableDiscovery, - double minPow); +bool nimbus_start(uint16_t port, bool startListening, bool enableDiscovery, + double minPow, uint8_t* privkey); /** Add peers to connect to - must be called after nimbus_start */ void nimbus_add_peer(const char* nodeId); diff --git a/wrappers/libnimbus.nim b/wrappers/libnimbus.nim index 4a28cf363..c1422d5e2 100644 --- a/wrappers/libnimbus.nim +++ b/wrappers/libnimbus.nim @@ -110,13 +110,22 @@ proc subscribeChannel( # notice "no luck parsing", message=getCurrentExceptionMsg() proc nimbus_start(port: uint16, startListening: bool, enableDiscovery: bool, - minPow: float64) - {.exportc.} = + minPow: float64, privateKey: ptr byte): bool {.exportc.} = let address = Address( udpPort: port.Port, tcpPort: port.Port, ip: parseIpAddress("0.0.0.0")) - let keys = newKeyPair() - node = newEthereumNode(keys, address, 1, nil, addAllCapabilities = false) + var keypair: KeyPair + if privateKey.isNil: + keypair = newKeyPair() + else: + try: + let privKey = initPrivateKey(makeOpenArray(privateKey, 32)) + keypair = KeyPair(seckey: privKey, pubkey: privKey.getPublicKey()) + except EthKeysException: + error "Passed an invalid privateKey" + return false + + node = newEthereumNode(keypair, address, 1, nil, addAllCapabilities = false) node.addCapability Whisper node.protocolState(Whisper).config.powRequirement = minPow @@ -139,6 +148,8 @@ proc nimbus_start(port: uint16, startListening: bool, enableDiscovery: bool, traceAsyncErrors node.peerPool.connectToNode(whisperNode) + result = true + proc nimbus_poll() {.exportc.} = poll() @@ -209,15 +220,23 @@ proc nimbus_new_keypair(): cstring {.exportc.} = result = generateRandomID() whisperKeys.asymKeys.add($result, newKeyPair()) -proc nimbus_add_keypair(key: ptr PrivateKey): +proc nimbus_add_keypair(privateKey: ptr byte): cstring {.exportc.} = ## It is important that the caller makes a copy of the returned cstring before ## doing any other API calls. This might not hold for all types of GC. - result = generateRandomID() + doAssert(not privateKey.isNil, "Passed a null pointer as privateKey") + var privKey: PrivateKey + try: + privKey = initPrivateKey(makeOpenArray(privateKey, 32)) + except EthKeysException: + error "Passed an invalid privateKey" + return "" + + result = generateRandomID() # Creating a KeyPair here does a copy of the key and so does the add - whisperKeys.asymKeys.add($result, KeyPair(seckey: key[], - pubkey: key[].getPublicKey())) + whisperKeys.asymKeys.add($result, KeyPair(seckey: privKey, + pubkey: privKey.getPublicKey())) proc nimbus_delete_keypair(id: cstring): bool {.exportc.} = var unneeded: KeyPair @@ -225,21 +244,26 @@ proc nimbus_delete_keypair(id: cstring): bool {.exportc.} = proc nimbus_get_private_key(id: cstring, privateKey: ptr PrivateKey): bool {.exportc.} = + doAssert(not privateKey.isNil, "Passed a null pointer as privateKey") + try: privateKey[] = whisperKeys.asymkeys[$id].seckey result = true except KeyError: + error "Private key not found" result = false # Symmetric Keys API -proc nimbus_add_symkey(key: ptr SymKey): cstring {.exportc.} = +proc nimbus_add_symkey(symKey: ptr SymKey): cstring {.exportc.} = ## It is important that the caller makes a copy of the returned cstring before ## doing any other API calls. This might not hold for all types of GC. + doAssert(not symKey.isNil, "Passed a null pointer as symKey") + result = generateRandomID().cstring # Copy of key happens at add - whisperKeys.symKeys.add($result, key[]) + whisperKeys.symKeys.add($result, symKey[]) proc nimbus_add_symkey_from_password(password: cstring): cstring {.exportc.} = @@ -260,6 +284,8 @@ proc nimbus_delete_symkey(id: cstring): bool {.exportc.} = proc nimbus_get_symkey(id: cstring, symKey: ptr SymKey): bool {.exportc.} = + doAssert(not symKey.isNil, "Passed a null pointer as symKey") + try: symKey[] = whisperKeys.symkeys[$id] result = true @@ -270,7 +296,7 @@ proc nimbus_get_symkey(id: cstring, symKey: ptr SymKey): proc nimbus_post(message: ptr CPostMessage): bool {.exportc.} = ## Encryption is mandatory. - ## A symmetric key or an asymmetric key can be provided. Both is not allowed. + ## A symmetric key or an asymmetric key must be provided. Both is not allowed. ## Providing a payload is mandatory, it cannot be nil, but can be of length 0. var sigPrivKey: Option[PrivateKey] @@ -323,6 +349,8 @@ proc nimbus_post(message: ptr CPostMessage): bool {.exportc.} = proc nimbus_subscribe_filter(options: ptr CFilterOptions, handler: proc (msg: ptr CReceivedMessage, udata: pointer) {.gcsafe, cdecl.}, udata: pointer = nil): cstring {.exportc.} = + ## Encryption is mandatory. + ## A symmetric key or an asymmetric key must be provided. Both is not allowed. ## In case of a passed handler, the received msg needs to be copied before the ## handler ends. var @@ -330,6 +358,14 @@ proc nimbus_subscribe_filter(options: ptr CFilterOptions, symKey: Option[SymKey] privateKey: Option[PrivateKey] + if not options.privateKeyID.isNil() and not options.symKeyID.isNil(): + warn "Both symmetric and asymmetric keys are provided, choose one." + return "" + + if options.privateKeyID.isNil() and options.symKeyID.isNil(): + warn "Both symmetric and asymmetric keys are nil, provide one." + return "" + if not options.source.isNil(): src = some(options.source[]) @@ -339,7 +375,7 @@ proc nimbus_subscribe_filter(options: ptr CFilterOptions, if not options.privateKeyID.isNil(): privateKey = some(whisperKeys.asymKeys[$options.privateKeyID].seckey) except KeyError: - return nil + return "" let filter = newFilter(src, privateKey, symKey, @[options.topic], options.minPow, options.allowP2P) diff --git a/wrappers/wrapper_example.c b/wrappers/wrapper_example.c index 98ae164c9..ac2b79b06 100644 --- a/wrappers/wrapper_example.c +++ b/wrappers/wrapper_example.c @@ -22,7 +22,7 @@ int main(int argc, char* argv[]) { time_t lastmsg; NimMain(); - nimbus_start(30303, false, false, 0.002); + nimbus_start(30303, true, false, 0.002, NULL); nimbus_join_public_chat(channel, print_msg); diff --git a/wrappers/wrapper_example.go b/wrappers/wrapper_example.go index 8d62b7bea..1c6d854e5 100644 --- a/wrappers/wrapper_example.go +++ b/wrappers/wrapper_example.go @@ -39,7 +39,7 @@ func receiveHandler(msg *C.received_message) { func Start() { C.NimMain() fmt.Println("[nim-status] Start Nimbus") - C.nimbus_start(30306, false, false, 0.002) + C.nimbus_start(30306, true, false, 0.002, nil) peer1 := "enode://2d3e27d7846564f9b964308038dfadd4076e4373ac938e020708ad8819fd4fd90e5eb8314140768f782db704cb313b60707b968f8b61108a6fecd705b041746d@192.168.0.33:30303" peer2 := "enode://4ea35352702027984a13274f241a56a47854a7fd4b3ba674a596cff917d3c825506431cf149f9f2312a293bb7c2b1cca55db742027090916d01529fe0729643b@206.189.243.178:443" diff --git a/wrappers/wrapper_whisper_example.go b/wrappers/wrapper_whisper_example.go index 0d4e3d120..da7d272ea 100644 --- a/wrappers/wrapper_whisper_example.go +++ b/wrappers/wrapper_whisper_example.go @@ -5,6 +5,7 @@ import ( "runtime" "time" "unsafe" + "encoding/hex" ) /* @@ -45,7 +46,18 @@ func receiveHandler(msg *C.received_message, udata unsafe.Pointer) { func Start() { C.NimMain() fmt.Println("[nim-status] Start Nimbus") - C.nimbus_start(30306, false, false, 0.002) + + privKeyHex := "a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617" + data, err := hex.DecodeString(privKeyHex) + if err != nil { + panic(err) + } + privKey := (*C.uint8_t)(C.CBytes(data)) + defer C.free(unsafe.Pointer(privKey)) + + if C.nimbus_start(30306, true, false, 0.002, privKey) == false { + panic("Can't start nimbus") + } } func StatusListenAndPost(channel string) {