From f3320d4812a6ff9324ea2d60058752bac0f7bc53 Mon Sep 17 00:00:00 2001 From: SilkovAlexander Date: Fri, 20 Aug 2021 12:17:03 +0300 Subject: [PATCH] Fixed retry as in SDK --- Cargo.toml | 2 +- src/call.rs | 37 +++++++++++++------------------------ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eededf6c..8352fa0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ readme = "README.md" license = "Apache-2.0" keywords = ["TON", "SDK", "smart contract", "tonlabs", "solidity"] edition = "2018" -version = "0.17.17" +version = "0.17.18" [dependencies] async-trait = "0.1.42" diff --git a/src/call.rs b/src/call.rs index 9afd819f..6b3f0353 100644 --- a/src/call.rs +++ b/src/call.rs @@ -32,8 +32,9 @@ use ton_client::processing::{ ParamsOfWaitForTransaction, wait_for_transaction, send_message, + ErrorCode }; -use ton_client::tvm::{run_tvm, run_get, ParamsOfRunTvm, ParamsOfRunGet, run_executor, ParamsOfRunExecutor, AccountForExecutor}; +use ton_client::tvm::{run_tvm, run_get, ParamsOfRunTvm, ParamsOfRunGet, run_executor, ParamsOfRunExecutor, AccountForExecutor, StdContractError}; use ton_client::error::ClientError; use ton_block::{Account, Serializable, Deserializable}; use std::str::FromStr; @@ -470,10 +471,10 @@ pub async fn call_contract_with_result( let mut attempts = conf.retries + 1; // + 1 (first try) let total_attempts = attempts.clone(); - let expire_at = conf.lifetime + now(); - let time = now_ms(); while attempts != 0 { attempts -= 1; + let expire_at = conf.lifetime + now(); + let time = now_ms(); let header = FunctionHeader { expire: Some(expire_at), time: Some(time), @@ -494,30 +495,18 @@ pub async fn call_contract_with_result( print_encoded_message(&msg); } - let mut retry: bool = true; + let mut retry: bool = false; let error_handler = |err: ClientError| { - // obtaining error code - let code = err.code.clone(); - // but if it was simulated locally and local exit code is not zero, - // we ignore previous exit code because it means we shouldn't make a retry. - if !err.data["exit_code"].is_null() { - if err.data["exit_code"].as_i64().unwrap_or(-1) != 0 { - retry = false; + // retry only if error code is MessageExpired + if err.code == ErrorCode::MessageExpired as u32{ + // but we should also check possible local execution error + let local_error = err.data["local_error"]["data"]["exit_code"].clone(); + if err.data["local_error"].is_null() || + local_error.as_i64().unwrap_or(-1) == StdContractError::ReplayProtection as i64|| + local_error.as_i64().unwrap_or(-1) == StdContractError::ExtMessageExpired as i64 { + retry = true; } } - // There is also another way how SDK can print local run results. - let local_error = err.data["local_error"]["data"]["exit_code"].clone(); - if !local_error.is_null() { - if local_error.as_i64().unwrap_or(-1) != 0 { - retry = false; - } - } - // if error code was 4XX then don't perform a retry. Also if error was 508, - // it means that message could have been delivered after timeout and for not - // to cause double call we shouldn't perform a retry. - if (((code / 100) as u32 % 10) == 4) || (code == 508) { - retry = false; - } }; if (!local && conf.local_run) || is_fee {