From db1e8b805b04d75f20688a1aeeb838d011f5f6dc Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 5 Aug 2021 09:41:33 +0200 Subject: [PATCH] Calculate hashes only once --- abc/acks.nim | 51 ++++++++++++++++++++++++++------------------ abc/transactions.nim | 33 +++++++++++++++++----------- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/abc/acks.nim b/abc/acks.nim index bfcae88..7a3da69 100644 --- a/abc/acks.nim +++ b/abc/acks.nim @@ -10,11 +10,24 @@ type previous: ?Hash transactions: seq[Hash] validator: PublicKey + hash: Hash signature: ?Signature -func init*(_: type Ack, - transactions: openArray[Hash], - validator: PublicKey): ?Ack = +func toBytes*(ack: Ack): seq[byte] = + let previous = ack.previous |? Hash.default + result.add(previous.toBytes) + result.add(ack.transactions.len.uint8) + for transaction in ack.transactions: + result.add(transaction.toBytes) + result.add(ack.validator.toBytes) + +func init(_: type Ack, + previous: ?Hash, + transactions: openArray[Hash], + validator: PublicKey): ?Ack = + if previous =? previous and previous.kind != HashKind.Ack: + return none Ack + if transactions.len == 0: return none Ack @@ -22,20 +35,24 @@ func init*(_: type Ack, if transaction.kind != HashKind.Tx: return none Ack - some Ack(transactions: @transactions, validator: validator) + var ack = Ack( + previous: previous, + transactions: @transactions, + validator: validator + ) + ack.hash = hash(ack.toBytes, HashKind.Ack) + some ack + +func init*(_: type Ack, + transactions: openArray[Hash], + validator: PublicKey): ?Ack = + Ack.init(Hash.none, transactions, validator) func init*(_: type Ack, previous: Hash, transactions: openArray[Hash], validator: PublicKey): ?Ack = - if previous.kind != HashKind.Ack: - return none Ack - - without var ack =? Ack.init(transactions, validator): - return none Ack - - ack.previous = previous.some - some ack + Ack.init(previous.some, transactions, validator) func previous*(ack: Ack): ?Hash = ack.previous @@ -52,16 +69,8 @@ func signature*(ack: Ack): ?Signature = func `signature=`*(ack: var Ack, signature: Signature) = ack.signature = signature.some -func toBytes*(ack: Ack): seq[byte] = - let previous = ack.previous |? Hash.default - result.add(previous.toBytes) - result.add(ack.transactions.len.uint8) - for transaction in ack.transactions: - result.add(transaction.toBytes) - result.add(ack.validator.toBytes) - func hash*(ack: Ack): Hash = - hash(ack.toBytes, HashKind.Ack) + ack.hash func sign*(key: PrivateKey, ack: var Ack) = ack.signature = key.sign(ack.hash.toBytes).some diff --git a/abc/transactions.nim b/abc/transactions.nim index 2335596..ff8aec7 100644 --- a/abc/transactions.nim +++ b/abc/transactions.nim @@ -16,6 +16,7 @@ type inputs: seq[TxInput] outputs: seq[TxOutput] validator: PublicKey + hash: Hash signature: Signature TxInput* = tuple transaction: Hash @@ -24,6 +25,17 @@ type owner: PublicKey value: UInt256 +func toBytes*(transaction: Transaction): seq[byte] = + result.add(transaction.inputs.len.uint8) + for (txHash, owner) in transaction.inputs: + result.add(txHash.toBytes) + result.add(owner.toBytes) + result.add(transaction.outputs.len.uint8) + for (owner, value) in transaction.outputs: + result.add(owner.toBytes) + result.add(value.toBytes) + result.add(transaction.validator.toBytes) + func init*(_: type Transaction, inputs: openArray[TxInput], outputs: openArray[TxOutput], @@ -38,7 +50,13 @@ func init*(_: type Transaction, if input.transaction.kind != HashKind.Tx: return none Transaction - some Transaction(inputs: @inputs, outputs: @outputs, validator: validator) + var transaction = Transaction( + inputs: @inputs, + outputs: @outputs, + validator: validator + ) + transaction.hash = hash(transaction.toBytes, HashKind.Tx) + some transaction func init*(_: type Transaction, outputs: openArray[TxOutput], @@ -60,19 +78,8 @@ func validator*(transaction: Transaction): PublicKey = func add*(transaction: var Transaction, signature: Signature) = transaction.signature = aggregate(transaction.signature, signature) -func toBytes*(transaction: Transaction): seq[byte] = - result.add(transaction.inputs.len.uint8) - for (txHash, owner) in transaction.inputs: - result.add(txHash.toBytes) - result.add(owner.toBytes) - result.add(transaction.outputs.len.uint8) - for (owner, value) in transaction.outputs: - result.add(owner.toBytes) - result.add(value.toBytes) - result.add(transaction.validator.toBytes) - func hash*(transaction: Transaction): Hash = - hash(transaction.toBytes, HashKind.Tx) + transaction.hash func sign*(key: PrivateKey, transaction: var Transaction) = transaction.add(key.sign(transaction.hash.toBytes))