mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-23 02:29:26 +00:00
implement more eth rpc
This commit is contained in:
parent
9c38266ba7
commit
f987e86562
@ -24,10 +24,6 @@ type
|
|||||||
currentBlock*: BlockNumber
|
currentBlock*: BlockNumber
|
||||||
highestBlock*: BlockNumber
|
highestBlock*: BlockNumber
|
||||||
|
|
||||||
#KeyType = enum
|
|
||||||
# blockNumberToHash
|
|
||||||
# blockHashToScore
|
|
||||||
#
|
|
||||||
TransactionKey = tuple
|
TransactionKey = tuple
|
||||||
blockNumber: BlockNumber
|
blockNumber: BlockNumber
|
||||||
index: int
|
index: int
|
||||||
@ -132,7 +128,7 @@ proc addBlockNumberToHashLookup*(self: BaseChainDB; header: BlockHeader) =
|
|||||||
self.db.put(blockNumberToHashKey(header.blockNumber).toOpenArray,
|
self.db.put(blockNumberToHashKey(header.blockNumber).toOpenArray,
|
||||||
rlp.encode(header.hash))
|
rlp.encode(header.hash))
|
||||||
|
|
||||||
proc persistTransactions*(self: BaseChainDB, blockNumber:
|
proc persistTransactions*(self: BaseChainDB, blockNumber:
|
||||||
BlockNumber, transactions: openArray[Transaction]): Hash256 =
|
BlockNumber, transactions: openArray[Transaction]): Hash256 =
|
||||||
var trie = initHexaryTrie(self.db)
|
var trie = initHexaryTrie(self.db)
|
||||||
for idx, tx in transactions:
|
for idx, tx in transactions:
|
||||||
@ -142,7 +138,14 @@ proc persistTransactions*(self: BaseChainDB, blockNumber:
|
|||||||
txKey: TransactionKey = (blockNumber, idx)
|
txKey: TransactionKey = (blockNumber, idx)
|
||||||
trie.put(rlp.encode(idx), encodedTx)
|
trie.put(rlp.encode(idx), encodedTx)
|
||||||
self.db.put(transactionHashToBlockKey(txHash).toOpenArray, rlp.encode(txKey))
|
self.db.put(transactionHashToBlockKey(txHash).toOpenArray, rlp.encode(txKey))
|
||||||
trie.rootHash
|
trie.rootHash
|
||||||
|
|
||||||
|
proc getTransaction*(self: BaseChainDB, txRoot: Hash256, txIndex: int, res: var Transaction): bool =
|
||||||
|
var db = initHexaryTrie(self.db, txRoot)
|
||||||
|
let txData = db.get(rlp.encode(txIndex))
|
||||||
|
if txData.len > 0:
|
||||||
|
res = rlp.decode(txData, Transaction)
|
||||||
|
result = true
|
||||||
|
|
||||||
iterator getBlockTransactionData*(self: BaseChainDB, transactionRoot: Hash256): seq[byte] =
|
iterator getBlockTransactionData*(self: BaseChainDB, transactionRoot: Hash256): seq[byte] =
|
||||||
var transactionDb = initHexaryTrie(self.db, transactionRoot)
|
var transactionDb = initHexaryTrie(self.db, transactionRoot)
|
||||||
@ -155,7 +158,11 @@ iterator getBlockTransactionData*(self: BaseChainDB, transactionRoot: Hash256):
|
|||||||
break
|
break
|
||||||
inc transactionIdx
|
inc transactionIdx
|
||||||
|
|
||||||
iterator getBlockTransactionHashes(self: BaseChainDB, blockHeader: BlockHeader): Hash256 =
|
iterator getBlockTransactions*(self: BaseChainDB, header: BlockHeader): Transaction =
|
||||||
|
for encodedTx in self.getBlockTransactionData(header.txRoot):
|
||||||
|
yield rlp.decode(encodedTx, Transaction)
|
||||||
|
|
||||||
|
iterator getBlockTransactionHashes*(self: BaseChainDB, blockHeader: BlockHeader): Hash256 =
|
||||||
## Returns an iterable of the transaction hashes from th block specified
|
## Returns an iterable of the transaction hashes from th block specified
|
||||||
## by the given block header.
|
## by the given block header.
|
||||||
for encodedTx in self.getBlockTransactionData(blockHeader.txRoot):
|
for encodedTx in self.getBlockTransactionData(blockHeader.txRoot):
|
||||||
@ -177,6 +184,12 @@ proc getUnclesCount*(self: BaseChainDB, ommersHash: Hash256): int =
|
|||||||
let r = rlpFromBytes(encodedUncles)
|
let r = rlpFromBytes(encodedUncles)
|
||||||
result = r.listLen
|
result = r.listLen
|
||||||
|
|
||||||
|
proc getUncles*(self: BaseChainDB, ommersHash: Hash256): seq[BlockHeader] =
|
||||||
|
if ommersHash != EMPTY_UNCLE_HASH:
|
||||||
|
let encodedUncles = self.db.get(genericHashKey(ommersHash).toOpenArray)
|
||||||
|
if encodedUncles.len != 0:
|
||||||
|
result = rlp.decode(encodedUncles, seq[BlockHeader])
|
||||||
|
|
||||||
proc getBlockBody*(self: BaseChainDB, blockHash: Hash256, output: var BlockBody): bool =
|
proc getBlockBody*(self: BaseChainDB, blockHash: Hash256, output: var BlockBody): bool =
|
||||||
var header: BlockHeader
|
var header: BlockHeader
|
||||||
if self.getBlockHeader(blockHash, header):
|
if self.getBlockHeader(blockHash, header):
|
||||||
@ -203,11 +216,22 @@ proc getUncleHashes*(self: BaseChainDB, blockHashes: openArray[Hash256]): seq[Ha
|
|||||||
for uncle in blockBody.uncles:
|
for uncle in blockBody.uncles:
|
||||||
result.add uncle.hash
|
result.add uncle.hash
|
||||||
|
|
||||||
|
proc getUncleHashes*(self: BaseChainDB, header: BlockHeader): seq[Hash256] =
|
||||||
|
if header.ommersHash != EMPTY_UNCLE_HASH:
|
||||||
|
let encodedUncles = self.db.get(genericHashKey(header.ommersHash).toOpenArray)
|
||||||
|
if encodedUncles.len != 0:
|
||||||
|
let uncles = rlp.decode(encodedUncles, seq[BlockHeader])
|
||||||
|
for x in uncles:
|
||||||
|
result.add x.hash
|
||||||
|
|
||||||
proc getTransactionKey*(self: BaseChainDB, transactionHash: Hash256): tuple[blockNumber: BlockNumber, index: int] {.inline.} =
|
proc getTransactionKey*(self: BaseChainDB, transactionHash: Hash256): tuple[blockNumber: BlockNumber, index: int] {.inline.} =
|
||||||
let
|
let tx = self.db.get(transactionHashToBlockKey(transactionHash).toOpenArray)
|
||||||
tx = self.db.get(transactionHashToBlockKey(transactionHash).toOpenArray)
|
|
||||||
key = rlp.decode(tx, TransactionKey)
|
if tx.len > 0:
|
||||||
return (key.blockNumber, key.index)
|
let key = rlp.decode(tx, TransactionKey)
|
||||||
|
result = (key.blockNumber, key.index)
|
||||||
|
else:
|
||||||
|
result = (0.toBlockNumber, -1)
|
||||||
|
|
||||||
proc removeTransactionFromCanonicalChain(self: BaseChainDB, transactionHash: Hash256) {.inline.} =
|
proc removeTransactionFromCanonicalChain(self: BaseChainDB, transactionHash: Hash256) {.inline.} =
|
||||||
## Removes the transaction specified by the given hash from the canonical chain.
|
## Removes the transaction specified by the given hash from the canonical chain.
|
||||||
|
@ -231,7 +231,6 @@ proc `%`*(value: whisper_protocol.Topic): JsonNode =
|
|||||||
proc `%`*(value: seq[byte]): JsonNode =
|
proc `%`*(value: seq[byte]): JsonNode =
|
||||||
result = %("0x" & value.toHex)
|
result = %("0x" & value.toHex)
|
||||||
|
|
||||||
|
|
||||||
# Helpers for the fromJson procs
|
# Helpers for the fromJson procs
|
||||||
|
|
||||||
proc toPublicKey*(key: string): PublicKey {.inline.} =
|
proc toPublicKey*(key: string): PublicKey {.inline.} =
|
||||||
@ -271,6 +270,13 @@ proc fromJson*(n: JsonNode, argName: string, result: var EthAddressStr) =
|
|||||||
raise newException(ValueError, invalidMsg(argName) & "\" as an Ethereum address \"" & hexStr & "\"")
|
raise newException(ValueError, invalidMsg(argName) & "\" as an Ethereum address \"" & hexStr & "\"")
|
||||||
result = hexStr.EthAddressStr
|
result = hexStr.EthAddressStr
|
||||||
|
|
||||||
|
proc fromJson*(n: JsonNode, argName: string, result: var EthAddress) =
|
||||||
|
n.kind.expect(JString, argName)
|
||||||
|
let hexStr = n.getStr()
|
||||||
|
if not hexStr.isValidEthAddress:
|
||||||
|
raise newException(ValueError, invalidMsg(argName) & "\" as an Ethereum address \"" & hexStr & "\"")
|
||||||
|
hexToByteArray(hexStr, result)
|
||||||
|
|
||||||
proc fromJson*(n: JsonNode, argName: string, result: var EthHashStr) =
|
proc fromJson*(n: JsonNode, argName: string, result: var EthHashStr) =
|
||||||
n.kind.expect(JString, argName)
|
n.kind.expect(JString, argName)
|
||||||
let hexStr = n.getStr()
|
let hexStr = n.getStr()
|
||||||
@ -336,3 +342,6 @@ proc fromJson*(n: JsonNode, argName: string, result: var Hash256) =
|
|||||||
if not hexStr.isValidHash256:
|
if not hexStr.isValidHash256:
|
||||||
raise newException(ValueError, invalidMsg(argName) & " as a Hash256 \"" & hexStr & "\"")
|
raise newException(ValueError, invalidMsg(argName) & " as a Hash256 \"" & hexStr & "\"")
|
||||||
hexToByteArray(hexStr, result.data)
|
hexToByteArray(hexStr, result.data)
|
||||||
|
|
||||||
|
proc fromJson*(n: JsonNode, argName: string, result: var JsonNode) =
|
||||||
|
result = n
|
||||||
|
@ -26,10 +26,6 @@ import
|
|||||||
type cast to avoid extra processing.
|
type cast to avoid extra processing.
|
||||||
]#
|
]#
|
||||||
|
|
||||||
# Work around for https://github.com/nim-lang/Nim/issues/8645
|
|
||||||
# proc `%`*(value: Time): JsonNode =
|
|
||||||
# result = %value.toUnix
|
|
||||||
|
|
||||||
proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB , server: RpcServer) =
|
proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB , server: RpcServer) =
|
||||||
|
|
||||||
proc getAccountDb(header: BlockHeader): ReadOnlyStateDB =
|
proc getAccountDb(header: BlockHeader): ReadOnlyStateDB =
|
||||||
@ -280,49 +276,18 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB , server: RpcServer) =
|
|||||||
callData = callData(call, false, chain)
|
callData = callData(call, false, chain)
|
||||||
result = estimateGas(callData, header, chain, call.gas.isSome)
|
result = estimateGas(callData, header, chain, call.gas.isSome)
|
||||||
|
|
||||||
#[
|
|
||||||
func populateBlockObject(header: BlockHeader, blockBody: BlockBody): BlockObject =
|
|
||||||
result.number = some(header.blockNumber)
|
|
||||||
result.hash = some(header.hash)
|
|
||||||
result.parentHash = header.parentHash
|
|
||||||
result.nonce = header.nonce.toUint
|
|
||||||
|
|
||||||
# Calculate hash for all uncle headers
|
|
||||||
var
|
|
||||||
rawdata = newSeq[byte](blockBody.uncles.len * 32)
|
|
||||||
startIdx = 0
|
|
||||||
for i in 0 ..< blockBody.uncles.len:
|
|
||||||
rawData[startIdx .. startIdx + 32] = blockBody.uncles[i].hash.data
|
|
||||||
startIdx += 32
|
|
||||||
result.sha3Uncles = keccakHash(rawData)
|
|
||||||
|
|
||||||
result.logsBloom = some(header.bloom)
|
|
||||||
result.transactionsRoot = header.txRoot
|
|
||||||
result.stateRoot = header.stateRoot
|
|
||||||
result.receiptsRoot = header.receiptRoot
|
|
||||||
result.miner = ZERO_ADDRESS # TODO: Get miner address
|
|
||||||
result.difficulty = header.difficulty
|
|
||||||
result.totalDifficulty = header.difficulty # TODO: Calculate
|
|
||||||
result.extraData = header.extraData
|
|
||||||
result.size = 0 # TODO: Calculate block size
|
|
||||||
result.gasLimit = header.gasLimit
|
|
||||||
result.gasUsed = header.gasUsed
|
|
||||||
result.timestamp = header.timeStamp
|
|
||||||
result.transactions = blockBody.transactions
|
|
||||||
result.uncles = @[]
|
|
||||||
for i in 0 ..< blockBody.uncles.len:
|
|
||||||
result.uncles[i] = blockBody.uncles[i].hash
|
|
||||||
|
|
||||||
server.rpc("eth_getBlockByHash") do(data: EthHashStr, fullTransactions: bool) -> Option[BlockObject]:
|
server.rpc("eth_getBlockByHash") do(data: EthHashStr, fullTransactions: bool) -> Option[BlockObject]:
|
||||||
## Returns information about a block by hash.
|
## Returns information about a block by hash.
|
||||||
##
|
##
|
||||||
## data: Hash of a block.
|
## data: Hash of a block.
|
||||||
## fullTransactions: If true it returns the full transaction objects, if false only the hashes of the transactions.
|
## fullTransactions: If true it returns the full transaction objects, if false only the hashes of the transactions.
|
||||||
## Returns BlockObject or nil when no block was found.
|
## Returns BlockObject or nil when no block was found.
|
||||||
let
|
var
|
||||||
h = data.toHash
|
header: BlockHeader
|
||||||
header = chain.getBlockHeader(h)
|
hash = data.toHash
|
||||||
result = some(populateBlockObject(header, getBlockBody(h)))
|
|
||||||
|
if chain.getBlockHeader(hash, header):
|
||||||
|
result = some(populateBlockObject(header, chain, fullTransactions))
|
||||||
|
|
||||||
server.rpc("eth_getBlockByNumber") do(quantityTag: string, fullTransactions: bool) -> Option[BlockObject]:
|
server.rpc("eth_getBlockByNumber") do(quantityTag: string, fullTransactions: bool) -> Option[BlockObject]:
|
||||||
## Returns information about a block by block number.
|
## Returns information about a block by block number.
|
||||||
@ -330,110 +295,72 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB , server: RpcServer) =
|
|||||||
## quantityTag: integer of a block number, or the string "earliest", "latest" or "pending", as in the default block parameter.
|
## quantityTag: integer of a block number, or the string "earliest", "latest" or "pending", as in the default block parameter.
|
||||||
## fullTransactions: If true it returns the full transaction objects, if false only the hashes of the transactions.
|
## fullTransactions: If true it returns the full transaction objects, if false only the hashes of the transactions.
|
||||||
## Returns BlockObject or nil when no block was found.
|
## Returns BlockObject or nil when no block was found.
|
||||||
let
|
try:
|
||||||
header = chain.headerFromTag(quantityTag)
|
let header = chain.headerFromTag(quantityTag)
|
||||||
|
result = some(populateBlockObject(header, chain, fullTransactions))
|
||||||
|
except:
|
||||||
|
result = none(BlockObject)
|
||||||
|
|
||||||
result = some(populateBlockObject(header, getBlockBody(header.hash)))
|
server.rpc("eth_getTransactionByHash") do(data: EthHashStr) -> Option[TransactionObject]:
|
||||||
|
|
||||||
proc populateTransactionObject(transaction: Transaction, txIndex: int64, blockHeader: BlockHeader, blockHash: Hash256): TransactionObject =
|
|
||||||
let
|
|
||||||
# TODO: header.stateRoot to prevStateRoot?
|
|
||||||
vmState = newBaseVMState(blockHeader.stateRoot, blockHeader, chain)
|
|
||||||
accountDb = vmState.readOnlyStateDB()
|
|
||||||
address = transaction.getSender()
|
|
||||||
txCount = accountDb.getNonce(address)
|
|
||||||
txHash = transaction.rlpHash
|
|
||||||
accountGas = accountDb.balance(address)
|
|
||||||
|
|
||||||
result.hash = txHash
|
|
||||||
result.nonce = txCount
|
|
||||||
result.blockHash = some(blockHash)
|
|
||||||
result.blockNumber = some(blockHeader.blockNumber)
|
|
||||||
result.transactionIndex = some(txIndex)
|
|
||||||
result.source = transaction.getSender()
|
|
||||||
result.to = some(transaction.to)
|
|
||||||
result.value = transaction.value
|
|
||||||
result.gasPrice = transaction.gasPrice
|
|
||||||
result.gas = accountGas
|
|
||||||
result.input = transaction.payload
|
|
||||||
|
|
||||||
server.rpc("eth_getTransactionByHash") do(data: EthHashStr) -> TransactionObject:
|
|
||||||
## Returns the information about a transaction requested by transaction hash.
|
## Returns the information about a transaction requested by transaction hash.
|
||||||
##
|
##
|
||||||
## data: hash of a transaction.
|
## data: hash of a transaction.
|
||||||
## Returns requested transaction information.
|
## Returns requested transaction information.
|
||||||
let
|
let txDetails = chain.getTransactionKey(data.toHash())
|
||||||
h = data.toHash()
|
if txDetails.index < 0:
|
||||||
txDetails = chain.getTransactionKey(h)
|
return none(TransactionObject)
|
||||||
header = chain.getBlockHeader(txDetails.blockNumber)
|
|
||||||
blockHash = chain.getBlockHash(txDetails.blockNumber)
|
let header = chain.getBlockHeader(txDetails.blockNumber)
|
||||||
transaction = getBlockBody(blockHash).transactions[txDetails.index]
|
var tx: Transaction
|
||||||
result = populateTransactionObject(transaction, txDetails.index, header, blockHash)
|
if chain.getTransaction(header.txRoot, txDetails.index, tx):
|
||||||
|
result = some(populateTransactionObject(tx, header, txDetails.index))
|
||||||
|
|
||||||
# TODO: if the requested transaction not in blockchain
|
# TODO: if the requested transaction not in blockchain
|
||||||
# try to look for pending transaction in txpool
|
# try to look for pending transaction in txpool
|
||||||
|
|
||||||
server.rpc("eth_getTransactionByBlockHashAndIndex") do(data: EthHashStr, quantity: int) -> TransactionObject:
|
server.rpc("eth_getTransactionByBlockHashAndIndex") do(data: EthHashStr, quantity: HexQuantityStr) -> Option[TransactionObject]:
|
||||||
## Returns information about a transaction by block hash and transaction index position.
|
## Returns information about a transaction by block hash and transaction index position.
|
||||||
##
|
##
|
||||||
## data: hash of a block.
|
## data: hash of a block.
|
||||||
## quantity: integer of the transaction index position.
|
## quantity: integer of the transaction index position.
|
||||||
## Returns requested transaction information.
|
## Returns requested transaction information.
|
||||||
let
|
let index = hexToInt(quantity.string, int)
|
||||||
blockHash = data.toHash()
|
var header: BlockHeader
|
||||||
header = chain.getBlockHeader(blockHash)
|
if not chain.getBlockHeader(data.toHash(), header):
|
||||||
transaction = getBlockBody(blockHash).transactions[quantity]
|
return none(TransactionObject)
|
||||||
result = populateTransactionObject(transaction, quantity, header, blockHash)
|
|
||||||
|
|
||||||
server.rpc("eth_getTransactionByBlockNumberAndIndex") do(quantityTag: string, quantity: int) -> TransactionObject:
|
var tx: Transaction
|
||||||
|
if chain.getTransaction(header.txRoot, index, tx):
|
||||||
|
result = some(populateTransactionObject(tx, header, index))
|
||||||
|
|
||||||
|
server.rpc("eth_getTransactionByBlockNumberAndIndex") do(quantityTag: string, quantity: HexQuantityStr) -> Option[TransactionObject]:
|
||||||
## Returns information about a transaction by block number and transaction index position.
|
## Returns information about a transaction by block number and transaction index position.
|
||||||
##
|
##
|
||||||
## quantityTag: a block number, or the string "earliest", "latest" or "pending", as in the default block parameter.
|
## quantityTag: a block number, or the string "earliest", "latest" or "pending", as in the default block parameter.
|
||||||
## quantity: the transaction index position.
|
## quantity: the transaction index position.
|
||||||
let
|
let
|
||||||
header = chain.headerFromTag(quantityTag)
|
header = chain.headerFromTag(quantityTag)
|
||||||
blockHash = header.hash
|
index = hexToInt(quantity.string, int)
|
||||||
transaction = getBlockBody(blockHash).transactions[quantity]
|
|
||||||
result = populateTransactionObject(transaction, quantity, header, blockHash)
|
|
||||||
|
|
||||||
proc populateReceipt(receipt: Receipt, gasUsed: GasInt, tx: Transaction, txIndex: int, blockHeader: BlockHeader): ReceiptObject =
|
var tx: Transaction
|
||||||
result.transactionHash = tx.rlpHash
|
if chain.getTransaction(header.txRoot, index, tx):
|
||||||
result.transactionIndex = txIndex
|
result = some(populateTransactionObject(tx, header, index))
|
||||||
result.blockHash = blockHeader.hash
|
|
||||||
result.blockNumber = blockHeader.blockNumber
|
|
||||||
result.sender = tx.getSender()
|
|
||||||
result.to = some(tx.to)
|
|
||||||
result.cumulativeGasUsed = receipt.cumulativeGasUsed
|
|
||||||
result.gasUsed = gasUsed
|
|
||||||
|
|
||||||
if tx.isContractCreation:
|
server.rpc("eth_getTransactionReceipt") do(data: EthHashStr) -> Option[ReceiptObject]:
|
||||||
var sender: EthAddress
|
|
||||||
if tx.getSender(sender):
|
|
||||||
let contractAddress = generateAddress(sender, tx.accountNonce)
|
|
||||||
result.contractAddress = some(contractAddress)
|
|
||||||
else:
|
|
||||||
doAssert(false)
|
|
||||||
else:
|
|
||||||
result.contractAddress = none(EthAddress)
|
|
||||||
|
|
||||||
result.logs = receipt.logs
|
|
||||||
result.logsBloom = receipt.bloom
|
|
||||||
# post-transaction stateroot (pre Byzantium).
|
|
||||||
if receipt.hasStateRoot:
|
|
||||||
result.root = some(receipt.stateRoot)
|
|
||||||
else:
|
|
||||||
# 1 = success, 0 = failure.
|
|
||||||
result.status = some(receipt.status)
|
|
||||||
|
|
||||||
server.rpc("eth_getTransactionReceipt") do(data: EthHashStr) -> ReceiptObject:
|
|
||||||
## Returns the receipt of a transaction by transaction hash.
|
## Returns the receipt of a transaction by transaction hash.
|
||||||
##
|
##
|
||||||
## data: hash of a transaction.
|
## data: hash of a transaction.
|
||||||
## Returns transaction receipt.
|
## Returns transaction receipt.
|
||||||
let
|
|
||||||
h = data.toHash
|
let txDetails = chain.getTransactionKey(data.toHash())
|
||||||
txDetails = chain.getTransactionKey(h)
|
if txDetails.index < 0:
|
||||||
header = chain.getBlockHeader(txDetails.blockNumber)
|
return none(ReceiptObject)
|
||||||
body = getBlockBody(header.hash)
|
|
||||||
|
let header = chain.getBlockHeader(txDetails.blockNumber)
|
||||||
|
var tx: Transaction
|
||||||
|
if not chain.getTransaction(header.txRoot, txDetails.index, tx):
|
||||||
|
return none(ReceiptObject)
|
||||||
|
|
||||||
var
|
var
|
||||||
idx = 0
|
idx = 0
|
||||||
prevGasUsed = GasInt(0)
|
prevGasUsed = GasInt(0)
|
||||||
@ -442,37 +369,47 @@ proc setupEthRpc*(node: EthereumNode, chain: BaseChainDB , server: RpcServer) =
|
|||||||
let gasUsed = receipt.cumulativeGasUsed - prevGasUsed
|
let gasUsed = receipt.cumulativeGasUsed - prevGasUsed
|
||||||
prevGasUsed = receipt.cumulativeGasUsed
|
prevGasUsed = receipt.cumulativeGasUsed
|
||||||
if idx == txDetails.index:
|
if idx == txDetails.index:
|
||||||
return populateReceipt(receipt, gasUsed, body.transactions[txDetails.index], txDetails.index, header)
|
return some(populateReceipt(receipt, gasUsed, tx, txDetails.index, header))
|
||||||
idx.inc
|
idx.inc
|
||||||
|
|
||||||
server.rpc("eth_getUncleByBlockHashAndIndex") do(data: EthHashStr, quantity: int) -> Option[BlockObject]:
|
server.rpc("eth_getUncleByBlockHashAndIndex") do(data: EthHashStr, quantity: HexQuantityStr) -> Option[BlockObject]:
|
||||||
## Returns information about a uncle of a block by hash and uncle index position.
|
## Returns information about a uncle of a block by hash and uncle index position.
|
||||||
##
|
##
|
||||||
## data: hash of block.
|
## data: hash of block.
|
||||||
## quantity: the uncle's index position.
|
## quantity: the uncle's index position.
|
||||||
## Returns BlockObject or nil when no block was found.
|
## Returns BlockObject or nil when no block was found.
|
||||||
let
|
let index = hexToInt(quantity.string, int)
|
||||||
blockHash = data.toHash()
|
var header: BlockHeader
|
||||||
body = getBlockBody(blockHash)
|
if not chain.getBlockHeader(data.toHash(), header):
|
||||||
if quantity < 0 or quantity >= body.uncles.len:
|
return none(BlockObject)
|
||||||
raise newException(ValueError, "Uncle index out of range")
|
|
||||||
let uncle = body.uncles[quantity]
|
|
||||||
result = some(populateBlockObject(uncle, body))
|
|
||||||
|
|
||||||
server.rpc("eth_getUncleByBlockNumberAndIndex") do(quantityTag: string, quantity: int) -> Option[BlockObject]:
|
let uncles = chain.getUncles(header.ommersHash)
|
||||||
|
if index < 0 or index >= uncles.len:
|
||||||
|
return none(BlockObject)
|
||||||
|
|
||||||
|
var uncle = populateBlockObject(uncles[index], chain, false, true)
|
||||||
|
uncle.totalDifficulty = encodeQuantity(chain.getScore(header.hash))
|
||||||
|
result = some(uncle)
|
||||||
|
|
||||||
|
server.rpc("eth_getUncleByBlockNumberAndIndex") do(quantityTag: string, quantity: HexQuantityStr) -> Option[BlockObject]:
|
||||||
# Returns information about a uncle of a block by number and uncle index position.
|
# Returns information about a uncle of a block by number and uncle index position.
|
||||||
##
|
##
|
||||||
## quantityTag: a block number, or the string "earliest", "latest" or "pending", as in the default block parameter.
|
## quantityTag: a block number, or the string "earliest", "latest" or "pending", as in the default block parameter.
|
||||||
## quantity: the uncle's index position.
|
## quantity: the uncle's index position.
|
||||||
## Returns BlockObject or nil when no block was found.
|
## Returns BlockObject or nil when no block was found.
|
||||||
let
|
let
|
||||||
|
index = hexToInt(quantity.string, int)
|
||||||
header = chain.headerFromTag(quantityTag)
|
header = chain.headerFromTag(quantityTag)
|
||||||
body = getBlockBody(header.hash)
|
uncles = chain.getUncles(header.ommersHash)
|
||||||
if quantity < 0 or quantity >= body.uncles.len:
|
|
||||||
raise newException(ValueError, "Uncle index out of range")
|
|
||||||
let uncle = body.uncles[quantity]
|
|
||||||
result = some(populateBlockObject(uncle, body))
|
|
||||||
|
|
||||||
|
if index < 0 or index >= uncles.len:
|
||||||
|
return none(BlockObject)
|
||||||
|
|
||||||
|
var uncle = populateBlockObject(uncles[index], chain, false, true)
|
||||||
|
uncle.totalDifficulty = encodeQuantity(chain.getScore(header.hash))
|
||||||
|
result = some(uncle)
|
||||||
|
|
||||||
|
#[
|
||||||
server.rpc("eth_newFilter") do(filterOptions: FilterOptions) -> int:
|
server.rpc("eth_newFilter") do(filterOptions: FilterOptions) -> int:
|
||||||
## Creates a filter object, based on filter options, to notify when the state changes (logs).
|
## Creates a filter object, based on filter options, to notify when the state changes (logs).
|
||||||
## To check if the state has changed, call eth_getFilterChanges.
|
## To check if the state has changed, call eth_getFilterChanges.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import
|
import
|
||||||
hexstrings, options, eth/[common, keys, rlp],
|
hexstrings, options, eth/[common, keys, rlp], json,
|
||||||
eth/p2p/rlpx_protocols/whisper_protocol
|
eth/p2p/rlpx_protocols/whisper_protocol
|
||||||
|
|
||||||
#[
|
#[
|
||||||
@ -43,39 +43,42 @@ type
|
|||||||
## Note that this includes slightly different information from eth/common.BlockHeader
|
## Note that this includes slightly different information from eth/common.BlockHeader
|
||||||
BlockObject* = object
|
BlockObject* = object
|
||||||
# Returned to user
|
# Returned to user
|
||||||
number*: Option[BlockNumber] # the block number. null when its pending block.
|
number*: Option[HexQuantityStr] # the block number. null when its pending block.
|
||||||
hash*: Option[Hash256] # hash of the block. null when its pending block.
|
hash*: Option[Hash256] # hash of the block. null when its pending block.
|
||||||
parentHash*: Hash256 # hash of the parent block.
|
parentHash*: Hash256 # hash of the parent block.
|
||||||
nonce*: uint64 # hash of the generated proof-of-work. null when its pending block.
|
nonce*: Option[HexDataStr] # hash of the generated proof-of-work. null when its pending block.
|
||||||
sha3Uncles*: Hash256 # SHA3 of the uncles data in the block.
|
sha3Uncles*: Hash256 # SHA3 of the uncles data in the block.
|
||||||
logsBloom*: Option[BloomFilter] # the bloom filter for the logs of the block. null when its pending block.
|
logsBloom*: Option[BloomFilter] # the bloom filter for the logs of the block. null when its pending block.
|
||||||
transactionsRoot*: Hash256 # the root of the transaction trie of the block.
|
transactionsRoot*: Hash256 # the root of the transaction trie of the block.
|
||||||
stateRoot*: Hash256 # the root of the final state trie of the block.
|
stateRoot*: Hash256 # the root of the final state trie of the block.
|
||||||
receiptsRoot*: Hash256 # the root of the receipts trie of the block.
|
receiptsRoot*: Hash256 # the root of the receipts trie of the block.
|
||||||
miner*: EthAddress # the address of the beneficiary to whom the mining rewards were given.
|
miner*: EthAddress # the address of the beneficiary to whom the mining rewards were given.
|
||||||
difficulty*: UInt256 # integer of the difficulty for this block.
|
difficulty*: HexQuantityStr # integer of the difficulty for this block.
|
||||||
totalDifficulty*: UInt256 # integer of the total difficulty of the chain until this block.
|
totalDifficulty*: HexQuantityStr# integer of the total difficulty of the chain until this block.
|
||||||
extraData*: Blob # the "extra data" field of this block.
|
extraData*: HexDataStr # the "extra data" field of this block.
|
||||||
size*: int # integer the size of this block in bytes.
|
size*: HexQuantityStr # integer the size of this block in bytes.
|
||||||
gasLimit*: GasInt # the maximum gas allowed in this block.
|
gasLimit*: HexQuantityStr # the maximum gas allowed in this block.
|
||||||
gasUsed*: GasInt # the total used gas by all transactions in this block.
|
gasUsed*: HexQuantityStr # the total used gas by all transactions in this block.
|
||||||
timestamp*: EthTime # the unix timestamp for when the block was collated.
|
timestamp*: HexQuantityStr # the unix timestamp for when the block was collated.
|
||||||
transactions*: seq[Transaction] # list of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.
|
transactions*: seq[JsonNode] # list of transaction objects, or 32 Bytes transaction hashes depending on the last given parameter.
|
||||||
uncles*: seq[Hash256] # list of uncle hashes.
|
uncles*: seq[Hash256] # list of uncle hashes.
|
||||||
|
|
||||||
TransactionObject* = object # A transaction object, or null when no transaction was found:
|
TransactionObject* = object # A transaction object, or null when no transaction was found:
|
||||||
# Returned to user
|
# Returned to user
|
||||||
hash*: Hash256 # hash of the transaction.
|
|
||||||
nonce*: AccountNonce # the number of transactions made by the sender prior to this one.
|
|
||||||
blockHash*: Option[Hash256] # hash of the block where this transaction was in. null when its pending.
|
blockHash*: Option[Hash256] # hash of the block where this transaction was in. null when its pending.
|
||||||
blockNumber*: Option[BlockNumber] # block number where this transaction was in. null when its pending.
|
blockNumber*: Option[HexQuantityStr] # block number where this transaction was in. null when its pending.
|
||||||
transactionIndex*: Option[int64] # integer of the transactions index position in the block. null when its pending.
|
`from`*: EthAddress # address of the sender.
|
||||||
source*: EthAddress # address of the sender.
|
gas*: HexQuantityStr # gas provided by the sender.
|
||||||
to*: Option[EthAddress] # address of the receiver. null when its a contract creation transaction.
|
gasPrice*: HexQuantityStr # gas price provided by the sender in Wei.
|
||||||
value*: UInt256 # value transferred in Wei.
|
hash*: Hash256 # hash of the transaction.
|
||||||
gasPrice*: GasInt # gas price provided by the sender in Wei.
|
|
||||||
gas*: GasInt # gas provided by the sender.
|
|
||||||
input*: Blob # the data send along with the transaction.
|
input*: Blob # the data send along with the transaction.
|
||||||
|
nonce*: HexQuantityStr # the number of transactions made by the sender prior to this one.
|
||||||
|
to*: Option[EthAddress] # address of the receiver. null when its a contract creation transaction.
|
||||||
|
transactionIndex*: Option[HexQuantityStr] # integer of the transactions index position in the block. null when its pending.
|
||||||
|
value*: HexQuantityStr # value transferred in Wei.
|
||||||
|
v*: HexQuantityStr # ECDSA recovery id
|
||||||
|
r*: HexQuantityStr # 32 Bytes - ECDSA signature r
|
||||||
|
s*: HexQuantityStr # 32 Bytes - ECDSA signature s
|
||||||
|
|
||||||
FilterLog* = object
|
FilterLog* = object
|
||||||
# Returned to user
|
# Returned to user
|
||||||
@ -94,13 +97,13 @@ type
|
|||||||
ReceiptObject* = object
|
ReceiptObject* = object
|
||||||
# A transaction receipt object, or null when no receipt was found:
|
# A transaction receipt object, or null when no receipt was found:
|
||||||
transactionHash*: Hash256 # hash of the transaction.
|
transactionHash*: Hash256 # hash of the transaction.
|
||||||
transactionIndex*: int # integer of the transactions index position in the block.
|
transactionIndex*: HexQuantityStr # integer of the transactions index position in the block.
|
||||||
blockHash*: Hash256 # hash of the block where this transaction was in.
|
blockHash*: Hash256 # hash of the block where this transaction was in.
|
||||||
blockNumber*: BlockNumber # block number where this transaction was in.
|
blockNumber*: HexQuantityStr # block number where this transaction was in.
|
||||||
sender*: EthAddress # address of the sender.
|
`from`*: EthAddress # address of the sender.
|
||||||
to*: Option[EthAddress] # address of the receiver. null when its a contract creation transaction.
|
to*: Option[EthAddress] # address of the receiver. null when its a contract creation transaction.
|
||||||
cumulativeGasUsed*: GasInt # the total amount of gas used when this transaction was executed in the block.
|
cumulativeGasUsed*: HexQuantityStr # the total amount of gas used when this transaction was executed in the block.
|
||||||
gasUsed*: GasInt # the amount of gas used by this specific transaction alone.
|
gasUsed*: HexQuantityStr # the amount of gas used by this specific transaction alone.
|
||||||
contractAddress*: Option[EthAddress] # the contract address created, if the transaction was a contract creation, otherwise null.
|
contractAddress*: Option[EthAddress] # the contract address created, if the transaction was a contract creation, otherwise null.
|
||||||
logs*: seq[Log] # list of log objects which this transaction generated.
|
logs*: seq[Log] # list of log objects which this transaction generated.
|
||||||
logsBloom*: BloomFilter # bloom filter for light clients to quickly retrieve related logs.
|
logsBloom*: BloomFilter # bloom filter for light clients to quickly retrieve related logs.
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
# those terms.
|
# those terms.
|
||||||
|
|
||||||
import hexstrings, eth/[common, rlp, keys, trie/db], stew/byteutils, nimcrypto,
|
import hexstrings, eth/[common, rlp, keys, trie/db], stew/byteutils, nimcrypto,
|
||||||
../db/[db_chain, accounts_cache], strutils, algorithm, options,
|
../db/[db_chain, accounts_cache], strutils, algorithm, options, times, json,
|
||||||
../constants, stint, hexstrings, rpc_types, ../config,
|
../constants, stint, hexstrings, rpc_types, ../config,
|
||||||
../vm_state_transactions, ../vm_state, ../vm_types, ../vm/interpreter/vm_forks,
|
../vm_state_transactions, ../vm_state, ../vm_types, ../vm/interpreter/vm_forks,
|
||||||
../vm/computation, ../p2p/executor
|
../vm/computation, ../p2p/executor, ../utils, ../transaction
|
||||||
|
|
||||||
type
|
type
|
||||||
UnsignedTx* = object
|
UnsignedTx* = object
|
||||||
@ -242,4 +242,87 @@ proc estimateGas*(call: CallData, header: BlockHeader, chain: BaseChainDB, haveG
|
|||||||
let gasUsed = processTransaction(tx, call.source, vmState, fork)
|
let gasUsed = processTransaction(tx, call.source, vmState, fork)
|
||||||
result = encodeQuantity(gasUsed.uint64)
|
result = encodeQuantity(gasUsed.uint64)
|
||||||
dbTx.dispose()
|
dbTx.dispose()
|
||||||
# TODO: handle revert and error
|
# TODO: handle revert and error
|
||||||
|
|
||||||
|
proc populateTransactionObject*(tx: Transaction, header: BlockHeader, txIndex: int): TransactionObject =
|
||||||
|
result.blockHash = some(header.hash)
|
||||||
|
result.blockNumber = some(encodeQuantity(header.blockNumber))
|
||||||
|
result.`from` = tx.getSender()
|
||||||
|
result.gas = encodeQuantity(tx.gasLimit.uint64)
|
||||||
|
result.gasPrice = encodeQuantity(tx.gasPrice.uint64)
|
||||||
|
result.hash = tx.rlpHash
|
||||||
|
result.input = tx.payLoad
|
||||||
|
result.nonce = encodeQuantity(tx.accountNonce.uint64)
|
||||||
|
if not tx.isContractCreation:
|
||||||
|
result.to = some(tx.to)
|
||||||
|
result.transactionIndex = some(encodeQuantity(txIndex.uint64))
|
||||||
|
result.value = encodeQuantity(tx.value)
|
||||||
|
result.v = encodeQuantity(tx.V.uint)
|
||||||
|
result.r = encodeQuantity(tx.R)
|
||||||
|
result.s = encodeQuantity(tx.S)
|
||||||
|
|
||||||
|
proc populateBlockObject*(header: BlockHeader, chain: BaseChainDB, fullTx: bool, isUncle = false): BlockObject =
|
||||||
|
let blockHash = header.blockHash
|
||||||
|
|
||||||
|
result.number = some(encodeQuantity(header.blockNumber))
|
||||||
|
result.hash = some(blockHash)
|
||||||
|
result.parentHash = header.parentHash
|
||||||
|
result.nonce = some(hexDataStr(header.nonce))
|
||||||
|
result.sha3Uncles = header.ommersHash
|
||||||
|
result.logsBloom = some(header.bloom)
|
||||||
|
result.transactionsRoot = header.txRoot
|
||||||
|
result.stateRoot = header.stateRoot
|
||||||
|
result.receiptsRoot = header.receiptRoot
|
||||||
|
result.miner = header.coinbase
|
||||||
|
result.difficulty = encodeQuantity(header.difficulty)
|
||||||
|
result.extraData = hexDataStr(header.extraData)
|
||||||
|
|
||||||
|
# discard sizeof(seq[byte]) of extraData and use actual length
|
||||||
|
let size = sizeof(BlockHeader) - sizeof(Blob) + header.extraData.len
|
||||||
|
result.size = encodeQuantity(size.uint)
|
||||||
|
|
||||||
|
result.gasLimit = encodeQuantity(header.gasLimit.uint64)
|
||||||
|
result.gasUsed = encodeQuantity(header.gasUsed.uint64)
|
||||||
|
result.timestamp = encodeQuantity(header.timeStamp.toUnix.uint64)
|
||||||
|
|
||||||
|
if not isUncle:
|
||||||
|
result.totalDifficulty = encodeQuantity(chain.getScore(blockHash))
|
||||||
|
result.uncles = chain.getUncleHashes(header)
|
||||||
|
|
||||||
|
if fullTx:
|
||||||
|
var i = 0
|
||||||
|
for tx in chain.getBlockTransactions(header):
|
||||||
|
result.transactions.add %(populateTransactionObject(tx, header, i))
|
||||||
|
inc i
|
||||||
|
else:
|
||||||
|
for x in chain.getBlockTransactionHashes(header):
|
||||||
|
result.transactions.add %(x)
|
||||||
|
|
||||||
|
proc populateReceipt*(receipt: Receipt, gasUsed: GasInt, tx: Transaction, txIndex: int, header: BlockHeader): ReceiptObject =
|
||||||
|
result.transactionHash = tx.rlpHash
|
||||||
|
result.transactionIndex = encodeQuantity(txIndex.uint)
|
||||||
|
result.blockHash = header.hash
|
||||||
|
result.blockNumber = encodeQuantity(header.blockNumber)
|
||||||
|
result.`from` = tx.getSender()
|
||||||
|
|
||||||
|
if tx.isContractCreation:
|
||||||
|
result.to = some(tx.to)
|
||||||
|
|
||||||
|
result.cumulativeGasUsed = encodeQuantity(receipt.cumulativeGasUsed.uint64)
|
||||||
|
result.gasUsed = encodeQuantity(gasUsed.uint64)
|
||||||
|
|
||||||
|
if tx.isContractCreation:
|
||||||
|
var sender: EthAddress
|
||||||
|
if tx.getSender(sender):
|
||||||
|
let contractAddress = generateAddress(sender, tx.accountNonce)
|
||||||
|
result.contractAddress = some(contractAddress)
|
||||||
|
|
||||||
|
result.logs = receipt.logs
|
||||||
|
result.logsBloom = receipt.bloom
|
||||||
|
|
||||||
|
# post-transaction stateroot (pre Byzantium).
|
||||||
|
if receipt.hasStateRoot:
|
||||||
|
result.root = some(receipt.stateRoot)
|
||||||
|
else:
|
||||||
|
# 1 = success, 0 = failure.
|
||||||
|
result.status = some(receipt.status)
|
||||||
|
@ -40,15 +40,14 @@ proc eth_sendTransaction(data: TxSend): EthHashStr
|
|||||||
proc eth_sendRawTransaction(data: HexDataStr): EthHashStr
|
proc eth_sendRawTransaction(data: HexDataStr): EthHashStr
|
||||||
proc eth_call(call: EthCall, quantityTag: string): HexDataStr
|
proc eth_call(call: EthCall, quantityTag: string): HexDataStr
|
||||||
proc eth_estimateGas(call: EthCall, quantityTag: string): HexQuantityStr
|
proc eth_estimateGas(call: EthCall, quantityTag: string): HexQuantityStr
|
||||||
|
proc eth_getBlockByHash(data: Hash256, fullTransactions: bool): Option[BlockObject]
|
||||||
proc eth_getBlockByHash(data: Hash256, fullTransactions: bool): BlockObject
|
proc eth_getBlockByNumber(quantityTag: string, fullTransactions: bool): Option[BlockObject]
|
||||||
proc eth_getBlockByNumber(quantityTag: string, fullTransactions: bool): BlockObject
|
proc eth_getTransactionByHash(data: Hash256): Option[TransactionObject]
|
||||||
proc eth_getTransactionByHash(data: Hash256): TransactionObject
|
proc eth_getTransactionByBlockHashAndIndex(data: Hash256, quantity: HexQuantityStr): Option[TransactionObject]
|
||||||
proc eth_getTransactionByBlockHashAndIndex(data: Hash256, quantity: int): TransactionObject
|
proc eth_getTransactionByBlockNumberAndIndex(quantityTag: string, quantity: HexQuantityStr): Option[TransactionObject]
|
||||||
proc eth_getTransactionByBlockNumberAndIndex(quantityTag: string, quantity: int): TransactionObject
|
proc eth_getTransactionReceipt(data: Hash256): Option[ReceiptObject]
|
||||||
proc eth_getTransactionReceipt(data: Hash256): ReceiptObject
|
proc eth_getUncleByBlockHashAndIndex(data: Hash256, quantity: HexQuantityStr): Option[BlockObject]
|
||||||
proc eth_getUncleByBlockHashAndIndex(data: Hash256, quantity: int64): BlockObject
|
proc eth_getUncleByBlockNumberAndIndex(quantityTag: string, quantity: HexQuantityStr): Option[BlockObject]
|
||||||
proc eth_getUncleByBlockNumberAndIndex(quantityTag: string, quantity: int64): BlockObject
|
|
||||||
|
|
||||||
#[
|
#[
|
||||||
proc eth_getCompilers(): seq[string]
|
proc eth_getCompilers(): seq[string]
|
||||||
|
@ -30,7 +30,12 @@ template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
|
|||||||
const sigPath = &"{sourceDir}{DirSep}rpcclient{DirSep}ethcallsigs.nim"
|
const sigPath = &"{sourceDir}{DirSep}rpcclient{DirSep}ethcallsigs.nim"
|
||||||
createRpcSigs(RpcSocketClient, sigPath)
|
createRpcSigs(RpcSocketClient, sigPath)
|
||||||
|
|
||||||
proc setupEnv(chain: BaseChainDB, signer, ks2: EthAddress, conf: NimbusConfiguration) =
|
type
|
||||||
|
TestEnv = object
|
||||||
|
txHash: Hash256
|
||||||
|
blockHash: HAsh256
|
||||||
|
|
||||||
|
proc setupEnv(chain: BaseChainDB, signer, ks2: EthAddress, conf: NimbusConfiguration): TestEnv =
|
||||||
var
|
var
|
||||||
parent = chain.getCanonicalHead()
|
parent = chain.getCanonicalHead()
|
||||||
ac = newAccountStateDB(chain.db, parent.stateRoot, chain.pruneTrie)
|
ac = newAccountStateDB(chain.db, parent.stateRoot, chain.pruneTrie)
|
||||||
@ -84,9 +89,8 @@ proc setupEnv(chain: BaseChainDB, signer, ks2: EthAddress, conf: NimbusConfigura
|
|||||||
timeStamp = date.toTime
|
timeStamp = date.toTime
|
||||||
difficulty = calcDifficulty(chain.config, timeStamp, parent)
|
difficulty = calcDifficulty(chain.config, timeStamp, parent)
|
||||||
|
|
||||||
let header = BlockHeader(
|
var header = BlockHeader(
|
||||||
parentHash : parentHash,
|
parentHash : parentHash,
|
||||||
#ommersHash*: Hash256
|
|
||||||
#coinbase*: EthAddress
|
#coinbase*: EthAddress
|
||||||
stateRoot : vmState.accountDb.rootHash,
|
stateRoot : vmState.accountDb.rootHash,
|
||||||
txRoot : txRoot,
|
txRoot : txRoot,
|
||||||
@ -102,7 +106,15 @@ proc setupEnv(chain: BaseChainDB, signer, ks2: EthAddress, conf: NimbusConfigura
|
|||||||
#nonce: BlockNonce
|
#nonce: BlockNonce
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let uncles = [header]
|
||||||
|
header.ommersHash = chain.persistUncles(uncles)
|
||||||
|
|
||||||
discard chain.persistHeaderToDb(header)
|
discard chain.persistHeaderToDb(header)
|
||||||
|
result = TestEnv(
|
||||||
|
txHash: signedTx1.rlpHash,
|
||||||
|
blockHash: header.hash
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
proc doTests {.async.} =
|
proc doTests {.async.} =
|
||||||
# TODO: Include other transports such as Http
|
# TODO: Include other transports such as Http
|
||||||
@ -131,7 +143,7 @@ proc doTests {.async.} =
|
|||||||
|
|
||||||
defaultGenesisBlockForNetwork(conf.net.networkId.toPublicNetwork()).commit(chain)
|
defaultGenesisBlockForNetwork(conf.net.networkId.toPublicNetwork()).commit(chain)
|
||||||
doAssert(canonicalHeadHashKey().toOpenArray in chain.db)
|
doAssert(canonicalHeadHashKey().toOpenArray in chain.db)
|
||||||
setupEnv(chain, signer, ks2, conf)
|
let env = setupEnv(chain, signer, ks2, conf)
|
||||||
|
|
||||||
# Create Ethereum RPCs
|
# Create Ethereum RPCs
|
||||||
let RPC_PORT = 8545
|
let RPC_PORT = 8545
|
||||||
@ -321,6 +333,73 @@ proc doTests {.async.} =
|
|||||||
let res = await client.eth_estimateGas(ec, "latest")
|
let res = await client.eth_estimateGas(ec, "latest")
|
||||||
check hexToInt(res.string, int) == 21000
|
check hexToInt(res.string, int) == 21000
|
||||||
|
|
||||||
|
test "eth_getBlockByHash":
|
||||||
|
let res = await client.eth_getBlockByHash(env.blockHash, true)
|
||||||
|
check res.isSome
|
||||||
|
check res.get().hash.get() == env.blockHash
|
||||||
|
let res2 = await client.eth_getBlockByHash(env.txHash, true)
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
test "eth_getBlockByNumber":
|
||||||
|
let res = await client.eth_getBlockByNumber("latest", true)
|
||||||
|
check res.isSome
|
||||||
|
check res.get().hash.get() == env.blockHash
|
||||||
|
let res2 = await client.eth_getBlockByNumber($1, true)
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
test "eth_getTransactionByHash":
|
||||||
|
let res = await client.eth_getTransactionByHash(env.txHash)
|
||||||
|
check res.isSome
|
||||||
|
check res.get().blockNumber.get().string.hexToInt(int) == 1
|
||||||
|
let res2 = await client.eth_getTransactionByHash(env.blockHash)
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
test "eth_getTransactionByBlockHashAndIndex":
|
||||||
|
let res = await client.eth_getTransactionByBlockHashAndIndex(env.blockHash, encodeQuantity(0))
|
||||||
|
check res.isSome
|
||||||
|
check res.get().blockNumber.get().string.hexToInt(int) == 1
|
||||||
|
|
||||||
|
let res2 = await client.eth_getTransactionByBlockHashAndIndex(env.blockHash, encodeQuantity(3))
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
let res3 = await client.eth_getTransactionByBlockHashAndIndex(env.txHash, encodeQuantity(3))
|
||||||
|
check res3.isNone
|
||||||
|
|
||||||
|
test "eth_getTransactionByBlockNumberAndIndex":
|
||||||
|
let res = await client.eth_getTransactionByBlockNumberAndIndex("latest", encodeQuantity(1))
|
||||||
|
check res.isSome
|
||||||
|
check res.get().blockNumber.get().string.hexToInt(int) == 1
|
||||||
|
|
||||||
|
let res2 = await client.eth_getTransactionByBlockNumberAndIndex("latest", encodeQuantity(3))
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
test "eth_getTransactionReceipt":
|
||||||
|
let res = await client.eth_getTransactionReceipt(env.txHash)
|
||||||
|
check res.isSome
|
||||||
|
check res.get().blockNumber.string.hexToInt(int) == 1
|
||||||
|
|
||||||
|
let res2 = await client.eth_getTransactionReceipt(env.blockHash)
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
test "eth_getUncleByBlockHashAndIndex":
|
||||||
|
let res = await client.eth_getUncleByBlockHashAndIndex(env.blockHash, encodeQuantity(0))
|
||||||
|
check res.isSome
|
||||||
|
check res.get().number.get().string.hexToInt(int) == 1
|
||||||
|
|
||||||
|
let res2 = await client.eth_getUncleByBlockHashAndIndex(env.blockHash, encodeQuantity(1))
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
|
let res3 = await client.eth_getUncleByBlockHashAndIndex(env.txHash, encodeQuantity(0))
|
||||||
|
check res3.isNone
|
||||||
|
|
||||||
|
test "eth_getUncleByBlockNumberAndIndex":
|
||||||
|
let res = await client.eth_getUncleByBlockNumberAndIndex("latest", encodeQuantity(0))
|
||||||
|
check res.isSome
|
||||||
|
check res.get().number.get().string.hexToInt(int) == 1
|
||||||
|
|
||||||
|
let res2 = await client.eth_getUncleByBlockNumberAndIndex("latest", encodeQuantity(1))
|
||||||
|
check res2.isNone
|
||||||
|
|
||||||
rpcServer.stop()
|
rpcServer.stop()
|
||||||
rpcServer.close()
|
rpcServer.close()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user