mirror of https://github.com/status-im/nim-abc.git
Speed up hashing of transactions and hashes
Calculate hashing without first concatenating bytes.
This commit is contained in:
parent
7e705dba3f
commit
652e34d6b2
14
abc/acks.nim
14
abc/acks.nim
|
@ -13,13 +13,15 @@ type
|
|||
hash: Hash
|
||||
signature: ?Signature
|
||||
|
||||
func toBytes*(ack: Ack): seq[byte] =
|
||||
func calculateHash(ack: Ack) =
|
||||
var hashing = Hashing.init(HashKind.Ack)
|
||||
let previous = ack.previous |? Hash.default
|
||||
result.add(previous.toBytes)
|
||||
result.add(ack.transactions.len.uint8)
|
||||
hashing.update(previous.toBytes)
|
||||
hashing.update([ack.transactions.len.uint8])
|
||||
for transaction in ack.transactions:
|
||||
result.add(transaction.toBytes)
|
||||
result.add(ack.validator.toBytes)
|
||||
hashing.update(transaction.toBytes)
|
||||
hashing.update(ack.validator.toBytes)
|
||||
ack.hash = hashing.finish()
|
||||
|
||||
func new(_: type Ack,
|
||||
previous: ?Hash,
|
||||
|
@ -40,7 +42,7 @@ func new(_: type Ack,
|
|||
transactions: @transactions,
|
||||
validator: validator
|
||||
)
|
||||
ack.hash = hash(ack.toBytes, HashKind.Ack)
|
||||
ack.calculateHash()
|
||||
some ack
|
||||
|
||||
func new*(_: type Ack,
|
||||
|
|
15
abc/hash.nim
15
abc/hash.nim
|
@ -6,6 +6,9 @@ type
|
|||
Hash* = object
|
||||
kind*: HashKind
|
||||
hash: MDigest[256]
|
||||
Hashing* = object
|
||||
kind: HashKind
|
||||
context: sha256
|
||||
|
||||
func hash*(bytes: openArray[byte], kind: HashKind): Hash =
|
||||
Hash(kind: kind, hash: sha256.digest(bytes))
|
||||
|
@ -22,3 +25,15 @@ func `$`*(hash: Hash): string =
|
|||
"Tx(" & $hash.hash & ")"
|
||||
of Ack:
|
||||
"Ack(" & $hash.hash & ")"
|
||||
|
||||
func init*(_: type Hashing, kind: HashKind): Hashing =
|
||||
result.kind = kind
|
||||
result.context.init()
|
||||
|
||||
func update*(hashing: var Hashing, bytes: openArray[byte]) =
|
||||
hashing.context.update(bytes)
|
||||
|
||||
func finish*(hashing: var Hashing): Hash =
|
||||
let hash = hashing.context.finish()
|
||||
hashing.context.clear()
|
||||
Hash(kind: hashing.kind, hash: hash)
|
||||
|
|
|
@ -25,16 +25,18 @@ type
|
|||
owner: PublicKey
|
||||
value: UInt256
|
||||
|
||||
func toBytes*(transaction: Transaction): seq[byte] =
|
||||
result.add(transaction.inputs.len.uint8)
|
||||
func calculateHash(transaction: Transaction) =
|
||||
var hashing = Hashing.init(HashKind.Tx)
|
||||
hashing.update([transaction.inputs.len.uint8])
|
||||
for (txHash, owner) in transaction.inputs:
|
||||
result.add(txHash.toBytes)
|
||||
result.add(owner.toBytes)
|
||||
result.add(transaction.outputs.len.uint8)
|
||||
hashing.update(txHash.toBytes)
|
||||
hashing.update(owner.toBytes)
|
||||
hashing.update([transaction.outputs.len.uint8])
|
||||
for (owner, value) in transaction.outputs:
|
||||
result.add(owner.toBytes)
|
||||
result.add(value.toBytes)
|
||||
result.add(transaction.validator.toBytes)
|
||||
hashing.update(owner.toBytes)
|
||||
hashing.update(value.toBytes)
|
||||
hashing.update(transaction.validator.toBytes)
|
||||
transaction.hash = hashing.finish()
|
||||
|
||||
func new*(_: type Transaction,
|
||||
inputs: openArray[TxInput],
|
||||
|
@ -55,7 +57,7 @@ func new*(_: type Transaction,
|
|||
outputs: @outputs,
|
||||
validator: validator
|
||||
)
|
||||
transaction.hash = hash(transaction.toBytes, HashKind.Tx)
|
||||
transaction.calculateHash()
|
||||
some transaction
|
||||
|
||||
func new*(_: type Transaction,
|
||||
|
|
|
@ -28,7 +28,7 @@ suite "Acknowledgements":
|
|||
check ack.?previous == previous.hash.some
|
||||
check ack.?validator == victor.some
|
||||
|
||||
test "an acknowledgement can be converted to bytes":
|
||||
test "an acknowledgement hash is derived from its fields":
|
||||
let previous = Ack.example
|
||||
let ack = !Ack.new(previous.hash, [tx1.hash, tx2.hash], victor)
|
||||
var expected: seq[byte]
|
||||
|
@ -37,7 +37,7 @@ suite "Acknowledgements":
|
|||
expected.add(tx1.hash.toBytes)
|
||||
expected.add(tx2.hash.toBytes)
|
||||
expected.add(victor.toBytes)
|
||||
check ack.toBytes == expected
|
||||
check ack.hash == hash(expected, HashKind.Ack)
|
||||
|
||||
test "a signature can be added to an acknowledgment":
|
||||
let key = PrivateKey.example
|
||||
|
|
|
@ -37,7 +37,7 @@ suite "Transactions":
|
|||
check genesis.outputValue(bob) == 10.u256
|
||||
check genesis.outputValue(victor) == 0.u256
|
||||
|
||||
test "a transaction can be converted to bytes":
|
||||
test "a transaction hash is derived from its fields":
|
||||
let genesis = !Transaction.new({alice: 32.u256, bob: 10.u256}, victor)
|
||||
let transaction = !Transaction.new(
|
||||
{genesis.hash: alice},
|
||||
|
@ -54,7 +54,7 @@ suite "Transactions":
|
|||
expected.add(bob.toBytes)
|
||||
expected.add(30.u256.toBytes)
|
||||
expected.add(victor.toBytes)
|
||||
check transaction.toBytes == expected
|
||||
check transaction.hash == hash(expected, HashKind.Tx)
|
||||
|
||||
test "signatures can be added to a transaction":
|
||||
let key1, key2 = PrivateKey.example
|
||||
|
|
Loading…
Reference in New Issue