Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PoC] Sassafras Consensus #1336

Draft
wants to merge 38 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
312724f
Runtime pallet
davxy Aug 31, 2023
4e7d224
Client test utils
davxy Aug 31, 2023
95df98f
Client module
davxy Aug 31, 2023
a32be43
Sassafras node PoC
davxy Aug 31, 2023
1a0cb61
Misc tweaks
davxy Aug 31, 2023
23ecf2c
Merge branch 'master' into davxy-sassafras-consensus
davxy Sep 19, 2023
53ffd81
Align with #1599
davxy Sep 19, 2023
837a2fa
Remove versions from Cargo file
davxy Sep 19, 2023
f12ca09
Pallet feature to construct a dummy ring context
davxy Sep 20, 2023
12a5b8c
Workaround while waiting for serializable RingVerifier
davxy Sep 20, 2023
7cd48a7
Fix sassafras node benchmark functions
davxy Sep 20, 2023
76c2630
Update benches using RingVerifier serialization workaround
davxy Sep 20, 2023
a8d2b73
Ignore duplicate tickets
davxy Sep 20, 2023
5f7cf58
Fix a couple of bugs
davxy Sep 20, 2023
761a52d
Postpone ring verifier initialization
davxy Sep 21, 2023
d11b8ca
Merge branch 'master' into davxy-sassafras-consensus
davxy Oct 9, 2023
3310196
Merge branch 'master' into davxy-sassafras-consensus
davxy Oct 20, 2023
8ad1253
Port of new stuff from pallet's PR
davxy Oct 23, 2023
2381b69
Update bandersnatch vrf
davxy Oct 25, 2023
7c7d7fb
Expose ec-utils host functions
davxy Oct 25, 2023
0e12c92
Merge branch 'master' into davxy-sassafras-consensus
davxy Dec 2, 2023
7285aa6
Fix sp-consensus-client after merge
davxy Dec 2, 2023
08b6fcc
Sassafras node starts but is currently broken
davxy Dec 2, 2023
7222dfe
Review client logging
davxy Dec 2, 2023
dbe29df
Marker for TODOs
davxy Dec 2, 2023
da032e6
Fix the hack...
davxy Dec 2, 2023
4363c70
Fix test-utils
davxy Dec 2, 2023
8bca723
Exclude node-sassafras license check
davxy Dec 2, 2023
46bfecc
Make taplo happy
davxy Dec 2, 2023
15859f7
Restore Sassafras (#2585)
davxy Dec 5, 2023
2f63dd6
Nits
davxy Jan 22, 2024
87bcb06
Merge branch 'master' into davxy-sassafras-consensus
davxy Jul 27, 2024
f636bc5
Fix after master merge
davxy Jul 27, 2024
816cafb
Fix pallet
davxy Jul 27, 2024
b5e976a
Update sassafras primitives
davxy Jul 27, 2024
0aa5694
Update bandersnatch
davxy Jul 27, 2024
7c951b8
Restore tickets file
davxy Jul 27, 2024
62378ca
Plug session pallet stuff
davxy Jul 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
295 changes: 256 additions & 39 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ members = [
"polkadot/xcm/xcm-simulator",
"polkadot/xcm/xcm-simulator/example",
"polkadot/xcm/xcm-simulator/fuzzer",
"substrate/bin/node-sassafras/node",
"substrate/bin/node-sassafras/runtime",
"substrate/bin/node/bench",
"substrate/bin/node/cli",
"substrate/bin/node/inspect",
Expand Down Expand Up @@ -263,6 +265,7 @@ members = [
"substrate/client/consensus/grandpa/rpc",
"substrate/client/consensus/manual-seal",
"substrate/client/consensus/pow",
"substrate/client/consensus/sassafras",
"substrate/client/consensus/slots",
"substrate/client/db",
"substrate/client/executor",
Expand Down Expand Up @@ -1431,3 +1434,17 @@ wasmi = { opt-level = 3 }
x25519-dalek = { opt-level = 3 }
yamux = { opt-level = 3 }
zeroize = { opt-level = 3 }

# [patch."/~https://github.com/w3f/ring-vrf"]
# # bandersnatch_vrfs = { git = "/~https://github.com/davxy/ring-vrf", branch = "davxy-patch" }
# bandersnatch_vrfs = { path = "../../w3f/ring-vrf/bandersnatch_vrfs" }

# [patch."/~https://github.com/w3f/ring-proof"]
# # ring = { git = "/~https://github.com/davxy/ring-proof", branch = "davxy-patch" }
# # common = { git = "/~https://github.com/davxy/ring-proof", branch = "davxy-patch" }
# ring = { path = "../../w3f/ring-proof/ring" }
# common = { path = "../../w3f/ring-proof/common" }

# [patch."/~https://github.com/w3f/fflonk"]
# # fflonk = { git = "/~https://github.com/davxy/fflonk", branch = "davxy-patch" }
# fflonk = { path = "../../w3f/fflonk" }
38 changes: 38 additions & 0 deletions benchmark.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash

binary="./target/release/node-sassafras"

steps=20
repeat=3

export RUST_LOG="sassafras=debug"

pallet='pallet_sassafras'

extrinsic=$1

if [[ $extrinsic == "" ]]; then
list=$($binary benchmark pallet --list | grep $pallet | cut -d ',' -f 2)

echo "Usage: $0 <benchmark>"
echo ""
echo "Available benchmarks:"
for bench in $list; do
echo "- $bench"
done
echo "- all"
exit
fi

if [[ $extrinsic == "all" ]]; then
extrinsic='*'
fi

$binary benchmark pallet \
--chain dev \
--pallet $pallet \
--extrinsic "$extrinsic" \
--steps $steps \
--repeat $repeat \
--output weights.rs \
--template substrate/.maintain/frame-weight-template.hbs
16 changes: 16 additions & 0 deletions substrate/bin/node-sassafras/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
root = true

[*]
indent_style=space
indent_size=2
tab_width=2
end_of_line=lf
charset=utf-8
trim_trailing_whitespace=true
insert_final_newline = true

[*.{rs,toml}]
indent_style=tab
indent_size=tab
tab_width=4
max_line_length=100
84 changes: 84 additions & 0 deletions substrate/bin/node-sassafras/node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[package]
name = "node-sassafras"
version = "0.3.4-dev"
authors = ["Davide Galassi <davxy@datawok.net>", "Parity Technologies <admin@parity.io>"]
description = "Node testbed for Sassafras consensus."
homepage = "https://substrate.io/"
edition = "2021"
license = "Unlicense"
publish = false
build = "build.rs"

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

[[bin]]
name = "node-sassafras"

[dependencies]
clap = { version = "4.0.9", features = ["derive"] }
futures = { version = "0.3.21", features = ["thread-pool"] }
serde_json = "1.0.108"

sc-cli = { path = "../../../client/cli" }
sp-core = { path = "../../../primitives/core" }
sc-executor = { path = "../../../client/executor" }
sc-network = { path = "../../../client/network" }
sc-service = { path = "../../../client/service" }
sc-telemetry = { path = "../../../client/telemetry" }
sc-keystore = { path = "../../../client/keystore" }
sc-transaction-pool = { path = "../../../client/transaction-pool" }
sc-transaction-pool-api = { path = "../../../client/transaction-pool/api" }
sc-offchain = { path = "../../../client/offchain" }
sc-consensus-sassafras = { path = "../../../client/consensus/sassafras" }
sp-consensus-sassafras = { path = "../../../primitives/consensus/sassafras" }
sp-consensus = { path = "../../../primitives/consensus/common" }
sc-consensus = { path = "../../../client/consensus/common" }
sc-consensus-grandpa = { path = "../../../client/consensus/grandpa" }
sp-consensus-grandpa = { path = "../../../primitives/consensus/grandpa" }
sc-client-api = { path = "../../../client/api" }
sp-runtime = { path = "../../../primitives/runtime" }
sp-io = { path = "../../../primitives/io" }
sp-timestamp = { path = "../../../primitives/timestamp" }
sp-inherents = { path = "../../../primitives/inherents" }
sp-keyring = { path = "../../../primitives/keyring" }
frame-system = { path = "../../../frame/system" }
pallet-transaction-payment = { path = "../../../frame/transaction-payment" }
sp-crypto-ec-utils = { path = "../../../primitives/crypto/ec-utils", features = ["bls12-381", "ed-on-bls12-381-bandersnatch"] }
sp-consensus-slots = { path = "../../../primitives/consensus/slots" }
sc-consensus-slots = { path = "../../../client/consensus/slots" }

# These dependencies are used for the node template's RPCs
jsonrpsee = { version = "0.16.2", features = ["server"] }
sc-rpc = { path = "../../../client/rpc" }
sp-api = { path = "../../../primitives/api" }
sc-rpc-api = { path = "../../../client/rpc-api" }
sp-blockchain = { path = "../../../primitives/blockchain" }
sp-block-builder = { path = "../../../primitives/block-builder" }
sc-basic-authorship = { path = "../../../client/basic-authorship" }
substrate-frame-rpc-system = { path = "../../../utils/frame/rpc/system" }
pallet-transaction-payment-rpc = { path = "../../../frame/transaction-payment/rpc/" }

# These dependencies are used for runtime benchmarking
frame-benchmarking = { path = "../../../frame/benchmarking" }
frame-benchmarking-cli = { path = "../../../utils/frame/benchmarking-cli" }

# Local Dependencies
node-sassafras-runtime = { path = "../runtime" }

[build-dependencies]
substrate-build-script-utils = { path = "../../../utils/build-script-utils" }

[features]
default = []
runtime-benchmarks = [
"frame-benchmarking-cli/runtime-benchmarks",
"frame-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"node-sassafras-runtime/runtime-benchmarks",
"sc-service/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
use-session-pallet = [
"node-sassafras-runtime/use-session-pallet",
]
7 changes: 7 additions & 0 deletions substrate/bin/node-sassafras/node/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};

fn main() {
generate_cargo_keys();

rerun_if_git_head_changed();
}
162 changes: 162 additions & 0 deletions substrate/bin/node-sassafras/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#[cfg(feature = "use-session-pallet")]
use node_sassafras_runtime::SessionKeys;
use node_sassafras_runtime::{AccountId, RuntimeGenesisConfig, Signature, WASM_BINARY};
use sc_service::ChainType;
use sp_consensus_grandpa::AuthorityId as GrandpaId;
use sp_consensus_sassafras::AuthorityId as SassafrasId;
use sp_core::{sr25519, Pair, Public};
use sp_runtime::traits::{IdentifyAccount, Verify};

// Genesis constants for Sassafras parameters configuration.
const SASSAFRAS_TICKETS_MAX_ATTEMPTS_NUMBER: u32 = 8;
const SASSAFRAS_TICKETS_REDUNDANCY_FACTOR: u32 = 1;

/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
/// Ec-utils host functions required to construct the test `RingContext` instance.
pub type ChainSpec = sc_service::GenericChainSpec<
RuntimeGenesisConfig,
Option<()>,
(
sp_crypto_ec_utils::bls12_381::host_calls::HostFunctions,
sp_crypto_ec_utils::ed_on_bls12_381_bandersnatch::host_calls::HostFunctions,
),
>;

/// Generate a crypto pair from seed.
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}

type AccountPublic = <Signature as Verify>::Signer;

/// Generate an account id from seed.
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}

/// Generate authority account id and keys from seed.
pub fn authority_keys_from_seed(seed: &str) -> (AccountId, SassafrasId, GrandpaId) {
(
get_account_id_from_seed::<sr25519::Public>(seed),
get_from_seed::<SassafrasId>(seed),
get_from_seed::<GrandpaId>(seed),
)
}

pub fn development_config() -> Result<ChainSpec, String> {
Ok(ChainSpec::builder(
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("Development")
.with_id("dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_patch(testnet_genesis(
vec![authority_keys_from_seed("Alice")],
get_account_id_from_seed::<sr25519::Public>("Alice"),
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
],
))
.build())
}

