From 343b4bdccd07f2ea844817a0728fb7a75a0c8d41 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Tue, 10 Dec 2024 15:47:37 +0100 Subject: [PATCH] block serialization --- codexvalidator/blocks.nim | 9 ++++ codexvalidator/blocks/blck.nim | 12 ++++++ codexvalidator/blocks/blockid.nim | 9 ++++ codexvalidator/blocks/serialization.nim | 41 +++++++++++++++++++ codexvalidator/hashing.nim | 14 +++++++ codexvalidator/transaction/serialization.nim | 8 ++-- .../blocks/testSerialization.nim | 29 +++++++++++++ tests/codexvalidator/examples.nim | 19 +++++++++ tests/tests.nim | 1 + 9 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 codexvalidator/blocks.nim create mode 100644 codexvalidator/blocks/blck.nim create mode 100644 codexvalidator/blocks/blockid.nim create mode 100644 codexvalidator/blocks/serialization.nim create mode 100644 codexvalidator/hashing.nim create mode 100644 tests/codexvalidator/blocks/testSerialization.nim diff --git a/codexvalidator/blocks.nim b/codexvalidator/blocks.nim new file mode 100644 index 0000000..9ab3228 --- /dev/null +++ b/codexvalidator/blocks.nim @@ -0,0 +1,9 @@ +import ./blocks/blockid +import ./blocks/blck + +export blockid +export blck + +import ./blocks/serialization + +export serialization.toBytes diff --git a/codexvalidator/blocks/blck.nim b/codexvalidator/blocks/blck.nim new file mode 100644 index 0000000..ba0e1b5 --- /dev/null +++ b/codexvalidator/blocks/blck.nim @@ -0,0 +1,12 @@ +import pkg/mysticeti +import ../transaction +import ./blockid + +export mysticeti.CommitteeMember + +type Block* = ref object + author*: CommitteeMember + round*: uint64 + parents*: seq[blockid.BlockId] + transactions*: seq[Transaction] + id*: blockid.BlockId diff --git a/codexvalidator/blocks/blockid.nim b/codexvalidator/blocks/blockid.nim new file mode 100644 index 0000000..49a186e --- /dev/null +++ b/codexvalidator/blocks/blockid.nim @@ -0,0 +1,9 @@ +import pkg/mysticeti +import ../hashing + +export mysticeti.init +export mysticeti.author +export mysticeti.round +export mysticeti.hash + +type BlockId* = mysticeti.BlockId[hashing.Hash] diff --git a/codexvalidator/blocks/serialization.nim b/codexvalidator/blocks/serialization.nim new file mode 100644 index 0000000..58bea1d --- /dev/null +++ b/codexvalidator/blocks/serialization.nim @@ -0,0 +1,41 @@ +import pkg/protobuf_serialization +import ../basics +import ../hashing +import ../transaction +import ../transaction/serialization +import ./blockid +import ./blck + +export protobuf_serialization + +type BlockIdMessage* {.proto3.} = object + author* {.fieldNumber: 1, pint.}: uint32 + round* {.fieldNumber: 2, pint.}: uint64 + hash* {.fieldNumber: 3.}: seq[byte] + +func init*(_: type BlockIdMessage, id: BlockId): BlockIdMessage = + BlockIdMessage( + author: id.author.uint32, + round: id.round, + hash: @(id.hash.toBytes()) + ) + +func toBytes*(id: BlockId): seq[byte] = + Protobuf.encode(BlockIdMessage.init(id)) + +type BlockMessage* {.proto3.} = object + author* {.fieldNumber: 1, pint.}: uint32 + round* {.fieldNumber: 2, pint.}: uint64 + parents* {.fieldNumber: 3.}: seq[BlockIdMessage] + transactions* {.fieldNumber: 4.}: seq[TransactionMessage] + +func init*(_: type BlockMessage, blck: Block): BlockMessage = + BlockMessage( + author: blck.author.uint32, + round: blck.round, + parents: blck.parents.mapIt(BlockIdMessage.init(it)), + transactions: blck.transactions.mapIt(TransactionMessage.init(it)) + ) + +func toBytes*(blck: Block): seq[byte] = + Protobuf.encode(BlockMessage.init(blck)) diff --git a/codexvalidator/hashing.nim b/codexvalidator/hashing.nim new file mode 100644 index 0000000..500accf --- /dev/null +++ b/codexvalidator/hashing.nim @@ -0,0 +1,14 @@ +import pkg/nimcrypto/sha2 +import pkg/nimcrypto/hash + +type Hash* = MDigest[256] + +func hash*(_: type Hash, bytes: openArray[byte]): Hash = + var context: sha256 + context.init() + context.update(bytes) + result = context.finish() + context.clear() + +func toBytes*(hash: Hash): auto = + hash.data diff --git a/codexvalidator/transaction/serialization.nim b/codexvalidator/transaction/serialization.nim index 46cd492..3eb23f4 100644 --- a/codexvalidator/transaction/serialization.nim +++ b/codexvalidator/transaction/serialization.nim @@ -28,8 +28,7 @@ type real* {.fieldNumber: 1.}: seq[byte] imag* {.fieldNumber: 2.}: seq[byte] - -func toBytes*(transaction: Transaction): seq[byte] = +func init*(_: type TransactionMessage, transaction: Transaction): TransactionMessage = var message = TransactionMessage( version: transaction.version.uint32, kind: transaction.kind.uint32, @@ -60,4 +59,7 @@ func toBytes*(transaction: Transaction): seq[byte] = y: @(transaction.proof.c.y.toBytesBE()) ) ) - ProtoBuf.encode(message) + message + +func toBytes*(transaction: Transaction): seq[byte] = + ProtoBuf.encode(TransactionMessage.init(transaction)) diff --git a/tests/codexvalidator/blocks/testSerialization.nim b/tests/codexvalidator/blocks/testSerialization.nim new file mode 100644 index 0000000..a49cc5b --- /dev/null +++ b/tests/codexvalidator/blocks/testSerialization.nim @@ -0,0 +1,29 @@ +import ../basics +import codexvalidator/blocks +import codexvalidator/blocks/serialization +import codexvalidator/transaction/serialization +import codexvalidator/hashing +import ../examples + +suite "Block serialization": + + test "serializes a block id with protobuf": + let id = BlockId.example + let serialized = id.toBytes() + {.warning[Deprecated]: off.} # ignore warning in protobuf_serialization + let protobuf = ProtoBuf.decode(serialized, BlockIdMessage) + {.warning[Deprecated]: on.} + check protobuf.author == id.author.uint32 + check protobuf.round == id.round + check protobuf.hash == id.hash.toBytes() + + test "serializes a block with protobuf": + let blck = Block.example + let serialized = blck.toBytes() + {.warning[Deprecated]: off.} # ignore warning in protobuf_serialization + let protobuf = ProtoBuf.decode(serialized, BlockMessage) + {.warning[Deprecated]: on.} + check protobuf.author == blck.author.uint32 + check protobuf.round == blck.round + check protobuf.parents == blck.parents.mapIt(BlockIdMessage.init(it)) + check protobuf.transactions == blck.transactions.mapIt(TransactionMessage.init(it)) diff --git a/tests/codexvalidator/examples.nim b/tests/codexvalidator/examples.nim index 030dc0e..498bb1e 100644 --- a/tests/codexvalidator/examples.nim +++ b/tests/codexvalidator/examples.nim @@ -1,6 +1,8 @@ import std/random +import codexvalidator/hashing import codexvalidator/transaction import codexvalidator/signatures +import codexvalidator/blocks import ./basics proc example*[T: SomeInteger](_: type T): T = @@ -71,3 +73,20 @@ proc example*(_: type Transaction): Transaction = proc example*(_: type Identity): Identity = Identity.random(result) + +proc example*(_: type CommitteeMember): CommitteeMember = + CommitteeMember(uint32.example.int) + +proc example*(_: type Hash): Hash = + Hash.hash(seq[byte].example) + +proc example*(_: type BlockId): BlockId = + BlockId.init(CommitteeMember.example, uint64.example, Hash.example) + +proc example*(_: type Block): Block = + Block( + author: CommitteeMember.example, + round: uint64.example, + parents: seq[BlockId].example, + transactions: seq[Transaction].example + ) diff --git a/tests/tests.nim b/tests/tests.nim index 6f0d631..42c33c8 100644 --- a/tests/tests.nim +++ b/tests/tests.nim @@ -2,5 +2,6 @@ import ./codexvalidator/testSignatures import ./codexvalidator/transaction/testTransaction import ./codexvalidator/transaction/testSigning import ./codexvalidator/transaction/testSerialization +import ./codexvalidator/blocks/testSerialization {.warning[UnusedImport]:off.}