mirror of https://github.com/status-im/nim-eth.git
Add a helper type used in web3 and elsewhere to denote blocks
This commit is contained in:
parent
71d6dbd1b4
commit
5dff021cbc
|
@ -1,5 +1,6 @@
|
||||||
import
|
import
|
||||||
stew/endians2, options, times, chronicles,
|
strutils,
|
||||||
|
stew/[endians2, byteutils], options, times, chronicles,
|
||||||
stint, nimcrypto/[keccak, hash], eth/rlp, eth/trie/[trie_defs, db]
|
stint, nimcrypto/[keccak, hash], eth/rlp, eth/trie/[trie_defs, db]
|
||||||
|
|
||||||
export
|
export
|
||||||
|
@ -125,6 +126,7 @@ type
|
||||||
receiptRoot*: Hash256
|
receiptRoot*: Hash256
|
||||||
blockNumber*: BlockNumber
|
blockNumber*: BlockNumber
|
||||||
|
|
||||||
|
# TODO: Make BlockNumber a uint64 and deprecate either this or BlockHashOrNumber
|
||||||
HashOrNum* = object
|
HashOrNum* = object
|
||||||
case isHash*: bool
|
case isHash*: bool
|
||||||
of true:
|
of true:
|
||||||
|
@ -132,6 +134,13 @@ type
|
||||||
else:
|
else:
|
||||||
number*: BlockNumber
|
number*: BlockNumber
|
||||||
|
|
||||||
|
BlockHashOrNumber* = object
|
||||||
|
case isHash*: bool
|
||||||
|
of true:
|
||||||
|
hash*: Hash256
|
||||||
|
else:
|
||||||
|
number*: uint64
|
||||||
|
|
||||||
BlocksRequest* = object
|
BlocksRequest* = object
|
||||||
startBlock*: HashOrNum
|
startBlock*: HashOrNum
|
||||||
maxResults*, skip*: uint
|
maxResults*, skip*: uint
|
||||||
|
@ -301,6 +310,24 @@ proc read*(rlp: var Rlp, T: typedesc[HashOrStatus]): T {.inline.} =
|
||||||
raise newException(RlpTypeMismatch,
|
raise newException(RlpTypeMismatch,
|
||||||
"HashOrStatus expected, but the source RLP is not a blob of right size.")
|
"HashOrStatus expected, but the source RLP is not a blob of right size.")
|
||||||
|
|
||||||
|
func init*(T: type BlockHashOrNumber, str: string): T
|
||||||
|
{.raises: [ValueError, Defect].} =
|
||||||
|
if str.startsWith "0x":
|
||||||
|
if str.len != sizeof(result.hash.data) * 2 + 2:
|
||||||
|
raise newException(ValueError, "Block hash has incorrect length")
|
||||||
|
|
||||||
|
result.isHash = true
|
||||||
|
hexToByteArray(str, result.hash.data)
|
||||||
|
else:
|
||||||
|
result.isHash = false
|
||||||
|
result.number = parseBiggestUInt str
|
||||||
|
|
||||||
|
func `$`*(x: BlockHashOrNumber): string =
|
||||||
|
if x.isHash:
|
||||||
|
"0x" & x.hash.data.toHex
|
||||||
|
else:
|
||||||
|
$x.number
|
||||||
|
|
||||||
proc append*(rlpWriter: var RlpWriter, value: HashOrStatus) {.inline.} =
|
proc append*(rlpWriter: var RlpWriter, value: HashOrStatus) {.inline.} =
|
||||||
if value.isHash:
|
if value.isHash:
|
||||||
rlpWriter.append(value.hash)
|
rlpWriter.append(value.hash)
|
||||||
|
|
|
@ -2,6 +2,9 @@ import
|
||||||
times, net,
|
times, net,
|
||||||
json_serialization, nimcrypto/[hash, utils], eth_types
|
json_serialization, nimcrypto/[hash, utils], eth_types
|
||||||
|
|
||||||
|
export
|
||||||
|
json_serialization
|
||||||
|
|
||||||
{.push raises: [SerializationError, IOError, Defect].}
|
{.push raises: [SerializationError, IOError, Defect].}
|
||||||
|
|
||||||
proc writeValue*(w: var JsonWriter, a: MDigest) =
|
proc writeValue*(w: var JsonWriter, a: MDigest) =
|
||||||
|
@ -42,3 +45,12 @@ proc writeValue*(w: var JsonWriter, value: HashOrNum) =
|
||||||
w.writeField("number", value.number)
|
w.writeField("number", value.number)
|
||||||
w.endRecord()
|
w.endRecord()
|
||||||
|
|
||||||
|
proc writeValue*(w: var JsonWriter, value: BlockHashOrNumber) =
|
||||||
|
w.writeValue $value
|
||||||
|
|
||||||
|
proc readValue*(r: var JsonReader, value: var BlockHashOrNumber) =
|
||||||
|
try:
|
||||||
|
value = init(BlockHashOrNumber, r.readValue(string))
|
||||||
|
except ValueError:
|
||||||
|
r.raiseUnexpectedValue("A hex-encoded block hash or a decimal block number expected")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
import
|
||||||
|
unittest,
|
||||||
|
nimcrypto/hash,
|
||||||
|
serialization/testing/generic_suite,
|
||||||
|
../../eth/common/[eth_types, eth_types_json_serialization]
|
||||||
|
|
||||||
|
func `==`*(lhs, rhs: BlockHashOrNumber): bool =
|
||||||
|
if lhs.isHash != rhs.isHash:
|
||||||
|
return false
|
||||||
|
|
||||||
|
if lhs.isHash:
|
||||||
|
lhs.hash == rhs.hash
|
||||||
|
else:
|
||||||
|
lhs.number == rhs.number
|
||||||
|
|
||||||
|
suite "BlockHashOrNumber":
|
||||||
|
test "construction":
|
||||||
|
expect ValueError:
|
||||||
|
var x = BlockHashOrNumber.init ""
|
||||||
|
echo "An empty string should not produce the value ", x
|
||||||
|
|
||||||
|
let x1 = BlockHashOrNumber.init "0"
|
||||||
|
check((not x1.isHash) and x1.number == 0)
|
||||||
|
|
||||||
|
let x2 = BlockHashOrNumber.init "1241328"
|
||||||
|
check((not x1.isHash) and x2.number == 1241328)
|
||||||
|
|
||||||
|
expect ValueError:
|
||||||
|
var x = BlockHashOrNumber.init "0x"
|
||||||
|
echo "An empty hash should not produce the value ", x
|
||||||
|
|
||||||
|
expect ValueError:
|
||||||
|
var x = BlockHashOrNumber.init "0xff11"
|
||||||
|
echo "A shorter hash should not produce the value ", x
|
||||||
|
|
||||||
|
expect ValueError:
|
||||||
|
var x = BlockHashOrNumber.init "0x7a64245f7f95164f6176d90bd4903dbdd3e5433d555dd1385e81787f9672c58z"
|
||||||
|
echo "An invalid hash should not produce the value ", x
|
||||||
|
|
||||||
|
expect ValueError:
|
||||||
|
var x = BlockHashOrNumber.init "0x7a64245f7f95164f6176d90bd4903dbdd3e5433d555dd1385e81787f9672c58811"
|
||||||
|
echo "A longer hash should not produce the value ", x
|
||||||
|
|
||||||
|
test "serialization":
|
||||||
|
let hash = Hash256.fromHex "0x7a64245f7f95164f6176d90bd4903dbdd3e5433d555dd1385e81787f9672c588"
|
||||||
|
|
||||||
|
Json.roundtripTest BlockHashOrNumber(isHash: true, hash: hash),
|
||||||
|
"\"0x7a64245f7f95164f6176d90bd4903dbdd3e5433d555dd1385e81787f9672c588\""
|
||||||
|
|
||||||
|
Json.roundtripTest BlockHashOrNumber(isHash: false, number: 1209231231),
|
||||||
|
"\"1209231231\""
|
Loading…
Reference in New Issue