diff --git a/Cargo.toml b/Cargo.toml
index 3e269959..727238f0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,8 @@ repository = "https://github.com/noirhq/noir.git"
[workspace]
resolver = "2"
members = [
+ "client/consensus",
+ "client/consensus/pow",
"core-primitives",
"frame/babel",
"frame/cosmos",
@@ -23,7 +25,10 @@ members = [
"frame/multimap",
"frame/solana",
"frame/solana/runtime-api",
+ "frame/wtema",
"primitives/babel",
+ "primitives/consensus", # dummy
+ "primitives/consensus/pow",
"primitives/cosmos",
"primitives/ethereum",
"primitives/multimap",
@@ -56,6 +61,7 @@ members = [
"vendor/solana/rpc-client-api",
]
default-members = [
+ "client/*",
"core-primitives",
"frame/*",
"primitives/*",
@@ -68,6 +74,7 @@ useless_conversion = "allow"
[workspace.dependencies]
ark-bn254 = { version = "0.4.0", default-features = false, features = ["curve"] }
assert_matches = "1.5.0"
+async-trait = "0.1"
base64 = { version = "0.22", default-features = false }
bech32 = { version = "0.11", default-features = false }
bincode = { package = "solana-bincode", git = "https://github.com/noirhq/solana-sdk", branch = "v2.0", default-features = false }
@@ -96,6 +103,7 @@ enum-iterator = "1.5.0"
env_logger = "0.9"
ethereum = { version = "0.15.0", default-features = false }
futures = "0.3"
+futures-timer = "3.0"
getrandom = { version = "0.2", default-features = false }
hex = { version = "0.4.3", default-features = false }
hex-literal = "0.4"
@@ -116,6 +124,7 @@ num-traits = { version = "0.2", default-features = false }
num_enum = { version = "0.7", default-features = false }
parity-scale-codec = { version = "3.6", default-features = false }
parity-wasm = { version = "0.45.0", default-features = false }
+parking_lot = "0.12"
paste = "1.0"
percentage = "0.1.0"
rand = { version = "0.8.5", default-features = false }
@@ -148,6 +157,8 @@ wasmi-validation = { version = "0.5.0", default-features = false }
wat = "1.0"
# substrate
+sc-client-api = { version = "37.0.0" }
+sc-consensus = { version = "0.44.0" }
frame-support = { version = "38.2.0", default-features = false }
frame-system = { version = "38.0.0", default-features = false }
pallet-assets = { version = "40.0.0", default-features = false }
@@ -158,11 +169,15 @@ pallet-transaction-payment = { version = "38.0.2", default-features = false }
sc-transaction-pool-api = { version = "37.0.0" }
sp-api = { version = "34.0.0", default-features = false }
sp-arithmetic = { version = "26.0.0", default-features = false }
+sp-block-builder = { version = "34.0.0", default-features = false }
sp-blockchain = { version = "37.0.1" }
+sp-consensus = { version = "0.40.0", default-features = false }
sp-core = { version = "34.0.0", default-features = false }
+sp-inherents = { version = "34.0.0", default-features = false }
sp-io = { version = "38.0.0", default-features = false }
sp-keyring = { version = "39.0.0", default-features = false }
sp-runtime = { version = "39.0.5", default-features = false }
+substrate-prometheus-endpoint = { version = "0.17.0", default-features = false }
# frontier
fp-evm = { git = "https://github.com/noirhq/frontier", branch = "crates.io/stable2409", default-features = false }
@@ -179,9 +194,12 @@ precompile-utils = { git = "https://github.com/noirhq/frontier", branch = "crate
cosmos-rpc = { path = "frame/cosmos/rpc", default-features = false }
cosmos-runtime-api = { path = "frame/cosmos/runtime-api", default-features = false }
frame-babel = { path = "frame/babel", default-features = false }
+nc-consensus = { path = "client/consensus" }
+nc-consensus-pow = { path = "client/consensus/pow" }
noir-core-primitives = { path = "core-primitives", default-features = false }
noir-runtime-common = { path = "runtime/common", default-features = false }
np-babel = { path = "primitives/babel", default-features = false }
+np-consensus-pow = { path = "primitives/consensus/pow", default-features = false }
np-cosmos = { path = "primitives/cosmos", default-features = false }
np-ethereum = { path = "primitives/ethereum", default-features = false }
np-multimap = { path = "primitives/multimap", default-features = false }
@@ -199,6 +217,7 @@ pallet-cosmos-x-wasm = { path = "frame/cosmos/x/wasm", default-features = false
pallet-cosmos-x-wasm-types = { path = "frame/cosmos/x/wasm/types", default-features = false }
pallet-multimap = { path = "frame/multimap", default-features = false }
pallet-solana = { path = "frame/solana", default-features = false }
+pallet-wtema = { path = "frame/wtema", default-features = false }
# vendor
composable-support = { path = "vendor/composable/composable-support", default-features = false }
diff --git a/client/consensus/Cargo.toml b/client/consensus/Cargo.toml
new file mode 100644
index 00000000..356ed668
--- /dev/null
+++ b/client/consensus/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "nc-consensus"
+description = "Noir common types for consensus"
+license = "Apache-2.0"
+authors = { workspace = true }
+version = { workspace = true }
+edition = { workspace = true }
+repository = { workspace = true }
+publish = false
+
+[dependencies]
+async-trait = { workspace = true }
+sp-blockchain = { workspace = true, default-features = true }
+sp-runtime = { workspace = true, default-features = true }
diff --git a/client/consensus/pow/Cargo.toml b/client/consensus/pow/Cargo.toml
new file mode 100644
index 00000000..96b63aa9
--- /dev/null
+++ b/client/consensus/pow/Cargo.toml
@@ -0,0 +1,30 @@
+[package]
+name = "nc-consensus-pow"
+description = "Noir PoW consensus algorithm"
+license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
+authors = { workspace = true }
+version = { workspace = true }
+edition = { workspace = true }
+repository = { workspace = true }
+
+[dependencies]
+async-trait = { workspace = true }
+futures = { workspace = true }
+futures-timer = { workspace = true }
+log = { workspace = true, default-features = true }
+parity-scale-codec = { workspace = true, default-features = true, features = ["derive"] }
+parking_lot = { workspace = true, default-features = true }
+thiserror = { workspace = true, default-features = true }
+
+nc-consensus = { workspace = true }
+np-consensus-pow = { workspace = true, default-features = true }
+sc-client-api = { workspace = true }
+sc-consensus = { workspace = true }
+sp-api = { workspace = true }
+sp-block-builder = { workspace = true, default-features = true }
+sp-blockchain = { workspace = true, default-features = true }
+sp-consensus = { workspace = true, default-features = true }
+sp-core = { workspace = true, default-features = true }
+sp-inherents = { workspace = true, default-features = true }
+sp-runtime = { workspace = true, default-features = true }
+substrate-prometheus-endpoint = { workspace = true, default-features = true }
diff --git a/client/consensus/pow/README.md b/client/consensus/pow/README.md
new file mode 100644
index 00000000..8f2f68a7
--- /dev/null
+++ b/client/consensus/pow/README.md
@@ -0,0 +1,29 @@
+Proof of work consensus for Substrate.
+
+To use this engine, you can need to have a struct that implements
+`PowAlgorithm`. After that, pass an instance of the struct, along
+with other necessary client references to `import_queue` to setup
+the queue.
+
+This library also comes with an async mining worker, which can be
+started via the `start_mining_worker` function. It returns a worker
+handle together with a future. The future must be pulled. Through
+the worker handle, you can pull the metadata needed to start the
+mining process via `MiningWorker::metadata`, and then do the actual
+mining on a standalone thread. Finally, when a seal is found, call
+`MiningWorker::submit` to build the block.
+
+The auxiliary storage for PoW engine only stores the total difficulty.
+For other storage requirements for particular PoW algorithm (such as
+the actual difficulty for each particular blocks), you can take a client
+reference in your `PowAlgorithm` implementation, and use a separate prefix
+for the auxiliary storage. It is also possible to just use the runtime
+as the storage, but it is not recommended as it won't work well with light
+clients.
+
+License: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+
+## Release
+
+Polkadot SDK stable2409
diff --git a/client/consensus/pow/src/aux_schema.rs b/client/consensus/pow/src/aux_schema.rs
new file mode 100644
index 00000000..52c0eca3
--- /dev/null
+++ b/client/consensus/pow/src/aux_schema.rs
@@ -0,0 +1,58 @@
+// This file is part of Noir.
+
+// Copyright (C) Haderech Pte. 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 .
+
+use np_consensus_pow::BlockWeight;
+use parity_scale_codec::{Decode, Encode};
+use sc_client_api::AuxStore;
+use sp_blockchain::{Error, Result};
+
+pub fn block_weight_key(block_hash: H) -> Vec {
+ (b"block_weight", block_hash).encode()
+}
+
+fn load_decode(backend: &B, key: &[u8]) -> Result