2019-01-06 15:21:34 +00:00
|
|
|
import
|
|
|
|
json, strutils, times, options, os,
|
2019-02-05 19:15:50 +00:00
|
|
|
eth/[rlp, common], httputils, nimcrypto, chronicles,
|
|
|
|
stint, byteutils
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
import
|
|
|
|
../nimbus/[transaction, rpc/hexstrings]
|
|
|
|
|
2019-01-11 06:53:18 +00:00
|
|
|
func hexToInt*(s: string, T: typedesc[SomeInteger]): T =
|
2019-01-06 15:21:34 +00:00
|
|
|
var i = 0
|
|
|
|
if s[i] == '0' and (s[i+1] in {'x', 'X'}): inc(i, 2)
|
|
|
|
if s.len - i > sizeof(T) * 2:
|
|
|
|
raise newException(ValueError, "input hex too big for destination int")
|
|
|
|
while i < s.len:
|
|
|
|
result = result shl 4 or readHexChar(s[i]).T
|
|
|
|
inc(i)
|
|
|
|
|
|
|
|
proc prefixHex*(x: Hash256): string =
|
|
|
|
"0x" & toLowerAscii($x)
|
|
|
|
|
|
|
|
proc prefixHex*(x: int64 | uint64 | byte | int): string =
|
|
|
|
encodeQuantity(x.uint64).toLowerAscii
|
|
|
|
|
|
|
|
proc prefixHex*(x: openArray[byte]): string =
|
|
|
|
"0x" & toHex(x, true)
|
|
|
|
|
|
|
|
proc prefixHex*(x: UInt256): string =
|
|
|
|
"0x" & stint.toHex(x)
|
|
|
|
|
|
|
|
proc prefixHex*(x: string): string =
|
|
|
|
"0x" & toLowerAscii(x)
|
|
|
|
|
|
|
|
type
|
|
|
|
SomeData = EthAddress | BloomFilter | BlockNonce
|
|
|
|
|
|
|
|
proc fromJson(n: JsonNode, name: string, x: var SomeData) =
|
|
|
|
hexToByteArray(n[name].getStr(), x)
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(x.prefixHex == toLowerAscii(n[name].getStr()))
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc fromJson(n: JsonNode, name: string, x: var Hash256) =
|
|
|
|
hexToByteArray(n[name].getStr(), x.data)
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(x.prefixHex == toLowerAscii(n[name].getStr()))
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc fromJson(n: JsonNode, name: string, x: var Blob) =
|
|
|
|
x = hexToSeqByte(n[name].getStr())
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(x.prefixHex == toLowerAscii(n[name].getStr()))
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc fromJson(n: JsonNode, name: string, x: var UInt256) =
|
|
|
|
x = UInt256.fromHex(n[name].getStr())
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(x.prefixHex == toLowerAscii(n[name].getStr()))
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc fromJson(n: JsonNode, name: string, x: var SomeInteger) =
|
|
|
|
x = hexToInt(n[name].getStr(), type(x))
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(x.prefixHex == toLowerAscii(n[name].getStr()))
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc fromJson(n: JsonNode, name: string, x: var EthTime) =
|
|
|
|
x = initTime(hexToInt(n[name].getStr(), int64), 0)
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert(x.toUnix.prefixHex == toLowerAscii(n[name].getStr()))
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc parseBlockHeader*(n: JsonNode): BlockHeader =
|
|
|
|
n.fromJson "parentHash", result.parentHash
|
|
|
|
n.fromJson "sha3Uncles", result.ommersHash
|
|
|
|
n.fromJson "miner", result.coinbase
|
|
|
|
n.fromJson "stateRoot", result.stateRoot
|
|
|
|
n.fromJson "transactionsRoot", result.txRoot
|
|
|
|
n.fromJson "receiptsRoot", result.receiptRoot
|
|
|
|
n.fromJson "logsBloom", result.bloom
|
|
|
|
n.fromJson "difficulty", result.difficulty
|
|
|
|
n.fromJson "number", result.blockNumber
|
|
|
|
n.fromJson "gasLimit", result.gasLimit
|
|
|
|
n.fromJson "gasUsed", result.gasUsed
|
|
|
|
n.fromJson "timestamp", result.timestamp
|
|
|
|
n.fromJson "extraData", result.extraData
|
|
|
|
n.fromJson "mixHash", result.mixDigest
|
|
|
|
n.fromJson "nonce", result.nonce
|
|
|
|
|
|
|
|
proc parseTransaction*(n: JsonNode): Transaction =
|
|
|
|
n.fromJson "nonce", result.accountNonce
|
|
|
|
n.fromJson "gasPrice", result.gasPrice
|
|
|
|
n.fromJson "gas", result.gasLimit
|
|
|
|
|
|
|
|
result.isContractCreation = n["to"].kind == JNull
|
|
|
|
if not result.isContractCreation:
|
|
|
|
n.fromJson "to", result.to
|
|
|
|
|
|
|
|
n.fromJson "value", result.value
|
|
|
|
n.fromJson "input", result.payload
|
|
|
|
n.fromJson "v", result.V
|
|
|
|
n.fromJson "r", result.R
|
|
|
|
n.fromJson "s", result.S
|
|
|
|
|
|
|
|
var sender = result.getSender()
|
2019-03-13 21:36:54 +00:00
|
|
|
doAssert sender.prefixHex == n["from"].getStr()
|
|
|
|
doAssert n["hash"].getStr() == result.rlpHash().prefixHex
|
2019-01-06 15:21:34 +00:00
|
|
|
|
|
|
|
proc parseLog(n: JsonNode): Log =
|
|
|
|
n.fromJson "address", result.address
|
|
|
|
n.fromJson "data", result.data
|
|
|
|
let topics = n["topics"]
|
|
|
|
result.topics = newSeqOfCap[Topic](n.len)
|
|
|
|
var topicHash: Topic
|
|
|
|
for tp in topics:
|
|
|
|
hexToByteArray(tp.getStr(), topicHash)
|
|
|
|
result.topics.add topicHash
|
|
|
|
|
|
|
|
proc parseLogs(n: JsonNode): seq[Log] =
|
|
|
|
if n.len > 0:
|
|
|
|
result = newSeqOfCap[Log](n.len)
|
|
|
|
for log in n:
|
|
|
|
result.add parseLog(log)
|
|
|
|
else:
|
|
|
|
result = @[]
|
|
|
|
|
|
|
|
proc parseReceipt*(n: JsonNode): Receipt =
|
|
|
|
if n.hasKey("root"):
|
|
|
|
var hash: Hash256
|
|
|
|
n.fromJson "root", hash
|
|
|
|
result.stateRootOrStatus = hashOrStatus(hash)
|
|
|
|
else:
|
|
|
|
var status: int
|
|
|
|
n.fromJson "status", status
|
|
|
|
result.stateRootOrStatus = hashOrStatus(status == 1)
|
|
|
|
|
|
|
|
n.fromJson "cumulativeGasUsed", result.cumulativeGasUsed
|
|
|
|
n.fromJson "logsBloom", result.bloom
|
|
|
|
result.logs = parseLogs(n["logs"])
|
|
|
|
|
|
|
|
proc headerHash*(n: JsonNode): Hash256 =
|
|
|
|
n.fromJson "hash", result
|
2019-01-15 08:55:39 +00:00
|
|
|
|
|
|
|
proc parseAccount*(n: JsonNode): Account =
|
|
|
|
n.fromJson "nonce", result.nonce
|
|
|
|
n.fromJson "balance", result.balance
|
|
|
|
n.fromJson "storageRoot", result.storageRoot
|
|
|
|
n.fromJson "codeHash", result.codeHash
|