commit blocks that are certified by >2f validators

This commit is contained in:
Mark Spanbroek 2024-09-19 10:08:42 +02:00
parent 666835dd03
commit d491b68843
2 changed files with 69 additions and 0 deletions

View File

@ -17,6 +17,7 @@ type
ProposerSlot[Signing, Hashing] = object
proposal: Block[Signing, Hashing]
skippedBy: Stake
certifiedBy: Stake
status: ProposalStatus
ProposalStatus* = enum
undecided
@ -78,9 +79,34 @@ func updateSkipped(validator: Validator, received: Block) =
if slot.skippedBy > 2/3:
slot.status = ProposalStatus.toSkip
func supports(blck: Block, round: uint64, author: Identifier): bool =
for parent in blck.parents:
if parent.round == round and parent.author == author:
return true
false
func updateCertified(validator: Validator, received: Block) =
# three rounds: proposing -> supporting -> certifying
let certifying = validator.round
without supporting =? certifying.previous:
return
without proposing =? supporting.previous:
return
for (proposerId, proposerSlot) in proposing.slots.mpairs:
var support: Stake
for (supporterId, supporterSlot) in supporting.slots.pairs:
if received.supports(supporting.number, supporterId):
if supporterSlot.proposal.supports(proposing.number, proposerId):
support += validator.committee.stake(supporterId)
if support > 2/3:
proposerSlot.certifiedBy += validator.committee.stake(received.author)
if proposerSlot.certifiedBy > 2/3:
proposerSlot.status = ProposalStatus.toCommit
func receive*(validator: Validator, signed: SignedBlock) =
validator.round.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

View File

@ -83,3 +83,46 @@ suite "Validator":
check validator1.status(proposal) == some ProposalStatus.undecided
validator1.receive(validator4.propose(seq[Transaction].example))
check validator1.status(proposal) == some ProposalStatus.toSkip
test "commits blocks that have >2f certificates":
let proposal1 = validator1.propose(seq[Transaction].example)
let proposal2 = validator2.propose(seq[Transaction].example)
let proposal3 = validator3.propose(seq[Transaction].example)
let proposal4 = validator4.propose(seq[Transaction].example)
validator1.receive(proposal2)
validator1.receive(proposal3)
validator1.receive(proposal4)
validator2.receive(proposal1)
validator2.receive(proposal3)
validator2.receive(proposal4)
validator3.receive(proposal1)
validator3.receive(proposal2)
validator3.receive(proposal4)
validator4.receive(proposal1)
validator4.receive(proposal2)
validator4.receive(proposal3)
nextRound()
let proposal5 = validator1.propose(seq[Transaction].example)
let proposal6 = validator2.propose(seq[Transaction].example)
let proposal7 = validator3.propose(seq[Transaction].example)
let proposal8 = validator4.propose(seq[Transaction].example)
validator1.receive(proposal6)
validator1.receive(proposal7)
validator1.receive(proposal8)
validator2.receive(proposal5)
validator2.receive(proposal7)
validator2.receive(proposal8)
validator3.receive(proposal5)
validator3.receive(proposal6)
validator3.receive(proposal8)
validator4.receive(proposal5)
validator4.receive(proposal6)
validator4.receive(proposal7)
nextRound()
let proposal10 = validator2.propose(seq[Transaction].example)
let proposal11 = validator3.propose(seq[Transaction].example)
let proposal12 = validator4.propose(seq[Transaction].example)
validator1.receive(proposal10)
validator1.receive(proposal11)
check validator1.status(proposal1) == some ProposalStatus.undecided
validator1.receive(proposal12)
check validator1.status(proposal1) == some ProposalStatus.toCommit