Skip to content

Commit

Permalink
feat: tweak SendBlocksProof message to support ckb2023
Browse files Browse the repository at this point in the history
  • Loading branch information
quake committed Oct 23, 2023
1 parent 385bc89 commit 1a7bfad
Show file tree
Hide file tree
Showing 7 changed files with 824 additions and 12 deletions.
2 changes: 1 addition & 1 deletion util/gen-types/schemas/blockchain.mol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ array Uint256 [byte; 32];

vector Bytes <byte>;
option BytesOpt (Bytes);

vector BytesOptVec <BytesOpt>;
vector BytesVec <Bytes>;
vector Byte32Vec <Byte32>;

Expand Down
19 changes: 19 additions & 0 deletions util/gen-types/schemas/extensions.mol
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,25 @@ table SendBlocksProof {
missing_block_hashes: Byte32Vec,
}

table SendBlocksProofV1 {
// Refer to `SendLastStateProof.last_header`.
last_header: VerifiableHeader,
// Refer to `SendLastStateProof.proof`.
proof: HeaderDigestVec,

// Block headers for the blocks which require verifying.
headers: HeaderVec,

// Block hashes for the blocks which were not found.
missing_block_hashes: Byte32Vec,

// Uncle hashes for the blocks which require verifying.
blocks_uncles_hash: Byte32Vec,

// Block extension for the blocks which require verifying.
blocks_extension: BytesOptVec,
}

