@@ -146,35 +146,43 @@ td::Result<DnsInterface::EntryData> DnsInterface::EntryData::from_cellslice(vm::
146146 return td::Status::Error (" Unknown entry data" );
147147}
148148
149- SmartContract::Args DnsInterface::resolve_args_raw (td::Slice encoded_name, td::int16 category) {
149+ SmartContract::Args DnsInterface::resolve_args_raw (td::Slice encoded_name, td::Bits256 category,
150+ block::StdAddress address) {
150151 SmartContract::Args res;
151152 res.set_method_id (" dnsresolve" );
152153 res.set_stack (
153- {vm::load_cell_slice_ref (vm::CellBuilder ().store_bytes (encoded_name).finalize ()), td::make_refint (category)});
154+ {vm::load_cell_slice_ref (vm::CellBuilder ().store_bytes (encoded_name).finalize ()),
155+ td::bits_to_refint (category.cbits (), 256 , false )});
156+ res.set_address (std::move (address));
154157 return res;
155158}
156159
157- td::Result<SmartContract::Args> DnsInterface::resolve_args (td::Slice name, td::int32 category_big) {
158- TRY_RESULT (category, td::narrow_cast_safe<td::int16>(category_big));
160+ td::Result<SmartContract::Args> DnsInterface::resolve_args (td::Slice name, td::Bits256 category,
161+ block::StdAddress address) {
159162 if (name.size () > get_default_max_name_size ()) {
160163 return td::Status::Error (" Name is too long" );
161164 }
162165 auto encoded_name = encode_name (name);
163- return resolve_args_raw (encoded_name, category);
166+ return resolve_args_raw (encoded_name, category, std::move (address) );
164167}
165168
166- td::Result<std::vector<DnsInterface::Entry>> DnsInterface::resolve (td::Slice name, td::int32 category) const {
169+ td::Result<std::vector<DnsInterface::Entry>> DnsInterface::resolve (td::Slice name, td::Bits256 category) const {
167170 TRY_RESULT (raw_entries, resolve_raw (name, category));
168171 std::vector<Entry> entries;
169172 entries.reserve (raw_entries.size ());
170173 for (auto & raw_entry : raw_entries) {
171174 Entry entry;
172175 entry.name = std::move (raw_entry.name );
173176 entry.category = raw_entry.category ;
174- auto cs = vm::load_cell_slice (raw_entry.data );
175- TRY_RESULT (data, EntryData::from_cellslice (cs));
176- entry.data = std::move (data);
177- entries.push_back (std::move (entry));
177+ entry.partially_resolved = raw_entry.partially_resolved ;
178+ auto cs = *raw_entry.data ;
179+ auto data = EntryData::from_cellslice (cs);
180+ if (data.is_error ()) {
181+ LOG (INFO) << " Failed to parse DNS entry: " << data.move_as_error ();
182+ } else {
183+ entry.data = data.move_as_ok ();
184+ entries.push_back (std::move (entry));
185+ }
178186 }
179187 return entries;
180188}
@@ -188,9 +196,9 @@ td::Result<std::vector<DnsInterface::Entry>> DnsInterface::resolve(td::Slice nam
188196 Inline [Name] structure: [UInt<6b>:length] [Bytes<lengthB>:data]
189197 Operations (continuation of message):
190198 00 Contract initialization message (only if seqno = 0) (x=-)
191- 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell (x=-)
199+ 31 TSet: replace ENTIRE DOMAIN TABLE with the provided tree root cell (x=-)
192200 [Cell<1r>:new_domains_table]
193- 51 OSet: replace owner public key with a new one (x=-)
201+ 51 OSet: replace owner public key with a new one (x=-)
194202 [UInt<256b>:new_public_key]
195203*/
196204// creation
@@ -233,37 +241,37 @@ td::Result<td::uint32> ManualDns::get_wallet_id_or_throw() const {
233241 return static_cast <td::uint32>(vm::load_cell_slice (state_.data ).fetch_ulong (32 ));
234242}
235243
236- td::Result<td::Ref<vm::Cell>> ManualDns::create_set_value_unsigned (td::int16 category, td::Slice name,
244+ td::Result<td::Ref<vm::Cell>> ManualDns::create_set_value_unsigned (td::Bits256 category, td::Slice name,
237245 td::Ref<vm::Cell> data) const {
238246 // 11 VSet: set specified value to specified subdomain->category (x=2)
239- // [Int<16b >:category] [Name<?>:subdomain] [Cell<1r>:value]
247+ // [Int<256b >:category] [Name<?>:subdomain] [Cell<1r>:value]
240248 vm::CellBuilder cb;
241249 cb.store_long (11 , 6 );
242- if (name.size () <= 58 - 2 ) {
243- cb.store_long (category, 16 );
250+ if (name.size () <= 58 - 32 ) {
251+ cb.store_bytes (category. as_slice () );
244252 cb.store_long (0 , 1 );
245253 cb.store_long (name.size (), 6 );
246254 cb.store_bytes (name);
247255 } else {
248- cb.store_long (category, 16 );
256+ cb.store_bytes (category. as_slice () );
249257 cb.store_long (1 , 1 );
250258 cb.store_ref (vm::CellBuilder ().store_bytes (name).finalize ());
251259 }
252260 cb.store_maybe_ref (std::move (data));
253261 return cb.finalize ();
254262}
255- td::Result<td::Ref<vm::Cell>> ManualDns::create_delete_value_unsigned (td::int16 category, td::Slice name) const {
263+ td::Result<td::Ref<vm::Cell>> ManualDns::create_delete_value_unsigned (td::Bits256 category, td::Slice name) const {
256264 // 12 VDel: delete specified subdomain->category (x=2)
257- // [Int<16b >:category] [Name<?>:subdomain]
265+ // [Int<256b >:category] [Name<?>:subdomain]
258266 vm::CellBuilder cb;
259267 cb.store_long (12 , 6 );
260- if (name.size () <= 58 - 2 ) {
261- cb.store_long (category, 16 );
268+ if (name.size () <= 58 - 32 ) {
269+ cb.store_bytes (category. as_slice () );
262270 cb.store_long (0 , 1 );
263271 cb.store_long (name.size (), 6 );
264272 cb.store_bytes (name);
265273 } else {
266- cb.store_long (category, 16 );
274+ cb.store_bytes (category. as_slice () );
267275 cb.store_long (1 , 1 );
268276 cb.store_ref (vm::CellBuilder ().store_bytes (name).finalize ());
269277 }
@@ -295,10 +303,9 @@ td::Result<td::Ref<vm::Cell>> ManualDns::create_set_all_unsigned(td::Span<Action
295303 if (o_dict.not_null ()) {
296304 o_dict->prefetch_maybe_ref (dict_root);
297305 }
298- vm::Dictionary dict (dict_root, 16 );
306+ vm::Dictionary dict (dict_root, 256 );
299307 if (!action.data .value ().is_null ()) {
300- auto key = dict.integer_key (td::make_refint (action.category ), 16 );
301- dict.set_ref (key.bits (), 16 , action.data .value ());
308+ dict.set_ref (action.category .bits (), 256 , action.data .value ());
302309 }
303310 pdict.set (ptr, ptr_size, dict.get_root ());
304311 }
@@ -340,14 +347,13 @@ td::Result<td::Ref<vm::Cell>> ManualDns::create_set_name_unsigned(td::Slice name
340347 cb.store_ref (vm::CellBuilder ().store_bytes (name).finalize ());
341348 }
342349
343- vm::Dictionary dict (16 );
350+ vm::Dictionary dict (256 );
344351
345352 for (auto & action : entries) {
346353 if (action.data .value ().is_null ()) {
347354 continue ;
348355 }
349- auto key = dict.integer_key (td::make_refint (action.category ), 16 );
350- dict.set_ref (key.bits (), 16 , action.data .value ());
356+ dict.set_ref (action.category .cbits (), 256 , action.data .value ());
351357 }
352358 cb.store_maybe_ref (dict.get_root_cell ());
353359
@@ -395,17 +401,16 @@ size_t ManualDns::get_max_name_size() const {
395401 return get_default_max_name_size ();
396402}
397403
398- td::Result<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw (td::Slice name, td::int32 category_big ) const {
399- return TRY_VM (resolve_raw_or_throw (name, category_big ));
404+ td::Result<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw (td::Slice name, td::Bits256 category ) const {
405+ return TRY_VM (resolve_raw_or_throw (name, category ));
400406}
401407td::Result<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw_or_throw (td::Slice name,
402- td::int32 category_big) const {
403- TRY_RESULT (category, td::narrow_cast_safe<td::int16>(category_big));
408+ td::Bits256 category) const {
404409 if (name.size () > get_max_name_size ()) {
405410 return td::Status::Error (" Name is too long" );
406411 }
407412 auto encoded_name = encode_name (name);
408- auto res = run_get_method (resolve_args_raw (encoded_name, category));
413+ auto res = run_get_method (resolve_args_raw (encoded_name, category, address_ ));
409414 if (!res.success ) {
410415 return td::Status::Error (" get method failed" );
411416 }
@@ -419,19 +424,22 @@ td::Result<std::vector<ManualDns::RawEntry>> ManualDns::resolve_raw_or_throw(td:
419424 return td::Status::Error (" Prefix size is not divisible by 8" );
420425 }
421426 prefix_size /= 8 ;
427+ if (prefix_size == 0 ) {
428+ return vec;
429+ }
422430 if (prefix_size < encoded_name.size ()) {
423- vec.push_back ({decode_name (td::Slice (encoded_name).substr (0 , prefix_size)), -1 , data});
431+ vec.push_back ({decode_name (td::Slice (encoded_name).substr (0 , prefix_size)), DNS_NEXT_RESOLVER_CATEGORY,
432+ vm::load_cell_slice_ref (data), true });
424433 } else {
425- if (category == 0 ) {
426- vm::Dictionary dict (std::move (data), 16 );
427- dict.check_for_each ([&](auto cs, auto x, auto y) {
428- td::BigInt256 cat;
429- cat.import_bits (x, y, true );
430- vec.push_back ({name.str (), td::narrow_cast<td::int16>(cat.to_long ()), cs->prefetch_ref ()});
434+ if (category.is_zero ()) {
435+ vm::Dictionary dict (std::move (data), 256 );
436+ dict.check_for_each ([&](auto cs, td::ConstBitPtr key, int n) {
437+ CHECK (n == 256 );
438+ vec.push_back ({name.str (), td::Bits256 (key), cs});
431439 return true ;
432440 });
433441 } else {
434- vec.push_back ({name.str (), category, data});
442+ vec.push_back ({name.str (), category, vm::load_cell_slice_ref ( data) });
435443 }
436444 }
437445
@@ -445,7 +453,7 @@ td::Result<td::Ref<vm::Cell>> ManualDns::create_update_query(CombinedActions<Act
445453 }
446454 return create_set_all_unsigned (combined.actions .value ());
447455 }
448- if (combined.category == 0 ) {
456+ if (combined.category . is_zero () ) {
449457 if (!combined.actions ) {
450458 return create_delete_name_unsigned (encode_name (combined.name ));
451459 }
@@ -488,9 +496,13 @@ td::Result<td::Ref<vm::Cell>> ManualDns::create_update_query(td::Ed25519::Privat
488496
489497std::string DnsInterface::encode_name (td::Slice name) {
490498 std::string res;
499+ if (name.empty () || name == " ." ) {
500+ res += ' \0 ' ;
501+ return res;
502+ }
491503 while (!name.empty ()) {
492504 auto pos = name.rfind (' .' );
493- if (pos == name. npos ) {
505+ if (pos == td::Slice:: npos) {
494506 res += name.str ();
495507 name = td::Slice ();
496508 } else {
@@ -504,20 +516,15 @@ std::string DnsInterface::encode_name(td::Slice name) {
504516
505517std::string DnsInterface::decode_name (td::Slice name) {
506518 std::string res;
507- if (!name.empty () && name.back () == 0 ) {
508- name.remove_suffix (1 );
509- }
510519 while (!name.empty ()) {
511520 auto pos = name.rfind (' \0 ' );
512- if (!res.empty ()) {
513- res += ' .' ;
514- }
515- if (pos == name.npos ) {
521+ if (pos == td::Slice::npos) {
516522 res += name.str ();
517523 name = td::Slice ();
518524 } else {
519525 res += name.substr (pos + 1 ).str ();
520526 name.truncate (pos);
527+ res += ' .' ;
521528 }
522529 }
523530 return res;
@@ -570,17 +577,16 @@ td::Result<ManualDns::ActionExt> ManualDns::parse_line(td::Slice cmd) {
570577 if (type == " set" ) {
571578 auto name = parser.read_word ();
572579 auto category_str = parser.read_word ();
573- TRY_RESULT (category, td::to_integer_safe<td::int16>(category_str));
574580 TRY_RESULT (data, parse_data (parser.read_all ()));
575- return ManualDns::ActionExt{name.str (), category , std::move (data)};
581+ return ManualDns::ActionExt{name.str (), td::sha256_bits256 ( td::as_slice (category_str)) , std::move (data)};
576582 } else if (type == " delete.name" ) {
577583 auto name = parser.read_word ();
578584 if (name.empty ()) {
579585 return td::Status::Error (" name is empty" );
580586 }
581- return ManualDns::ActionExt{name.str (), 0 , {}};
587+ return ManualDns::ActionExt{name.str (), td::Bits256::zero () , {}};
582588 } else if (type == " delete.all" ) {
583- return ManualDns::ActionExt{" " , 0 , {}};
589+ return ManualDns::ActionExt{" " , td::Bits256::zero () , {}};
584590 }
585591 return td::Status::Error (PSLICE () << " Unknown command: " << type);
586592}
0 commit comments