Skip to content

Commit

Permalink
Upstream 0.23.0 (#134)
Browse files Browse the repository at this point in the history
* Impl #BE-1881: Replaced dashmap by tokio::sync:Mutex to avoid mem leaks

* Impl #BE-1846 : library cache

* impl display for TonHash

* Impl #BE-1839: Boxed long errors, updated builder methods

* Impl: #BE-1893: Library provider trait and implementation of  BlockChainLibraryProvider

* NI: bump tonlib-sys to 2024.10.4

* Release v0.23.0

---------

Co-authored-by: Dmitrii Korchagin <[email protected]>
Co-authored-by: dbaranov34 <[email protected]>
  • Loading branch information
3 people authored Jan 9, 2025
1 parent ad30374 commit b239b06
Show file tree
Hide file tree
Showing 31 changed files with 842 additions and 248 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@
### v0.22.4

* make pub TvmEmulatorUnsafe
### v0.23.0

* Impl #BE-1846: library cache
* Impl #BE-1881: Replaced dashmap by tokio::sync:Mutex to avoid mem leaks
* Impl #BE-1839: Boxed long errors, updated builder methods
* Impl #BE-1892: Display for TonHash
* Impl #BE-1893: Library provider trait and implementation of BlockChainLibraryProvider
* NI: bump tonlib-sys to 2024.10.4
7 changes: 3 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ resolver = "2"


[workspace.package]
version = "0.22.4"
version = "0.23.0"
edition = "2021"
description = "Rust SDK for The Open Network"
license = "MIT"
Expand All @@ -25,7 +25,6 @@ base64 = "0.22"
base64-serde = "0.7"
bitstream-io = "2.2"
crc = "3"
dashmap = "5"
futures = "0.3"
hex = "0.4"
hmac = { version = "0.12", features = ["std"] }
Expand All @@ -50,10 +49,10 @@ tokio-retry = "0.3"
tokio-test = "0.4"
ton_liteapi = "0.1.0"
adnl = "2.0"
tonlib-sys = "=2024.10.3"
tonlib-sys = "=2024.10.4"
tokio-tower = "0.6.0"
tower = "0.5.1"
libc = "0.2"

# internal deps
tonlib-core = { version = "0.22", path = "core" }
tonlib-core = { version = "0.23", path = "core" }
1 change: 0 additions & 1 deletion client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ base64.workspace = true
base64-serde.workspace = true

crc.workspace = true
dashmap.workspace = true
futures.workspace = true
hex.workspace = true

Expand Down
3 changes: 1 addition & 2 deletions client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ async fn call_blockchain_methods()-> anyhow::Result<()>{
txs.incomplete
);
for tx_id in txs.transactions {
let mut t: TonHash = ZERO_HASH;
t.clone_from_slice(tx_id.account.as_slice());
let t = TonHash::try_from(tx_id.account.as_slice())?;
let addr = TonAddress::new(workchain, &t);
let id = InternalTransactionId {
hash: tx_id.hash.clone(),
Expand Down
21 changes: 12 additions & 9 deletions client/src/client/connection.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::collections::HashMap;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::{Arc, Weak};
use std::thread;
use std::thread::JoinHandle;
use std::time::Instant;

use async_trait::async_trait;
use dashmap::DashMap;
use tokio::sync::{broadcast, oneshot, Semaphore, SemaphorePermit};
use tokio::sync::{broadcast, oneshot, Mutex, Semaphore, SemaphorePermit};

use crate::client::{
TonClientError, TonClientInterface, TonConnectionCallback, TonConnectionParams,
Expand All @@ -28,7 +28,7 @@ struct RequestData {
sender: oneshot::Sender<Result<TonResult, TonClientError>>,
}

type RequestMap = DashMap<u32, RequestData>;
type RequestMap = Mutex<HashMap<u32, RequestData>>;
type TonNotificationSender = broadcast::Sender<Arc<TonNotification>>;

struct Inner {
Expand Down Expand Up @@ -85,10 +85,12 @@ impl TonConnection {
} else {
None
};

let request_map = Mutex::new(HashMap::new());
let inner = Inner {
tl_client: TlTonClient::new(tag.as_str()),
counter: AtomicU32::new(0),
request_map: RequestMap::new(),
request_map,
notification_sender: sender,
callback,
_notification_receiver: receiver,
Expand Down Expand Up @@ -271,14 +273,14 @@ impl TonClientInterface for TonConnection {
send_time: Instant::now(),
sender: tx,
};
self.inner.request_map.insert(cnt, data);
self.inner.request_map.lock().await.insert(cnt, data);
self.inner
.callback
.on_invoke(self.inner.tl_client.get_tag(), cnt, function);

let res = self.inner.tl_client.send(function, extra.as_str());
if let Err(e) = res {
let (_, data) = self.inner.request_map.remove(&cnt).unwrap();
let data = self.inner.request_map.lock().await.remove(&cnt).unwrap();
let tag = self.inner.tl_client.get_tag();
let duration = Instant::now().duration_since(data.send_time);
let res = Err(TonClientError::TlError(e));
Expand Down Expand Up @@ -322,12 +324,13 @@ fn run_loop(tag: String, weak_inner: Weak<Inner>, callback: Arc<dyn TonConnectio
} else {
None
};
let maybe_data = maybe_request_id.and_then(|i| inner.request_map.remove(&i));
let maybe_data =
maybe_request_id.and_then(|i| inner.request_map.blocking_lock().remove(&i));
let result: Result<TonResult, TonClientError> = match ton_result {
Ok(TonResult::Error { code, message }) => {
let method = maybe_data
.as_ref()
.map(|d| d.1.method)
.map(|d| d.method)
.unwrap_or(NOT_AVAILABLE);
Err(TonClientError::TonlibError {
method,
Expand All @@ -339,7 +342,7 @@ fn run_loop(tag: String, weak_inner: Weak<Inner>, callback: Arc<dyn TonConnectio
Ok(r) => Ok(r),
};

if let Some((_, data)) = maybe_data {
if let Some(data) = maybe_data {
// Found corresponding request, reply to it
let request_id = maybe_request_id.unwrap(); // Can't be empty if data is not empty
let now = Instant::now();
Expand Down
60 changes: 44 additions & 16 deletions client/src/contract/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::borrow::Cow;
use std::sync::Arc;

use thiserror::Error;
use tonlib_core::cell::TonCellError;
use tonlib_core::types::TonHashParseError;
use tonlib_core::TonAddress;

use crate::client::TonClientError;
Expand Down Expand Up @@ -77,7 +79,7 @@ pub enum TonContractError {
TvmStackParseError {
method: TonMethodId,
address: TonAddress,
error: StackParseError,
error: Box<StackParseError>,
},

#[error(
Expand All @@ -87,22 +89,25 @@ pub enum TonContractError {
TvmRunError {
method: TonMethodId,
address: TonAddress,
vm_log: Option<String>,
vm_log: Box<Option<String>>,
exit_code: i32,
stack: Vec<TvmStackEntry>,
stack: Box<Vec<TvmStackEntry>>,
missing_library: Option<String>,
gas_used: i64,
},

#[error("{0}")]
CacheError(#[from] Arc<TonContractError>),

#[error("{0}")]
TonLibraryError(#[from] TonLibraryError),
}

pub trait MapStackError<R> {
#[allow(clippy::result_large_err)]
fn map_stack_error(
self,
method: &'static str,
method: impl Into<Cow<'static, str>>,
address: &TonAddress,
) -> Result<R, TonContractError>;
}
Expand All @@ -111,49 +116,72 @@ pub trait MapCellError<R> {
#[allow(clippy::result_large_err)]
fn map_cell_error(
self,
method: &'static str,
method: impl Into<Cow<'static, str>>,
address: &TonAddress,
) -> Result<R, TonContractError>;
}

impl<R> MapStackError<R> for Result<R, TvmStackError> {
fn map_stack_error(
self,
method: &'static str,
method: impl Into<Cow<'static, str>>,
address: &TonAddress,
) -> Result<R, TonContractError> {
self.map_err(|e| TonContractError::MethodResultStackError {
method: method.into(),
address: address.clone(),
error: e,
})
self.map_err(
|e: TvmStackError| TonContractError::MethodResultStackError {
method: TonMethodId::Name(method.into()),
address: address.clone(),
error: e,
},
)
}
}

impl<R> MapStackError<R> for Result<R, StackParseError> {
fn map_stack_error(
self,
method: &'static str,
method: impl Into<Cow<'static, str>>,
address: &TonAddress,
) -> Result<R, TonContractError> {
self.map_err(|e| TonContractError::TvmStackParseError {
method: method.into(),
method: TonMethodId::Name(method.into()),
address: address.clone(),
error: e,
error: e.into(),
})
}
}

impl<R> MapCellError<R> for Result<R, TonCellError> {
fn map_cell_error(
self,
method: &'static str,
method: impl Into<Cow<'static, str>>,
address: &TonAddress,
) -> Result<R, TonContractError> {
self.map_err(|e| TonContractError::MethodResultStackError {
method: method.into(),
method: TonMethodId::Name(method.into()),
address: address.clone(),
error: e.into(),
})
}
}

#[derive(Error, Debug)]
pub enum TonLibraryError {
#[error("{0}")]
TonClientError(#[from] TonClientError),

#[error("{0}")]
TonCellError(#[from] TonCellError),

#[error("{0}")]
TonHashParseError(#[from] TonHashParseError),

#[error("Library not found for {0}")]
LibraryNotFound(String),

#[error("Expected exactly one library, but got multiple")]
MultipleLibrariesReturned,

#[error("Getting library by mc_seqno is not supported")]
SeqnoNotSupported,
}
16 changes: 10 additions & 6 deletions client/src/contract/factory.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::sync::atomic::AtomicI32;
use std::sync::Arc;
use std::time::Duration;

pub use blockchain_library_provider::*;
pub use builder::*;
pub use cache::*;
pub use library_loader::*;
pub use library_helper::*;
pub use library_provider::*;
use tokio::sync::OnceCell;
use tonlib_core::TonAddress;
Expand All @@ -12,11 +14,11 @@ use crate::client::{TonClient, TonClientError, TonClientInterface};
use crate::contract::{LoadedSmcState, TonContract, TonContractError, TonContractState};
use crate::tl::{ConfigInfo, InternalTransactionId, RawFullAccountState};

mod blockchain_library_provider;
mod builder;
mod cache;
mod library_loader;
mod library_helper;
mod library_provider;

#[derive(Clone)]
pub struct TonContractFactory {
inner: Arc<Inner>,
Expand All @@ -25,7 +27,7 @@ pub struct TonContractFactory {
struct Inner {
client: TonClient,
config_info: OnceCell<ConfigInfo>,
library_provider: LibraryProvider,
library_provider: Arc<dyn LibraryProvider>,
cache: Option<ContractFactoryCache>,
}

Expand All @@ -43,7 +45,8 @@ impl TonContractFactory {
txid_cache_capacity: u64,
txid_cache_time_to_live: Duration,
presync_blocks: i32,
library_provider: LibraryProvider,
library_provider: Arc<dyn LibraryProvider>,
current_seqno: Arc<AtomicI32>,
) -> Result<TonContractFactory, TonContractError> {
let cache = if with_cache {
let cache = ContractFactoryCache::new(
Expand All @@ -53,6 +56,7 @@ impl TonContractFactory {
txid_cache_capacity,
txid_cache_time_to_live,
presync_blocks,
current_seqno,
)
.await?;
Some(cache)
Expand Down Expand Up @@ -85,7 +89,7 @@ impl TonContractFactory {
Ok(c.config.bytes.as_slice())
}

pub fn library_provider(&self) -> LibraryProvider {
pub fn library_provider(&self) -> Arc<dyn LibraryProvider> {
self.inner.library_provider.clone()
}

Expand Down
Loading

0 comments on commit b239b06

Please sign in to comment.