Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Beefy node cleanup (#75)
Browse files Browse the repository at this point in the history
* bump serde

* bump substrate, scale-codec 2.0.0

* we need a proper beefy node

* rename primitives as well

* Sort members.

Co-authored-by: Tomasz Drwięga <[email protected]>
  • Loading branch information
adoerr and tomusdrw authored Feb 3, 2021
1 parent 85d81b2 commit ad86b0e
Show file tree
Hide file tree
Showing 13 changed files with 1,309 additions and 19 deletions.
5 changes: 3 additions & 2 deletions client/beefy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
codec = { version = "1.3.5", package = "parity-scale-codec", features = ["derive"] }
futures = "0.3"
log = "0.4"
parking_lot = "0.11"

beefy-primitives = { path = "../primitives" }
codec = { version = "2.0.0", package = "parity-scale-codec", features = ["derive"] }

sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master" }
Expand All @@ -26,3 +25,5 @@ sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "mas
sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network-gossip = { git = "https://github.com/paritytech/substrate", branch = "master" }

beefy-primitives = { path = "../beefy-primitives" }
24 changes: 14 additions & 10 deletions client/beefy/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
beefy-gadget = { path = "../." }
beefy-primitives = { path = "../../primitives" }
futures = { version = "0.3.12", features = ["compat"] }
log = "0.4"
serde = { version = "1.0.123", features = ["derive"] }
serde_json = "1.0.61"

codec = { version = "1.3.5", package = "parity-scale-codec", features = ["derive"] }
sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
jsonrpc-core = "15.1.0"
jsonrpc-core-client = "15.1.0"
jsonrpc-derive = "15.1.0"
jsonrpc-pubsub = "15.1.0"
futures = { version = "0.3.12", features = ["compat"] }
serde = { version = "1.0.119", features = ["derive"] }
serde_json = "1.0.61"
log = "0.4.13"

codec = { version = "2.0.0", package = "parity-scale-codec", features = ["derive"] }

sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "master" }

sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }

beefy-gadget = { path = "../." }
beefy-primitives = { path = "../../beefy-primitives" }
8 changes: 4 additions & 4 deletions frame/beefy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
codec = { version = "1.3.5", package = "parity-scale-codec", default-features = false, features = ["derive"] }
serde = { version = "1.0.119", optional = true }

beefy-primitives = { path = "../primitives", default-features = false }
codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] }
serde = { version = "1.0.123", optional = true }

frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
Expand All @@ -19,6 +17,8 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f

pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }

beefy-primitives = { path = "../beefy-primitives", default-features = false }

[dev-dependencies]
sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
sp-io = { git = "https://github.com/paritytech/substrate.git", branch = "master" }
Expand Down
8 changes: 5 additions & 3 deletions frame/beefy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@

use codec::Encode;

use beefy_primitives::{AuthorityIndex, ConsensusLog, BEEFY_ENGINE_ID};
use frame_support::{decl_module, decl_storage, Parameter};
use frame_support::{decl_module, decl_storage, traits::OneSessionHandler, Parameter};

use sp_runtime::{
generic::DigestItem,
traits::{IsMember, Member},
RuntimeAppPublic,
};
use sp_std::prelude::*;

use beefy_primitives::{AuthorityIndex, ConsensusLog, BEEFY_ENGINE_ID};

#[cfg(test)]
mod mock;

Expand Down Expand Up @@ -91,7 +93,7 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
type Public = T::AuthorityId;
}

impl<T: Config> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
impl<T: Config> OneSessionHandler<T::AccountId> for Module<T> {
type Key = T::AuthorityId;

fn on_genesis_session<'a, I: 'a>(validators: I)
Expand Down
29 changes: 29 additions & 0 deletions primitives/beefy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "beefy-primitives"
version = "0.1.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"

[dependencies]
codec = { version = "2.0.0", package = "parity-scale-codec", default-features = false, features = ["derive"] }

sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }

[dev-dependencies]
hex-literal = "0.3"

[features]
default = ["std"]
std = [
"codec/std",
"sp-api/std",
"sp-application-crypto/std",
"sp-core/std",
"sp-runtime/std",
"sp-std/std",
]
198 changes: 198 additions & 0 deletions primitives/beefy/src/commitment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Copyright (C) 2020 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use sp_std::{cmp, prelude::*};

use crate::ValidatorSetId;

