diff --git a/eth/bloom.nim b/eth/bloom.nim index 0976deb..676dcd5 100644 --- a/eth/bloom.nim +++ b/eth/bloom.nim @@ -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 diff --git a/eth/common/eth_hash.nim b/eth/common/eth_hash.nim index 6387cf4..1ed55f9 100644 --- a/eth/common/eth_hash.nim +++ b/eth/common/eth_hash.nim @@ -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)) diff --git a/eth/common/eth_hash_rlp.nim b/eth/common/eth_hash_rlp.nim index 4fcfc04..40d21e5 100644 --- a/eth/common/eth_hash_rlp.nim +++ b/eth/common/eth_hash_rlp.nim @@ -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) diff --git a/eth/common/eth_types.nim b/eth/common/eth_types.nim index da1d678..5dbf7f6 100644 --- a/eth/common/eth_types.nim +++ b/eth/common/eth_types.nim @@ -17,6 +17,8 @@ import ./eth_hash, ./eth_times +from nimcrypto/hash import MDigest + export results, stint, diff --git a/eth/rlp/writer.nim b/eth/rlp/writer.nim index 8b4607f..cdf37fc 100644 --- a/eth/rlp/writer.nim +++ b/eth/rlp/writer.nim @@ -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 diff --git a/eth/trie/trie_utils.nim b/eth/trie/trie_utils.nim index e87a85a..ca1e97c 100644 --- a/eth/trie/trie_utils.nim +++ b/eth/trie/trie_utils.nim @@ -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)