use crate::{
api::ShadowShared,
bytes,
chain::eth::{EthHeader, EthHeaderJson, EthashProof, EthashProofJson},
mmr::{helper, MergeHash, Store, H256},
};
use actix_web::{web, Responder};
use cmmr::MMR;
use reqwest::Client;
use scale::{Decode, Encode};
#[derive(Deserialize, Encode)]
pub struct ProposalReq {
pub member: u64,
pub target: u64,
pub last_leaf: u64,
}
impl ProposalReq {
async fn header(&self, client: &Client) -> EthHeaderJson {
EthHeader::get(&client, self.target)
.await
.unwrap_or_default()
.into()
}
fn ethash_proof(&self) -> Vec<EthashProofJson> {
let proof = super::ffi::proof(self.target);
<Vec<EthashProof>>::decode(&mut bytes!(proof.as_str()).as_ref())
.unwrap_or_default()
.iter()
.map(Into::<EthashProofJson>::into)
.collect()
}
pub fn mmr_root(&self, store: &Store) -> String {
if self.target < 1 {
"0x0000000000000000000000000000000000000000000000000000000000000000".into()
} else {
format!(
"0x{}",
H256::hex(
&MMR::<_, MergeHash, _>::new(
cmmr::leaf_index_to_mmr_size(self.target - 1),
store
)
.get_root()
.unwrap_or_default()
)
)
}
}
pub fn mmr_proof(&self, store: &Store) -> Vec<String> {
if self.last_leaf < 1 {
return vec![];
}
helper::gen_proof(store, self.member, self.last_leaf)
}
pub async fn gen(&self, shared: web::Data<ShadowShared>) -> ProposalHeader {
ProposalHeader {
header: self.header(&shared.client).await,
ethash_proof: self.ethash_proof(),
mmr_root: self.mmr_root(&shared.store),
mmr_proof: self.mmr_proof(&shared.store),
}
}
}
#[derive(Serialize, Encode)]
pub struct ProposalHeader {
header: EthHeaderJson,
ethash_proof: Vec<EthashProofJson>,
mmr_root: String,
mmr_proof: Vec<String>,
}
pub async fn handle(req: web::Json<ProposalReq>, share: web::Data<ShadowShared>) -> impl Responder {
web::Json(req.0.gen(share).await)
}