introduce committee with stakes

This commit is contained in:
Mark Spanbroek 2024-09-18 11:42:59 +02:00
parent 0102e17efb
commit 67f9f1e149
3 changed files with 52 additions and 33 deletions

View File

@ -1,6 +1,7 @@
import ./mysticeti/validator
export validator.Validator
export validator.Committee
export validator.ProposalStatus
export validator.new
export validator.identifier
@ -24,6 +25,9 @@ export blocks.signer
import ./mysticeti/signing
export signing.Identity
export signing.init
export signing.identifier
export signing.`$`
import ./mysticeti/hashing

View File

@ -6,7 +6,11 @@ import ./blocks
type
Validator*[Signing, Hashing] = ref object
identity: Identity[Signing]
committee: Committee[Signing]
round: Round[Signing, Hashing]
Committee*[Signing] = ref object
stakes: Table[Identifier[Signing], Stake]
Stake = float64
Round[Signing, Hashing] = ref object
number: uint64
previous: ?Round[Signing, Hashing]
@ -19,10 +23,12 @@ type
toSkip
toCommit
proc new*(T: type Validator): T =
let identity = Identity[T.Signing].init()
func new*(T: type Validator; identity: Identity, committee: Committee): T =
let round = Round[T.Signing, T.Hashing](number: 0)
T(identity: identity, round: round)
T(identity: identity, committee: committee, round: round)
func new*(_: type Committee, stakes: openArray[(Identifier, Stake)]): auto =
Committee[Identifier.Signing](stakes: stakes.toTable)
func new*(_: type Round, number: uint64, previous: Round): auto =
Round(number: number, previous: some previous)

View File

@ -7,55 +7,64 @@ import ./mocks
suite "Validator":
type Validator = mysticeti.Validator[MockSigning, MockHashing]
type Identity = mysticeti.Identity[MockSigning]
var validator: Validator
var validator2, validator3: Validator
var validator1, validator2, validator3, validator4: Validator
setup:
validator = Validator.new()
validator2 = Validator.new()
validator3 = Validator.new()
let identity1, identity2, identity3, identity4 = Identity.init()
let committee = Committee.new({
identity1.identifier: 1/4,
identity2.identifier: 1/4,
identity3.identifier: 1/4,
identity4.identifier: 1/4
})
validator1 = Validator.new(identity1, committee)
validator2 = Validator.new(identity2, committee)
validator3 = Validator.new(identity3, committee)
validator4 = Validator.new(identity4, committee)
test "has a unique identifier":
check Validator.new().identifier != Validator.new().identifier
test "starts at round 0":
check validator.round == 0
check validator1.round == 0
test "can move to next round":
validator.nextRound()
check validator.round == 1
validator.nextRound()
validator.nextRound()
check validator.round == 3
validator1.nextRound()
check validator1.round == 1
validator1.nextRound()
validator1.nextRound()
check validator1.round == 3
test "validators sign their proposals":
let proposal = validator.propose(seq[Transaction].example)
check proposal.blck.author == validator.identifier
check proposal.signer == validator.identifier
let proposal = validator1.propose(seq[Transaction].example)
check proposal.blck.author == validator1.identifier
check proposal.signer == validator1.identifier
test "validator cannot propose more than once in a round":
discard validator.propose(seq[Transaction].example)
discard validator1.propose(seq[Transaction].example)
expect AssertionDefect:
discard validator.propose(seq[Transaction].example)
discard validator1.propose(seq[Transaction].example)
test "by default our own proposals are undecided":
let proposal = validator.propose(seq[Transaction].example)
check validator.status(proposal) == some ProposalStatus.undecided
let proposal = validator1.propose(seq[Transaction].example)
check validator1.status(proposal) == some ProposalStatus.undecided
test "by default received proposals are undecided":
let proposal = validator2.propose(seq[Transaction].example)
validator.receive(proposal)
check validator.status(proposal) == some ProposalStatus.undecided
validator1.receive(proposal)
check validator1.status(proposal) == some ProposalStatus.undecided
test "validator includes blocks from previous round as parents":
let proposal1 = validator.propose(seq[Transaction].example)
let proposal1 = validator1.propose(seq[Transaction].example)
let proposal2 = validator2.propose(seq[Transaction].example)
let proposal3 = validator3.propose(seq[Transaction].example)
validator.receive(proposal2)
validator.receive(proposal3)
validator.nextRound()
let proposal4 = validator.propose(seq[Transaction].example)
check proposal1.blck.blockHash in proposal4.blck.parents
check proposal2.blck.blockHash in proposal4.blck.parents
check proposal3.blck.blockHash in proposal4.blck.parents
let proposal4 = validator4.propose(seq[Transaction].example)
validator1.receive(proposal2)
validator1.receive(proposal3)
validator1.receive(proposal4)
validator1.nextRound()
let proposal5 = validator1.propose(seq[Transaction].example)
check proposal1.blck.blockHash in proposal5.blck.parents
check proposal2.blck.blockHash in proposal5.blck.parents
check proposal3.blck.blockHash in proposal5.blck.parents
check proposal4.blck.blockHash in proposal5.blck.parents