Merge branch 'master' into nim-1.2

This commit is contained in:
Ștefan Talpalaru 2020-04-08 20:16:37 +02:00
commit af89b51503
No known key found for this signature in database
GPG Key ID: CBF7934204F1B6F9
17 changed files with 118 additions and 101 deletions

View File

@ -429,8 +429,9 @@ proc processProtocolList(v: string, flags: var set[ProtocolFlags]): ConfigStatus
proc processENode(v: string, o: var ENode): ConfigStatus = proc processENode(v: string, o: var ENode): ConfigStatus =
## Convert string to ENode. ## Convert string to ENode.
let res = initENode(v, o) let res = ENode.fromString(v)
if res == ENodeStatus.Success: if res.isOk:
o = res[]
result = Success result = Success
else: else:
result = ErrorParseOption result = ErrorParseOption
@ -450,11 +451,12 @@ proc processENodesList(v: string, o: var seq[ENode]): ConfigStatus =
proc processPrivateKey(v: string, o: var PrivateKey): ConfigStatus = proc processPrivateKey(v: string, o: var PrivateKey): ConfigStatus =
## Convert hexadecimal string to private key object. ## Convert hexadecimal string to private key object.
try: let seckey = PrivateKey.fromHex(v)
o = initPrivateKey(v) if seckey.isOk():
result = Success o = seckey[]
except CatchableError: return Success
result = ErrorParseOption
result = ErrorParseOption
# proc processHexBytes(v: string, o: var seq[byte]): ConfigStatus = # proc processHexBytes(v: string, o: var seq[byte]): ConfigStatus =
# ## Convert hexadecimal string to seq[byte]. # ## Convert hexadecimal string to seq[byte].

View File

@ -62,12 +62,10 @@ proc start(nimbus: NimbusNode) =
setupCommonRpc(nimbus.rpcServer) setupCommonRpc(nimbus.rpcServer)
## Creating P2P Server ## Creating P2P Server
if conf.net.nodekey.isZeroKey(): if not conf.net.nodekey.verify():
conf.net.nodekey = newPrivateKey() conf.net.nodekey = PrivateKey.random().tryGet()
var keypair: KeyPair let keypair = conf.net.nodekey.toKeyPair().tryGet()
keypair.seckey = conf.net.nodekey
keypair.pubkey = conf.net.nodekey.getPublicKey()
var address: Address var address: Address
address.ip = parseIpAddress("0.0.0.0") address.ip = parseIpAddress("0.0.0.0")

View File

@ -211,10 +211,10 @@ proc `%`*(value: Bytes): JsonNode =
# Helpers for the fromJson procs # Helpers for the fromJson procs
proc toPublicKey*(key: string): PublicKey {.inline.} = proc toPublicKey*(key: string): PublicKey {.inline.} =
result = initPublicKey(key[4 .. ^1]) result = PublicKey.fromHex(key[4 .. ^1]).tryGet()
proc toPrivateKey*(key: string): PrivateKey {.inline.} = proc toPrivateKey*(key: string): PrivateKey {.inline.} =
result = initPrivateKey(key[2 .. ^1]) result = PrivateKey.fromHex(key[2 .. ^1]).tryGet()
proc toSymKey*(key: string): SymKey {.inline.} = proc toSymKey*(key: string): SymKey {.inline.} =
hexToByteArray(key[2 .. ^1], result) hexToByteArray(key[2 .. ^1], result)

View File

@ -226,7 +226,7 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) =
template sign(privateKey: PrivateKey, message: string): string = template sign(privateKey: PrivateKey, message: string): string =
# TODO: Is message length encoded as bytes or characters? # TODO: Is message length encoded as bytes or characters?
let msgData = "\x19Ethereum Signed Message:\n" & $message.len & message let msgData = "\x19Ethereum Signed Message:\n" & $message.len & message
$signMessage(privateKey, msgData) $sign(privateKey, msgData.toBytes()).tryGet()
rpcsrv.rpc("eth_sign") do(data: EthAddressStr, message: HexDataStr) -> HexDataStr: rpcsrv.rpc("eth_sign") do(data: EthAddressStr, message: HexDataStr) -> HexDataStr:
## The sign method calculates an Ethereum specific signature with: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))). ## The sign method calculates an Ethereum specific signature with: sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message))).

