1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

bugfixed + crypto update

- compiles vs BoringSSL
- config proposal/vote fift code
- bugfixes in catchain
- other small fixes
This commit is contained in:
ton 2020-03-27 18:59:00 +04:00
parent 606e970ed5
commit a31f8d4424
39 changed files with 722 additions and 132 deletions

View file

@ -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")

View file

@ -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 <http://www.gnu.org/licenses/>.
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;

View file

@ -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 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
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()

View file

@ -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 {

View file

@ -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;

View file

@ -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 <stack>
#include <algorithm>

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "common/bitstring.h"
#include <cstring>
@ -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 {

View file

@ -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 <http://www.gnu.org/licenses/>.
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 <assert.h>
#include <cstring>

View file

@ -28,6 +28,8 @@
#include "common/bitstring.h"
#include "common/util.h"
#include "openssl/digest.hpp"
#include "Ed25519.h"
#include "vm/cells.h"

View file

@ -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();

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "openssl/bignum.h"
#ifdef OPENSSL_IS_BORINGSSL
#include <openssl/mem.h>
#endif
// impl only
#include <cstring>

View file

@ -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 <http://www.gnu.org/licenses/>.
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() {

151
crypto/openssl/digest.hpp Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include <assert.h>
#include <openssl/evp.h>
#include <openssl/opensslv.h>
#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 <typename H>
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 <typename H>
void HashCtx<H>::init() {
ctx = EVP_MD_CTX_create();
reset();
}
template <typename H>
void HashCtx<H>::reset() {
EVP_DigestInit_ex(ctx, H::get_evp(), 0);
}
template <typename H>
void HashCtx<H>::clear() {
EVP_MD_CTX_destroy(ctx);
ctx = nullptr;
}
template <typename H>
void HashCtx<H>::feed(const void *data, std::size_t len) {
EVP_DigestUpdate(ctx, data, len);
}
template <typename H>
std::size_t HashCtx<H>::extract(unsigned char buffer[digest_bytes]) {
unsigned olen = 0;
EVP_DigestFinal_ex(ctx, buffer, &olen);
assert(olen == digest_bytes);
return olen;
}
template <typename H>
std::size_t HashCtx<H>::extract(td::MutableSlice slice) {
return extract(slice.ubegin());
}
template <typename H>
std::string HashCtx<H>::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<OpensslEVP_SHA1> SHA1;
typedef HashCtx<OpensslEVP_SHA256> SHA256;
typedef HashCtx<OpensslEVP_SHA512> SHA512;
template <typename T>
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 <typename T>
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 <typename T>
std::string hash_str(const void *data, std::size_t size) {
T hasher(data, size);
return hasher.extract();
}
template <typename T>
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

View file

@ -40,6 +40,9 @@
{ <b x{c4} s, rot 32 u, swap 64 u, b> 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 <b swap 16 u, swap 16 u, swap 16 u, b> 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"
<b x{538e81278a} s, rot B, swap 64 u, b> <s
tuck <b x{538e81278a} s, rot B, swap 64 u, b> <s
validator-dict 2@ dup 1+ 3 -roll swap
16 udict!+ 0= abort"cannot add validator"
swap validator-dict 2!
swap validator-dict 2! validators-weight +!
} : add-validator
// since-ut until-ut main-val-cnt-or-0 --
{ ?dup 0= { validator# } if
validator# 0= abort"no initial validators defined"
rot <b x{11} s, swap 32 u, rot 32 u, validator# 16 u, swap 16 u,
validator-dict @ first <s s, b>
rot <b x{12} s, swap 32 u, rot 32 u, validator# 16 u, swap 16 u,
validators-weight @ 64 u, validator-dict @ first dict, b>
34 config!
} : config.validators!

View file

@ -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;
}

View file

@ -0,0 +1,33 @@
#!/usr/bin/fift -s
"TonUtil.fif" include
"GetOpt.fif" include
"validator-to-sign.req" =: savefile
{ ."usage: " @' $0 type ." <expire-at> <validator-idx> <proposal-hash> [<savefile>]" cr
."Creates an unsigned request expiring at unixtime <expire-at> to vote for configuration proposal <proposal-hash> (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index <validator-idx> in current validator set (as stored in configuration parameter 34)" cr
."The result is saved into <savefile> (" 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

View file

@ -0,0 +1,51 @@
#!/usr/bin/fift -s
"TonUtil.fif" include
"GetOpt.fif" include
"vote-query.boc" =: savefile
{ ."usage: " @' $0 type ." <config-addr> <expire-at> <validator-idx> <proposal-hash> <validator-pubkey> <validator-signature> [<savefile>]" cr
."Creates an external message addressed to the configuration smart contract <config-addr> containing a signed request expiring at unixtime <expire-at> to vote for configuration proposal <proposal-hash> (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index <validator-idx> and (Base64) public key <validator-pubkey> in current validator set (as stored in configuration parameter 34)" cr
."<validator-signature> must be the base64 representation of Ed25519 signature of the previously generated unsigned request by means of <validator-pubkey>" cr
."The result is saved into <savefile> (" 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
<b b{1000100} s, config-addr addr, 0 Gram, b{00} s,
signature B, to_sign B, b>
cr ."External message is " dup <s csr. cr
2 boc+>B savefile tuck B>file ."Saved to file " type cr

View file

@ -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
" <index> <new-value-boc> [-x <expire-in>] [-c] [-H <old-hash>] [<savefile>]" +cr +tab
+"Creates a new configuration proposal for setting configuration parameter <index> to <new-value-boc> (`null` means no new value), "
+"and saves it as an internal message body into <savefile>.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 <s csr. cr
} cond
=: param-value
{ 2drop true } : is-valid-config?
dup param-idx is-valid-config? not abort"not a valid value for chosen configuration parameter"
critical { ."Critical" } { ."Non-critical" } cond
." configuration proposal will expire at " expire-at . ."(in " expire-in . ."seconds)" cr
now 32 << param-idx + =: query-id
."Query id is " query-id . cr
// create message body
<b x{6e565052} s, query-id 64 u, expire-at 32 u,
<b x{f3} s, param-idx 32 i, param-value dict,
old-hash tuck 0>= tuck 1 i, -rot { 256 u, } { drop } cond b> ref,
critical 1 i, b>
dup ."resulting internal message body: " <s csr. cr
2 boc+>B dup Bx. cr
savefile tuck B>file
."(Saved to file " type .")" cr

View file

@ -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

View file

@ -27,9 +27,26 @@
#include <limits>
namespace ton {
td::Ref<vm::Cell> HighloadWallet::get_init_state(const td::Ed25519::PublicKey& public_key,
td::uint32 wallet_id) noexcept {
auto code = get_init_code();
td::optional<td::int32> 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<td::int32> 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<vm::Cell> 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<vm::Cell> 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<vm::Cell> HighloadWallet::get_init_code() noexcept {
return SmartContractCode::get_code(SmartContractCode::HighloadWalletV1);
td::Ref<vm::Cell> 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<vm::Cell> HighloadWallet::get_init_data(const td::Ed25519::PublicKey& public_key,

View file

@ -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<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
static td::Ref<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id,
td::int32 revision) noexcept;
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id) noexcept;
static td::Ref<vm::Cell> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 wallet_id,
td::uint32 seqno, td::uint32 valid_until, td::Span<Gift> gifts) noexcept;
static td::Ref<vm::Cell> get_init_code() noexcept;
static td::Ref<vm::Cell> get_init_code(td::int32 revision) noexcept;
static vm::CellHash get_init_code_hash() noexcept;
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id) noexcept;
static td::optional<td::int32> guess_revision(const vm::Cell::Hash& code_hash);
static td::optional<td::int32> guess_revision(const block::StdAddress& address,
const td::Ed25519::PublicKey& public_key, td::uint32 wallet_id);
td::Result<td::uint32> get_seqno() const;
td::Result<td::uint32> get_wallet_id() const;

View file

@ -103,6 +103,7 @@ const auto& get_map() {
} // namespace
td::Result<td::Ref<vm::Cell>> SmartContractCode::load(td::Slice name) {
LOG(ERROR) << "LOAD " << name;
auto& map = get_map();
auto it = map.find(name);
if (it == map.end()) {

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include <algorithm>
#include <string>
@ -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;

View file

@ -52,6 +52,8 @@
#include <openssl/sha.h>
#include "openssl/digest.hpp"
namespace vm {
std::vector<int> do_get_serialization_modes() {

View file

@ -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());

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include <ostream>
#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,

View file

@ -24,7 +24,7 @@
#include "td/utils/misc.h"
#include "td/utils/format.h"
#include "openssl/digest.h"
#include "openssl/digest.hpp"
namespace vm {

View file

@ -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 <http://www.gnu.org/licenses/>.
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"

View file

@ -26,6 +26,8 @@
#include "vm/dict.h"
#include "Ed25519.h"
#include "openssl/digest.hpp"
namespace vm {
namespace {

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/tests.h"

View file

@ -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 <http://www.gnu.org/licenses/>.
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<Impl>(BN_lebin2bn(str.ubegin(), narrow_cast<int>(str.size()), nullptr)));
#else
LOG(FATAL) << "Unsupported from_le_binary";
@ -132,7 +132,11 @@ BigNum::BigNum(unique_ptr<Impl> &&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;

View file

@ -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);

View file

@ -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 <http://www.gnu.org/licenses/>.
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
#endif

View file

@ -50,6 +50,8 @@ int main() {
CHECK(id.serialize() == td::to_lower(id_str));
}
td::to_integer_safe<td::uint32>("0").ensure();
std::string db_root_ = "tmp-ee";
td::rmrf(db_root_).ignore();
td::mkdir(db_root_).ensure();

View file

@ -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<tonlib_api::init>(make_object<tonlib_api::options>(
@ -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";

View file

@ -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<block::StdAddress> 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<td::uint32>(test_wallet_state.wallet_id_)));
0 /*zerochain*/,
ton::HighloadWallet::get_init_state(key, static_cast<td::uint32>(test_wallet_state.wallet_id_), revision));
}
td::Result<block::StdAddress> 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;
}();

View file

@ -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 <http://www.gnu.org/licenses/>.
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<BlockSeqno>(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<t
}
void ValidatorManagerImpl::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> 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));
}

View file

@ -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 <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once

View file

@ -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); },