1#![allow(clippy::too_many_arguments)]
3
4use crate::{MassaRpcServer, Public, RpcServer, StopHandle, Value, API};
5use async_trait::async_trait;
6use itertools::{izip, Itertools};
7use jsonrpsee::core::{client::Error as JsonRpseeError, RpcResult};
8use massa_api_exports::{
9 address::{
10 AddressFilter, AddressInfo, GetAddressDatastoreKeysRequest, GetAddressDatastoreKeysResponse,
11 },
12 block::{BlockInfo, BlockInfoContent, BlockSummary},
13 config::APIConfig,
14 datastore::{DatastoreEntryInput, DatastoreEntryOutput},
15 endorsement::EndorsementInfo,
16 error::ApiError,
17 execution::{
18 DeferredCallResponse, DeferredCallsQuoteRequest, DeferredCallsQuoteResponse,
19 DeferredCallsSlotResponse, ExecuteReadOnlyResponse, ReadOnlyBytecodeExecution,
20 ReadOnlyCall, ReadOnlyResult, Transfer,
21 },
22 node::NodeStatus,
23 operation::{OperationInfo, OperationInput},
24 page::{PageRequest, PagedVec},
25 slot::SlotAmount,
26 TimeInterval,
27};
28use massa_consensus_exports::block_status::DiscardReason;
29use massa_consensus_exports::ConsensusController;
30use massa_execution_exports::{
31 ExecutionController, ExecutionQueryRequest, ExecutionQueryRequestItem, ExecutionQueryResponse,
32 ExecutionQueryResponseItem, ExecutionStackElement, ReadOnlyExecutionRequest,
33 ReadOnlyExecutionTarget,
34};
35use massa_models::{
36 address::Address,
37 amount::Amount,
38 block::{Block, BlockGraphStatus},
39 block_id::BlockId,
40 clique::Clique,
41 composite::PubkeySig,
42 config::CompactConfig,
43 datastore::{cleanup_datastore_key_range_query, DatastoreDeserializer},
44 deferred_calls::DeferredCallId,
45 endorsement::{EndorsementId, SecureShareEndorsement},
46 error::ModelsError,
47 execution::EventFilter,
48 node::NodeId,
49 operation::{OperationDeserializer, OperationId, SecureShareOperation},
50 output_event::SCOutputEvent,
51 prehash::{PreHashMap, PreHashSet},
52 secure_share::SecureShareDeserializer,
53 slot::{IndexedSlot, Slot},
54 timeslots::{self, get_latest_block_slot_at_timestamp, time_range_to_slot_range},
55 version::Version,
56};
57use massa_pool_exports::PoolController;
58use massa_pos_exports::SelectorController;
59use massa_protocol_exports::{PeerConnectionType, ProtocolConfig, ProtocolController};
60use massa_serialization::{DeserializeError, Deserializer};
61use massa_storage::Storage;
62use massa_time::MassaTime;
63use massa_versioning::versioning_factory::FactoryStrategy;
64use massa_versioning::{
65 keypair_factory::KeyPairFactory, versioning::MipStore, versioning_factory::VersioningFactory,
66};
67use std::net::{IpAddr, SocketAddr};
68use std::{collections::BTreeMap, str::FromStr};
69use tracing::warn;
70
71impl API<Public> {
72 pub fn new(
74 consensus_controller: Box<dyn ConsensusController>,
75 execution_controller: Box<dyn ExecutionController>,
76 api_settings: APIConfig,
77 selector_controller: Box<dyn SelectorController>,
78 pool_command_sender: Box<dyn PoolController>,
79 protocol_controller: Box<dyn ProtocolController>,
80 protocol_config: ProtocolConfig,
81 version: Version,
82 node_id: NodeId,
83 storage: Storage,
84 mip_store: MipStore,
85 ) -> Self {
86 API(Public {
87 consensus_controller,
88 api_settings,
89 pool_command_sender,
90 version,
91 protocol_controller,
92 node_id,
93 execution_controller,
94 selector_controller,
95 protocol_config,
96 storage,
97 keypair_factory: KeyPairFactory { mip_store },
98 })
99 }
100
101 fn exec_query(&self, requests: Vec<ExecutionQueryRequestItem>) -> ExecutionQueryResponse {
102 self.0
103 .execution_controller
104 .query_state(ExecutionQueryRequest {
105 requests,
106 max_response_size: self.0.api_settings.max_response_body_size as usize,
107 max_event_count: Some(self.0.api_settings.max_event_per_query as usize),
108 query_state_deadline_ms: self.0.api_settings.query_state_deadline_ms,
109 })
110 }
111}
112
113#[async_trait]
114impl RpcServer for API<Public> {
115 async fn serve(
116 self,
117 url: &SocketAddr,
118 api_config: &APIConfig,
119 ) -> Result<StopHandle, JsonRpseeError> {
120 crate::serve(self.into_rpc(), url, api_config).await
121 }
122}
123
124#[doc(hidden)]
125#[async_trait]
126impl MassaRpcServer for API<Public> {
127 fn stop_node(&self) -> RpcResult<()> {
128 crate::wrong_api::<()>()
129 }
130
131 async fn node_sign_message(&self, _: Vec<u8>) -> RpcResult<PubkeySig> {
132 crate::wrong_api::<PubkeySig>()
133 }
134
135 async fn add_staking_secret_keys(&self, _: Vec<String>) -> RpcResult<()> {
136 crate::wrong_api::<()>()
137 }
138
139 #[cfg(feature = "execution-trace")]
140 async fn get_slots_transfers(&self, slots: Vec<Slot>) -> RpcResult<Vec<Vec<Transfer>>> {
141 use massa_api_exports::execution::TransferContext;
142 use std::str::FromStr;
143
144 let mut res: Vec<Vec<Transfer>> = Vec::with_capacity(slots.len());
145 for slot in slots {
146 let Some(block_id) = self
147 .0
148 .consensus_controller
149 .get_blockclique_block_at_slot(slot)
150 else {
151 res.push(Vec::new());
157 continue;
158 };
159 let mut transfers = Vec::new();
160 let (abi_calls, slot_transfers) = self
164 .0
165 .execution_controller
166 .get_slot_abi_call_stack_and_transfers(slot);
167 if let Some(abi_calls) = abi_calls {
168 let abi_transfer_1 = "assembly_script_transfer_coins".to_string();
171 let abi_transfer_2 = "assembly_script_transfer_coins_for".to_string();
172 let abi_transfer_3 = "abi_transfer_coins".to_string();
173 let transfer_abi_names = vec![abi_transfer_1, abi_transfer_2, abi_transfer_3];
174 for (i, asc_call_stack) in abi_calls.asc_call_stacks.iter().enumerate() {
175 for abi_trace in asc_call_stack {
176 let only_transfer = abi_trace.flatten_filter(&transfer_abi_names);
177 for transfer in only_transfer {
178 let (t_from, t_to, t_amount) = transfer.parse_transfer();
179 if let (Ok(addr_from), Ok(addr_to)) =
180 (Address::from_str(&t_from), Address::from_str(&t_to))
181 {
182 transfers.push(Transfer {
183 from: addr_from,
184 to: addr_to,
185 amount: Amount::from_raw(t_amount),
186 effective_amount_received: Amount::from_raw(t_amount),
187 context: TransferContext::ASC(i as u64),
188 succeed: true,
189 fee: Amount::from_raw(0),
190 block_id,
191 });
192 }
193 }
194 }
195 }
196
197 for (call_id, deferred_call_call_stack) in abi_calls.deferred_call_stacks {
198 for abi_trace in deferred_call_call_stack {
199 let only_transfer = abi_trace.flatten_filter(&transfer_abi_names);
200 for transfer in only_transfer {
201 let (t_from, t_to, t_amount) = transfer.parse_transfer();
202 if let (Ok(addr_from), Ok(addr_to)) =
203 (Address::from_str(&t_from), Address::from_str(&t_to))
204 {
205 transfers.push(Transfer {
206 from: addr_from,
207 to: addr_to,
208 amount: Amount::from_raw(t_amount),
209 effective_amount_received: Amount::from_raw(t_amount),
210 context: TransferContext::DeferredCall(call_id.clone()),
211 succeed: true,
212 fee: Amount::from_raw(0),
213 block_id,
214 });
215 }
216 }
217 }
218 }
219
220 for op_call_stack in abi_calls.operation_call_stacks {
221 let op_id = op_call_stack.0;
222 let op_call_stack = op_call_stack.1;
223 for abi_trace in op_call_stack {
224 let only_transfer = abi_trace.flatten_filter(&transfer_abi_names);
225 for transfer in only_transfer {
226 let (t_from, t_to, t_amount) = transfer.parse_transfer();
227 if let (Ok(addr_from), Ok(addr_to)) =
228 (Address::from_str(&t_from), Address::from_str(&t_to))
229 {
230 transfers.push(Transfer {
231 from: addr_from,
232 to: addr_to,
233 amount: Amount::from_raw(t_amount),
234 effective_amount_received: Amount::from_raw(t_amount),
235 context: TransferContext::Operation(op_id),
236 succeed: true,
237 fee: Amount::from_raw(0),
238 block_id,
239 });
240 }
241 }
242 }
243 }
244 }
245 let transfers_op: Vec<Transfer> = slot_transfers
246 .unwrap_or_default()
247 .iter()
248 .map(|t| Transfer {
249 from: t.from,
250 to: t.to,
251 amount: t.amount,
252 effective_amount_received: t.effective_received_amount,
253 context: TransferContext::Operation(t.op_id),
254 succeed: t.succeed,
255 fee: t.fee,
256 block_id,
257 })
258 .collect();
259 transfers.extend(transfers_op);
260 res.push(transfers);
261 }
262 Ok(res)
263 }
264
265 #[cfg(not(feature = "execution-trace"))]
266 async fn get_slots_transfers(&self, _: Vec<Slot>) -> RpcResult<Vec<Vec<Transfer>>> {
267 RpcResult::Err(ApiError::BadRequest("feature execution-trace is not enabled".into()).into())
268 }
269
270 async fn execute_read_only_bytecode(
271 &self,
272 reqs: Vec<ReadOnlyBytecodeExecution>,
273 ) -> RpcResult<Vec<ExecuteReadOnlyResponse>> {
274 if reqs.len() as u64 > self.0.api_settings.max_arguments {
275 return Err(ApiError::BadRequest("too many arguments".into()).into());
276 }
277
278 let mut res: Vec<ExecuteReadOnlyResponse> = Vec::with_capacity(reqs.len());
279 for ReadOnlyBytecodeExecution {
280 max_gas,
281 address,
282 bytecode,
283 operation_datastore,
284 fee,
285 } in reqs
286 {
287 let address = if let Some(addr) = address {
288 addr
289 } else {
290 let now = MassaTime::now();
291 let keypair = self
292 .0
293 .keypair_factory
294 .create(&(), FactoryStrategy::At(now))
295 .map_err(ApiError::from)?;
296 Address::from_public_key(&keypair.get_public_key())
297 };
298
299 let op_datastore = match operation_datastore {
300 Some(v) => {
301 let deserializer = DatastoreDeserializer::new(
302 self.0.api_settings.max_op_datastore_entry_count,
303 self.0.api_settings.max_op_datastore_key_length,
304 self.0.api_settings.max_op_datastore_value_length,
305 );
306 match deserializer.deserialize::<DeserializeError>(&v) {
307 Ok((_, deserialized)) => Some(deserialized),
308 Err(e) => {
309 return Err(ApiError::InconsistencyError(format!(
310 "Operation datastore error: {}",
311 e
312 ))
313 .into())
314 }
315 }
316 }
317 None => None,
318 };
319
320 let req = ReadOnlyExecutionRequest {
322 max_gas,
323 target: ReadOnlyExecutionTarget::BytecodeExecution(bytecode),
324 call_stack: vec![ExecutionStackElement {
325 address,
326 coins: Default::default(),
327 owned_addresses: vec![address],
328 operation_datastore: op_datastore,
329 }],
330 coins: None,
331 fee,
332 };
333
334 if let Some(fee) = fee {
336 if fee.checked_sub(self.0.api_settings.minimal_fees).is_none() {
337 let result = ExecuteReadOnlyResponse {
338 executed_at: Slot::new(0, 0),
339 result: ReadOnlyResult::Error(format!(
340 "fee is too low provided: {} , minimal_fees required: {}",
341 fee, self.0.api_settings.minimal_fees
342 )),
343 gas_cost: 0,
344 output_events: Default::default(),
345 state_changes: Default::default(),
346 };
347 res.push(result);
348 continue;
349 }
350 }
351
352 let result = self.0.execution_controller.execute_readonly_request(req);
354
355 let result = ExecuteReadOnlyResponse {
357 executed_at: result
358 .as_ref()
359 .map_or_else(|_| Slot::new(0, 0), |v| v.out.slot),
360 result: result.as_ref().map_or_else(
361 |err| ReadOnlyResult::Error(format!("readonly call failed: {}", err)),
362 |res| ReadOnlyResult::Ok(res.call_result.clone()),
363 ),
364 gas_cost: result.as_ref().map_or_else(|_| 0, |v| v.gas_cost),
365 output_events: result
366 .as_ref()
367 .map_or_else(|_| Default::default(), |v| v.out.events.clone().0),
368 state_changes: result.map_or_else(|_| Default::default(), |v| v.out.state_changes),
369 };
370
371 res.push(result);
372 }
373
374 Ok(res)
376 }
377
378 async fn execute_read_only_call(
380 &self,
381 reqs: Vec<ReadOnlyCall>,
382 ) -> RpcResult<Vec<ExecuteReadOnlyResponse>> {
383 if reqs.len() as u64 > self.0.api_settings.max_arguments {
384 return Err(ApiError::BadRequest("too many arguments".into()).into());
385 }
386
387 let mut res: Vec<ExecuteReadOnlyResponse> = Vec::with_capacity(reqs.len());
388 for ReadOnlyCall {
389 max_gas,
390 target_address,
391 target_function,
392 parameter,
393 caller_address,
394 coins,
395 fee,
396 } in reqs
397 {
398 let caller_address = if let Some(addr) = caller_address {
399 addr
400 } else {
401 let now = MassaTime::now();
402 let keypair = self
403 .0
404 .keypair_factory
405 .create(&(), FactoryStrategy::At(now))
406 .map_err(ApiError::from)?;
407 Address::from_public_key(&keypair.get_public_key())
408 };
409
410 let req = ReadOnlyExecutionRequest {
412 max_gas,
413 target: ReadOnlyExecutionTarget::FunctionCall {
414 target_func: target_function,
415 target_addr: target_address,
416 parameter,
417 },
418 call_stack: vec![
419 ExecutionStackElement {
420 address: caller_address,
421 coins: Default::default(),
422 owned_addresses: vec![caller_address],
423 operation_datastore: None, },
425 ExecutionStackElement {
426 address: target_address,
427 coins: coins.unwrap_or(Amount::default()),
428 owned_addresses: vec![target_address],
429 operation_datastore: None, },
431 ],
432 coins,
433 fee,
434 };
435
436 if let Some(fee) = fee {
437 if fee.checked_sub(self.0.api_settings.minimal_fees).is_none() {
438 let result = ExecuteReadOnlyResponse {
439 executed_at: Slot::new(0, 0),
440 result: ReadOnlyResult::Error(format!(
441 "fee is too low provided: {} , minimal_fees required: {}",
442 fee, self.0.api_settings.minimal_fees
443 )),
444 gas_cost: 0,
445 output_events: Default::default(),
446 state_changes: Default::default(),
447 };
448 res.push(result);
449 continue;
450 }
451 }
452
453 let result = self.0.execution_controller.execute_readonly_request(req);
455
456 let result = ExecuteReadOnlyResponse {
458 executed_at: result
459 .as_ref()
460 .map_or_else(|_| Slot::new(0, 0), |v| v.out.slot),
461 result: result.as_ref().map_or_else(
462 |err| ReadOnlyResult::Error(format!("readonly call failed: {}", err)),
463 |res| ReadOnlyResult::Ok(res.call_result.clone()),
464 ),
465 gas_cost: result.as_ref().map_or_else(|_| 0, |v| v.gas_cost),
466 output_events: result
467 .as_ref()
468 .map_or_else(|_| Default::default(), |v| v.out.events.clone().0),
469 state_changes: result.map_or_else(|_| Default::default(), |v| v.out.state_changes),
470 };
471
472 res.push(result);
473 }
474
475 Ok(res)
477 }
478
479 async fn remove_staking_addresses(&self, _: Vec<Address>) -> RpcResult<()> {
480 crate::wrong_api::<()>()
481 }
482
483 async fn get_staking_addresses(&self) -> RpcResult<PreHashSet<Address>> {
484 crate::wrong_api::<PreHashSet<Address>>()
485 }
486
487 async fn node_ban_by_ip(&self, _: Vec<IpAddr>) -> RpcResult<()> {
488 crate::wrong_api::<()>()
489 }
490
491 async fn node_ban_by_id(&self, _: Vec<NodeId>) -> RpcResult<()> {
492 crate::wrong_api::<()>()
493 }
494
495 async fn node_unban_by_ip(&self, _: Vec<IpAddr>) -> RpcResult<()> {
496 crate::wrong_api::<()>()
497 }
498
499 async fn node_unban_by_id(&self, _: Vec<NodeId>) -> RpcResult<()> {
500 crate::wrong_api::<()>()
501 }
502
503 async fn get_status(&self) -> RpcResult<NodeStatus> {
505 let version = self.0.version;
506 let api_settings = self.0.api_settings.clone();
507 let protocol_config = self.0.protocol_config.clone();
508 let node_id = self.0.node_id;
509 let config = CompactConfig::default();
510 let now = MassaTime::now();
511
512 let current_mip_version = self
513 .0
514 .keypair_factory
515 .mip_store
516 .get_network_version_current();
517
518 let last_slot_result = get_latest_block_slot_at_timestamp(
519 api_settings.thread_count,
520 api_settings.t0,
521 api_settings.genesis_timestamp,
522 now,
523 );
524 let last_slot = match last_slot_result {
525 Ok(last_slot) => last_slot,
526 Err(e) => return Err(ApiError::ModelsError(e).into()),
527 };
528
529 let execution_stats = self.0.execution_controller.get_stats();
530 let consensus_stats_result = self.0.consensus_controller.get_stats();
531 let consensus_stats = match consensus_stats_result {
532 Ok(consensus_stats) => consensus_stats,
533 Err(e) => return Err(ApiError::ConsensusError(e.to_string()).into()),
534 };
535
536 let (network_stats, peers) = match self.0.protocol_controller.get_stats() {
537 Ok((stats, peers)) => (stats, peers),
538 Err(e) => return Err(ApiError::ProtocolError(e.to_string()).into()),
539 };
540
541 let pool_stats = (
542 match self
543 .0
544 .pool_command_sender
545 .get_operation_count(Some(self.0.api_settings.pool_api_timeout))
546 {
547 Ok(count) => count,
548 Err(e) => return Err(ApiError::PoolError(e).into()),
549 },
550 match self
551 .0
552 .pool_command_sender
553 .get_endorsement_count(Some(self.0.api_settings.pool_api_timeout))
554 {
555 Ok(count) => count,
556 Err(e) => return Err(ApiError::PoolError(e).into()),
557 },
558 );
559
560 let next_slot_result = last_slot
561 .unwrap_or_else(|| Slot::new(0, 0))
562 .get_next_slot(api_settings.thread_count);
563
564 let next_slot = match next_slot_result {
565 Ok(next_slot) => next_slot,
566 Err(e) => return Err(ApiError::ModelsError(e).into()),
567 };
568
569 let connected_nodes = peers
570 .iter()
571 .map(|(id, peer)| {
572 let is_outgoing = match peer.1 {
573 PeerConnectionType::IN => false,
574 PeerConnectionType::OUT => true,
575 };
576 (NodeId::new(id.get_public_key()), (peer.0.ip(), is_outgoing))
577 })
578 .collect::<BTreeMap<_, _>>();
579
580 let current_cycle = last_slot
581 .unwrap_or_else(|| Slot::new(0, 0))
582 .get_cycle(api_settings.periods_per_cycle);
583
584 let cycle_duration = match api_settings.t0.checked_mul(api_settings.periods_per_cycle) {
585 Ok(cycle_duration) => cycle_duration,
586 Err(e) => return Err(ApiError::TimeError(e).into()),
587 };
588
589 let current_cycle_time_result = if current_cycle == 0 {
590 Ok(api_settings.genesis_timestamp)
591 } else {
592 cycle_duration.checked_mul(current_cycle).and_then(
593 |elapsed_time_before_current_cycle| {
594 api_settings
595 .genesis_timestamp
596 .checked_add(elapsed_time_before_current_cycle)
597 },
598 )
599 };
600
601 let current_cycle_time = match current_cycle_time_result {
602 Ok(current_cycle_time) => current_cycle_time,
603 Err(e) => return Err(ApiError::TimeError(e).into()),
604 };
605
606 let next_cycle_time = match current_cycle_time.checked_add(cycle_duration) {
607 Ok(next_cycle_time) => next_cycle_time,
608 Err(e) => return Err(ApiError::TimeError(e).into()),
609 };
610
611 Ok(NodeStatus {
612 node_id,
613 node_ip: protocol_config.routable_ip,
614 version,
615 current_time: now,
616 current_cycle_time,
617 next_cycle_time,
618 connected_nodes,
619 last_slot,
620 next_slot,
621 execution_stats,
622 consensus_stats,
623 network_stats,
624 pool_stats,
625 config,
626 current_cycle,
627 chain_id: self.0.api_settings.chain_id,
628 minimal_fees: self.0.api_settings.minimal_fees,
629 current_mip_version,
630 max_datastore_keys_query: self.0.api_settings.max_datastore_keys_queries,
631 })
632 }
633
634 async fn get_cliques(&self) -> RpcResult<Vec<Clique>> {
636 Ok(self.0.consensus_controller.get_cliques())
637 }
638
639 async fn get_stakers(
641 &self,
642 page_request: Option<PageRequest>,
643 ) -> RpcResult<PagedVec<(Address, u64)>> {
644 let cfg = self.0.api_settings.clone();
645
646 let now = MassaTime::now();
647
648 let latest_block_slot_at_timestamp_result = get_latest_block_slot_at_timestamp(
649 cfg.thread_count,
650 cfg.t0,
651 cfg.genesis_timestamp,
652 now,
653 );
654
655 let curr_cycle = match latest_block_slot_at_timestamp_result {
656 Ok(Some(cur_slot)) if cur_slot.period <= self.0.api_settings.last_start_period => {
657 Slot::new(self.0.api_settings.last_start_period, 0).get_cycle(cfg.periods_per_cycle)
658 }
659 Ok(Some(cur_slot)) => cur_slot.get_cycle(cfg.periods_per_cycle),
660 Ok(None) => 0,
661 Err(e) => return Err(ApiError::ModelsError(e).into()),
662 };
663
664 let mut staker_vec = self
665 .0
666 .execution_controller
667 .get_cycle_active_rolls(curr_cycle)
668 .into_iter()
669 .collect::<Vec<(Address, u64)>>();
670
671 staker_vec
672 .sort_by(|&(_, roll_counts_a), &(_, roll_counts_b)| roll_counts_b.cmp(&roll_counts_a));
673
674 let paged_vec = PagedVec::new(staker_vec, page_request);
675
676 Ok(paged_vec)
677 }
678
679 async fn get_operations(
681 &self,
682 operations_ids: Vec<OperationId>,
683 ) -> RpcResult<Vec<OperationInfo>> {
684 let api_cfg = self.0.api_settings.clone();
685 if operations_ids.len() as u64 > api_cfg.max_arguments {
687 return Err(ApiError::BadRequest("too many arguments".into()).into());
688 }
689
690 let secure_share_operations: Vec<SecureShareOperation> = {
692 let read_ops = self.0.storage.read_operations();
693 operations_ids
694 .iter()
695 .filter_map(|id| read_ops.get(id).cloned())
696 .collect()
697 };
698
699 let storage_info: Vec<(SecureShareOperation, PreHashSet<BlockId>)> = {
700 let read_blocks = self.0.storage.read_blocks();
701 secure_share_operations
702 .into_iter()
703 .map(|secure_share_operation| {
704 let op_id = secure_share_operation.id;
705 (
706 secure_share_operation,
707 read_blocks
708 .get_blocks_by_operation(&op_id)
709 .cloned()
710 .unwrap_or_default(),
711 )
712 })
713 .collect()
714 };
715
716 let ops: Vec<OperationId> = storage_info.iter().map(|(op, _)| op.id).collect();
718
719 let in_pool = self
724 .0
725 .pool_command_sender
726 .contains_operations(&ops, Some(api_cfg.pool_api_timeout))
727 .unwrap_or_else(|e| {
728 warn!(
729 "could not read operations from pool, reporting in_pool=false: {}",
730 e
731 );
732 vec![false; ops.len()]
733 });
734
735 let op_exec_statuses = self.0.execution_controller.get_ops_exec_status(&ops);
736
737 let (is_operation_final, statuses): (Vec<Option<bool>>, Vec<Option<bool>>) =
739 op_exec_statuses
740 .into_iter()
741 .map(|(spec_exec, final_exec)| match (spec_exec, final_exec) {
742 (Some(true), Some(true)) => (Some(true), Some(true)),
743 (Some(false), Some(false)) => (Some(true), Some(false)),
744 (Some(true), None) => (Some(false), Some(true)),
745 (Some(false), None) => (Some(false), Some(false)),
746 _ => (None, None),
747 })
748 .collect::<Vec<(Option<bool>, Option<bool>)>>()
749 .into_iter()
750 .unzip();
751
752 let mut res: Vec<OperationInfo> = Vec::with_capacity(ops.len());
754 let zipped_iterator = izip!(
755 ops.into_iter(),
756 storage_info.into_iter(),
757 in_pool.into_iter(),
758 is_operation_final.into_iter(),
759 statuses.into_iter(),
760 );
761 for (id, (operation, in_blocks), in_pool, is_operation_final, op_exec_status) in
762 zipped_iterator
763 {
764 #[cfg(feature = "execution-trace")]
765 {
766 let mut transfer = None;
767 if is_operation_final.is_none() || op_exec_status.is_none() {
768 transfer = self.0.execution_controller.get_transfer_for_op(&id);
769 }
770 let is_operation_final = is_operation_final.or(Some(transfer.is_some()));
771 let op_exec_status = op_exec_status.or(transfer.map(|t| t.succeed));
772 res.push(OperationInfo {
773 id,
774 in_pool,
775 is_operation_final,
776 thread: operation
777 .content_creator_address
778 .get_thread(api_cfg.thread_count),
779 operation,
780 in_blocks: in_blocks.into_iter().collect(),
781 op_exec_status,
782 });
783 }
784 #[cfg(not(feature = "execution-trace"))]
785 {
786 res.push(OperationInfo {
787 id,
788 in_pool,
789 is_operation_final,
790 thread: operation
791 .content_creator_address
792 .get_thread(api_cfg.thread_count),
793 operation,
794 in_blocks: in_blocks.into_iter().collect(),
795 op_exec_status,
796 });
797 }
798 }
799
800 Ok(res)
802 }
803
804 async fn get_endorsements(
806 &self,
807 mut endorsement_ids: Vec<EndorsementId>,
808 ) -> RpcResult<Vec<EndorsementInfo>> {
809 if endorsement_ids.len() as u64 > self.0.api_settings.max_arguments {
810 return Err(ApiError::BadRequest("too many arguments".into()).into());
811 }
812
813 let mut secure_share_endorsements: Vec<SecureShareEndorsement> =
814 Vec::with_capacity(endorsement_ids.len());
815 {
816 let endorsement_storage_lock = self.0.storage.read_endorsements();
817 endorsement_ids.retain(|id| {
818 if let Some(wrapped_endorsement) = endorsement_storage_lock.get(id) {
819 secure_share_endorsements.push(wrapped_endorsement.clone());
820 return true;
821 };
822 false
823 });
824 }
825
826 let storage_info: Vec<(SecureShareEndorsement, PreHashSet<BlockId>)> = {
827 let read_blocks = self.0.storage.read_blocks();
828 secure_share_endorsements
829 .into_iter()
830 .map(|secure_share_operation| {
831 let ed_id = secure_share_operation.id;
832 (
833 secure_share_operation,
834 read_blocks
835 .get_blocks_by_endorsement(&ed_id)
836 .cloned()
837 .unwrap_or_default(),
838 )
839 })
840 .collect()
841 };
842
843 let in_pool = self
848 .0
849 .pool_command_sender
850 .contains_endorsements(&endorsement_ids, Some(self.0.api_settings.pool_api_timeout))
851 .unwrap_or_else(|e| {
852 warn!(
853 "could not read endorsements from pool, reporting in_pool=false: {}",
854 e
855 );
856 vec![false; endorsement_ids.len()]
857 });
858
859 let is_final: Vec<bool> = {
861 let involved_blocks: Vec<BlockId> = storage_info
862 .iter()
863 .flat_map(|(_ed, bs)| bs.iter())
864 .unique()
865 .cloned()
866 .collect();
867
868 let involved_block_statuses = self
869 .0
870 .consensus_controller
871 .get_block_statuses(&involved_blocks);
872
873 let block_statuses: PreHashMap<BlockId, BlockGraphStatus> = involved_blocks
874 .into_iter()
875 .zip(involved_block_statuses)
876 .collect();
877 storage_info
878 .iter()
879 .map(|(_ed, bs)| {
880 bs.iter()
881 .any(|b| block_statuses.get(b) == Some(&BlockGraphStatus::Final))
882 })
883 .collect()
884 };
885
886 let mut res: Vec<EndorsementInfo> = Vec::with_capacity(endorsement_ids.len());
888 let zipped_iterator = izip!(
889 endorsement_ids.into_iter(),
890 storage_info.into_iter(),
891 in_pool.into_iter(),
892 is_final.into_iter()
893 );
894 for (id, (endorsement, in_blocks), in_pool, is_final) in zipped_iterator {
895 res.push(EndorsementInfo {
896 id,
897 endorsement,
898 in_pool,
899 is_final,
900 in_blocks: in_blocks.into_iter().collect(),
901 });
902 }
903
904 Ok(res)
906 }
907
908 async fn get_blocks(&self, mut ids: Vec<BlockId>) -> RpcResult<Vec<BlockInfo>> {
911 let mut blocks: Vec<Block> = Vec::with_capacity(ids.len());
912 {
913 let block_storage_lock = self.0.storage.read_blocks();
914 ids.retain(|id| {
915 if let Some(wrapped_block) = block_storage_lock.get(id) {
916 blocks.push(wrapped_block.content.clone());
917 return true;
918 };
919 false
920 });
921 }
922 let block_statuses = self.0.consensus_controller.get_block_statuses(&ids);
923 let res = ids
924 .into_iter()
925 .zip(blocks)
926 .zip(block_statuses)
927 .map(|((id, content), graph_status)| BlockInfo {
928 id,
929 content: Some(BlockInfoContent {
930 is_final: graph_status == BlockGraphStatus::Final,
931 is_in_blockclique: graph_status == BlockGraphStatus::ActiveInBlockclique,
932 is_candidate: graph_status == BlockGraphStatus::ActiveInBlockclique
933 || graph_status == BlockGraphStatus::ActiveInAlternativeCliques,
934 is_discarded: graph_status == BlockGraphStatus::Discarded,
935 block: content,
936 }),
937 })
938 .collect();
939 Ok(res)
940 }
941
942 async fn get_blockclique_block_by_slot(&self, slot: Slot) -> RpcResult<Option<Block>> {
943 let block_id_option = self
944 .0
945 .consensus_controller
946 .get_blockclique_block_at_slot(slot);
947
948 let block_id = match block_id_option {
949 Some(id) => id,
950 None => return Ok(None),
951 };
952
953 let res = self
954 .0
955 .storage
956 .read_blocks()
957 .get(&block_id)
958 .map(|b| b.content.clone());
959 Ok(res)
960 }
961
962 async fn get_graph_interval(&self, time: TimeInterval) -> RpcResult<Vec<BlockSummary>> {
965 let api_settings = self.0.api_settings.clone();
966
967 let time_range_to_slot_range_result = time_range_to_slot_range(
969 api_settings.thread_count,
970 api_settings.t0,
971 api_settings.genesis_timestamp,
972 time.start,
973 time.end,
974 );
975
976 let (start_slot, end_slot) = match time_range_to_slot_range_result {
977 Ok(time_range_to_slot_range) => time_range_to_slot_range,
978 Err(e) => return Err(ApiError::ModelsError(e).into()),
979 };
980
981 let graph = match self
982 .0
983 .consensus_controller
984 .get_block_graph_status(start_slot, end_slot)
985 {
986 Ok(graph) => graph,
987 Err(e) => return Err(ApiError::ConsensusError(e.to_string()).into()),
988 };
989
990 let mut res = Vec::with_capacity(graph.active_blocks.len());
991 let blockclique = graph
992 .max_cliques
993 .iter()
994 .find(|clique| clique.is_blockclique)
995 .ok_or_else(|| ApiError::InconsistencyError("missing blockclique".to_string()))?;
996 for (id, exported_block) in graph.active_blocks.into_iter() {
997 res.push(BlockSummary {
998 id,
999 is_final: exported_block.is_final,
1000 is_stale: false,
1001 is_in_blockclique: blockclique.block_ids.contains(&id),
1002 slot: exported_block.header.content.slot,
1003 creator: exported_block.header.content_creator_address,
1004 parents: exported_block.header.content.parents,
1005 });
1006 }
1007 for (id, (reason, (slot, creator, parents))) in graph.discarded_blocks.into_iter() {
1008 if reason == DiscardReason::Stale {
1009 res.push(BlockSummary {
1010 id,
1011 is_final: false,
1012 is_stale: true,
1013 is_in_blockclique: false,
1014 slot,
1015 creator,
1016 parents,
1017 });
1018 }
1019 }
1020 Ok(res)
1021 }
1022
1023 async fn get_datastore_entries(
1025 &self,
1026 entries: Vec<DatastoreEntryInput>,
1027 ) -> RpcResult<Vec<DatastoreEntryOutput>> {
1028 Ok(self
1029 .0
1030 .execution_controller
1031 .get_final_and_active_data_entry(
1032 entries
1033 .into_iter()
1034 .map(|input| (input.address, input.key))
1035 .collect::<Vec<_>>(),
1036 )
1037 .into_iter()
1038 .map(|output| DatastoreEntryOutput {
1039 final_value: output.0,
1040 candidate_value: output.1,
1041 })
1042 .collect())
1043 }
1044
1045 async fn get_addresses_datastore_keys(
1046 &self,
1047 arg: Vec<GetAddressDatastoreKeysRequest>,
1048 ) -> RpcResult<Vec<GetAddressDatastoreKeysResponse>> {
1049 if let Some(conf_max) = self.0.api_settings.max_addresses_datastore_keys_query {
1050 if arg.len() > conf_max as usize {
1051 return Err(ApiError::BadRequest(format!("too many arguments received. Only a maximum of {} arguments are accepted per request", conf_max)).into());
1052 }
1053 }
1054
1055 let requests: Vec<ExecutionQueryRequestItem> = arg
1056 .into_iter()
1057 .map(|request| {
1058 get_address_datastore_keys_to_state_query_item(
1059 request,
1060 self.0.api_settings.max_datastore_keys_queries,
1061 self.0.api_settings.max_datastore_key_length,
1062 )
1063 })
1064 .collect::<Result<_, _>>()?;
1065
1066 let mut result: Vec<GetAddressDatastoreKeysResponse> = Vec::with_capacity(requests.len());
1067
1068 let response = self.exec_query(requests);
1069
1070 for response_item in response.responses {
1071 match response_item {
1072 Ok(item) => match item {
1073 ExecutionQueryResponseItem::AddressDatastoreKeys(keys, address, is_final) => {
1074 result.push(GetAddressDatastoreKeysResponse {
1075 address,
1076 is_final,
1077 keys: keys.into_iter().collect(),
1078 });
1079 }
1080 _ => {
1081 return Err(
1082 ApiError::ExecutionError("unexpected response".to_string()).into()
1083 );
1084 }
1085 },
1086 Err(e) => {
1087 return Err(ApiError::ExecutionError(e.to_string()).into());
1088 }
1089 }
1090 }
1091
1092 Ok(result)
1093 }
1094
1095 async fn get_addresses(&self, addresses: Vec<Address>) -> RpcResult<Vec<AddressInfo>> {
1097 let created_blocks: Vec<PreHashSet<BlockId>> = {
1099 let lck = self.0.storage.read_blocks();
1100 addresses
1101 .iter()
1102 .map(|address| {
1103 lck.get_blocks_created_by(address)
1104 .cloned()
1105 .unwrap_or_default()
1106 })
1107 .collect()
1108 };
1109
1110 let created_operations: Vec<PreHashSet<OperationId>> = {
1112 let lck = self.0.storage.read_operations();
1113 addresses
1114 .iter()
1115 .map(|address| {
1116 lck.get_operations_created_by(address)
1117 .cloned()
1118 .unwrap_or_default()
1119 })
1120 .collect()
1121 };
1122
1123 let created_endorsements: Vec<PreHashSet<EndorsementId>> = {
1125 let lck = self.0.storage.read_endorsements();
1126 addresses
1127 .iter()
1128 .map(|address| {
1129 lck.get_endorsements_created_by(address)
1130 .cloned()
1131 .unwrap_or_default()
1132 })
1133 .collect()
1134 };
1135
1136 let bound_ts = MassaTime::now().saturating_add(self.0.api_settings.deferred_credits_delta);
1138
1139 let deferred_credit_max_slot = timeslots::get_closest_slot_to_timestamp(
1140 self.0.api_settings.thread_count,
1141 self.0.api_settings.t0,
1142 self.0.api_settings.genesis_timestamp,
1143 bound_ts,
1144 );
1145
1146 let execution_infos = self.0.execution_controller.get_addresses_infos(
1148 &addresses,
1149 std::ops::Bound::Included(deferred_credit_max_slot),
1150 self.0.api_settings.max_datastore_keys_queries,
1151 );
1152
1153 let selection_draws = {
1155 let cur_slot = timeslots::get_current_latest_block_slot(
1156 self.0.api_settings.thread_count,
1157 self.0.api_settings.t0,
1158 self.0.api_settings.genesis_timestamp,
1159 )
1160 .expect("could not get latest current slot")
1161 .unwrap_or_else(|| Slot::new(0, 0));
1162 let slot_end = Slot::new(
1163 cur_slot
1164 .period
1165 .saturating_add(self.0.api_settings.draw_lookahead_period_count),
1166 cur_slot.thread,
1167 );
1168 let selections = self
1169 .0
1170 .selector_controller
1171 .get_available_selections_in_range(
1172 cur_slot..=slot_end,
1173 Some(&addresses.iter().copied().collect()),
1174 )
1175 .unwrap_or_default();
1176
1177 addresses
1178 .iter()
1179 .map(|addr| {
1180 let mut producer_slots = Vec::new();
1181 let mut endorser_slots = Vec::new();
1182 for (selection_slot, selection) in &selections {
1183 if selection.producer == *addr {
1184 producer_slots.push(*selection_slot);
1185 }
1186 for (index, endorser) in selection.endorsements.iter().enumerate() {
1187 if endorser == addr {
1188 endorser_slots.push(IndexedSlot {
1189 slot: *selection_slot,
1190 index,
1191 });
1192 }
1193 }
1194 }
1195 (producer_slots, endorser_slots)
1196 })
1197 .collect::<Vec<_>>()
1198 };
1199
1200 let mut res = Vec::with_capacity(addresses.len());
1202 let iterator = izip!(
1203 addresses.into_iter(),
1204 created_blocks.into_iter(),
1205 created_operations.into_iter(),
1206 created_endorsements.into_iter(),
1207 execution_infos.into_iter(),
1208 selection_draws.into_iter(),
1209 );
1210 for (
1211 address,
1212 created_blocks,
1213 created_operations,
1214 created_endorsements,
1215 execution_infos,
1216 (next_block_draws, next_endorsement_draws),
1217 ) in iterator
1218 {
1219 res.push(AddressInfo {
1220 address,
1222 thread: address.get_thread(self.0.api_settings.thread_count),
1223
1224 final_balance: execution_infos.final_balance,
1226 final_roll_count: execution_infos.final_roll_count,
1227 final_datastore_keys: execution_infos
1228 .final_datastore_keys
1229 .into_iter()
1230 .collect::<Vec<_>>(),
1231
1232 candidate_balance: execution_infos.candidate_balance,
1234 candidate_roll_count: execution_infos.candidate_roll_count,
1235 candidate_datastore_keys: execution_infos
1236 .candidate_datastore_keys
1237 .into_iter()
1238 .collect::<Vec<_>>(),
1239
1240 deferred_credits: execution_infos
1242 .future_deferred_credits
1243 .into_iter()
1244 .map(|(slot, amount)| SlotAmount { slot, amount })
1245 .collect::<Vec<_>>(),
1246
1247 next_block_draws,
1249 next_endorsement_draws,
1250
1251 created_blocks: created_blocks.into_iter().collect::<Vec<_>>(),
1253 created_endorsements: created_endorsements.into_iter().collect::<Vec<_>>(),
1254 created_operations: created_operations.into_iter().collect::<Vec<_>>(),
1255
1256 cycle_infos: execution_infos.cycle_infos,
1258 });
1259 }
1260
1261 Ok(res)
1262 }
1263
1264 async fn get_addresses_bytecode(&self, args: Vec<AddressFilter>) -> RpcResult<Vec<Vec<u8>>> {
1266 let queries = args
1267 .into_iter()
1268 .map(|arg| {
1269 if arg.is_final {
1270 ExecutionQueryRequestItem::AddressBytecodeFinal(arg.address)
1271 } else {
1272 ExecutionQueryRequestItem::AddressBytecodeCandidate(arg.address)
1273 }
1274 })
1275 .collect::<Vec<_>>();
1276
1277 if queries.is_empty() {
1278 return Err(ApiError::BadRequest("no arguments specified".to_string()).into());
1279 }
1280
1281 if queries.len() as u64 > self.0.api_settings.max_arguments {
1282 return Err(ApiError::BadRequest(format!("too many arguments received. Only a maximum of {} arguments are accepted per request", self.0.api_settings.max_arguments)).into());
1283 }
1284
1285 let responses = self.exec_query(queries).responses;
1286
1287 let res: Result<Vec<Vec<u8>>, ApiError> = responses
1288 .into_iter()
1289 .map(|value| match value {
1290 Ok(item) => match item {
1291 ExecutionQueryResponseItem::Bytecode(bytecode) => Ok(bytecode.0),
1292 _ => Err(ApiError::InternalServerError(
1293 "unexpected response type".to_string(),
1294 )),
1295 },
1296 Err(err) => Err(ApiError::InternalServerError(err.to_string())),
1297 })
1298 .collect();
1299
1300 Ok(res?)
1301 }
1302
1303 async fn get_deferred_call_quote(
1304 &self,
1305 req: Vec<DeferredCallsQuoteRequest>,
1306 ) -> RpcResult<Vec<DeferredCallsQuoteResponse>> {
1307 if req.len() as u64 > self.0.api_settings.max_arguments {
1308 return Err(ApiError::BadRequest("too many arguments".into()).into());
1309 }
1310
1311 let queries: Vec<ExecutionQueryRequestItem> = req
1312 .into_iter()
1313 .map(|call| ExecutionQueryRequestItem::DeferredCallQuote {
1314 target_slot: call.target_slot,
1315 max_gas_request: call.max_gas_request,
1316 params_size: call.params_size,
1317 })
1318 .collect();
1319
1320 let result = self
1321 .exec_query(queries)
1322 .responses
1323 .into_iter()
1324 .map(|response| match response {
1325 Ok(ExecutionQueryResponseItem::DeferredCallQuote(
1326 target_slot,
1327 max_gas_request,
1328 available,
1329 price,
1330 )) => Ok(DeferredCallsQuoteResponse {
1331 target_slot,
1332 max_gas_request,
1333 available,
1334 price,
1335 }),
1336 Ok(_) => Err(ApiError::InternalServerError(
1337 "unexpected response type".to_string(),
1338 )),
1339 Err(err) => Err(ApiError::InternalServerError(err.to_string())),
1340 })
1341 .collect::<Result<Vec<DeferredCallsQuoteResponse>, ApiError>>()?;
1342
1343 Ok(result)
1344 }
1345
1346 async fn get_deferred_call_info(
1347 &self,
1348 arg: Vec<String>,
1349 ) -> RpcResult<Vec<DeferredCallResponse>> {
1350 if arg.len() as u64 > self.0.api_settings.max_arguments {
1351 return Err(ApiError::BadRequest("too many arguments".into()).into());
1352 }
1353
1354 let requests: Vec<ExecutionQueryRequestItem> = arg
1355 .into_iter()
1356 .map(|id_str| {
1357 DeferredCallId::from_str(&id_str)
1358 .map_err(|e| ApiError::BadRequest(e.to_string()))
1359 .map(ExecutionQueryRequestItem::DeferredCallInfo)
1360 })
1361 .collect::<Result<_, _>>()?;
1362
1363 let result: Vec<DeferredCallResponse> = self
1364 .exec_query(requests)
1365 .responses
1366 .into_iter()
1367 .map(|exec| match exec {
1368 Ok(ExecutionQueryResponseItem::DeferredCallInfo(id, call)) => {
1369 Ok(DeferredCallResponse {
1370 call_id: id.to_string(),
1371 call,
1372 })
1373 }
1374 Ok(_) => Err(ApiError::InternalServerError(
1375 "unexpected response type".to_string(),
1376 )),
1377 Err(err) => Err(ApiError::InternalServerError(err.to_string())),
1378 })
1379 .collect::<Result<_, _>>()?;
1380
1381 Ok(result)
1382 }
1383
1384 async fn get_deferred_call_ids_by_slot(
1385 &self,
1386 slots: Vec<Slot>,
1387 ) -> RpcResult<Vec<DeferredCallsSlotResponse>> {
1388 if slots.len() as u64 > self.0.api_settings.max_arguments {
1389 return Err(ApiError::BadRequest("too many arguments".into()).into());
1390 }
1391
1392 let requests: Vec<ExecutionQueryRequestItem> = slots
1393 .into_iter()
1394 .map(ExecutionQueryRequestItem::DeferredCallsBySlot)
1395 .collect();
1396
1397 let mut slot_calls = Vec::new();
1398
1399 for exec in self.exec_query(requests).responses.into_iter() {
1400 match exec {
1401 Ok(ExecutionQueryResponseItem::DeferredCallsBySlot(slot, result)) => {
1402 let call_ids = result.into_iter().map(|id| id.to_string()).collect();
1403
1404 slot_calls.push(DeferredCallsSlotResponse { slot, call_ids });
1405 }
1406 Ok(_) => {
1407 return Err(ApiError::InternalServerError(
1408 "unexpected response type".to_string(),
1409 )
1410 .into())
1411 }
1412 Err(err) => return Err(ApiError::InternalServerError(err.to_string()).into()),
1413 }
1414 }
1415
1416 Ok(slot_calls)
1417 }
1418
1419 async fn send_operations(&self, ops: Vec<OperationInput>) -> RpcResult<Vec<OperationId>> {
1421 let mut cmd_sender = self.0.pool_command_sender.clone();
1422 let protocol_sender = self.0.protocol_controller.clone();
1423 let api_cfg = &self.0.api_settings;
1424 let mut to_send = self.0.storage.clone_without_refs();
1425
1426 if ops.len() as u64 > api_cfg.max_arguments {
1427 return Err(ApiError::BadRequest("too many arguments".into()).into());
1428 }
1429 let now = MassaTime::now();
1430 let last_slot = get_latest_block_slot_at_timestamp(
1431 api_cfg.thread_count,
1432 api_cfg.t0,
1433 api_cfg.genesis_timestamp,
1434 now,
1435 )
1436 .map_err(ApiError::ModelsError)?;
1437
1438 let verified_ops = ops
1439 .into_iter()
1440 .map(|op_input| check_input_operation(op_input, api_cfg, last_slot))
1441 .map(|op| match op {
1442 Ok(operation) => {
1443 if operation
1444 .content
1445 .fee
1446 .checked_sub(api_cfg.minimal_fees)
1447 .is_none()
1448 {
1449 return Err(ApiError::BadRequest(format!(
1450 "fee is too low provided: {} , minimal_fees required: {}",
1451 operation.content.fee, self.0.api_settings.minimal_fees
1452 ))
1453 .into());
1454 }
1455
1456 let _verify_signature = match operation.verify_signature(None) {
1457 Ok(()) => (),
1458 Err(e) => return Err(ApiError::ModelsError(e).into()),
1459 };
1460 Ok(operation)
1461 }
1462 Err(e) => Err(e),
1463 })
1464 .collect::<RpcResult<Vec<SecureShareOperation>>>()?;
1465
1466 to_send.store_operations(verified_ops.clone());
1467 let ids: Vec<OperationId> = verified_ops.iter().map(|op| op.id).collect();
1468
1469 let to_propagate = to_send.clone();
1473 tokio::task::spawn_blocking(move || protocol_sender.propagate_operations(to_propagate))
1474 .await
1475 .map_err(|err| ApiError::InternalServerError(err.to_string()))?
1476 .map_err(|err| {
1477 ApiError::InternalServerError(format!("Failed to propagate operations: {}", err))
1478 })?;
1479
1480 cmd_sender.add_operations(to_send).map_err(|err| {
1481 ApiError::InternalServerError(format!("Failed to add operations to pool: {}", err))
1482 })?;
1483
1484 Ok(ids)
1485 }
1486
1487 async fn get_filtered_sc_output_event(
1494 &self,
1495 filter: EventFilter,
1496 ) -> RpcResult<Vec<SCOutputEvent>> {
1497 let events = self
1498 .0
1499 .execution_controller
1500 .get_filtered_sc_output_event(filter);
1501
1502 Ok(events)
1504 }
1505
1506 async fn node_peers_whitelist(&self) -> RpcResult<Vec<IpAddr>> {
1507 crate::wrong_api::<Vec<IpAddr>>()
1508 }
1509
1510 async fn node_add_to_peers_whitelist(&self, _: Vec<IpAddr>) -> RpcResult<()> {
1511 crate::wrong_api::<()>()
1512 }
1513
1514 async fn node_remove_from_peers_whitelist(&self, _: Vec<IpAddr>) -> RpcResult<()> {
1515 crate::wrong_api::<()>()
1516 }
1517
1518 async fn node_bootstrap_whitelist(&self) -> RpcResult<Vec<IpAddr>> {
1519 crate::wrong_api::<Vec<IpAddr>>()
1520 }
1521
1522 async fn node_bootstrap_whitelist_allow_all(&self) -> RpcResult<()> {
1523 crate::wrong_api::<()>()
1524 }
1525
1526 async fn node_add_to_bootstrap_whitelist(&self, _: Vec<IpAddr>) -> RpcResult<()> {
1527 crate::wrong_api::<()>()
1528 }
1529
1530 async fn node_remove_from_bootstrap_whitelist(&self, _: Vec<IpAddr>) -> RpcResult<()> {
1531 crate::wrong_api::<()>()
1532 }
1533
1534 async fn node_bootstrap_blacklist(&self) -> RpcResult<Vec<IpAddr>> {
1535 crate::wrong_api::<Vec<IpAddr>>()
1536 }
1537
1538 async fn node_add_to_bootstrap_blacklist(&self, _: Vec<IpAddr>) -> RpcResult<()> {
1539 crate::wrong_api::<()>()
1540 }
1541
1542 async fn node_remove_from_bootstrap_blacklist(&self, _: Vec<IpAddr>) -> RpcResult<()> {
1543 crate::wrong_api::<()>()
1544 }
1545
1546 async fn get_openrpc_spec(&self) -> RpcResult<Value> {
1548 let openrpc_spec_path = self.0.api_settings.openrpc_spec_path.clone();
1549 let openrpc: RpcResult<Value> = std::fs::read_to_string(openrpc_spec_path)
1550 .map_err(|e| {
1551 ApiError::InternalServerError(format!(
1552 "failed to read OpenRPC specification: {}",
1553 e
1554 ))
1555 .into()
1556 })
1557 .and_then(|openrpc_str| {
1558 serde_json::from_str(&openrpc_str).map_err(|e| {
1559 ApiError::InternalServerError(format!(
1560 "failed to parse OpenRPC specification: {}",
1561 e
1562 ))
1563 .into()
1564 })
1565 });
1566
1567 openrpc
1568 }
1569}
1570
1571fn check_input_operation(
1588 op_input: OperationInput,
1589 api_cfg: &APIConfig,
1590 last_slot: Option<Slot>,
1591) -> RpcResult<SecureShareOperation> {
1592 let operation_deserializer = SecureShareDeserializer::new(
1593 OperationDeserializer::new(
1594 api_cfg.max_bytecode_size,
1595 api_cfg.max_function_name_length,
1596 api_cfg.max_parameter_size,
1597 api_cfg.max_op_datastore_entry_count,
1598 api_cfg.max_op_datastore_key_length,
1599 api_cfg.max_op_datastore_value_length,
1600 ),
1601 api_cfg.chain_id,
1602 );
1603
1604 let mut op_serialized = Vec::new();
1605 op_serialized.extend(op_input.signature.to_bytes());
1606 op_serialized.extend(op_input.creator_public_key.to_bytes());
1607 op_serialized.extend(op_input.serialized_content);
1608 let (rest, op): (&[u8], SecureShareOperation) = operation_deserializer
1609 .deserialize::<DeserializeError>(&op_serialized)
1610 .map_err(|err| ApiError::ModelsError(ModelsError::DeserializeError(err.to_string())))?;
1611 let op_size = op.serialized_size();
1614 if op_size > api_cfg.max_serialized_operation_size {
1615 return Err(ApiError::BadRequest(format!(
1616 "serialized operation size {} exceeds the maximum authorized size of {} bytes. Your operation will never be included in a block.",
1617 op_size, api_cfg.max_serialized_operation_size
1618 ))
1619 .into());
1620 }
1621 if let Err(err_msg) = op.check_gas_usage(
1622 api_cfg.max_gas_per_block,
1623 api_cfg.base_operation_gas_cost,
1624 api_cfg.sp_compilation_cost,
1625 ) {
1626 return Err(ApiError::InconsistencyError(err_msg).into());
1627 }
1628 if let Some(slot) = last_slot {
1629 if op.content.expire_period < slot.period {
1630 return Err(
1631 ApiError::InconsistencyError(
1632 "Operation expire_period is lower than the current period of this node. Your operation will never be included in a block.".into()
1633 ).into()
1634 );
1635 }
1636 }
1637 if rest.is_empty() {
1638 Ok(op)
1639 } else {
1640 Err(ApiError::ModelsError(ModelsError::DeserializeError(
1641 "There is data left after operation deserialization".to_owned(),
1642 ))
1643 .into())
1644 }
1645}
1646
1647fn get_address_datastore_keys_to_state_query_item(
1649 value: GetAddressDatastoreKeysRequest,
1650 max_datastore_query_config: Option<u32>,
1651 max_datastore_key_length: u8,
1652) -> RpcResult<ExecutionQueryRequestItem> {
1653 let start_key = match (value.start_key, value.inclusive_start_key.unwrap_or(true)) {
1654 (None, _) => std::ops::Bound::Unbounded,
1655 (Some(k), true) => std::ops::Bound::Included(k),
1656 (Some(k), false) => std::ops::Bound::Excluded(k),
1657 };
1658 let end_key = match (value.end_key, value.inclusive_end_key.unwrap_or(true)) {
1659 (None, _) => std::ops::Bound::Unbounded,
1660 (Some(k), true) => std::ops::Bound::Included(k),
1661 (Some(k), false) => std::ops::Bound::Excluded(k),
1662 };
1663
1664 let (prefix, start_key, end_key, count) = cleanup_datastore_key_range_query(
1665 &value.prefix,
1666 start_key,
1667 end_key,
1668 value.count,
1669 max_datastore_key_length,
1670 max_datastore_query_config,
1671 )
1672 .map_err(|e| {
1673 ApiError::BadRequest(format!(
1674 "error querying datastore keys for address {}: {}",
1675 value.address, e
1676 ))
1677 })?;
1678
1679 if value.is_final {
1680 Ok(ExecutionQueryRequestItem::AddressDatastoreKeysFinal {
1681 address: value.address,
1682 prefix,
1683 start_key,
1684 end_key,
1685 count,
1686 })
1687 } else {
1688 Ok(ExecutionQueryRequestItem::AddressDatastoreKeysCandidate {
1689 address: value.address,
1690 prefix,
1691 start_key,
1692 end_key,
1693 count,
1694 })
1695 }
1696}