diff --git a/CMakeLists.txt b/CMakeLists.txt
index a005e915..4e85633b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -255,6 +255,18 @@ if (NOT ANDROID) # _FILE_OFFSET_BITS is broken in ndk r15 and r15b and doesn't w
add_definitions(-D_FILE_OFFSET_BITS=64)
endif()
+set(INTERNAL_COMPILE "0")
+#BEGIN internal
+ add_definitions(-D_INTERNAL_COMPILE=1)
+ set(INTERNAL_COMPILE "1")
+#END internal
+
+set(TONLIB_COMPILE "0")
+#BEGIN tonlib
+ add_definitions(-D_TONLIB_COMPILE=1)
+ set(TONLIB_COMPILE "1")
+#END tonlib
+
include(AddCXXCompilerFlag)
if (MSVC)
add_cxx_compiler_flag("/experimental:external /external:anglebrackets /external:W0")
diff --git a/catchain/catchain-receiver-source.cpp b/catchain/catchain-receiver-source.cpp
index 502843f9..aca522dc 100644
--- a/catchain/catchain-receiver-source.cpp
+++ b/catchain/catchain-receiver-source.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "catchain-receiver-source.hpp"
#include "common/errorlog.h"
@@ -75,6 +75,7 @@ void CatChainReceiverSourceImpl::blame() {
if (!blamed_) {
LOG(ERROR) << this << ": CATCHAIN: blaming source " << id_;
blocks_.clear();
+ delivered_height_ = 0;
chain_->on_blame(id_);
}
blamed_ = true;
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 7be5475b..f2865f55 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -56,7 +56,7 @@ set(TON_CRYPTO_SOURCE
ellcurve/TwEdwards.h
openssl/bignum.h
- openssl/digest.h
+ openssl/digest.hpp
openssl/rand.hpp
openssl/residue.h
@@ -391,7 +391,15 @@ endif()
add_executable(create-state block/create-state.cpp)
target_include_directories(create-state PUBLIC $
$)
-target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib)
+if (INTERNAL_COMPILE)
+ target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib)
+else()
+ if (TONLIB_COMPILE)
+ target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib)
+ else()
+ target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block)
+ endif()
+endif()
if (WINGETOPT_FOUND)
target_link_libraries_system(create-state wingetopt)
endif()
diff --git a/crypto/block/check-proof.cpp b/crypto/block/check-proof.cpp
index f8d38baa..6d991256 100644
--- a/crypto/block/check-proof.cpp
+++ b/crypto/block/check-proof.cpp
@@ -25,7 +25,7 @@
#include "ton/ton-shard.h"
#include "vm/cells/MerkleProof.h"
-#include "openssl/digest.h"
+#include "openssl/digest.hpp"
#include "Ed25519.h"
namespace block {
diff --git a/crypto/block/create-state.cpp b/crypto/block/create-state.cpp
index e850603f..2dc3f597 100644
--- a/crypto/block/create-state.cpp
+++ b/crypto/block/create-state.cpp
@@ -55,13 +55,16 @@
#include "td/utils/port/path.h"
#include "td/utils/port/signals.h"
-#include "tonlib/keys/Mnemonic.h"
-
#include "block.h"
#include "block-parse.h"
#include "block-auto.h"
#include "mc-config.h"
+#if defined(_INTERNAL_COMPILE) || defined(_TONLIB_COMPILE)
+# define WITH_TONLIB
+# include "tonlib/keys/Mnemonic.h"
+#endif
+
#define PDO(__op) \
if (!(__op)) { \
ok = false; \
@@ -636,6 +639,7 @@ void interpret_sub_extra_currencies(vm::Stack& stack) {
stack.push_bool(ok);
}
+#ifdef WITH_TONLIB
void interpret_mnemonic_to_privkey(vm::Stack& stack, int mode) {
td::SecureString str{td::Slice{stack.pop_string()}};
auto res = tonlib::Mnemonic::create(std::move(str), td::SecureString());
@@ -652,6 +656,7 @@ void interpret_mnemonic_to_privkey(vm::Stack& stack, int mode) {
}
stack.push_bytes(key.as_slice());
}
+#endif
void init_words_custom(fift::Dictionary& d) {
using namespace std::placeholders;
@@ -671,8 +676,10 @@ void init_words_custom(fift::Dictionary& d) {
d.def_stack_word("isWorkchainDescr? ", interpret_is_workchain_descr);
d.def_stack_word("CC+? ", interpret_add_extra_currencies);
d.def_stack_word("CC-? ", interpret_sub_extra_currencies);
+#ifdef WITH_TONLIB
d.def_stack_word("mnemo>priv ", std::bind(interpret_mnemonic_to_privkey, _1, 0));
d.def_stack_word("mnemo>pub ", std::bind(interpret_mnemonic_to_privkey, _1, 1));
+#endif
}
tlb::TypenameLookup tlb_dict;
diff --git a/crypto/block/mc-config.cpp b/crypto/block/mc-config.cpp
index d2774797..b202b60c 100644
--- a/crypto/block/mc-config.cpp
+++ b/crypto/block/mc-config.cpp
@@ -35,7 +35,7 @@
#include "td/utils/uint128.h"
#include "ton/ton-types.h"
#include "ton/ton-shard.h"
-#include "crypto/openssl/digest.h"
+#include "openssl/digest.hpp"
#include
#include
diff --git a/crypto/common/bitstring.cpp b/crypto/common/bitstring.cpp
index 6a23f072..0a273949 100644
--- a/crypto/common/bitstring.cpp
+++ b/crypto/common/bitstring.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "common/bitstring.h"
#include
@@ -22,7 +22,7 @@
#include "td/utils/as.h"
#include "td/utils/bits.h"
#include "td/utils/misc.h"
-#include "crypto/openssl/digest.h"
+#include "crypto/openssl/digest.hpp"
namespace td {
diff --git a/crypto/ellcurve/Ed25519.h b/crypto/ellcurve/Ed25519.h
index cb899cc1..4b9e6348 100644
--- a/crypto/ellcurve/Ed25519.h
+++ b/crypto/ellcurve/Ed25519.h
@@ -14,12 +14,12 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "ellcurve/Montgomery.h"
#include "ellcurve/TwEdwards.h"
-#include "openssl/digest.h"
+#include "openssl/digest.hpp"
#include "openssl/rand.hpp"
#include
#include
diff --git a/crypto/fift/words.cpp b/crypto/fift/words.cpp
index f9be336f..775e821a 100644
--- a/crypto/fift/words.cpp
+++ b/crypto/fift/words.cpp
@@ -28,6 +28,8 @@
#include "common/bitstring.h"
#include "common/util.h"
+#include "openssl/digest.hpp"
+
#include "Ed25519.h"
#include "vm/cells.h"
diff --git a/crypto/func/func.h b/crypto/func/func.h
index fd2bffd6..1506b974 100644
--- a/crypto/func/func.h
+++ b/crypto/func/func.h
@@ -934,7 +934,7 @@ struct AsmOp {
void out_indent_nl(std::ostream& os, bool no_nl = false) const;
std::string to_string() const;
void compute_gconst() {
- gconst = (is_custom() && (op == "PUSHNULL" || op == "NEWC" || op == "NEWB" || op == "TRUE" || op == "FALSE"));
+ gconst = (is_custom() && (op == "PUSHNULL" || op == "NEWC" || op == "NEWB" || op == "TRUE" || op == "FALSE" || op == "NOW"));
}
bool is_nop() const {
return t == a_none && op.empty();
diff --git a/crypto/openssl/bignum.cpp b/crypto/openssl/bignum.cpp
index 275b01bb..74dd6bbf 100644
--- a/crypto/openssl/bignum.cpp
+++ b/crypto/openssl/bignum.cpp
@@ -14,10 +14,14 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "openssl/bignum.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include
+#endif
+
// impl only
#include
diff --git a/crypto/openssl/bignum.h b/crypto/openssl/bignum.h
index 40d7d582..2a8dd8a0 100644
--- a/crypto/openssl/bignum.h
+++ b/crypto/openssl/bignum.h
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
@@ -115,7 +115,7 @@ class Bignum {
return set_hex_str(hs.str);
}
Bignum& swap(Bignum& x) {
- BN_swap(val, x.val);
+ std::swap(val, x.val);
return *this;
}
BIGNUM* bn_ptr() {
diff --git a/crypto/openssl/digest.hpp b/crypto/openssl/digest.hpp
new file mode 100644
index 00000000..5c232df9
--- /dev/null
+++ b/crypto/openssl/digest.hpp
@@ -0,0 +1,151 @@
+/*
+ This file is part of TON Blockchain Library.
+
+ TON Blockchain Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ TON Blockchain Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with TON Blockchain Library. If not, see .
+
+ Copyright 2017-2020 Telegram Systems LLP
+*/
+#pragma once
+#include
+
+#include
+#include
+
+#include "td/utils/Slice.h"
+
+namespace digest {
+struct OpensslEVP_SHA1 {
+ enum { digest_bytes = 20 };
+ static const EVP_MD *get_evp() {
+ return EVP_sha1();
+ }
+};
+
+struct OpensslEVP_SHA256 {
+ enum { digest_bytes = 32 };
+ static const EVP_MD *get_evp() {
+ return EVP_sha256();
+ }
+};
+
+struct OpensslEVP_SHA512 {
+ enum { digest_bytes = 64 };
+ static const EVP_MD *get_evp() {
+ return EVP_sha512();
+ }
+};
+
+template
+class HashCtx {
+ EVP_MD_CTX *ctx{nullptr};
+ void init();
+ void clear();
+
+ public:
+ enum { digest_bytes = H::digest_bytes };
+ HashCtx() {
+ init();
+ }
+ HashCtx(const void *data, std::size_t len) {
+ init();
+ feed(data, len);
+ }
+ ~HashCtx() {
+ clear();
+ }
+ void reset();
+ void feed(const void *data, std::size_t len);
+ void feed(td::Slice slice) {
+ feed(slice.data(), slice.size());
+ }
+ std::size_t extract(unsigned char buffer[digest_bytes]);
+ std::size_t extract(td::MutableSlice slice);
+ std::string extract();
+};
+
+template
+void HashCtx::init() {
+ ctx = EVP_MD_CTX_create();
+ reset();
+}
+
+template
+void HashCtx::reset() {
+ EVP_DigestInit_ex(ctx, H::get_evp(), 0);
+}
+
+template
+void HashCtx::clear() {
+ EVP_MD_CTX_destroy(ctx);
+ ctx = nullptr;
+}
+
+template
+void HashCtx::feed(const void *data, std::size_t len) {
+ EVP_DigestUpdate(ctx, data, len);
+}
+
+template
+std::size_t HashCtx::extract(unsigned char buffer[digest_bytes]) {
+ unsigned olen = 0;
+ EVP_DigestFinal_ex(ctx, buffer, &olen);
+ assert(olen == digest_bytes);
+ return olen;
+}
+
+template
+std::size_t HashCtx::extract(td::MutableSlice slice) {
+ return extract(slice.ubegin());
+}
+
+template
+std::string HashCtx::extract() {
+ unsigned char buffer[digest_bytes];
+ unsigned olen = 0;
+ EVP_DigestFinal_ex(ctx, buffer, &olen);
+ assert(olen == digest_bytes);
+ return std::string((char *)buffer, olen);
+}
+
+typedef HashCtx SHA1;
+typedef HashCtx SHA256;
+typedef HashCtx SHA512;
+
+template
+std::size_t hash_str(unsigned char buffer[T::digest_bytes], const void *data, std::size_t size) {
+ T hasher(data, size);
+ return hasher.extract(buffer);
+}
+
+template
+std::size_t hash_two_str(unsigned char buffer[T::digest_bytes], const void *data1, std::size_t size1, const void *data2,
+ std::size_t size2) {
+ T hasher(data1, size1);
+ hasher.feed(data2, size2);
+ return hasher.extract(buffer);
+}
+
+template
+std::string hash_str(const void *data, std::size_t size) {
+ T hasher(data, size);
+ return hasher.extract();
+}
+
+template
+std::string hash_two_str(const void *data1, std::size_t size1, const void *data2, std::size_t size2) {
+ T hasher(data1, size1);
+ hasher.feed(data2, size2);
+ return hasher.extract();
+}
+} // namespace digest
diff --git a/crypto/smartcont/CreateState.fif b/crypto/smartcont/CreateState.fif
index c369df56..7497cb44 100644
--- a/crypto/smartcont/CreateState.fif
+++ b/crypto/smartcont/CreateState.fif
@@ -40,6 +40,9 @@
{ 8 config! } : config.version!
1 constant capIhr
2 constant capCreateStats
+4 constant capBounceMsgBody
+8 constant capReportVersion
+16 constant capSplitMergeTransactions
// max-validators masterchain-validators min-validators --
{ swap rot 16 config! } : config.validator_num!
@@ -54,21 +57,24 @@
variable validator-dict
dictnew 0 validator-dict 2!
+variable validators-weight
+validators-weight 0!
+
{ validator-dict @ second } : validator#
// val-pubkey weight --
{ dup 0<= abort"validator weight must be non-negative"
dup 64 ufits not abort"validator weight must fit into 64 bits"
over Blen 32 <> abort"validator public key must be 32 bytes long"
-
+ rot
34 config!
} : config.validators!
diff --git a/crypto/smartcont/config-code.fc b/crypto/smartcont/config-code.fc
index 5559ba27..612d8c93 100644
--- a/crypto/smartcont/config-code.fc
+++ b/crypto/smartcont/config-code.fc
@@ -91,7 +91,7 @@ _ get_vote_config(int critical?) inline_ref {
() after_code_upgrade(slice param, cont old_code) impure method_id(1666) {
}
-_ perform_action(cfg_dict, public_key, action, cs) {
+_ perform_action(cfg_dict, public_key, action, cs) inline_ref {
if (action == 0x43665021) {
;; change one configuration parameter
var param_index = cs~load_int(32);
@@ -166,6 +166,58 @@ _ perform_action(cfg_dict, public_key, action, cs) {
return (id, val, hash);
}
+(cell, int, cell) accept_proposal(cell cfg_dict, cell proposal, int critical?) inline_ref {
+ var (param_id, param_val, req_hash) = parse_config_proposal(proposal);
+ cell cur_val = cfg_dict.idict_get_ref(32, param_id);
+ int cur_hash = null?(cur_val) ? 0 : cell_hash(cur_val);
+ if ((cur_hash != req_hash) & (req_hash >= 0)) {
+ ;; current value has incorrect hash, do not apply changes
+ return (cfg_dict, 0, null());
+ }
+ cell mparams = cfg_dict.idict_get_ref(32, 9); ;; mandatory parameters
+ var (_, found?) = mparams.idict_get?(32, param_id);
+ if (found? & param_val.null?()) {
+ ;; cannot set a mandatory parameter to (null)
+ return (cfg_dict, 0, null());
+ }
+ cell cparams = cfg_dict.idict_get_ref(32, 10); ;; critical parameters
+ (_, found?) = cparams.idict_get?(32, param_id);
+ if (found? < critical?) {
+ ;; trying to set a critical parameter after a non-critical voting
+ return (cfg_dict, 0, null());
+ }
+ ;; CHANGE ONE CONFIGURATION PARAMETER (!)
+ cfg_dict~idict_set_ref(32, param_id, param_val);
+ return (cfg_dict, param_id, param_val);
+}
+
+(cell, int) perform_proposed_action(cell cfg_dict, int public_key, int param_id, cell param_val) inline_ref {
+ if (param_id == -999) {
+ ;; appoint or depose dictator
+ return (cfg_dict, param_val.null?() ? 0 : param_val.begin_parse().preload_uint(256));
+ }
+ if (param_val.null?()) {
+ return (cfg_dict, public_key);
+ }
+ if (param_id == -1000) {
+ ;; upgrade code
+ var cs = param_val.begin_parse();
+ var new_code = cs~load_ref();
+ set_code(new_code);
+ var old_code = get_c3();
+ set_c3(new_code.begin_parse().bless());
+ after_code_upgrade(cs, old_code);
+ throw(0);
+ return (cfg_dict, public_key);
+ }
+ if (param_id == -1001) {
+ ;; update elector code
+ var cs = param_val.begin_parse();
+ change_elector_code(cs);
+ }
+ return (cfg_dict, public_key);
+}
+
;; cfg_proposal_status#ce expires:uint32 proposal:^ConfigProposal is_critical:Bool
;; voters:(HashmapE 16 True) remaining_weight:int64 validator_set_id:uint256
;; rounds_remaining:uint8 wins:uint8 losses:uint8 = ConfigProposalStatus;
@@ -174,6 +226,26 @@ _ perform_action(cfg_dict, public_key, action, cs) {
return (cs~load_uint(32), cs~load_ref(), cs~load_int(1), cs~load_dict(), cs~load_int(64), cs~load_uint(256), cs);
}
+slice update_proposal_status(slice rest, int weight_remaining, int critical?) inline_ref {
+ var [min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _] = get_vote_config(critical?);
+ var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8));
+ losses -= (weight_remaining >= 0);
+ if (losses > max_losses) {
+ ;; lost too many times
+ return null();
+ }
+ rounds_remaining -= 1;
+ if (rounds_remaining < 0) {
+ ;; existed for too many rounds
+ return null();
+ }
+ return begin_cell()
+ .store_uint(rounds_remaining, 8)
+ .store_uint(losses, 8)
+ .store_uint(wins, 8)
+ .end_cell().begin_parse();
+}
+
builder begin_pack_proposal_status(int expires, cell proposal, int critical?, cell voters, int weight_remaining, int vset_id) inline {
return begin_cell()
.store_int(0xce - 0x100, 8)
@@ -185,54 +257,107 @@ builder begin_pack_proposal_status(int expires, cell proposal, int critical?, ce
.store_uint(vset_id, 256);
}
-(cell, int, int, slice) new_proposal(cs) inline {
- return (null(), 0, 0, cs);
-}
-
-(cell, int, int, slice) unpack_proposal(slice cs) inline {
- return (cs~load_dict(), cs~load_uint(64), cs~load_uint(256), cs);
-}
-
-builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inline {
- return begin_cell().store_dict(voters).store_uint(sum_weight, 64).store_uint(vset_id, 256).store_slice(body);
-}
-
-(cell, slice) register_vote(vote_dict, action, cs, idx, weight, total_weight, cur_vset_id) {
- int hash = 0;
- int found? = 0;
- var entry = null();
- if (action & 1) {
- hash = slice_hash(cs);
- (entry, found?) = vote_dict.udict_get?(256, hash);
- } else {
- hash = cs.preload_uint(256);
- (entry, found?) = vote_dict.udict_get?(256, hash);
- throw_unless(42, found?);
+(cell, cell, int) register_vote(vote_dict, phash, idx, weight) inline_ref {
+ var (pstatus, found?) = vote_dict.udict_get?(256, phash);
+ ifnot (found?) {
+ ;; config proposal not found
+ return (vote_dict, null(), false);
+ }
+ var (cur_vset, total_weight, _) = get_current_vset();
+ int cur_vset_id = cur_vset.cell_hash();
+ var (expires, proposal, critical?, voters, weight_remaining, vset_id, rest) = unpack_proposal_status(pstatus);
+ if (expires <= now()) {
+ ;; config proposal expired, delete and report not found
+ vote_dict~udict_delete?(256, phash);
+ return (vote_dict, null(), false);
}
- var (voters, sum_weight, vset_id, body) = found? ? unpack_proposal(entry) : (null(), 0, cur_vset_id, cs);
if (vset_id != cur_vset_id) {
- voters = null();
- sum_weight = 0;
+ ;; config proposal belongs to a previous validator set
vset_id = cur_vset_id;
+ rest = update_proposal_status(rest, weight_remaining, critical?);
+ voters = null();
+ weight_remaining = muldiv(total_weight, 3, 4);
+ }
+ if (rest.null?()) {
+ ;; discard proposal (existed for too many rounds, or too many losses)
+ vote_dict~udict_delete?(256, phash);
+ return (vote_dict, null(), false);
}
var (_, found?) = voters.udict_get?(16, idx);
- ifnot (found?) {
- voters~udict_set_builder(16, idx, begin_cell().store_uint(32, now()));
- sum_weight += weight;
- if (sum_weight * 3 > total_weight * 2) {
- ;; proposal accepted
- vote_dict~udict_delete?(256, hash);
- return (vote_dict, body);
- } else {
- vote_dict~udict_set_builder(256, hash, pack_proposal(voters, sum_weight, cur_vset_id, body));
- return (vote_dict, null());
- }
- } else {
- return (vote_dict, null());
+ if (found?) {
+ ;; already voted for this proposal, ignore vote
+ return (vote_dict, null(), false);
}
+ ;; register vote
+ voters~udict_set_builder(16, idx, begin_cell().store_uint(now(), 32));
+ int old_wr = weight_remaining;
+ weight_remaining -= weight;
+ if ((weight_remaining ^ old_wr) >= 0) {
+ ;; not enough votes, or proposal already accepted in this round
+ ;; simply update weight_remaining
+ vote_dict~udict_set_builder(256, phash, begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id).store_slice(rest));
+ return (vote_dict, null(), false);
+ }
+ ;; proposal wins in this round
+ var [min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _] = get_vote_config(critical?);
+ var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8));
+ wins += 1;
+ if (wins >= min_wins) {
+ ;; proposal is accepted, remove and process
+ vote_dict~udict_delete?(256, phash);
+ return (vote_dict, proposal, critical?);
+ }
+ ;; update proposal info
+ vote_dict~udict_set_builder(256, phash,
+ begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id)
+ .store_uint(rounds_remaining, 8)
+ .store_uint(wins, 8)
+ .store_uint(losses, 8));
+ return (vote_dict, null(), false);
}
-int register_voting_proposal(slice cs, int msg_value) inline_ref {
+(slice, int) scan_proposal(int phash, slice pstatus) inline_ref {
+ var (cur_vset, total_weight, _) = get_current_vset();
+ int cur_vset_id = cur_vset.cell_hash();
+ var (expires, proposal, critical?, voters, weight_remaining, vset_id, rest) = unpack_proposal_status(pstatus);
+ if (expires <= now()) {
+ ;; config proposal expired, delete
+ return (null(), true);
+ }
+ if (vset_id == cur_vset_id) {
+ ;; config proposal already processed or voted for in this round, change nothing
+ return (pstatus, false);
+ }
+ ;; config proposal belongs to a previous validator set
+ vset_id = cur_vset_id;
+ rest = update_proposal_status(rest, weight_remaining, critical?);
+ voters = null();
+ weight_remaining = muldiv(total_weight, 3, 4);
+ if (rest.null?()) {
+ ;; discard proposal (existed for too many rounds, or too many losses)
+ return (null(), true);
+ }
+ ;; return updated proposal
+ return (begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id).store_slice(rest).end_cell().begin_parse(), true);
+}
+
+cell scan_random_proposal(cell vote_dict) inline_ref {
+ var (phash, pstatus, found?) = vote_dict.udict_get_nexteq?(256, random());
+ ifnot (found?) {
+ return vote_dict;
+ }
+ (pstatus, var changed?) = scan_proposal(phash, pstatus);
+ if (changed?) {
+ if (pstatus.null?()) {
+ vote_dict~udict_delete?(256, phash);
+ } else {
+ vote_dict~udict_set(256, phash, pstatus);
+ }
+ }
+ return vote_dict;
+}
+
+int register_voting_proposal(slice cs, int msg_value) impure inline_ref {
var (expire_at, proposal, critical?) = (cs~load_uint(32), cs~load_ref(), cs~load_int(1));
if (expire_at >> 30) {
expire_at -= now();
@@ -306,7 +431,7 @@ int register_voting_proposal(slice cs, int msg_value) inline_ref {
}
;; obtain current validator set data
var (vset, total_weight, _) = get_current_vset();
- int weight_remaining = muldiv(total_weight, 2, 3) + 1;
+ int weight_remaining = muldiv(total_weight, 3, 4);
;; create new proposal
vote_dict~udict_set_builder(256, phash,
begin_pack_proposal_status(expire_at, proposal, critical?, null(), weight_remaining, vset.cell_hash())
@@ -374,27 +499,32 @@ int register_voting_proposal(slice cs, int msg_value) inline_ref {
int msg_seqno = cs~load_uint(32);
var valid_until = cs~load_uint(32);
throw_if(35, valid_until < now());
- throw_if(39, slice_depth(cs) > 64);
+ throw_if(39, slice_depth(cs) > 128);
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
- throw_unless(33, msg_seqno == stored_seqno);
- ifnot ((action - 0x566f7465) & -2) {
- var idx = cs~load_uint(16);
+ if (action == 0x566f7465) {
+ var (idx, phash) = (cs~load_uint(16), cs~load_uint(256));
+ cs.end_parse();
var (vdescr, total_weight) = get_validator_descr(idx);
var (val_pubkey, weight) = unpack_validator_descr(vdescr);
- throw_unless(34, check_signature(slice_hash(in_msg), signature, val_pubkey));
+ throw_unless(34, check_data_signature(in_msg, signature, val_pubkey));
accept_message();
stored_seqno += 1;
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
commit();
- var (_, bits, refs) = cs.slice_compute_data_size(1024);
- (vote_dict, var accepted) = register_vote(vote_dict, action, cs, idx, weight, total_weight, config_param(34).cell_hash());
+ (vote_dict, var accepted_proposal, var critical?) = register_vote(vote_dict, phash, idx, weight);
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
- ifnot (accepted.null?()) {
- (cfg_dict, public_key) = perform_action(cfg_dict, public_key, accepted~load_uint(32), accepted);
+ ifnot (accepted_proposal.null?()) {
+ (cfg_dict, var param_id, var param_val) = accept_proposal(cfg_dict, accepted_proposal, critical?);
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
+ if (param_id) {
+ commit();
+ (cfg_dict, public_key) = perform_proposed_action(cfg_dict, public_key, param_id, param_val);
+ store_data(cfg_dict, stored_seqno, public_key, vote_dict);
+ }
}
return ();
}
+ throw_unless(33, msg_seqno == stored_seqno);
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
accept_message();
stored_seqno += 1;
@@ -405,11 +535,10 @@ int register_voting_proposal(slice cs, int msg_value) inline_ref {
}
() run_ticktock(int is_tock) impure {
- var cs = begin_parse(get_data());
- var cfg_dict = cs~load_ref();
+ var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
int kl = 32;
- ;; cfg_dict~idict_set_ref(kl, -17, begin_cell().store_uint(now() >> 16, 32).end_cell());
var next_vset = cfg_dict.idict_get_ref(kl, 36);
+ var updated? = false;
ifnot (next_vset.null?()) {
;; check whether we have to set next_vset as the current validator set
var ds = next_vset.begin_parse();
@@ -421,12 +550,56 @@ int register_voting_proposal(slice cs, int msg_value) inline_ref {
var cur_vset = cfg_dict~idict_set_get_ref(kl, 34, next_vset); ;; next_vset -> cur_vset
cfg_dict~idict_set_get_ref(kl, 32, cur_vset); ;; cur_vset -> prev_vset
cfg_dict~idict_delete?(kl, 36); ;; (null) -> next_vset
+ updated? = true;
}
}
}
- set_data(begin_cell().store_ref(cfg_dict).store_slice(cs).end_cell());
+ ifnot (updated?) {
+ ;; if nothing has been done so far, scan a random voting proposal instead
+ vote_dict = scan_random_proposal(vote_dict);
+ }
+ ;; save data and return
+ return store_data(cfg_dict, stored_seqno, public_key, vote_dict);
}
-int seqno() impure method_id {
+int seqno() method_id {
return get_data().begin_parse().preload_uint(32);
}
+
+_ unpack_proposal(slice pstatus) inline_ref {
+ (int expires, cell proposal, int critical?, cell voters, int weight_remaining, int vset_id, slice rest) = unpack_proposal_status(pstatus);
+ var voters_list = null();
+ var voter_id = (1 << 32);
+ do {
+ (voter_id, _, var f) = voters.udict_get_prev?(16, voter_id);
+ if (f) {
+ voters_list = cons(voter_id, voters_list);
+ }
+ } until (~ f);
+ var (rounds_remaining, losses, wins) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8));
+ rest.end_parse();
+ var (param_id, param_val, param_hash) = parse_config_proposal(proposal);
+ return [expires, critical?, [param_id, param_val, param_hash], vset_id, voters_list, weight_remaining, rounds_remaining, losses, wins];
+}
+
+_ get_proposal(int phash) method_id {
+ (_, _, _, var vote_dict) = load_data();
+ var (pstatus, found?) = vote_dict.udict_get?(256, phash);
+ ifnot (found?) {
+ return null();
+ }
+ return unpack_proposal(pstatus);
+}
+
+_ list_proposals() method_id {
+ (_, _, _, var vote_dict) = load_data();
+ var phash = (1 << 255) + ((1 << 255) - 1);
+ var list = null();
+ do {
+ (phash, var pstatus, var f) = vote_dict.udict_get_prev?(256, phash);
+ if (f) {
+ list = cons([phash, unpack_proposal(pstatus)], list);
+ }
+ } until (~ f);
+ return list;
+}
diff --git a/crypto/smartcont/config-proposal-vote-req.fif b/crypto/smartcont/config-proposal-vote-req.fif
new file mode 100644
index 00000000..654a6064
--- /dev/null
+++ b/crypto/smartcont/config-proposal-vote-req.fif
@@ -0,0 +1,33 @@
+#!/usr/bin/fift -s
+"TonUtil.fif" include
+"GetOpt.fif" include
+
+"validator-to-sign.req" =: savefile
+
+{ ."usage: " @' $0 type ." []" cr
+ ."Creates an unsigned request expiring at unixtime to vote for configuration proposal (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index in current validator set (as stored in configuration parameter 34)" cr
+ ."The result is saved into (" savefile type ." by default) and output in hexadecimal form, to be signed later by the validator public key" cr 1 halt
+} : usage
+
+$# dup 3 < swap 4 > or ' usage if
+4 :$1..n
+
+$1 parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if
+ dup =: expire-at
+ dup now <= abort"expiration time must be in the future"
+ 32 ufits not abort"invalid expiration time"
+$2 parse-int dup =: val-idx
+ 16 ufits not abort"validator index out of range"
+$3 parse-int dup =: prop-hash
+ 256 ufits not abort"invalid proposal hash"
+$4 savefile replace-if-null =: savefile
+0 =: seqno
+
+."Creating a request expiring at " expire-at .
+."to vote for configuration proposal 0x" prop-hash 64x.
+."on behalf of validator with index " val-idx . cr
+
+B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+ val-idx 16 u>B B+ prop-hash 256 u>B B+
+dup Bx. cr
+dup B>base64url type cr
+savefile tuck B>file ."Saved to file " type cr
diff --git a/crypto/smartcont/config-proposal-vote-signed.fif b/crypto/smartcont/config-proposal-vote-signed.fif
new file mode 100644
index 00000000..38f1eff4
--- /dev/null
+++ b/crypto/smartcont/config-proposal-vote-signed.fif
@@ -0,0 +1,51 @@
+#!/usr/bin/fift -s
+"TonUtil.fif" include
+"GetOpt.fif" include
+
+"vote-query.boc" =: savefile
+
+{ ."usage: " @' $0 type ." []" cr
+ ."Creates an external message addressed to the configuration smart contract containing a signed request expiring at unixtime to vote for configuration proposal (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index and (Base64) public key in current validator set (as stored in configuration parameter 34)" cr
+ ." must be the base64 representation of Ed25519 signature of the previously generated unsigned request by means of " cr
+ ."The result is saved into (" savefile type ." by default), to be sent later by the lite-client" cr 1 halt
+} : usage
+
+$# dup 6 < swap 7 > or ' usage if
+7 :$1..n
+
+$1 true parse-load-address drop over 1+ abort"configuration smart contract must be in masterchain"
+ 2=: config-addr
+$2 parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if
+ dup =: expire-at
+ dup now <= abort"expiration time must be in the future"
+ 32 ufits not abort"invalid expiration time"
+$3 parse-int dup =: val-idx
+ 16 ufits not abort"validator index out of range"
+$4 parse-int dup =: prop-hash
+ 256 ufits not abort"invalid proposal hash"
+$5 base64>B dup Blen 36 <> abort"validator Ed25519 public key must be exactly 36 bytes long"
+ 32 B>u@+ 0xC6B41348 <> abort"invalid Ed25519 public key: unknown magic number"
+ =: pubkey
+$6 base64>B dup Blen 64 <> abort"validator Ed25519 signature must be exactly 64 bytes long"
+ =: signature
+$7 savefile replace-if-null =: savefile
+0 =: seqno
+
+."Creating an external message to configuration smart contract "
+config-addr 2dup 6 .Addr ." = " .addr cr
+."containing a signed request expiring at " expire-at .
+."to vote for configuration proposal 0x" prop-hash 64x.
+."on behalf of validator with index " val-idx . "and public key" pubkey 64x. cr
+
+B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+ val-idx 16 u>B B+ prop-hash 256 u>B B+
+dup =: to_sign
+."String to sign is " Bx. cr
+
+to_sign signature pubkey ed25519_chksign not abort"Ed25519 signature is invalid"
+."Provided a valid Ed25519 signature " signature Bx. ." with validator public key " pubkey Bx. cr
+
+
+cr ."External message is " dup B savefile tuck B>file ."Saved to file " type cr
diff --git a/crypto/smartcont/create-config-proposal.fif b/crypto/smartcont/create-config-proposal.fif
new file mode 100644
index 00000000..427f2f25
--- /dev/null
+++ b/crypto/smartcont/create-config-proposal.fif
@@ -0,0 +1,63 @@
+#!/usr/bin/fift -s
+"TonUtil.fif" include
+"GetOpt.fif" include
+
+{ show-options-help 1 halt } : usage
+86400 30 * =: expire-in
+false =: critical
+-1 =: old-hash
+
+begin-options
+ " [-x ] [-c] [-H ] []" +cr +tab
+ +"Creates a new configuration proposal for setting configuration parameter to (`null` means no new value), "
+ +"and saves it as an internal message body into .boc ('config-msg-body.boc' by default)"
+ disable-digit-options generic-help-setopt
+ "c" "--critical" { true =: critical } short-long-option
+ "Creates a critical parameter change proposal" option-help
+ "x" "--expires-in" { parse-int =: expire-in } short-long-option-arg
+ "Sets proposal expiration time in seconds (default " expire-in (.) $+ +")" option-help
+ "H" "--old-hash" { (hex-number) not abort"256-bit hex number expected as hash" =: old-hash }
+ short-long-option-arg
+ "Sets the required cell hash of existing parameter value (0 means no value)" option-help
+ "h" "--help" { usage } short-long-option
+ "Shows a help message" option-help
+parse-options
+
+$# dup 2 < swap 3 > or ' usage if
+3 :$1..n
+
+$1 parse-int dup =: param-idx
+ 32 fits not abort"parameter index out of range"
+$2 =: boc-filename
+$3 "config-msg-body.boc" replace-if-null =: savefile
+expire-in now + =: expire-at
+
+boc-filename dup "null" $= {
+ ."New value of configuration parameter" param-idx . ."is null" cr drop null
+} {
+ ."Loading new value of configuration parameter " param-idx . ."from file " dup type cr
+ boc-filename file>B B>boc
+ dup = tuck 1 i, -rot { 256 u, } { drop } cond b> ref,
+ critical 1 i, b>
+
+dup ."resulting internal message body: " B dup Bx. cr
+savefile tuck B>file
+."(Saved to file " type .")" cr
diff --git a/crypto/smartcont/gen-zerostate.fif b/crypto/smartcont/gen-zerostate.fif
index 8fc00c32..eb0902fa 100644
--- a/crypto/smartcont/gen-zerostate.fif
+++ b/crypto/smartcont/gen-zerostate.fif
@@ -157,7 +157,7 @@ Masterchain swap
*
*/
// version capabilities
-0 capCreateStats config.version!
+1 capCreateStats capBounceMsgBody or capReportVersion or config.version!
// max-validators max-main-validators min-validators
// 9 4 1 config.validator_num!
1000 100 13 config.validator_num!
@@ -202,12 +202,12 @@ smc1_addr config.minter_smc!
1000000000000 -17 of-cc 666666666666 239 of-cc cc+ config.to_mint!
( 0 1 9 10 12 14 15 16 17 18 20 21 22 23 24 25 28 34 ) config.mandatory_params!
-( -1000 -1001 0 1 9 10 12 14 15 16 17 32 34 36 ) config.critical_params!
+( -999 -1000 -1001 0 1 9 10 12 14 15 16 17 32 34 36 ) config.critical_params!
-// [ min_tot_rounds max_tot_rounds min_wins max_losses min_store_sec max_store_sec bit_price cell_price ]
+// [ min_tot_rounds max_tot_rounds min_wins max_losses min_store_sec max_store_sec bit_pps cell_pps ]
// first for ordinary proposals, then for critical proposals
-_( 2 3 2 2 1000000 10000000 GR$.001 GR$.2 )
-_( 4 7 4 2 5000000 20000000 GR$.002 GR$.8 )
+_( 2 3 2 2 1000000 10000000 1 500 )
+_( 4 7 4 2 5000000 20000000 2 1000 )
config.param_proposals_setup!
"validator-keys" +suffix +".pub" file>B
diff --git a/crypto/smc-envelope/HighloadWallet.cpp b/crypto/smc-envelope/HighloadWallet.cpp
index faf08950..af529a1b 100644
--- a/crypto/smc-envelope/HighloadWallet.cpp
+++ b/crypto/smc-envelope/HighloadWallet.cpp
@@ -27,9 +27,26 @@
#include
namespace ton {
-td::Ref HighloadWallet::get_init_state(const td::Ed25519::PublicKey& public_key,
- td::uint32 wallet_id) noexcept {
- auto code = get_init_code();
+td::optional HighloadWallet::guess_revision(const vm::Cell::Hash& code_hash) {
+ for (td::int32 i = 1; i <= 2; i++) {
+ if (get_init_code(i)->get_hash() == code_hash) {
+ return i;
+ }
+ }
+ return {};
+}
+td::optional HighloadWallet::guess_revision(const block::StdAddress& address,
+ const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) {
+ for (td::int32 i = 1; i <= 2; i++) {
+ if (GenericAccount::get_address(address.workchain, get_init_state(public_key, wallet_id, i)) == address) {
+ return i;
+ }
+ }
+ return {};
+}
+td::Ref HighloadWallet::get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id,
+ td::int32 revision) noexcept {
+ auto code = get_init_code(revision);
auto data = get_init_data(public_key, wallet_id);
return GenericAccount::get_init_state(std::move(code), std::move(data));
}
@@ -80,12 +97,12 @@ td::Ref HighloadWallet::make_a_gift_message(const td::Ed25519::Private
return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize();
}
-td::Ref HighloadWallet::get_init_code() noexcept {
- return SmartContractCode::get_code(SmartContractCode::HighloadWalletV1);
+td::Ref HighloadWallet::get_init_code(td::int32 revision) noexcept {
+ return SmartContractCode::get_code(SmartContractCode::HighloadWalletV1, revision);
}
vm::CellHash HighloadWallet::get_init_code_hash() noexcept {
- return get_init_code()->get_hash();
+ return get_init_code(0)->get_hash();
}
td::Ref HighloadWallet::get_init_data(const td::Ed25519::PublicKey& public_key,
diff --git a/crypto/smc-envelope/HighloadWallet.h b/crypto/smc-envelope/HighloadWallet.h
index 68d3fe43..ce37af49 100644
--- a/crypto/smc-envelope/HighloadWallet.h
+++ b/crypto/smc-envelope/HighloadWallet.h
@@ -32,15 +32,18 @@ class HighloadWallet : public ton::SmartContract, public WalletInterface {
}
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
static constexpr unsigned max_gifts_size = 254;
- static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
+ static td::Ref get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id,
+ td::int32 revision) noexcept;
static td::Ref get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id) noexcept;
static td::Ref make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id,
td::uint32 seqno, td::uint32 valid_until, td::Span gifts) noexcept;
- static td::Ref get_init_code() noexcept;
+ static td::Ref get_init_code(td::int32 revision) noexcept;
static vm::CellHash get_init_code_hash() noexcept;
static td::Ref get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
-
+ static td::optional guess_revision(const vm::Cell::Hash& code_hash);
+ static td::optional guess_revision(const block::StdAddress& address,
+ const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id);
td::Result get_seqno() const;
td::Result get_wallet_id() const;
diff --git a/crypto/smc-envelope/SmartContractCode.cpp b/crypto/smc-envelope/SmartContractCode.cpp
index 6256dcc0..27bf58ab 100644
--- a/crypto/smc-envelope/SmartContractCode.cpp
+++ b/crypto/smc-envelope/SmartContractCode.cpp
@@ -103,6 +103,7 @@ const auto& get_map() {
} // namespace
td::Result> SmartContractCode::load(td::Slice name) {
+ LOG(ERROR) << "LOAD " << name;
auto& map = get_map();
auto it = map.find(name);
if (it == map.end()) {
diff --git a/crypto/test/test-cells.cpp b/crypto/test/test-cells.cpp
index bda9caa6..327f73c6 100644
--- a/crypto/test/test-cells.cpp
+++ b/crypto/test/test-cells.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include
#include
@@ -580,7 +580,7 @@ bool check_exp(std::ostream& stream, const td::NegExpBinTable& tab, double x) {
}
double y = yy.to_double() * exp2(-252);
double y0 = exp(x);
- bool ok = (abs(y - y0) < 1e-15);
+ bool ok = (fabs(y - y0) < 1e-15);
if (!ok) {
stream << "exp(" << x << ") = exp(" << xx << " * 2^(-52)) = " << yy << " / 2^252 = " << y << " (correct value is "
<< y0 << ") " << (ok ? "match" : "incorrect") << std::endl;
diff --git a/crypto/test/test-db.cpp b/crypto/test/test-db.cpp
index 411e0c77..f143ca0a 100644
--- a/crypto/test/test-db.cpp
+++ b/crypto/test/test-db.cpp
@@ -52,6 +52,8 @@
#include
+#include "openssl/digest.hpp"
+
namespace vm {
std::vector do_get_serialization_modes() {
diff --git a/crypto/test/test-smartcont.cpp b/crypto/test/test-smartcont.cpp
index 08b19a05..5048bb28 100644
--- a/crypto/test/test-smartcont.cpp
+++ b/crypto/test/test-smartcont.cpp
@@ -331,11 +331,12 @@ TEST(Tonlib, HighloadWallet) {
td::Ed25519::PrivateKey priv_key{td::SecureString{new_wallet_pk}};
auto pub_key = priv_key.get_public_key().move_as_ok();
- auto init_state = ton::HighloadWallet::get_init_state(pub_key, 239);
+ auto init_state = ton::HighloadWallet::get_init_state(pub_key, 239, -1);
auto init_message = ton::HighloadWallet::get_init_message(priv_key, 239);
auto address = ton::GenericAccount::get_address(0, init_state);
- ton::HighloadWallet wallet({ton::HighloadWallet::get_init_code(), ton::HighloadWallet::get_init_data(pub_key, 239)});
+ ton::HighloadWallet wallet(
+ {ton::HighloadWallet::get_init_code(-1), ton::HighloadWallet::get_init_data(pub_key, 239)});
ASSERT_EQ(239u, wallet.get_wallet_id().ok());
ASSERT_EQ(0u, wallet.get_seqno().ok());
CHECK(pub_key.as_octet_string() == wallet.get_public_key().ok().as_octet_string());
diff --git a/crypto/vm/cells.h b/crypto/vm/cells.h
index ea362597..cf917eff 100644
--- a/crypto/vm/cells.h
+++ b/crypto/vm/cells.h
@@ -14,26 +14,16 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
-#include
-#include "common/refcnt.hpp"
-#include "common/bitstring.h"
-#include "common/bigint.hpp"
-#include "common/refint.h"
-
#include "vm/cells/Cell.h"
#include "vm/cells/CellBuilder.h"
#include "vm/cells/DataCell.h"
#include "vm/cells/UsageCell.h"
#include "vm/cells/VirtualCell.h"
-#include "td/utils/Slice.h"
-#include "td/utils/StringBuilder.h"
-#include "openssl/digest.h"
-
// H_i(cell) = H(cell_i)
// cell.hash = sha256(
// d1, d2,
diff --git a/crypto/vm/cells/CellBuilder.cpp b/crypto/vm/cells/CellBuilder.cpp
index dc7f5eb8..481c2581 100644
--- a/crypto/vm/cells/CellBuilder.cpp
+++ b/crypto/vm/cells/CellBuilder.cpp
@@ -24,7 +24,7 @@
#include "td/utils/misc.h"
#include "td/utils/format.h"
-#include "openssl/digest.h"
+#include "openssl/digest.hpp"
namespace vm {
diff --git a/crypto/vm/cells/DataCell.cpp b/crypto/vm/cells/DataCell.cpp
index 4a89a276..cccb11dc 100644
--- a/crypto/vm/cells/DataCell.cpp
+++ b/crypto/vm/cells/DataCell.cpp
@@ -14,11 +14,11 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "vm/cells/DataCell.h"
-#include "openssl/digest.h"
+#include "openssl/digest.hpp"
#include "td/utils/ScopeGuard.h"
diff --git a/crypto/vm/tonops.cpp b/crypto/vm/tonops.cpp
index ca8e4b00..88d8fda9 100644
--- a/crypto/vm/tonops.cpp
+++ b/crypto/vm/tonops.cpp
@@ -26,6 +26,8 @@
#include "vm/dict.h"
#include "Ed25519.h"
+#include "openssl/digest.hpp"
+
namespace vm {
namespace {
diff --git a/tddb/test/key_value.cpp b/tddb/test/key_value.cpp
index c7d3c8f3..e04e7ee9 100644
--- a/tddb/test/key_value.cpp
+++ b/tddb/test/key_value.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/tests.h"
diff --git a/tdutils/td/utils/BigNum.cpp b/tdutils/td/utils/BigNum.cpp
index 66a51187..49b44899 100644
--- a/tdutils/td/utils/BigNum.cpp
+++ b/tdutils/td/utils/BigNum.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/BigNum.h"
@@ -98,7 +98,7 @@ BigNum BigNum::from_binary(Slice str) {
}
BigNum BigNum::from_le_binary(Slice str) {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
return BigNum(make_unique(BN_lebin2bn(str.ubegin(), narrow_cast(str.size()), nullptr)));
#else
LOG(FATAL) << "Unsupported from_le_binary";
@@ -132,7 +132,11 @@ BigNum::BigNum(unique_ptr &&impl) : impl_(std::move(impl)) {
}
void BigNum::ensure_const_time() {
+#if !defined(OPENSSL_IS_BORINGSSL)
BN_set_flags(impl_->big_num, BN_FLG_CONSTTIME);
+#else
+ LOG(FATAL) << "Unsupported BN_FLG_CONSTTIME";
+#endif
}
int BigNum::get_num_bits() const {
@@ -217,7 +221,7 @@ string BigNum::to_binary(int exact_size) const {
}
string BigNum::to_le_binary(int exact_size) const {
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
int num_size = get_num_bytes();
if (exact_size == -1) {
exact_size = num_size;
diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp
index d8a0d7b6..02bc4fcf 100644
--- a/tdutils/td/utils/crypto.cpp
+++ b/tdutils/td/utils/crypto.cpp
@@ -253,6 +253,13 @@ int pq_factorize(Slice pq_str, string *p_str, string *q_str) {
return 0;
}
+#ifdef OPENSSL_IS_BORINGSSL
+extern "C" {
+void AES_ige_encrypt(const unsigned char *in_ptr, unsigned char *out, size_t length, const AES_KEY *key,
+ unsigned char *ivec, const int enc);
+}
+#endif
+
static void aes_ige_xcrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlice to, bool encrypt_flag) {
CHECK(aes_key.size() == 32);
CHECK(aes_iv.size() == 16);
diff --git a/tdutils/test/ConcurrentHashMap.cpp b/tdutils/test/ConcurrentHashMap.cpp
index ba52105d..baceae6a 100644
--- a/tdutils/test/ConcurrentHashMap.cpp
+++ b/tdutils/test/ConcurrentHashMap.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/benchmark.h"
#include "td/utils/ConcurrentHashTable.h"
@@ -263,4 +263,4 @@ TEST(ConcurrentHashMap, Benchmark) {
#endif
}
-#endif
\ No newline at end of file
+#endif
diff --git a/test/test-adnl.cpp b/test/test-adnl.cpp
index 14fd92c2..d9ae4abe 100644
--- a/test/test-adnl.cpp
+++ b/test/test-adnl.cpp
@@ -50,6 +50,8 @@ int main() {
CHECK(id.serialize() == td::to_lower(id_str));
}
+ td::to_integer_safe("0").ensure();
+
std::string db_root_ = "tmp-ee";
td::rmrf(db_root_).ignore();
td::mkdir(db_root_).ensure();
diff --git a/tonlib/test/offline.cpp b/tonlib/test/offline.cpp
index 799c246f..2c35d934 100644
--- a/tonlib/test/offline.cpp
+++ b/tonlib/test/offline.cpp
@@ -566,6 +566,7 @@ TEST(Tonlib, ConfigCache) {
using tonlib_api::make_object;
Client client;
+ td::rmrf("testdir").ignore();
td::mkdir("testdir").ignore();
// init
sync_send(client, make_object(make_object(
@@ -595,8 +596,8 @@ TEST(Tonlib, ConfigCache) {
"workchain": -1,
"shard": -9223372036854775808,
"seqno": 0,
- "root_hash": "VXSXxDHhTALFxReyTZRd8E4Ya3ySOmpOWAS4rBX9XBY=",
- "file_hash": "eh9yveSz1qMdJ7mOsO+I+H77jkLr9NpAuEkoJuseXBo="
+ "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=",
+ "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24="
}
}
})abc";
diff --git a/tonlib/tonlib/TonlibClient.cpp b/tonlib/tonlib/TonlibClient.cpp
index d9dc0660..532cc73f 100644
--- a/tonlib/tonlib/TonlibClient.cpp
+++ b/tonlib/tonlib/TonlibClient.cpp
@@ -412,6 +412,14 @@ class AccountState {
{ton::HighloadWalletV2::get_init_code(wallet_revision_), ton::WalletV3::get_init_data(key, wallet_id_)});
return wallet_type_;
}
+ o_revision = ton::HighloadWallet::guess_revision(address_, key, wallet_id_);
+ if (o_revision) {
+ wallet_type_ = WalletType::HighloadWalletV1;
+ wallet_revision_ = o_revision.value();
+ set_new_state(
+ {ton::HighloadWallet::get_init_code(wallet_revision_), ton::WalletV3::get_init_data(key, wallet_id_)});
+ return wallet_type_;
+ }
o_revision = ton::ManualDns::guess_revision(address_, key, wallet_id_);
if (o_revision) {
wallet_type_ = WalletType::ManualDns;
@@ -428,11 +436,6 @@ class AccountState {
address_.addr) {
set_new_state({ton::Wallet::get_init_code(), ton::Wallet::get_init_data(key)});
wallet_type_ = WalletType::Wallet;
- } else if (ton::GenericAccount::get_address(address_.workchain,
- ton::HighloadWallet::get_init_state(key, wallet_id_))
- .addr == address_.addr) {
- set_new_state({ton::HighloadWallet::get_init_code(), ton::HighloadWallet::get_init_data(key, wallet_id_)});
- wallet_type_ = WalletType::HighloadWalletV1;
}
return wallet_type_;
}
@@ -494,6 +497,12 @@ class AccountState {
wallet_revision_ = o_revision.value();
return wallet_type_;
}
+ o_revision = ton::HighloadWallet::guess_revision(code_hash);
+ if (o_revision) {
+ wallet_type_ = WalletType::HighloadWalletV1;
+ wallet_revision_ = o_revision.value();
+ return wallet_type_;
+ }
o_revision = ton::ManualDns::guess_revision(code_hash);
if (o_revision) {
wallet_type_ = WalletType::ManualDns;
@@ -1438,7 +1447,8 @@ td::Result get_account_address(
TRY_RESULT(key_bytes, get_public_key(test_wallet_state.public_key_));
auto key = td::Ed25519::PublicKey(td::SecureString(key_bytes.key));
return ton::GenericAccount::get_address(
- 0 /*zerochain*/, ton::HighloadWallet::get_init_state(key, static_cast(test_wallet_state.wallet_id_)));
+ 0 /*zerochain*/,
+ ton::HighloadWallet::get_init_state(key, static_cast(test_wallet_state.wallet_id_), revision));
}
td::Result get_account_address(
@@ -1688,6 +1698,29 @@ const MasterConfig& get_default_master_config() {
"init_block":
{"workchain":-1,"shard":-9223372036854775808,"seqno":870721,"root_hash":"jYKhSQ1xeSPprzgjqiUOnAWwc2yqs7nCVAU21k922s4=","file_hash":"kHidF02CZpaz2ia9jtXUJLp0AiWMWwfzprTUIsddHSo="}
}
+})abc");
+ res.add_config("testnet2", R"abc({
+ "liteservers": [
+ {
+ "ip": 1137658550,
+ "port": 4924,
+ "id": {
+ "@type": "pub.ed25519",
+ "key": "peJTw/arlRfssgTuf9BMypJzqOi7SXEqSPSWiEw2U1M="
+ }
+ }
+ ],
+ "validator": {
+ "@type": "validator.config.global",
+ "zero_state": {
+ "workchain": -1,
+ "shard": -9223372036854775808,
+ "seqno": 0,
+ "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=",
+ "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24="
+ },
+ "init_block": {"workchain":-1,"shard":-9223372036854775808,"seqno":2908451,"root_hash":"5+7X1QHVUBFLFMwa/yd/2fGzt2KeQtwr+o6UUFOQ7Qc=","file_hash":"gmiUgrtAbvEJZYDEkcbeNOhGPS3g+qCepSOEBFLZFzk="}
+ }
})abc");
return res;
}();
diff --git a/validator/manager.cpp b/validator/manager.cpp
index cad63baf..f4829b97 100644
--- a/validator/manager.cpp
+++ b/validator/manager.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#include "manager.hpp"
#include "validator-group.hpp"
@@ -1413,6 +1413,9 @@ void ValidatorManagerImpl::start_up() {
}
fname = fname.substr(8);
+ while (fname.size() > 1 && fname[0] == '0') {
+ fname.remove_prefix(1);
+ }
auto v = td::to_integer_safe(fname);
if (v.is_error()) {
return;
@@ -1486,6 +1489,10 @@ bool ValidatorManagerImpl::out_of_sync() {
return false;
}
+ if (last_masterchain_seqno_ < last_known_key_block_handle_->id().seqno()) {
+ return true;
+ }
+
if (validator_groups_.size() > 0 && last_known_key_block_handle_->id().seqno() <= last_masterchain_seqno_) {
return false;
}
@@ -1510,7 +1517,7 @@ void ValidatorManagerImpl::download_next_archive() {
}
auto seqno = std::min(last_masterchain_seqno_, shard_client_handle_->id().seqno());
- auto it = to_import_.upper_bound(seqno);
+ auto it = to_import_.upper_bound(seqno + 1);
if (it != to_import_.begin()) {
it--;
if (it->second.second) {
@@ -1715,12 +1722,12 @@ void ValidatorManagerImpl::update_shards() {
// DIRTY. But we don't want to create hardfork now
// TODO! DELETE IT LATER
- if (last_masterchain_seqno_ >= 2904932 && val_set->get_catchain_seqno() == 44896) {
- if (opts_->zero_block_id().file_hash.to_hex() ==
- "5E994FCF4D425C0A6CE6A792594B7173205F740A39CD56F537DEFD28B48A0F6E") {
- val_group_id[0] = !val_group_id[0];
- }
- }
+ //if (last_masterchain_seqno_ >= 2904932 && val_set->get_catchain_seqno() == 44896) {
+ // if (opts_->zero_block_id().file_hash.to_hex() ==
+ // "5E994FCF4D425C0A6CE6A792594B7173205F740A39CD56F537DEFD28B48A0F6E") {
+ // val_group_id[0] = !val_group_id[0];
+ // }
+ //}
VLOG(VALIDATOR_DEBUG) << "validating group " << val_group_id;
auto it = validator_groups_.find(val_group_id);
@@ -2214,6 +2221,10 @@ void ValidatorManagerImpl::try_get_static_file(FileHash file_hash, td::Promise promise) {
+ if (masterchain_seqno > last_masterchain_seqno_) {
+ promise.set_error(td::Status::Error(ErrorCode::notready, "masterchain seqno too big"));
+ return;
+ }
td::actor::send_closure(db_, &Db::get_archive_id, masterchain_seqno, std::move(promise));
}
diff --git a/validator/manager.hpp b/validator/manager.hpp
index de788081..fdb53670 100644
--- a/validator/manager.hpp
+++ b/validator/manager.hpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see .
- Copyright 2017-2019 Telegram Systems LLP
+ Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
diff --git a/validator/validator-group.cpp b/validator/validator-group.cpp
index 9643b487..ca5fa065 100644
--- a/validator/validator-group.cpp
+++ b/validator/validator-group.cpp
@@ -20,6 +20,7 @@
#include "fabric.h"
#include "ton/ton-io.hpp"
#include "td/utils/overloaded.h"
+#include "common/delay.h"
namespace ton {
@@ -50,8 +51,12 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat
if (S.code() != ErrorCode::timeout && S.code() != ErrorCode::notready) {
LOG(ERROR) << "failed to validate candidate: " << S;
}
- td::actor::send_closure(SelfId, &ValidatorGroup::validate_block_candidate, round_id, std::move(block),
- std::move(promise));
+ delay_action(
+ [SelfId, round_id, block = std::move(block), promise = std::move(promise)]() mutable {
+ td::actor::send_closure(SelfId, &ValidatorGroup::validate_block_candidate, round_id, std::move(block),
+ std::move(promise));
+ },
+ td::Timestamp::in(0.1));
} else {
auto v = R.move_as_ok();
v.visit(td::overloaded([&](UnixTime ts) { promise.set_result(ts); },