0

When writing tests for client module I'm having troubles instantiating gadget for the client with the error:

the trait module_primitives::ModuleApi<sp_runtime::generic::Block<sp_runtime::generic::Header<u64, BlakeTwo256>, sc_network_test::Extrinsic>> is not implemented for RuntimeApiImpl<sp_runtime::generic::Block<sp_runtime::generic::Header<u64, BlakeTwo256>, sc_network_test::Extrinsic>, substrate_test_runtime_client::client::Client<substrate_test_runtime_client::sc_client_db::Backend<sp_runtime::generic::Block<sp_runtime::generic::Header<u64, BlakeTwo256>, sc_network_test::Extrinsic>>, LocalCallExecutor<sp_runtime::generic::Block<sp_runtime::generic::Header<u64, BlakeTwo256>, sc_network_test::Extrinsic>, substrate_test_runtime_client::sc_client_db::Backend<sp_runtime::generic::Block<sp_runtime::generic::Header<u64, BlakeTwo256>, sc_network_test::Extrinsic>>, NativeElseWasmExecutor<LocalExecutorDispatch>>, sp_runtime::generic::Block<sp_runtime::generic::Header<u64, BlakeTwo256>, sc_network_test::Extrinsic>, substrate_test_runtime_client::substrate_test_runtime::RuntimeApi>>

Implementation:

pub(crate) type ModuleTestParams = ModuleParams<PeersFullClient, Backend>;
pub(crate) type PeerData = Option<ModuleTestParams>;

pub(crate) type ModulePeer = Peer<PeerData, PeersClient>;

pub(crate) struct ModuleTestNet {
    peers: Vec<ModulePeer>,
}

impl ModuleTestNet {
    pub(crate) fn new(n_authority: usize, n_full: usize) -> Self {
        let mut net = ModuleTestNet { peers: Vec::with_capacity(n_authority + n_full) };
        for _ in 0..n_authority {
            net.add_authority_peer();
        }
        for _ in 0..n_full {
            net.add_full_peer();
        }
        net
    }

    pub(crate) fn add_authority_peer(&mut self) {
        self.add_full_peer_with_config(FullPeerConfig {
            notifications_protocols: vec!["module/1".into()],
            is_authority: true,
            ..Default::default()
        })
    }

    pub(crate) fn add_full_peer(&mut self) {
        todo!()
    }
    pub(crate) fn generate_blocks(
        &mut self,
        count: usize,
        session_length: u64,
        validator_set: &ValidatorSet<AuthorityId>,
    ) {
        self.peer(0).generate_blocks(count, BlockOrigin::File, |builder| {
            let mut block = builder.build().unwrap().block;

            if *block.header.number() % session_length == 0 {
                add_auth_change_digest(&mut block.header, validator_set.clone());
            }

            block
        });
    }
}

TestNetFactory is implemented.

Then trait:

pub(crate) struct RuntimeApi {
    inner: TestApi,
}

impl ProvideRuntimeApi<Block> for TestApi {
    type Api = RuntimeApi;
    fn runtime_api<'a>(&'a self) -> ApiRef<'a, Self::Api> {
        RuntimeApi { inner: self.clone() }.into()
    }
}

sp_api::mock_impl_runtime_apis! {
    impl ModuleApi<Block> for RuntimeApi {}
}

And instantiation (where error comes from):

fn initialize_module(
    net: &mut ModuleTestNet,
    peers: Vec<(usize, &ModuleKeyring, ModuleTestParams)>,
) -> impl Future<Output = ()> {
    let voters = FuturesUnordered::new();

    for (peer_id, key, module_params) in peers.into_iter() {
        let gadget = start_module_gadget::<_, _, _>(module_params);

        fn assert_send<T: Send>(_: &T) {}
        assert_send(&gadget);
        voters.push(gadget);
    }

    voters.for_each(|_| async move {})
}

Declaration of gadget starting function:

pub async fn start_module_gadget<B, BE, C>(module_params: ModuleParams<C, BE>)
where
    B: Block,
    BE: Backend<B>,
    C: Client<B, BE>,
    C::Api: ModuleApi<B>,
{
    let ModuleParams { client, backend, key_store, rpc_send } = module_params;

    let worker_params = worker::WorkerParams { client, backend, key_store, rpc_send };

    let mut worker = worker::ModuleWorker::<_, _, _>::new(worker_params);

    worker.run().await
}

1 Answer 1

2

I think you are missing a bound C: ProvideRuntimeApi<B> on your start_module_gadget function.

2
  • added but getting same error... Apr 26 at 15:25
  • 1
    was able to fix this by extending ModuleWorker and ModuleParams with R: ProvideRuntimeApi<B> and moving R:Api there. weird stuff but marking as correct answer. Apr 27 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.