From ac9fb3746517936ef8da809bd270425e7e84dda6 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 27 Nov 2018 18:21:28 +0000 Subject: [PATCH 1/8] Initial commit for eth_estimateGas --- nimbus/rpc/p2p.nim | 73 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/nimbus/rpc/p2p.nim b/nimbus/rpc/p2p.nim index afe6500fa..e37524a49 100644 --- a/nimbus/rpc/p2p.nim +++ b/nimbus/rpc/p2p.nim @@ -13,7 +13,7 @@ import eth_common, eth_p2p, eth_keys, eth_trie/db, rlp, ../utils/header, ../transaction, ../config, ../vm_state, ../constants, ../vm_types, ../vm_state_transactions, ../utils/addresses, - ../db/[db_chain, state_db, storage_types], + ../vm/[interpreter_dispatch, computation], rpc_types, rpc_utils, ../vm/[message, computation] #[ @@ -33,6 +33,52 @@ template balance(addressDb: ReadOnlyStateDb, address: EthAddress): GasInt = # TODO: Account balance u256 but GasInt is int64? addressDb.getBalance(address).truncate(int64) +proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress, gasPrice: GasInt, tolerance = 1): GasInt = + proc dummyComputation(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress): BaseComputation = + # Note that vmState may be altered + setupComputation( + vmState.blockHeader, + vmState, + transaction, + sender) + + proc dummyTransaction(gasLimit, gasPrice: GasInt, destination: EthAddress, value: UInt256): Transaction = + Transaction( + accountNonce: 0.AccountNonce, + gasPrice: gasPrice, + gasLimit: gasLimit, + to: destination, + value: value + ) + var + hiGas = vmState.gasLimit + loGas = transaction.intrinsicGas + gasPrice = transaction.gasPrice # TODO: Or zero? + + proc tryTransaction(vmState: var BaseVMState, gasLimit: GasInt): bool = + var + spoofTransaction = dummyTransaction(gasLimit, gasPrice, transaction.to, transaction.value) + computation = vmState.dummyComputation(spoofTransaction, sender) + computation.executeOpcodes + if not computation.isError: + return true + + if vmState.tryTransaction(loGas): + return loGas + if not vmState.tryTransaction(hiGas): + return 0.GasInt # TODO: Reraise error from computation + + var + minVal = vmState.gasLimit + maxVal = transaction.intrinsicGas + while loGas - hiGas > tolerance: + let midPoint = (loGas + hiGas) div 2 + if vmState.tryTransaction(midPoint): + minVal = midPoint + else: + maxVal = midPoint + result = minVal + proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = func getAccountDb(header: BlockHeader): ReadOnlyStateDB = @@ -274,7 +320,7 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = discard comp.execComputation result = ("0x" & nimcrypto.toHex(comp.output)).HexDataStr - + rpcsrv.rpc("eth_estimateGas") do(call: EthCall, quantityTag: string) -> GasInt: ## Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. ## The transaction will not be added to the blockchain. Note that the estimate may be significantly more than @@ -283,7 +329,28 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = ## call: the transaction call object. ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter. ## Returns the amount of gas used. - discard + # TODO: Use optional fields with EthCall + var + header = chain.headerFromTag(quantityTag) + vmState = newBaseVMState(header, chain) + let + gasLimit = if call.gas > 0.GasInt: call.gas else: header.gasLimit + gasPrice = if call.gasPrice > 0: call.gasPrice else: 0.GasInt + curState = chain.getStateDb(header.stateRoot, true) + sender = call.source.string.strToAddress + destination = call.to.string.strToAddress + nonce = curState.getNonce(sender) + value = call.value + # TODO: Use initTransaction when merged + transaction = Transaction( + accountNonce: nonce, + gasPrice: gasPrice, + gasLimit: gasLimit, + to: destination, + value: value.u256, + payload: @[] + ) + result = vmState.binarySearchGas(transaction, sender, gasPrice) func populateBlockObject(header: BlockHeader, blockBody: BlockBody): BlockObject = result.number = some(header.blockNumber) From 3f1122702e6f5c498b435b61c8305d3cb0187d3c Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 27 Nov 2018 18:21:28 +0000 Subject: [PATCH 2/8] Initial commit for eth_estimateGas --- nimbus/rpc/p2p.nim | 48 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/nimbus/rpc/p2p.nim b/nimbus/rpc/p2p.nim index e37524a49..e981e8909 100644 --- a/nimbus/rpc/p2p.nim +++ b/nimbus/rpc/p2p.nim @@ -14,7 +14,7 @@ import ../utils/header, ../transaction, ../config, ../vm_state, ../constants, ../vm_types, ../vm_state_transactions, ../utils/addresses, ../vm/[interpreter_dispatch, computation], - rpc_types, rpc_utils, ../vm/[message, computation] + rpc_types, rpc_utils, ../vm/[message, computation, interpreter_dispatch] #[ Note: @@ -79,6 +79,52 @@ proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: maxVal = midPoint result = minVal +proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress, gasPrice: GasInt, tolerance = 1): GasInt = + proc dummyComputation(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress): BaseComputation = + # Note that vmState may be altered + setupComputation( + vmState.blockHeader, + vmState, + transaction, + sender) + + proc dummyTransaction(gasLimit, gasPrice: GasInt, destination: EthAddress, value: UInt256): Transaction = + Transaction( + accountNonce: 0.AccountNonce, + gasPrice: gasPrice, + gasLimit: gasLimit, + to: destination, + value: value + ) + var + hiGas = vmState.gasLimit + loGas = transaction.intrinsicGas + gasPrice = transaction.gasPrice # TODO: Or zero? + + proc tryTransaction(vmState: var BaseVMState, gasLimit: GasInt): bool = + var + spoofTransaction = dummyTransaction(gasLimit, gasPrice, transaction.to, transaction.value) + computation = vmState.dummyComputation(spoofTransaction, sender) + computation.executeOpcodes + if not computation.isError: + return true + + if vmState.tryTransaction(loGas): + return loGas + if not vmState.tryTransaction(hiGas): + return 0.GasInt # TODO: Reraise error from computation + + var + minVal = vmState.gasLimit + maxVal = transaction.intrinsicGas + while loGas - hiGas > tolerance: + let midPoint = (loGas + hiGas) div 2 + if vmState.tryTransaction(midPoint): + minVal = midPoint + else: + maxVal = midPoint + result = minVal + proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = func getAccountDb(header: BlockHeader): ReadOnlyStateDB = From ab0f8f6748a46dd318647b056c1fbe55fb686136 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 29 Nov 2018 18:30:07 +0000 Subject: [PATCH 3/8] Update eth_estimateGas to use optional types --- nimbus/rpc/p2p.nim | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/nimbus/rpc/p2p.nim b/nimbus/rpc/p2p.nim index e981e8909..87d6270fb 100644 --- a/nimbus/rpc/p2p.nim +++ b/nimbus/rpc/p2p.nim @@ -375,25 +375,34 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = ## call: the transaction call object. ## quantityTag: integer block number, or the string "latest", "earliest" or "pending", see the default block parameter. ## Returns the amount of gas used. - # TODO: Use optional fields with EthCall var header = chain.headerFromTag(quantityTag) vmState = newBaseVMState(header, chain) let - gasLimit = if call.gas > 0.GasInt: call.gas else: header.gasLimit - gasPrice = if call.gasPrice > 0: call.gasPrice else: 0.GasInt + gasLimit = if + call.gas.isSome and call.gas.get > 0.GasInt: call.gas.get + else: header.gasLimit + gasPrice = if + call.gasPrice.isSome and call.gasPrice.get > 0: call.gasPrice.get + else: 0.GasInt + sender = if + call.source.isSome: call.source.get.toAddress + else: ZERO_ADDRESS + destination = if + call.to.isSome: call.to.get.toAddress + else: ZERO_ADDRESS curState = chain.getStateDb(header.stateRoot, true) - sender = call.source.string.strToAddress - destination = call.to.string.strToAddress nonce = curState.getNonce(sender) - value = call.value - # TODO: Use initTransaction when merged + value = if + call.value.isSome: call.value.get + else: 0.u256 + transaction = Transaction( accountNonce: nonce, gasPrice: gasPrice, gasLimit: gasLimit, to: destination, - value: value.u256, + value: value, payload: @[] ) result = vmState.binarySearchGas(transaction, sender, gasPrice) From c2fae69318178a3c5a05b01855b4f2a3d4cc7caf Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 29 Nov 2018 18:53:12 +0000 Subject: [PATCH 4/8] Add assertion to check for canonical head --- tests/test_rpc.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_rpc.nim b/tests/test_rpc.nim index 21b7e471b..21f8e453b 100644 --- a/tests/test_rpc.nim +++ b/tests/test_rpc.nim @@ -4,7 +4,7 @@ import ../nimbus/rpc/[common, p2p, hexstrings, rpc_types], ../nimbus/constants, ../nimbus/nimbus/[vm_state, config], - ../nimbus/db/[state_db, db_chain], eth_common, byteutils, + ../nimbus/db/[state_db, db_chain, storage_types], eth_common, byteutils, ../nimbus/p2p/chain, ../nimbus/genesis, eth_trie/db, @@ -58,7 +58,8 @@ proc doTests = defaultGenesisBlockForNetwork(conf.net.networkId.toPublicNetwork()).commit(chain) state.mutateStateDB: db.setBalance(address, balance) - + assert(canonicalHeadHashKey().toOpenArray in state.chainDb.db) + # Create Ethereum RPCs var rpcServer = newRpcSocketServer(["localhost:8545"]) From 20933f494bdc2947248b81f5b17736ce56752e41 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Mon, 3 Dec 2018 19:47:20 +0000 Subject: [PATCH 5/8] Moved and unstubbed intrinsicGas from vm_state_transactions --- nimbus/transaction.nim | 10 +++++++++- nimbus/vm_state_transactions.nim | 8 -------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/nimbus/transaction.nim b/nimbus/transaction.nim index 699d6e039..423663d38 100644 --- a/nimbus/transaction.nim +++ b/nimbus/transaction.nim @@ -20,11 +20,19 @@ proc initTransaction*(nonce: AccountNonce, gasPrice, gasLimit: GasInt, to: EthAd result.S = S result.isContractCreation = isContractCreation +func intrinsicGas*(data: openarray[byte]): GasInt = + result = 21_000 # GasTransaction + for i in data: + if i == 0: + result += 4 # GasTXDataZero + else: + result += 68 # GasTXDataNonZero + proc intrinsicGas*(t: Transaction): GasInt = # Compute the baseline gas cost for this transaction. This is the amount # of gas needed to send this transaction (but that is not actually used # for computation) - raise newException(ValueError, "not implemented intrinsicGas") + result = t.payload.intrinsicGas proc validate*(t: Transaction) = # Hook called during instantiation to ensure that all transaction diff --git a/nimbus/vm_state_transactions.nim b/nimbus/vm_state_transactions.nim index f809f85b3..7a35d41de 100644 --- a/nimbus/vm_state_transactions.nim +++ b/nimbus/vm_state_transactions.nim @@ -12,14 +12,6 @@ import ./transaction, ./vm_types, ./vm_state, ./block_types, ./db/[db_chain, state_db], ./utils/header, ./vm/interpreter, ./vm/interpreter/gas_costs, ./utils/addresses -func intrinsicGas*(data: openarray[byte]): GasInt = - result = 21_000 - for i in data: - if i == 0: - result += 4 - else: - result += 68 - proc validateTransaction*(vmState: BaseVMState, transaction: Transaction, sender: EthAddress): bool = # XXX: https://github.com/status-im/nimbus/issues/35#issuecomment-391726518 # XXX: lots of avoidable u256 construction From 2c1c3d6c763b8c78811d3eb554dd90a825b77a86 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Mon, 3 Dec 2018 19:48:10 +0000 Subject: [PATCH 6/8] Update eth_estimateGas sig for testing --- tests/rpcclient/ethcallsigs.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/rpcclient/ethcallsigs.nim b/tests/rpcclient/ethcallsigs.nim index c508bf6e5..41725de85 100644 --- a/tests/rpcclient/ethcallsigs.nim +++ b/tests/rpcclient/ethcallsigs.nim @@ -1,7 +1,7 @@ ## This module contains signatures for the Ethereum client RPCs. ## The signatures are not imported directly, but read and processed with parseStmt, ## then a procedure body is generated to marshal native Nim parameters to json and visa versa. -import json, stint, eth_common, ../../nimbus/rpc/hexstrings +import json, stint, eth_common, ../../nimbus/rpc/hexstrings, ../../nimbus/rpc/rpc_types proc web3_clientVersion(): string proc web3_sha3(data: string): string @@ -27,11 +27,11 @@ proc eth_getCode(data: EthAddressStr, quantityTag: string): HexDataStr proc eth_sign(data:EthAddressStr, message: HexDataStr): HexDataStr #proc eth_sendRawTransaction(data: string, quantityTag: int): UInt256 proc eth_call(call: EthCall, quantityTag: string): string +proc eth_estimateGas(call: EthCall, quantityTag: string): GasInt # TODO: Use eth_common types #[proc eth_sendTransaction(obj: EthSend): UInt256 -proc eth_estimateGas(call: EthCall, quantityTag: string): UInt256 proc eth_getBlockByHash(data: array[32, byte], fullTransactions: bool): BlockObject proc eth_getBlockByNumber(quantityTag: string, fullTransactions: bool): BlockObject proc eth_getTransactionByHash(data: Uint256): TransactionObject From d19a7f7c04d7134aa7ded46109eaf349900455f8 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Mon, 3 Dec 2018 20:06:00 +0000 Subject: [PATCH 7/8] Add simple test for eth_estimateGas --- tests/test_rpc.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_rpc.nim b/tests/test_rpc.nim index 21f8e453b..08064984e 100644 --- a/tests/test_rpc.nim +++ b/tests/test_rpc.nim @@ -87,6 +87,12 @@ proc doTests = let blockNum = state.blockheader.blockNumber var r = waitFor client.eth_getBalance(address.toEthAddressStr, "0x" & blockNum.toHex) echo r + test "eth_estimateGas": + let + call = EthCall() + blockNum = state.blockheader.blockNumber + var r = waitFor client.eth_estimateGas(call, "0x" & blockNum.toHex) + check r == 21_000 rpcServer.stop() rpcServer.close() From 7c7260552d0e6eadb856d4de2702ca0f70ae407b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C8=98tefan=20Talpalaru?= Date: Sun, 6 Jan 2019 20:19:48 +0100 Subject: [PATCH 8/8] rebase and various fixes - port to new APIs - added copyright headers - bumped the copyright interval in modified files - fixed tests - reorganised imports - normalised function names - deleted some trailing space - added test_rpc to all_tests - assert() -> doAssert() - moved the RPC port in a constant for the test suite --- nimbus/rpc/p2p.nim | 59 +++----------------------- nimbus/vm/interpreter/opcodes_impl.nim | 6 +-- tests/all_tests.nim | 5 ++- tests/rpcclient/ethcallsigs.nim | 14 +++++- tests/rpcclient/test_hexstrings.nim | 7 +++ tests/test_rpc.nim | 44 ++++++++++--------- 6 files changed, 56 insertions(+), 79 deletions(-) diff --git a/nimbus/rpc/p2p.nim b/nimbus/rpc/p2p.nim index 87d6270fb..b0493bd75 100644 --- a/nimbus/rpc/p2p.nim +++ b/nimbus/rpc/p2p.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2019 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) # * MIT license ([LICENSE-MIT](LICENSE-MIT)) @@ -13,7 +13,7 @@ import eth_common, eth_p2p, eth_keys, eth_trie/db, rlp, ../utils/header, ../transaction, ../config, ../vm_state, ../constants, ../vm_types, ../vm_state_transactions, ../utils/addresses, - ../vm/[interpreter_dispatch, computation], + ../db/[db_chain, state_db, storage_types], rpc_types, rpc_utils, ../vm/[message, computation, interpreter_dispatch] #[ @@ -37,11 +37,10 @@ proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: proc dummyComputation(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress): BaseComputation = # Note that vmState may be altered setupComputation( - vmState.blockHeader, vmState, transaction, sender) - + proc dummyTransaction(gasLimit, gasPrice: GasInt, destination: EthAddress, value: UInt256): Transaction = Transaction( accountNonce: 0.AccountNonce, @@ -54,53 +53,7 @@ proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: hiGas = vmState.gasLimit loGas = transaction.intrinsicGas gasPrice = transaction.gasPrice # TODO: Or zero? - - proc tryTransaction(vmState: var BaseVMState, gasLimit: GasInt): bool = - var - spoofTransaction = dummyTransaction(gasLimit, gasPrice, transaction.to, transaction.value) - computation = vmState.dummyComputation(spoofTransaction, sender) - computation.executeOpcodes - if not computation.isError: - return true - if vmState.tryTransaction(loGas): - return loGas - if not vmState.tryTransaction(hiGas): - return 0.GasInt # TODO: Reraise error from computation - - var - minVal = vmState.gasLimit - maxVal = transaction.intrinsicGas - while loGas - hiGas > tolerance: - let midPoint = (loGas + hiGas) div 2 - if vmState.tryTransaction(midPoint): - minVal = midPoint - else: - maxVal = midPoint - result = minVal - -proc binarySearchGas(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress, gasPrice: GasInt, tolerance = 1): GasInt = - proc dummyComputation(vmState: var BaseVMState, transaction: Transaction, sender: EthAddress): BaseComputation = - # Note that vmState may be altered - setupComputation( - vmState.blockHeader, - vmState, - transaction, - sender) - - proc dummyTransaction(gasLimit, gasPrice: GasInt, destination: EthAddress, value: UInt256): Transaction = - Transaction( - accountNonce: 0.AccountNonce, - gasPrice: gasPrice, - gasLimit: gasLimit, - to: destination, - value: value - ) - var - hiGas = vmState.gasLimit - loGas = transaction.intrinsicGas - gasPrice = transaction.gasPrice # TODO: Or zero? - proc tryTransaction(vmState: var BaseVMState, gasLimit: GasInt): bool = var spoofTransaction = dummyTransaction(gasLimit, gasPrice, transaction.to, transaction.value) @@ -192,7 +145,7 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = let accountDb = accountDbFromTag(quantityTag) addrBytes = data.toAddress - balance = accountDb.get_balance(addrBytes) + balance = accountDb.getBalance(addrBytes) result = balance @@ -366,7 +319,7 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = discard comp.execComputation result = ("0x" & nimcrypto.toHex(comp.output)).HexDataStr - + rpcsrv.rpc("eth_estimateGas") do(call: EthCall, quantityTag: string) -> GasInt: ## Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. ## The transaction will not be added to the blockchain. Note that the estimate may be significantly more than @@ -391,7 +344,7 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB, rpcsrv: RpcServer) = destination = if call.to.isSome: call.to.get.toAddress else: ZERO_ADDRESS - curState = chain.getStateDb(header.stateRoot, true) + curState = vmState.readOnlyStateDb() nonce = curState.getNonce(sender) value = if call.value.isSome: call.value.get diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index a1623f152..257d524e4 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2019 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) # * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) @@ -781,8 +781,8 @@ op selfDestruct, inline = false: computation.vmState.mutateStateDB: let - local_balance = db.get_balance(computation.msg.storage_address) - beneficiary_balance = db.get_balance(beneficiary) + local_balance = db.getBalance(computation.msg.storage_address) + beneficiary_balance = db.getBalance(beneficiary) # Transfer to beneficiary db.setBalance(beneficiary, local_balance + beneficiary_balance) diff --git a/tests/all_tests.nim b/tests/all_tests.nim index a481896e6..bfc409964 100644 --- a/tests/all_tests.nim +++ b/tests/all_tests.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2018 Status Research & Development GmbH +# Copyright (c) 2018-2019 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) # * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) @@ -17,4 +17,5 @@ import ./test_code_stream, ./test_precompiles, ./test_generalstate_json, ./test_tracer_json, - ./test_persistblock_json + ./test_persistblock_json, + ./test_rpc diff --git a/tests/rpcclient/ethcallsigs.nim b/tests/rpcclient/ethcallsigs.nim index 41725de85..a5ad0edf0 100644 --- a/tests/rpcclient/ethcallsigs.nim +++ b/tests/rpcclient/ethcallsigs.nim @@ -1,7 +1,17 @@ +# Nimbus +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or distributed except according to those terms. + ## This module contains signatures for the Ethereum client RPCs. ## The signatures are not imported directly, but read and processed with parseStmt, ## then a procedure body is generated to marshal native Nim parameters to json and visa versa. -import json, stint, eth_common, ../../nimbus/rpc/hexstrings, ../../nimbus/rpc/rpc_types +import + json, + stint, eth_common, + ../../nimbus/rpc/hexstrings, ../../nimbus/rpc/rpc_types proc web3_clientVersion(): string proc web3_sha3(data: string): string @@ -64,4 +74,4 @@ proc shh_newFilter(filterOptions: FilterOptions, to: array[60, byte], topics: se proc shh_uninstallFilter(id: int): bool proc shh_getFilterChanges(id: int): seq[WhisperMessage] proc shh_getMessages(id: int): seq[WhisperMessage] -]# \ No newline at end of file +]# diff --git a/tests/rpcclient/test_hexstrings.nim b/tests/rpcclient/test_hexstrings.nim index b5efd4014..1d07dc7ae 100644 --- a/tests/rpcclient/test_hexstrings.nim +++ b/tests/rpcclient/test_hexstrings.nim @@ -1,3 +1,10 @@ +# Nimbus +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or distributed except according to those terms. + # Separated from main tests for brevity import unittest, ../../nimbus/rpc/hexstrings, json diff --git a/tests/test_rpc.nim b/tests/test_rpc.nim index 08064984e..cb9bcf1e3 100644 --- a/tests/test_rpc.nim +++ b/tests/test_rpc.nim @@ -1,15 +1,21 @@ +# Nimbus +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Licensed under either of +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +# at your option. This file may not be copied, modified, or distributed except according to those terms. + import - unittest, json, strformat, nimcrypto, rlp, options, + unittest, json, strformat, options, + nimcrypto, rlp, eth_trie/db, eth_p2p, eth_keys, json_rpc/[rpcserver, rpcclient], ../nimbus/rpc/[common, p2p, hexstrings, rpc_types], ../nimbus/constants, - ../nimbus/nimbus/[vm_state, config], + ../nimbus/[vm_state, config], ../nimbus/db/[state_db, db_chain, storage_types], eth_common, byteutils, ../nimbus/p2p/chain, - ../nimbus/genesis, - eth_trie/db, - eth_p2p, eth_keys -import rpcclient/test_hexstrings + ../nimbus/genesis, + ./rpcclient/test_hexstrings # Perform checks for hex string validation doHexStrTests() @@ -58,41 +64,41 @@ proc doTests = defaultGenesisBlockForNetwork(conf.net.networkId.toPublicNetwork()).commit(chain) state.mutateStateDB: db.setBalance(address, balance) - assert(canonicalHeadHashKey().toOpenArray in state.chainDb.db) + doAssert(canonicalHeadHashKey().toOpenArray in state.chainDb.db) # Create Ethereum RPCs + let RPC_PORT = 8545 var - rpcServer = newRpcSocketServer(["localhost:8545"]) + rpcServer = newRpcSocketServer(["localhost:" & $RPC_PORT]) client = newRpcSocketClient() setupCommonRpc(rpcServer) setupEthRpc(ethNode, chain, rpcServer) # Begin tests rpcServer.start() - waitFor client.connect("localhost", Port(8545)) + waitFor client.connect("localhost", Port(RPC_PORT)) + # TODO: add more tests here suite "Remote Procedure Calls": - # TODO: Currently returning 'block not found' when fetching header in p2p, so cannot perform tests test "eth_call": let blockNum = state.blockheader.blockNumber callParams = EthCall(value: some(100.u256)) - var r = waitFor client.eth_call(callParams, "0x" & blockNum.toHex) - echo r + r1 = waitFor client.eth_call(callParams, "0x" & blockNum.toHex) + check r1 == "0x" test "eth_getBalance": - expect ValueError: - # check error is raised on null address - var r = waitFor client.eth_getBalance(ZERO_ADDRESS.toEthAddressStr, "0x0") + let r2 = waitFor client.eth_getBalance(ZERO_ADDRESS.toEthAddressStr, "0x0") + check r2 == 0 let blockNum = state.blockheader.blockNumber - var r = waitFor client.eth_getBalance(address.toEthAddressStr, "0x" & blockNum.toHex) - echo r + let r3 = waitFor client.eth_getBalance(address.toEthAddressStr, "0x" & blockNum.toHex) + check r3 == 0 test "eth_estimateGas": let call = EthCall() blockNum = state.blockheader.blockNumber - var r = waitFor client.eth_estimateGas(call, "0x" & blockNum.toHex) - check r == 21_000 + r4 = waitFor client.eth_estimateGas(call, "0x" & blockNum.toHex) + check r4 == 21_000 rpcServer.stop() rpcServer.close()