Skip to content

Commit ac9fc3a

Browse files
authored
Merge pull request #478 from ton-blockchain/upd-dns-smartcontracts
auto-dns & manual-dns smartcontracts updated to actual DNS standard
2 parents 1ded7af + 313d37e commit ac9fc3a

File tree

4 files changed

+61
-26
lines changed

4 files changed

+61
-26
lines changed

crypto/smartcont/auto-dns.fif

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ $# 4 > need-params <> abort"extra parameters, or no parameters for chosen main o
4343
variable Values dictnew Values !
4444
// ( i c -- )
4545
{ over 0= abort"category cannot be zero"
46-
<b swap ref, swap Values @ 16 b>idict!+ not abort"duplicate category id"
46+
<b swap ref, swap Values @ 256 b>udict!+ not abort"duplicate category id"
4747
Values !
4848
} : register-value
4949

5050
{ @end? abort"category number expected" @next (number) 1 <> abort"category must be integer"
51-
dup 16 fits not abort"category does not fit into 16 bit integer"
51+
dup 256 fits not abort"category does not fit into 256 bit integer"
5252
dup 0= abort"category must be non-zero"
5353
} : parse-cat-num
5454
{ @end? abort"smart contract address expected"

crypto/smartcont/dns-auto-code.fc

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@
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
;;===========================================================================;;
@@ -19,7 +26,7 @@
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
}

crypto/smartcont/dns-manual-code.fc

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@
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

1213
;;===========================================================================;;
1314
;; Custom ASM instructions ;;
1415
;;===========================================================================;;
1516

