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

Add a LightSyncState field to the chain spec #6894

Merged
23 commits merged into from
Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
488d0a9
Reset code, almost ready for PR
expenses Aug 14, 2020
ddc7e3e
Merge remote-tracking branch 'origin/master' into ashley-chain-spec
expenses Aug 14, 2020
15dcb28
Improved build_hardcoded_spec
expenses Aug 14, 2020
ecb2f56
Fix line widths
expenses Aug 14, 2020
837c5f7
Fix tests
expenses Aug 14, 2020
42d88d5
Fix sc-service-test
expenses Aug 14, 2020
4288dc4
Suggestions from code review
expenses Aug 14, 2020
44ff9f9
Rename to LightSyncState
expenses Aug 14, 2020
a6b5491
It's not syncing :^(
expenses Aug 17, 2020
c67d005
t Merge remote-tracking branch 'origin/master' into ashley-chain-spec…
expenses Aug 17, 2020
346b711
It syncs!
expenses Aug 17, 2020
6447b85
Remove rpc call
expenses Aug 17, 2020
1adad2e
Convert spaces to tabs
expenses Aug 17, 2020
9372667
Moved sc-service things to export_sync_state.rs
expenses Aug 17, 2020
db2da96
Fix tests
expenses Aug 17, 2020
b530147
Wait for syncing with network_status_sinks
expenses Aug 17, 2020
004a8a4
Remove sc-network from node-template
expenses Aug 17, 2020
ea62d80
Apply suggestions from code review
expenses Aug 17, 2020
9b558eb
Various changes, split the flag up into 2 pieces to make testing easier.
expenses Aug 18, 2020
fd1d2b1
Update client/cli/src/commands/build_spec_cmd.rs
expenses Aug 18, 2020
57cbb15
Merge remote-tracking branch 'origin/master' into ashley-chain-spec
expenses Aug 19, 2020
fa51717
Revert a lot of changes
expenses Aug 19, 2020
285c5af
Merge remote-tracking branch 'origin/master' into ashley-chain-spec
expenses Aug 24, 2020
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bin/node-template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
backend: backend.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
Expand Down Expand Up @@ -258,6 +259,7 @@ pub fn new_light(config: Configuration) -> Result<TaskManager, ServiceError> {
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
backend: backend.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
Expand Down
2 changes: 2 additions & 0 deletions bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ pub fn new_full_base(
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
backend: backend.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
Expand Down Expand Up @@ -394,6 +395,7 @@ pub fn new_light_base(config: Configuration) -> Result<(
sc_service::build_network(sc_service::BuildNetworkParams {
config: &config,
client: client.clone(),
backend: backend.clone(),
transaction_pool: transaction_pool.clone(),
spawn_handle: task_manager.spawn_handle(),
import_queue,
Expand Down
18 changes: 10 additions & 8 deletions client/api/src/in_mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,16 @@ impl<Block: BlockT> light::Storage<Block> for Blockchain<Block>
Blockchain::finalize_header(self, id, None)
}

fn cache(&self) -> Option<Arc<dyn blockchain::Cache<Block>>> {
None
}

fn usage_info(&self) -> Option<UsageInfo> {
None
}
}

impl<Block: BlockT> light::ChtRootStorage<Block> for Blockchain<Block> {
fn header_cht_root(
&self,
_cht_size: NumberFor<Block>,
Expand All @@ -466,14 +476,6 @@ impl<Block: BlockT> light::Storage<Block> for Blockchain<Block>
.ok_or_else(|| sp_blockchain::Error::Backend(format!("Changes trie CHT for block {} not exists", block)))
.map(Some)
}

fn cache(&self) -> Option<Arc<dyn blockchain::Cache<Block>>> {
None
}

fn usage_info(&self) -> Option<UsageInfo> {
None
}
}

/// In-memory operation.
Expand Down
19 changes: 12 additions & 7 deletions client/api/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,9 @@ pub trait FetchChecker<Block: BlockT>: Send + Sync {


/// Light client blockchain storage.
pub trait Storage<Block: BlockT>: AuxStore + HeaderBackend<Block> + HeaderMetadata<Block, Error=ClientError> {
pub trait Storage<Block: BlockT>: AuxStore + HeaderBackend<Block>
+ HeaderMetadata<Block, Error=ClientError> + ChtRootStorage<Block>
{
/// Store new header. Should refuse to revert any finalized blocks.
///
/// Takes new authorities, the leaf state of the new block, and
Expand All @@ -254,6 +256,15 @@ pub trait Storage<Block: BlockT>: AuxStore + HeaderBackend<Block> + HeaderMetada
/// Get last finalized header.
fn last_finalized(&self) -> ClientResult<Block::Hash>;

/// Get storage cache.
fn cache(&self) -> Option<Arc<dyn BlockchainCache<Block>>>;

/// Get storage usage statistics.
fn usage_info(&self) -> Option<UsageInfo>;
}

/// Light client CHT root storage.
pub trait ChtRootStorage<Block: BlockT> {
/// Get headers CHT root for given block. Returns None if the block is not pruned (not a part of any CHT).
fn header_cht_root(
&self,
Expand All @@ -267,12 +278,6 @@ pub trait Storage<Block: BlockT>: AuxStore + HeaderBackend<Block> + HeaderMetada
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> ClientResult<Option<Block::Hash>>;

/// Get storage cache.
fn cache(&self) -> Option<Arc<dyn BlockchainCache<Block>>>;

/// Get storage usage statistics.
fn usage_info(&self) -> Option<UsageInfo>;
}

/// Remote header.
Expand Down
1 change: 1 addition & 0 deletions client/chain-spec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ serde_json = "1.0.41"
sp-runtime = { version = "2.0.0-rc5", path = "../../primitives/runtime" }
sp-chain-spec = { version = "2.0.0-rc5", path = "../../primitives/chain-spec" }
sc-telemetry = { version = "2.0.0-rc5", path = "../telemetry" }
codec = { package = "parity-scale-codec", version = "1.3.4" }
89 changes: 78 additions & 11 deletions client/chain-spec/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Substrate chain configurations.
#![warn(missing_docs)]

use std::{borrow::Cow, fs::File, path::PathBuf, sync::Arc, collections::HashMap};
use serde::{Serialize, Deserialize};
Expand All @@ -26,6 +27,7 @@ use serde_json as json;
use crate::{RuntimeGenesis, ChainType, extension::GetExtension, Properties};
use sc_network::config::MultiaddrWithPeerId;
use sc_telemetry::TelemetryEndpoints;
use sp_runtime::traits::Block as BlockT;

enum GenesisSource<G> {
File(PathBuf),
Expand Down Expand Up @@ -157,6 +159,7 @@ struct ClientSpec<E> {
consensus_engine: (),
#[serde(skip_serializing)]
genesis: serde::de::IgnoredAny,
hardcoded_sync: Option<SerializableHardcodedSync>,
}

/// A type denoting empty extensions.
Expand Down Expand Up @@ -245,6 +248,7 @@ impl<G, E> ChainSpec<G, E> {
extensions,
consensus_engine: (),
genesis: Default::default(),
hardcoded_sync: None,
};

ChainSpec {
Expand All @@ -257,6 +261,11 @@ impl<G, E> ChainSpec<G, E> {
fn chain_type(&self) -> ChainType {
self.client_spec.chain_type.clone()
}

/// Hardcode infomation to allow light clients to sync quickly into the chain spec.
fn set_hardcoded_sync(&mut self, hardcoded_sync: SerializableHardcodedSync) {
self.client_spec.hardcoded_sync = Some(hardcoded_sync);
}
}

impl<G, E: serde::de::DeserializeOwned> ChainSpec<G, E> {
Expand Down Expand Up @@ -284,16 +293,15 @@ impl<G, E: serde::de::DeserializeOwned> ChainSpec<G, E> {
}
}

impl<G: RuntimeGenesis, E: serde::Serialize + Clone + 'static> ChainSpec<G, E> {
/// Dump to json string.
pub fn as_json(&self, raw: bool) -> Result<String, String> {
#[derive(Serialize, Deserialize)]
struct Container<G, E> {
#[serde(flatten)]
client_spec: ClientSpec<E>,
genesis: Genesis<G>,
#[derive(Serialize, Deserialize)]
struct JsonContainer<G, E> {
#[serde(flatten)]
client_spec: ClientSpec<E>,
genesis: Genesis<G>,
}

};
impl<G: RuntimeGenesis, E: serde::Serialize + Clone + 'static> ChainSpec<G, E> {
fn json_container(&self, raw: bool) -> Result<JsonContainer<G, E>, String> {
let genesis = match (raw, self.genesis.resolve()?) {
(true, Genesis::Runtime(g)) => {
let storage = g.build_storage()?;
Expand All @@ -313,13 +321,25 @@ impl<G: RuntimeGenesis, E: serde::Serialize + Clone + 'static> ChainSpec<G, E> {
},
(_, genesis) => genesis,
};
let container = Container {
Ok(JsonContainer {
client_spec: self.client_spec.clone(),
genesis,
};
})
}

/// Dump to json string.
pub fn as_json(&self, raw: bool) -> Result<String, String> {
let container = self.json_container(raw)?;
json::to_string_pretty(&container)
.map_err(|e| format!("Error generating spec json: {}", e))
}

/// Dump to json value
pub fn as_json_value(&self, raw: bool) -> Result<json::Value, String> {
let container = self.json_container(raw)?;
json::to_value(container)
.map_err(|e| format!("Error generating spec json: {}", e))
}
}

impl<G, E> crate::ChainSpec for ChainSpec<G, E>
Expand Down Expand Up @@ -367,6 +387,10 @@ where
ChainSpec::as_json(self, raw)
}

fn as_json_value(&self, raw: bool) -> Result<serde_json::Value, String> {
ChainSpec::as_json_value(self, raw)
}

fn as_storage_builder(&self) -> &dyn BuildStorage {
self
}
Expand All @@ -378,6 +402,49 @@ where
fn set_storage(&mut self, storage: Storage) {
self.genesis = GenesisSource::Storage(storage);
}

fn set_hardcoded_sync(&mut self, hardcoded_sync: SerializableHardcodedSync) {
ChainSpec::set_hardcoded_sync(self, hardcoded_sync)
}
}

/// Hardcoded infomation that allows light clients to sync quickly.
pub struct HardcodedSync<Block: BlockT> {
expenses marked this conversation as resolved.
Show resolved Hide resolved
/// The header of the best finalized block.
pub header: <Block as BlockT>::Header,
/// A list of all CHTs in the chain.
pub chts: Vec<<Block as BlockT>::Hash>,
}

impl<Block: BlockT> HardcodedSync<Block> {
/// Convert into a `SerializableHardcodecSync`.
pub fn to_serializable(&self) -> SerializableHardcodedSync {
use codec::Encode;

SerializableHardcodedSync {
header: StorageData(self.header.encode()),
chts: self.chts.iter().map(|hash| StorageData(hash.encode())).collect(),
}
}

/// Convert from a `SerializableHardcodecSync`.
pub fn from_serializable(serialized: &SerializableHardcodedSync) -> Result<Self, codec::Error> {
Ok(Self {
header: codec::Decode::decode(&mut &serialized.header.0[..])?,
chts: serialized.chts.iter()
.map(|cht| codec::Decode::decode(&mut &cht.0[..]))
.collect::<Result<_, _>>()?,
})
}
}

/// The serializable form of `HardcodedSync`. Created using `HardcodedSync::serialize`.
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct SerializableHardcodedSync {
header: StorageData,
chts: Vec<StorageData>,
Comment on lines +435 to +436
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that StorageData is the best way to serialize these, but there could be a better alternative.

}

#[cfg(test)]
Expand Down
8 changes: 7 additions & 1 deletion client/chain-spec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@
mod chain_spec;
mod extension;

pub use chain_spec::{ChainSpec as GenericChainSpec, NoExtension};
pub use chain_spec::{
ChainSpec as GenericChainSpec, NoExtension, HardcodedSync, SerializableHardcodedSync,
};
pub use extension::{Group, Fork, Forks, Extension, GetExtension, get_extension};
pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup};
pub use sp_chain_spec::{Properties, ChainType};
Expand Down Expand Up @@ -147,6 +149,8 @@ pub trait ChainSpec: BuildStorage + Send {
fn add_boot_node(&mut self, addr: MultiaddrWithPeerId);
/// Return spec as JSON.
fn as_json(&self, raw: bool) -> Result<String, String>;
/// Return spec as JSON value.
fn as_json_value(&self, raw: bool) -> Result<serde_json::Value, String>;
/// Return StorageBuilder for this spec.
fn as_storage_builder(&self) -> &dyn BuildStorage;
/// Returns a cloned `Box<dyn ChainSpec>`.
Expand All @@ -155,6 +159,8 @@ pub trait ChainSpec: BuildStorage + Send {
///
/// This will be used as storage at genesis.
fn set_storage(&mut self, storage: Storage);
/// Hardcode infomation to allow light clients to sync quickly into the chain spec.
fn set_hardcoded_sync(&mut self, hardcoded_sync: SerializableHardcodedSync);
}

impl std::fmt::Debug for dyn ChainSpec {
Expand Down
38 changes: 21 additions & 17 deletions client/db/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use sc_client_api::{
blockchain::{
BlockStatus, Cache as BlockchainCache, Info as BlockchainInfo,
},
Storage
Storage, ChtRootStorage,
};
use sp_blockchain::{
CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache,
Expand Down Expand Up @@ -523,22 +523,6 @@ impl<Block> Storage<Block> for LightStorage<Block>
}
}

fn header_cht_root(
&self,
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> ClientResult<Option<Block::Hash>> {
self.read_cht_root(HEADER_CHT_PREFIX, cht_size, block)
}

fn changes_trie_cht_root(
&self,
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> ClientResult<Option<Block::Hash>> {
self.read_cht_root(CHANGES_TRIE_CHT_PREFIX, cht_size, block)
}

fn finalize_header(&self, id: BlockId<Block>) -> ClientResult<()> {
if let Some(header) = self.header(id)? {
let mut transaction = Transaction::new();
Expand Down Expand Up @@ -612,6 +596,26 @@ impl<Block> Storage<Block> for LightStorage<Block>
}
}

impl<Block> ChtRootStorage<Block> for LightStorage<Block>
where Block: BlockT,
{
fn header_cht_root(
&self,
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> ClientResult<Option<Block::Hash>> {
self.read_cht_root(HEADER_CHT_PREFIX, cht_size, block)
}

fn changes_trie_cht_root(
&self,
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> ClientResult<Option<Block::Hash>> {
self.read_cht_root(CHANGES_TRIE_CHT_PREFIX, cht_size, block)
}
}

/// Build the key for inserting header-CHT at given block.
fn cht_key<N: TryInto<u32>>(cht_type: u8, block: N) -> ClientResult<[u8; 5]> {
let mut key = [cht_type; 5];
Expand Down
1 change: 1 addition & 0 deletions client/rpc-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ serde = { version = "1.0.101", features = ["derive"] }
serde_json = "1.0.41"
sp-transaction-pool = { version = "2.0.0-rc5", path = "../../primitives/transaction-pool" }
sp-rpc = { version = "2.0.0-rc5", path = "../../primitives/rpc" }
sp-blockchain = { version = "2.0.0-rc5", path = "../../primitives/blockchain" }
Loading