diff --git a/mysticeti.nim b/mysticeti.nim index f34667a..224ece3 100644 --- a/mysticeti.nim +++ b/mysticeti.nim @@ -42,6 +42,10 @@ export blocks.round export blocks.parents export blocks.id +import ./mysticeti/basics/immutableseq + +export immutableseq + import ./mysticeti/blocks/signed export signed.SignedBlock diff --git a/mysticeti/basics.nim b/mysticeti/basics.nim index f91434b..8dab6cd 100644 --- a/mysticeti/basics.nim +++ b/mysticeti/basics.nim @@ -11,3 +11,7 @@ export results import ./dependencies export dependencies + +import ./basics/immutableseq + +export immutableseq diff --git a/mysticeti/basics/immutableseq.nim b/mysticeti/basics/immutableseq.nim new file mode 100644 index 0000000..481eb07 --- /dev/null +++ b/mysticeti/basics/immutableseq.nim @@ -0,0 +1,27 @@ +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/blck.nim b/mysticeti/blocks/blck.nim index 82cf585..4074c52 100644 --- a/mysticeti/blocks/blck.nim +++ b/mysticeti/blocks/blck.nim @@ -3,12 +3,12 @@ import ../committee import ./blockid type - Block*[Dependencies] = object + Block*[Dependencies] = ref object id: BlockId[Dependencies] author: CommitteeMember round: uint64 - parents: seq[BlockId[Dependencies]] - transactions: seq[Dependencies.Transaction] + parents: ImmutableSeq[BlockId[Dependencies]] + transactions: ImmutableSeq[Dependencies.Transaction] func calculateId(blck: var Block) = mixin hash @@ -27,8 +27,8 @@ func new*[Dependencies]( var blck = Block[Dependencies]( author: author, round: round, - parents: parents, - transactions: transactions + parents: parents.immutable, + transactions: transactions.immutable ) blck.calculateId() blck diff --git a/mysticeti/validator.nim b/mysticeti/validator.nim index 1a37c53..afa7001 100644 --- a/mysticeti/validator.nim +++ b/mysticeti/validator.nim @@ -153,7 +153,7 @@ func updateIndirect(validator: Validator, slot: ProposerSlot, round: Round) = return without anchorProposal =? anchor.proposal: return - var todo = anchorProposal.blck.parents + var todo = anchorProposal.blck.parents.copy while todo.len > 0: let parent = todo.pop() if parent.round < round.number + 2: @@ -164,7 +164,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) + todo.add(parentBlock.blck.parents.copy) slot.skip() iterator committed*(validator: Validator): auto = diff --git a/tests/mysticeti/testBlocks.nim b/tests/mysticeti/testBlocks.nim index e76a738..5016007 100644 --- a/tests/mysticeti/testBlocks.nim +++ b/tests/mysticeti/testBlocks.nim @@ -19,8 +19,8 @@ suite "Blocks": let blck = Block.new(author, round, parents, transactions) check blck.author == author check blck.round == round - check blck.parents == parents - check blck.transactions == blck.transactions + 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