block serialization

This commit is contained in:
Mark Spanbroek 2024-12-10 15:47:37 +01:00
parent 9d45f90ba3
commit 343b4bdccd
9 changed files with 139 additions and 3 deletions

View File

@ -0,0 +1,9 @@
import ./blocks/blockid
import ./blocks/blck
export blockid
export blck
import ./blocks/serialization
export serialization.toBytes

View File

@ -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

View File

@ -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]

View File

@ -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))

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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
)

View File

@ -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.}