/// A commitment signed by GRANDPA validators as part of BEEFY protocol.
///
/// The commitment contains a [payload] extracted from the finalized block at height [block_number].
/// GRANDPA validators collect signatures on commitments and a stream of such signed commitments
/// (see [SignedCommitment]) forms the BEEFY protocol.
#[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)]
pub struct Commitment<TBlockNumber, TPayload> {
/// The payload being signed.
///
/// This should be some form of cumulative representation of the chain (think MMR root hash).
/// The payload should also contain some details that allow the light client to verify next
/// validator set. The protocol does not enforce any particular format of this data,
/// nor how often it should be present in commitments, however the light client has to be
/// provided with full validator set whenever it performs the transition (i.e. importing first
/// block with [validator_set_id] incremented).
pub payload: TPayload,

/// Finalized block number this commitment is for.
///
/// GRANDPA validators agree on a block they create a commitment for and start collecting
/// signatures. This process is called a round.
/// There might be multiple rounds in progress (depending on the block choice rule), however
/// since the payload is supposed to be cumulative, it is not required to import all
/// commitments.
/// BEEFY light client is expected to import at least one commitment per epoch,
/// but is free to import as many as it requires.
pub block_number: TBlockNumber,

/// BEEFY validator set supposed to sign this commitment.
///
/// Validator set is changing once per epoch. The Light Client must be provided by details about
/// the validator set whenever it's importing first commitment with a new `validator_set_id`.
/// Validator set data MUST be verifiable, for instance using [payload] information.
pub validator_set_id: ValidatorSetId,
}

impl<TBlockNumber, TPayload> cmp::PartialOrd for Commitment<TBlockNumber, TPayload>
where
TBlockNumber: cmp::Ord,
TPayload: cmp::Eq,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}

impl<TBlockNumber, TPayload> cmp::Ord for Commitment<TBlockNumber, TPayload>
where
TBlockNumber: cmp::Ord,
TPayload: cmp::Eq,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.validator_set_id
.cmp(&other.validator_set_id)
.then_with(|| self.block_number.cmp(&other.block_number))
}
}

/// A commitment with matching GRANDPA validators' signatures.
#[derive(Clone, Debug, PartialEq, Eq, codec::Encode, codec::Decode)]
pub struct SignedCommitment<TBlockNumber, TPayload, TSignature> {
/// The commitment signatures are collected for.
pub commitment: Commitment<TBlockNumber, TPayload>,
/// GRANDPA validators' signatures for the commitment.
///
/// The length of this `Vec` must match number of validators in the current set (see
/// [Commitment::validator_set_id]).
pub signatures: Vec<Option<TSignature>>,
}

impl<TBlockNumber, TPayload, TSignature> SignedCommitment<TBlockNumber, TPayload, TSignature> {
/// Return the number of collected signatures.
pub fn no_of_signatures(&self) -> usize {
self.signatures.iter().filter(|x| x.is_some()).count()
}
}

#[cfg(test)]
mod tests {
use super::*;
use codec::Decode;

type TestCommitment = Commitment<u128, String>;
type TestSignedCommitment = SignedCommitment<u128, String, Vec<u8>>;

#[test]
fn commitment_encode_decode() {
// given
let commitment: TestCommitment = Commitment {
payload: "Hello World!".into(),
block_number: 5,
validator_set_id: 0,
};

// when
let encoded = codec::Encode::encode(&commitment);
let decoded = TestCommitment::decode(&mut &*encoded);

// then
assert_eq!(decoded, Ok(commitment));
assert_eq!(
encoded,
hex_literal::hex!("3048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000")
);
}

#[test]
fn signed_commitment_encode_decode() {
// given
let commitment: TestCommitment = Commitment {
payload: "Hello World!".into(),
block_number: 5,
validator_set_id: 0,
};
let signed = SignedCommitment {
commitment,
signatures: vec![None, None, Some(vec![1, 2, 3, 4]), Some(vec![5, 6, 7, 8])],
};

// when
let encoded = codec::Encode::encode(&signed);
let decoded = TestSignedCommitment::decode(&mut &*encoded);

// then
assert_eq!(decoded, Ok(signed));
assert_eq!(
encoded,
hex_literal::hex!(
"3048656c6c6f20576f726c6421050000000000000000000000000000000000000000000000100000011001020304011005060708"
)
);
}

#[test]
fn signed_commitment_count_signatures() {
// given
let commitment: TestCommitment = Commitment {
payload: "Hello World!".into(),
block_number: 5,
validator_set_id: 0,
};
let mut signed = SignedCommitment {
commitment,
signatures: vec![None, None, Some(vec![1, 2, 3, 4]), Some(vec![5, 6, 7, 8])],
};
assert_eq!(signed.no_of_signatures(), 2);

// when
signed.signatures[2] = None;

// then
assert_eq!(signed.no_of_signatures(), 1);
}

#[test]
fn commitment_ordering() {
fn commitment(block_number: u128, validator_set_id: crate::ValidatorSetId) -> TestCommitment {
Commitment {
payload: "Hello World!".into(),
block_number,
validator_set_id,
}
}

// given
let a = commitment(1, 0);
let b = commitment(2, 1);
let c = commitment(10, 0);
let d = commitment(10, 1);

// then
assert!(a < b);
assert!(a < c);
assert!(c < b);
assert!(c < d);
assert!(b < d);
}
}
Loading

0 comments on commit ad86b0e

Please sign in to comment.