From 9208af338f55a3ecda66f187525d4c2382c4d0eb Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 30 Jun 2021 17:18:19 +0200 Subject: [PATCH] Introduce acknowledgements --- abc/acks.nim | 40 ++++++++++++++++++++++++++++++++++++++++ tests/abc/examples.nim | 5 +++++ tests/abc/testAcks.nim | 40 ++++++++++++++++++++++++++++++++++++++++ tests/testAll.nim | 1 + 4 files changed, 86 insertions(+) create mode 100644 abc/acks.nim create mode 100644 tests/abc/testAcks.nim diff --git a/abc/acks.nim b/abc/acks.nim new file mode 100644 index 0000000..f22576c --- /dev/null +++ b/abc/acks.nim @@ -0,0 +1,40 @@ +import pkg/questionable +import ./hash + +export hash + +type + Ack* = object + previous: ?Hash + transactions: seq[Hash] + +func init*(_: type Ack, transactions: openArray[Hash]): ?Ack = + if transactions.len == 0: + return none Ack + + some Ack(transactions: @transactions) + +func init*(_: type Ack, + previous: Hash, + transactions: openArray[Hash]): ?Ack = + without var ack =? Ack.init(transactions): + return none Ack + + ack.previous = previous.some + some ack + +func previous*(ack: Ack): ?Hash = + ack.previous + +func transactions*(ack: Ack): seq[Hash] = + ack.transactions + +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) + +func hash*(ack: Ack): Hash = + hash(ack.toBytes) diff --git a/tests/abc/examples.nim b/tests/abc/examples.nim index 8ac3bef..0c587b5 100644 --- a/tests/abc/examples.nim +++ b/tests/abc/examples.nim @@ -1,6 +1,7 @@ import std/random import pkg/questionable import abc +import abc/acks import ./alicebob proc example*(_: type PrivateKey): PrivateKey = @@ -25,3 +26,7 @@ proc example*(_: type Transaction): Transaction = victor ) transaction + +proc example*(_: type Ack): Ack = + let tx1, tx2 = Transaction.example + !Ack.init([tx1.hash, tx2.hash]) diff --git a/tests/abc/testAcks.nim b/tests/abc/testAcks.nim new file mode 100644 index 0000000..3bb205e --- /dev/null +++ b/tests/abc/testAcks.nim @@ -0,0 +1,40 @@ +import abc/acks +import ./basics +import ./alicebob + +suite "Acknowledgements": + + let tx1, tx2 = Transaction.example + + test "a first acknowledgement can be made": + let ack = Ack.init([tx1.hash, tx2.hash]) + check ack.isSome + check ack.?transactions == @[tx1.hash, tx2.hash].some + check ack.?previous == Hash.none + + test "an acknowledgement has a hash": + let ack1, ack2 = Ack.example + check ack1.hash == ack1.hash + check ack2.hash == ack2.hash + check ack1.hash != ack2.hash + + test "an acknowledgement references a previous acknowledgement": + let previous = Ack.example + let ack = Ack.init(previous.hash, [tx1.hash, tx2.hash]) + check ack.isSome + check ack.?transactions == @[tx1.hash, tx2.hash].some + check ack.?previous == previous.hash.some + + test "an acknowledgement can be converted to bytes": + let previous = Ack.example + let ack = !Ack.init(previous.hash, [tx1.hash, tx2.hash]) + var expected: seq[byte] + expected.add(previous.hash.toBytes) + expected.add(2) # amount of transactions + expected.add(tx1.hash.toBytes) + expected.add(tx2.hash.toBytes) + check ack.toBytes == expected + + test "an acknowledgement must contain at least one transaction": + let previous = Ack.example + check Ack.init(previous.hash, []).isNone diff --git a/tests/testAll.nim b/tests/testAll.nim index 3f93f98..a24f3d6 100644 --- a/tests/testAll.nim +++ b/tests/testAll.nim @@ -1,3 +1,4 @@ +import abc/testAcks import abc/testKeys import abc/testTransactions import abc/testTxStore