mirror of
https://github.com/logos-storage/nim-mysticeti.git
synced 2026-01-02 13:43:09 +00:00
simulate scenario from figure 4 in the Mysticeti paper
needed fix: call updateSkipped() when proposing a block
This commit is contained in:
parent
f5fdf8e581
commit
b757074193
@ -70,6 +70,12 @@ func updateCertified(validator: Validator, certificate: Block) =
|
||||
let stake = validator.committee.stake(certificate.author)
|
||||
proposal.certifyBy(certificate.id, stake)
|
||||
|
||||
func addBlock(validator: Validator, signedBlock: SignedBlock) =
|
||||
if round =? validator.rounds.latest.find(signedBlock.blck.round):
|
||||
round.addProposal(signedBlock)
|
||||
validator.updateSkipped(signedBlock.blck)
|
||||
validator.updateCertified(signedBlock.blck)
|
||||
|
||||
proc propose*(validator: Validator, transactions: seq[Transaction]): auto =
|
||||
type SignedBlock = blocks.SignedBlock[Validator.Signing, Validator.Hashing]
|
||||
let round = validator.rounds.latest
|
||||
@ -93,8 +99,7 @@ proc propose*(validator: Validator, transactions: seq[Transaction]): auto =
|
||||
transactions = transactions
|
||||
)
|
||||
let signedBlock = validator.identity.sign(blck)
|
||||
round.addProposal(signedBlock)
|
||||
validator.updateCertified(blck)
|
||||
validator.addBlock(signedBlock)
|
||||
success signedBlock
|
||||
|
||||
func check*(validator: Validator, signed: SignedBlock): auto =
|
||||
@ -134,10 +139,7 @@ func check*(validator: Validator, signed: SignedBlock): auto =
|
||||
BlockCheck.correct(signed)
|
||||
|
||||
func receive*(validator: Validator, correct: CorrectBlock) =
|
||||
if round =? validator.rounds.latest.find(correct.blck.round):
|
||||
round.addProposal(correct.signedBlock)
|
||||
validator.updateSkipped(correct.blck)
|
||||
validator.updateCertified(correct.blck)
|
||||
validator.addBlock(correct.signedBlock)
|
||||
|
||||
func getBlock*(validator: Validator, id: BlockId): auto =
|
||||
validator.rounds.latest.find(id)
|
||||
|
||||
52
tests/mysticeti/scenarios.nim
Normal file
52
tests/mysticeti/scenarios.nim
Normal file
@ -0,0 +1,52 @@
|
||||
import ./basics
|
||||
import ./simulator
|
||||
|
||||
proc scenarioFigure4*(simulator: NetworkSimulator): ?!seq[seq[SignedBlock]] =
|
||||
# replays scenario from Figure 4 in the Mysticeti paper
|
||||
# https://arxiv.org/pdf/2310.14821v4
|
||||
# note: round robin is not applied correctly in the figure from
|
||||
# the Mysticeti paper, so this simulation uses different proposer
|
||||
# labels from the fourth round
|
||||
var proposals: seq[seq[SignedBlock]]
|
||||
proposals.add(? simulator.exchangeProposals {
|
||||
0: @[0, 1, 2, 3],
|
||||
1: @[0, 1],
|
||||
2: @[0, 2, 3],
|
||||
3: @[1, 2, 3]
|
||||
})
|
||||
simulator.nextRound()
|
||||
proposals.add(? simulator.exchangeProposals {
|
||||
0: @[0, 1, 3],
|
||||
1: @[0, 1, 3],
|
||||
2: @[0, 3],
|
||||
3: @[1, 3]
|
||||
})
|
||||
simulator.nextRound()
|
||||
proposals.add(? simulator.exchangeProposals {
|
||||
0: @[2, 3, 0, 1],
|
||||
1: @[2, 3, 0, 1],
|
||||
|
||||
3: @[2, 3, 0, 1]
|
||||
})
|
||||
simulator.nextRound()
|
||||
proposals.add(? simulator.exchangeProposals {
|
||||
2: @[2, 3, 0, 1],
|
||||
3: @[3],
|
||||
0: @[2, 3, 0, 1],
|
||||
1: @[2, 3, 0, 1]
|
||||
})
|
||||
simulator.nextRound()
|
||||
proposals.add(? simulator.exchangeProposals {
|
||||
2: @[],
|
||||
3: @[2, 3, 0],
|
||||
0: @[2, 3, 0],
|
||||
1: @[2, 3, 0]
|
||||
})
|
||||
simulator.nextRound()
|
||||
proposals.add(? simulator.exchangeProposals {
|
||||
2: @[2, 3, 0],
|
||||
3: @[2, 3, 0],
|
||||
0: @[2, 3, 0]
|
||||
|
||||
})
|
||||
success proposals
|
||||
@ -2,9 +2,9 @@ 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[MockSigning, MockHashing]
|
||||
type Identity* = mysticeti.Identity[MockSigning]
|
||||
type SignedBlock* = blocks.SignedBlock[MockSigning, MockHashing]
|
||||
|
||||
type NetworkSimulator* = object
|
||||
identities: seq[Identity]
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import ../basics
|
||||
import ../simulator
|
||||
import ../scenarios
|
||||
import mysticeti
|
||||
import mysticeti/blocks
|
||||
import mysticeti/hashing
|
||||
@ -269,70 +270,11 @@ suite "Multiple Validators":
|
||||
check toSeq(simulator.validators[0].committed()) == second
|
||||
|
||||
test "commits blocks using the indirect decision rule":
|
||||
# first round: proposals
|
||||
let proposals = !simulator.exchangeProposals {
|
||||
0: @[0, 1, 2, 3],
|
||||
1: @[0, 1],
|
||||
2: @[0, 2, 3],
|
||||
3: @[1, 2, 3]
|
||||
}
|
||||
# second round: voting
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals {
|
||||
0: @[0, 1, 3],
|
||||
1: @[0, 1, 3],
|
||||
2: @[0, 3],
|
||||
3: @[1, 3]
|
||||
}
|
||||
# third round: certifying
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals {
|
||||
0: @[0, 1, 2, 3],
|
||||
1: @[0, 1, 2, 3],
|
||||
3: @[0, 1, 2, 3]
|
||||
}
|
||||
# fourth round: anchor
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals()
|
||||
# fifth round: voting on anchor
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals()
|
||||
# sixth round: certifying anchor
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals()
|
||||
check toSeq(simulator.validators[0].committed()).contains(proposals[3].blck)
|
||||
let proposals = !scenarioFigure4(simulator)
|
||||
let committed = toSeq(simulator.validators[0].committed())
|
||||
check committed.contains(proposals[0][3].blck)
|
||||
|
||||
test "skips blocks using the indirect decision rule":
|
||||
# Modelled after Figure 3f from the Mysticeti paper
|
||||
# first round: proposals
|
||||
let proposals = !simulator.exchangeProposals {
|
||||
0: @[0, 1, 2, 3],
|
||||
1: @[0, 1],
|
||||
2: @[0, 2, 3],
|
||||
3: @[1, 2, 3]
|
||||
}
|
||||
# second round: voting
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals {
|
||||
0: @[0, 1, 3],
|
||||
1: @[0, 1, 3],
|
||||
2: @[0, 3],
|
||||
3: @[1, 3]
|
||||
}
|
||||
# third round: certifying
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals {
|
||||
0: @[0, 1, 2, 3],
|
||||
1: @[0, 1, 2, 3],
|
||||
3: @[0, 1, 2, 3]
|
||||
}
|
||||
# fourth round: anchor
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals()
|
||||
# fifth round: voting on anchor
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals()
|
||||
# sixth round: certifying anchor
|
||||
simulator.nextRound()
|
||||
discard !simulator.exchangeProposals()
|
||||
check not toSeq(simulator.validators[0].committed()).contains(proposals[1].blck)
|
||||
let proposals = !scenarioFigure4(simulator)
|
||||
let committed = toSeq(simulator.validators[0].committed())
|
||||
check not committed.contains(proposals[0][1].blck)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user