1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
//! A collection of node-specific RPC methods.
18
//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer
19
//! used by Substrate nodes. This file extends those RPC definitions with
20
//! capabilities that are specific to this project's runtime configuration.
21

            
22
#![warn(missing_docs)]
23

            
24
use {
25
    cumulus_primitives_core::ParaId,
26
    dancebox_runtime::{opaque::Block, AccountId, Index as Nonce},
27
    manual_container_chains_exclusion_rpc::{
28
        ManualContainerChainsExclusion, ManualContainerChainsExclusionApiServer,
29
    },
30
    manual_randomness_rpc::{ManualRandomness, ManualRandomnessApiServer},
31
    manual_xcm_rpc::{ManualXcm, ManualXcmApiServer},
32
    polkadot_primitives::Hash,
33
    sc_client_api::{AuxStore, UsageProvider},
34
    sc_consensus_manual_seal::{
35
        rpc::{ManualSeal, ManualSealApiServer},
36
        EngineCommand,
37
    },
38
    sc_transaction_pool_api::TransactionPool,
39
    services_payment_rpc::{
40
        ServicesPayment, ServicesPaymentApiServer as _, ServicesPaymentRuntimeApi,
41
    },
42
    sp_api::ProvideRuntimeApi,
43
    sp_block_builder::BlockBuilder,
44
    sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata},
45
    std::sync::Arc,
46
    stream_payment_rpc::{StreamPayment, StreamPaymentApiServer as _, StreamPaymentRuntimeApi},
47
};
48

            
49
/// A type representing all RPC extensions.
50
pub type RpcExtension = jsonrpsee::RpcModule<()>;
51

            
52
/// Full client dependencies
53
pub struct FullDeps<C, P> {
54
    /// The client instance to use.
55
    pub client: Arc<C>,
56
    /// Transaction pool instance.
57
    pub pool: Arc<P>,
58
    /// Manual seal command sink
59
    pub command_sink: Option<futures::channel::mpsc::Sender<EngineCommand<Hash>>>,
60
    /// Channels for manual xcm messages (downward, hrmp)
61
    pub xcm_senders: Option<(flume::Sender<Vec<u8>>, flume::Sender<(ParaId, Vec<u8>)>)>,
62
    /// Channels for manually activating the randomness
63
    pub randomness_sender: Option<flume::Sender<(bool, Option<[u8; 32]>)>>,
64
    /// Channels for manually excluding container chains from producing blocks
65
    pub container_chain_exclusion_sender: Option<flume::Sender<Vec<ParaId>>>,
66
}
67

            
68
/// Instantiate all RPC extensions.
69
388
pub fn create_full<C, P>(
70
388
    deps: FullDeps<C, P>,
71
388
) -> Result<RpcExtension, Box<dyn std::error::Error + Send + Sync>>
72
388
where
73
388
    C: ProvideRuntimeApi<Block>
74
388
        + HeaderBackend<Block>
75
388
        + AuxStore
76
388
        + HeaderMetadata<Block, Error = BlockChainError>
77
388
        + Send
78
388
        + Sync
79
388
        + UsageProvider<Block>
80
388
        + 'static,
81
388
    C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
82
388
    C::Api: BlockBuilder<Block>,
83
388
    C::Api: StreamPaymentRuntimeApi<Block, u64, u128, u128>,
84
388
    C::Api: ServicesPaymentRuntimeApi<Block, u128, ParaId>,
85
388
    P: TransactionPool + Sync + Send + 'static,
86
388
{
87
    use substrate_frame_rpc_system::{System, SystemApiServer};
88

            
89
388
    let mut module = RpcExtension::new(());
90
388
    let FullDeps {
91
388
        client,
92
388
        pool,
93
388
        command_sink,
94
388
        xcm_senders,
95
388
        randomness_sender,
96
388
        container_chain_exclusion_sender,
97
388
    } = deps;
98
388

            
99
388
    module.merge(System::new(client.clone(), pool).into_rpc())?;
100
388
    module.merge(StreamPayment::<_, Block>::new(client.clone()).into_rpc())?;
101
388
    module.merge(ServicesPayment::<_, Block>::new(client).into_rpc())?;
102

            
103
388
    if let Some(command_sink) = command_sink {
104
348
        module.merge(
105
348
            // We provide the rpc handler with the sending end of the channel to allow the rpc
106
348
            // send EngineCommands to the background block authorship task.
107
348
            ManualSeal::new(command_sink).into_rpc(),
108
348
        )?;
109
40
    };
110

            
111
388
    if let Some((downward_message_channel, hrmp_message_channel)) = xcm_senders {
112
388
        module.merge(
113
388
            ManualXcm {
114
388
                downward_message_channel,
115
388
                hrmp_message_channel,
116
388
            }
117
388
            .into_rpc(),
118
388
        )?;
119
    }
120

            
121
388
    if let Some(randomness_message_channel) = randomness_sender {
122
388
        module.merge(
123
388
            ManualRandomness {
124
388
                randomness_message_channel,
125
388
            }
126
388
            .into_rpc(),
127
388
        )?;
128
    }
129

            
130
388
    if let Some(container_chain_exclusion_message_channel) = container_chain_exclusion_sender {
131
388
        module.merge(
132
388
            ManualContainerChainsExclusion {
133
388
                container_chain_exclusion_message_channel,
134
388
            }
135
388
            .into_rpc(),
136
388
        )?;
137
    }
138

            
139
388
    Ok(module)
140
388
}