pub fn local_testnet_config() -> Result<ChainSpec, String> {
Ok(ChainSpec::builder(
WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?,
None,
)
.with_name("Local Testnet")
.with_id("local_testnet")
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(testnet_genesis(
// Initial PoA authorities
vec![authority_keys_from_seed("Alice"), authority_keys_from_seed("Bob")],
// Sudo account
get_account_id_from_seed::<sr25519::Public>("Alice"),
// Pre-funded accounts
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
],
))
.build())
}

#[cfg(feature = "use-session-pallet")]
fn testnet_genesis(
initial_authorities: Vec<(AccountId, SassafrasId, GrandpaId)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
) -> serde_json::Value {
serde_json::json!({
"balances": {
"balances": endowed_accounts.iter().cloned().map(|k| (k, 1u64 << 60)).collect::<Vec<_>>(),
},
"sassafras": {
"epochConfig": sp_consensus_sassafras::EpochConfiguration {
attempts_number: SASSAFRAS_TICKETS_MAX_ATTEMPTS_NUMBER,
redundancy_factor: SASSAFRAS_TICKETS_REDUNDANCY_FACTOR,
},
},
"session": {
"keys": initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
SessionKeys { sassafras: x.1.clone(), grandpa: x.2.clone() },
)
})
.collect::<Vec<_>>(),
},
"sudo": {
"key": Some(root_key),
},
})
}

