mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-17 09:10:30 +00:00
Disable logging in release builds
This commit is contained in:
parent
bd05bd01b9
commit
fa5c3dbf8f
@ -249,6 +249,8 @@ typedef enum {
|
||||
|
||||
_client = std::make_shared<tonlib::Client>();
|
||||
|
||||
[self setupLogging];
|
||||
|
||||
std::weak_ptr<tonlib::Client> weakClient = _client;
|
||||
|
||||
NSLock *requestHandlersLock = _requestHandlersLock;
|
||||
@ -310,6 +312,20 @@ typedef enum {
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setupLogging {
|
||||
#if DEBUG
|
||||
auto query = make_object<tonlib_api::setLogStream>(
|
||||
make_object<tonlib_api::logStreamDefault>()
|
||||
);
|
||||
_client->execute({ INT16_MAX + 1, std::move(query) });
|
||||
#else
|
||||
auto query = make_object<tonlib_api::setLogStream>(
|
||||
make_object<tonlib_api::logStreamEmpty>()
|
||||
);
|
||||
_client->execute({ INT16_MAX + 1, std::move(query) });
|
||||
#endif
|
||||
}
|
||||
|
||||
- (MTSignal *)requestInitWithConfigString:(NSString *)configString blockchainName:(NSString *)blockchainName keystoreDirectory:(NSString *)keystoreDirectory enableExternalRequests:(bool)enableExternalRequests {
|
||||
return [[[[MTSignal alloc] initWithGenerator:^id<MTDisposable>(MTSubscriber *subscriber) {
|
||||
uint64_t requestId = _nextRequestId;
|
||||
|
@ -67,13 +67,16 @@ private final class TonInstanceImpl {
|
||||
let network = self.network
|
||||
instance = TON(keystoreDirectory: self.basePath + "/ton-keystore", config: self.config, blockchainName: self.blockchainName, performExternalRequest: { request in
|
||||
if let network = network {
|
||||
Logger.shared.log("TON Proxy", "request: \(request.data.count)")
|
||||
let _ = (
|
||||
network.request(Api.functions.wallet.sendLiteRequest(body: Buffer(data: request.data)))
|
||||
|> timeout(20.0, queue: .concurrentDefaultQueue(), alternate: .fail(MTRpcError(errorCode: 500, errorDescription: "NETWORK_ERROR")))
|
||||
).start(next: { result in
|
||||
switch result {
|
||||
case let .liteResponse(response):
|
||||
request.onResult(response.makeData(), nil)
|
||||
let data = response.makeData()
|
||||
Logger.shared.log("TON Proxy", "response: \(data.count)")
|
||||
request.onResult(data, nil)
|
||||
}
|
||||
}, error: { error in
|
||||
request.onResult(nil, error.errorDescription)
|
||||
|
@ -831,7 +831,31 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
self.headerNode.update(size: self.headerNode.bounds.size, navigationHeight: navigationHeight, offset: self.listOffset ?? 0.0, transition: .immediate, isScrolling: false)
|
||||
}
|
||||
|
||||
self.transactionsLoaded(isReload: true, transactions: combinedState.topTransactions, pendingTransactions: combinedState.pendingTransactions)
|
||||
var updatedTransactions: [WalletTransaction] = combinedState.topTransactions
|
||||
if let currentEntries = self.currentEntries {
|
||||
var existingIds = Set<WalletInfoListEntryId>()
|
||||
for transaction in updatedTransactions {
|
||||
existingIds.insert(.transaction(transaction.transactionId))
|
||||
}
|
||||
for entry in currentEntries {
|
||||
switch entry {
|
||||
case let .transaction(_, transaction):
|
||||
switch transaction {
|
||||
case let .completed(transaction):
|
||||
if !existingIds.contains(.transaction(transaction.transactionId)) {
|
||||
existingIds.insert(.transaction(transaction.transactionId))
|
||||
updatedTransactions.append(transaction)
|
||||
}
|
||||
case .pending:
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.transactionsLoaded(isReload: true, transactions: updatedTransactions, pendingTransactions: combinedState.pendingTransactions)
|
||||
|
||||
if isUpdated {
|
||||
self.headerNode.isRefreshing = false
|
||||
|
@ -897,7 +897,7 @@ static int process_workchain_shard_hashes(Ref<vm::Cell>& branch, ton::ShardIdFul
|
||||
int f = (int)cs.fetch_ulong(1);
|
||||
if (f == 1) {
|
||||
if ((shard.shard & 1) || cs.size_ext() != 0x20000) {
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
auto left = cs.prefetch_ref(0), right = cs.prefetch_ref(1);
|
||||
int r = process_workchain_shard_hashes(left, ton::shard_child(shard, true), func);
|
||||
|
@ -1922,7 +1922,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
||||
if (--ptr > buff) {
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
} else {
|
||||
int mask = (-0x100 >> offs) & 0xff;
|
||||
int mask = (0xff00 >> offs) & 0xff;
|
||||
if (((unsigned char)v ^ s) & mask) {
|
||||
return false;
|
||||
}
|
||||
@ -1943,7 +1943,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
||||
if (--ptr > buff) {
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
} else {
|
||||
int mask = (-0x100 >> offs) & 0xff;
|
||||
int mask = (0xff00 >> offs) & 0xff;
|
||||
if (((unsigned char)v ^ s) & mask) {
|
||||
return false;
|
||||
}
|
||||
@ -1961,7 +1961,7 @@ bool AnyIntView<Tr>::export_bits_any(unsigned char* buff, int offs, unsigned bit
|
||||
*ptr = (unsigned char)(v & 0xff);
|
||||
v >>= 8;
|
||||
}
|
||||
int mask = (-0x100 >> offs) & 0xff;
|
||||
int mask = (0xff00 >> offs) & 0xff;
|
||||
if (((unsigned char)v ^ s) & mask) {
|
||||
return false;
|
||||
}
|
||||
|
@ -132,9 +132,7 @@ int main(int argc, char* const argv[]) {
|
||||
|
||||
if (!no_env) {
|
||||
const char* path = std::getenv("FIFTPATH");
|
||||
if (path) {
|
||||
parse_include_path_set(path ? path : "/usr/lib/fift", source_include_path);
|
||||
}
|
||||
parse_include_path_set(path ? path : "/usr/lib/fift", source_include_path);
|
||||
}
|
||||
std::string current_dir;
|
||||
auto r_current_dir = td::realpath(".");
|
||||
|
@ -764,6 +764,10 @@ void interpret_string_to_bytes(vm::Stack& stack) {
|
||||
stack.push_bytes(stack.pop_string());
|
||||
}
|
||||
|
||||
void interpret_bytes_to_string(vm::Stack& stack) {
|
||||
stack.push_string(stack.pop_bytes());
|
||||
}
|
||||
|
||||
void interpret_bytes_hash(vm::Stack& stack, bool as_uint) {
|
||||
std::string str = stack.pop_bytes();
|
||||
unsigned char buffer[32];
|
||||
@ -796,7 +800,9 @@ void interpret_store_str(vm::Stack& stack) {
|
||||
stack.check_underflow(2);
|
||||
auto str = stack.pop_string();
|
||||
auto cell = stack.pop_builder();
|
||||
cell.write().store_bytes(str); // may throw CellWriteError
|
||||
if (!cell.write().store_bytes_bool(str)) {
|
||||
throw IntError{"string does not fit into cell"};
|
||||
}
|
||||
stack.push(cell);
|
||||
}
|
||||
|
||||
@ -804,14 +810,18 @@ void interpret_store_bytes(vm::Stack& stack) {
|
||||
stack.check_underflow(2);
|
||||
auto str = stack.pop_bytes();
|
||||
auto cell = stack.pop_builder();
|
||||
cell.write().store_bytes(str); // may throw CellWriteError
|
||||
if (!cell.write().store_bytes_bool(str)) {
|
||||
throw IntError{"byte string does not fit into cell"};
|
||||
}
|
||||
stack.push(cell);
|
||||
}
|
||||
|
||||
void interpret_string_to_cellslice(vm::Stack& stack) {
|
||||
auto str = stack.pop_string();
|
||||
vm::CellBuilder cb;
|
||||
cb.store_bytes(str); // may throw CellWriteError
|
||||
if (!cb.store_bytes_bool(str)) {
|
||||
throw IntError{"string does not fit into cell"};
|
||||
}
|
||||
stack.push_cellslice(td::Ref<vm::CellSlice>{true, cb.finalize()});
|
||||
}
|
||||
|
||||
@ -819,7 +829,9 @@ void interpret_store_cellslice(vm::Stack& stack) {
|
||||
stack.check_underflow(2);
|
||||
auto cs = stack.pop_cellslice();
|
||||
auto cb = stack.pop_builder();
|
||||
vm::cell_builder_add_slice(cb.write(), *cs);
|
||||
if (!vm::cell_builder_add_slice_bool(cb.write(), *cs)) {
|
||||
throw IntError{"slice does not fit into cell"};
|
||||
}
|
||||
stack.push(std::move(cb));
|
||||
}
|
||||
|
||||
@ -840,9 +852,11 @@ void interpret_concat_cellslice(vm::Stack& stack) {
|
||||
auto cs2 = stack.pop_cellslice();
|
||||
auto cs1 = stack.pop_cellslice();
|
||||
vm::CellBuilder cb;
|
||||
vm::cell_builder_add_slice(cb, *cs1);
|
||||
vm::cell_builder_add_slice(cb, *cs2);
|
||||
stack.push_cellslice(td::Ref<vm::CellSlice>{true, cb.finalize()});
|
||||
if (vm::cell_builder_add_slice_bool(cb, *cs1) && vm::cell_builder_add_slice_bool(cb, *cs2)) {
|
||||
stack.push_cellslice(td::Ref<vm::CellSlice>{true, cb.finalize()});
|
||||
} else {
|
||||
throw IntError{"concatenation of two slices does not fit into a cell"};
|
||||
}
|
||||
}
|
||||
|
||||
void interpret_concat_cellslice_ref(vm::Stack& stack) {
|
||||
@ -862,7 +876,9 @@ void interpret_concat_builders(vm::Stack& stack) {
|
||||
stack.check_underflow(2);
|
||||
auto cb2 = stack.pop_builder();
|
||||
auto cb1 = stack.pop_builder();
|
||||
cb1.write().append_builder(std::move(cb2));
|
||||
if (!cb1.write().append_builder_bool(std::move(cb2))) {
|
||||
throw IntError{"cannot concatenate two builders"};
|
||||
}
|
||||
stack.push_builder(std::move(cb1));
|
||||
}
|
||||
|
||||
@ -2490,6 +2506,7 @@ void init_words_common(Dictionary& d) {
|
||||
d.def_stack_word("B>Lu@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x12));
|
||||
d.def_stack_word("B>Li@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x13));
|
||||
d.def_stack_word("$>B ", interpret_string_to_bytes);
|
||||
d.def_stack_word("B>$ ", interpret_bytes_to_string);
|
||||
d.def_stack_word("Bhash ", std::bind(interpret_bytes_hash, _1, true));
|
||||
d.def_stack_word("Bhashu ", std::bind(interpret_bytes_hash, _1, true));
|
||||
d.def_stack_word("BhashB ", std::bind(interpret_bytes_hash, _1, false));
|
||||
|
@ -138,7 +138,7 @@ bool Op::set_var_info_except(const VarDescrList& new_var_info, const std::vector
|
||||
}
|
||||
VarDescrList tmp_info{new_var_info};
|
||||
tmp_info -= var_list;
|
||||
return set_var_info(new_var_info);
|
||||
return set_var_info(tmp_info);
|
||||
}
|
||||
|
||||
bool Op::set_var_info_except(VarDescrList&& new_var_info, const std::vector<var_idx_t>& var_list) {
|
||||
|
@ -149,6 +149,10 @@ AsmOp AsmOp::IntConst(td::RefInt256 x) {
|
||||
return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT");
|
||||
}
|
||||
|
||||
AsmOp AsmOp::BoolConst(bool f) {
|
||||
return AsmOp::Const(f ? "TRUE" : "FALSE");
|
||||
}
|
||||
|
||||
AsmOp AsmOp::Parse(std::string custom_op) {
|
||||
if (custom_op == "NOP") {
|
||||
return AsmOp::Nop();
|
||||
|
@ -620,7 +620,7 @@ int compute_compare(td::RefInt256 x, td::RefInt256 y, int mode) {
|
||||
if (mode == 7) {
|
||||
return s;
|
||||
} else {
|
||||
return (mode >> (1 - s)) & 1;
|
||||
return -((mode >> (1 - s)) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -641,8 +641,8 @@ int compute_compare(const VarDescr& x, const VarDescr& y, int mode) {
|
||||
return x.always_less(y) ? 1 : (x.always_geq(y) ? 2 : 3);
|
||||
case 5: // <>
|
||||
return x.always_neq(y) ? 1 : (x.always_equal(y) ? 2 : 3);
|
||||
case 6: // >=
|
||||
return x.always_geq(y) ? 1 : (x.always_less(y) ? 2 : 3);
|
||||
case 6: // <=
|
||||
return x.always_leq(y) ? 1 : (x.always_greater(y) ? 2 : 3);
|
||||
case 7: // <=>
|
||||
return x.always_less(y)
|
||||
? 1
|
||||
@ -661,10 +661,11 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
||||
assert(res.size() == 1 && args.size() == 2);
|
||||
VarDescr &r = res[0], &x = args[0], &y = args[1];
|
||||
if (x.is_int_const() && y.is_int_const()) {
|
||||
r.set_const(compute_compare(x.int_const, y.int_const, mode));
|
||||
int v = compute_compare(x.int_const, y.int_const, mode);
|
||||
r.set_const(v);
|
||||
x.unused();
|
||||
y.unused();
|
||||
return push_const(r.int_const);
|
||||
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0);
|
||||
}
|
||||
int v = compute_compare(x, y, mode);
|
||||
assert(v);
|
||||
@ -672,7 +673,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
|
||||
r.set_const(v - (v >> 2) - 2);
|
||||
x.unused();
|
||||
y.unused();
|
||||
return push_const(r.int_const);
|
||||
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v & 1);
|
||||
}
|
||||
r.val = ~0;
|
||||
if (v & 1) {
|
||||
@ -957,12 +958,11 @@ void define_builtins() {
|
||||
AsmOp::Nop());
|
||||
define_builtin_func("~dump", TypeExpr::new_forall({X}, TypeExpr::new_map(X, TypeExpr::new_tensor({X, Unit}))),
|
||||
AsmOp::Custom("s0 DUMP", 1, 1));
|
||||
define_builtin_func(
|
||||
"run_method0", TypeExpr::new_map(Int, Unit),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true);
|
||||
define_builtin_func_x(
|
||||
"run_method1", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true);
|
||||
define_builtin_func("run_method0", TypeExpr::new_map(Int, Unit),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true);
|
||||
define_builtin_func_x("run_method1",
|
||||
TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true);
|
||||
define_builtin_func_x(
|
||||
"run_method2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y}), Unit)),
|
||||
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 2, false); }, {1, 2, 0}, {}, true);
|
||||
|
@ -950,6 +950,7 @@ struct AsmOp {
|
||||
static AsmOp make_stk2(int a, int b, const char* str, int delta);
|
||||
static AsmOp make_stk3(int a, int b, int c, const char* str, int delta);
|
||||
static AsmOp IntConst(td::RefInt256 value);
|
||||
static AsmOp BoolConst(bool f);
|
||||
static AsmOp Const(std::string push_op) {
|
||||
return AsmOp(a_const, 0, 1, std::move(push_op));
|
||||
}
|
||||
|
@ -101,8 +101,12 @@ dictnew constant special-dict
|
||||
1 'nop
|
||||
} ::_ sg~
|
||||
|
||||
// gas_price gas_limit spec_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit -- c
|
||||
{ 7 0 reverse <b x{de} s, { swap 64 u, } 7 times b>
|
||||
// gas_price gas_limit spec_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit b -- c
|
||||
{ 7 1 reverse x{de} s, { swap 64 u, } 7 times b>
|
||||
} : make-gas-prices-basic
|
||||
// gas_price ... delete_due_limit flat_gas_limit flat_gas_rate -- c
|
||||
{ 2dup or { <b x{d1} s, rot 64 u, swap 64 u, } { 2drop <b } cond
|
||||
make-gas-prices-basic
|
||||
} : make-gas-prices
|
||||
{ make-gas-prices 20 config! } : config.mc_gas_prices!
|
||||
{ make-gas-prices 21 config! } : config.gas_prices!
|
||||
|
@ -171,9 +171,9 @@ elector_addr config.elector_smc!
|
||||
1 500 1000 500000 config.storage_prices!
|
||||
config.special!
|
||||
|
||||
// gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit --
|
||||
1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 config.gas_prices!
|
||||
10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 config.mc_gas_prices!
|
||||
// gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit flat_gas_limit flat_gas_price --
|
||||
1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 100 100000 config.gas_prices!
|
||||
10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 0 0 config.mc_gas_prices!
|
||||
// lump_price bit_price cell_price ihr_factor first_frac next_frac
|
||||
1000000 1000 sg* 100000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.fwd_prices!
|
||||
10000000 10000 sg* 1000000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.mc_fwd_prices!
|
||||
|
@ -31,8 +31,9 @@ serialized_boc#b5ee9c72 has_idx:(## 1) has_crc32c:(## 1)
|
||||
absent:(##(size * 8)) { roots + absent <= cells }
|
||||
tot_cells_size:(##(off_bytes * 8))
|
||||
root_list:(roots * ##(size * 8))
|
||||
index:(cells * ##(off_bytes * 8))
|
||||
index:has_idx?(cells * ##(off_bytes * 8))
|
||||
cell_data:(tot_cells_size * [ uint8 ])
|
||||
crc32c:has_crc32c?uint32
|
||||
= BagOfCells;
|
||||
|
||||
compiled_smart_contract
|
||||
|
@ -75,7 +75,7 @@ td::Result<int> CellSerializationInfo::get_bits(td::Slice cell) const {
|
||||
if (data_with_bits) {
|
||||
DCHECK(data_len != 0);
|
||||
int last = cell[data_offset + data_len - 1];
|
||||
if (!last || last == 0x80) {
|
||||
if (!(last & 0x7f)) {
|
||||
return td::Status::Error("overlong encoding");
|
||||
}
|
||||
return td::narrow_cast<int>((data_len - 1) * 8 + 7 - td::count_trailing_zeroes_non_zero32(last));
|
||||
@ -391,15 +391,6 @@ td::uint64 BagOfCells::compute_sizes(int mode, int& r_size, int& o_size) {
|
||||
r_size = o_size = 0;
|
||||
return 0;
|
||||
}
|
||||
if (!(mode & Mode::WithIndex)) {
|
||||
if (rs > 2 || os > 4) {
|
||||
rs = std::max(3, rs);
|
||||
os = 8;
|
||||
data_bytes_adj = data_bytes + (unsigned long long)int_refs * rs + hashes;
|
||||
} else {
|
||||
os = 4;
|
||||
}
|
||||
}
|
||||
r_size = rs;
|
||||
o_size = os;
|
||||
return data_bytes_adj;
|
||||
|
@ -527,9 +527,6 @@ int CellBuilder::serialize(unsigned char* buff, int buff_size) const {
|
||||
|
||||
CellBuilder* CellBuilder::make_copy() const {
|
||||
CellBuilder* c = new CellBuilder();
|
||||
if (!c) {
|
||||
throw CellWriteError();
|
||||
}
|
||||
c->bits = bits;
|
||||
std::memcpy(c->data, data, (bits + 7) >> 3);
|
||||
c->refs_cnt = refs_cnt;
|
||||
|
@ -134,6 +134,8 @@ object_ptr<Function> Function::fetch(td::TlParser &p) {
|
||||
return liteServer_queryPrefix::fetch(p);
|
||||
case liteServer_sendMessage::ID:
|
||||
return liteServer_sendMessage::fetch(p);
|
||||
case liteServer_waitMasterchainSeqno::ID:
|
||||
return liteServer_waitMasterchainSeqno::fetch(p);
|
||||
default:
|
||||
FAIL(PSTRING() << "Unknown constructor found " << td::format::as_hex(constructor));
|
||||
}
|
||||
@ -2770,5 +2772,57 @@ liteServer_sendMessage::ReturnType liteServer_sendMessage::fetch_result(td::TlPa
|
||||
return TlFetchBoxed<TlFetchObject<liteServer_sendMsgStatus>, 961602967>::parse(p);
|
||||
#undef FAIL
|
||||
}
|
||||
|
||||
liteServer_waitMasterchainSeqno::liteServer_waitMasterchainSeqno()
|
||||
: seqno_()
|
||||
, timeout_ms_()
|
||||
{}
|
||||
|
||||
liteServer_waitMasterchainSeqno::liteServer_waitMasterchainSeqno(std::int32_t seqno_, std::int32_t timeout_ms_)
|
||||
: seqno_(seqno_)
|
||||
, timeout_ms_(timeout_ms_)
|
||||
{}
|
||||
|
||||
const std::int32_t liteServer_waitMasterchainSeqno::ID;
|
||||
|
||||
object_ptr<liteServer_waitMasterchainSeqno> liteServer_waitMasterchainSeqno::fetch(td::TlParser &p) {
|
||||
return make_object<liteServer_waitMasterchainSeqno>(p);
|
||||
}
|
||||
|
||||
liteServer_waitMasterchainSeqno::liteServer_waitMasterchainSeqno(td::TlParser &p)
|
||||
#define FAIL(error) p.set_error(error)
|
||||
: seqno_(TlFetchInt::parse(p))
|
||||
, timeout_ms_(TlFetchInt::parse(p))
|
||||
#undef FAIL
|
||||
{}
|
||||
|
||||
void liteServer_waitMasterchainSeqno::store(td::TlStorerCalcLength &s) const {
|
||||
(void)sizeof(s);
|
||||
s.store_binary(-1159022446);
|
||||
TlStoreBinary::store(seqno_, s);
|
||||
TlStoreBinary::store(timeout_ms_, s);
|
||||
}
|
||||
|
||||
void liteServer_waitMasterchainSeqno::store(td::TlStorerUnsafe &s) const {
|
||||
(void)sizeof(s);
|
||||
s.store_binary(-1159022446);
|
||||
TlStoreBinary::store(seqno_, s);
|
||||
TlStoreBinary::store(timeout_ms_, s);
|
||||
}
|
||||
|
||||
void liteServer_waitMasterchainSeqno::store(td::TlStorerToString &s, const char *field_name) const {
|
||||
if (!LOG_IS_STRIPPED(ERROR)) {
|
||||
s.store_class_begin(field_name, "liteServer_waitMasterchainSeqno");
|
||||
s.store_field("seqno", seqno_);
|
||||
s.store_field("timeout_ms", timeout_ms_);
|
||||
s.store_class_end();
|
||||
}
|
||||
}
|
||||
|
||||
liteServer_waitMasterchainSeqno::ReturnType liteServer_waitMasterchainSeqno::fetch_result(td::TlParser &p) {
|
||||
#define FAIL(error) p.set_error(error); return ReturnType()
|
||||
return TlFetchBoxed<TlFetchObject<Object>, 695225504>::parse(p);
|
||||
#undef FAIL
|
||||
}
|
||||
} // namespace lite_api
|
||||
} // namespace ton
|
||||
|
@ -1481,5 +1481,34 @@ class liteServer_sendMessage final : public Function {
|
||||
static ReturnType fetch_result(td::TlParser &p);
|
||||
};
|
||||
|
||||
class liteServer_waitMasterchainSeqno final : public Function {
|
||||
public:
|
||||
std::int32_t seqno_;
|
||||
std::int32_t timeout_ms_;
|
||||
|
||||
liteServer_waitMasterchainSeqno();
|
||||
|
||||
liteServer_waitMasterchainSeqno(std::int32_t seqno_, std::int32_t timeout_ms_);
|
||||
|
||||
static const std::int32_t ID = -1159022446;
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
using ReturnType = object_ptr<Object>;
|
||||
|
||||
static object_ptr<liteServer_waitMasterchainSeqno> fetch(td::TlParser &p);
|
||||
|
||||
explicit liteServer_waitMasterchainSeqno(td::TlParser &p);
|
||||
|
||||
void store(td::TlStorerCalcLength &s) const final;
|
||||
|
||||
void store(td::TlStorerUnsafe &s) const final;
|
||||
|
||||
void store(td::TlStorerToString &s, const char *field_name) const final;
|
||||
|
||||
static ReturnType fetch_result(td::TlParser &p);
|
||||
};
|
||||
|
||||
} // namespace lite_api
|
||||
} // namespace ton
|
||||
|
@ -178,6 +178,9 @@ bool downcast_call(Function &obj, const T &func) {
|
||||
case liteServer_sendMessage::ID:
|
||||
func(static_cast<liteServer_sendMessage &>(obj));
|
||||
return true;
|
||||
case liteServer_waitMasterchainSeqno::ID:
|
||||
func(static_cast<liteServer_waitMasterchainSeqno &>(obj));
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -528,14 +528,16 @@ raw_accountState::raw_accountState()
|
||||
, code_()
|
||||
, data_()
|
||||
, last_transaction_id_()
|
||||
, frozen_hash_()
|
||||
, sync_utime_()
|
||||
{}
|
||||
|
||||
raw_accountState::raw_accountState(std::int64_t balance_, std::string const &code_, std::string const &data_, object_ptr<internal_transactionId> &&last_transaction_id_, std::int64_t sync_utime_)
|
||||
raw_accountState::raw_accountState(std::int64_t balance_, std::string const &code_, std::string const &data_, object_ptr<internal_transactionId> &&last_transaction_id_, std::string const &frozen_hash_, std::int64_t sync_utime_)
|
||||
: balance_(balance_)
|
||||
, code_(std::move(code_))
|
||||
, data_(std::move(data_))
|
||||
, last_transaction_id_(std::move(last_transaction_id_))
|
||||
, frozen_hash_(std::move(frozen_hash_))
|
||||
, sync_utime_(sync_utime_)
|
||||
{}
|
||||
|
||||
@ -548,6 +550,7 @@ void raw_accountState::store(td::TlStorerToString &s, const char *field_name) co
|
||||
s.store_bytes_field("code", code_);
|
||||
s.store_bytes_field("data", data_);
|
||||
if (last_transaction_id_ == nullptr) { s.store_field("last_transaction_id", "null"); } else { last_transaction_id_->store(s, "last_transaction_id"); }
|
||||
s.store_bytes_field("frozen_hash", frozen_hash_);
|
||||
s.store_field("sync_utime", sync_utime_);
|
||||
s.store_class_end();
|
||||
}
|
||||
@ -748,12 +751,14 @@ void testWallet_initialAccountState::store(td::TlStorerToString &s, const char *
|
||||
uninited_accountState::uninited_accountState()
|
||||
: balance_()
|
||||
, last_transaction_id_()
|
||||
, frozen_hash_()
|
||||
, sync_utime_()
|
||||
{}
|
||||
|
||||
uninited_accountState::uninited_accountState(std::int64_t balance_, object_ptr<internal_transactionId> &&last_transaction_id_, std::int64_t sync_utime_)
|
||||
uninited_accountState::uninited_accountState(std::int64_t balance_, object_ptr<internal_transactionId> &&last_transaction_id_, std::string const &frozen_hash_, std::int64_t sync_utime_)
|
||||
: balance_(balance_)
|
||||
, last_transaction_id_(std::move(last_transaction_id_))
|
||||
, frozen_hash_(std::move(frozen_hash_))
|
||||
, sync_utime_(sync_utime_)
|
||||
{}
|
||||
|
||||
@ -764,6 +769,7 @@ void uninited_accountState::store(td::TlStorerToString &s, const char *field_nam
|
||||
s.store_class_begin(field_name, "uninited_accountState");
|
||||
s.store_field("balance", balance_);
|
||||
if (last_transaction_id_ == nullptr) { s.store_field("last_transaction_id", "null"); } else { last_transaction_id_->store(s, "last_transaction_id"); }
|
||||
s.store_bytes_field("frozen_hash", frozen_hash_);
|
||||
s.store_field("sync_utime", sync_utime_);
|
||||
s.store_class_end();
|
||||
}
|
||||
|
@ -568,13 +568,14 @@ class raw_accountState final : public Object {
|
||||
std::string code_;
|
||||
std::string data_;
|
||||
object_ptr<internal_transactionId> last_transaction_id_;
|
||||
std::string frozen_hash_;
|
||||
std::int64_t sync_utime_;
|
||||
|
||||
raw_accountState();
|
||||
|
||||
raw_accountState(std::int64_t balance_, std::string const &code_, std::string const &data_, object_ptr<internal_transactionId> &&last_transaction_id_, std::int64_t sync_utime_);
|
||||
raw_accountState(std::int64_t balance_, std::string const &code_, std::string const &data_, object_ptr<internal_transactionId> &&last_transaction_id_, std::string const &frozen_hash_, std::int64_t sync_utime_);
|
||||
|
||||
static const std::int32_t ID = 461615898;
|
||||
static const std::int32_t ID = 1205935434;
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
@ -720,13 +721,14 @@ class uninited_accountState final : public Object {
|
||||
public:
|
||||
std::int64_t balance_;
|
||||
object_ptr<internal_transactionId> last_transaction_id_;
|
||||
std::string frozen_hash_;
|
||||
std::int64_t sync_utime_;
|
||||
|
||||
uninited_accountState();
|
||||
|
||||
uninited_accountState(std::int64_t balance_, object_ptr<internal_transactionId> &&last_transaction_id_, std::int64_t sync_utime_);
|
||||
uninited_accountState(std::int64_t balance_, object_ptr<internal_transactionId> &&last_transaction_id_, std::string const &frozen_hash_, std::int64_t sync_utime_);
|
||||
|
||||
static const std::int32_t ID = 1768941188;
|
||||
static const std::int32_t ID = -918880075;
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::
|
||||
{"generic.accountStateTestGiver", 1134654598},
|
||||
{"generic.accountStateUninited", -908702008},
|
||||
{"internal.transactionId", -989527262},
|
||||
{"raw.accountState", 461615898},
|
||||
{"raw.accountState", 1205935434},
|
||||
{"raw.initialAccountState", 777456197},
|
||||
{"raw.message", -906281442},
|
||||
{"raw.transaction", 1887601793},
|
||||
@ -88,7 +88,7 @@ Result<int32> tl_constructor_from_string(tonlib_api::Object *object, const std::
|
||||
{"testGiver.accountState", 860930426},
|
||||
{"testWallet.accountState", 305698744},
|
||||
{"testWallet.initialAccountState", -1231516227},
|
||||
{"uninited.accountState", 1768941188},
|
||||
{"uninited.accountState", -918880075},
|
||||
{"wallet.accountState", -1919815977},
|
||||
{"wallet.initialAccountState", -1079249978}
|
||||
};
|
||||
@ -479,6 +479,12 @@ Status from_json(tonlib_api::raw_accountState &to, JsonObject &from) {
|
||||
TRY_STATUS(from_json(to.last_transaction_id_, value));
|
||||
}
|
||||
}
|
||||
{
|
||||
TRY_RESULT(value, get_json_object_field(from, "frozen_hash", JsonValue::Type::Null, true));
|
||||
if (value.type() != JsonValue::Type::Null) {
|
||||
TRY_STATUS(from_json_bytes(to.frozen_hash_, value));
|
||||
}
|
||||
}
|
||||
{
|
||||
TRY_RESULT(value, get_json_object_field(from, "sync_utime", JsonValue::Type::Null, true));
|
||||
if (value.type() != JsonValue::Type::Null) {
|
||||
@ -695,6 +701,12 @@ Status from_json(tonlib_api::uninited_accountState &to, JsonObject &from) {
|
||||
TRY_STATUS(from_json(to.last_transaction_id_, value));
|
||||
}
|
||||
}
|
||||
{
|
||||
TRY_RESULT(value, get_json_object_field(from, "frozen_hash", JsonValue::Type::Null, true));
|
||||
if (value.type() != JsonValue::Type::Null) {
|
||||
TRY_STATUS(from_json_bytes(to.frozen_hash_, value));
|
||||
}
|
||||
}
|
||||
{
|
||||
TRY_RESULT(value, get_json_object_field(from, "sync_utime", JsonValue::Type::Null, true));
|
||||
if (value.type() != JsonValue::Type::Null) {
|
||||
@ -1488,6 +1500,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::raw_accountState &object) {
|
||||
if (object.last_transaction_id_) {
|
||||
jo << ctie("last_transaction_id", ToJson(object.last_transaction_id_));
|
||||
}
|
||||
jo << ctie("frozen_hash", ToJson(JsonBytes{object.frozen_hash_}));
|
||||
jo << ctie("sync_utime", ToJson(object.sync_utime_));
|
||||
}
|
||||
void to_json(JsonValueScope &jv, const tonlib_api::raw_initialAccountState &object) {
|
||||
@ -1564,6 +1577,7 @@ void to_json(JsonValueScope &jv, const tonlib_api::uninited_accountState &object
|
||||
if (object.last_transaction_id_) {
|
||||
jo << ctie("last_transaction_id", ToJson(object.last_transaction_id_));
|
||||
}
|
||||
jo << ctie("frozen_hash", ToJson(JsonBytes{object.frozen_hash_}));
|
||||
jo << ctie("sync_utime", ToJson(object.sync_utime_));
|
||||
}
|
||||
void to_json(JsonValueScope &jv, const tonlib_api::wallet_accountState &object) {
|
||||
|
@ -74,3 +74,4 @@ liteServer.getConfigParams mode:# id:tonNode.blockIdExt param_list:(vector int)
|
||||
|
||||
liteServer.queryPrefix = Object;
|
||||
liteServer.query data:bytes = Object;
|
||||
liteServer.waitMasterchainSeqno seqno:int timeout_ms:int = Object; // query prefix
|
||||
|
Binary file not shown.
@ -38,7 +38,7 @@ unpackedAccountAddress workchain_id:int32 bounceable:Bool testnet:Bool addr:byte
|
||||
internal.transactionId lt:int64 hash:bytes = internal.TransactionId;
|
||||
|
||||
raw.initialAccountState code:bytes data:bytes = raw.InitialAccountState;
|
||||
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId sync_utime:int53 = raw.AccountState;
|
||||
raw.accountState balance:int64 code:bytes data:bytes last_transaction_id:internal.transactionId frozen_hash:bytes sync_utime:int53 = raw.AccountState;
|
||||
raw.message source:string destination:string value:int64 fwd_fee:int64 ihr_fee:int64 created_lt:int64 body_hash:bytes message:bytes = raw.Message;
|
||||
raw.transaction utime:int53 data:bytes transaction_id:internal.transactionId fee:int64 storage_fee:int64 other_fee:int64 in_msg:raw.message out_msgs:vector<raw.message> = raw.Transaction;
|
||||
raw.transactions transactions:vector<raw.transaction> previous_transaction_id:internal.transactionId = raw.Transactions;
|
||||
@ -51,7 +51,7 @@ wallet.accountState balance:int64 seqno:int32 last_transaction_id:internal.trans
|
||||
|
||||
testGiver.accountState balance:int64 seqno:int32 last_transaction_id:internal.transactionId sync_utime:int53= testGiver.AccountState;
|
||||
|
||||
uninited.accountState balance:int64 last_transaction_id:internal.transactionId sync_utime:int53 = uninited.AccountState;
|
||||
uninited.accountState balance:int64 last_transaction_id:internal.transactionId frozen_hash:bytes sync_utime:int53 = uninited.AccountState;
|
||||
|
||||
//generic.initialAccountStateRaw initital_account_state:raw.initialAccountState = generic.InitialAccountState;
|
||||
//generic.initialAccountStateTestWallet initital_account_state:testWallet.initialAccountState = generic.InitialAccountState;
|
||||
|
Binary file not shown.
@ -68,7 +68,7 @@ int TD_TL_writer::get_storer_type(const tl::tl_combinator *t, const std::string
|
||||
|
||||
tl::TL_writer::Mode TD_TL_writer::get_parser_mode(int type) const {
|
||||
if (tl_name == "tonlib_api") {
|
||||
#ifndef TD_ENABLE_JNI // we need to parse all types in order to implement toString
|
||||
#ifndef TONLIB_ENABLE_JNI // we need to parse all types in order to implement toString
|
||||
return Server;
|
||||
#endif
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ add_executable(tonlib-cli tonlib/tonlib-cli.cpp)
|
||||
target_link_libraries(tonlib-cli tonlib tdactor tdutils terminal)
|
||||
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
if (TD_ENABLE_JNI)
|
||||
if (TONLIB_ENABLE_JNI)
|
||||
#FIXME
|
||||
#add_dependencies(tonlib tonlib_generate_java_api)
|
||||
endif()
|
||||
|
@ -420,18 +420,24 @@ TEST(Tonlib, ParseAddres) {
|
||||
ASSERT_EQ(-1, addr->workchain_id_);
|
||||
ASSERT_EQ(true, addr->bounceable_);
|
||||
ASSERT_EQ(false, addr->testnet_);
|
||||
auto raw = addr->addr_;
|
||||
|
||||
auto addr_str = sync_send(client, make_object<tonlib_api::packAccountAddress>(std::move(addr))).move_as_ok();
|
||||
ASSERT_EQ("Ef9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfYFX", addr_str->account_address_);
|
||||
auto addr_str2 = sync_send(client, make_object<tonlib_api::packAccountAddress>(
|
||||
make_object<tonlib_api::unpackedAccountAddress>(-1, false, false, raw)))
|
||||
.move_as_ok();
|
||||
ASSERT_EQ("Uf9Tj6fMJP-OqhAdhKXxq36DL-HYSzCc3-9O6UNzqsgPfdyS", addr_str2->account_address_);
|
||||
}
|
||||
|
||||
TEST(Tonlib, KeysApi) {
|
||||
using tonlib_api::make_object;
|
||||
Client client;
|
||||
|
||||
td::mkdir("testdir").ignore();
|
||||
// init
|
||||
sync_send(client, make_object<tonlib_api::init>(
|
||||
make_object<tonlib_api::options>(nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("."))))
|
||||
sync_send(client, make_object<tonlib_api::init>(make_object<tonlib_api::options>(
|
||||
nullptr, make_object<tonlib_api::keyStoreTypeDirectory>("testdir"))))
|
||||
.ensure();
|
||||
auto local_password = td::SecureString("local password");
|
||||
auto mnemonic_password = td::SecureString("mnemonic password");
|
||||
@ -550,7 +556,7 @@ TEST(Tonlib, KeysApi) {
|
||||
make_object<tonlib_api::inputKey>(
|
||||
make_object<tonlib_api::key>(key->public_key_, imported_key->secret_.copy()), new_local_password.copy()),
|
||||
pem_password.copy()));
|
||||
if (r_exported_pem_key.is_error() && r_exported_pem_key.error().message() == "Not supported") {
|
||||
if (r_exported_pem_key.is_error() && r_exported_pem_key.error().message() == "INTERNAL Not supported") {
|
||||
return;
|
||||
}
|
||||
auto exported_pem_key = r_exported_pem_key.move_as_ok();
|
||||
|
Binary file not shown.
BIN
submodules/ton/tonlib-src/tonlib/tonlib/.TonlibClient.cpp.swp
Normal file
BIN
submodules/ton/tonlib-src/tonlib/tonlib/.TonlibClient.cpp.swp
Normal file
Binary file not shown.
Binary file not shown.
@ -57,10 +57,16 @@ class ExtClient {
|
||||
void with_last_block(td::Promise<LastBlockState> promise);
|
||||
|
||||
template <class QueryT>
|
||||
void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise) {
|
||||
void send_query(QueryT query, td::Promise<typename QueryT::ReturnType> promise, td::int32 seq_no = -1) {
|
||||
auto raw_query = ton::serialize_tl_object(&query, true);
|
||||
td::uint32 tag = td::Random::fast_uint32();
|
||||
VLOG(lite_server) << "send query to liteserver: " << tag << " " << to_string(query);
|
||||
if (seq_no >= 0) {
|
||||
auto wait = ton::lite_api::liteServer_waitMasterchainSeqno(seq_no, 5000);
|
||||
VLOG(lite_server) << " with prefix " << to_string(wait);
|
||||
auto prefix = ton::serialize_tl_object(&wait, true);
|
||||
raw_query = td::BufferSlice(PSLICE() << prefix.as_slice() << raw_query.as_slice());
|
||||
}
|
||||
td::BufferSlice liteserver_query =
|
||||
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(raw_query)), true);
|
||||
|
||||
|
@ -69,7 +69,7 @@ td::Result<DecryptedKey> KeyStorage::export_decrypted_key(InputKey input_key) {
|
||||
if (r_encrypted_data.is_error()) {
|
||||
r_encrypted_data = kv_->get(to_file_name_old(input_key.key));
|
||||
if (r_encrypted_data.is_ok()) {
|
||||
LOG(WARNING) << "Restore private from deprecated location " << to_file_name_old(input_key.key) << " --> "
|
||||
LOG(WARNING) << "Restore private key from deprecated location " << to_file_name_old(input_key.key) << " --> "
|
||||
<< to_file_name(input_key.key);
|
||||
TRY_STATUS_PREFIX(kv_->set(to_file_name(input_key.key), r_encrypted_data.ok()), TonlibError::Internal());
|
||||
kv_->erase(to_file_name_old(input_key.key)).ignore();
|
||||
@ -78,9 +78,24 @@ td::Result<DecryptedKey> KeyStorage::export_decrypted_key(InputKey input_key) {
|
||||
TRY_RESULT_PREFIX(encrypted_data, std::move(r_encrypted_data), TonlibError::KeyUnknown());
|
||||
EncryptedKey encrypted_key{std::move(encrypted_data), td::Ed25519::PublicKey(std::move(input_key.key.public_key)),
|
||||
std::move(input_key.key.secret)};
|
||||
{
|
||||
auto r_decrypted_key = encrypted_key.decrypt(input_key.local_password.copy(), true, true);
|
||||
if (r_decrypted_key.is_ok()) {
|
||||
LOG(WARNING) << "Restore private from deprecated encryption " << to_file_name(input_key.key);
|
||||
auto decrypted_key = r_decrypted_key.move_as_ok();
|
||||
auto key = Key{encrypted_key.public_key.as_octet_string(), encrypted_key.secret.copy()};
|
||||
auto new_encrypted_key = decrypted_key.encrypt(input_key.local_password.copy(), encrypted_key.secret);
|
||||
CHECK(new_encrypted_key.public_key.as_octet_string() == encrypted_key.public_key.as_octet_string());
|
||||
CHECK(new_encrypted_key.secret == encrypted_key.secret);
|
||||
CHECK(new_encrypted_key.decrypt(input_key.local_password.copy()).ok().private_key.as_octet_string() ==
|
||||
decrypted_key.private_key.as_octet_string());
|
||||
kv_->set(to_file_name(key), new_encrypted_key.encrypted_data);
|
||||
return decrypted_key;
|
||||
}
|
||||
}
|
||||
TRY_RESULT_PREFIX(decrypted_key, encrypted_key.decrypt(std::move(input_key.local_password)),
|
||||
TonlibError::KeyDecrypt());
|
||||
return decrypted_key;
|
||||
return std::move(decrypted_key);
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::ExportedKey> KeyStorage::export_key(InputKey input_key) {
|
||||
@ -139,14 +154,9 @@ td::Result<KeyStorage::ExportedPemKey> KeyStorage::export_pem_key(InputKey input
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::change_local_password(InputKey input_key, td::Slice new_local_password) {
|
||||
auto new_secret =
|
||||
DecryptedKey::change_local_password(input_key.key.secret, input_key.local_password, new_local_password);
|
||||
Key res;
|
||||
res.public_key = std::move(input_key.key.public_key);
|
||||
res.secret = std::move(new_secret);
|
||||
TRY_RESULT_PREFIX(value, kv_->get(to_file_name(input_key.key)), TonlibError::KeyUnknown());
|
||||
TRY_STATUS_PREFIX(kv_->add(to_file_name(res), value), TonlibError::Internal());
|
||||
return std::move(res);
|
||||
auto old_name = to_file_name(input_key.key);
|
||||
TRY_RESULT(decrypted_key, export_decrypted_key(std::move(input_key)));
|
||||
return save_key(std::move(decrypted_key), new_local_password);
|
||||
}
|
||||
|
||||
td::Result<KeyStorage::Key> KeyStorage::import_pem_key(td::Slice local_password, td::Slice key_password,
|
||||
|
@ -39,7 +39,7 @@ class KeyValueDir : public KeyValue {
|
||||
}
|
||||
|
||||
td::Status erase(td::Slice key) override {
|
||||
return td::unlink(key.str());
|
||||
return td::unlink(to_file_path(key.str()));
|
||||
}
|
||||
|
||||
void foreach_key(std::function<void(td::Slice)> f) override {
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace tonlib {
|
||||
class KeyValue {
|
||||
public:
|
||||
|
@ -32,7 +32,8 @@ namespace tonlib {
|
||||
//
|
||||
td::StringBuilder& operator<<(td::StringBuilder& sb, const LastBlockState& state) {
|
||||
return sb << td::tag("last_block", state.last_block_id.to_str())
|
||||
<< td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime);
|
||||
<< td::tag("last_key_block", state.last_key_block_id.to_str()) << td::tag("utime", state.utime)
|
||||
<< td::tag("init_block", state.init_block_id.to_str());
|
||||
}
|
||||
|
||||
LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, td::unique_ptr<Callback> callback)
|
||||
@ -40,8 +41,7 @@ LastBlock::LastBlock(ExtClientRef client, LastBlockState state, Config config, t
|
||||
client_.set_client(client);
|
||||
state_.last_block_id = state_.last_key_block_id;
|
||||
|
||||
VLOG(last_block) << "check_init_block: skip - FIXME before release";
|
||||
check_init_block_state_ = QueryState::Done;
|
||||
VLOG(last_block) << "State: " << state_;
|
||||
}
|
||||
|
||||
void LastBlock::get_last_block(td::Promise<LastBlockState> promise) {
|
||||
@ -87,7 +87,7 @@ void LastBlock::sync_loop() {
|
||||
} else {
|
||||
check_init_block_state_ = QueryState::Active;
|
||||
check_init_block_stats_.start();
|
||||
if (state_.last_block_id.id.seqno >= config_.init_block_id.id.seqno) {
|
||||
if (state_.last_key_block_id.id.seqno >= config_.init_block_id.id.seqno) {
|
||||
VLOG(last_block) << "check_init_block: start - init_block -> last_block";
|
||||
do_check_init_block(config_.init_block_id, state_.last_key_block_id);
|
||||
} else {
|
||||
@ -136,7 +136,7 @@ td::Result<std::unique_ptr<block::BlockProofChain>> LastBlock::process_block_pro
|
||||
TRY_RESULT(block_proof, std::move(r_block_proof)); //TODO: it is fatal?
|
||||
TRY_RESULT_PREFIX(chain, TRY_VM(process_block_proof(from, std::move(block_proof))),
|
||||
TonlibError::ValidateBlockProof());
|
||||
return chain;
|
||||
return std::move(chain);
|
||||
}
|
||||
|
||||
td::Result<std::unique_ptr<block::BlockProofChain>> LastBlock::process_block_proof(
|
||||
@ -148,7 +148,7 @@ td::Result<std::unique_ptr<block::BlockProofChain>> LastBlock::process_block_pro
|
||||
<< ", not from requested block " << from.to_str());
|
||||
}
|
||||
TRY_STATUS(chain->validate());
|
||||
return chain;
|
||||
return std::move(chain);
|
||||
}
|
||||
|
||||
void LastBlock::update_state(block::BlockProofChain& chain) {
|
||||
@ -162,10 +162,18 @@ void LastBlock::update_state(block::BlockProofChain& chain) {
|
||||
update_utime(chain.last_utime);
|
||||
}
|
||||
if (is_changed) {
|
||||
callback_->on_state_changed(state_);
|
||||
save_state();
|
||||
}
|
||||
}
|
||||
|
||||
void LastBlock::save_state() {
|
||||
if (check_init_block_state_ != QueryState::Done) {
|
||||
VLOG(last_block) << "skip `save_state` because `check_init_block` is not finished";
|
||||
return;
|
||||
}
|
||||
callback_->on_state_changed(state_);
|
||||
}
|
||||
|
||||
void LastBlock::on_block_proof(
|
||||
ton::BlockIdExt from,
|
||||
td::Result<ton::ton_api::object_ptr<ton::lite_api::liteServer_partialBlockProof>> r_block_proof) {
|
||||
@ -209,6 +217,9 @@ void LastBlock::on_init_block_proof(
|
||||
if (chain->complete) {
|
||||
VLOG(last_block) << "check_init_block: done\n" << check_init_block_stats_;
|
||||
check_init_block_state_ = QueryState::Done;
|
||||
if (update_init_block(config_.init_block_id)) {
|
||||
save_state();
|
||||
}
|
||||
sync_loop();
|
||||
} else {
|
||||
do_check_init_block(chain->to, to);
|
||||
@ -291,6 +302,22 @@ bool LastBlock::update_mc_last_key_block(ton::BlockIdExt mc_key_block_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LastBlock::update_init_block(ton::BlockIdExt init_block_id) {
|
||||
if (has_fatal_error()) {
|
||||
return false;
|
||||
}
|
||||
if (!init_block_id.is_valid()) {
|
||||
LOG(ERROR) << "Ignore invalid init block";
|
||||
return false;
|
||||
}
|
||||
if (state_.init_block_id != init_block_id) {
|
||||
state_.init_block_id = init_block_id;
|
||||
LOG(INFO) << "Update init block id: " << state_.init_block_id.to_str();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LastBlock::update_utime(td::int64 utime) {
|
||||
if (state_.utime < utime) {
|
||||
state_.utime = utime;
|
||||
|
@ -201,7 +201,9 @@ class LastBlock : public td::actor::Actor {
|
||||
bool update_mc_last_block(ton::BlockIdExt mc_block_id);
|
||||
bool update_mc_last_key_block(ton::BlockIdExt mc_key_block_id);
|
||||
void update_utime(td::int64 utime);
|
||||
bool update_init_block(ton::BlockIdExt init_block_id);
|
||||
|
||||
void save_state();
|
||||
void on_sync_ok();
|
||||
void on_sync_error(td::Status status);
|
||||
void on_fatal_error(td::Status status);
|
||||
|
@ -48,7 +48,7 @@ td::Ref<vm::Cell> TestWallet::make_a_gift_message(const td::Ed25519::PrivateKey&
|
||||
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
|
||||
.store_long(dest_address.workchain, 8)
|
||||
.store_int256(dest_addr, 256);
|
||||
td::int8 send_mode = 3;
|
||||
td::int32 send_mode = 3;
|
||||
if (gramms == -1) {
|
||||
gramms = 0;
|
||||
send_mode += 128;
|
||||
|
@ -108,7 +108,6 @@ class GetTransactionHistory : public td::actor::Actor {
|
||||
|
||||
void check(td::Status status) {
|
||||
if (status.is_error()) {
|
||||
LOG(ERROR) << status;
|
||||
promise_.set_error(std::move(status));
|
||||
stop();
|
||||
}
|
||||
@ -208,7 +207,7 @@ class GetRawAccountState : public td::actor::Actor {
|
||||
auto cell = res.info.root;
|
||||
std::ostringstream outp;
|
||||
block::gen::t_Account.print_ref(outp, cell);
|
||||
LOG(ERROR) << outp.str();
|
||||
LOG(INFO) << outp.str();
|
||||
if (cell.is_null()) {
|
||||
return res;
|
||||
}
|
||||
@ -261,7 +260,8 @@ class GetRawAccountState : public td::actor::Actor {
|
||||
ton::lite_api::liteServer_getAccountState(
|
||||
ton::create_tl_lite_block_id(last_block_.last_block_id),
|
||||
ton::create_tl_object<ton::lite_api::liteServer_accountId>(address_.workchain, address_.addr)),
|
||||
[self = this](auto r_state) { self->with_account_state(std::move(r_state)); });
|
||||
[self = this](auto r_state) { self->with_account_state(std::move(r_state)); },
|
||||
last_block_.last_block_id.id.seqno);
|
||||
return td::Status::OK();
|
||||
}
|
||||
|
||||
@ -681,8 +681,9 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_accountState>> to_raw_accountS
|
||||
.as_slice()
|
||||
.str();
|
||||
}
|
||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(
|
||||
raw_state.balance, std::move(code), std::move(data), to_transaction_id(raw_state.info), raw_state.info.gen_utime);
|
||||
return tonlib_api::make_object<tonlib_api::raw_accountState>(raw_state.balance, std::move(code), std::move(data),
|
||||
to_transaction_id(raw_state.info), raw_state.frozen_hash,
|
||||
raw_state.info.gen_utime);
|
||||
}
|
||||
|
||||
td::Result<std::string> to_std_address_or_throw(td::Ref<vm::CellSlice> cs) {
|
||||
@ -802,7 +803,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::raw_transaction>> to_raw_transacti
|
||||
|
||||
std::ostringstream outp;
|
||||
block::gen::t_Transaction.print_ref(outp, info.transaction);
|
||||
LOG(ERROR) << outp.str();
|
||||
LOG(INFO) << outp.str();
|
||||
|
||||
auto is_just = trans.r1.in_msg->prefetch_long(1);
|
||||
if (is_just == trans.r1.in_msg->fetch_long_eof) {
|
||||
@ -916,7 +917,7 @@ td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> to_generic_
|
||||
if (raw_state.code.is_null()) {
|
||||
return tonlib_api::make_object<tonlib_api::generic_accountStateUninited>(
|
||||
tonlib_api::make_object<tonlib_api::uninited_accountState>(raw_state.balance, to_transaction_id(raw_state.info),
|
||||
raw_state.info.gen_utime));
|
||||
raw_state.frozen_hash, raw_state.info.gen_utime));
|
||||
}
|
||||
|
||||
auto code_hash = raw_state.code->prefetch_ref()->get_hash();
|
||||
@ -952,7 +953,6 @@ td::Status TonlibClient::do_request(const tonlib_api::raw_sendMessage& request,
|
||||
client_.send_query(ton::lite_api::liteServer_sendMessage(vm::std_boc_serialize(message).move_as_ok()),
|
||||
[promise = std::move(promise)](auto r_info) mutable {
|
||||
TRY_RESULT_PROMISE(promise, info, std::move(r_info));
|
||||
LOG(ERROR) << "info: " << to_string(info);
|
||||
promise.set_value(tonlib_api::make_object<tonlib_api::ok>());
|
||||
});
|
||||
return td::Status::OK();
|
||||
@ -1041,7 +1041,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testWallet_sendGrams& requ
|
||||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||
auto address = GenericAccount::get_address(
|
||||
0 /*zerochain*/, TestWallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
||||
@ -1115,7 +1114,6 @@ td::Status TonlibClient::do_request(const tonlib_api::wallet_sendGrams& request,
|
||||
TRY_RESULT_PREFIX(valid_until, td::narrow_cast_safe<td::uint32>(request.valid_until_),
|
||||
TonlibError::InvalidField("valid_until", "overflow"));
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
TRY_RESULT(input_key, from_tonlib(*request.private_key_));
|
||||
auto address = GenericAccount::get_address(
|
||||
0 /*zerochain*/, Wallet::get_init_state(td::Ed25519::PublicKey(input_key.key.public_key.copy())));
|
||||
@ -1167,7 +1165,6 @@ td::Status TonlibClient::do_request(const tonlib_api::testGiver_sendGrams& reque
|
||||
return TonlibError::MessageTooLong();
|
||||
}
|
||||
TRY_RESULT(account_address, get_account_address(request.destination_->account_address_));
|
||||
account_address.bounceable = false;
|
||||
auto message = TestGiver::make_a_gift_message(request.seqno_, request.amount_, request.message_, account_address);
|
||||
auto message_hash = message->get_hash().as_slice().str();
|
||||
td::Promise<object_ptr<tonlib_api::ok>> new_promise =
|
||||
@ -1244,7 +1241,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||
block::StdAddress source_address_;
|
||||
|
||||
tonlib_api::object_ptr<tonlib_api::generic_AccountState> destination_state_;
|
||||
bool is_destination_bounce_{false};
|
||||
bool is_destination_bounceable_{false};
|
||||
|
||||
void check(td::Status status) {
|
||||
if (status.is_error()) {
|
||||
@ -1262,7 +1259,7 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||
return TonlibError::EmptyField("destination");
|
||||
}
|
||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
||||
is_destination_bounce_ = destination_address.bounceable;
|
||||
is_destination_bounceable_ = destination_address.bounceable;
|
||||
|
||||
if (!send_grams_.source_) {
|
||||
return TonlibError::EmptyField("destination");
|
||||
@ -1332,9 +1329,23 @@ class GenericSendGrams : public TonlibQueryActor {
|
||||
td::Status do_on_destination_state(td::Result<tonlib_api::object_ptr<tonlib_api::generic_AccountState>> r_state) {
|
||||
TRY_RESULT(state, std::move(r_state));
|
||||
destination_state_ = std::move(state);
|
||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounce_ &&
|
||||
!send_grams_.allow_send_to_uninited_) {
|
||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
||||
if (destination_state_->get_id() == tonlib_api::generic_accountStateUninited::ID && is_destination_bounceable_) {
|
||||
//FIXME: after restoration of frozen accounts will be supported
|
||||
if (!static_cast<tonlib_api::generic_accountStateUninited&>(*destination_state_)
|
||||
.account_state_->frozen_hash_.empty()) {
|
||||
return TonlibError::TransferToFrozen();
|
||||
//return TonlibError::DangerousTransaction("Transfer to frozen wallet");
|
||||
}
|
||||
if (send_grams_.allow_send_to_uninited_) {
|
||||
TRY_RESULT(destination_address, get_account_address(send_grams_.destination_->account_address_));
|
||||
destination_address.bounceable = false;
|
||||
auto new_destination_address = destination_address.rserialize(true);
|
||||
LOG(INFO) << "Change destination address from bounceable to non-bounceable "
|
||||
<< send_grams_.destination_->account_address_ << " -> " << new_destination_address;
|
||||
send_grams_.destination_->account_address_ = std::move(new_destination_address);
|
||||
} else {
|
||||
return TonlibError::DangerousTransaction("Transfer to uninited wallet");
|
||||
}
|
||||
}
|
||||
return do_loop();
|
||||
}
|
||||
|
@ -128,6 +128,9 @@ struct TonlibError {
|
||||
static td::Status NotEnoughFunds() {
|
||||
return td::Status::Error(500, "NOT_ENOUGH_FUNDS");
|
||||
}
|
||||
static td::Status TransferToFrozen() {
|
||||
return td::Status::Error(500, "TRANSFER_TO_FROZEN");
|
||||
}
|
||||
|
||||
static td::Status LiteServer(td::int32 code, td::Slice message) {
|
||||
auto f = [&](td::Slice code_description) { return LiteServer(code, code_description, message); };
|
||||
|
@ -54,7 +54,7 @@ td::Ref<vm::Cell> Wallet::make_a_gift_message(const td::Ed25519::PrivateKey& pri
|
||||
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
|
||||
.store_long(dest_address.workchain, 8)
|
||||
.store_int256(dest_addr, 256);
|
||||
td::int8 send_mode = 3;
|
||||
td::int32 send_mode = 3;
|
||||
if (gramms == -1) {
|
||||
gramms = 0;
|
||||
send_mode += 128;
|
||||
|
@ -35,40 +35,17 @@ DecryptedKey::DecryptedKey(RawDecryptedKey key)
|
||||
: DecryptedKey(std::move(key.mnemonic_words), td::Ed25519::PrivateKey(key.private_key.copy())) {
|
||||
}
|
||||
|
||||
td::SecureString DecryptedKey::change_local_password(td::Slice secret_str, td::Slice old_local_password,
|
||||
td::Slice new_local_password) {
|
||||
CHECK(secret_str.size() == 32);
|
||||
td::SecureString old_local_password_hash(32);
|
||||
sha256(old_local_password, old_local_password_hash.as_mutable_slice());
|
||||
td::SecureString new_local_password_hash(32);
|
||||
sha256(new_local_password, new_local_password_hash.as_mutable_slice());
|
||||
|
||||
td::SecureString new_secret(32);
|
||||
for (size_t i = 0; i < new_secret.size(); i++) {
|
||||
new_secret.as_mutable_slice()[i] =
|
||||
secret_str[i] ^ old_local_password_hash.as_slice()[i] ^ new_local_password_hash.as_slice()[i];
|
||||
}
|
||||
return new_secret;
|
||||
}
|
||||
|
||||
EncryptedKey DecryptedKey::encrypt(td::Slice local_password, td::Slice old_secret) const {
|
||||
LOG(ERROR) << "encrypt";
|
||||
td::SecureString secret(32);
|
||||
if (old_secret.size() == td::as_slice(secret).size()) {
|
||||
secret.as_mutable_slice().copy_from(old_secret);
|
||||
} else {
|
||||
td::Random::secure_bytes(secret.as_mutable_slice());
|
||||
}
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
td::SecureString decrypted_secret(32);
|
||||
for (size_t i = 0; i < decrypted_secret.size(); i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
td::SecureString decrypted_secret = SimpleEncryption::combine_secrets(secret, local_password);
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS,
|
||||
encryption_secret.as_mutable_slice());
|
||||
td::SecureString encryption_secret =
|
||||
SimpleEncryption::kdf(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS);
|
||||
|
||||
std::vector<td::SecureString> mnemonic_words_copy;
|
||||
for (auto &w : mnemonic_words) {
|
||||
|
@ -56,8 +56,6 @@ struct DecryptedKey {
|
||||
std::vector<td::SecureString> mnemonic_words;
|
||||
td::Ed25519::PrivateKey private_key;
|
||||
|
||||
static td::SecureString change_local_password(td::Slice secret, td::Slice old_local_password,
|
||||
td::Slice new_local_password);
|
||||
EncryptedKey encrypt(td::Slice local_password, td::Slice secret = {}) const;
|
||||
};
|
||||
|
||||
|
@ -24,19 +24,25 @@
|
||||
#include "td/utils/crypto.h"
|
||||
|
||||
namespace tonlib {
|
||||
td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool check_public_key) {
|
||||
td::Result<DecryptedKey> EncryptedKey::decrypt(td::Slice local_password, bool check_public_key, bool old) const {
|
||||
if (secret.size() != 32) {
|
||||
return td::Status::Error("Failed to decrypt key: invalid secret size");
|
||||
}
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
td::SecureString decrypted_secret(32);
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
td::SecureString decrypted_secret;
|
||||
if (old) {
|
||||
decrypted_secret = td::SecureString(32);
|
||||
td::SecureString local_password_hash(32);
|
||||
sha256(local_password, local_password_hash.as_mutable_slice());
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
decrypted_secret.as_mutable_slice()[i] = secret.as_slice()[i] ^ local_password_hash.as_slice()[i];
|
||||
}
|
||||
} else {
|
||||
decrypted_secret = SimpleEncryption::combine_secrets(secret, local_password);
|
||||
}
|
||||
|
||||
td::SecureString encryption_secret(64);
|
||||
pbkdf2_sha512(as_slice(decrypted_secret), "TON local key", PBKDF_ITERATIONS, encryption_secret.as_mutable_slice());
|
||||
td::SecureString encryption_secret =
|
||||
SimpleEncryption::kdf(as_slice(decrypted_secret), "TON local key", EncryptedKey::PBKDF_ITERATIONS);
|
||||
|
||||
TRY_RESULT(decrypted_data, SimpleEncryption::decrypt_data(as_slice(encrypted_data), as_slice(encryption_secret)));
|
||||
|
||||
RawDecryptedKey raw_decrypted_key;
|
||||
|
@ -32,7 +32,7 @@ struct EncryptedKey {
|
||||
td::Ed25519::PublicKey public_key;
|
||||
td::SecureString secret;
|
||||
|
||||
td::Result<DecryptedKey> decrypt(td::Slice local_password, bool check_public_key = true);
|
||||
td::Result<DecryptedKey> decrypt(td::Slice local_password, bool check_public_key = true, bool old = false) const;
|
||||
};
|
||||
|
||||
} // namespace tonlib
|
||||
|
@ -50,6 +50,12 @@ td::SecureString SimpleEncryption::combine_secrets(td::Slice a, td::Slice b) {
|
||||
return res;
|
||||
}
|
||||
|
||||
td::SecureString SimpleEncryption::kdf(td::Slice secret, td::Slice password, int iterations) {
|
||||
td::SecureString new_secret(64);
|
||||
pbkdf2_sha512(secret, password, iterations, new_secret.as_mutable_slice());
|
||||
return new_secret;
|
||||
}
|
||||
|
||||
td::SecureString SimpleEncryption::encrypt_data_with_prefix(td::Slice data, td::Slice secret) {
|
||||
CHECK(data.size() % 16 == 0);
|
||||
auto data_hash = sha256(data);
|
||||
|
@ -27,13 +27,14 @@ class SimpleEncryption {
|
||||
public:
|
||||
static td::SecureString encrypt_data(td::Slice data, td::Slice secret);
|
||||
static td::Result<td::SecureString> decrypt_data(td::Slice encrypted_data, td::Slice secret);
|
||||
static td::SecureString combine_secrets(td::Slice a, td::Slice b);
|
||||
static td::SecureString kdf(td::Slice secret, td::Slice password, int iterations);
|
||||
|
||||
private:
|
||||
static td::AesCbcState calc_aes_cbc_state_hash(td::Slice hash);
|
||||
static td::AesCbcState calc_aes_cbc_state_sha512(td::Slice seed);
|
||||
static td::SecureString gen_random_prefix(td::int64 data_size);
|
||||
|
||||
static td::SecureString combine_secrets(td::Slice a, td::Slice b);
|
||||
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret);
|
||||
};
|
||||
} // namespace tonlib
|
||||
|
@ -186,11 +186,21 @@ class TonlibCli : public td::actor::Actor {
|
||||
if (cmd.empty()) {
|
||||
return;
|
||||
}
|
||||
auto to_bool = [](td::Slice word, bool def = false) {
|
||||
if (word.empty()) {
|
||||
return def;
|
||||
}
|
||||
if (word == "0" || word == "FALSE" || word == "false") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (cmd == "help") {
|
||||
td::TerminalIO::out() << "help - show this help\n";
|
||||
td::TerminalIO::out() << "genkey - generate new secret key\n";
|
||||
td::TerminalIO::out() << "keys - show all stored keys\n";
|
||||
td::TerminalIO::out() << "unpackaddress <address> - validate and parse address\n";
|
||||
td::TerminalIO::out() << "setbounceble <address> [<bounceble>] - change bounceble flag in address\n";
|
||||
td::TerminalIO::out() << "importkey - import key\n";
|
||||
td::TerminalIO::out() << "deletekeys - delete ALL PRIVATE KEYS\n";
|
||||
td::TerminalIO::out() << "exportkey [<key_id>] - export key\n";
|
||||
@ -214,6 +224,8 @@ class TonlibCli : public td::actor::Actor {
|
||||
try_stop();
|
||||
} else if (cmd == "keys") {
|
||||
dump_keys();
|
||||
} else if (cmd == "deletekey") {
|
||||
//delete_key(parser.read_word());
|
||||
} else if (cmd == "deletekeys") {
|
||||
delete_all_keys();
|
||||
} else if (cmd == "exportkey") {
|
||||
@ -223,15 +235,6 @@ class TonlibCli : public td::actor::Actor {
|
||||
} else if (cmd == "setconfig") {
|
||||
auto config = parser.read_word();
|
||||
auto name = parser.read_word();
|
||||
auto to_bool = [](td::Slice word) {
|
||||
if (word.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (word == "0" || word == "FALSE" || word == "false") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto use_callback = parser.read_word();
|
||||
auto force = parser.read_word();
|
||||
set_config(config, name, to_bool(use_callback), to_bool(force));
|
||||
@ -251,6 +254,10 @@ class TonlibCli : public td::actor::Actor {
|
||||
get_hints(parser.read_word());
|
||||
} else if (cmd == "unpackaddress") {
|
||||
unpack_address(parser.read_word());
|
||||
} else if (cmd == "setbounceable") {
|
||||
auto addr = parser.read_word();
|
||||
auto bounceable = parser.read_word();
|
||||
set_bounceable(addr, to_bool(bounceable, true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,6 +332,26 @@ class TonlibCli : public td::actor::Actor {
|
||||
});
|
||||
}
|
||||
|
||||
void set_bounceable(td::Slice addr, bool bounceable) {
|
||||
send_query(tonlib_api::make_object<tonlib_api::unpackAccountAddress>(addr.str()),
|
||||
[addr = addr.str(), bounceable, this](auto r_parsed_addr) mutable {
|
||||
if (r_parsed_addr.is_error()) {
|
||||
LOG(ERROR) << "Failed to parse address: " << r_parsed_addr.error();
|
||||
return;
|
||||
}
|
||||
auto parsed_addr = r_parsed_addr.move_as_ok();
|
||||
parsed_addr->bounceable_ = bounceable;
|
||||
this->send_query(tonlib_api::make_object<tonlib_api::packAccountAddress>(std::move(parsed_addr)),
|
||||
[](auto r_addr) mutable {
|
||||
if (r_addr.is_error()) {
|
||||
LOG(ERROR) << "Failed to pack address";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << r_addr.ok()->account_address_ << "\n";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void generate_key(td::SecureString entropy = {}) {
|
||||
if (entropy.size() < 20) {
|
||||
td::TerminalIO::out() << "Enter some entropy";
|
||||
@ -527,6 +554,25 @@ class TonlibCli : public td::actor::Actor {
|
||||
return std::move(res);
|
||||
}
|
||||
|
||||
void delete_key(td::Slice key) {
|
||||
auto r_key_i = to_key_i(key);
|
||||
if (r_key_i.is_error()) {
|
||||
td::TerminalIO::out() << "Unknown key id: [" << key << "]\n";
|
||||
return;
|
||||
}
|
||||
using tonlib_api::make_object;
|
||||
auto key_i = r_key_i.move_as_ok();
|
||||
send_query(make_object<tonlib_api::deleteKey>(
|
||||
make_object<tonlib_api::key>(keys_[key_i].public_key, keys_[key_i].secret.copy())),
|
||||
|
||||
[key = key.str()](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't delete key id: [" << key << "] " << r_res.error() << "\n";
|
||||
return;
|
||||
}
|
||||
td::TerminalIO::out() << "Ok\n";
|
||||
});
|
||||
}
|
||||
void export_key(td::Slice key) {
|
||||
if (key.empty()) {
|
||||
dump_keys();
|
||||
@ -754,6 +800,11 @@ class TonlibCli : public td::actor::Actor {
|
||||
}
|
||||
void transfer(Address from, Address to, td::uint64 grams, td::Slice password, td::Slice message,
|
||||
bool allow_send_to_uninited) {
|
||||
auto r_sz = td::to_integer_safe<td::size_t>(message);
|
||||
auto msg = message.str();
|
||||
if (r_sz.is_ok()) {
|
||||
msg = std::string(r_sz.ok(), 'Z');
|
||||
}
|
||||
using tonlib_api::make_object;
|
||||
auto key = !from.secret.empty()
|
||||
? make_object<tonlib_api::inputKey>(
|
||||
@ -761,7 +812,7 @@ class TonlibCli : public td::actor::Actor {
|
||||
: nullptr;
|
||||
send_query(
|
||||
make_object<tonlib_api::generic_sendGrams>(std::move(key), std::move(from.address), std::move(to.address),
|
||||
grams, 30, allow_send_to_uninited, message.str()),
|
||||
grams, 60, allow_send_to_uninited, std::move(msg)),
|
||||
[this](auto r_res) {
|
||||
if (r_res.is_error()) {
|
||||
td::TerminalIO::out() << "Can't transfer: " << r_res.error() << "\n";
|
||||
@ -881,6 +932,10 @@ int main(int argc, char* argv[]) {
|
||||
options.config = std::move(data);
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('N', "config-name", "set lite server config name", [&](td::Slice arg) {
|
||||
options.name = arg.str();
|
||||
return td::Status::OK();
|
||||
});
|
||||
p.add_option('n', "use-callbacks-for-network", "do not use this", [&]() {
|
||||
options.use_callbacks_for_network = true;
|
||||
return td::Status::OK();
|
||||
|
Loading…
x
Reference in New Issue
Block a user