introduce doubly linked list for rounds

This commit is contained in:
Mark Spanbroek 2024-09-25 10:56:59 +02:00
parent 64df40e8e8
commit 9dc432ae3c

View File

@ -7,10 +7,10 @@ type
Validator*[Signing, Hashing] = ref object
identity: Identity[Signing]
committee: Committee[Signing]
round: Round[Signing, Hashing]
first, last: Round[Signing, Hashing]
Round[Signing, Hashing] = ref object
number: uint64
previous: ?Round[Signing, Hashing]
previous, next: ?Round[Signing, Hashing]
slots: Table[Identifier[Signing], ProposerSlot[Signing, Hashing]]
ProposerSlot[Signing, Hashing] = object
proposal: Block[Signing, Hashing]
@ -24,7 +24,7 @@ type
func new*(T: type Validator; identity: Identity, committee: Committee): T =
let round = Round[T.Signing, T.Hashing](number: 0)
T(identity: identity, committee: committee, round: round)
T(identity: identity, committee: committee, first: round, last: round)
func new*(_: type Round, number: uint64, previous: Round): auto =
Round(number: number, previous: some previous)
@ -36,20 +36,22 @@ func identifier*(validator: Validator): auto =
validator.identity.identifier
func round*(validator: Validator): uint64 =
validator.round.number
validator.last.number
func wave(validator: Validator): auto =
# A wave consists of 3 rounds: proposing -> voting -> certifying
type Round = typeof(validator.round)
let certifying = validator.round
type Round = typeof(validator.last)
let certifying = validator.last
if voting =? certifying.previous:
if proposing =? voting.previous:
return some (proposing, voting, certifying)
none (Round, Round, Round)
func nextRound*(validator: Validator) =
let previous = validator.round
validator.round = Round.new(previous.number + 1, previous)
let previous = validator.last
let next = Round.new(previous.number + 1, previous)
validator.last = next
previous.next = some next
func hasParent(blck: Block, round: uint64, author: Identifier): bool =
for parent in blck.parents:
@ -58,7 +60,7 @@ func hasParent(blck: Block, round: uint64, author: Identifier): bool =
false
func updateSkipped(validator: Validator, supporter: Block) =
if previous =? validator.round.previous:
if previous =? validator.last.previous:
for (id, slot) in previous.slots.mpairs:
if not supporter.hasParent(previous.number, id):
slot.skippedBy += validator.committee.stake(supporter.author)
@ -80,28 +82,28 @@ func updateCertified(validator: Validator, certificate: Block) =
proposerSlot.status = ProposalStatus.toCommit
proc propose*(validator: Validator, transactions: seq[Transaction]): auto =
assert validator.identifier notin validator.round.slots
assert validator.identifier notin validator.last.slots
var parents: seq[BlockId[Validator.Signing, Validator.Hashing]]
if previous =? validator.round.previous:
if previous =? validator.last.previous:
for id in previous.slots.keys:
parents.add(previous.slots[id].proposal.id)
let blck = Block.new(
author = validator.identifier,
round = validator.round.number,
round = validator.last.number,
parents = parents,
transactions = transactions
)
validator.round.slots[validator.identifier] = ProposerSlot.init(blck)
validator.last.slots[validator.identifier] = ProposerSlot.init(blck)
validator.updateCertified(blck)
validator.identity.sign(blck)
func receive*(validator: Validator, signed: SignedBlock) =
validator.round.slots[signed.blck.author] = ProposerSlot.init(signed.blck)
validator.last.slots[signed.blck.author] = ProposerSlot.init(signed.blck)
validator.updateSkipped(signed.blck)
validator.updateCertified(signed.blck)
func round(validator: Validator, number: uint64): auto =
var round = validator.round
var round = validator.last
while round.number > number and previous =? round.previous:
round = previous
if round.number == number: