From c600c5a2ef40dda736963444b2a1b42d9573e10c Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Wed, 6 Nov 2024 13:45:37 +0100 Subject: [PATCH] combine generic types for signing and hashing --- mysticeti.nim | 4 ++++ mysticeti/basics.nim | 4 ++++ mysticeti/blocks/blck.nim | 16 +++++++------- mysticeti/blocks/blockid.nim | 8 +++---- mysticeti/blocks/signed.nim | 9 ++++---- mysticeti/committee/committee.nim | 8 +++---- mysticeti/dependencies.nim | 1 + mysticeti/hashing.nim | 8 +++---- mysticeti/signing.nim | 22 +++++++++---------- mysticeti/validator.nim | 19 ++++++++-------- mysticeti/validator/checks.nim | 13 ++++++----- mysticeti/validator/round.nim | 8 +++---- mysticeti/validator/rounds.nim | 8 +++---- mysticeti/validator/slots.nim | 14 ++++++------ tests/mysticeti/committee/testCommittee.nim | 4 +++- tests/mysticeti/examples.nim | 14 ++++++------ tests/mysticeti/mocks.nim | 3 +++ tests/mysticeti/simulator.nim | 7 +++--- tests/mysticeti/testBlocks.nim | 9 ++++---- tests/mysticeti/validator/testRound.nim | 6 ++--- tests/mysticeti/validator/testRounds.nim | 4 ++-- tests/mysticeti/validator/testSlots.nim | 8 +++---- tests/mysticeti/validator/testValidator.nim | 5 +++-- .../validator/testValidatorNetwork.nim | 11 +++++----- 24 files changed, 117 insertions(+), 96 deletions(-) create mode 100644 mysticeti/dependencies.nim diff --git a/mysticeti.nim b/mysticeti.nim index 4f0b0b3..053b449 100644 --- a/mysticeti.nim +++ b/mysticeti.nim @@ -1,3 +1,7 @@ +import ./mysticeti/dependencies + +export dependencies.Dependencies + import ./mysticeti/validator export validator.Validator diff --git a/mysticeti/basics.nim b/mysticeti/basics.nim index 4f81af7..f91434b 100644 --- a/mysticeti/basics.nim +++ b/mysticeti/basics.nim @@ -7,3 +7,7 @@ import pkg/questionable/results export questionable export results + +import ./dependencies + +export dependencies diff --git a/mysticeti/blocks/blck.nim b/mysticeti/blocks/blck.nim index 0d5036f..eb7c70b 100644 --- a/mysticeti/blocks/blck.nim +++ b/mysticeti/blocks/blck.nim @@ -4,20 +4,20 @@ import ./blockid import ./transaction type - Block*[Hashing] = object + Block*[Dependencies] = object author: CommitteeMember round: uint64 - parents: seq[BlockId[Hashing]] + parents: seq[BlockId[Dependencies]] transactions: seq[Transaction] -func new*[Hashing]( - _: type Block[Hashing]; +func new*[Dependencies]( + _: type Block[Dependencies]; author: CommitteeMember, round: uint64, - parents: seq[BlockId[Hashing]], + parents: seq[BlockId[Dependencies]], transactions: seq[Transaction] ): auto = - Block[Hashing]( + Block[Dependencies]( author: author, round: round, parents: parents, @@ -40,8 +40,8 @@ func toBytes*(blck: Block): seq[byte] = cast[seq[byte]]($blck) # TODO: proper serialization func id*(blck: Block): auto = - BlockId.new( + BlockId[Block.Dependencies].new( blck.author, blck.round, - Block.Hashing.hash(blck.toBytes) + Hash[Block.Dependencies].hash(blck.toBytes) ) diff --git a/mysticeti/blocks/blockid.nim b/mysticeti/blocks/blockid.nim index 84df5be..96b1036 100644 --- a/mysticeti/blocks/blockid.nim +++ b/mysticeti/blocks/blockid.nim @@ -1,18 +1,18 @@ import ../committee import ../hashing -type BlockId*[Hashing] = object +type BlockId*[Dependencies] = object author: CommitteeMember round: uint64 - hash: Hash[Hashing] + hash: Hash[Dependencies] func new*( - _: type BlockId, + T: type BlockId, author: CommitteeMember, round: uint64, hash: Hash ): auto = - BlockId[Hash.Hashing]( + T( author: author, round: round, hash: hash diff --git a/mysticeti/blocks/signed.nim b/mysticeti/blocks/signed.nim index b2738e0..11dd97d 100644 --- a/mysticeti/blocks/signed.nim +++ b/mysticeti/blocks/signed.nim @@ -1,12 +1,13 @@ +import ../basics import ../signing import ./blck -type SignedBlock*[Signing, Hashing] = object - blck: Block[Hashing] - signature: Signature[Signing] +type SignedBlock*[Dependencies] = object + blck: Block[Dependencies] + signature: Signature[Dependencies] func new*(_: type SignedBlock, blck: Block, signature: Signature): auto = - SignedBlock[Signature.Signing, Block.Hashing](blck: blck, signature: signature) + SignedBlock[Block.Dependencies](blck: blck, signature: signature) func blck*(signed: SignedBlock): auto = signed.blck diff --git a/mysticeti/committee/committee.nim b/mysticeti/committee/committee.nim index bcee691..18b87e5 100644 --- a/mysticeti/committee/committee.nim +++ b/mysticeti/committee/committee.nim @@ -3,13 +3,13 @@ import ../signing import ./members type - Committee*[Signing] = ref object - members: seq[Identifier[Signing]] + Committee*[Dependencies] = ref object + members: seq[Identifier[Dependencies]] stakes: seq[Stake] Stake* = float64 -func new*(_: type Committee, stakes: openArray[(Identifier, Stake)]): auto = - var committee = Committee[Identifier.Signing]() +func new*(T: type Committee, stakes: openArray[(Identifier, Stake)]): auto = + var committee = T() for (member, stake) in stakes: committee.members.add(member) committee.stakes.add(stake) diff --git a/mysticeti/dependencies.nim b/mysticeti/dependencies.nim new file mode 100644 index 0000000..5dfe949 --- /dev/null +++ b/mysticeti/dependencies.nim @@ -0,0 +1 @@ +type Dependencies*[Signing, Hashing] = object diff --git a/mysticeti/hashing.nim b/mysticeti/hashing.nim index e325932..a622960 100644 --- a/mysticeti/hashing.nim +++ b/mysticeti/hashing.nim @@ -1,11 +1,11 @@ type - Hash*[Hashing] = object - value: Hashing.Hash + Hash*[Dependencies] = object + value: Dependencies.Hashing.Hash Hashing*[Hash] = object -func hash*(T: type Hashing, bytes: openArray[byte]): auto = +func hash*(T: type Hash, bytes: openArray[byte]): auto = mixin hash - Hash[T](value: T.Hash.hash(bytes)) + T(value: T.Dependencies.Hashing.Hash.hash(bytes)) func `$`*(hash: Hash): string = $hash.value diff --git a/mysticeti/signing.nim b/mysticeti/signing.nim index c84e405..4c7cc5c 100644 --- a/mysticeti/signing.nim +++ b/mysticeti/signing.nim @@ -1,27 +1,27 @@ type - Identity*[Signing] = object - value: Signing.Identity - Identifier*[Signing] = object - value: Signing.Identifier - Signature*[Signing] = object - value: Signing.Signature + Identity*[Dependencies] = object + value: Dependencies.Signing.Identity + Identifier*[Dependencies] = object + value: Dependencies.Signing.Identifier + Signature*[Dependencies] = object + value: Dependencies.Signing.Signature Signing*[Identity, Identifier, Signature] = object -proc init*[Signing](_: type Identity[Signing]): Identity[Signing] = +proc init*(T: type Identity): T = mixin init - Identity[Signing](value: Signing.Identity.init()) + T(value: T.Dependencies.Signing.Identity.init()) func identifier*(identity: Identity): auto = mixin identifier - Identifier[Identity.Signing](value: identity.value.identifier) + Identifier[Identity.Dependencies](value: identity.value.identifier) func sign*(identity: Identity, bytes: openArray[byte]): auto = mixin sign - Signature[Identity.Signing](value: identity.value.sign(bytes)) + Signature[Identity.Dependencies](value: identity.value.sign(bytes)) func signer*(signature: Signature, bytes: openArray[byte]): auto = mixin signer - Identifier[Signature.Signing](value: signature.value.signer(bytes)) + Identifier[Signature.Dependencies](value: signature.value.signer(bytes)) func `$`*(identity: Identity): string = $identity.value diff --git a/mysticeti/validator.nim b/mysticeti/validator.nim index 401a160..e9fb9a6 100644 --- a/mysticeti/validator.nim +++ b/mysticeti/validator.nim @@ -9,11 +9,11 @@ import ./validator/checks export slots export checks -type Validator*[Signing, Hashing] = ref object - identity: Identity[Signing] - committee: Committee[Signing] +type Validator*[Dependencies] = ref object + identity: Identity[Dependencies] + committee: Committee[Dependencies] membership: CommitteeMember - rounds: Rounds[Signing, Hashing] + rounds: Rounds[Dependencies] func new*(T: type Validator; identity: Identity, committee: Committee): ?!T = without membership =? committee.membership(identity.identifier): @@ -22,7 +22,7 @@ func new*(T: type Validator; identity: Identity, committee: Committee): ?!T = identity: identity, committee: committee, membership: membership, - rounds: Rounds[T.Signing, T.Hashing].init(committee.size) + rounds: Rounds[T.Dependencies].init(committee.size) ) func identifier*(validator: Validator): auto = @@ -77,11 +77,12 @@ func addBlock(validator: Validator, signedBlock: SignedBlock) = validator.updateCertified(signedBlock.blck) proc propose*(validator: Validator, transactions: seq[Transaction]): auto = - type SignedBlock = blocks.SignedBlock[Validator.Signing, Validator.Hashing] + type Block = blocks.Block[Validator.Dependencies] + type SignedBlock = blocks.SignedBlock[Validator.Dependencies] let round = validator.rounds.latest if round[validator.membership].proposals.len > 0: return SignedBlock.failure "already proposed this round" - var parents: seq[BlockId[Validator.Hashing]] + var parents: seq[BlockId[Validator.Dependencies]] var parentStake: Stake if previous =? round.previous: for slot in previous.slots: @@ -103,8 +104,8 @@ proc propose*(validator: Validator, transactions: seq[Transaction]): auto = success signedBlock func check*(validator: Validator, signed: SignedBlock): auto = - type BlockCheck = checks.BlockCheck[SignedBlock.Signing, SignedBlock.Hashing] - type BlockId = blocks.BlockId[SignedBlock.Hashing] + type BlockCheck = checks.BlockCheck[SignedBlock.Dependencies] + type BlockId = blocks.BlockId[SignedBlock.Dependencies] without member =? validator.committee.membership(signed.signer): return BlockCheck.invalid("block is not signed by a committee member") if member != signed.blck.author: diff --git a/mysticeti/validator/checks.nim b/mysticeti/validator/checks.nim index b50a33e..fe0dabc 100644 --- a/mysticeti/validator/checks.nim +++ b/mysticeti/validator/checks.nim @@ -1,3 +1,4 @@ +import ../basics import ../blocks type @@ -5,15 +6,15 @@ type invalid incomplete correct - BlockCheck*[Signing, Hashing] = object + BlockCheck*[Dependencies] = object case verdict: BlockVerdict of invalid: reason: string of incomplete: - missing: seq[BlockId[Hashing]] + missing: seq[BlockId[Dependencies]] of correct: - blck: CorrectBlock[Signing, Hashing] - CorrectBlock*[Signing, Hashing] = distinct SignedBlock[Signing, Hashing] + blck: CorrectBlock[Dependencies] + CorrectBlock*[Dependencies] = distinct SignedBlock[Dependencies] func invalid*(T: type BlockCheck, reason: string): T = T(verdict: BlockVerdict.invalid, reason: reason) @@ -22,7 +23,7 @@ func incomplete*(T: type BlockCheck; missing: seq[BlockId]): T = T(verdict: BlockVerdict.incomplete, missing: missing) func correct*(T: type BlockCheck, signedBlock: SignedBlock): T = - let blck = CorrectBlock[SignedBlock.Signing, SignedBlock.Hashing](signedBlock) + let blck = CorrectBlock[SignedBlock.Dependencies](signedBlock) T(verdict: BlockVerdict.correct, blck: blck) func verdict*(check: BlockCheck): BlockVerdict = @@ -38,7 +39,7 @@ func blck*(check: BlockCheck): auto = check.blck func signedBlock*(correct: CorrectBlock): auto = - SignedBlock[CorrectBlock.Signing, CorrectBlock.Hashing](correct) + SignedBlock[CorrectBlock.Dependencies](correct) func blck*(correct: CorrectBlock): auto = correct.signedBlock.blck diff --git a/mysticeti/validator/round.nim b/mysticeti/validator/round.nim index a7c1b2a..412813e 100644 --- a/mysticeti/validator/round.nim +++ b/mysticeti/validator/round.nim @@ -3,14 +3,14 @@ import ../blocks import ../committee import ./slots -type Round*[Signing, Hashing] = ref object +type Round*[Dependencies] = ref object number: uint64 - previous, next: ?Round[Signing, Hashing] - slots: seq[ProposerSlot[Signing, Hashing]] + previous, next: ?Round[Dependencies] + slots: seq[ProposerSlot[Dependencies]] func new*(T: type Round, number: uint64, slots: int): T = assert slots > 0 - type Slot = ProposerSlot[T.Signing, T.Hashing] + type Slot = ProposerSlot[T.Dependencies] let slots = newSeqWith(slots, Slot.new()) T(number: number, slots: slots) diff --git a/mysticeti/validator/rounds.nim b/mysticeti/validator/rounds.nim index 5990b38..622618a 100644 --- a/mysticeti/validator/rounds.nim +++ b/mysticeti/validator/rounds.nim @@ -3,11 +3,11 @@ import ./round export round -type Rounds*[Signing, Hashing] = object - oldest, latest: Round[Signing, Hashing] +type Rounds*[Dependencies] = object + oldest, latest: Round[Dependencies] func init*(T: type Rounds, slots: int, start: uint64 = 0): T = - let round = Round[T.Signing, T.Hashing].new(start, slots) + let round = Round[T.Dependencies].new(start, slots) T(oldest: round, latest: round) func oldest*(rounds: Rounds): auto = @@ -17,7 +17,7 @@ func latest*(rounds: Rounds): auto = rounds.latest func addNewRound*(rounds: var Rounds) = - rounds.latest = Round[Rounds.Signing, Rounds.Hashing].new(rounds.latest) + rounds.latest = Round[Rounds.Dependencies].new(rounds.latest) func removeOldestRound*(rounds: var Rounds) = assert rounds.oldest.next.isSome diff --git a/mysticeti/validator/slots.nim b/mysticeti/validator/slots.nim index fb2247f..df0f873 100644 --- a/mysticeti/validator/slots.nim +++ b/mysticeti/validator/slots.nim @@ -3,15 +3,15 @@ import ../blocks import ../committee type - ProposerSlot*[Signing, Hashing] = ref object - proposals: seq[Proposal[Signing, Hashing]] + ProposerSlot*[Dependencies] = ref object + proposals: seq[Proposal[Dependencies]] skippedBy: Voting status: SlotStatus - Proposal*[Signing, Hashing] = ref object - slot: ProposerSlot[Signing, Hashing] - signedBlock: SignedBlock[Signing, Hashing] + Proposal*[Dependencies] = ref object + slot: ProposerSlot[Dependencies] + signedBlock: SignedBlock[Dependencies] certifiedBy: Voting - certificates: seq[BlockId[Hashing]] + certificates: seq[BlockId[Dependencies]] SlotStatus* {.pure.} = enum undecided skip @@ -40,7 +40,7 @@ func certificates*(proposal: Proposal): auto = proposal.certificates func addProposal*(slot: ProposerSlot, signedBlock: SignedBlock) = - let proposal = Proposal[SignedBlock.Signing, SignedBlock.Hashing]( + let proposal = Proposal[ProposerSlot.Dependencies]( slot: slot, signedBlock: signedBlock ) diff --git a/tests/mysticeti/committee/testCommittee.nim b/tests/mysticeti/committee/testCommittee.nim index 70a217a..6b66685 100644 --- a/tests/mysticeti/committee/testCommittee.nim +++ b/tests/mysticeti/committee/testCommittee.nim @@ -1,10 +1,12 @@ import ../basics +import mysticeti import mysticeti/committee import mysticeti/signing suite "Committee": - type Identifier = signing.Identifier[MockSigning] + type Identifier = signing.Identifier[MockDependencies] + type Committee = committee.Committee[MockDependencies] test "committee has numbered members": let identifiers = array[4, Identifier].example diff --git a/tests/mysticeti/examples.nim b/tests/mysticeti/examples.nim index 4f39a56..46daf7b 100644 --- a/tests/mysticeti/examples.nim +++ b/tests/mysticeti/examples.nim @@ -14,26 +14,26 @@ proc example*(T: type Identity): T = T.init() proc example*(T: type Identifier): T = - Identity[T.Signing].example.identifier + Identity[T.Dependencies].example.identifier proc example*(T: type CommitteeMember): T = CommitteeMember(int.example) proc example*(T: type Hash): T = - T.Hashing.hash(seq[byte].example) + T.hash(seq[byte].example) proc example*(T: type BlockId): T = let author = CommitteeMember.example let round = uint64.example - let hash = Hash[T.Hashing].example - BlockId.new(author, round, hash) + let hash = Hash[T.Dependencies].example + T.new(author, round, hash) proc example*( T: type Block, author = CommitteeMember.example, round = uint64.example ): T = - let parents = seq[BlockId[T.Hashing]].example + let parents = seq[BlockId[T.Dependencies]].example let transactions = seq[Transaction].example T.new(author, round, parents, transactions) @@ -42,8 +42,8 @@ proc example*( author = CommitteeMember.example, round = uint64.example ): T = - let identity = Identity[T.Signing].example - let blck = Block[T.Hashing].example(author = author, round = round) + let identity = Identity[T.Dependencies].example + let blck = Block[T.Dependencies].example(author = author, round = round) identity.sign(blck) proc example*[T](_: type seq[T], length=0..10): seq[T] = diff --git a/tests/mysticeti/mocks.nim b/tests/mysticeti/mocks.nim index aa9330e..85fa7e1 100644 --- a/tests/mysticeti/mocks.nim +++ b/tests/mysticeti/mocks.nim @@ -1,5 +1,8 @@ +import mysticeti/dependencies import ./mocks/signing import ./mocks/hashing export signing export hashing + +type MockDependencies* = Dependencies[MockSigning, MockHashing] diff --git a/tests/mysticeti/simulator.nim b/tests/mysticeti/simulator.nim index a66df6c..c036d77 100644 --- a/tests/mysticeti/simulator.nim +++ b/tests/mysticeti/simulator.nim @@ -2,9 +2,10 @@ import ./basics import mysticeti import mysticeti/blocks -type Validator* = mysticeti.Validator[MockSigning, MockHashing] -type Identity* = mysticeti.Identity[MockSigning] -type SignedBlock* = blocks.SignedBlock[MockSigning, MockHashing] +type Validator* = mysticeti.Validator[MockDependencies] +type Committee* = mysticeti.Committee[MockDependencies] +type Identity* = mysticeti.Identity[MockDependencies] +type SignedBlock* = blocks.SignedBlock[MockDependencies] type NetworkSimulator* = object identities: seq[Identity] diff --git a/tests/mysticeti/testBlocks.nim b/tests/mysticeti/testBlocks.nim index 503c25c..b2b1b24 100644 --- a/tests/mysticeti/testBlocks.nim +++ b/tests/mysticeti/testBlocks.nim @@ -5,9 +5,10 @@ import mysticeti/hashing suite "Blocks": - type Block = mysticeti.Block[MockHashing] - type BlockId = mysticeti.BlockId[MockHashing] - type Identity = mysticeti.Identity[MockSigning] + type Block = mysticeti.Block[MockDependencies] + type BlockId = mysticeti.BlockId[MockDependencies] + type Identity = mysticeti.Identity[MockDependencies] + type Hash = hashing.Hash[MockDependencies] test "blocks have an author, a round, parents and transactions": let author = CommitteeMember.example @@ -25,7 +26,7 @@ suite "Blocks": let id = blck.id check id.author == blck.author check id.round == blck.round - check id.hash == Block.Hashing.hash(blck.toBytes) + check id.hash == Hash.hash(blck.toBytes) test "blocks can be signed": let signer = Identity.init diff --git a/tests/mysticeti/validator/testRound.nim b/tests/mysticeti/validator/testRound.nim index ef99c17..0718a67 100644 --- a/tests/mysticeti/validator/testRound.nim +++ b/tests/mysticeti/validator/testRound.nim @@ -6,9 +6,9 @@ import mysticeti/validator/round suite "Validator Round": - type Round = round.Round[MockSigning, MockHashing] - type Block = mysticeti.Block[MockHashing] - type SignedBlock = mysticeti.SignedBlock[MockSigning, MockHashing] + type Round = round.Round[MockDependencies] + type Block = mysticeti.Block[MockDependencies] + type SignedBlock = mysticeti.SignedBlock[MockDependencies] test "rounds have a number": check Round.new(0, 1).number == 0 diff --git a/tests/mysticeti/validator/testRounds.nim b/tests/mysticeti/validator/testRounds.nim index a3696fb..6e2a83b 100644 --- a/tests/mysticeti/validator/testRounds.nim +++ b/tests/mysticeti/validator/testRounds.nim @@ -3,8 +3,8 @@ import mysticeti/validator/rounds suite "List of Validator Rounds": - type Rounds = rounds.Rounds[MockSigning, MockHashing] - type Round = rounds.Round[MockSigning, MockHashing] + type Rounds = rounds.Rounds[MockDependencies] + type Round = rounds.Round[MockDependencies] test "has a single round initially": let rounds = Rounds.init(slots = 4) diff --git a/tests/mysticeti/validator/testSlots.nim b/tests/mysticeti/validator/testSlots.nim index b9ce529..a7993dc 100644 --- a/tests/mysticeti/validator/testSlots.nim +++ b/tests/mysticeti/validator/testSlots.nim @@ -4,10 +4,10 @@ import mysticeti/validator/slots suite "Proposer Slots": - type BlockId = mysticeti.BlockId[MockHashing] - type SignedBlock = mysticeti.SignedBlock[MockSigning, MockHashing] - type Proposal = slots.Proposal[MockSigning, MockHashing] - type ProposerSlot = slots.ProposerSlot[MockSigning, MockHashing] + type BlockId = mysticeti.BlockId[MockDependencies] + type SignedBlock = mysticeti.SignedBlock[MockDependencies] + type Proposal = slots.Proposal[MockDependencies] + type ProposerSlot = slots.ProposerSlot[MockDependencies] var slot: ProposerSlot diff --git a/tests/mysticeti/validator/testValidator.nim b/tests/mysticeti/validator/testValidator.nim index 74b455b..a833353 100644 --- a/tests/mysticeti/validator/testValidator.nim +++ b/tests/mysticeti/validator/testValidator.nim @@ -1,8 +1,9 @@ import ../basics import mysticeti -type Validator = mysticeti.Validator[MockSigning, MockHashing] -type Identity = mysticeti.Identity[MockSigning] +type Validator = mysticeti.Validator[MockDependencies] +type Identity = mysticeti.Identity[MockDependencies] +type Committee = mysticeti.Committee[MockDependencies] suite "Validator": diff --git a/tests/mysticeti/validator/testValidatorNetwork.nim b/tests/mysticeti/validator/testValidatorNetwork.nim index a7d0041..3bc9f45 100644 --- a/tests/mysticeti/validator/testValidatorNetwork.nim +++ b/tests/mysticeti/validator/testValidatorNetwork.nim @@ -7,11 +7,12 @@ import mysticeti/hashing suite "Validator Network": - type Validator = mysticeti.Validator[MockSigning, MockHashing] - type Identity = mysticeti.Identity[MockSigning] - type Block = blocks.Block[MockHashing] - type BlockId = blocks.BlockId[MockHashing] - type Hash = hashing.Hash[MockHashing] + type Validator = mysticeti.Validator[MockDependencies] + type Committee = mysticeti.Committee[MockDependencies] + type Identity = mysticeti.Identity[MockDependencies] + type Block = blocks.Block[MockDependencies] + type BlockId = blocks.BlockId[MockDependencies] + type Hash = hashing.Hash[MockDependencies] var simulator: NetworkSimulator