use crate::{bytes, core, generated::packed, prelude::*, vec::Vec};
type BlockNumber = u64;
impl packed::Byte32 {
pub fn zero() -> Self {
Self::default()
}
pub fn max_value() -> Self {
[u8::MAX; 32].into()
}
pub fn is_zero(&self) -> bool {
self.as_slice().iter().all(|x| *x == 0)
}
pub fn new(v: [u8; 32]) -> Self {
v.into()
}
}
impl packed::ProposalShortId {
pub fn from_tx_hash(h: &packed::Byte32) -> Self {
let mut inner = [0u8; 10];
inner.copy_from_slice(&h.as_slice()[..10]);
inner.into()
}
pub fn zero() -> Self {
Self::default()
}
pub fn new(v: [u8; 10]) -> Self {
v.into()
}
}
impl packed::OutPoint {
pub fn new(tx_hash: packed::Byte32, index: u32) -> Self {
packed::OutPoint::new_builder()
.tx_hash(tx_hash)
.index(index)
.build()
}
pub fn null() -> Self {
packed::OutPoint::new_builder().index(u32::MAX).build()
}
pub fn is_null(&self) -> bool {
self.tx_hash().is_zero() && Into::<u32>::into(self.index().as_reader()) == u32::MAX
}
pub fn to_cell_key(&self) -> Vec<u8> {
let mut key = Vec::with_capacity(36);
let index: u32 = self.index().as_reader().into();
key.extend_from_slice(self.tx_hash().as_slice());
key.extend_from_slice(&index.to_be_bytes());
key
}
}
impl packed::CellInput {
pub fn new(previous_output: packed::OutPoint, block_number: BlockNumber) -> Self {
packed::CellInput::new_builder()
.since(block_number)
.previous_output(previous_output)
.build()
}
pub fn new_cellbase_input(block_number: BlockNumber) -> Self {
Self::new(packed::OutPoint::null(), block_number)
}
}
impl packed::Script {
pub fn into_witness(self) -> packed::Bytes {
packed::CellbaseWitness::new_builder()
.lock(self)
.build()
.as_bytes()
.into()
}
pub fn from_witness(witness: packed::Bytes) -> Option<Self> {
packed::CellbaseWitness::from_slice(&witness.raw_data())
.map(|cellbase_witness| cellbase_witness.lock())
.ok()
}
pub fn is_hash_type_type(&self) -> bool {
Into::<u8>::into(self.hash_type()) == Into::<u8>::into(core::ScriptHashType::Type)
}
}
impl packed::Transaction {
pub fn is_cellbase(&self) -> bool {
let raw_tx = self.raw();
raw_tx.inputs().len() == 1
&& self.witnesses().len() == 1
&& raw_tx
.inputs()
.get(0)
.should_be_ok()
.previous_output()
.is_null()
}
pub fn proposal_short_id(&self) -> packed::ProposalShortId {
packed::ProposalShortId::from_tx_hash(&self.calc_tx_hash())
}
}
impl packed::Block {
pub fn as_uncle(&self) -> packed::UncleBlock {
packed::UncleBlock::new_builder()
.header(self.header())
.proposals(self.proposals())
.build()
}
pub fn extra_field(&self, index: usize) -> Option<bytes::Bytes> {
let count = self.count_extra_fields();
if count > index {
let slice = self.as_slice();
let i = (1 + Self::FIELD_COUNT + index) * molecule::NUMBER_SIZE;
let start = molecule::unpack_number(&slice[i..]) as usize;
if count == index + 1 {
Some(self.as_bytes().slice(start..))
} else {
let j = i + molecule::NUMBER_SIZE;
let end = molecule::unpack_number(&slice[j..]) as usize;
Some(self.as_bytes().slice(start..end))
}
} else {
None
}
}
pub fn extension(&self) -> Option<packed::Bytes> {
self.extra_field(0)
.map(|data| packed::Bytes::from_slice(&data).unwrap())
}
}
impl packed::CompactBlock {
pub fn txs_len(&self) -> usize {
self.prefilled_transactions().len() + self.short_ids().len()
}
pub fn extra_field(&self, index: usize) -> Option<bytes::Bytes> {
let count = self.count_extra_fields();
if count > index {
let slice = self.as_slice();
let i = (1 + Self::FIELD_COUNT + index) * molecule::NUMBER_SIZE;
let start = molecule::unpack_number(&slice[i..]) as usize;
if count == index + 1 {
Some(self.as_bytes().slice(start..))
} else {
let j = i + molecule::NUMBER_SIZE;
let end = molecule::unpack_number(&slice[j..]) as usize;
Some(self.as_bytes().slice(start..end))
}
} else {
None
}
}
pub fn extension(&self) -> Option<packed::Bytes> {
self.extra_field(0)
.map(|data| packed::Bytes::from_slice(&data).unwrap())
}
}
impl packed::BlockV1 {
pub fn as_v0(&self) -> packed::Block {
packed::Block::new_unchecked(self.as_bytes())
}
}
impl<'r> packed::BlockReader<'r> {
pub fn extra_field(&self, index: usize) -> Option<&[u8]> {
let count = self.count_extra_fields();
if count > index {
let slice = self.as_slice();
let i = (1 + Self::FIELD_COUNT + index) * molecule::NUMBER_SIZE;
let start = molecule::unpack_number(&slice[i..]) as usize;
if count == index + 1 {
Some(&self.as_slice()[start..])
} else {
let j = i + molecule::NUMBER_SIZE;
let end = molecule::unpack_number(&slice[j..]) as usize;
Some(&self.as_slice()[start..end])
}
} else {
None
}
}
pub fn extension(&self) -> Option<packed::BytesReader<'_>> {
self.extra_field(0)
.map(|data| packed::BytesReader::from_slice(data).unwrap())
}
}
impl<'r> packed::BlockV1Reader<'r> {
pub fn as_v0(&self) -> packed::BlockReader<'_> {
packed::BlockReader::new_unchecked(self.as_slice())
}
}
impl packed::CompactBlockV1 {
pub fn as_v0(&self) -> packed::CompactBlock {
packed::CompactBlock::new_unchecked(self.as_bytes())
}
}
impl<'r> packed::CompactBlockV1Reader<'r> {
pub fn as_v0(&self) -> packed::CompactBlockReader<'_> {
packed::CompactBlockReader::new_unchecked(self.as_slice())
}
}
impl AsRef<[u8]> for packed::TransactionKey {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl packed::HeaderDigest {
pub fn is_default(&self) -> bool {
let default = Self::default();
self.as_slice() == default.as_slice()
}
}
impl From<packed::SendBlocksProofV1> for packed::LightClientMessageUnion {
fn from(item: packed::SendBlocksProofV1) -> Self {
packed::LightClientMessageUnion::SendBlocksProof(packed::SendBlocksProof::new_unchecked(
item.as_bytes(),
))
}
}
impl From<packed::SendTransactionsProofV1> for packed::LightClientMessageUnion {
fn from(item: packed::SendTransactionsProofV1) -> Self {
packed::LightClientMessageUnion::SendTransactionsProof(
packed::SendTransactionsProof::new_unchecked(item.as_bytes()),
)
}
}