use crate::error::RPCError;
use async_trait::async_trait;
use ckb_async_runtime::Handle;
use ckb_jsonrpc_types::Alert;
use ckb_network::{NetworkController, SupportProtocols};
use ckb_network_alert::{notifier::Notifier as AlertNotifier, verifier::Verifier as AlertVerifier};
use ckb_types::{packed, prelude::*};
use ckb_util::Mutex;
use jsonrpc_core::Result;
use jsonrpc_utils::rpc;
use std::sync::Arc;
#[rpc(openrpc)]
#[async_trait]
pub trait AlertRpc {
#[rpc(name = "send_alert")]
fn send_alert(&self, alert: Alert) -> Result<()>;
}
#[derive(Clone)]
pub(crate) struct AlertRpcImpl {
network_controller: NetworkController,
verifier: Arc<AlertVerifier>,
notifier: Arc<Mutex<AlertNotifier>>,
handle: Handle,
}
impl AlertRpcImpl {
pub fn new(
verifier: Arc<AlertVerifier>,
notifier: Arc<Mutex<AlertNotifier>>,
network_controller: NetworkController,
handle: Handle,
) -> Self {
AlertRpcImpl {
network_controller,
verifier,
notifier,
handle,
}
}
}
#[async_trait]
impl AlertRpc for AlertRpcImpl {
fn send_alert(&self, alert: Alert) -> Result<()> {
let alert: packed::Alert = alert.into();
let now_ms = ckb_systemtime::unix_time_as_millis();
let notice_until: u64 = alert.raw().notice_until().into();
if notice_until < now_ms {
return Err(RPCError::invalid_params(format!(
"Expected `params[0].notice_until` in the future (> {now_ms}), got {notice_until}",
)));
}
let result = self.verifier.verify_signatures(&alert);
match result {
Ok(()) => {
self.notifier.lock().add(&alert);
self.network_controller.broadcast_with_handle(
SupportProtocols::Alert.protocol_id(),
alert.as_bytes(),
&self.handle,
);
Ok(())
}
Err(e) => Err(RPCError::custom_with_error(
RPCError::AlertFailedToVerifySignatures,
e,
)),
}
}
}