use bytes::BytesMut;
use crate::fixed_codec::{FixedCodec, FixedCodecError};
use crate::types::epoch::{Epoch, EpochHeader, Pill, Proof, Validator};
use crate::types::primitive::Hash;
use crate::types::Bloom;
use crate::{impl_default_fixed_codec_for, ProtocolResult};
impl_default_fixed_codec_for!(epoch, [Proof, Validator, Epoch, EpochHeader, Pill]);
impl rlp::Encodable for Proof {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(5)
.append(&self.bitmap.to_vec())
.append(&self.epoch_hash)
.append(&self.epoch_id)
.append(&self.round)
.append(&self.signature.to_vec());
}
}
impl rlp::Decodable for Proof {
fn decode(r: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
if !r.is_list() && r.size() != 5 {
return Err(rlp::DecoderError::RlpIncorrectListLen);
}
let bitmap = BytesMut::from(r.at(0)?.data()?).freeze();
let epoch_hash: Hash = rlp::decode(r.at(1)?.as_raw())?;
let epoch_id = r.at(2)?.as_val()?;
let round = r.at(3)?.as_val()?;
let signature = BytesMut::from(r.at(4)?.data()?).freeze();
Ok(Proof {
epoch_id,
round,
epoch_hash,
signature,
bitmap,
})
}
}
impl rlp::Encodable for Validator {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(3)
.append(&self.address)
.append(&self.propose_weight)
.append(&self.vote_weight);
}
}
impl rlp::Decodable for Validator {
fn decode(r: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
if !r.is_list() && r.size() != 3 {
return Err(rlp::DecoderError::RlpIncorrectListLen);
}
let address = rlp::decode(r.at(0)?.as_raw())?;
let propose_weight = r.at(1)?.as_val()?;
let vote_weight = r.at(2)?.as_val()?;
Ok(Validator {
address,
propose_weight,
vote_weight,
})
}
}
impl rlp::Encodable for EpochHeader {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(15)
.append(&self.chain_id)
.append_list(&self.confirm_root)
.append_list(&self.cycles_used)
.append(&self.epoch_id)
.append(&self.exec_epoch_id)
.append_list(&self.logs_bloom)
.append(&self.order_root)
.append(&self.pre_hash)
.append(&self.proof)
.append(&self.proposer)
.append_list(&self.receipt_root)
.append(&self.state_root)
.append(&self.timestamp)
.append(&self.validator_version)
.append_list(&self.validators);
}
}
impl rlp::Decodable for EpochHeader {
fn decode(r: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
if !r.is_list() && r.size() != 15 {
return Err(rlp::DecoderError::RlpIncorrectListLen);
}
let chain_id: Hash = rlp::decode(r.at(0)?.as_raw())?;
let confirm_root: Vec<Hash> = rlp::decode_list(r.at(1)?.as_raw());
let cycles_used: Vec<u64> = rlp::decode_list(r.at(2)?.as_raw());
let epoch_id: u64 = r.at(3)?.as_val()?;
let exec_epoch_id: u64 = r.at(4)?.as_val()?;
let logs_bloom: Vec<Bloom> = rlp::decode_list(r.at(5)?.as_raw());
let order_root = rlp::decode(r.at(6)?.as_raw())?;
let pre_hash = rlp::decode(r.at(7)?.as_raw())?;
let proof: Proof = rlp::decode(r.at(8)?.as_raw())?;
let proposer = rlp::decode(r.at(9)?.as_raw())?;
let receipt_root: Vec<Hash> = rlp::decode_list(r.at(10)?.as_raw());
let state_root = rlp::decode(r.at(11)?.as_raw())?;
let timestamp: u64 = r.at(12)?.as_val()?;
let validator_version: u64 = r.at(13)?.as_val()?;
let validators: Vec<Validator> = rlp::decode_list(r.at(14)?.as_raw());
Ok(EpochHeader {
chain_id,
epoch_id,
exec_epoch_id,
pre_hash,
timestamp,
logs_bloom,
order_root,
confirm_root,
state_root,
receipt_root,
cycles_used,
proposer,
proof,
validator_version,
validators,
})
}
}
impl rlp::Encodable for Epoch {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(2)
.append(&self.header)
.append_list(&self.ordered_tx_hashes);
}
}
impl rlp::Decodable for Epoch {
fn decode(r: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
if !r.is_list() && r.size() != 2 {
return Err(rlp::DecoderError::RlpIncorrectListLen);
}
let header: EpochHeader = rlp::decode(r.at(0)?.as_raw())?;
let ordered_tx_hashes: Vec<Hash> = rlp::decode_list(r.at(1)?.as_raw());
Ok(Epoch {
header,
ordered_tx_hashes,
})
}
}
impl rlp::Encodable for Pill {
fn rlp_append(&self, s: &mut rlp::RlpStream) {
s.begin_list(2)
.append(&self.epoch)
.append_list(&self.propose_hashes);
}
}
impl rlp::Decodable for Pill {
fn decode(r: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
if !r.is_list() && r.size() != 2 {
return Err(rlp::DecoderError::RlpIncorrectListLen);
}
let epoch: Epoch = rlp::decode(r.at(0)?.as_raw())?;
let propose_hashes: Vec<Hash> = rlp::decode_list(r.at(1)?.as_raw());
Ok(Pill {
epoch,
propose_hashes,
})
}
}