|
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