Skip to content

Commit

Permalink
first shot of using smoldot
Browse files Browse the repository at this point in the history
  • Loading branch information
gilescope committed Oct 2, 2022
1 parent 3b2fb76 commit 215e93c
Show file tree
Hide file tree
Showing 8 changed files with 16,540 additions and 160 deletions.
1,143 changes: 1,118 additions & 25 deletions Cargo.lock

Large diffs are not rendered by default.

19 changes: 12 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ default = ["normalmouse"]
spacemouse = ["bevy_spacemouse"]
normalmouse = ["bevy_flycam"]
adaptive-fps = []
light-client = ["polkapipe/smoldot-std"]

[dependencies]
primitive-types = { version = "0.11", default-features = false, features = [
Expand All @@ -29,10 +30,10 @@ async-recursion = "*"

# Not needed since rust 1.63
lazy_static = "*"
futures = { version = "0.3.13", defalult-features = false, features = [] }
futures = { version = "0.3.13", default-features = false, features = [] }
# winit = { version = "*", default-features=false, features = ["x11"] }
hex = "*"
#smoldot = { git= "https://github.com/paritytech/smoldot.git", defalult-features = false }
#smoldot = { git= "https://github.com/paritytech/smoldot.git", default-features = false }
parity-scale-codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = [
"derive",
"full",
Expand Down Expand Up @@ -124,7 +125,9 @@ bevy = { version = "0.8.1", default-features = false, features = [
"dynamic",
] }

polkapipe = { git = "https://github.com/gilescope/polkapipe", rev="a1a85669791d468b7ed1387feee81c54473e608a", features = ["wss"]}
polkapipe = { git = "https://github.com/gilescope/polkapipe", rev = "19aac258bf0106e67f83ff489bdf7c1ebfe2b3ab", features = [
"wss",
] }
# polkapipe = { path = "/home/gilescope/git/polkapipe", default-features = false, features = [
# "wss",
# ] }
Expand All @@ -147,7 +150,9 @@ getrandom = { version = "0.2.7", features = ["wasm-bindgen", "js"] }
wasm-bindgen = "*"
ws_stream_wasm = "*"
# wasm32 branch
polkapipe = { git = "https://github.com/gilescope/polkapipe", rev="a1a85669791d468b7ed1387feee81c54473e608a", features = ["ws-web"]}
polkapipe = { git = "https://github.com/gilescope/polkapipe", rev = "19aac258bf0106e67f83ff489bdf7c1ebfe2b3ab", features = [
"ws-web",
] }
# polkapipe = { path = "/home/gilescope/git/polkapipe", default-features = false, features = [
# "ws-web",
# ] }
Expand Down Expand Up @@ -175,7 +180,7 @@ bevy_web_fullscreen = { git = "https://github.com/ostwilkens/bevy_web_fullscreen
# http-types= {git="https://github.com/http-rs/http-types.git"}
#console_error_panic_hook = { version = "0.1", optional = true }

#smoldot = { git= "https://github.com/paritytech/smoldot.git", defalult-features = false }
#smoldot = { git= "https://github.com/paritytech/smoldot.git", default-features = false }

#subxt = {git= "https://github.com/paritytech/subxt.git"}

Expand Down Expand Up @@ -203,10 +208,10 @@ opt-level = 1
[profile.release]
lto = true
opt-level = 's'
debuginfo = 0
debug = 0
strip = "debuginfo" # strip symbols brakes it findong the worker.
codegen-units = 1
panic = "abort"
# panic = "abort" - doesn't work with bevy "dyn".
incremental = false


Expand Down
3,475 changes: 3,475 additions & 0 deletions assets/chainspecs/kusama.json

Large diffs are not rendered by default.

11,696 changes: 11,696 additions & 0 deletions assets/chainspecs/polkadot.json

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion src/datasource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::{
};
// use async_std::stream::StreamExt;
use serde::{Deserialize, Serialize};
#[cfg(feature = "light-client")]
use crate::datasource::raw_source::LightClientDataSource;
// #[cfg(not(target_arch = "wasm32"))]
// use async_tungstenite::tungstenite::util::NonBlockingResult;
use bevy::{prelude::warn, utils::default};
Expand Down Expand Up @@ -168,8 +170,17 @@ where
// log!("listening to as of {:?}", as_of);

let url = &chain_info.chain_ws;
let urll = match url.as_str() {
"wss://rpc.polkadot.io:443" => { include_str!("../../assets/chainspecs/polkadot.json") },
"wss://kusama-rpc.polkadot.io:443" => { include_str!("../../assets/chainspecs/kusama.json") },
_ => panic!("not found {}", &url),
};
#[cfg(not(target_arch = "wasm32"))]
let mut source = CachedDataSource::new(RawDataSource::new(url));
let mut source = if chain_info.chain_url.is_relay() {
CachedDataSource::new(LightClientDataSource::new(urll))
} else {
CachedDataSource::new(LightClientDataSource::new(urll))
};
#[cfg(target_arch = "wasm32")]
let mut source = RawDataSource::new(url);

Expand Down
196 changes: 149 additions & 47 deletions src/datasource/raw_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,29 +288,8 @@ impl RawDataSource {
}
}

// #[async_trait(?Send)]
// trait ProcessIncoming {
// async fn process_incoming_messages(&self);
// }

#[async_trait(?Send)]
impl Source for RawDataSource {
// #[cfg(target_arch="wasm32")]
// async fn process_incoming_messages(&mut self) -> WSBackend {
// log!("get message processor");

// // while self.client.is_none() {
// // async_std::task::yield_now().await;
// // }
// // log!("await process incoming messages");
// let client = self.client();
// if let Some(_client) = client.await {
// log!("got message processor");
// self.client.as_ref().unwrap().clone()
// } else { panic!("no client could be gottet")}
// // log!("finish process incoming messages");
// }

async fn fetch_block_hash(
&mut self,
block_number: u32,
Expand All @@ -328,15 +307,6 @@ impl Source for RawDataSource {
}
}

/// Return then in bin form rather than link to subxt:
/// subxt::sp_runtime::generic::SignedBlock<
/// subxt::sp_runtime::generic::Block<
/// subxt::sp_runtime::generic::Header<
/// u32,
/// subxt::sp_runtime::traits::BlakeTwo256
/// >,
/// subxt::sp_runtime::OpaqueExtrinsic
///
async fn fetch_block(
&mut self,
block_hash: Option<H256>,
Expand Down Expand Up @@ -401,23 +371,6 @@ impl Source for RawDataSource {
} else {
Err(polkapipe::Error::Node(format!("can't get client for {}", self.ws_url)))
}
// //TODO: we're decoding and encoding here. cut it out.
// Ok(Some(AgnosticBlock {
// block_number: block_body.block.header.number,
// extrinsics: block_body
// .block
// .extrinsics
// .into_iter()
// .map(|ex| ex.encode())
// .collect::<Vec<_>>(),
// }))
// } else {
// if let Err(err) = result {
// Err(err)
// } else {
// Ok(None)
// }
// }
}

async fn fetch_storage(
Expand Down Expand Up @@ -453,6 +406,155 @@ impl Source for RawDataSource {
}
}

#[cfg(feature = "light-client")]
pub struct LightClientDataSource {
ws_url: String,
client: Option<polkapipe::smoldot_std::Backend>,
}

/// WIP: Just relay chains to start with as powered by smart clients because where to source
/// the chain-specs?
#[cfg(feature = "light-client")]
impl LightClientDataSource {
pub fn new(url: &str) -> Self {
LightClientDataSource { ws_url: url.to_string(), client: None }
}

async fn client(&mut self) -> Option<&mut polkapipe::smoldot_std::Backend> {
if self.client.is_none() {
//TODO specify parent
if let Ok(client) = polkapipe::smoldot_std::Backend::new(&self.ws_url, None).await
{
self.client = Some(client);
}
}
self.client.as_mut()
}
}

#[cfg(feature = "light-client")]
#[async_trait(?Send)]
impl Source for LightClientDataSource {
async fn fetch_block_hash(
&mut self,
block_number: u32,
) -> Result<Option<primitive_types::H256>, BError> {

if let Some(client) = self.client().await {
log!("get block number {}", block_number);
// log!("got client");
client
.query_block_hash(&[block_number])
.await
.map(|res| Some(H256::from_slice(&res[..])))
} else {
log!("could not get client");
Err(polkapipe::Error::Node(format!("can't get client for {}", self.ws_url)))
}
}

async fn fetch_block(
&mut self,
block_hash: Option<H256>,
) -> Result<Option<AgnosticBlock>, BError> {
if let Some(client) = self.client().await {
let opt = block_hash.map(|b|hex::encode(b.as_bytes()));
log!("get block hash {:?}", &opt);
let result = client.query_block(opt.as_deref()).await;

if let Ok(serde_json::value::Value::Object(map)) = &result {
// println!("got 2here");
if let Some(serde_json::value::Value::Object(map)) = map.get("block") {
let mut res = AgnosticBlock { block_number: 0, extrinsics: vec![] };
if let Some(serde_json::value::Value::Object(m)) = map.get("header") {
if let Some(serde_json::value::Value::String(num_original)) = m.get("number") {
let mut num = num_original.trim_start_matches("0x").to_string();
if num.len() % 2 == 1 {
// println!("odd found {}", num_original);
num = format!("0{}", num);
}

let _bytes = hex::decode(&num).unwrap();

// bytes.reverse(); //TODO: why is this needed? it gets the right number but...
/* while bytes.len() < 4 {
bytes.insert(0, 0);
} */
// println!("bytes or {}", num_original);
// println!("bytes is {}", hex::encode(&bytes));
// use parity_scale_codec::Decode;

let number: u32 = u32::from_str_radix(num_original.trim_start_matches("0x"), 16).unwrap();
// let number = u32::decode(&mut &bytes[..]).unwrap();

/* let mut b = [0,0,0,0];
for (i, bb) in bytes.iter().enumerate() {
b[i] = *bb;
} */
/* use parity_scale_codec::Compact;
/* */let number = Compact::<u32>::decode(&mut &bytes[..]).unwrap(); */
/* /* */let re : u32 = number.into(); */
// println!("bytes {} -> {}",&num_original, number);
res.block_number = number;
}
}
if let Some(serde_json::value::Value::Array(extrinsics)) = map.get("extrinsics")
{
for ex in extrinsics {
if let serde_json::value::Value::String(val) = ex {
/* println!("about to decode '{}'", &val); */
res.extrinsics
.push(hex::decode(val.trim_start_matches("0x")).unwrap());
} else {
panic!()
}
}
// println!("got 4here aa{}", extrinsics.len());
}
return Ok(Some(res))
}
}
result.map(|_| None)
} else {
Err(polkapipe::Error::Node(format!("can't get client for {}", self.ws_url)))
}
}

async fn fetch_storage(
&mut self,
key: &[u8],
as_of: Option<H256>,
) -> Result<Option<Vec<u8>>, BError> {
if let Some(client) = self.client().await {
log!("fetch storage {:?} {:?}", key, as_of);
if let Some(as_of) = as_of {
client.query_storage(key, Some(as_of.as_bytes())).await.map(Some)
} else {
client.query_storage(key, None).await.map(Some)
}
} else {
Err(polkapipe::Error::Node(format!("can't get client for {}", self.ws_url)))
}
}

async fn fetch_metadata(&mut self, as_of: Option<H256>) -> Result<Option<Vec<u8>>, ()> {
if let Some(client) = self.client().await {
log!("fetch metadata {:?}", as_of);
if let Some(as_of) = as_of {
client.query_metadata(Some(as_of.as_bytes())).await.map(Some).map_err(|_e| ())
} else {
client.query_metadata(None).await.map(Some).map_err(|_e| ())
}
} else {
Err(())
}
}

fn url(&self) -> &str {
&self.ws_url
}
}

#[cfg(test)]
mod tests {
use parity_scale_codec::Encode;
Expand Down
6 changes: 2 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(option_get_or_insert_default)]
#![feature(async_closure)]
#![feature(stmt_expr_attributes)]
#![feature(let_chains)]
use crate::ui::UrlBar;
use bevy::{ecs as bevy_ecs, prelude::*};
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -186,10 +185,9 @@ fn log(s: &str) {
}

pub fn main() {
#[cfg(target_arch = "wasm32")]
async_std::task::block_on(async_main());
let result = async_std::task::block_on(async_main());
#[cfg(not(target_arch = "wasm32"))]
async_std::task::block_on(async_main()).unwrap();
result.unwrap();
}

macro_rules! log {
Expand Down
Loading

0 comments on commit 215e93c

Please sign in to comment.