Numeric Assets - Sub-Assets and Unique Descriptions

It’s a good idea to display an asset’s description next to its name - especially for numeric assets. Here’s a good implementation by Tokenly:

It may also be useful to display icons that indicate certain properties. E.g. Blockscan shows a green unlocked padlock for unlocked assets and an orange locked padlock for locked assets.

Another icon can be used to “link” assets. Say you own BULLIONSHOP. You issue a numeric asset with description “BULLIONSHOP $2 off Silver Eagle”. The wallet could show a chain icon to indicate the link.

Another use case may be unique description / asset name relationship. By design descriptions are NOT unique but an asset name can be the hash of the description. It’s usually easy to remember a description and if you know the asset name is the hash of the description (and the wallet thus displays a star icon), you can be confident you’re dealing with the right asset. E.g. the asset with description “Gold” hashes to A2470383366696965147, and this is thus the one and only asset with desciption “Gold” that features.a star icon.

The following is a bit technical. It’s an algorithm that makes a unique numeric asset name from a description. Of course there are many ways to achieve this, There can be better ways.

<script src=""></script>
function numericAssetFromDescription(asset_description) {
	var str = asset_description;
	str = str.substring(0,21);
	str = str.toLowerCase();
	str = str.replace(/[^a-z]/g,'');
	str = CryptoJS.SHA256(str).toString();
	str = str.replace(/[a-f]/g,'');
	str = str.substring(0,19);
	while (str.length < 19) str = str+'0';
	if (str[0] == '0') str = '1'+str.substring(1);
	return 'A'+str;
  • Only use the first 21 characters. In a wallet GUI it’s impractical to display much more. I chose 21 since it is the same as the max (numeric) asset name length.
  • Make the string lowercase. If it were case insensitive one could more easily deceive users.
  • Eliminate any non-alphabetic character. Otherwise one could be deceived by using similar looking characters and/or punctuation and spaces. E.g. the Cyrillic А looks identical to Latin A.
  • Make a sha256 hash of the string.
  • Remove letters from the hash so left only with digits.
  • Keep the first 19 digits.
  • If less than 19 digits, add 0’s so the length becomes 19.
  • The asset name is A + the 19 digits.

Some considerations

  • I wanted the algorithm to be as short and simple as possible

  • All numbers will be exactly 19 digits. This gives 10^19 or about 2^63 possibilities, A collision will never happen by accident, but can theoretically be achieved through brute-force. Yet there’s nothing to gain by brute-forcing a collision, so this is not an issue.

  • Numeric assets can also have 17, 18 or 20 digits but not all 17 or 20 digit numbers are valid. The highest possible number is 2^64-1 = 18,446,744,073,709,551,615 and the lowest is 26^12+1 = 95,428,956,661,682,177

  • A more elegant solution would be to encode the hash in base-10. I did not find a simple solution. Seemingly you could use parseInt(hash_hex, 16) but it has less than 19 digits of precision.

  • Around 1 in 50 mln hashes will have less than 19 digits. This is a non-problem, and the added 0’s ensure that a valid asset name will be created even in the rarest case. The calculation; the distribution is binomial. prob of digit is 10/16, prob of [a-f] is 6/16, the length of a hash is 64 chars, the expected number of digits is 64*(10/16) = 40, the variance is 64*(10/16) *(6/16) = 15 and the standard deviation is sqrt(15) = 3.87. To have 18 digits there must be 22/3.87 = 5.68 standard devs less than expected. From a table you get that it happens extremely rare.

1 Like

The asset description of the numeric assets displayed in the Tokenly Pockets screenshot is actually the torrent infohash of the asset data json file. The asset name is a value within that json file.

The possibility certainly exists for the spoofing of numeric asset ids by creating one that’s only one number off and recreating the json data and subsequent infohash to reflect that. I think the best solution to that is looking at the issuing address for each asset and comparing that against known addresses. It’s the storage and identification of known addresses where it starts to become challenging because there are a lot of different ways to approach it, all with different strengths and weaknesses.

1 Like

I had a look at it. Great work! How can I find the corresponding json files?

I suppose the advantages of your method are that 1) the data in the json is verified by the hash and 2) a spider needs to load the json only once and 3) all jsons can be merged into one easy-to-download block.

On the contrary, the URL json standard is used by more than 18,000 assets. The only way to know if information has changed is by reloading the URL, right?

Someone needs to be seeding the json file in order for you to find it. It can be seeded by anyone, but in practice it will likely be the asset owner that seeds it. The data is not stored on a server but by the asset holders themselves (once their wallets have discovered the webtorrent and downloaded the json, any asset holder can then seed the data). Eventually, I’d like to incorporate webseeds which would allow for the json files to be stored on a web server and be discoverable by the wallet.