1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use crate::{components::io::IoError, types::PeerId};
use tendermint::abci::transaction::Hash;
use contracts::contract_trait;
pub use tendermint::evidence::Evidence;
#[contract_trait]
#[allow(missing_docs)]
pub trait EvidenceReporter: Send + Sync {
fn report(&self, e: Evidence, peer: PeerId) -> Result<Hash, IoError>;
}
#[cfg(feature = "rpc-client")]
pub use self::prod::ProdEvidenceReporter;
#[cfg(feature = "rpc-client")]
mod prod {
use super::*;
use crate::utils::block_on;
use contracts::pre;
use std::{collections::HashMap, time::Duration};
use tendermint_rpc as rpc;
use tendermint_rpc::Client;
#[derive(Clone, Debug)]
pub struct ProdEvidenceReporter {
peer_map: HashMap<PeerId, tendermint::net::Address>,
timeout: Option<Duration>,
}
#[contract_trait]
impl EvidenceReporter for ProdEvidenceReporter {
#[pre(self.peer_map.contains_key(&peer))]
fn report(&self, e: Evidence, peer: PeerId) -> Result<Hash, IoError> {
let client = self.rpc_client_for(peer)?;
let res = block_on(
self.timeout,
async move { client.broadcast_evidence(e).await },
)?;
match res {
Ok(response) => Ok(response.hash),
Err(err) => Err(IoError::RpcError(err)),
}
}
}
impl ProdEvidenceReporter {
pub fn new(
peer_map: HashMap<PeerId, tendermint::net::Address>,
timeout: Option<Duration>,
) -> Self {
Self { peer_map, timeout }
}
#[pre(self.peer_map.contains_key(&peer))]
fn rpc_client_for(&self, peer: PeerId) -> Result<rpc::HttpClient, IoError> {
let peer_addr = self.peer_map.get(&peer).unwrap().to_owned();
Ok(rpc::HttpClient::new(peer_addr).map_err(IoError::from)?)
}
}
}