Merge branch 'master' into nim-1.2
This commit is contained in:
commit
af89b51503
|
@ -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,10 +451,11 @@ 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 =
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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))).
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit c3f23e5912efff98fc6c8181db579037e5a19a2c
|
Subproject commit 0b110f3287f26e03f5e7ac4c9e7f0103456895c0
|
|
@ -1 +1 @@
|
||||||
Subproject commit 76beeb769e30adc912d648c014fd95bf748fef24
|
Subproject commit 9414202d53fac99a0b1af33acac816ff9236e6d0
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,33 +160,42 @@ 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
|
||||||
|
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."
|
error "Passed an invalid private key."
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
keypair = kp[]
|
||||||
|
|
||||||
result = true
|
result = true
|
||||||
id = generateRandomID()
|
id = generateRandomID()
|
||||||
whisperKeys.asymKeys.add(id.toHex(), keypair)
|
whisperKeys.asymKeys.add(id.toHex(), keypair)
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue