77 | Author: Oleksandr Murzin (tg: @skydev / em:
[email protected] ) |
88 | October 2019 |
99 \------------------------------------------------------------------------/
10+ Updated to actual DNS standard version by starlightduck in 2022
1011-}
1112
13+ ;;===========================================================================;;
14+ ;; Custom ASM instructions ;;
15+ ;;===========================================================================;;
16+
17+ cell udict_get_ref_(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETOPTREF";
18+
1219;;===========================================================================;;
1320;; Utility functions ;;
1421;;===========================================================================;;
1926 [OptRef<1b+1r?>:Hashmap<UInt<160b>(Time|Hash128)->Slice(DomName)>:gc]
2027 [UInt<32b>:stdperiod] [Gram:PPReg] [Gram:PPCell] [Gram:PPBit]
2128 [UInt<32b>:lasthousekeeping]
22- <CatTable> := HashmapE 16 ^DNSRecord
29+ <CatTable> := HashmapE 256 (~~16~~) ^DNSRecord
2330
2431 STORED DOMAIN NAME SLICE FORMAT: (#ZeroChars<7b>) (Domain name value)
2532 #Zeros allows to simultaneously store, for example, com\0 and com\0google\0
@@ -189,6 +196,7 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
189196 store_data(ctl, domdata, gc, [stdper, ppr, ppc, ppb], nhk, lhk);
190197 return send_ok(0);
191198 }
199+ var (addr, query_id, op) = query_info;
192200 if (op == 0x4344656c) { ;; CDel = destroy smart contract
193201 ifnot (domdata.null?()) {
194202 ;; domain dictionary not empty, force gc
@@ -199,9 +207,12 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
199207 ;; domain dictionary still not empty, error
200208 return send_error(0xee74656d);
201209 }
202- var (addr, query_id, op) = query_info;
203210 return send_message(addr, 0xef6b6179, query_id, op, 0, 128 + 32);
204211 }
212+ if (op == 0x54616b65) { ;; Take = take grams from the contract
213+ var amount = in_msg~load_grams();
214+ return send_message(addr, 0xef6b6179, query_id, op, amount, 64);
215+ }
205216 return send_error(0xffffffff);
206217}
207218
@@ -289,7 +300,8 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
289300 if (exp >= n) { ;; entry not expired
290301 cell cat_table = val~load_ref();
291302 val.end_parse();
292- var (cown, ok) = cat_table.idict_get_ref?(16, -2);
303+ ;; update: category length now u256 instead of i16, owner index is now 0 instead of -2
304+ var (cown, ok) = cat_table.udict_get_ref?(256, 0);
293305 if (ok) {
294306 owner_info = cown;
295307 }
@@ -318,14 +330,15 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
318330 data = in_msg~load_ref();
319331 ;; basic integrity check of (client-provided) dictionary
320332 ifnot (data.dict_empty?()) { ;; 1000 gas!
321- var (oinfo, ok) = data.idict_get_ref?(16, -2);
333+ ;; update: category length now u256 instead of i16, owner index is now 0 instead of -2
334+ var (oinfo, ok) = data.udict_get_ref?(256, 0);
322335 if (ok) {
323336 var cs = oinfo.begin_parse();
324337 throw_unless(31, cs.slice_bits() >= 16 + 3 + 8 + 256);
325338 throw_unless(31, cs.preload_uint(19) == 0x9fd3 * 8 + 4);
326339 }
327- (_, _, int minok) = data.idict_get_min?(16);
328- (_, _, int maxok) = data.idict_get_max?(16);
340+ (_, _, int minok) = data.udict_get_min?(256); ;; update: category length now u256 instead of i16
341+ (_, _, int maxok) = data.udict_get_max?(256); ;; update: category length now u256 instead of i16
329342 throw_unless(31, minok & maxok);
330343 }
331344 } else {
@@ -410,7 +423,8 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
410423 (int bits, int refs) = domain.slice_bits_refs();
411424 throw_if(30, refs | (bits & 7)); ;; malformed input (~ 8n-bit)
412425 ifnot (bits) {
413- return (0, null(), 0, null()); ;; zero-length input
426+ ;; return (0, null(), 0, null()); ;; zero-length input
427+ throw(30); ;; update: throw exception for empty input
414428 }
415429
416430 int domain_last_byte = domain.slice_last(8).preload_uint(8);
@@ -420,7 +434,14 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
420434 bits += 8;
421435 }
422436 if (bits == 8) {
423- return (0, null(), 0, null()); ;; zero-length input, but with zero byte
437+ return (0, null(), 8, null()); ;; zero-length input, but with zero byte
438+ ;; update: return 8 as resolved, but with no data
439+ }
440+ int domain_first_byte = domain.preload_uint(8);
441+ if (domain_first_byte == 0) {
442+ ;; update: remove prefix \0
443+ domain~load_uint(8);
444+ bits -= 8;
424445 }
425446 var ds = get_data().begin_parse();
426447 (_, cell root) = (ds~load_ref(), ds~load_dict());
@@ -453,10 +474,11 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
453474(int, cell) dnsresolve(slice domain, int category) method_id {
454475 (int exp, cell cat_table, int exact?, slice pfx) = dnsdictlookup(domain, now());
455476 ifnot (exp) {
456- return (0 , null());
477+ return (exact? , null()); ;; update: reuse exact? to return 8 for \0
457478 }
458479 ifnot (exact?) { ;; incomplete subdomain found, must return next resolver (-1)
459- category = -1;
480+ category = "dns_next_resolver"H; ;; 0x19f02441ee588fdb26ee24b2568dd035c3c9206e11ab979be62e55558a1d17ff
481+ ;; update: next resolver is now sha256("dns_next_resolver") instead of -1
460482 }
461483
462484 int pfx_bits = pfx.slice_bits();
@@ -467,7 +489,7 @@ int check_owner(cell cat_table, cell owner_info, int src_wc, int src_addr, int s
467489 ifnot (category) {
468490 return (pfx_bits, cat_table); ;; return cell with entire dictionary for 0
469491 } else {
470- cell cat_found = cat_table.idict_get_ref(16 , category);
492+ cell cat_found = cat_table.udict_get_ref_(256 , category); ;; update: category length now u256 instead of i16
471493 return (pfx_bits, cat_found);
472494 }
473495}
0 commit comments