#[cfg(not(feature = "use-session-pallet"))]
fn testnet_genesis(
initial_authorities: Vec<(AccountId, SassafrasId, GrandpaId)>,
root_key: AccountId,
endowed_accounts: Vec<AccountId>,
) -> serde_json::Value {
serde_json::json!({
"balances": {
"balances": endowed_accounts.iter().cloned().map(|k| (k, 1u64 << 60)).collect::<Vec<_>>(),
},
"sassafras": {
"authorities": initial_authorities.iter().map(|x| x.1.clone()).collect::<Vec<_>>(),
"epochConfig": sp_consensus_sassafras::EpochConfiguration {
attempts_number: SASSAFRAS_TICKETS_MAX_ATTEMPTS_NUMBER,
redundancy_factor: SASSAFRAS_TICKETS_REDUNDANCY_FACTOR,
},
},
"grandpa": {
"authorities": initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect::<Vec<_>>(),
},
"sudo": {
"key": Some(root_key),
},
})
}
45 changes: 45 additions & 0 deletions substrate/bin/node-sassafras/node/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use sc_cli::RunCmd;

#[derive(Debug, clap::Parser)]
pub struct Cli {
#[clap(subcommand)]
pub subcommand: Option<Subcommand>,

#[clap(flatten)]
pub run: RunCmd,
}

#[derive(Debug, clap::Subcommand)]
pub enum Subcommand {
/// Key management cli utilities
#[clap(subcommand)]
Key(sc_cli::KeySubcommand),

/// Build a chain specification.
BuildSpec(sc_cli::BuildSpecCmd),

/// Validate blocks.
CheckBlock(sc_cli::CheckBlockCmd),

/// Export blocks.
ExportBlocks(sc_cli::ExportBlocksCmd),

/// Export the state of a given block into a chain spec.
ExportState(sc_cli::ExportStateCmd),

/// Import blocks.
ImportBlocks(sc_cli::ImportBlocksCmd),

/// Remove the whole chain.
PurgeChain(sc_cli::PurgeChainCmd),

/// Revert the chain to a previous state.
Revert(sc_cli::RevertCmd),

/// Sub-commands concerned with benchmarking.
#[clap(subcommand)]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),

/// Db meta columns information.
ChainInfo(sc_cli::ChainInfoCmd),
}
Loading
Loading