table GetTransactionsProof {
// Refer to `GetLastStateProof.last_hash`.
last_hash: Byte32,
Expand Down
8 changes: 8 additions & 0 deletions util/gen-types/src/extension/shortcut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,11 @@ impl packed::HeaderDigest {
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(),
))
}
}
340 changes: 340 additions & 0 deletions util/gen-types/src/generated/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2386,6 +2386,346 @@ impl molecule::prelude::Builder for BytesOptBuilder {
}
}
#[derive(Clone)]
pub struct BytesOptVec(molecule::bytes::Bytes);
impl ::core::fmt::LowerHex for BytesOptVec {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
use molecule::hex_string;
if f.alternate() {
write!(f, "0x")?;
}
write!(f, "{}", hex_string(self.as_slice()))
}
}
impl ::core::fmt::Debug for BytesOptVec {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{}({:#x})", Self::NAME, self)
}
}
impl ::core::fmt::Display for BytesOptVec {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{} [", Self::NAME)?;
for i in 0..self.len() {
if i == 0 {
write!(f, "{}", self.get_unchecked(i))?;
} else {
write!(f, ", {}", self.get_unchecked(i))?;
}
}
write!(f, "]")
}
}
impl ::core::default::Default for BytesOptVec {
fn default() -> Self {
let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE);
BytesOptVec::new_unchecked(v)
}
}
impl BytesOptVec {
const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0];
pub fn total_size(&self) -> usize {
molecule::unpack_number(self.as_slice()) as usize
}
pub fn item_count(&self) -> usize {
if self.total_size() == molecule::NUMBER_SIZE {
0
} else {
(molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1
}
}
pub fn len(&self) -> usize {
self.item_count()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, idx: usize) -> Option<BytesOpt> {
if idx >= self.len() {
None
} else {
Some(self.get_unchecked(idx))
}
}
pub fn get_unchecked(&self, idx: usize) -> BytesOpt {
let slice = self.as_slice();
let start_idx = molecule::NUMBER_SIZE * (1 + idx);
let start = molecule::unpack_number(&slice[start_idx..]) as usize;
if idx == self.len() - 1 {
BytesOpt::new_unchecked(self.0.slice(start..))
} else {
let end_idx = start_idx + molecule::NUMBER_SIZE;
let end = molecule::unpack_number(&slice[end_idx..]) as usize;
BytesOpt::new_unchecked(self.0.slice(start..end))
}
}
pub fn as_reader<'r>(&'r self) -> BytesOptVecReader<'r> {
BytesOptVecReader::new_unchecked(self.as_slice())
}
}
impl molecule::prelude::Entity for BytesOptVec {
type Builder = BytesOptVecBuilder;
const NAME: &'static str = "BytesOptVec";
fn new_unchecked(data: molecule::bytes::Bytes) -> Self {
BytesOptVec(data)
}
fn as_bytes(&self) -> molecule::bytes::Bytes {
self.0.clone()
}
fn as_slice(&self) -> &[u8] {
&self.0[..]
}
fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult<Self> {
BytesOptVecReader::from_slice(slice).map(|reader| reader.to_entity())
}
fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult<Self> {
BytesOptVecReader::from_compatible_slice(slice).map(|reader| reader.to_entity())
}
fn new_builder() -> Self::Builder {
::core::default::Default::default()
}
fn as_builder(self) -> Self::Builder {
Self::new_builder().extend(self.into_iter())
}
}
#[derive(Clone, Copy)]
pub struct BytesOptVecReader<'r>(&'r [u8]);
impl<'r> ::core::fmt::LowerHex for BytesOptVecReader<'r> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
use molecule::hex_string;
if f.alternate() {
write!(f, "0x")?;
}
write!(f, "{}", hex_string(self.as_slice()))
}
}
impl<'r> ::core::fmt::Debug for BytesOptVecReader<'r> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{}({:#x})", Self::NAME, self)
}
}
impl<'r> ::core::fmt::Display for BytesOptVecReader<'r> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{} [", Self::NAME)?;
for i in 0..self.len() {
if i == 0 {
write!(f, "{}", self.get_unchecked(i))?;
} else {
write!(f, ", {}", self.get_unchecked(i))?;
}
}
write!(f, "]")
}
}
impl<'r> BytesOptVecReader<'r> {
pub fn total_size(&self) -> usize {
molecule::unpack_number(self.as_slice()) as usize
}
pub fn item_count(&self) -> usize {
if self.total_size() == molecule::NUMBER_SIZE {
0
} else {
(molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1
}
}
pub fn len(&self) -> usize {
self.item_count()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&self, idx: usize) -> Option<BytesOptReader<'r>> {
if idx >= self.len() {
None
} else {
Some(self.get_unchecked(idx))
}
}
pub fn get_unchecked(&self, idx: usize) -> BytesOptReader<'r> {
let slice = self.as_slice();
let start_idx = molecule::NUMBER_SIZE * (1 + idx);
let start = molecule::unpack_number(&slice[start_idx..]) as usize;
if idx == self.len() - 1 {
BytesOptReader::new_unchecked(&self.as_slice()[start..])
} else {
let end_idx = start_idx + molecule::NUMBER_SIZE;
let end = molecule::unpack_number(&slice[end_idx..]) as usize;
BytesOptReader::new_unchecked(&self.as_slice()[start..end])
}
}
}
impl<'r> molecule::prelude::Reader<'r> for BytesOptVecReader<'r> {
type Entity = BytesOptVec;
const NAME: &'static str = "BytesOptVecReader";
fn to_entity(&self) -> Self::Entity {
Self::Entity::new_unchecked(self.as_slice().to_owned().into())
}
fn new_unchecked(slice: &'r [u8]) -> Self {
BytesOptVecReader(slice)
}
fn as_slice(&self) -> &'r [u8] {
self.0
}
fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> {
use molecule::verification_error as ve;
let slice_len = slice.len();
if slice_len < molecule::NUMBER_SIZE {
return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len);
}
let total_size = molecule::unpack_number(slice) as usize;
if slice_len != total_size {
return ve!(Self, TotalSizeNotMatch, total_size, slice_len);
}
if slice_len == molecule::NUMBER_SIZE {
return Ok(());
}
if slice_len < molecule::NUMBER_SIZE * 2 {
return ve!(
Self,
TotalSizeNotMatch,
molecule::NUMBER_SIZE * 2,
slice_len
);
}
let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize;
if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 {
return ve!(Self, OffsetsNotMatch);
}
if slice_len < offset_first {
return ve!(Self, HeaderIsBroken, offset_first, slice_len);
}
let mut offsets: Vec<usize> = slice[molecule::NUMBER_SIZE..offset_first]
.chunks_exact(molecule::NUMBER_SIZE)
.map(|x| molecule::unpack_number(x) as usize)
.collect();
offsets.push(total_size);
if offsets.windows(2).any(|i| i[0] > i[1]) {
return ve!(Self, OffsetsNotMatch);
}
for pair in offsets.windows(2) {
let start = pair[0];
let end = pair[1];
BytesOptReader::verify(&slice[start..end], compatible)?;
}
Ok(())
}
}
#[derive(Debug, Default)]
pub struct BytesOptVecBuilder(pub(crate) Vec<BytesOpt>);
impl BytesOptVecBuilder {
pub fn set(mut self, v: Vec<BytesOpt>) -> Self {
self.0 = v;
self
}
pub fn push(mut self, v: BytesOpt) -> Self {
self.0.push(v);
self
}
pub fn extend<T: ::core::iter::IntoIterator<Item = BytesOpt>>(mut self, iter: T) -> Self {
for elem in iter {
self.0.push(elem);
}
self
}
pub fn replace(&mut self, index: usize, v: BytesOpt) -> Option<BytesOpt> {
self.0
.get_mut(index)
.map(|item| ::core::mem::replace(item, v))
}
}
impl molecule::prelude::Builder for BytesOptVecBuilder {
type Entity = BytesOptVec;
const NAME: &'static str = "BytesOptVecBuilder";
fn expected_length(&self) -> usize {
molecule::NUMBER_SIZE * (self.0.len() + 1)
+ self
.0
.iter()
.map(|inner| inner.as_slice().len())
.sum::<usize>()
}
fn write<W: molecule::io::Write>(&self, writer: &mut W) -> molecule::io::Result<()> {
let item_count = self.0.len();
if item_count == 0 {
writer.write_all(&molecule::pack_number(
molecule::NUMBER_SIZE as molecule::Number,
))?;
} else {
let (total_size, offsets) = self.0.iter().fold(
(
molecule::NUMBER_SIZE * (item_count + 1),
Vec::with_capacity(item_count),
),
|(start, mut offsets), inner| {
offsets.push(start);
(start + inner.as_slice().len(), offsets)
},
);
writer.write_all(&molecule::pack_number(total_size as molecule::Number))?;
for offset in offsets.into_iter() {
writer.write_all(&molecule::pack_number(offset as molecule::Number))?;
}
for inner in self.0.iter() {
writer.write_all(inner.as_slice())?;
}
}
Ok(())
}
fn build(&self) -> Self::Entity {
let mut inner = Vec::with_capacity(self.expected_length());
self.write(&mut inner)
.unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME));
BytesOptVec::new_unchecked(inner.into())
}
}
pub struct BytesOptVecIterator(BytesOptVec, usize, usize);
impl ::core::iter::Iterator for BytesOptVecIterator {
type Item = BytesOpt;
fn next(&mut self) -> Option<Self::Item> {
if self.1 >= self.2 {
None
} else {
let ret = self.0.get_unchecked(self.1);
self.1 += 1;
Some(ret)
}
}
}
impl ::core::iter::ExactSizeIterator for BytesOptVecIterator {
fn len(&self) -> usize {
self.2 - self.1
}
}
impl ::core::iter::IntoIterator for BytesOptVec {
type Item = BytesOpt;
type IntoIter = BytesOptVecIterator;
fn into_iter(self) -> Self::IntoIter {
let len = self.len();
BytesOptVecIterator(self, 0, len)
}
}
impl<'r> BytesOptVecReader<'r> {
pub fn iter<'t>(&'t self) -> BytesOptVecReaderIterator<'t, 'r> {
BytesOptVecReaderIterator(&self, 0, self.len())
}
}
pub struct BytesOptVecReaderIterator<'t, 'r>(&'t BytesOptVecReader<'r>, usize, usize);
impl<'t: 'r, 'r> ::core::iter::Iterator for BytesOptVecReaderIterator<'t, 'r> {
type Item = BytesOptReader<'t>;
fn next(&mut self) -> Option<Self::Item> {
if self.1 >= self.2 {
None
} else {
let ret = self.0.get_unchecked(self.1);
self.1 += 1;
Some(ret)
}
}
}
impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for BytesOptVecReaderIterator<'t, 'r> {
fn len(&self) -> usize {
self.2 - self.1
}
}
#[derive(Clone)]
pub struct BytesVec(molecule::bytes::Bytes);
impl ::core::fmt::LowerHex for BytesVec {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
Expand Down
Loading

0 comments on commit 1a7bfad

Please sign in to comment.