|
|
@@ -3,9 +3,11 @@ use core::array::ArrayTrait;
|
|
|
use core::keccak::cairo_keccak;
|
|
|
use core::integer::u128_byte_reverse;
|
|
|
use core::fmt::{Debug, Formatter};
|
|
|
+use pyth::util::{UNEXPECTED_OVERFLOW, UNEXPECTED_ZERO, one_shift_left_bytes_u128};
|
|
|
|
|
|
-pub const EOF: felt252 = 'unexpected end of input';
|
|
|
-pub const UNEXPECTED_OVERFLOW: felt252 = 'unexpected overflow';
|
|
|
+pub mod error_codes {
|
|
|
+ pub const EOF: felt252 = 'unexpected end of input';
|
|
|
+}
|
|
|
|
|
|
/// A byte array with storage format similar to `core::ByteArray`, but
|
|
|
/// suitable for reading data from it.
|
|
|
@@ -70,8 +72,7 @@ pub impl ByteArrayImpl of ByteArrayTrait {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/// Allows to read data from a byte array.
|
|
|
-/// Uses big endian unless specified otherwise.
|
|
|
+/// Allows to read data from a byte array as big endian integers.
|
|
|
/// All methods return `EOF` error if attempted to
|
|
|
/// read more bytes than is available.
|
|
|
#[derive(Drop, Clone)]
|
|
|
@@ -94,7 +95,8 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
}
|
|
|
|
|
|
/// Reads the specified number of bytes (up to 16) as a big endian unsigned integer.
|
|
|
- fn read(ref self: Reader, num_bytes: u8) -> Result<u128, felt252> {
|
|
|
+ fn read_num_bytes(ref self: Reader, num_bytes: u8) -> Result<u128, felt252> {
|
|
|
+ assert!(num_bytes <= 16, "Reader::read_num_bytes: num_bytes is too large");
|
|
|
if num_bytes <= self.num_current_bytes {
|
|
|
let x = self.read_from_current(num_bytes);
|
|
|
return Result::Ok(x);
|
|
|
@@ -102,7 +104,7 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
let num_low_bytes = num_bytes - self.num_current_bytes;
|
|
|
let high = self.current;
|
|
|
self.fetch_next()?;
|
|
|
- let low = self.read(num_low_bytes)?;
|
|
|
+ let low = self.read_num_bytes(num_low_bytes)?;
|
|
|
let value = if num_low_bytes == 16 {
|
|
|
low
|
|
|
} else {
|
|
|
@@ -112,28 +114,34 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
}
|
|
|
|
|
|
fn read_u256(ref self: Reader) -> Result<u256, felt252> {
|
|
|
- let high = self.read(16)?;
|
|
|
- let low = self.read(16)?;
|
|
|
+ let high = self.read_num_bytes(16)?;
|
|
|
+ let low = self.read_num_bytes(16)?;
|
|
|
+ let value = u256 { high, low };
|
|
|
+ Result::Ok(value)
|
|
|
+ }
|
|
|
+ fn read_u160(ref self: Reader) -> Result<u256, felt252> {
|
|
|
+ let high = self.read_num_bytes(4)?;
|
|
|
+ let low = self.read_num_bytes(16)?;
|
|
|
let value = u256 { high, low };
|
|
|
Result::Ok(value)
|
|
|
}
|
|
|
fn read_u128(ref self: Reader) -> Result<u128, felt252> {
|
|
|
- self.read(16)
|
|
|
+ self.read_num_bytes(16)
|
|
|
}
|
|
|
fn read_u64(ref self: Reader) -> Result<u64, felt252> {
|
|
|
- let value = self.read(8)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
+ let value = self.read_num_bytes(8)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
Result::Ok(value)
|
|
|
}
|
|
|
fn read_u32(ref self: Reader) -> Result<u32, felt252> {
|
|
|
- let value = self.read(4)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
+ let value = self.read_num_bytes(4)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
Result::Ok(value)
|
|
|
}
|
|
|
fn read_u16(ref self: Reader) -> Result<u16, felt252> {
|
|
|
- let value = self.read(2)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
+ let value = self.read_num_bytes(2)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
Result::Ok(value)
|
|
|
}
|
|
|
fn read_u8(ref self: Reader) -> Result<u8, felt252> {
|
|
|
- let value = self.read(1)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
+ let value = self.read_num_bytes(1)?.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
Result::Ok(value)
|
|
|
}
|
|
|
|
|
|
@@ -142,7 +150,7 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
let mut result = Result::Ok(());
|
|
|
while num_bytes > 0 {
|
|
|
if num_bytes > 16 {
|
|
|
- match self.read(16) {
|
|
|
+ match self.read_num_bytes(16) {
|
|
|
Result::Ok(_) => {},
|
|
|
Result::Err(err) => {
|
|
|
result = Result::Err(err);
|
|
|
@@ -151,7 +159,7 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
}
|
|
|
num_bytes -= 16;
|
|
|
} else {
|
|
|
- match self.read(num_bytes) {
|
|
|
+ match self.read_num_bytes(num_bytes) {
|
|
|
Result::Ok(_) => {},
|
|
|
Result::Err(err) => {
|
|
|
result = Result::Err(err);
|
|
|
@@ -165,7 +173,7 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
}
|
|
|
|
|
|
/// Reads the specified number of bytes as a new byte array.
|
|
|
- fn read_bytes(ref self: Reader, num_bytes: usize) -> Result<ByteArray, felt252> {
|
|
|
+ fn read_byte_array(ref self: Reader, num_bytes: usize) -> Result<ByteArray, felt252> {
|
|
|
let mut array: Array<bytes31> = array![];
|
|
|
let mut num_last_bytes = Option::None;
|
|
|
let mut num_remaining_bytes = num_bytes;
|
|
|
@@ -204,40 +212,6 @@ pub impl ReaderImpl of ReaderTrait {
|
|
|
};
|
|
|
self.num_current_bytes.into() + num_next_bytes + self.array.len()
|
|
|
}
|
|
|
-
|
|
|
- /// Reads the specified number of bytes (up to 16) as a little endian unsigned integer.
|
|
|
- fn read_le(ref self: Reader, num_bytes: u8) -> Result<u128, felt252> {
|
|
|
- if num_bytes == 0 {
|
|
|
- return Result::Ok(0);
|
|
|
- }
|
|
|
- let value = u128_byte_reverse(self.read(num_bytes)?)
|
|
|
- / one_shift_left_bytes_u128(16 - num_bytes);
|
|
|
- Result::Ok(value)
|
|
|
- }
|
|
|
-
|
|
|
- /// Reads and hashes all the remaining data.
|
|
|
- fn keccak256(ref self: Reader) -> Result<u256, felt252> {
|
|
|
- let mut data: Array<u64> = array![];
|
|
|
-
|
|
|
- let mut result = Result::Ok(());
|
|
|
- while self.len() >= 8 {
|
|
|
- match self.read_le(8) {
|
|
|
- Result::Ok(value) => { data.append(value.try_into().expect(UNEXPECTED_OVERFLOW)); },
|
|
|
- Result::Err(err) => {
|
|
|
- result = Result::Err(err);
|
|
|
- break;
|
|
|
- },
|
|
|
- }
|
|
|
- };
|
|
|
- result?;
|
|
|
-
|
|
|
- let last_len = self.len();
|
|
|
- // last_len < 8
|
|
|
- let last = self.read_le(last_len.try_into().expect(UNEXPECTED_OVERFLOW))?;
|
|
|
- let last = last.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
- let hash = cairo_keccak(ref data, last, last_len);
|
|
|
- Result::Ok(hash)
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
#[generate_trait]
|
|
|
@@ -246,9 +220,10 @@ impl ReaderPrivateImpl of ReaderPrivateTrait {
|
|
|
/// Panics if attempted to read more than `self.num_current_bytes`.
|
|
|
fn read_from_current(ref self: Reader, num_bytes: u8) -> u128 {
|
|
|
let num_remaining_bytes = self.num_current_bytes - num_bytes;
|
|
|
- let divisor = one_shift_left_bytes_u128(num_remaining_bytes);
|
|
|
- // divisor != 0
|
|
|
- let (high, low) = DivRem::div_rem(self.current, divisor.try_into().unwrap());
|
|
|
+ let divisor = one_shift_left_bytes_u128(num_remaining_bytes)
|
|
|
+ .try_into()
|
|
|
+ .expect(UNEXPECTED_ZERO);
|
|
|
+ let (high, low) = DivRem::div_rem(self.current, divisor);
|
|
|
self.current = low;
|
|
|
self.num_current_bytes = num_remaining_bytes;
|
|
|
high
|
|
|
@@ -265,7 +240,7 @@ impl ReaderPrivateImpl of ReaderPrivateTrait {
|
|
|
self.num_current_bytes = 16;
|
|
|
},
|
|
|
Option::None => {
|
|
|
- let (value, bytes) = self.array.pop_front().ok_or(EOF)?;
|
|
|
+ let (value, bytes) = self.array.pop_front().ok_or(error_codes::EOF)?;
|
|
|
let value: u256 = value.into();
|
|
|
if bytes > 16 {
|
|
|
self.current = value.high;
|
|
|
@@ -285,49 +260,25 @@ impl ReaderPrivateImpl of ReaderPrivateTrait {
|
|
|
ref self: Reader, num_bytes: usize, ref array: Array<bytes31>
|
|
|
) -> Result<(usize, bool), felt252> {
|
|
|
if num_bytes >= 31 {
|
|
|
- let high = self.read(15)?;
|
|
|
- let low = self.read(16)?;
|
|
|
+ let high = self.read_num_bytes(15)?;
|
|
|
+ let low = self.read_num_bytes(16)?;
|
|
|
let value: felt252 = u256 { high, low }.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
array.append(value.try_into().expect(UNEXPECTED_OVERFLOW));
|
|
|
Result::Ok((31, false))
|
|
|
} else if num_bytes > 16 {
|
|
|
// num_bytes < 31
|
|
|
- let high = self.read((num_bytes - 16).try_into().expect(UNEXPECTED_OVERFLOW))?;
|
|
|
- let low = self.read(16)?;
|
|
|
+ let high = self
|
|
|
+ .read_num_bytes((num_bytes - 16).try_into().expect(UNEXPECTED_OVERFLOW))?;
|
|
|
+ let low = self.read_num_bytes(16)?;
|
|
|
let value: felt252 = u256 { high, low }.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
array.append(value.try_into().expect(UNEXPECTED_OVERFLOW));
|
|
|
Result::Ok((num_bytes, true))
|
|
|
} else {
|
|
|
// bytes < 16
|
|
|
- let low = self.read(num_bytes.try_into().expect(UNEXPECTED_OVERFLOW))?;
|
|
|
+ let low = self.read_num_bytes(num_bytes.try_into().expect(UNEXPECTED_OVERFLOW))?;
|
|
|
let value: felt252 = low.try_into().expect(UNEXPECTED_OVERFLOW);
|
|
|
array.append(value.try_into().expect(UNEXPECTED_OVERFLOW));
|
|
|
Result::Ok((num_bytes, true))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-// Returns 1 << (8 * `n_bytes`) as u128, where `n_bytes` must be < BYTES_IN_U128.
|
|
|
-//
|
|
|
-// Panics if `n_bytes >= 16`.
|
|
|
-fn one_shift_left_bytes_u128(n_bytes: u8) -> u128 {
|
|
|
- match n_bytes {
|
|
|
- 0 => 0x1,
|
|
|
- 1 => 0x100,
|
|
|
- 2 => 0x10000,
|
|
|
- 3 => 0x1000000,
|
|
|
- 4 => 0x100000000,
|
|
|
- 5 => 0x10000000000,
|
|
|
- 6 => 0x1000000000000,
|
|
|
- 7 => 0x100000000000000,
|
|
|
- 8 => 0x10000000000000000,
|
|
|
- 9 => 0x1000000000000000000,
|
|
|
- 10 => 0x100000000000000000000,
|
|
|
- 11 => 0x10000000000000000000000,
|
|
|
- 12 => 0x1000000000000000000000000,
|
|
|
- 13 => 0x100000000000000000000000000,
|
|
|
- 14 => 0x10000000000000000000000000000,
|
|
|
- 15 => 0x1000000000000000000000000000000,
|
|
|
- _ => core::panic_with_felt252('n_bytes too big'),
|
|
|
- }
|
|
|
-}
|