Merge branch 'master' into UnhappyPathAndPaceMaker
This commit is contained in:
commit
3d9e1004b1
|
@ -0,0 +1,79 @@
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.serpython
|
||||||
|
python
|
||||||
|
venv
|
|
@ -1,25 +1,21 @@
|
||||||
Psuedocode specification of the Carnot consensus algorithm.
|
# Carnot Specification
|
||||||
|
This is the pseudocode specification of the Carnot consensus algorithm.
|
||||||
In this specification we will omit any cryptographic material, block validity and proof checks. A real implementation is expected to check those before hitting this code.
|
In this specification we will omit any cryptographic material, block validity and proof checks. A real implementation is expected to check those before hitting this code.
|
||||||
In addition, all types can be expected to have their invariants checked by the type contract, e.g. in an instance of type `Qc::Aggregate` the `high_qc` field is always the most recent qc among the aggregate qcs and the code can skip this check.
|
In addition, all types can be expected to have their invariants checked by the type contract, e.g. in an instance of type `Qc::Aggregate` the `high_qc` field is always the most recent qc among the aggregate qcs and the code can skip this check.
|
||||||
|
|
||||||
'Q:' is used to indicate unresolved questions.
|
'Q:' is used to indicate unresolved questions.
|
||||||
Notation is loosely based on CDDL.
|
Notation is loosely based on CDDL.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
A critical piece in the protocol, these are the different kind of messages used by participants during the protocol execution.
|
A critical piece in the protocol, these are the different kind of messages used by participants during the protocol execution.
|
||||||
* `Block`: propose a new block
|
* `Block`: propose a new block
|
||||||
* `Vote`: vote for a block proposal
|
* `Vote`: vote for a block proposal
|
||||||
* `TimeoutMsg`: propose to jump to a new (next) view after a proposal for the current one was not received before a configurable timeout.
|
* `Timeout`: propose to jump to a new view after a proposal for the current one was not received before a configurable timeout.
|
||||||
|
|
||||||
|
|
||||||
### Block
|
### Block
|
||||||
|
|
||||||
(sometimes also called proposal)
|
(sometimes also called proposal)
|
||||||
```
|
|
||||||
view: View
|
|
||||||
qc: Qc
|
|
||||||
```
|
|
||||||
We assume an unique identifier of the block can be obtained, for example by hashing its contents. We will use the `id()` function to access the identifier of the current block.
|
We assume an unique identifier of the block can be obtained, for example by hashing its contents. We will use the `id()` function to access the identifier of the current block.
|
||||||
We also assume that a unique tree order of blocks can be determined, and in particular each participant can identify the parent of each block. We will use the `parent()` function to access such parent block.
|
We also assume that a unique tree order of blocks can be determined, and in particular each participant can identify the parent of each block. We will use the `parent()` function to access such parent block.
|
||||||
|
|
||||||
|
@ -31,51 +27,37 @@ class Block:
|
||||||
```
|
```
|
||||||
|
|
||||||
##### View
|
##### View
|
||||||
```
|
|
||||||
view_n: uint
|
A monotonically increasing number (considerations about the size?)
|
||||||
```
|
|
||||||
a monotonically increasing number (considerations about the size?)
|
|
||||||
|
|
||||||
```python
|
```python
|
||||||
View = int
|
View = int
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Qc
|
##### Qc
|
||||||
There are currently two different types of QC:
|
|
||||||
```
|
|
||||||
Qc = Standard / Aggregate
|
|
||||||
```
|
|
||||||
|
|
||||||
|
There are currently two different types of QC:
|
||||||
```python
|
```python
|
||||||
Qc = StandardQc | AggregateQc
|
Qc = StandardQc | AggregateQc
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Standard
|
###### Standard
|
||||||
```
|
|
||||||
view: View
|
|
||||||
block: Id
|
|
||||||
```
|
|
||||||
Q: there can only be one block on which consensus in achieved for a view, so maybe the block field is redundant?
|
Q: there can only be one block on which consensus in achieved for a view, so maybe the block field is redundant?
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class StandardQc:
|
class StandardQc:
|
||||||
view: View
|
view: View
|
||||||
block: Id
|
block: Id
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Aggregate
|
###### Aggregate
|
||||||
```
|
|
||||||
view: View
|
|
||||||
high_qc: Qc
|
|
||||||
```
|
|
||||||
`high_qc` is `Qc` for the most recent view among the aggregated ones. The rest of the qcs are ignored in the rest of this algorithm.
|
`high_qc` is `Qc` for the most recent view among the aggregated ones. The rest of the qcs are ignored in the rest of this algorithm.
|
||||||
|
|
||||||
We assume there is a `block` function available that returns the block for the Qc. In case of a standard qc, this is trivially qc.block, while for aggregate it can be obtained by accessing `high_qc`. `high_qc` is guaranteed to be a 'Standard' qc.
|
We assume there is a `block` function available that returns the block for the Qc. In case of a standard qc, this is trivially qc.block, while for aggregate it can be obtained by accessing `high_qc`. `high_qc` is guaranteed to be a 'Standard' qc.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@dataclass
|
|
||||||
class AggregateQc:
|
class AggregateQc:
|
||||||
view: View
|
view: View
|
||||||
qcs: List[Qc]
|
qcs: List[Qc]
|
||||||
|
@ -88,21 +70,15 @@ class AggregateQc:
|
||||||
undef, will assume a 32-byte opaque string
|
undef, will assume a 32-byte opaque string
|
||||||
|
|
||||||
```python
|
```python
|
||||||
Id = bytearray
|
Id: bytes = bytearray(32)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Vote
|
### Vote
|
||||||
|
|
||||||
A vote for `block` in `view`
|
A vote for `block` in `view`
|
||||||
```
|
|
||||||
block: Id
|
|
||||||
view: View
|
|
||||||
voter: Id
|
|
||||||
? qc: Qc
|
|
||||||
```
|
|
||||||
qc is the optional field containing the QC built by root nodes from 2/3 + 1 votes from their child committees and forwarded the the next view leader.
|
qc is the optional field containing the QC built by root nodes from 2/3 + 1 votes from their child committees and forwarded the the next view leader.
|
||||||
# While adding votes, timeout msgs etc, make sure duplicate msgs are discarded.
|
|
||||||
```python
|
```python
|
||||||
@dataclass
|
|
||||||
class Vote:
|
class Vote:
|
||||||
block: Id
|
block: Id
|
||||||
view: View
|
view: View
|
||||||
|
@ -127,6 +103,12 @@ class TimeoutMsg:
|
||||||
timeout_qc: Qc
|
timeout_qc: Qc
|
||||||
sender: Id
|
sender: Id
|
||||||
|
|
||||||
|
### Timeout
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Timeout:
|
||||||
|
view: View
|
||||||
|
high_qc: Qc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Local Variables
|
## Local Variables
|
||||||
|
@ -190,9 +172,11 @@ The following functions are expected to be available to participants during the
|
||||||
|
|
||||||
|
|
||||||
## Core functions
|
## Core functions
|
||||||
|
|
||||||
These are the core functions necessary for the Carnot consensus protocol, to be executed in response of incoming messages, except for `timeout` which is triggered by a participant configurable timer.
|
These are the core functions necessary for the Carnot consensus protocol, to be executed in response of incoming messages, except for `timeout` which is triggered by a participant configurable timer.
|
||||||
|
|
||||||
### Receive block
|
### Receive block
|
||||||
|
|
||||||
```python3
|
```python3
|
||||||
def receive_block(block: Block):
|
def receive_block(block: Block):
|
||||||
if block.id() is known or block.view <=LATEST_COMMITTED_VIEW:
|
if block.id() is known or block.view <=LATEST_COMMITTED_VIEW:
|
||||||
|
@ -217,12 +201,12 @@ def receive_block(block: Block):
|
||||||
else:
|
else:
|
||||||
send(vote, parent_commitee())
|
send(vote, parent_commitee())
|
||||||
current_view += 1
|
current_view += 1
|
||||||
reset_timer(current_view) # needs to be updated after pacemaker is completed.
|
reset_timer()
|
||||||
try_to_commit_grandparent(block)
|
try_to_commit_grandparent(block)
|
||||||
```
|
```
|
||||||
##### Auxiliary functions
|
##### Auxiliary functions
|
||||||
```python
|
|
||||||
|
|
||||||
|
```python
|
||||||
def safe_block(block: Block):
|
def safe_block(block: Block):
|
||||||
match block.qc:
|
match block.qc:
|
||||||
case StandardQc() as standard:
|
case StandardQc() as standard:
|
||||||
|
@ -279,7 +263,9 @@ def update_high_qc(qc: Qc):
|
||||||
```
|
```
|
||||||
|
|
||||||
### Receive Vote
|
### Receive Vote
|
||||||
|
|
||||||
Q: this whole function needs to be revised
|
Q: this whole function needs to be revised
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
|
||||||
def receive_vote(vote: Vote):
|
def receive_vote(vote: Vote):
|
||||||
|
|
Loading…
Reference in New Issue