@@ -45,12 +45,14 @@ use crate::{
4545} ;
4646
4747use alloc:: {
48+ borrow:: Cow ,
49+ boxed:: Box ,
4850 format,
4951 string:: { String , ToString as _} ,
5052 sync:: Arc ,
5153} ;
52- use core:: num:: NonZeroU32 ;
53- use smoldot :: { chain_spec , json_rpc :: service } ;
54+ use core:: { num:: NonZeroU32 , pin :: Pin } ;
55+ use futures_lite :: StreamExt as _ ;
5456
5557/// Configuration for [`service()`].
5658pub struct Config < TPlat : PlatformRef > {
@@ -81,6 +83,7 @@ pub struct Config<TPlat: PlatformRef> {
8183 ///
8284 /// This parameter is necessary in order to prevent users from using up too much memory within
8385 /// the client.
86+ // TODO: unused at the moment
8487 pub max_parallel_requests : NonZeroU32 ,
8588}
8689
@@ -93,22 +96,20 @@ pub struct Config<TPlat: PlatformRef> {
9396pub fn service < TPlat : PlatformRef > ( config : Config < TPlat > ) -> ( Frontend < TPlat > , ServicePrototype ) {
9497 let log_target = format ! ( "json-rpc-{}" , config. log_name) ;
9598
96- let ( requests_processing_task, requests_responses_io) =
97- service:: client_main_task ( service:: Config {
98- max_active_subscriptions : config. max_subscriptions ,
99- max_pending_requests : config. max_pending_requests ,
100- } ) ;
99+ let ( requests_tx, requests_rx) = async_channel:: bounded ( 32 ) ; // TODO: capacity?
100+ let ( responses_tx, responses_rx) = async_channel:: bounded ( 16 ) ; // TODO: capacity?
101101
102102 let frontend = Frontend {
103103 platform : config. platform ,
104104 log_target : log_target. clone ( ) ,
105- requests_responses_io : Arc :: new ( requests_responses_io) ,
105+ responses_rx : Arc :: new ( async_lock:: Mutex :: new ( Box :: pin ( responses_rx) ) ) ,
106+ requests_tx,
106107 } ;
107108
108109 let prototype = ServicePrototype {
109110 log_target,
110- requests_processing_task ,
111- max_parallel_requests : config . max_parallel_requests ,
111+ requests_rx ,
112+ responses_tx ,
112113 } ;
113114
114115 ( frontend, prototype)
@@ -125,10 +126,12 @@ pub struct Frontend<TPlat> {
125126 /// See [`Config::platform`].
126127 platform : TPlat ,
127128
128- /// Sending requests and receiving responses.
129- ///
130- /// Connected to the [`background`].
131- requests_responses_io : Arc < service:: SerializedRequestsIo > ,
129+ /// How to send requests to the background task.
130+ requests_tx : async_channel:: Sender < String > ,
131+
132+ /// How to receive responses coming from the background task.
133+ // TODO: we use an Arc so that it's clonable, but that's questionnable
134+ responses_rx : Arc < async_lock:: Mutex < Pin < Box < async_channel:: Receiver < String > > > > > ,
132135
133136 /// Target to use when emitting logs.
134137 log_target : String ,
@@ -145,10 +148,7 @@ impl<TPlat: PlatformRef> Frontend<TPlat> {
145148 crate :: util:: truncated_str ( json_rpc_request. chars ( ) . filter ( |c| !c. is_control ( ) ) , 250 )
146149 . to_string ( ) ;
147150
148- match self
149- . requests_responses_io
150- . try_send_request ( json_rpc_request)
151- {
151+ match self . requests_tx . try_send ( json_rpc_request) {
152152 Ok ( ( ) ) => {
153153 log ! (
154154 & self . platform,
@@ -159,16 +159,9 @@ impl<TPlat: PlatformRef> Frontend<TPlat> {
159159 ) ;
160160 Ok ( ( ) )
161161 }
162- Err ( service:: TrySendRequestError {
163- cause : service:: TrySendRequestErrorCause :: TooManyPendingRequests ,
164- request,
165- } ) => Err ( HandleRpcError :: TooManyPendingRequests {
166- json_rpc_request : request,
162+ Err ( err) => Err ( HandleRpcError :: TooManyPendingRequests {
163+ json_rpc_request : err. into_inner ( ) ,
167164 } ) ,
168- Err ( service:: TrySendRequestError {
169- cause : service:: TrySendRequestErrorCause :: ClientMainTaskDestroyed ,
170- ..
171- } ) => unreachable ! ( ) ,
172165 }
173166 }
174167
@@ -177,9 +170,9 @@ impl<TPlat: PlatformRef> Frontend<TPlat> {
177170 /// If this function is called multiple times in parallel, the order in which the calls are
178171 /// responded to is unspecified.
179172 pub async fn next_json_rpc_response ( & self ) -> String {
180- let message = match self . requests_responses_io . wait_next_response ( ) . await {
181- Ok ( m) => m,
182- Err ( service :: WaitNextResponseError :: ClientMainTaskDestroyed ) => unreachable ! ( ) ,
173+ let message = match self . responses_rx . lock ( ) . await . next ( ) . await {
174+ Some ( m) => m,
175+ None => unreachable ! ( ) ,
183176 } ;
184177
185178 log ! (
@@ -197,20 +190,16 @@ impl<TPlat: PlatformRef> Frontend<TPlat> {
197190
198191/// Prototype for a JSON-RPC service. Must be initialized using [`ServicePrototype::start`].
199192pub struct ServicePrototype {
200- /// Task processing the requests.
201- ///
202- /// Later sent to the [`background`].
203- requests_processing_task : service:: ClientMainTask ,
204-
205193 /// Target to use when emitting logs.
206194 log_target : String ,
207195
208- /// Value obtained through [`Config::max_parallel_requests`].
209- max_parallel_requests : NonZeroU32 ,
196+ requests_rx : async_channel:: Receiver < String > ,
197+
198+ responses_tx : async_channel:: Sender < String > ,
210199}
211200
212201/// Configuration for a JSON-RPC service.
213- pub struct StartConfig < ' a , TPlat : PlatformRef > {
202+ pub struct StartConfig < TPlat : PlatformRef > {
214203 /// Access to the platform's capabilities.
215204 // TODO: redundant with Config above?
216205 pub platform : TPlat ,
@@ -228,8 +217,14 @@ pub struct StartConfig<'a, TPlat: PlatformRef> {
228217 /// Service that provides a ready-to-be-called runtime for the current best block.
229218 pub runtime_service : Arc < runtime_service:: RuntimeService < TPlat > > ,
230219
231- /// Specification of the chain.
232- pub chain_spec : & ' a chain_spec:: ChainSpec ,
220+ /// Name of the chain, as found in the chain specification.
221+ pub chain_name : String ,
222+ /// Type of chain, as found in the chain specification.
223+ pub chain_ty : String ,
224+ /// JSON-encoded properties of the chain, as found in the chain specification.
225+ pub chain_properties_json : String ,
226+ /// Whether the chain is a live network. Found in the chain specification.
227+ pub chain_is_live : bool ,
233228
234229 /// Value to return when the `system_name` RPC is called. Should be set to the name of the
235230 /// final executable.
@@ -240,33 +235,20 @@ pub struct StartConfig<'a, TPlat: PlatformRef> {
240235 pub system_version : String ,
241236
242237 /// Hash of the genesis block of the chain.
243- ///
244- /// > **Note**: This can be derived from a [`chain_spec::ChainSpec`]. While the
245- /// > [`ServicePrototype::start`] function could in theory use the
246- /// > [`StartConfig::chain_spec`] parameter to derive this value, doing so is quite
247- /// > expensive. We prefer to require this value from the upper layer instead, as
248- /// > it is most likely needed anyway.
249238 pub genesis_block_hash : [ u8 ; 32 ] ,
250239
251240 /// Hash of the storage trie root of the genesis block of the chain.
252- ///
253- /// > **Note**: This can be derived from a [`chain_spec::ChainSpec`]. While the
254- /// > [`ServicePrototype::start`] function could in theory use the
255- /// > [`StartConfig::chain_spec`] parameter to derive this value, doing so is quite
256- /// > expensive. We prefer to require this value from the upper layer instead, as
257- /// > it is most likely needed anyway.
258241 pub genesis_block_state_root : [ u8 ; 32 ] ,
259242}
260243
261244impl ServicePrototype {
262245 /// Consumes this prototype and starts the service through [`PlatformRef::spawn_task`].
263- pub fn start < TPlat : PlatformRef > ( self , config : StartConfig < ' _ , TPlat > ) {
264- background:: start (
265- self . log_target . clone ( ) ,
266- config,
267- self . requests_processing_task ,
268- self . max_parallel_requests ,
269- )
246+ pub fn start < TPlat : PlatformRef > ( self , config : StartConfig < TPlat > ) {
247+ let platform = config. platform . clone ( ) ;
248+ platform. spawn_task (
249+ Cow :: Owned ( self . log_target . clone ( ) ) ,
250+ background:: run ( self . log_target , config, self . requests_rx , self . responses_tx ) ,
251+ ) ;
270252 }
271253}
272254
0 commit comments