Skip to content

Commit

Permalink
Merge pull request #155 from tonlabs/0.26.0-rc
Browse files Browse the repository at this point in the history
Version 0.26.0
  • Loading branch information
z3g authored Aug 26, 2020
2 parents 5e1b966 + 96a43b1 commit fe83996
Show file tree
Hide file tree
Showing 14 changed files with 200 additions and 81 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Release Notes
All notable changes to this project will be documented in this file.

## 0.26.0 Aug 7, 2020
### New
- `crypto` function `crypto.derive_sign_keys_from_mnemonic`
- full local run functions use `LocalRunContext` to exactly reproduce all transaction parameters and
produce the same result as node

## 0.25.4 Aug 5, 2020
### Fixed
- `waitForTransaction` didn't use prev_alt_ref for block walking
Expand Down
22 changes: 22 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,7 @@ ton_client/platforms/ton-client-web"""
if [ -e 'toDeploy' ] ; then echo 'Remove...' ; rm -rf toDeploy ; fi
mkdir toDeploy
"""

dir('toDeploy') {
unstash 'cl-linux-bin'
unstash 'cl-darwin-bin'
Expand All @@ -1105,14 +1106,35 @@ ton_client/platforms/ton-client-web"""
unstash 'web-bin'
def deployPath = 'tmp_sdk'
if(GIT_BRANCH == "${getVar(G_binversion)}-rc") {

TON_SDK_BIN_VERSION = GIT_BRANCH.replaceAll("\\.", "_")
echo "TON_SDK_BIN_VERSION: ${TON_SDK_BIN_VERSION}"

deployPath = ''
sh """
for it in \$(ls)
do
mv \$it \$(echo \$it | sed -E \"s/([0-9]+_[0-9]+_[0-9]+)/\\1-rc/\");
done
"""

def params = [
[
$class: 'StringParameterValue',
name: 'TON_SDK_BIN_VERSION',
value: "${TON_SDK_BIN_VERSION}"
],
[
$class: 'BooleanParameterValue',
name: 'RUN_TESTS_TON_SURF',
value: true
],
]

build job: "Integration/integration-tests/master", parameters: params

}

withAWS(credentials: 'CI_bucket_writer', region: 'eu-central-1') {
identity = awsIdentity()
s3Upload \
Expand Down
2 changes: 1 addition & 1 deletion ton_client/client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ton_client"
version = "0.25.4"
version = "0.26.0"
authors = ["Michael Vlasov"]
edition = "2018"
license = "Apache-2.0"
Expand Down
25 changes: 21 additions & 4 deletions ton_client/client/src/contracts/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ pub struct DeployFunctionCallSet {
pub constructor_params: serde_json::Value,
}

impl DeployFunctionCallSet {
pub fn function_name() -> &'static str {
"constructor"
}
}

impl Into<FunctionCallSet> for DeployFunctionCallSet {
fn into(self) -> FunctionCallSet {
FunctionCallSet {
func: "constructor".to_owned(),
func: Self::function_name().to_owned(),
header: self.constructor_header.map(|value| value.to_string().to_owned()),
input: self.constructor_params.to_string(),
abi: self.abi.to_string(),
Expand Down Expand Up @@ -133,11 +139,20 @@ pub(crate) async fn deploy(context: &mut ClientContext, params: ParamsOfDeploy)

let client = context.get_client()?;
trace!("-> -> deploy");
let tr = deploy_contract(client, params, contract_image, &key_pair).await?;
let tr = deploy_contract(client, params, contract_image, &key_pair)
.await
.map_err(|err| err
.add_function(Some(&DeployFunctionCallSet::function_name()))
.add_network_url(client)
)?;
trace!("-> -> deploy transaction: {}", tr.parsed.id());

trace!("<-");
super::run::check_transaction_status(&tr.parsed, true, &account_id, None)?;
super::run::check_transaction_status(&tr.parsed, true, &account_id, None)
.map_err(|err| err
.add_function(Some(&DeployFunctionCallSet::function_name()))
.add_network_url(client)
)?;
Ok(ResultOfDeploy {
address: account_encode(&account_id),
already_deployed: false,
Expand Down Expand Up @@ -308,7 +323,9 @@ async fn deploy_contract(client: &NodeClient, params: ParamsOfDeploy, image: Con
match result {
Err(err) =>
Err(resolve_msg_sdk_error(
client, err, &msg, ApiError::contracts_deploy_failed).await?),
client, err, &msg, None,
ApiError::contracts_deploy_failed).await?
),
Ok(tr) => Ok(tr)
}
}
Expand Down
9 changes: 6 additions & 3 deletions ton_client/client/src/contracts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,9 @@ pub(crate) async fn process_message(context: &mut ClientContext, params: ParamsO
let transaction = match result {
Err(err) =>
return Err(run::resolve_msg_sdk_error(
client, err, &msg, ApiError::contracts_process_message_failed
).await?),
client, err, &msg, params.function_name.as_ref().map(|string| string.as_str()), ApiError::contracts_process_message_failed
).await?
),
Ok(tr) => tr
};

Expand Down Expand Up @@ -368,7 +369,9 @@ pub(crate) async fn wait_transaction(context: &mut ClientContext, params: Params
let transaction = match result {
Err(err) =>
return Err(run::resolve_msg_sdk_error(
client, err, &msg, ApiError::contracts_process_message_failed
client, err, &msg,
params.function_name.as_ref().map(|string| string.as_str()),
ApiError::contracts_process_message_failed
).await?),
Ok(tr) => tr
};
Expand Down
72 changes: 42 additions & 30 deletions ton_client/client/src/contracts/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
* limitations under the License.
*/

use ton_sdk::{Contract, MessageType, AbiContract, FunctionCallSet};
use ton_sdk::{Contract, MessageType, AbiContract, FunctionCallSet, Transaction, Message,
TransactionFees, LocalRunContext};
use ton_sdk::json_abi::encode_function_call;
use ton_types::cells_serialization::BagOfCells;
use ton_block::{AccStatusChange, Message as TvmMessage, MsgAddressInt};
use ton_sdk::{Transaction, Message, TransactionFees};

use crate::contracts::{EncodedMessage, EncodedUnsignedMessage};
use crate::client::ClientContext;
Expand Down Expand Up @@ -76,7 +76,8 @@ pub(crate) struct ParamsOfLocalRun {
pub key_pair: Option<KeyPair>,
#[serde(default)]
pub full_run: bool,
pub time: Option<u32>,
#[serde(flatten)]
pub context: LocalRunContext,
}

#[derive(Serialize, Deserialize)]
Expand All @@ -89,7 +90,8 @@ pub(crate) struct ParamsOfLocalRunWithMsg {
pub message_base64: String,
#[serde(default)]
pub full_run: bool,
pub time: Option<u32>,
#[serde(flatten)]
pub context: LocalRunContext,
}

#[derive(Serialize, Deserialize)]
Expand Down Expand Up @@ -320,7 +322,7 @@ pub(crate) fn local_run(context: &mut ClientContext, params: ParamsOfLocalRun) -
address,
account,
params.full_run,
params.time,
params.context,
).map_err(|err| match context.get_client() {
Ok(client) => err.add_network_url(client),
Err(_) => err
Expand Down Expand Up @@ -356,7 +358,7 @@ pub(crate) fn local_run_msg(context: &mut ClientContext, params: ParamsOfLocalRu
params.function_name,
msg,
params.full_run,
params.time,
params.context,
).map_err(|err| match context.get_client() {
Ok(client) => err.add_network_url(client),
Err(_) => err
Expand Down Expand Up @@ -616,7 +618,8 @@ async fn call_contract(
match result {
Err(err) =>
Err(resolve_msg_sdk_error(
client, err, &msg, ApiError::contracts_run_failed).await?),
client, err, &msg, Some(&params.call_set.function_name), ApiError::contracts_run_failed
).await?),
Ok(tr) => Ok(tr)
}
}
Expand All @@ -630,7 +633,7 @@ pub(crate) fn do_local_run(
address: MsgAddressInt,
account: Option<Contract>,
full_run: bool,
time: Option<u32>,
run_context: LocalRunContext,
) -> ApiResult<ResultOfLocalRun> {
let msg = Contract::construct_call_message_json(
address.clone(), call_set.clone().into(), false, keys, None, None)
Expand All @@ -644,7 +647,7 @@ pub(crate) fn do_local_run(
Some(call_set.function_name),
msg.message,
full_run,
time)
run_context)
}

pub(crate) fn do_local_run_msg(
Expand All @@ -655,7 +658,7 @@ pub(crate) fn do_local_run_msg(
function_name: Option<String>,
msg: TvmMessage,
full_run: bool,
time: Option<u32>,
run_context: LocalRunContext,
) -> ApiResult<ResultOfLocalRun> {
let contract = match account {
// load contract data from node manually
Expand Down Expand Up @@ -684,8 +687,8 @@ pub(crate) fn do_local_run_msg(
};

if full_run {
let result = contract.local_call(msg, time)
.map_err(|err|
let result = contract.local_call(msg, run_context)
.map_err(|err|
match err.downcast_ref::<ton_sdk::SdkError>() {
Some(ton_sdk::SdkError::ContractError(exit_code)) =>
ApiError::tvm_execution_failed(None, *exit_code, &address),
Expand Down Expand Up @@ -739,14 +742,16 @@ pub(crate) fn resolve_msg_error(
Err(err) => return err
};

let result = do_local_run_msg(None, address, Some(account), None, None, msg, true, Some(time));
let mut context = LocalRunContext::default();
context.time = Some(time);
let result = do_local_run_msg(None, address.clone(), Some(account), None, None, msg, true, context);

if let Err(mut err) = result {
err.data["original_error"] = serde_json::to_value(main_error).unwrap_or_default();
err
} else {
main_error.data["disclaimer"] = "Local contract call succeded. Can not resolve extended error".into();
main_error
main_error.add_address(&address)
}
}

Expand All @@ -755,23 +760,30 @@ pub(crate) async fn resolve_msg_sdk_error<F: Fn(String) -> ApiError>(
client: &NodeClient,
error: failure::Error,
msg: &ton_sdk::SdkMessage,
function: Option<&str>,
default_error: F,
) -> ApiResult<ApiError> {
match error.downcast_ref::<SdkError>() {
Some(SdkError::MessageExpired { msg_id: _, expire: _, sending_time, block_time: _, block_id: _ }) |
Some(SdkError::TransactionWaitTimeout { msg_id: _, sending_time, timeout: _, state: _ }) => {
let account = Contract::load(client, &msg.address)
.await
.map_err(|err| apierror_from_sdkerror(
&err, ApiError::contracts_run_contract_load_failed, Some(client),
).add_address(&msg.address))?
.ok_or(ApiError::account_missing(&msg.address))?;
let main_error = apierror_from_sdkerror(&error, default_error, None);
let resolved = resolve_msg_error(
msg.address.clone(), account, &msg.serialized_message, *sending_time, main_error,
).add_network_url(client);
Ok(resolved)
let err = {
match error.downcast_ref::<SdkError>() {
Some(SdkError::MessageExpired { msg_id: _, expire: _, sending_time, block_time: _, block_id: _ }) |
Some(SdkError::TransactionWaitTimeout { msg_id: _, sending_time, timeout: _, state: _ }) => {
let account = Contract::load(client, &msg.address)
.await
.map_err(|err| apierror_from_sdkerror(
&err, ApiError::contracts_run_contract_load_failed, Some(client),
).add_address(&msg.address))?
.ok_or(ApiError::account_missing(&msg.address))?;
let main_error = apierror_from_sdkerror(&error, default_error, None);
let resolved = resolve_msg_error(
msg.address.clone(), account, &msg.serialized_message, *sending_time, main_error,
);
Ok(resolved)
}
_ => Err(apierror_from_sdkerror(&error, default_error, Some(client)))
}
_ => Err(apierror_from_sdkerror(&error, default_error, Some(client)))
}
}?;
Ok(err
.add_network_url(client)
.add_function(function)
.add_address(&msg.address))
}
25 changes: 14 additions & 11 deletions ton_client/client/src/crypto/mnemonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ pub trait CryptoMnemonic {
fn entropy_from_phrase(&self, phrase: &String) -> ApiResult<String>;
}

fn check_phrase(mnemonic: &dyn CryptoMnemonic, phrase: &String) -> ApiResult<()> {
if mnemonic.is_phrase_valid(phrase)? {
Ok(())
} else {
Err(ApiError::crypto_bip39_invalid_phrase(phrase))
}
}

pub struct Bip39Mnemonic {
mnemonic_type: MnemonicType,
language: Language,
Expand Down Expand Up @@ -84,6 +92,7 @@ impl CryptoMnemonic for Bip39Mnemonic {
path: &String,
compliant: bool,
) -> ApiResult<KeyPair> {
check_phrase(self, phrase)?;
let derived = HDPrivateKey::from_mnemonic(phrase)?.derive_path(path, compliant)?;
ed25519_keys_from_secret_bytes(&derived.secret())
}
Expand All @@ -99,6 +108,7 @@ impl CryptoMnemonic for Bip39Mnemonic {
}

fn seed_from_phrase_and_salt(&self, phrase: &String, salt: &String) -> ApiResult<String> {
check_phrase(self, phrase)?;
let mnemonic = Mnemonic::from_phrase(phrase, self.language)
.map_err(|err| ApiError::crypto_bip39_invalid_phrase(err))?;

Expand All @@ -115,6 +125,7 @@ impl CryptoMnemonic for Bip39Mnemonic {

#[allow(dead_code)]
fn entropy_from_phrase(&self, phrase: &String) -> ApiResult<String> {
check_phrase(self, phrase)?;
let mnemonic = Mnemonic::from_phrase(phrase, self.language)
.map_err(|err| ApiError::crypto_bip39_invalid_phrase(err))?;
Ok(hex::encode(mnemonic.entropy()))
Expand Down Expand Up @@ -169,14 +180,6 @@ impl TonMnemonic {
};
count == self.word_count && Self::is_basic_seed(phrase)
}

fn check_phrase(&self, phrase: &String) -> ApiResult<()> {
if self.internal_is_phrase_valid(phrase) {
Ok(())
} else {
Err(ApiError::crypto_bip39_invalid_phrase(phrase))
}
}
}


Expand Down Expand Up @@ -205,7 +208,7 @@ impl CryptoMnemonic for TonMnemonic {
_path: &String,
_compliant: bool,
) -> ApiResult<KeyPair> {
self.check_phrase(phrase)?;
check_phrase(self, phrase)?;
let seed = Self::seed_from_string(&phrase, "TON default seed", 100_000);
ed25519_keys_from_secret_bytes(&seed[..32])
}
Expand All @@ -227,12 +230,12 @@ impl CryptoMnemonic for TonMnemonic {
}

fn seed_from_phrase_and_salt(&self, phrase: &String, salt: &String) -> ApiResult<String> {
self.check_phrase(phrase)?;
check_phrase(self, phrase)?;
Ok(hex::encode(Self::seed_from_string(phrase, salt, 100_000).as_ref()))
}

fn entropy_from_phrase(&self, phrase: &String) -> ApiResult<String> {
self.check_phrase(phrase)?;
check_phrase(self, phrase)?;
Ok(hex::encode(Self::entropy_from_string(&phrase).as_ref()))
}
}
Expand Down
Loading

0 comments on commit fe83996

Please sign in to comment.