17+
cell udict_get_ref_(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETOPTREF";
18+
1619
(cell, ()) pfxdict_set_ref(cell dict, int key_len, slice key, cell value) {
1720
throw_unless(33, dict~pfxdict_set?(key_len, key, begin_cell().store_maybe_ref(value).end_cell().begin_parse()));
1821
return (dict, ());
@@ -67,9 +70,9 @@
6770
Operations (continuation of message):
6871
00 Contract initialization message (only if seqno = 0) (x=-)
6972
11 VSet: set specified value to specified subdomain->category (x=2)
70-
[Int<16b>:category] [Name<?>:subdomain] [Cell<1r>:value]
73+
[UInt<256b>:category] [Name<?>:subdomain] [Cell<1r>:value]
7174
12 VDel: delete specified subdomain->category (x=2)
72-
[Int<16b>:category] [Name<?>:subdomain]
75+
[UInt<256b>:category] [Name<?>:subdomain]
7376
21 DSet: replace entire category dictionary of domain with provided (x=0)
7477
[Name<?>:subdomain] [Cell<1r>:new_cat_table]
7578
22 DDel: delete entire category dictionary of specified domain (x=0)
@@ -112,7 +115,7 @@
112115
int cat = 0;
113116
if (op < 20) {
114117
;; for operations with codes 10..19 category is required
115-
cat = ops~load_int(16);
118+
cat = ops~load_uint(256); ;; update: category length now u256 instead of i16
116119
}
117120
slice name = null(); ;; any slice value
118121
cell cat_table = null();
@@ -159,13 +162,13 @@
159162
;; 11 VSet: set specified value to specified subdomain->category
160163
if (op == 11) {
161164
cell new_value = ops~load_maybe_ref();
162-
cat_table~idict_set_get_ref(16, cat, new_value);
165+
cat_table~udict_set_get_ref(256, cat, new_value); ;; update: category length now u256 instead of i16
163166
root~pfxdict_set_ref(1023, name, cat_table);
164167
return (root, ops);
165168
}
166169
;; 12 VDel: delete specified subdomain->category value
167170
if (op == 12) {
168-
if (cat_table~idict_delete?(16, cat)) {
171+
if (cat_table~udict_delete?(256, cat)) { ;; update: category length now u256 instead of i16
169172
root~pfxdict_set_ref(1023, name, cat_table);
170173
}
171174
return (root, ops);
@@ -261,7 +264,7 @@ cell process_ops(cell root, slice ops) inline_ref {
261264
Data structure:
262265
Root cell: [UInt<32b>:seqno] [UInt<256b>:owner_public_key]
263266
[OptRef<1b+1r?>:Hashmap<PfxDict:Slice->CatTable>:domains]
264-
<CatTable> := HashmapE 16 ^DNSRecord
267+
<CatTable> := HashmapE 256 (~~16~~) ^DNSRecord
265268

266269
STORED DOMAIN NAME SLICE FORMAT: (#ZeroChars<7b>) (Domain name value)
267270
#Zeros allows to simultaneously store, for example, com\0 and com\0google\0
@@ -291,7 +294,8 @@ int get_public_key() method_id {
291294
(int, cell) dnsresolve(slice subdomain, int category) method_id {
292295
int bits = subdomain.slice_bits();
293296
ifnot (bits) {
294-
return (0, null()); ;; zero-length input
297+
;; return (0, null()); ;; zero-length input
298+
throw(30); ;; update: throw exception for empty input
295299
}
296300
throw_if(30, bits & 7); ;; malformed input (~ 8n-bit)
297301

@@ -302,7 +306,14 @@ int get_public_key() method_id {
302306
bits += 8;
303307
}
304308
if (bits == 8) {
305-
return (0, null()); ;; zero-length input, but with zero byte
309+
return (8, null()); ;; zero-length input, but with zero byte
310+
;; update: return 8 as resolved, but with no data
311+
}
312+
int name_first_byte = subdomain.preload_uint(8);
313+
if (name_first_byte == 0) {
314+
;; update: remove prefix \0
315+
subdomain~load_uint(8);
316+
bits -= 8;
306317
}
307318
(_, _, _, cell root, _) = load_data();
308319

@@ -332,7 +343,9 @@ int get_public_key() method_id {
332343
zeros = - zeros;
333344

334345
ifnot (tail.slice_empty?()) { ;; if we have tail then len(pfx) < len(subdomain)
335-
category = -1; ;; incomplete subdomain found, must return next resolver (-1)
346+
;; incomplete subdomain found, must return next resolver
347+
category = "dns_next_resolver"H; ;; 0x19f02441ee588fdb26ee24b2568dd035c3c9206e11ab979be62e55558a1d17ff
348+
;; update: next resolver is now sha256("dns_next_resolver") instead of -1
336349
}
337350
int pfx_bits = pfx.slice_bits() - 7;
338351
cell cat_table = val;
@@ -342,7 +355,7 @@ int get_public_key() method_id {
342355
if (category == 0) {
343356
return (pfx_bits, cat_table); ;; return cell with entire dictionary for 0
344357
} else {
345-
cell cat_found = cat_table.idict_get_ref(16, category);
358+
cell cat_found = cat_table.udict_get_ref_(256, category); ;; update: category length now u256 instead of i16
346359
return (pfx_bits, cat_found);
347360
}
348361
}

crypto/smartcont/manual-dns-manage.fif

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ variable Actions
4242
{ @end? abort"subdomain name expected" @next dup $len 127 > abort"subdomain name too long"
4343
} : parse-domain
4444
{ @end? abort"category number expected" @next (number) 1 <> abort"category must be integer"
45-
dup 16 fits not abort"category does not fit into 16 bit integer"
45+
dup 256 fits not abort"category does not fit into 256 bit integer"
4646
dup 0= abort"category must be non-zero"
4747
} : parse-cat-num
4848
{ @end? abort"`cat` expected" @next "cat" $= not abort"`cat` expected" parse-cat-num
@@ -107,11 +107,11 @@ file-base +"-dns" +contractid +".addr" load-address
107107
{ dup first
108108
dup `add eq? {
109109
drop 4 untuple <b swap value, b> -rot
110-
<b 11 6 u, swap 16 i, swap subdomain,
110+
<b 11 6 u, swap 256 u, swap subdomain,
111111
swap dict, nip } {
112112
dup `delete eq? {
113113
drop untriple rot drop
114-
<b 12 6 u, swap 16 i, swap subdomain, } {
114+
<b 12 6 u, swap 256 u, swap subdomain, } {
115115
dup `drop eq? {
116116
drop second <b 22 6 u, swap subdomain, } {
117117
dup `upgrade eq? {

0 commit comments

Comments
 (0)