Skip to content

Commit

Permalink
Upstream 0.17.2 (#80)
Browse files Browse the repository at this point in the history
* Impl #168: Fix byte alignment in CellBuilder

* Impl #169: fixed  d2 descriptor of cell

* bump version

---------

Co-authored-by: Dmitrii Korchagin <[email protected]>
Co-authored-by: dbaranov34 <[email protected]>
  • Loading branch information
3 people authored Aug 13, 2024
1 parent 51e4282 commit c5d5199
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 31 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tonlib"
version = "0.17.1"
version = "0.17.2"
edition = "2021"
description = "Rust SDK for The Open Network"
license = "MIT"
Expand Down
13 changes: 6 additions & 7 deletions src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::types::{TonHash, DEFAULT_CELL_HASH};
mod bag_of_cells;
mod bit_string;
mod builder;

mod cell_type;
mod dict_loader;
mod error;
Expand Down Expand Up @@ -418,7 +419,7 @@ impl Default for Cell {
}

fn get_repr_for_data(
(original_data, original_data_bit_len): (&[u8], usize),
original_data_bit_len: usize,
(data, data_bit_len): (&[u8], usize),
refs: &[ArcCell],
level_mask: LevelMask,
Expand All @@ -432,7 +433,7 @@ fn get_repr_for_data(

let mut writer = BitWriter::endian(Vec::with_capacity(buffer_len), BigEndian);
let d1 = get_refs_descriptor(cell_type, refs, level_mask.apply(level).mask());
let d2 = get_bits_descriptor(original_data, original_data_bit_len);
let d2 = get_bits_descriptor(original_data_bit_len);

// Write descriptors
writer.write(8, d1).map_cell_parser_error()?;
Expand Down Expand Up @@ -504,7 +505,7 @@ fn calculate_hashes_and_depths(

// Calculate Hash
let repr = get_repr_for_data(
(data, bit_len),
bit_len,
(current_data, current_bit_len),
references,
level_mask,
Expand All @@ -531,10 +532,8 @@ fn get_refs_descriptor(cell_type: CellType, references: &[ArcCell], level_mask:
references.len() as u8 + 8 * cell_type_var + level_mask as u8 * 32
}

fn get_bits_descriptor(data: &[u8], bit_len: usize) -> u8 {
let rest_bits = bit_len % 8;
let full_bytes = rest_bits == 0;
data.len() as u8 * 2 - !full_bytes as u8 // subtract 1 if the last byte is not full
fn get_bits_descriptor(bit_len: usize) -> u8 {
(bit_len / 8 + (bit_len + 7) / 8) as u8
}

fn write_data(
Expand Down
66 changes: 55 additions & 11 deletions src/cell/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,22 @@ impl CellBuilder {
}

pub fn store_uint(&mut self, bit_len: usize, val: &BigUint) -> Result<&mut Self, TonCellError> {
if val.bits() as usize > bit_len {
let val_bits = if val.is_zero() {
0
} else {
val.bits() as usize
};

if val_bits > bit_len {
return Err(TonCellError::cell_builder_error(format!(
"Value {} doesn't fit in {} bits (takes {} bits)",
val,
bit_len,
val.bits()
val, bit_len, val_bits
)));
}
// example: bit_len=13, val=5. 5 = 00000101, we must store 0000000000101
// leading_zeros_bits = 10
// leading_zeros_bytes = 10 / 8 = 1
let leading_zero_bits = bit_len - val.bits() as usize;
let leading_zero_bits = bit_len - val_bits;
let leading_zeros_bytes = leading_zero_bits / 8;
for _ in 0..leading_zeros_bytes {
self.store_byte(0)?;
Expand All @@ -113,9 +117,13 @@ impl CellBuilder {
// and then store val's high byte in minimum number of bits
let val_bytes = val.to_bytes_be();
let high_bits_cnt = {
let cnt = val.bits() % 8;
let cnt = val_bits % 8;
if cnt == 0 {
8
if val.is_zero() {
0
} else {
8
}
} else {
cnt
}
Expand All @@ -133,13 +141,17 @@ impl CellBuilder {

pub fn store_int(&mut self, bit_len: usize, val: &BigInt) -> Result<&mut Self, TonCellError> {
let (sign, mag) = val.clone().into_parts();

let mag_bits = if mag.is_zero() {
bit_len as u64
} else {
mag.bits()
};
let bit_len = bit_len - 1; // reserve 1 bit for sign
if bit_len < mag.bits() as usize {
if bit_len < mag_bits as usize {
return Err(TonCellError::cell_builder_error(format!(
"Value {} doesn't fit in {} bits (takes {} bits)",
val,
bit_len,
mag.bits()
val, bit_len, mag_bits
)));
}
if sign == Sign::Minus {
Expand Down Expand Up @@ -369,6 +381,7 @@ mod tests {
use std::str::FromStr;

use num_bigint::{BigInt, BigUint, Sign};
use num_traits::Zero;

use crate::address::TonAddress;
use crate::cell::builder::extend_and_invert_bits;
Expand Down Expand Up @@ -567,9 +580,40 @@ mod tests {
println!("cell: {:?}", cell);
for bits_num in bits_for_tests.iter() {
let written_value = cell_parser.load_uint(*bits_num)?;
println!("RES: {:?},{:?}", written_value, value);

assert_eq!(written_value, value);
}

Ok(())
}

#[test]
fn test_padding() -> Result<(), TonCellError> {
let mut writer = CellBuilder::new();
writer.store_uint(32, &BigUint::zero())?; //deadline

let cell = writer.build()?;

println!("{:?}", cell);
assert_eq!(cell.data.len(), 4);
assert_eq!(cell.bit_len, 32);
Ok(())
}

#[test]
fn test_padding_r() -> Result<(), TonCellError> {
let mut writer = CellBuilder::new();
writer.store_uint(32, &BigUint::zero())?; //deadline
writer.store_address(&TonAddress::null())?; //recipientAddress
writer.store_address(&TonAddress::null())?; //referralAddress
writer.store_bit(false)?; //fulfillPayload
writer.store_bit(false)?; //rejectPayload
let cell = writer.build()?;
println!("{:?}", cell);

assert_eq!(cell.data.len(), 5);
assert_eq!(cell.bit_len, 38);
Ok(())
}
}
4 changes: 2 additions & 2 deletions src/contract/jetton/master_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub trait JettonMasterContract: TonContractInterface {
let method = JettonMasterMethods::GetJettonData.into();
let address = self.address().clone();

let res = self.run_get_method(method, &Vec::new()).await?;
let res = self.run_get_method(method, Vec::new()).await?;

let stack = res.stack;
if stack.len() == JETTON_DATA_STACK_ELEMENTS {
Expand Down Expand Up @@ -71,7 +71,7 @@ pub trait JettonMasterContract: TonContractInterface {
.map_cell_error(method, owner_address)?;
let cell_slice = CellSlice::full_cell(cell).map_cell_error(method, owner_address)?;
let slice = TvmStackEntry::Slice(cell_slice);
let res = self.run_get_method(method, &vec![slice]).await?;
let res = self.run_get_method(method, vec![slice]).await?;
let stack = res.stack;
if stack.len() == 1 {
stack[0].get_address().map_stack_error(method, &address)
Expand Down
2 changes: 1 addition & 1 deletion src/contract/jetton/wallet_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub trait JettonWalletContract: TonContractInterface {
let method = JettonWalletMethods::GetWalletData.into();
let address = self.address().clone();

let res = self.run_get_method(method, &Vec::new()).await?;
let res = self.run_get_method(method, Vec::new()).await?;

let stack = res.stack;
if stack.len() == WALLET_DATA_STACK_ELEMENTS {
Expand Down
2 changes: 1 addition & 1 deletion src/contract/nft/collection_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub trait NftCollectionContract: TonContractInterface {
let method = NftCollectionMethods::GetCollectionData.into();
let address = self.address().clone();

let stack = self.run_get_method(method, &Vec::new()).await?.stack;
let stack = self.run_get_method(method, Vec::new()).await?.stack;
if stack.len() == NFT_COLLECTION_STACK_ELEMENTS {
let next_item_index = stack[0].get_i64().map_stack_error(method, &address)?;
let cell = stack[1].get_cell().map_stack_error(method, &address)?;
Expand Down
2 changes: 1 addition & 1 deletion src/contract/nft/item_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub trait NftItemContract: TonContractInterface {
const NFT_DATA_STACK_ELEMENTS: usize = 5;
let address = self.address().clone();

let stack = self.run_get_method(method, &Vec::new()).await?.stack;
let stack = self.run_get_method(method, Vec::new()).await?.stack;
if stack.len() == NFT_DATA_STACK_ELEMENTS {
let init = stack[0].get_bool().map_stack_error(method, &address)?;
let index = stack[1].get_biguint().map_stack_error(method, &address)?;
Expand Down
4 changes: 2 additions & 2 deletions src/contract/wallet/wallet_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ enum WalletContractMethods {
pub trait TonWalletContract: TonContractInterface {
async fn seqno(&self) -> Result<u32, TonContractError> {
let method: &str = WalletContractMethods::Seqno.into();
let res = self.run_get_method("seqno", &Vec::new()).await?;
let res = self.run_get_method("seqno", Vec::new()).await?;
let stack = res.stack;
if stack.len() != 1 {
Err(TonContractError::InvalidMethodResultStackSize {
Expand All @@ -31,7 +31,7 @@ pub trait TonWalletContract: TonContractInterface {

async fn get_public_key(&self) -> Result<Vec<u8>, TonContractError> {
let method: &str = WalletContractMethods::GetPublicKey.into();
let res = self.run_get_method(method, &Vec::new()).await?;
let res = self.run_get_method(method, Vec::new()).await?;
let stack = res.stack;
if stack.len() != 1 {
Err(TonContractError::InvalidMethodResultStackSize {
Expand Down
4 changes: 2 additions & 2 deletions tests/contract_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub struct PoolData {
#[async_trait]
pub trait PoolContract: TonContractInterface {
async fn get_pool_data(&self) -> anyhow::Result<PoolData> {
let res = assert_ok!(self.run_get_method("get_pool_data", &Vec::new()).await);
let res = assert_ok!(self.run_get_method("get_pool_data", Vec::new()).await);
if res.stack.len() == 10 {
let pool_data = PoolData {
reserve0: assert_ok!(res.stack[0].get_biguint()),
Expand All @@ -58,7 +58,7 @@ pub trait PoolContract: TonContractInterface {
}

async fn invalid_method(&self) -> Result<TvmSuccess, TonContractError> {
self.run_get_method("invalid_method", &Vec::new()).await
self.run_get_method("invalid_method", Vec::new()).await
}
}

Expand Down
4 changes: 2 additions & 2 deletions tests/farm_data_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ async fn test_get_farming_minter_data() {

let stack = assert_ok!(
contract
.run_get_method("get_farming_minter_data", &Vec::new())
.run_get_method("get_farming_minter_data", Vec::new())
.await
);

Expand Down Expand Up @@ -139,7 +139,7 @@ async fn test_get_farming_data() {

let stack = assert_ok!(
contract
.run_get_method("get_farming_data", &Vec::new())
.run_get_method("get_farming_data", Vec::new())
.await
);

Expand Down
2 changes: 1 addition & 1 deletion tests/jetton_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ async fn test_jetton_image_data() -> anyhow::Result<()> {
17, 18, 84, 70, 179, 240, 137, 163, 42, 147, 119, 220,
];
let mut hasher: Sha256 = Sha256::new();
hasher.update(&content_res.image_data.unwrap());
hasher.update(content_res.image_data.unwrap());
let img_hash = hasher.finalize()[..].to_vec();
assert_eq!(TARGET_IMAGE_HASH.to_vec(), img_hash);

Expand Down

0 comments on commit c5d5199

Please sign in to comment.