Skip to content
Snippets Groups Projects
Commit a001c0bd authored by Igor Matuszewski's avatar Igor Matuszewski
Browse files

Move pollable runtime interface only to offchain one

And only forward blocking waits for HTTP calls.
parent 2c200163
Branches
No related merge requests found
...@@ -248,8 +248,24 @@ sp_core::wasm_export_functions! { ...@@ -248,8 +248,24 @@ sp_core::wasm_export_functions! {
run().is_some() run().is_some()
} }
fn test_pollable() -> bool { fn test_offchain_pollable() -> bool {
sp_io::pollable::is_ready(sp_io::PollableId::from(0)) use sp_core::offchain::{PollableKind, PollableId};
let run = || -> Option<()> {
let id = sp_io::offchain::http_request_start(
"POST",
"http://localhost:12345",
&[],
).ok()?;
sp_io::offchain::http_request_write_body(id, &[], None).ok()?;
// let status = sp_io::offchain::http_response_wait(&[id], None);
let id = sp_core::offchain::PollableId::from_parts(PollableKind::Http, id.0 as u32);
sp_io::offchain::pollable_wait(&[id]);
Some(())
};
run().is_some()
} }
// Just some test to make sure that `sp-allocator` compiles on `no_std`. // Just some test to make sure that `sp-allocator` compiles on `no_std`.
......
...@@ -522,17 +522,30 @@ fn offchain_http_should_work(wasm_method: WasmExecutionMethod) { ...@@ -522,17 +522,30 @@ fn offchain_http_should_work(wasm_method: WasmExecutionMethod) {
#[test_case(WasmExecutionMethod::Interpreted)] #[test_case(WasmExecutionMethod::Interpreted)]
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))] #[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
fn pollable_smoke_test(wasm_method: WasmExecutionMethod) { fn offchain_pollable_should_wait(wasm_method: WasmExecutionMethod) {
let mut ext = TestExternalities::default(); let mut ext = TestExternalities::default();
let (offchain, state) = testing::TestOffchainExt::new();
ext.register_extension(OffchainExt::new(offchain));
state.write().expect_request(
0,
testing::PendingRequest {
method: "POST".into(),
uri: "http://localhost:12345".into(),
sent: true,
response: Some(vec![1, 2, 3]),
response_headers: vec![("X-Auth".to_owned(), "hello".to_owned())],
..Default::default()
},
);
assert_eq!( assert_eq!(
call_in_wasm( call_in_wasm(
"test_pollable", "test_offchain_pollable",
&[0], &[0],
wasm_method, wasm_method,
&mut ext.ext(), &mut ext.ext(),
).unwrap(), ).unwrap(),
false.encode(), true.encode(),
); );
} }
......
...@@ -28,7 +28,7 @@ use sc_network::{PeerId, Multiaddr, NetworkStateInfo}; ...@@ -28,7 +28,7 @@ use sc_network::{PeerId, Multiaddr, NetworkStateInfo};
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use sp_core::offchain::{ use sp_core::offchain::{
self, HttpRequestId, Timestamp, HttpRequestStatus, HttpError, self, HttpRequestId, Timestamp, HttpRequestStatus, HttpError,
OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, StorageKind, OpaqueNetworkState, OpaquePeerId, OpaqueMultiaddr, PollableId, StorageKind,
}; };
pub use sp_offchain::STORAGE_PREFIX; pub use sp_offchain::STORAGE_PREFIX;
pub use http::SharedClient; pub use http::SharedClient;
...@@ -180,6 +180,17 @@ impl<Storage: OffchainStorage> offchain::Externalities for Api<Storage> { ...@@ -180,6 +180,17 @@ impl<Storage: OffchainStorage> offchain::Externalities for Api<Storage> {
) -> Result<usize, HttpError> { ) -> Result<usize, HttpError> {
self.http.response_read_body(request_id, buffer, deadline) self.http.response_read_body(request_id, buffer, deadline)
} }
fn pollable_wait(&mut self, ids: &[PollableId]) {
use sp_core::offchain::PollableKind;
// FIXME: Handle more pollable kinds
assert!(ids.iter().all(|x| x.kind() == PollableKind::Http));
let ids: Result<Vec<HttpRequestId>, _> = ids.iter().copied().map(TryFrom::try_from).collect();
if let Ok(ids) = ids {
let _ = self.http.response_wait(&ids, None);
}
}
} }
/// Information about the local node's network state. /// Information about the local node's network state.
......
...@@ -179,6 +179,65 @@ impl TryFrom<u32> for HttpRequestStatus { ...@@ -179,6 +179,65 @@ impl TryFrom<u32> for HttpRequestStatus {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)]
pub enum PollableKind {
Http = 1,
Unknown,
}
impl From<u32> for PollableKind {
fn from(value: u32) -> Self {
match value {
1 => PollableKind::Http,
_ => PollableKind::Unknown,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, Encode, Decode, PassByInner)]
#[cfg_attr(feature = "std", derive(Hash))]
#[repr(transparent)]
pub struct PollableId(pub u64);
impl PollableId {
pub fn kind(self) -> PollableKind {
PollableKind::from((self.0 >> 32) as u32)
}
pub fn from_parts(kind: PollableKind, id: u32) -> PollableId {
PollableId::from(((kind as u64) << 32)| id as u64)
}
}
impl From<u64> for PollableId {
fn from(value: u64) -> PollableId {
PollableId(value)
}
}
impl Into<u64> for PollableId {
fn into(self) -> u64 {
self.0
}
}
impl From<HttpRequestId> for PollableId {
fn from(value: HttpRequestId) -> PollableId {
PollableId::from_parts(PollableKind::Http, u32::from(value.0))
}
}
impl TryFrom<PollableId> for HttpRequestId {
type Error = ();
fn try_from(value: PollableId) -> Result<HttpRequestId, Self::Error> {
match value.kind() {
PollableKind::Http => Ok(HttpRequestId(value.0 as _)),
_ => Err(()),
}
}
}
/// A blob to hold information about the local node's network state /// A blob to hold information about the local node's network state
/// without committing to its format. /// without committing to its format.
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByCodec)] #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, PassByCodec)]
...@@ -495,6 +554,9 @@ pub trait Externalities: Send { ...@@ -495,6 +554,9 @@ pub trait Externalities: Send {
buffer: &mut [u8], buffer: &mut [u8],
deadline: Option<Timestamp> deadline: Option<Timestamp>
) -> Result<usize, HttpError>; ) -> Result<usize, HttpError>;
/// TODO:
fn pollable_wait(&mut self, ids: &[PollableId]);
} }
impl<T: Externalities + ?Sized> Externalities for Box<T> { impl<T: Externalities + ?Sized> Externalities for Box<T> {
...@@ -573,6 +635,10 @@ impl<T: Externalities + ?Sized> Externalities for Box<T> { ...@@ -573,6 +635,10 @@ impl<T: Externalities + ?Sized> Externalities for Box<T> {
) -> Result<usize, HttpError> { ) -> Result<usize, HttpError> {
(&mut **self).http_response_read_body(request_id, buffer, deadline) (&mut **self).http_response_read_body(request_id, buffer, deadline)
} }
fn pollable_wait(&mut self, ids: &[PollableId]) {
(&mut **self).pollable_wait(ids)
}
} }
/// An `OffchainExternalities` implementation with limited capabilities. /// An `OffchainExternalities` implementation with limited capabilities.
...@@ -691,6 +757,11 @@ impl<T: Externalities> Externalities for LimitedExternalities<T> { ...@@ -691,6 +757,11 @@ impl<T: Externalities> Externalities for LimitedExternalities<T> {
self.check(Capability::Http, "http_response_read_body"); self.check(Capability::Http, "http_response_read_body");
self.externalities.http_response_read_body(request_id, buffer, deadline) self.externalities.http_response_read_body(request_id, buffer, deadline)
} }
fn pollable_wait(&mut self, ids: &[PollableId]) {
self.check(Capability::Http, "pollable_wait");
self.externalities.pollable_wait(ids)
}
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
......
...@@ -32,6 +32,7 @@ use crate::offchain::{ ...@@ -32,6 +32,7 @@ use crate::offchain::{
HttpRequestStatus as RequestStatus, HttpRequestStatus as RequestStatus,
Timestamp, Timestamp,
StorageKind, StorageKind,
PollableId,
OpaqueNetworkState, OpaqueNetworkState,
TransactionPool, TransactionPool,
OffchainStorage, OffchainStorage,
...@@ -375,6 +376,19 @@ impl offchain::Externalities for TestOffchainExt { ...@@ -375,6 +376,19 @@ impl offchain::Externalities for TestOffchainExt {
Err(HttpError::IoError) Err(HttpError::IoError)
} }
} }
fn pollable_wait(&mut self, ids: &[PollableId]) {
let state = self.0.read();
use std::convert::TryFrom;
for id in ids.iter().copied().map(RequestId::try_from).filter_map(Result::ok) {
match state.requests.get(&id) {
Some(req) if req.response.is_none() =>
panic!("No `response` provided for request with id: {:?}", id),
_ => (),
}
}
}
} }
/// The internal state of the fake transaction pool. /// The internal state of the fake transaction pool.
......
...@@ -45,13 +45,14 @@ use sp_core::{ ...@@ -45,13 +45,14 @@ use sp_core::{
crypto::KeyTypeId, ed25519, sr25519, ecdsa, H256, LogLevel, crypto::KeyTypeId, ed25519, sr25519, ecdsa, H256, LogLevel,
offchain::{ offchain::{
Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState, Timestamp, HttpRequestId, HttpRequestStatus, HttpError, StorageKind, OpaqueNetworkState,
PollableId,
}, },
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use sp_trie::{TrieConfiguration, trie_types::Layout}; use sp_trie::{TrieConfiguration, trie_types::Layout};
use sp_runtime_interface::{runtime_interface, Pointer, pass_by::PassByInner}; use sp_runtime_interface::{runtime_interface, Pointer};
use codec::{Encode, Decode}; use codec::{Encode, Decode};
...@@ -329,54 +330,6 @@ pub trait DefaultChildStorage { ...@@ -329,54 +330,6 @@ pub trait DefaultChildStorage {
} }
} }
#[derive(Debug, Clone, Copy)]
#[repr(u32)]
pub enum PollableKind {
Http = 1,
Unknown,
}
impl From<u32> for PollableKind {
fn from(value: u32) -> Self {
match value {
1 => PollableKind::Http,
_ => PollableKind::Unknown,
}
}
}
#[derive(Debug, Clone, Copy, PassByInner)]
pub struct PollableId(u64);
impl PollableId {
pub fn kind(self) -> PollableKind {
PollableKind::from((self.0 >> 32) as u32)
}
}
impl From<u64> for PollableId {
fn from(value: u64) -> PollableId {
PollableId(value)
}
}
impl Into<u64> for PollableId {
fn into(self) -> u64 {
self.0
}
}
/// Interface that provides async execution related functionality.
#[runtime_interface]
pub trait Pollable {
fn is_ready(msg: PollableId) -> bool {
false
}
fn wait_for(msg: PollableId) {
unimplemented!()
}
}
/// Interface that provides trie related functionality. /// Interface that provides trie related functionality.
#[runtime_interface] #[runtime_interface]
pub trait Trie { pub trait Trie {
...@@ -1010,6 +963,12 @@ pub trait Offchain { ...@@ -1010,6 +963,12 @@ pub trait Offchain {
.http_response_read_body(request_id, buffer, deadline) .http_response_read_body(request_id, buffer, deadline)
.map(|r| r as u32) .map(|r| r as u32)
} }
fn pollable_wait(&mut self, ids: &[PollableId]) {
self.extension::<OffchainExt>()
.expect("pollable_wait can be called only in the offchain worker context")
.pollable_wait(ids)
}
} }
/// Wasm only interface that provides functions for calling into the allocator. /// Wasm only interface that provides functions for calling into the allocator.
...@@ -1246,7 +1205,6 @@ pub type SubstrateHostFunctions = ( ...@@ -1246,7 +1205,6 @@ pub type SubstrateHostFunctions = (
offchain::HostFunctions, offchain::HostFunctions,
crypto::HostFunctions, crypto::HostFunctions,
hashing::HostFunctions, hashing::HostFunctions,
pollable::HostFunctions,
allocator::HostFunctions, allocator::HostFunctions,
logging::HostFunctions, logging::HostFunctions,
sandbox::HostFunctions, sandbox::HostFunctions,
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment