From 030bbf33676326914fdbe2d9422392cacff714d8 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 20 Nov 2024 15:51:34 +0100 Subject: [PATCH] serialization algorithm can be set at compile time - calculate block id once - sign hashes, not byte sequences - simplify Transaction abstraction --- mysticeti.nim | 1 - mysticeti/blocks/blck.nim | 20 +++++++++------- mysticeti/blocks/signed.nim | 5 ++-- mysticeti/dependencies.nim | 3 ++- mysticeti/dependencies/signing.nim | 10 ++++---- mysticeti/dependencies/transacting.nim | 9 +------ tests/mysticeti/mocks.nim | 5 +++- tests/mysticeti/mocks/serialization.nim | 32 +++++++++++++++++++++++++ tests/mysticeti/mocks/signing.nim | 5 ++-- tests/mysticeti/mocks/transacting.nim | 3 +++ tests/mysticeti/testBlocks.nim | 3 ++- 11 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 tests/mysticeti/mocks/serialization.nim diff --git a/mysticeti.nim b/mysticeti.nim index ebefe0b..6a4d692 100644 --- a/mysticeti.nim +++ b/mysticeti.nim @@ -63,4 +63,3 @@ export hashing.`$` import ./mysticeti/dependencies/transacting export transacting.Transaction -export transacting.`$` diff --git a/mysticeti/blocks/blck.nim b/mysticeti/blocks/blck.nim index 871e54c..805f463 100644 --- a/mysticeti/blocks/blck.nim +++ b/mysticeti/blocks/blck.nim @@ -4,11 +4,18 @@ import ./blockid type Block*[Dependencies] = object + id: BlockId[Dependencies] author: CommitteeMember round: uint64 parents: seq[BlockId[Dependencies]] transactions: seq[Transaction[Dependencies]] +func calculateId(blck: var Block) = + type Dependencies = Block.Dependencies + let bytes = Dependencies.Serialization.toBytes(blck) + let hash = Hash[Dependencies].hash(bytes) + blck.id = BlockId[Dependencies].new(blck.author, blck.round, hash) + func new*[Dependencies]( _: type Block[Dependencies]; author: CommitteeMember, @@ -16,12 +23,14 @@ func new*[Dependencies]( parents: seq[BlockId[Dependencies]], transactions: seq[Transaction[Dependencies]] ): auto = - Block[Dependencies]( + var blck = Block[Dependencies]( author: author, round: round, parents: parents, transactions: transactions ) + blck.calculateId() + blck func author*(blck: Block): auto = blck.author @@ -35,12 +44,5 @@ func parents*(blck: Block): auto = func transactions*(blck: Block): auto = blck.transactions -func toBytes*(blck: Block): seq[byte] = - cast[seq[byte]]($blck) # TODO: proper serialization - func id*(blck: Block): auto = - BlockId[Block.Dependencies].new( - blck.author, - blck.round, - Hash[Block.Dependencies].hash(blck.toBytes) - ) + blck.id diff --git a/mysticeti/blocks/signed.nim b/mysticeti/blocks/signed.nim index 41ecb78..7426c4a 100644 --- a/mysticeti/blocks/signed.nim +++ b/mysticeti/blocks/signed.nim @@ -1,5 +1,6 @@ import ../basics import ./blck +import ./blockid type SignedBlock*[Dependencies] = object blck: Block[Dependencies] @@ -12,8 +13,8 @@ func blck*(signed: SignedBlock): auto = signed.blck func sign*(identity: Identity, blck: Block): auto = - let signature = identity.sign(blck.toBytes) + let signature = identity.sign(blck.id.hash) SignedBlock.new(blck, signature) func signer*(signed: SignedBlock): auto = - signed.signature.signer(signed.blck.toBytes) + signed.signature.signer(signed.blck.id.hash) diff --git a/mysticeti/dependencies.nim b/mysticeti/dependencies.nim index 9d64186..a1df009 100644 --- a/mysticeti/dependencies.nim +++ b/mysticeti/dependencies.nim @@ -9,5 +9,6 @@ export transacting type Dependencies*[ Hashing, Signing, - Transacting + Transacting, + Serialization ] = object diff --git a/mysticeti/dependencies/signing.nim b/mysticeti/dependencies/signing.nim index 4c7cc5c..eed56ac 100644 --- a/mysticeti/dependencies/signing.nim +++ b/mysticeti/dependencies/signing.nim @@ -1,3 +1,5 @@ +import ./hashing + type Identity*[Dependencies] = object value: Dependencies.Signing.Identity @@ -15,13 +17,13 @@ func identifier*(identity: Identity): auto = mixin identifier Identifier[Identity.Dependencies](value: identity.value.identifier) -func sign*(identity: Identity, bytes: openArray[byte]): auto = +func sign*(identity: Identity, hash: Hash): auto = mixin sign - Signature[Identity.Dependencies](value: identity.value.sign(bytes)) + Signature[Identity.Dependencies](value: identity.value.sign(hash)) -func signer*(signature: Signature, bytes: openArray[byte]): auto = +func signer*(signature: Signature, hash: Hash): auto = mixin signer - Identifier[Signature.Dependencies](value: signature.value.signer(bytes)) + Identifier[Signature.Dependencies](value: signature.value.signer(hash)) func `$`*(identity: Identity): string = $identity.value diff --git a/mysticeti/dependencies/transacting.nim b/mysticeti/dependencies/transacting.nim index efa7917..cdb9d45 100644 --- a/mysticeti/dependencies/transacting.nim +++ b/mysticeti/dependencies/transacting.nim @@ -1,10 +1,3 @@ type - Transaction*[Dependencies] = object - value: Dependencies.Transacting.Transaction + Transaction*[Dependencies] = Dependencies.Transacting.Transaction Transacting*[Transaction] = object - -func init*[T: Transaction](_: type T, value: T.Dependencies.Transacting.Transaction): T = - T(value: value) - -func `$`*(transaction: Transaction): string = - $transaction.value diff --git a/tests/mysticeti/mocks.nim b/tests/mysticeti/mocks.nim index c2cc5ae..b4b0ef0 100644 --- a/tests/mysticeti/mocks.nim +++ b/tests/mysticeti/mocks.nim @@ -2,13 +2,16 @@ import mysticeti/dependencies import ./mocks/signing import ./mocks/hashing import ./mocks/transacting +import ./mocks/serialization export signing export hashing export transacting +export serialization type MockDependencies* = Dependencies[ MockHashing, MockSigning, - MockTransacting + MockTransacting, + MockSerialization ] diff --git a/tests/mysticeti/mocks/serialization.nim b/tests/mysticeti/mocks/serialization.nim new file mode 100644 index 0000000..e4821c6 --- /dev/null +++ b/tests/mysticeti/mocks/serialization.nim @@ -0,0 +1,32 @@ +import std/json +import mysticeti +import ./transacting + +type MockSerialization* = object + +proc `%`*(member: CommitteeMember): JsonNode = + %member.int + +proc `%`*(id: BlockId): JsonNode = + %*{ + "author": id.author, + "round": id.round, + "hash": $id.hash + } + +proc `%`*(transaction: MockTransacting.Transaction): JsonNode = + %*{ + "nonce": transaction.nonce + } + +proc `%`*(blck: Block): JsonNode = + %*{ + "author": blck.author, + "round": blck.round, + "parents": blck.parents, + "transactions": blck.transactions + } + +func toBytes*(_: type MockSerialization, blck: Block): seq[byte] = + let json = %blck + cast[seq[byte]]($json) diff --git a/tests/mysticeti/mocks/signing.nim b/tests/mysticeti/mocks/signing.nim index b9b79a7..3c9ef46 100644 --- a/tests/mysticeti/mocks/signing.nim +++ b/tests/mysticeti/mocks/signing.nim @@ -2,6 +2,7 @@ import std/random import std/sequtils import std/strutils import mysticeti/dependencies/signing +import mysticeti/dependencies/hashing type Identity = object @@ -18,8 +19,8 @@ proc init*(_: type Identity): Identity = func identifier*(identity: Identity): Identifier = Identifier(id: identity.id) -func sign*(identity: Identity, bytes: openArray[byte]): Signature = +func sign*(identity: Identity, hash: Hash): Signature = Signature(signer: identity.id) -func signer*(signature: Signature, bytes: openArray[byte]): Identifier = +func signer*(signature: Signature, hash: Hash): Identifier = Identifier(id: signature.signer) diff --git a/tests/mysticeti/mocks/transacting.nim b/tests/mysticeti/mocks/transacting.nim index 6586901..e9c934e 100644 --- a/tests/mysticeti/mocks/transacting.nim +++ b/tests/mysticeti/mocks/transacting.nim @@ -6,5 +6,8 @@ type nonce: int MockTransacting* = Transacting[MockTransaction] +proc nonce*(transaction: MockTransaction): int = + transaction.nonce + proc example*(_: type MockTransaction): MockTransaction = MockTransaction(nonce: rand(int)) diff --git a/tests/mysticeti/testBlocks.nim b/tests/mysticeti/testBlocks.nim index 25cf88b..e756fe6 100644 --- a/tests/mysticeti/testBlocks.nim +++ b/tests/mysticeti/testBlocks.nim @@ -10,6 +10,7 @@ suite "Blocks": type Identity = mysticeti.Identity[MockDependencies] type Transaction = mysticeti.Transaction[MockDependencies] type Hash = hashing.Hash[MockDependencies] + type Serialization = MockDependencies.Serialization test "blocks have an author, a round, parents and transactions": let author = CommitteeMember.example @@ -27,7 +28,7 @@ suite "Blocks": let id = blck.id check id.author == blck.author check id.round == blck.round - check id.hash == Hash.hash(blck.toBytes) + check id.hash == Hash.hash(Serialization.toBytes(blck)) test "blocks can be signed": let signer = Identity.init