Skip to content

Commit 16824fc

Browse files
committed
[Tolk] Get rid of ton_crypto dependency, embed address parsing
Instead on 'ton_crypto', Tolk now depends on 'ton_crypto_core'. The only purpose of ton_crypto (in FunC also, btw) is address parsing: "EQCRDM9...", "0:52b3..." and so on. Such parsing has been implemented manually exactly the same way.
1 parent d9dba32 commit 16824fc

File tree

2 files changed

+76
-9
lines changed

2 files changed

+76
-9
lines changed

tolk/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ set(TOLK_SOURCE
2626

2727
add_executable(tolk tolk-main.cpp ${TOLK_SOURCE})
2828
target_include_directories(tolk PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
29-
target_link_libraries(tolk PUBLIC git ton_crypto) # todo replace with ton_crypto_core in the future
29+
target_link_libraries(tolk PUBLIC git ton_crypto_core)
3030
if (WINGETOPT_FOUND)
3131
target_link_libraries_system(tolk wingetopt)
3232
endif ()

tolk/pipe-ast-to-legacy.cpp

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
#include "compiler-state.h"
2121
#include "common/refint.h"
2222
#include "openssl/digest.hpp"
23-
#include "block/block.h"
24-
#include "block-parse.h"
23+
#include "crypto/common/util.h"
2524
#include "td/utils/crypto.h"
25+
#include "ton/ton-types.h"
2626

2727
/*
2828
* In this module, we convert modern AST representation to legacy representation
@@ -102,6 +102,64 @@ static void fire_error_invalid_mutate_arg_passed(SrcLocation loc, const SymDef*
102102
throw Fatal("unreachable");
103103
}
104104

105+
// parse address like "EQCRDM9h4k3UJdOePPuyX40mCgA4vxge5Dc5vjBR8djbEKC5"
106+
// based on unpack_std_smc_addr() from block.cpp
107+
// (which is not included to avoid linking with ton_crypto)
108+
static bool parse_friendly_address(const char packed[48], ton::WorkchainId& workchain, ton::StdSmcAddress& addr) {
109+
unsigned char buffer[36];
110+
if (!td::buff_base64_decode(td::MutableSlice{buffer, 36}, td::Slice{packed, 48}, true)) {
111+
return false;
112+
}
113+
td::uint16 crc = td::crc16(td::Slice{buffer, 34});
114+
if (buffer[34] != (crc >> 8) || buffer[35] != (crc & 0xff) || (buffer[0] & 0x3f) != 0x11) {
115+
return false;
116+
}
117+
workchain = (td::int8)buffer[1];
118+
std::memcpy(addr.data(), buffer + 2, 32);
119+
return true;
120+
}
121+
122+
// parse address like "0:527964d55cfa6eb731f4bfc07e9d025098097ef8505519e853986279bd8400d8"
123+
// based on StdAddress::parse_addr() from block.cpp
124+
// (which is not included to avoid linking with ton_crypto)
125+
static bool parse_raw_address(const std::string& acc_string, int& workchain, ton::StdSmcAddress& addr) {
126+
size_t pos = acc_string.find(':');
127+
if (pos != std::string::npos) {
128+
td::Result<int> r_wc = td::to_integer_safe<ton::WorkchainId>(acc_string.substr(0, pos));
129+
if (r_wc.is_error()) {
130+
return false;
131+
}
132+
workchain = r_wc.move_as_ok();
133+
pos++;
134+
} else {
135+
pos = 0;
136+
}
137+
if (acc_string.size() != pos + 64) {
138+
return false;
139+
}
140+
141+
for (int i = 0; i < 64; ++i) { // loop through each hex digit
142+
char c = acc_string[pos + i];
143+
int x;
144+
if (c >= '0' && c <= '9') {
145+
x = c - '0';
146+
} else if (c >= 'a' && c <= 'z') {
147+
x = c - 'a' + 10;
148+
} else if (c >= 'A' && c <= 'Z') {
149+
x = c - 'A' + 10;
150+
} else {
151+
return false;
152+
}
153+
154+
if ((i & 1) == 0) {
155+
addr.data()[i >> 1] = static_cast<unsigned char>((addr.data()[i >> 1] & 0x0F) | (x << 4));
156+
} else {
157+
addr.data()[i >> 1] = static_cast<unsigned char>((addr.data()[i >> 1] & 0xF0) | x);
158+
}
159+
}
160+
return true;
161+
}
162+
105163
namespace blk_fl {
106164
enum { end = 1, ret = 2, empty = 4 };
107165
typedef int val;
@@ -577,14 +635,23 @@ static Expr* process_expr(V<ast_string_const> v) {
577635
}
578636
break;
579637
}
580-
case 'a': { // MsgAddressInt
581-
// todo rewrite stdaddress parsing (if done, CMake dep "ton_crypto" can be replaced with "ton_crypto_core")
582-
block::StdAddress a;
583-
if (a.parse_addr(str)) {
584-
res->strval = block::tlb::MsgAddressInt().pack_std_address(a)->as_bitslice().to_hex();
585-
} else {
638+
case 'a': { // MsgAddress
639+
int workchain;
640+
ton::StdSmcAddress addr;
641+
bool correct = (str.size() == 48 && parse_friendly_address(str.data(), workchain, addr)) ||
642+
(str.size() != 48 && parse_raw_address(str, workchain, addr));
643+
if (!correct) {
586644
v->error("invalid standard address '" + str + "'");
587645
}
646+
if (workchain < -128 || workchain >= 128) {
647+
v->error("anycast addresses not supported");
648+
}
649+
650+
unsigned char data[3 + 8 + 256]; // addr_std$10 anycast:(Maybe Anycast) workchain_id:int8 address:bits256 = MsgAddressInt;
651+
td::bitstring::bits_store_long_top(data, 0, static_cast<uint64_t>(4) << (64 - 3), 3);
652+
td::bitstring::bits_store_long_top(data, 3, static_cast<uint64_t>(workchain) << (64 - 8), 8);
653+
td::bitstring::bits_memcpy(data, 3 + 8, addr.bits().ptr, 0, addr.size());
654+
res->strval = td::BitSlice{data, sizeof(data)}.to_hex();
588655
break;
589656
}
590657
case 'u': {

0 commit comments

Comments
 (0)