From de854cbb5fa6ad7c159144520c67abe7e211175a Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Mon, 9 Dec 2024 18:07:43 +0100 Subject: [PATCH] make Block a type dependency --- mysticeti.nim | 19 ++------ mysticeti/basics.nim | 4 -- mysticeti/basics/immutableseq.nim | 27 ----------- mysticeti/blocks.nim | 2 - mysticeti/blocks/blck.nim | 47 ------------------- mysticeti/blocks/signed.nim | 14 +++--- mysticeti/dependencies.nim | 3 +- mysticeti/validator.nim | 22 +++++---- mysticeti/validator/round.nim | 1 + mysticeti/validator/slots.nim | 1 + tests/mysticeti/examples.nim | 23 +++++---- tests/mysticeti/mocks.nim | 7 ++- tests/mysticeti/mocks/blck.nim | 33 +++++++++++++ tests/mysticeti/mocks/serialization.nim | 32 ------------- tests/mysticeti/simulator.nim | 4 +- tests/mysticeti/testBlocks.nim | 26 +--------- tests/mysticeti/validator/testRound.nim | 2 +- .../validator/testValidatorNetwork.nim | 5 +- 18 files changed, 81 insertions(+), 191 deletions(-) delete mode 100644 mysticeti/basics/immutableseq.nim delete mode 100644 mysticeti/blocks/blck.nim create mode 100644 tests/mysticeti/mocks/blck.nim delete mode 100644 tests/mysticeti/mocks/serialization.nim diff --git a/mysticeti.nim b/mysticeti.nim index 4da4b10..ab3223f 100644 --- a/mysticeti.nim +++ b/mysticeti.nim @@ -36,19 +36,8 @@ export committee.`$` import ./mysticeti/blocks -export blocks.Block export blocks.BlockId -export blocks.author -export blocks.round -export blocks.parents -export blocks.id - -import ./mysticeti/basics/immutableseq - -export immutableseq - -import ./mysticeti/blocks/signed - -export signed.SignedBlock -export signed.blck -export signed.signer +export blocks.new +export blocks.SignedBlock +export blocks.blck +export blocks.signer diff --git a/mysticeti/basics.nim b/mysticeti/basics.nim index 8dab6cd..f91434b 100644 --- a/mysticeti/basics.nim +++ b/mysticeti/basics.nim @@ -11,7 +11,3 @@ export results import ./dependencies export dependencies - -import ./basics/immutableseq - -export immutableseq diff --git a/mysticeti/basics/immutableseq.nim b/mysticeti/basics/immutableseq.nim deleted file mode 100644 index 481eb07..0000000 --- a/mysticeti/basics/immutableseq.nim +++ /dev/null @@ -1,27 +0,0 @@ -type ImmutableSeq*[Element] = ref object - ## Encapsulates a sequence, so that it no longer can be - ## modified, and can be passed by reference to avoid copying. - elements: seq[Element] - -func immutable*[Element](sequence: seq[Element]): ImmutableSeq[Element] = - ImmutableSeq[Element](elements: sequence) - -func copy*(sequence: ImmutableSeq): auto = - sequence.elements - -iterator items*(sequence: ImmutableSeq): auto = - for element in sequence.elements: - yield element - -func len*(sequence: ImmutableSeq): int = - sequence.elements.len - -func `[]`*(sequence: ImmutableSeq, index: int): auto = - sequence.elements[index] - -func contains*[Element](sequence: ImmutableSeq[Element], element: Element): bool = - sequence.elements.contains(element) - -func `==`*(a, b: ImmutableSeq): bool = - a.elements == b.elements - diff --git a/mysticeti/blocks.nim b/mysticeti/blocks.nim index f00f952..a4d72d9 100644 --- a/mysticeti/blocks.nim +++ b/mysticeti/blocks.nim @@ -1,7 +1,5 @@ -import ./blocks/blck import ./blocks/blockid import ./blocks/signed -export blck export blockid export signed diff --git a/mysticeti/blocks/blck.nim b/mysticeti/blocks/blck.nim deleted file mode 100644 index 133a48a..0000000 --- a/mysticeti/blocks/blck.nim +++ /dev/null @@ -1,47 +0,0 @@ -import ../basics -import ../committee -import ./blockid - -type - Block*[Dependencies] = ref object - author: CommitteeMember - round: uint64 - parents: ImmutableSeq[BlockId[Dependencies.Hash]] - transactions: ImmutableSeq[Dependencies.Transaction] - id: ?BlockId[Dependencies.Hash] - -func new*[Dependencies]( - _: type Block[Dependencies]; - author: CommitteeMember, - round: uint64, - parents: seq[BlockId[Dependencies.Hash]], - transactions: seq[Dependencies.Transaction] -): auto = - Block[Dependencies]( - author: author, - round: round, - parents: parents.immutable, - transactions: transactions.immutable - ) - -func author*(blck: Block): auto = - blck.author - -func round*(blck: Block): uint64 = - blck.round - -func parents*(blck: Block): auto = - blck.parents - -func transactions*(blck: Block): auto = - blck.transactions - -func id*(blck: Block): auto = - without var id =? blck.id: - type Dependencies = Block.Dependencies - mixin hash - let blockBytes = Dependencies.Serialization.toBytes(blck) - let blockHash = Dependencies.Hash.hash(blockBytes) - id = BlockId.new(blck.author, blck.round, blockHash) - blck.id = some id - id diff --git a/mysticeti/blocks/signed.nim b/mysticeti/blocks/signed.nim index f9323ae..2bb016a 100644 --- a/mysticeti/blocks/signed.nim +++ b/mysticeti/blocks/signed.nim @@ -1,21 +1,21 @@ import ../basics -import ./blck import ./blockid type SignedBlock*[Dependencies] = object - blck: Block[Dependencies] + blck: Dependencies.Block signature: Dependencies.Signature -func init*( - _: type SignedBlock, - blck: Block, - signature: Block.Dependencies.Signature +func init*[Dependencies]( + _: type SignedBlock[Dependencies]; + blck: Dependencies.Block, + signature: Dependencies.Signature ): auto = - SignedBlock[Block.Dependencies](blck: blck, signature: signature) + SignedBlock[Dependencies](blck: blck, signature: signature) func blck*(signed: SignedBlock): auto = signed.blck func signer*(signed: SignedBlock): auto = mixin signer + mixin id signed.signature.signer(signed.blck.id.hash) diff --git a/mysticeti/dependencies.nim b/mysticeti/dependencies.nim index 8a69fdf..7999ea9 100644 --- a/mysticeti/dependencies.nim +++ b/mysticeti/dependencies.nim @@ -1,6 +1,5 @@ type Dependencies*[ - Transaction, - Serialization, + Block, Hash, Identifier, Signature diff --git a/mysticeti/validator.nim b/mysticeti/validator.nim index f18cc95..99bf75b 100644 --- a/mysticeti/validator.nim +++ b/mysticeti/validator.nim @@ -43,13 +43,12 @@ func primaryProposer*(validator: Validator): CommitteeMember = func nextRound*(validator: Validator) = validator.rounds.addNewRound() -func skips(blck: Block, round: uint64, author: CommitteeMember): bool = - for parent in blck.parents: - if parent.round == round and parent.author == author: - return false - true - -func updateSkipped(validator: Validator, supporter: Block) = +func updateSkipped(validator: Validator, supporter: Validator.Dependencies.Block) = + func skips(blck: Validator.Dependencies.Block, round: uint64, author: CommitteeMember): bool = + for parent in blck.parents: + if parent.round == round and parent.author == author: + return false + true if round =? validator.rounds.latest.find(supporter.round) and previous =? round.previous: for proposer in previous.proposers: @@ -59,7 +58,8 @@ func updateSkipped(validator: Validator, supporter: Block) = let stake = validator.committee.stake(author) slot.skipBy(author, stake) -func updateCertified(validator: Validator, certificate: Block) = +func updateCertified(validator: Validator, certificate: Validator.Dependencies.Block) = + mixin id without certifying =? validator.rounds.latest.find(certificate.round) and voting =? certifying.previous and proposing =? voting.previous: @@ -83,6 +83,7 @@ func addBlock(validator: Validator, signedBlock: SignedBlock) = validator.updateCertified(signedBlock.blck) func parentBlocks*(validator: Validator): auto = + mixin id var parents: seq[BlockId[Validator.Dependencies.Hash]] if previous =? validator.rounds.latest.previous: for slot in previous.slots: @@ -91,6 +92,7 @@ func parentBlocks*(validator: Validator): auto = parents func check*(validator: Validator, signed: SignedBlock): auto = + mixin id type BlockCheck = checks.BlockCheck[SignedBlock.Dependencies] type BlockId = blocks.BlockId[SignedBlock.Dependencies.Hash] without member =? validator.committee.membership(signed.signer): @@ -141,7 +143,7 @@ func updateIndirect(validator: Validator, slot: ProposerSlot, round: Round) = return without anchorProposal =? anchor.proposal: return - var todo = anchorProposal.blck.parents.copy + var todo = anchorProposal.blck.parents while todo.len > 0: let parent = todo.pop() if parent.round < round.number + 2: @@ -152,7 +154,7 @@ func updateIndirect(validator: Validator, slot: ProposerSlot, round: Round) = return without parentBlock =? round.find(parent): raiseAssert "parent block not found" - todo.add(parentBlock.blck.parents.copy) + todo.add(parentBlock.blck.parents) slot.skip() iterator committed*(validator: Validator): auto = diff --git a/mysticeti/validator/round.nim b/mysticeti/validator/round.nim index d70d03b..4f686dd 100644 --- a/mysticeti/validator/round.nim +++ b/mysticeti/validator/round.nim @@ -65,6 +65,7 @@ func find*(round: Round, number: uint64): ?Round = current = previous func find*(round: Round, blockId: BlockId): auto = + mixin id if found =? round.find(blockId.round): let slot = found[blockId.author] for proposal in slot.proposals: diff --git a/mysticeti/validator/slots.nim b/mysticeti/validator/slots.nim index 9574d9e..58ca9b3 100644 --- a/mysticeti/validator/slots.nim +++ b/mysticeti/validator/slots.nim @@ -69,6 +69,7 @@ func certifyBy*(proposal: Proposal, certificate: BlockId, stake: Stake) = proposal.slot.status = SlotStatus.commit func certify*(proposal, anchor: Proposal) = + mixin id assert proposal.slot.status == SlotStatus.undecided assert anchor.slot.status == SlotStatus.commit assert anchor.certifiedBy.stake > 2/3 diff --git a/tests/mysticeti/examples.nim b/tests/mysticeti/examples.nim index 8ec43dd..4ffe160 100644 --- a/tests/mysticeti/examples.nim +++ b/tests/mysticeti/examples.nim @@ -16,24 +16,14 @@ proc example*(T: type BlockId): T = let hash = T.Hash.example BlockId.new(author, round, hash) -proc example*( - T: type Block, - author = CommitteeMember.example, - round = uint64.example -): T = - type Transaction = T.Dependencies.Transaction - let parents = seq[BlockId[T.Dependencies.Hash]].example - let transactions = seq[Transaction].example - T.new(author, round, parents, transactions) - proc example*( T: type SignedBlock, author = CommitteeMember.example, round = uint64.example ): T = - let blck = Block[T.Dependencies].example(author = author, round = round) + let blck = T.Dependencies.Block.example(author = author, round = round) let signature = T.Dependencies.Signature.example - SignedBlock.init(blck, signature) + SignedBlock[T.Dependencies].init(blck, signature) proc example*[T](_: type seq[T], length=0..10): seq[T] = let size = rand(length) @@ -54,3 +44,12 @@ proc example*(T: type MockIdentifier): T = proc example*(T: type MockSignature): T = MockIdentity.example.sign(MockHash.example) + +proc example*( + _: type MockBlock, + author = CommitteeMember.example, + round = uint64.example +): MockBlock = + let parents = seq[BlockId[MockHash]].example + let transactions = seq[MockTransaction].example + MockBlock.new(author, round, parents, transactions) diff --git a/tests/mysticeti/mocks.nim b/tests/mysticeti/mocks.nim index db5ce1f..dca1ae2 100644 --- a/tests/mysticeti/mocks.nim +++ b/tests/mysticeti/mocks.nim @@ -2,16 +2,15 @@ import mysticeti/dependencies import ./mocks/signing import ./mocks/hashing import ./mocks/transaction -import ./mocks/serialization +import ./mocks/blck export signing export hashing export transaction -export serialization +export blck type MockDependencies* = Dependencies[ - MockTransaction, - MockSerialization, + MockBlock, MockHash, MockIdentifier, MockSignature diff --git a/tests/mysticeti/mocks/blck.nim b/tests/mysticeti/mocks/blck.nim new file mode 100644 index 0000000..daefe34 --- /dev/null +++ b/tests/mysticeti/mocks/blck.nim @@ -0,0 +1,33 @@ +import mysticeti +import mysticeti/basics +import ./hashing +import ./transaction + +type MockBlock* = ref object + author*: CommitteeMember + round*: uint64 + parents*: seq[BlockId[MockHash]] + transactions*: seq[MockTransaction] + id: ?BlockId[MockHash] + +func new*( + _: type MockBlock, + author: CommitteeMember, + round: uint64, + parents: seq[BlockId[MockHash]], + transactions: seq[MockTransaction] +): auto = + MockBlock( + author: author, + round: round, + parents: parents, + transactions: transactions + ) + +func id*(blck: MockBlock): auto = + without var id =? blck.id: + let blockBytes = cast[seq[byte]]($blck[]) + let blockHash = MockHash.hash(blockBytes) + id = BlockId.new(blck.author, blck.round, blockHash) + blck.id = some id + id diff --git a/tests/mysticeti/mocks/serialization.nim b/tests/mysticeti/mocks/serialization.nim deleted file mode 100644 index 4f4c3e3..0000000 --- a/tests/mysticeti/mocks/serialization.nim +++ /dev/null @@ -1,32 +0,0 @@ -import std/json -import mysticeti -import ./transaction - -type MockSerialization* = object - -proc `%`*(member: CommitteeMember): JsonNode = - %member.int - -proc `%`*(id: BlockId): JsonNode = - %*{ - "author": id.author, - "round": id.round, - "hash": $id.hash - } - -proc `%`*(transaction: MockTransaction): 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/simulator.nim b/tests/mysticeti/simulator.nim index 4c49dfd..2753077 100644 --- a/tests/mysticeti/simulator.nim +++ b/tests/mysticeti/simulator.nim @@ -5,8 +5,8 @@ import mysticeti/blocks type Validator = mysticeti.Validator[MockDependencies] type Committee = mysticeti.Committee[MockDependencies] type Identity = MockIdentity -type Transaction = MockDependencies.Transaction -type Block = blocks.Block[MockDependencies] +type Transaction = MockTransaction +type Block = MockBlock type SignedBlock = blocks.SignedBlock[MockDependencies] type NetworkSimulator* = object diff --git a/tests/mysticeti/testBlocks.nim b/tests/mysticeti/testBlocks.nim index e7ed738..dec8f80 100644 --- a/tests/mysticeti/testBlocks.nim +++ b/tests/mysticeti/testBlocks.nim @@ -4,34 +4,12 @@ import mysticeti/blocks suite "Blocks": - type Block = mysticeti.Block[MockDependencies] - type BlockId = mysticeti.BlockId[MockDependencies.Hash] type Identity = MockIdentity - type Transaction = MockDependencies.Transaction - type Hash = MockDependencies.Hash - type Serialization = MockDependencies.Serialization - - test "blocks have an author, a round, parents and transactions": - let author = CommitteeMember.example - let round = uint64.example - let parents = seq[BlockId].example - let transactions = seq[Transaction].example - let blck = Block.new(author, round, parents, transactions) - check blck.author == author - check blck.round == round - check blck.parents == parents.immutable - check blck.transactions == transactions.immutable - - test "blocks have an id consisting of author, round and hash": - let blck = Block.example - let id = blck.id - check id.author == blck.author - check id.round == blck.round - check id.hash == Hash.hash(Serialization.toBytes(blck)) + type SignedBlock = mysticeti.SignedBlock[MockDependencies] test "blocks can be signed": let signer = Identity.init - let blck = Block.example + let blck = MockBlock.example let signature = signer.sign(blck.id.hash) let signed = SignedBlock.init(blck, signature) check signed.blck == blck diff --git a/tests/mysticeti/validator/testRound.nim b/tests/mysticeti/validator/testRound.nim index 05a1066..9bdcade 100644 --- a/tests/mysticeti/validator/testRound.nim +++ b/tests/mysticeti/validator/testRound.nim @@ -7,7 +7,7 @@ import mysticeti/validator/round suite "Validator Round": type Round = round.Round[MockDependencies] - type Block = mysticeti.Block[MockDependencies] + type Block = MockBlock type SignedBlock = mysticeti.SignedBlock[MockDependencies] test "rounds have a number": diff --git a/tests/mysticeti/validator/testValidatorNetwork.nim b/tests/mysticeti/validator/testValidatorNetwork.nim index bf29ddb..fcf08cf 100644 --- a/tests/mysticeti/validator/testValidatorNetwork.nim +++ b/tests/mysticeti/validator/testValidatorNetwork.nim @@ -6,8 +6,9 @@ import mysticeti/blocks suite "Validator Network": - type Transaction = MockDependencies.Transaction - type Block = blocks.Block[MockDependencies] + type Transaction = MockTransaction + type Block = MockBlock + type SignedBlock = blocks.SignedBlock[MockDependencies] type BlockId = blocks.BlockId[MockDependencies.Hash] type Hash = MockDependencies.Hash