diff --git a/.gitignore b/.gitignore index 434a952..85870ea 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,8 @@ local.properties *.iml gradlew gradlew.bat +android/.settings +android/.project # node.js # diff --git a/README.md b/README.md index e87f341..821d8e6 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,10 @@ const config: NodeConfig = { "enode://XXXX@X[::]:XXXX", "enode://YYYY@Y[::]:YYYY" ], - "networkID": networkID, // --networkid / Network identifier (integer, 0=Olympic (disused), 1=Frontier, 2=Morden (disused), 3=Ropsten) (default: 1) + "networkID": networkID, // --networkid / Network identifier (integer, 42220=mainnet, 62320=baklava (testnet), 44787=alfajores (testnet)) (default: 1) "maxPeers": 0, // --maxpeers / Maximum number of network peers (network disabled if set to 0) (default: 25) "genesis": genesis, // genesis.json file - "nodeDir": ".private-ethereum", // --datadir / Data directory for the databases and keystore + "nodeDir": ".celo", // --datadir / Data directory for the databases and keystore "keyStoreDir": "keystore", // --keystore / Directory for the keystore (default = inside the datadir) "enodes": "enode://XXXX@X[::]:XXXX" // static_nodes.json file. Comma separated enode URLs "noDiscovery": false, // --nodiscover / determines if the node will not participate in p2p discovery (v5) @@ -95,7 +95,7 @@ The object that holds the config of the node consists of these fields: - `logFile` **string** Path where to write geth logfile - `logFileLogLevel` **number** Log level when writing to file - `maxPeers` **number** Maximum number of network peers (network disabled if set to 0) (default: 25) -- `networkID` **number** Network identifier +- `networkID` **number** Network identifier - `noDiscovery` **boolean** Determines if the node will not participate in p2p discovery (v5) - `nodeDir` **string** Data directory for the databases and keystore - `syncMode` **number** The number associated with a sync mode in `celo-blockchain/mobile/geth.go` @@ -108,8 +108,8 @@ The object that holds the config of the node consists of these fields: When dealing with blockchain accounts we're usually handling binary data in the hexadecimal format as a general convention of the ecosystem. These can be private keys, hashes, or transactions encoded in RLP format. The `celo-blockchain` (geth) library being more low-level expects byte arrays, but getting byte arrays accross the native bridge is troublesome. -As mentioned above a hexadecimal encoded string is the common way of passing around such data but our native environments are lacking in standard library support for parsing hex strings. -We could have added additional code for this, but it would increase our attack surface, it being hard(er) to test and maintain. +As mentioned above a hexadecimal encoded string is the common way of passing around such data but our native environments are lacking in standard library support for parsing hex strings. +We could have added additional code for this, but it would increase our attack surface, it being hard(er) to test and maintain. Therefore, we've decided to rely on Base64 encoding which is better supported by the native platforms. This means in several places where we're passing binary data to the bridge `base64` is te preferred encoding. This is easily achieved on the javascript side with access to the `Buffer` type. @@ -128,7 +128,7 @@ Configures the node and returns true on success, may throw errors. **start(): Promise** -Start creates a live P2P node and starts running it. +Start creates a live P2P node and starts running it. Returns true if a node was started, false if node was already running and may throw errors. ### stop @@ -195,12 +195,12 @@ Sign a transaction with a passphrase for the signer account. **Parameters**: - `txRLPBase64` - base64 encoded transaction in RLP format -- `signer` - the address of the signer +- `signer` - the address of the signer - `passphrase` - the passphrase to unlock the signer account Returns the signed transaction in RLP format encoded as base64. -### signHash +### signHash **signHash(hashBase64: string, signer: string): Promise** @@ -220,7 +220,7 @@ Sign a hash with a passphrase for the signer account. **Parameters**: - `hashBase64` - base64 encoded hash -- `signer` - the address of the signer +- `signer` - the address of the signer - `passphrase` - the passphrase to unlock the signer account Returns the signature (binary) encoded as base64. diff --git a/android/src/main/java/com/reactnativegeth/RNGethModule.java b/android/src/main/java/com/reactnativegeth/RNGethModule.java index 9431754..9622f16 100644 --- a/android/src/main/java/com/reactnativegeth/RNGethModule.java +++ b/android/src/main/java/com/reactnativegeth/RNGethModule.java @@ -24,8 +24,8 @@ import org.ethereum.geth.Address; import org.ethereum.geth.BigInt; import org.ethereum.geth.Context; -// import org.ethereum.geth.Enode; -// import org.ethereum.geth.Enodes; +import org.ethereum.geth.Enode; +import org.ethereum.geth.Enodes; import org.ethereum.geth.EthereumClient; import org.ethereum.geth.Geth; import org.ethereum.geth.Header; @@ -107,17 +107,23 @@ public void setConfig(ReadableMap config, Promise promise) { if (config.hasKey("keyStoreDir")) keyStoreDir = config.getString("keyStoreDir"); if (config.hasKey("syncMode")) nc.setSyncMode(config.getInt("syncMode")); if (config.hasKey("useLightweightKDF")) nc.setUseLightweightKDF(config.getBoolean("useLightweightKDF")); - // if (config.hasKey("noDiscovery")) nc.setNoDiscovery(config.getBoolean("noDiscovery")); - // if (config.hasKey("bootnodeEnodes")) { - // ReadableArray bootnodeEnodes = config.getArray("bootnodeEnodes"); - // int enodesSize = bootnodeEnodes.size(); - // Enodes enodes = new Enodes(enodesSize); - // for (int i = 0; i < enodesSize; i++) { - // Enode enode = new Enode(bootnodeEnodes.getString(i)); - // enodes.set(i, enode); - // } - // nc.setBootstrapNodes(enodes); - // } + if (config.hasKey("noDiscovery")) nc.setNoDiscovery(config.getBoolean("noDiscovery")); + if (config.hasKey("bootnodeEnodes")) { + ReadableArray bootnodeEnodes = config.getArray("bootnodeEnodes"); + int enodesSize = bootnodeEnodes.size(); + Enodes enodes = new Enodes(enodesSize); + for (int i = 0; i < enodesSize; i++) { + Enode enode = new Enode(bootnodeEnodes.getString(i)); + enodes.set(i, enode); + } + nc.setBootstrapNodes(enodes); + } + // HTTP RPC configurations, which should only be used for development & debugging + if (config.hasKey("httpHost")) nc.setHTTPHost(config.getString("httpHost")); + if (config.hasKey("httpPort")) nc.setHTTPPort(config.getInt("httpPort")); + if (config.hasKey("httpVirtualHosts")) nc.setHTTPVirtualHosts(config.getString("httpVirtualHosts")); + if (config.hasKey("httpModules")) nc.setHTTPModules(config.getString("httpModules")); + if (config.hasKey("ipcPath")) nc.setIPCPath(config.getString("ipcPath")); if (config.hasKey("logFile")) { String logFileName = config.getString("logFile"); diff --git a/ios/RNGeth.swift b/ios/RNGeth.swift index 9d8f7e8..809d4bb 100644 --- a/ios/RNGeth.swift +++ b/ios/RNGeth.swift @@ -33,15 +33,15 @@ class RNGeth: RCTEventEmitter, GethNewHeadHandlerProtocol { runner = NodeRunner() super.init() } - + // MARK: Utils - + func convertToDictionary(from text: String) throws -> [String: String] { guard let data = text.data(using: .utf8) else { return [:] } let anyResult: Any = try JSONSerialization.jsonObject(with: data, options: []) return anyResult as? [String: String] ?? [:] } - + // MARK: RCTEventEmitter // Not yet sure we actually need main queue setup, @@ -63,9 +63,9 @@ class RNGeth: RCTEventEmitter, GethNewHeadHandlerProtocol { override func supportedEvents() -> [String]! { return ["GethNewHead"] } - + // MARK: GethNewHeadHandlerProtocol - + func onError(_ failure: String?) { NSLog("@", failure!) } @@ -88,7 +88,7 @@ class RNGeth: RCTEventEmitter, GethNewHeadHandlerProtocol { NSLog("@", NSErr) } } - + // MARK: Bridge methods /** @@ -100,13 +100,13 @@ class RNGeth: RCTEventEmitter, GethNewHeadHandlerProtocol { do { var addresses: [String] = [] let accounts = try runner.getAccounts() - + for i in 0.. Void { do { @@ -384,7 +420,7 @@ class RNGeth: RCTEventEmitter, GethNewHeadHandlerProtocol { reject(nil, nil, NSErr) } } - + /** * Terminates a running node along with all it's services. * diff --git a/src/GethNativeModule.ts b/src/GethNativeModule.ts index 9bd37b7..a138902 100644 --- a/src/GethNativeModule.ts +++ b/src/GethNativeModule.ts @@ -5,6 +5,10 @@ export type NodeConfig = { bootnodeEnodes?: string[], enodes?: string, genesis?: string, + httpHost?: string, + httpModules?: string, + httpPort?: number, + httpVirtualHosts?: string, ipcPath?: string keyStoreDir?: string, logFile?: string, @@ -99,4 +103,3 @@ export interface GethNativeModule { */ listAccounts: () => Promise, } -