Happy case
This commit is contained in:
parent
a0254971dc
commit
7774109b96
137
carnot/spec.md
137
carnot/spec.md
|
@ -114,7 +114,6 @@ class Timeout:
|
||||||
view: View ### Currently the 3 QC fields are not being used. But I am keeping it as it might be useful to save a roundtrip during unhappy path.
|
view: View ### Currently the 3 QC fields are not being used. But I am keeping it as it might be useful to save a roundtrip during unhappy path.
|
||||||
high_qcs: list[Qc]
|
high_qcs: list[Qc]
|
||||||
high_committed_qc : Qc
|
high_committed_qc : Qc
|
||||||
timeout_qc: Qc
|
|
||||||
sender: Id
|
sender: Id
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -178,9 +177,8 @@ The following functions are expected to be available to participants during the
|
||||||
* `child_committee(participant)`: returns true if the participant passed as argument is member of the child committee of the participant executing the function.
|
* `child_committee(participant)`: returns true if the participant passed as argument is member of the child committee of the participant executing the function.
|
||||||
|
|
||||||
* `supermajority()`: the behavior changes with the position of a participant in the overlay:
|
* `supermajority()`: the behavior changes with the position of a participant in the overlay:
|
||||||
* Root committee: returns if the number of distinctive signers of votes for a block in the child committee is equal to the threshold.
|
* committee members: returns if the number of distinctive signers of votes, for a block in the child committee is equal to the threshold.
|
||||||
|
* For leader: returns if the number of distinct voters for a block is 2/3 + 1 for both children committees of root committee and overall 2/3 + 1
|
||||||
* `leader_supermajority(votes, TimeoutMsgs)`: returns if the number of distinct voters for a block is 2/3 + 1 for both children committees of root committee and overall 2/3 + 1
|
|
||||||
|
|
||||||
* `morethanSsupermajority(votes)`: returns if the number of distinctive signers of votes for a block is is more than the threshold: TODO
|
* `morethanSsupermajority(votes)`: returns if the number of distinctive signers of votes for a block is is more than the threshold: TODO
|
||||||
* `parent_committe`: return the parent committee of the participant executing the function withing the committee tree overlay. Result is undefined if called from a participant in the root committee.
|
* `parent_committe`: return the parent committee of the participant executing the function withing the committee tree overlay. Result is undefined if called from a participant in the root committee.
|
||||||
|
@ -237,7 +235,7 @@ def safe_block_qc (block: Block):
|
||||||
# if standard.view <= LATEST_COMMITED_BLOCK:
|
# if standard.view <= LATEST_COMMITED_BLOCK:
|
||||||
if standard.view < CURRENT_VIEW:
|
if standard.view < CURRENT_VIEW:
|
||||||
return False
|
return False
|
||||||
increment_view_qc(standard.view+1)
|
# increment_view_qc(standard.view+1)
|
||||||
|
|
||||||
# this check makes sure block is not old
|
# this check makes sure block is not old
|
||||||
# and the previous leader did not fail
|
# and the previous leader did not fail
|
||||||
|
@ -262,7 +260,7 @@ def try_to_commit_grand_parent(block: Block):
|
||||||
grand_parent = parent.parent()
|
grand_parent = parent.parent()
|
||||||
return (
|
return (
|
||||||
parent.view == (grand_parent.view + 1) and
|
parent.view == (grand_parent.view + 1) and
|
||||||
isinstance(block.qc, (StandardQc, )) and # Q: Is this necessary?
|
isinstance(block.qc, (StandardQc, )) and # Q: Is this necessary? Yes, this is very important for safety.
|
||||||
isinstance(parent.qc, (StandardQc, )) # Q: Is this necessary?
|
isinstance(parent.qc, (StandardQc, )) # Q: Is this necessary?
|
||||||
)
|
)
|
||||||
# Update last_committed_view ?
|
# Update last_committed_view ?
|
||||||
|
@ -279,13 +277,13 @@ def update_high_qc(qc: Qc):
|
||||||
LOCAL_HIGH_QC = qc
|
LOCAL_HIGH_QC = qc
|
||||||
# Q: The original pseudocde checked for possilbly
|
# Q: The original pseudocde checked for possilbly
|
||||||
# missing view and downloaded them, but I think
|
# missing view and downloaded them, but I think
|
||||||
# we already dealt with this in receive_block
|
# we already dealt with this in receive_block (You are right!)
|
||||||
# Unhappy case
|
# Unhappy case
|
||||||
case Aggregate() as qc:
|
case Aggregate() as qc:
|
||||||
high_qc = qc.high_qc()
|
high_qc = qc.high_qc()
|
||||||
if high_qc.view != LOCAL_HIGH_QC.view:
|
if high_qc.view != LOCAL_HIGH_QC.view:
|
||||||
LOCAL_HIGH_QC = high_qc
|
LOCAL_HIGH_QC = high_qc
|
||||||
# Q: same thing about missing views
|
# Q: same thing about missing views. (some missing views may not have even generated any blocks.)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Receive Vote
|
### Receive Vote
|
||||||
|
@ -298,103 +296,73 @@ def receive_vote(vote: Vote):
|
||||||
if vote.block is missing:
|
if vote.block is missing:
|
||||||
block = download(vote.block)
|
block = download(vote.block)
|
||||||
receive(block)
|
receive(block)
|
||||||
|
|
||||||
|
if leader(vote.view+1): # Q? Which view? CURRENT_VIEW or vote.view? => Ans: vote.view+1 Vote for the view
|
||||||
|
if root_commitee(vote.voter):
|
||||||
|
if vote.view < CURRENT_VIEW - 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Q: No filtering? I can just create a key and vote?
|
||||||
|
PENDING_VOTE_COLLECTION[vote.block].append(vote)
|
||||||
|
if len(PENDING_VOTE_COLLECTION[vote.block])==supermajority():
|
||||||
|
qc = build_qc(PENDING_VOTE_COLLECTION[vote.block])
|
||||||
|
block = build_block(qc)
|
||||||
|
broadcast(block)
|
||||||
|
|
||||||
# Q: we should probably return if we already received this vote
|
# Q: we should probably return if we already received this vote
|
||||||
if member_of_internal_com() and not_member_of_root():
|
if member_of_internal_com() and not_member_of_root():
|
||||||
if child_commitee(vote.voter):
|
if child_commitee(vote.voter):
|
||||||
COLLECTION[vote.block].append(vote)
|
PENDING_VOTE_COLLECTION[vote.block].append(vote)
|
||||||
else:
|
# else:
|
||||||
# Q: not returning here would mean it's extremely easy to
|
# Q: not returning here would mean it's extremely easy to
|
||||||
# trigger building a new vote in the following branches
|
# trigger building a new vote in the following branches
|
||||||
return
|
# return
|
||||||
|
# (return is not necessary as long as it stays within if scope)
|
||||||
if supermajority(COLLECTION[vote.block]):
|
if len(PENDING_VOTE_COLLECTION[vote.block])==supermajority():
|
||||||
# Q: should we send it to everyone in the committee?
|
# Q: should we send it to everyone in the committee?
|
||||||
self_vote = build_vote()
|
self_vote = build_vote()
|
||||||
send(self_vote, parent_committee)
|
send(self_vote, parent_committee)
|
||||||
# Q: why here?
|
# Q: why here?
|
||||||
current_view += 1 # increment_view should be used instead of this.
|
|
||||||
|
# reset_timer()
|
||||||
reset_timer()
|
# Q: why do we do this here?
|
||||||
# Q: why do we do this here?
|
# try_to_commit_grand_parent(block) (Not needed)
|
||||||
try_to_commit_grand_parent(block)
|
|
||||||
|
|
||||||
if member_of_root():
|
if member_of_root():
|
||||||
if child_commitee(vote.voter):
|
if child_commitee(vote.voter):
|
||||||
COLLECTION[vote.block].append(vote)
|
PENDING_VOTE_COLLECTION[vote.block].append(vote)
|
||||||
else:
|
# else:
|
||||||
# Q: not returning here would mean it's extremely easy to
|
# Q: not returning here would mean it's extremely easy to
|
||||||
# trigger building a new vote in the following branches
|
# trigger building a new vote in the following branches
|
||||||
return
|
# return
|
||||||
|
# Ans: return is not necessary as long as it stays within if scope
|
||||||
|
|
||||||
if supermajority(COLLECTION[vote.block]):
|
|
||||||
# Q: The vote to send is not the one received but
|
# Q: The vote to send is not the one received but
|
||||||
# the one build by this participant, right?
|
|
||||||
self_vote = build_vote();
|
if len(PENDING_VOTE_COLLECTION[vote.block])==supermajority():
|
||||||
qc = build_qc(collection[vote.block])
|
# Q: The vote to send is not the one received but
|
||||||
self_vote.qc=qc
|
# the one build by this participant, right?
|
||||||
send(self_vote, leader(current_view + 1))
|
self_vote = build_vote();
|
||||||
# Q: why here?
|
qc = build_qc(PENDING_VOTE_COLLECTION[vote.block])
|
||||||
current_view += 1
|
self_vote.qc=qc
|
||||||
reset_timer()
|
send(self_vote, leader(current_view + 1))
|
||||||
# Q: why here?
|
|
||||||
try_to_commit_grandparent(block)
|
|
||||||
|
|
||||||
|
|
||||||
# Q: this means that we send a message for every incoming
|
# Q: this means that we send a message for every incoming
|
||||||
# message after the threshold has been reached, i.e. a vote
|
# message after the threshold has been reached, i.e. a vote
|
||||||
# from a node in the leaf committee can trigger
|
# from a node in the leaf committee can trigger
|
||||||
# at least height(tree) messages.
|
# at least height(tree) messages.
|
||||||
if morethanSsupermajority(collection[vote.block]):
|
if len(PENDING_VOTE_COLLECTION[vote.block]) > supermajority():
|
||||||
# just forward the vote to the leader
|
# just forward the vote to the leader
|
||||||
# Q: But then childcommitte(vote.voter) would return false
|
# Q: But then childcommitte(vote.voter) would return false
|
||||||
# in the leader, as it's a granchild, not a child
|
# in the leader, as it's a granchild, not a child
|
||||||
send(vote, leader(current_view + 1))
|
send(vote, leader(current_view + 1))
|
||||||
|
|
||||||
if leader(vote.view+1): # Q? Which view? CURRENT_VIEW or vote.view? => Ans: vote.view+1 Vote for the view
|
|
||||||
if vote.view < CURRENT_VIEW - 1:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Q: No filtering? I can just create a key and vote?
|
|
||||||
COLLECTION[vote.block].append(vote)
|
|
||||||
if supermajority(collection[vote.block]):
|
|
||||||
qc = build_qc(collection[vote.block])
|
|
||||||
block = build_block(qc)
|
|
||||||
broadcast(block)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Receive NewView ===> We are not using NewView any more but use timeoutMsg instead.
|
|
||||||
```Ruby
|
|
||||||
# Failure Case
|
|
||||||
Func receive(newView) {
|
|
||||||
# download the missing block
|
|
||||||
if newview.highQC.block missing {
|
|
||||||
let block = download(new_view.high_qc.block)
|
|
||||||
receive(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
# It's an old message. Ignore it.
|
|
||||||
if newView.view < current_view {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
# Q: this was update_high_qc_and_view(new_view.high_qc, Null)
|
|
||||||
update_high_qc(new_view.high_qc)
|
|
||||||
|
|
||||||
if member_of_internal_com() {
|
|
||||||
collection[newView.view].append(newView)
|
|
||||||
if supermajority[newView.view]{
|
|
||||||
newViewQC=buildQC(collection[newView.view])
|
|
||||||
if member_of_root(){
|
|
||||||
send(newViewQC, leader(view+1))
|
|
||||||
curView++
|
|
||||||
} else {
|
|
||||||
send(newViewQC, parent_committee())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
###### This is all part of pacemaker (liveness) module
|
###### This is all part of pacemaker (liveness) module
|
||||||
### Timeout
|
### Timeout
|
||||||
```python3
|
```python3
|
||||||
|
@ -463,7 +431,8 @@ def receive_syncMsg(sync_Msg: Sync_Msg):
|
||||||
high_qc=sync_Msg.qc
|
high_qc=sync_Msg.qc
|
||||||
if sync_Msg.committed_qc.view>high_committed_qc.view:
|
if sync_Msg.committed_qc.view>high_committed_qc.view:
|
||||||
high_committed_qc=sync_Msg.committed_qc
|
high_committed_qc=sync_Msg.committed_qc
|
||||||
|
|
||||||
|
PENDING_SYNCMSG_COLLECTION[sync_Msg.view].append(sync_Msg)
|
||||||
if len(PENDING_SYNCMSG_COLLECTION[sync_Msg.view])== supermajority():
|
if len(PENDING_SYNCMSG_COLLECTION[sync_Msg.view])== supermajority():
|
||||||
if member_of_internal() and not member_of_root():
|
if member_of_internal() and not member_of_root():
|
||||||
sync_Msg = create_sync_Msg (CURRENT_VIEW, high_qc, high_committed_qc)
|
sync_Msg = create_sync_Msg (CURRENT_VIEW, high_qc, high_committed_qc)
|
||||||
|
|
Loading…
Reference in New Issue