Skip to content

Commit

Permalink
Detach the implementation of RRSC from the forked Substrate repositor…
Browse files Browse the repository at this point in the history
…y and point the Substrate and Frontier libraries to the Party's official repository.
  • Loading branch information
0xbillw committed Nov 22, 2023
1 parent 4ec4c47 commit 5bb57ba
Show file tree
Hide file tree
Showing 33 changed files with 9,723 additions and 342 deletions.
613 changes: 432 additions & 181 deletions Cargo.lock

Large diffs are not rendered by default.

327 changes: 168 additions & 159 deletions Cargo.toml

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions crates/rrsc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[package]
name = "cessc-consensus-rrsc"
version = "0.10.0-dev"
authors = ["CESS"]
description = "RRSC consensus algorithm"
edition = "2021"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
homepage = "https://cess.one"
repository = "https://github.com/CESSProject/substrate"
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
async-trait = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.2.2", features = ["derive"] }
futures = { workspace = true }
log = { workspace = true }
num-bigint = { workspace = true }
num-rational = { workspace = true }
num-traits = { workspace = true }
parking_lot = { workspace = true }
thiserror = { workspace = true }
fork-tree = { workspace = true }
prometheus-endpoint = { workspace = true }
sc-client-api = { workspace = true }
sc-consensus = { workspace = true }
sc-consensus-epochs = { workspace = true }
sc-consensus-slots = { workspace = true }
sc-keystore = { workspace = true }
sc-telemetry = { workspace = true }
sp-api = { workspace = true }
sp-application-crypto = { workspace = true }
sp-block-builder = { workspace = true, features = ["std"]}
sp-blockchain = { workspace = true }
sp-consensus = { workspace = true }
sp-consensus-slots = { workspace = true }
sp-core = { workspace = true }
sp-inherents = { workspace = true }
sp-keystore = { workspace = true }
sp-runtime = { workspace = true }
cessp-consensus-rrsc = { workspace = true, features = ["std"]}

[dev-dependencies]
rand_chacha = { workspace = true }
sc-block-builder = { workspace = true }
sp-keyring = { workspace = true }
sc-network = { workspace = true }
sc-network-test = { workspace = true }
sp-timestamp = { workspace = true }
sp-tracing = { workspace = true }
substrate-test-runtime-client = { workspace = true }
tokio = { workspace = true }
139 changes: 139 additions & 0 deletions crates/rrsc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# RRSC (Random Rotational Selection Consensus)

## What is Consensus in Blockchain?

A consensus is a method used by nodes within a network to come into agreement. All nodes should come into agreement on a single state of the network at a given time. The nodes in a decentralized network stay synced with each other by adhering to the consensus mechanism. In the blockchain network, the consensus method helps generate new blocks and maintain the state of the network.

## Substrate Consensus

### Block Production: BABE

Blind Assignment for Blockchain Extension (BABE) is a block production mechanism that runs on validator nodes and determines the authors of new blocks.

Follow the following links to read more about BABE:

https://wiki.polkadot.network/docs/learn-consensus#block-production-babe

https://research.web3.foundation/en/latest/polkadot/block-production/Babe.html

BABE uses VRF for determining the next validator in every slot.

Slots are discrete units of time six seconds in length. Each slot can contain a block, but may not. Slots make up epochs - on Polkadot, 2400 slots make one epoch, which makes epochs four hours long.

In every slot, each validator "rolls a die". They execute a function (the VRF) that takes as input the following:

● The "secret key", a key specifically made for these die rolls.

● An epoch randomness value, which is the hash of VRF values from the blocks in the epoch before last (N-2), so past randomness affects the current pending randomness (N).

● The slot number.

# ![Figure 1](https://raw.githubusercontent.com/CESSProject/W3F-illustration/main/rrsc/image.png)

The output is two values: a RESULT (the random value) and a PROOF (a proof that the random value was generated correctly).

The RESULT is then compared to a threshold defined in the implementation of the protocol (specifically, in the Polkadot Host). If the value is less than the threshold, then the validator who rolled this number is a viable block production candidate for that slot. The validator then attempts to create a block and submits this block into the network along with the previously obtained PROOF and RESULT. Under VRF, every validator rolls a number for themselves, checks it against a threshold, and produces a block if the random roll is under that threshold.

The astute reader will notice that due to the way this works, some slots may have no validators as block producer candidates because all validator candidates rolled too high and missed the threshold. We clarify how we resolve this issue and make sure that Polkadot block times remain near constant-time in the wiki page on consensus.

## Random Rotational Selection(R²S)

### 1.1 Definitions

- **Slot**: Each slot will generate a new block, that is, the block out time. In the cess test network, 1 slot = 6 seconds.

- **Epoch**: A collection of fixed length slots. Each epoch will update the set of rotation nodes, but not every epoch will trigger the election. The election will be triggered in the first block from the sixth epoch of era. 1 epoch = 1 hour in the cess testnet.