View File

@ -1,5 +1,5 @@
import import
json_rpc/rpcserver, tables, options, sequtils, json_rpc/rpcserver, tables, options,
eth/[common, rlp, keys, p2p], eth/p2p/rlpx_protocols/waku_protocol, eth/[common, rlp, keys, p2p], eth/p2p/rlpx_protocols/waku_protocol,
nimcrypto/[sysrand, hmac, sha2, pbkdf2], nimcrypto/[sysrand, hmac, sha2, pbkdf2],
rpc_types, hexstrings, key_storage rpc_types, hexstrings, key_storage
@ -70,7 +70,7 @@ proc setupWakuRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer) =
## ##
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().Identifier result = generateRandomID().Identifier
keys.asymKeys.add(result.string, newKeyPair()) keys.asymKeys.add(result.string, KeyPair.random().tryGet())
rpcsrv.rpc("waku_addPrivateKey") do(key: PrivateKey) -> Identifier: rpcsrv.rpc("waku_addPrivateKey") do(key: PrivateKey) -> Identifier:
## Stores the key pair, and returns its ID. ## Stores the key pair, and returns its ID.
@ -80,7 +80,7 @@ proc setupWakuRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer) =
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().Identifier result = generateRandomID().Identifier
keys.asymKeys.add(result.string, key.toKeyPair()) keys.asymKeys.add(result.string, key.toKeyPair().tryGet())
rpcsrv.rpc("waku_deleteKeyPair") do(id: Identifier) -> bool: rpcsrv.rpc("waku_deleteKeyPair") do(id: Identifier) -> bool:
## Deletes the specifies key if it exists. ## Deletes the specifies key if it exists.

View File

@ -71,7 +71,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer) =
## ##
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().Identifier result = generateRandomID().Identifier
keys.asymKeys.add(result.string, newKeyPair()) keys.asymKeys.add(result.string, KeyPair.random().tryGet())
rpcsrv.rpc("shh_addPrivateKey") do(key: PrivateKey) -> Identifier: rpcsrv.rpc("shh_addPrivateKey") do(key: PrivateKey) -> Identifier:
## Stores the key pair, and returns its ID. ## Stores the key pair, and returns its ID.
@ -81,7 +81,7 @@ proc setupWhisperRPC*(node: EthereumNode, keys: KeyStorage, rpcsrv: RpcServer) =
## Returns key identifier on success and an error on failure. ## Returns key identifier on success and an error on failure.
result = generateRandomID().Identifier result = generateRandomID().Identifier
keys.asymKeys.add(result.string, key.toKeyPair()) keys.asymKeys.add(result.string, key.toKeyPair().tryGet())
rpcsrv.rpc("shh_deleteKeyPair") do(id: Identifier) -> bool: rpcsrv.rpc("shh_deleteKeyPair") do(id: Identifier) -> bool:
## Deletes the specifies key if it exists. ## Deletes the specifies key if it exists.

View File

@ -44,7 +44,11 @@ proc getSignature*(transaction: Transaction, output: var Signature): bool =
return false return false
bytes[64] = byte(v - 27) bytes[64] = byte(v - 27)
result = recoverSignature(bytes, output) == EthKeysStatus.Success let sig = Signature.fromRaw(bytes)
if sig.isOk:
output = sig[]
return true
return false
proc toSignature*(transaction: Transaction): Signature = proc toSignature*(transaction: Transaction): Signature =
if not getSignature(transaction, result): if not getSignature(transaction, result):
@ -54,10 +58,10 @@ proc getSender*(transaction: Transaction, output: var EthAddress): bool =
## Find the address the transaction was sent from. ## Find the address the transaction was sent from.
var sig: Signature var sig: Signature
if transaction.getSignature(sig): if transaction.getSignature(sig):
var pubKey: PublicKey
var txHash = transaction.txHashNoSignature var txHash = transaction.txHashNoSignature
if recoverSignatureKey(sig, txHash.data, pubKey) == EthKeysStatus.Success: let pubkey = recover(sig, txHash)
output = pubKey.toCanonicalAddress() if pubkey.isOk:
output = pubkey[].toCanonicalAddress()
result = true result = true
proc getSender*(transaction: Transaction): EthAddress = proc getSender*(transaction: Transaction): EthAddress =

