|
20 | 20 | #include "compiler-state.h" |
21 | 21 | #include "common/refint.h" |
22 | 22 | #include "openssl/digest.hpp" |
23 | | -#include "block/block.h" |
24 | | -#include "block-parse.h" |
| 23 | +#include "crypto/common/util.h" |
25 | 24 | #include "td/utils/crypto.h" |
| 25 | +#include "ton/ton-types.h" |
26 | 26 |
|
27 | 27 | /* |
28 | 28 | * 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* |
102 | 102 | throw Fatal("unreachable"); |
103 | 103 | } |
104 | 104 |
|
| 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 | + |
105 | 163 | namespace blk_fl { |
106 | 164 | enum { end = 1, ret = 2, empty = 4 }; |
107 | 165 | typedef int val; |
@@ -577,14 +635,23 @@ static Expr* process_expr(V<ast_string_const> v) { |
577 | 635 | } |
578 | 636 | break; |
579 | 637 | } |
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) { |
586 | 644 | v->error("invalid standard address '" + str + "'"); |
587 | 645 | } |
| 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(); |
588 | 655 | break; |
589 | 656 | } |
590 | 657 | case 'u': { |
|
0 commit comments