- **Era**: A collection of multiple epochs. Era starts the new rotation node set in the first block, and settles the consensus award of the previous era. In the cess testnet, 1 era = 6 epoch, that is, 6 hours.

### 1.2 Overall process

R²S is an important part of CESS protocol. Compared with the polkadot consensus mechanism, R²S pays more attention to the process of node election and block generation. The following is the overall process:

1. The node has become a consensus node through pledge and registration, and the current pledge amount is 1 million.

2. In each round of era, the validators are rotated. The rotation rule is score ranking. The 11 nodes with the highest scores (4 in the cess testnet) are selected as the validators of era.

3. The final score is determined by reputation score and random score, that is, final score = `(reputation score * 80%) + (random score * 20%)`.

4. Please refer to the next section for credit score calculation, and the random score is determined by VRF.

5. The selected validators generate blocks in sequence.

6. The current way of confirming blocks is the same as GRANDPA.

7. The last epoch of each era starts the validators election of the next era.

<img src="https://raw.githubusercontent.com/CESSProject/W3F-illustration/main/rrsc/image1.png" width = "600" alt="name" align=center />

### 1.3 Reputation model

As each consensus node that joins the cess network needs to maintain the network state, it also needs to undertake the work of storage data scheduling. In order to encourage consensus nodes to do more such work, we designed a reputation model. In our model, each consensus node has a reputation score, which is directly determined by the workload of the scheduler. Specifically, it includes the following items:

1. Total bytes of idle segment processed.

2. Total of bytes of service segment processed.

3. Number of penalties for random challenge timeout of verification file.

Reputation value calculation as follow:

`Scheduler reputation value = 1000 * processing bytes ratio - (10 * penalty times)`

### 1.4 Code Walkthrough

#### 1. The election

final_score = `random_score` * 20% + `credit` * 80%

The final score of the node is composed of two parts, random score accounting for 20% of the weight and reputation score accounting for 80% of the weight. Arrange according to the scores from large to small, and select no more than 11 nodes with the highest scores as the rotation nodes.

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/frame/rrsc/src/vrf_solver.rs#L46-L48

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/frame/rrsc/src/vrf_solver.rs#L61-L62

#### 2. The random scores

- Use the `currentblockrandomness` random function to calculate a random hash value for each node.

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/frame/rrsc/src/vrf_solver.rs#L87-L99

- Convert random hash value to U32 type value.

- Modulo the full score of reputation score with U32 type value to obtain random score.

- During the production of each block, the vrfoutput obtained by executing the VRF function is written into the block header.

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/client/consensus/rrsc/src/authorship.rs#L185-L199

- When each block is initialized, vrfoutput is taken from the block header, converted into randomness, and stored in the authorvrrandomness of pallet rrsc as the seed for running the random function in the current block

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/frame/rrsc/src/lib.rs#L749

- Randomness stored in authorvrrandomness is used as seed, and random hash value is obtained through byte array inversion, splicing and hash operation.

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/frame/rrsc/src/randomness.rs#L136-L148

#### 3. Reputation scores

Obtain reputation scores of all candidate nodes during election

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/frame/rrsc/src/vrf_solver.rs#L33

#### 4. Block generation

- Rotation nodes take turns to output blocks.

- Modulo the number of rotation nodes with the slot serial number, and take the modulo value as the node taken from the subscript of the rotation node list, which is the block out node of this slot. Slot numbers are cumulative, so the out of block nodes take turns.

https://github.com/CESSProject/substrate/blob/6f338348a5488f56fd338ab678d57e30f456e802/client/consensus/rrsc/src/authorship.rs#L180-L181

### 1.5 Future work

Consensus is the foundation of the blockchain network, and it is necessary for us to continuously optimize it. At this stage, we have completed the realization of the core functions. But this is far from enough, and there are still many points that need to be improved in the future.

1. Adjust consensus-related RPC interfaces to adapt to applications such as block explorers.

2. According to the actual test situation, the reputation model is continuously iterated to make it more perfect.

3. A more concrete theoretical security analysis will be conducted.
68 changes: 68 additions & 0 deletions crates/rrsc/pallet/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
[package]
name = "pallet-rrsc"
version = "4.0.0-dev"
authors = ["CESS"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://cess.one"
repository = "https://github.com/CESSProject/substrate/"
description = "Consensus extension module for RRSC consensus. Collects on-chain randomness from VRF outputs and manages epoch transitions."
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] }
log = { workspace = true }
scale-info = { workspace = true, features = ["derive"] }
frame-benchmarking = { workspace = true, optional = true }
frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-authorship = { workspace = true }
pallet-session = { workspace = true }
pallet-timestamp = { workspace = true }
sp-application-crypto = { workspace = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-npos-elections = { workspace = true }
sp-runtime = { workspace = true }
sp-session = { workspace = true }
sp-staking = { workspace = true }
sp-std = { workspace = true }
frame-election-provider-support = { workspace = true }
cessp-consensus-rrsc = { workspace = true }

[dev-dependencies]
frame-election-provider-support = { workspace = true }
pallet-balances = { workspace = true }
pallet-offences = { workspace = true }
pallet-staking = { workspace = true }
pallet-staking-reward-curve = { workspace = true }
sp-core = { workspace = true }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking?/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-authorship/std",
"pallet-session/std",
"pallet-timestamp/std",
"scale-info/std",
"sp-application-crypto/std",
"cessp-consensus-rrsc/std",
"sp-core/std",
"sp-io/std",
"sp-runtime/std",
"sp-session/std",
"sp-staking/std",
"sp-std/std",
"sp-npos-elections/std",
"frame-election-provider-support/std",
]
runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
4 changes: 4 additions & 0 deletions crates/rrsc/pallet/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Consensus extension module for BABE consensus. Collects on-chain randomness
from VRF outputs and manages epoch transitions.

License: Apache-2.0
74 changes: 74 additions & 0 deletions crates/rrsc/pallet/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Benchmarks for the RRSC Pallet.

#![cfg(feature = "runtime-benchmarks")]

use super::*;
use frame_benchmarking::benchmarks;

type Header = sp_runtime::generic::Header<u64, sp_runtime::traits::BlakeTwo256>;

benchmarks! {
check_equivocation_proof {
let x in 0 .. 1;

// NOTE: generated with the test below `test_generate_equivocation_report_blob`.
// the output is not deterministic since keys are generated randomly (and therefore
// signature content changes). it should not affect the benchmark.
// with the current benchmark setup it is not possible to generate this programatically
// from the benchmark setup.
const EQUIVOCATION_PROOF_BLOB: [u8; 416] = [
222, 241, 46, 66, 243, 228, 135, 233, 177, 64, 149, 170, 141, 92, 193, 106, 51, 73, 31,
27, 80, 218, 220, 248, 129, 29, 20, 128, 243, 250, 134, 39, 11, 0, 0, 0, 0, 0, 0, 0,
158, 4, 7, 240, 67, 153, 134, 190, 251, 196, 229, 95, 136, 165, 234, 228, 255, 18, 2,
187, 76, 125, 108, 50, 67, 33, 196, 108, 38, 115, 179, 86, 40, 36, 27, 5, 105, 58, 228,
94, 198, 65, 212, 218, 213, 61, 170, 21, 51, 249, 182, 121, 101, 91, 204, 25, 31, 87,
219, 208, 43, 119, 211, 185, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 66, 65, 66, 69, 52, 2, 0, 0, 0, 0, 11,
0, 0, 0, 0, 0, 0, 0, 5, 66, 65, 66, 69, 1, 1, 188, 192, 217, 91, 138, 78, 217, 80, 8,
29, 140, 55, 242, 210, 170, 184, 73, 98, 135, 212, 236, 209, 115, 52, 200, 79, 175,
172, 242, 161, 199, 47, 236, 93, 101, 95, 43, 34, 141, 16, 247, 220, 33, 59, 31, 197,
27, 7, 196, 62, 12, 238, 236, 124, 136, 191, 29, 36, 22, 238, 242, 202, 57, 139, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 40, 23, 175, 153, 83, 6, 33, 65, 123, 51, 80, 223, 126, 186, 226, 225, 240, 105, 28,
169, 9, 54, 11, 138, 46, 194, 201, 250, 48, 242, 125, 117, 116, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 6, 66, 65,
66, 69, 52, 2, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 5, 66, 65, 66, 69, 1, 1, 142, 12,
124, 11, 167, 227, 103, 88, 78, 23, 228, 33, 96, 41, 207, 183, 227, 189, 114, 70, 254,
30, 128, 243, 233, 83, 214, 45, 74, 182, 120, 119, 64, 243, 219, 119, 63, 240, 205,
123, 231, 82, 205, 174, 143, 70, 2, 86, 182, 20, 16, 141, 145, 91, 116, 195, 58, 223,
175, 145, 255, 7, 121, 133
];

let equivocation_proof1: cessp_consensus_rrsc::EquivocationProof<Header> =
Decode::decode(&mut &EQUIVOCATION_PROOF_BLOB[..]).unwrap();

let equivocation_proof2 = equivocation_proof1.clone();
}: {
cessp_consensus_rrsc::check_equivocation_proof::<Header>(equivocation_proof1);
} verify {
assert!(cessp_consensus_rrsc::check_equivocation_proof::<Header>(equivocation_proof2));
}

impl_benchmark_test_suite!(
Pallet,
crate::mock::new_test_ext(3),
crate::mock::Test,
)
}
Loading

0 comments on commit 5bb57ba

Please sign in to comment.