View File

@ -42,8 +42,10 @@ proc getSignature(computation: Computation): (array[32, byte], Signature) =
# Copy message data to buffer # Copy message data to buffer
bytes[0..(maxPos-64)] = data[64..maxPos] bytes[0..(maxPos-64)] = data[64..maxPos]
if recoverSignature(bytes, result[1]) != EthKeysStatus.Success: let sig = Signature.fromRaw(bytes)
if sig.isErr:
raise newException(ValidationError, "Could not recover signature computation") raise newException(ValidationError, "Could not recover signature computation")
result[1] = sig[]
# extract message hash, only need to copy when there is a valid signature # extract message hash, only need to copy when there is a valid signature
result[0][0..31] = data[0..31] result[0][0..31] = data[0..31]
@ -98,14 +100,14 @@ proc ecRecover*(computation: Computation) =
var var
(msgHash, sig) = computation.getSignature() (msgHash, sig) = computation.getSignature()
pubKey: PublicKey
if sig.recoverSignatureKey(msgHash, pubKey) != EthKeysStatus.Success: var pubkey = recover(sig, SkMessage(data: msgHash))
if pubkey.isErr:
raise newException(ValidationError, "Could not derive public key from computation") raise newException(ValidationError, "Could not derive public key from computation")
computation.output.setLen(32) computation.output.setLen(32)
computation.output[12..31] = pubKey.toCanonicalAddress() computation.output[12..31] = pubkey[].toCanonicalAddress()
trace "ECRecover precompile", derivedKey = pubKey.toCanonicalAddress() trace "ECRecover precompile", derivedKey = pubkey[].toCanonicalAddress()
proc sha256*(computation: Computation) = proc sha256*(computation: Computation) =
let let

View File

