mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Add an initial Substrate instantiation
Consensus has been nuked for an AcceptAny currently routed throough PoW (when it doesn't have to be, doing so just took care of a few pieces of leg work). Updates AGPL handling.
This commit is contained in:
33
substrate/consensus/Cargo.toml
Normal file
33
substrate/consensus/Cargo.toml
Normal file
@@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "serai-consensus"
|
||||
version = "0.1.0"
|
||||
description = "Serai consensus module"
|
||||
license = "AGPL-3.0-only"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
sp-core = { version = "6.0.0", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sp-trie = { version = "6.0.0", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sp-timestamp = { version = "4.0.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sc-consensus = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sp-consensus = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sc-transaction-pool = { version = "4.0.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sc-basic-authorship = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sc-consensus-pow = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sp-consensus-pow = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
|
||||
sc-network = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sc-service = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai", features = ["wasmtime"] }
|
||||
sc-executor = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai", features = ["wasmtime"] }
|
||||
sp-runtime = { version = "6.0.0", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
|
||||
substrate-prometheus-endpoint = { version = "0.10.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
|
||||
sc-client-api = { version = "4.0.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
sp-api = { version = "4.0.0-dev", git = "https://github.com/serai-dex/substrate.git", branch = "serai" }
|
||||
|
||||
serai-runtime = { path = "../runtime" }
|
||||
|
||||
tokio = "1.15"
|
||||
15
substrate/consensus/LICENSE
Normal file
15
substrate/consensus/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
||||
AGPL-3.0-only license
|
||||
|
||||
Copyright (c) 2022 Luke Parker
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License Version 3 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
27
substrate/consensus/src/algorithm.rs
Normal file
27
substrate/consensus/src/algorithm.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use sp_core::U256;
|
||||
|
||||
use sc_consensus_pow::{Error, PowAlgorithm};
|
||||
use sp_consensus_pow::Seal;
|
||||
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AcceptAny;
|
||||
impl<B: BlockT> PowAlgorithm<B> for AcceptAny {
|
||||
type Difficulty = U256;
|
||||
|
||||
fn difficulty(&self, _: B::Hash) -> Result<Self::Difficulty, Error<B>> {
|
||||
Ok(U256::one())
|
||||
}
|
||||
|
||||
fn verify(
|
||||
&self,
|
||||
_: &BlockId<B>,
|
||||
_: &B::Hash,
|
||||
_: Option<&[u8]>,
|
||||
_: &Seal,
|
||||
_: Self::Difficulty,
|
||||
) -> Result<bool, Error<B>> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
137
substrate/consensus/src/lib.rs
Normal file
137
substrate/consensus/src/lib.rs
Normal file
@@ -0,0 +1,137 @@
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use substrate_prometheus_endpoint::Registry;
|
||||
|
||||
use sc_consensus_pow as sc_pow;
|
||||
use sc_client_api::call_executor::ExecutorProvider;
|
||||
use sc_executor::NativeElseWasmExecutor;
|
||||
use sc_service::TaskManager;
|
||||
|
||||
use serai_runtime::{self, opaque::Block, RuntimeApi};
|
||||
|
||||
mod algorithm;
|
||||
|
||||
pub struct ExecutorDispatch;
|
||||
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
|
||||
#[cfg(not(feature = "runtime-benchmarks"))]
|
||||
type ExtendHostFunctions = ();
|
||||
|
||||
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
|
||||
serai_runtime::api::dispatch(method, data)
|
||||
}
|
||||
|
||||
fn native_version() -> sc_executor::NativeVersion {
|
||||
serai_runtime::native_version()
|
||||
}
|
||||
}
|
||||
|
||||
pub type FullClient = sc_service::TFullClient<
|
||||
Block,
|
||||
RuntimeApi,
|
||||
NativeElseWasmExecutor<ExecutorDispatch>
|
||||
>;
|
||||
|
||||
type Db = sp_trie::PrefixedMemoryDB<sp_runtime::traits::BlakeTwo256>;
|
||||
|
||||
pub fn import_queue<S: sp_consensus::SelectChain<Block> + 'static>(
|
||||
task_manager: &TaskManager,
|
||||
client: Arc<FullClient>,
|
||||
select_chain: S,
|
||||
registry: Option<&Registry>
|
||||
) -> Result<sc_pow::PowImportQueue<Block, Db>, sp_consensus::Error> {
|
||||
let pow_block_import = Box::new(
|
||||
sc_pow::PowBlockImport::new(
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
algorithm::AcceptAny,
|
||||
0,
|
||||
select_chain.clone(),
|
||||
|_, _| { async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) } },
|
||||
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone())
|
||||
)
|
||||
);
|
||||
|
||||
sc_pow::import_queue(
|
||||
pow_block_import,
|
||||
None,
|
||||
algorithm::AcceptAny,
|
||||
&task_manager.spawn_essential_handle(),
|
||||
registry
|
||||
)
|
||||
}
|
||||
|
||||
// Produce a block every 5 seconds
|
||||
async fn produce<
|
||||
Block: sp_api::BlockT<Hash = sp_core::H256>,
|
||||
Algorithm: sc_pow::PowAlgorithm<Block, Difficulty = sp_core::U256> +
|
||||
'static + Send + std::marker::Sync,
|
||||
C: sp_api::ProvideRuntimeApi<Block> + 'static,
|
||||
Link: sc_consensus::JustificationSyncLink<Block> + 'static,
|
||||
P: Send + 'static
|
||||
>(worker: sc_pow::MiningHandle<Block, Algorithm, C, Link, P>)
|
||||
where sp_api::TransactionFor<C, Block>: Send + 'static {
|
||||
loop {
|
||||
let worker_clone = worker.clone();
|
||||
std::thread::spawn(move || {
|
||||
tokio::runtime::Runtime::new().unwrap().handle().block_on(
|
||||
async { worker_clone.submit(vec![]).await; }
|
||||
);
|
||||
});
|
||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're an authority, produce blocks
|
||||
pub fn authority<S: sp_consensus::SelectChain<Block> + 'static>(
|
||||
task_manager: &TaskManager,
|
||||
client: Arc<FullClient>,
|
||||
network: Arc<sc_network::NetworkService<Block, <Block as sp_runtime::traits::Block>::Hash>>,
|
||||
pool: Arc<sc_transaction_pool::FullPool<Block, FullClient>>,
|
||||
select_chain: S,
|
||||
registry: Option<&Registry>
|
||||
) {
|
||||
let proposer = sc_basic_authorship::ProposerFactory::new(
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
pool,
|
||||
registry,
|
||||
None
|
||||
);
|
||||
|
||||
let can_author_with = sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
|
||||
|
||||
let pow_block_import = Box::new(sc_pow::PowBlockImport::new(
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
algorithm::AcceptAny,
|
||||
0, // Block to start checking inherents at
|
||||
select_chain.clone(),
|
||||
move |_, _| { async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) } },
|
||||
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone())
|
||||
));
|
||||
|
||||
let (worker, worker_task) = sc_pow::start_mining_worker(
|
||||
pow_block_import,
|
||||
client,
|
||||
select_chain,
|
||||
algorithm::AcceptAny,
|
||||
proposer,
|
||||
network.clone(),
|
||||
network.clone(),
|
||||
None,
|
||||
move |_, _| { async { Ok(sp_timestamp::InherentDataProvider::from_system_time()) } },
|
||||
Duration::from_secs(1),
|
||||
Duration::from_secs(2),
|
||||
can_author_with
|
||||
);
|
||||
|
||||
task_manager
|
||||
.spawn_essential_handle()
|
||||
.spawn_blocking("pow", None, worker_task);
|
||||
|
||||
task_manager
|
||||
.spawn_essential_handle()
|
||||
.spawn("producer", None, produce(worker));
|
||||
}
|
||||
Reference in New Issue
Block a user