mirror of https://github.com/status-im/nim-eth.git
port eth2_digest speedups to eth_hash (#716)
* port eth2_digest speedups to eth_hash * faster comparison * `hash` integration * lower-case printing
This commit is contained in:
parent
ebfe63b9b6
commit
864d54467e
|
@ -2,7 +2,7 @@ import stint, ./common/eth_hash
|
|||
|
||||
type UInt2048 = StUint[2048]
|
||||
|
||||
iterator chunksForBloom(h: MDigest[256]): array[2, uint8] =
|
||||
iterator chunksForBloom(h: KeccakHash): array[2, uint8] =
|
||||
yield [h.data[0], h.data[1]]
|
||||
yield [h.data[2], h.data[3]]
|
||||
yield [h.data[4], h.data[5]]
|
||||
|
@ -12,25 +12,25 @@ proc chunkToBloomBits(chunk: array[2, uint8]): UInt2048 =
|
|||
let l = chunk[1].int
|
||||
one(UInt2048) shl ((l + (h shl 8)) and 2047)
|
||||
|
||||
iterator bloomBits(h: MDigest[256]): UInt2048 =
|
||||
iterator bloomBits(h: KeccakHash): UInt2048 =
|
||||
for chunk in chunksForBloom(h):
|
||||
yield chunkToBloomBits(chunk)
|
||||
|
||||
type BloomFilter* = object
|
||||
value*: UInt2048
|
||||
|
||||
proc incl*(f: var BloomFilter, h: MDigest[256]) =
|
||||
proc incl*(f: var BloomFilter, h: KeccakHash) =
|
||||
for bits in bloomBits(h):
|
||||
f.value = f.value or bits
|
||||
|
||||
proc init*(_: type BloomFilter, h: MDigest[256]): BloomFilter =
|
||||
proc init*(_: type BloomFilter, h: KeccakHash): BloomFilter =
|
||||
result.incl(h)
|
||||
|
||||
# TODO: The following 2 procs should be one genric, but it doesn't compile. Nim bug?
|
||||
proc incl*(f: var BloomFilter, v: string) = f.incl(keccakHash(v))
|
||||
proc incl*(f: var BloomFilter, v: openArray[byte]) = f.incl(keccakHash(v))
|
||||
|
||||
proc contains*(f: BloomFilter, h: MDigest[256]): bool =
|
||||
proc contains*(f: BloomFilter, h: KeccakHash): bool =
|
||||
for bits in bloomBits(h):
|
||||
if (f.value and bits).isZero: return false
|
||||
return true
|
||||
|
|
|
@ -9,16 +9,19 @@
|
|||
## keccak256 is used across ethereum as the "default" hash function and this
|
||||
## module provides a type and some helpers to produce such hashes
|
||||
|
||||
import
|
||||
nimcrypto/[keccak, hash]
|
||||
import std/hashes
|
||||
import nimcrypto/[keccak, utils]
|
||||
import nimcrypto/hash except `$`
|
||||
|
||||
from nimcrypto/utils import bytesToHex
|
||||
|
||||
export
|
||||
keccak.update, keccak.finish, hash
|
||||
keccak.update, keccak.finish, hash.fromHex, hash.toDigest, hashes.Hash
|
||||
|
||||
type
|
||||
KeccakHash* = MDigest[256]
|
||||
## A hash value computed using keccak256
|
||||
## note: this aliases Eth2Digest too, which uses a different hash!
|
||||
## note: this aliases Eth2Digest too, which uses a different hash function!
|
||||
|
||||
template withKeccakHash*(body: untyped): KeccakHash =
|
||||
## This little helper will init the hash function and return the sliced
|
||||
|
@ -44,3 +47,23 @@ func keccakHash*(a, b: openArray[byte]): KeccakHash =
|
|||
withKeccakHash:
|
||||
h.update a
|
||||
h.update b
|
||||
|
||||
func `$`*(v: KeccakHash): string =
|
||||
var res = newString((len(v.data) shl 1))
|
||||
discard bytesToHex(v.data, res, {HexFlags.LowerCase})
|
||||
res
|
||||
|
||||
template hash*(x: KeccakHash): Hash =
|
||||
## Hash for digests for Nim hash tables
|
||||
# digests are already good hashes
|
||||
var h {.noinit.}: Hash
|
||||
copyMem(addr h, unsafeAddr x.data[0], static(sizeof(Hash)))
|
||||
h
|
||||
|
||||
func `==`*(a, b: KeccakHash): bool =
|
||||
when nimvm:
|
||||
a.data == b.data
|
||||
else:
|
||||
# nimcrypto uses a constant-time comparison for all MDigest types which for
|
||||
# KeccakHash is unnecessary - the type should never hold a secret!
|
||||
equalMem(unsafeAddr a.data[0], unsafeAddr b.data[0], sizeof(a.data))
|
||||
|
|
|
@ -10,8 +10,8 @@ import
|
|||
|
||||
export eth_hash, rlp
|
||||
|
||||
proc read*(rlp: var Rlp, T: typedesc[MDigest]): T =
|
||||
proc read*(rlp: var Rlp, T: typedesc[KeccakHash]): T =
|
||||
result.data = rlp.read(type(result.data))
|
||||
|
||||
proc append*(rlpWriter: var RlpWriter, a: MDigest) =
|
||||
proc append*(rlpWriter: var RlpWriter, a: KeccakHash) =
|
||||
rlpWriter.append(a.data)
|
||||
|
|
|
@ -17,6 +17,8 @@ import
|
|||
./eth_hash,
|
||||
./eth_times
|
||||
|
||||
from nimcrypto/hash import MDigest
|
||||
|
||||
export
|
||||
results,
|
||||
stint,
|
||||
|
|
|
@ -302,7 +302,7 @@ proc appendImpl(self: var RlpWriter, data: tuple) {.inline.} =
|
|||
# score in order to facilitate easier overloading with user types:
|
||||
template append*[T](w: var RlpWriter; data: T) =
|
||||
when data is (SomeSignedInt|enum|bool):
|
||||
when data is SomeSignedInt:
|
||||
when false and data is SomeSignedInt:
|
||||
# TODO potentially remove signed integer support - we should never make it
|
||||
# this far!
|
||||
{.warning: "Signed integers cannot reliably be encoded using RLP".}
|
||||
|
@ -314,7 +314,6 @@ proc initRlpList*(listSize: int): RlpWriter =
|
|||
result = initRlpWriter()
|
||||
startList(result, listSize)
|
||||
|
||||
# TODO: This should return a lent value
|
||||
template finish*(self: RlpWriter): seq[byte] =
|
||||
doAssert self.pendingLists.len == 0, "Insufficient number of elements written to a started list"
|
||||
self.output
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import
|
||||
stew/byteutils,
|
||||
./trie_defs
|
||||
|
||||
export trie_defs
|
||||
|
@ -10,8 +9,3 @@ template checkValidHashZ*(x: untyped) =
|
|||
|
||||
template isZeroHash*(x: openArray[byte]): bool =
|
||||
x.len == 0
|
||||
|
||||
proc hashFromHex*(bits: static[int], input: string): MDigest[bits] =
|
||||
MDigest(data: hexToByteArray[bits div 8](input))
|
||||
|
||||
template hashFromHex*(s: static[string]): untyped = hashFromHex(s.len * 4, s)
|
||||
|
|
Loading…
Reference in New Issue