@ -192,9 +192,9 @@ proc getFixtureTransaction*(j: JsonNode, dataIndex, gasIndex, valueIndex: int):
var secretKey = j["secretKey"].getStr var secretKey = j["secretKey"].getStr
removePrefix(secretKey, "0x") removePrefix(secretKey, "0x")
let privateKey = initPrivateKey(secretKey) let privateKey = PrivateKey.fromHex(secretKey).tryGet()
let sig = signMessage(privateKey, result.rlpEncode) let sig = sign(privateKey, result.rlpEncode).tryGet()
let raw = sig.getRaw() let raw = sig.toRaw()
result.R = fromBytesBE(Uint256, raw[0..31]) result.R = fromBytesBE(Uint256, raw[0..31])
result.S = fromBytesBE(Uint256, raw[32..63]) result.S = fromBytesBE(Uint256, raw[32..63])
@ -206,15 +206,16 @@ proc hashLogEntries*(logs: seq[Log]): string =
proc setupEthNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode = proc setupEthNode*(capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode =
var var
conf = getConfiguration() conf = getConfiguration()
keypair: KeyPair if not conf.net.nodekey.verify():
keypair.seckey = conf.net.nodekey conf.net.nodekey = PrivateKey.random().tryGet()
keypair.pubkey = conf.net.nodekey.getPublicKey() let keypair = conf.net.nodekey.toKeyPair().tryGet()
var srvAddress: Address var srvAddress: Address
srvAddress.ip = parseIpAddress("0.0.0.0") srvAddress.ip = parseIpAddress("0.0.0.0")
srvAddress.tcpPort = Port(conf.net.bindPort) srvAddress.tcpPort = Port(conf.net.bindPort)
srvAddress.udpPort = Port(conf.net.discPort) srvAddress.udpPort = Port(conf.net.discPort)
result = newEthereumNode(keypair, srvAddress, conf.net.networkId, result = newEthereumNode(
nil, "nimbus 0.1.0", addAllCapabilities = false) keypair, srvAddress, conf.net.networkId, nil, "nimbus 0.1.0",
addAllCapabilities = false)
for capability in capabilities: for capability in capabilities:
result.addCapability capability result.addCapability capability

View File

@ -65,7 +65,7 @@ proc doTests {.async.} =
let keyID2 = await client.shh_addPrivateKey(privkey) let keyID2 = await client.shh_addPrivateKey(privkey)
check: check:
await(client.shh_getPublicKey(keyID2)) == pubkey.toPublicKey await(client.shh_getPublicKey(keyID2)) == pubkey.toPublicKey
await(client.shh_getPrivateKey(keyID2)) == privkey.toPrivateKey await(client.shh_getPrivateKey(keyID2)).toRaw() == privkey.toPrivateKey.toRaw()
await(client.shh_hasKeyPair(keyID2)) == true await(client.shh_hasKeyPair(keyID2)) == true
await(client.shh_deleteKeyPair(keyID2)) == true await(client.shh_deleteKeyPair(keyID2)) == true
await(client.shh_hasKeyPair(keyID2)) == false await(client.shh_hasKeyPair(keyID2)) == false

2
vendor/nim-eth vendored

@ -1 +1 @@
Subproject commit c3f23e5912efff98fc6c8181db579037e5a19a2c Subproject commit 0b110f3287f26e03f5e7ac4c9e7f0103456895c0

2
vendor/nim-stew vendored

@ -1 +1 @@
Subproject commit 76beeb769e30adc912d648c014fd95bf748fef24 Subproject commit 9414202d53fac99a0b1af33acac816ff9236e6d0

View File

@ -87,9 +87,9 @@ This dashboard can be found at `./waku/metrics/waku-sim-all-nodes-grafana-dashbo
# Spec support # Spec support
*This section last updated February 14, 2020* *This section last updated April 7, 2020*
This client of Waku is spec compliant with [Waku spec v0.3](https://specs.vac.dev/waku/waku.html). This client of Waku is spec compliant with [Waku spec v0.4](https://specs.vac.dev/waku/waku.html).
It doesn't yet implement the following recommended features: It doesn't yet implement the following recommended features:
- No support for rate limiting - No support for rate limiting

View File

@ -5,7 +5,7 @@ import
type type
Fleet* = enum Fleet* = enum
none none
beta prod
staging staging
WakuNodeConf* = object WakuNodeConf* = object
@ -84,7 +84,7 @@ type
nodekey* {. nodekey* {.
desc: "P2P node private key as hex.", desc: "P2P node private key as hex.",
defaultValue: newKeyPair() defaultValue: KeyPair.random().tryGet()
name: "nodekey" }: KeyPair name: "nodekey" }: KeyPair
# TODO: Add nodekey file option # TODO: Add nodekey file option
@ -135,8 +135,8 @@ type
proc parseCmdArg*(T: type KeyPair, p: TaintedString): T = proc parseCmdArg*(T: type KeyPair, p: TaintedString): T =
try: try:
# TODO: add isValidPrivateKey check from Nimbus? # TODO: add isValidPrivateKey check from Nimbus?
result.seckey = initPrivateKey(p) result.seckey = PrivateKey.fromHex(string(p)).tryGet()
result.pubkey = result.seckey.getPublicKey() result.pubkey = result.seckey.toPublicKey()[]
except CatchableError as e: except CatchableError as e:
raise newException(ConfigurationError, "Invalid private key") raise newException(ConfigurationError, "Invalid private key")

View File

@ -45,7 +45,7 @@ proc initNodeCmd(nodeType: NodeType, shift: int, staticNodes: seq[string] = @[],
discovery = false, bootNodes: seq[string] = @[], topicInterest = false, discovery = false, bootNodes: seq[string] = @[], topicInterest = false,
master = false, label: string): NodeInfo = master = false, label: string): NodeInfo =
let let
keypair = newKeyPair() keypair = KeyPair.random().tryGet()
address = Address(ip: parseIpAddress("127.0.0.1"), address = Address(ip: parseIpAddress("127.0.0.1"),
udpPort: (30303 + shift).Port, tcpPort: (30303 + shift).Port) udpPort: (30303 + shift).Port, tcpPort: (30303 + shift).Port)
enode = ENode(pubkey: keypair.pubkey, address: address) enode = ENode(pubkey: keypair.pubkey, address: address)

View File

@ -11,18 +11,15 @@ const clientId = "Nimbus waku node"
let globalListeningAddr = parseIpAddress("0.0.0.0") let globalListeningAddr = parseIpAddress("0.0.0.0")
proc setBootNodes(nodes: openArray[string]): seq[ENode] = proc setBootNodes(nodes: openArray[string]): seq[ENode] =
var bootnode: ENode
result = newSeqOfCap[ENode](nodes.len) result = newSeqOfCap[ENode](nodes.len)
for nodeId in nodes: for nodeId in nodes:
# TODO: something more user friendly than an assert # TODO: something more user friendly than an expect
doAssert(initENode(nodeId, bootnode) == ENodeStatus.Success) result.add(ENode.fromString(nodeId).expect("correct node"))
result.add(bootnode)
proc connectToNodes(node: EthereumNode, nodes: openArray[string]) = proc connectToNodes(node: EthereumNode, nodes: openArray[string]) =
for nodeId in nodes: for nodeId in nodes:
var whisperENode: ENode
# TODO: something more user friendly than an assert # TODO: something more user friendly than an assert
doAssert(initENode(nodeId, whisperENode) == ENodeStatus.Success) let whisperENode = ENode.fromString(nodeId).expect("correct node")
traceAsyncErrors node.peerPool.connectToNode(newNode(whisperENode)) traceAsyncErrors node.peerPool.connectToNode(newNode(whisperENode))
@ -97,7 +94,7 @@ proc run(config: WakuNodeConf) =
# TODO: Status fleet bootnodes are discv5? That will not work. # TODO: Status fleet bootnodes are discv5? That will not work.
let bootnodes = if config.bootnodes.len > 0: setBootNodes(config.bootnodes) let bootnodes = if config.bootnodes.len > 0: setBootNodes(config.bootnodes)
elif config.fleet == beta: setBootNodes(StatusBootNodes) elif config.fleet == prod: setBootNodes(StatusBootNodes)
elif config.fleet == staging: setBootNodes(StatusBootNodesStaging) elif config.fleet == staging: setBootNodes(StatusBootNodesStaging)
else: @[] else: @[]
@ -107,7 +104,7 @@ proc run(config: WakuNodeConf) =
if not config.bootnodeOnly: if not config.bootnodeOnly:
# Optionally direct connect with a set of nodes # Optionally direct connect with a set of nodes
if config.staticnodes.len > 0: connectToNodes(node, config.staticnodes) if config.staticnodes.len > 0: connectToNodes(node, config.staticnodes)
elif config.fleet == beta: connectToNodes(node, WhisperNodes) elif config.fleet == prod: connectToNodes(node, WhisperNodes)
elif config.fleet == staging: connectToNodes(node, WhisperNodesStaging) elif config.fleet == staging: connectToNodes(node, WhisperNodesStaging)
if config.rpc: if config.rpc:

View File

@ -69,20 +69,18 @@ proc generateRandomID(): Identifier =
break break
proc setBootNodes(nodes: openArray[string]): seq[ENode] = proc setBootNodes(nodes: openArray[string]): seq[ENode] =
var bootnode: ENode
result = newSeqOfCap[ENode](nodes.len) result = newSeqOfCap[ENode](nodes.len)
for nodeId in nodes: for nodeId in nodes:
# For now we can just do assert as we only pass our own const arrays. # For now we can just do assert as we only pass our own const arrays.
doAssert(initENode(nodeId, bootnode) == ENodeStatus.Success) let enode = ENode.fromString(nodeId).expect("correct enode")
result.add(bootnode) result.add(enode)
proc connectToNodes(nodes: openArray[string]) = proc connectToNodes(nodes: openArray[string]) =
for nodeId in nodes: for nodeId in nodes:
var whisperENode: ENode
# For now we can just do assert as we only pass our own const arrays. # For now we can just do assert as we only pass our own const arrays.
doAssert(initENode(nodeId, whisperENode) == ENodeStatus.Success) let enode = ENode.fromString(nodeId).expect("correct enode")
traceAsyncErrors node.peerPool.connectToNode(newNode(whisperENode)) traceAsyncErrors node.peerPool.connectToNode(newNode(enode))
# Setting up the node # Setting up the node
@ -95,16 +93,21 @@ proc nimbus_start(port: uint16, startListening: bool, enableDiscovery: bool,
var keypair: KeyPair var keypair: KeyPair
if privateKey.isNil: if privateKey.isNil:
keypair = newKeyPair() var kp = KeyPair.random()
if kp.isErr:
error "Can't generate keypair", err = kp.error
return false
keypair = kp[]
else: else:
try: let
let privKey = initPrivateKey(makeOpenArray(privateKey, 32)) privKey = PrivateKey.fromRaw(makeOpenArray(privateKey, 32))
keypair = privKey.toKeyPair() kp = privKey and privKey[].toKeyPair()
if kp.isErr:
except EthKeysException:
error "Passed an invalid private key." error "Passed an invalid private key."
return false return false
keypair = kp[]
node = newEthereumNode(keypair, address, 1, nil, addAllCapabilities = false) node = newEthereumNode(keypair, address, 1, nil, addAllCapabilities = false)
node.addCapability Whisper node.addCapability Whisper
@ -130,12 +133,13 @@ proc nimbus_poll() {.exportc, dynlib.} =
proc nimbus_add_peer(nodeId: cstring): bool {.exportc, dynlib.} = proc nimbus_add_peer(nodeId: cstring): bool {.exportc, dynlib.} =
var var
whisperENode: ENode
whisperNode: Node whisperNode: Node
discard initENode($nodeId, whisperENode) let enode = ENode.fromString($nodeId)
if enode.isErr:
return false
try: try:
whisperNode = newNode(whisperENode) whisperNode = newNode(enode[])
except Secp256k1Exception: except CatchableError:
return false return false
# TODO: call can create `Exception`, why? # TODO: call can create `Exception`, why?
@ -145,7 +149,7 @@ proc nimbus_add_peer(nodeId: cstring): bool {.exportc, dynlib.} =
# Whisper API (Similar to Whisper JSON-RPC API) # Whisper API (Similar to Whisper JSON-RPC API)
proc nimbus_channel_to_topic(channel: cstring): CTopic proc nimbus_channel_to_topic(channel: cstring): CTopic
{.exportc, dynlib, raises: [].} = {.exportc, dynlib, raises: [Defect].} =
# Only used for the example, to conveniently convert channel to topic. # Only used for the example, to conveniently convert channel to topic.
doAssert(not channel.isNil, "Channel cannot be nil.") doAssert(not channel.isNil, "Channel cannot be nil.")
@ -156,32 +160,41 @@ proc nimbus_channel_to_topic(channel: cstring): CTopic
# Asymmetric Keys # Asymmetric Keys
proc nimbus_new_keypair(id: var Identifier): bool proc nimbus_new_keypair(id: var Identifier): bool
{.exportc, dynlib, raises: [].} = {.exportc, dynlib, raises: [Defect].} =
## Caller needs to provide as id a pointer to 32 bytes allocation. ## Caller needs to provide as id a pointer to 32 bytes allocation.
doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.")
id = generateRandomID() id = generateRandomID()
try: try:
whisperKeys.asymKeys.add(id.toHex(), newKeyPair()) whisperKeys.asymKeys.add(id.toHex(), KeyPair.random().tryGet())
result = true result = true
except Secp256k1Exception: except CatchableError:
# Don't think this can actually happen, comes from the `getPublicKey` part # Don't think this can actually happen, comes from the `getPublicKey` part
# in `newKeyPair` # in `newKeyPair`
discard discard
proc nimbus_add_keypair(privateKey: ptr byte, id: var Identifier): proc nimbus_add_keypair(privateKey: ptr byte, id: var Identifier):
bool {.exportc, dynlib, raises: [OSError, IOError, ValueError].} = bool {.exportc, dynlib, raises: [Defect, OSError, IOError, ValueError].} =
## Caller needs to provide as id a pointer to 32 bytes allocation. ## Caller needs to provide as id a pointer to 32 bytes allocation.
doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.")
doAssert(not privateKey.isNil, "Private key cannot be nil.") doAssert(not privateKey.isNil, "Private key cannot be nil.")
var keypair: KeyPair var keypair: KeyPair
try: if privateKey.isNil:
let privKey = initPrivateKey(makeOpenArray(privateKey, 32)) var kp = KeyPair.random()
keypair = privKey.toKeyPair() if kp.isErr:
except EthKeysException, Secp256k1Exception: error "Can't generate keypair", err = kp.error
error "Passed an invalid private key." return false
return false keypair = kp[]
else:
let
privKey = PrivateKey.fromRaw(makeOpenArray(privateKey, 32))
kp = privKey and privKey[].toKeyPair()
if kp.isErr:
error "Passed an invalid private key."
return false
keypair = kp[]
result = true result = true
id = generateRandomID() id = generateRandomID()
@ -220,7 +233,7 @@ proc nimbus_add_symkey(symKey: ptr SymKey, id: var Identifier): bool
whisperKeys.symKeys.add(id.toHex, symKey[]) whisperKeys.symKeys.add(id.toHex, symKey[])
proc nimbus_add_symkey_from_password(password: cstring, id: var Identifier): proc nimbus_add_symkey_from_password(password: cstring, id: var Identifier):
bool {.exportc, dynlib, raises: [].} = bool {.exportc, dynlib, raises: [Defect].} =
## Caller needs to provide as id a pointer to 32 bytes allocation. ## Caller needs to provide as id a pointer to 32 bytes allocation.
doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.") doAssert(not (unsafeAddr id).isNil, "Key id cannot be nil.")
doAssert(not password.isNil, "Password cannot be nil.") doAssert(not password.isNil, "Password cannot be nil.")
@ -277,11 +290,11 @@ proc nimbus_post(message: ptr CPostMessage): bool {.exportc, dynlib.} =
return false return false
if not message.pubKey.isNil(): if not message.pubKey.isNil():
try: let pubkey = PublicKey.fromRaw(makeOpenArray(message.pubKey, 64))
asymKey = some(initPublicKey(makeOpenArray(message.pubKey, 64))) if pubkey.isErr:
except EthKeysException:
error "Passed an invalid public key for encryption." error "Passed an invalid public key for encryption."
return false return false
asymKey = some(pubkey[])
try: try:
if not message.symKeyID.isNil(): if not message.symKeyID.isNil():
@ -340,11 +353,11 @@ proc nimbus_subscribe_filter(options: ptr CFilterOptions,
return false return false
if not options.source.isNil(): if not options.source.isNil():
try: let pubkey = PublicKey.fromRaw(makeOpenArray(options.source, 64))
src = some(initPublicKey(makeOpenArray(options.source, 64))) if pubkey.isErr:
except EthKeysException:
error "Passed an invalid public key as source." error "Passed an invalid public key as source."
return false return false
src = some(pubkey[])
try: try:
if not options.symKeyID.isNil(): if not options.symKeyID.isNil():
@ -377,11 +390,11 @@ proc nimbus_subscribe_filter(options: ptr CFilterOptions,
recipientPublicKey: array[RawPublicKeySize, byte] recipientPublicKey: array[RawPublicKeySize, byte]
if msg.decoded.src.isSome(): if msg.decoded.src.isSome():
# Need to pass the serialized form # Need to pass the serialized form
source = msg.decoded.src.get().getRaw() source = msg.decoded.src.get().toRaw()
cmsg.source = addr source[0] cmsg.source = addr source[0]
if msg.dst.isSome(): if msg.dst.isSome():
# Need to pass the serialized form # Need to pass the serialized form
recipientPublicKey = msg.decoded.src.get().getRaw() recipientPublicKey = msg.decoded.src.get().toRaw()
cmsg.recipientPublicKey = addr recipientPublicKey[0] cmsg.recipientPublicKey = addr recipientPublicKey[0]
handler(addr cmsg, udata) handler(addr cmsg, udata)
@ -456,7 +469,7 @@ proc nimbus_join_public_chat(channel: cstring,
# TODO: How would we do key management? In nimbus (like in rpc) or in status go? # TODO: How would we do key management? In nimbus (like in rpc) or in status go?
proc nimbus_post_public(channel: cstring, payload: cstring) proc nimbus_post_public(channel: cstring, payload: cstring)
{.exportc, dynlib.} = {.exportc, dynlib.} =
let encPrivateKey = initPrivateKey("5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3") let encPrivateKey = PrivateKey.fromHex("5dc5381cae54ba3174dc0d46040fe11614d0cc94d41185922585198b4fcef9d3")[]
var ctx: HMAC[sha256] var ctx: HMAC[sha256]
var symKey: SymKey var symKey: SymKey