NFT Research - Attributes and Modifications

in HiveDevs3 years ago (edited)

Further Open Discussion of NFTs

Starting with:

In this part I'd like to discuss attribute calculation, modification, and storage of NFT attributes, especially as they might relate to gaming.

Stats in Space

9,007,199,254,740,991 is a big number, but it's also a small number and we're going to discuss why. For starters this is the biggest integer than can be represented as a "number" in javascript. That also means its the largest number that can be handled by the "math" package in javascript. When stored in RAM its just 1 long 64 bit address which is just fine for for nearly all modern 64bit computers. However, when sent around in JSON and DB backups, its 16 bytes long. This is the space we are trying to minimize. We write this number as base64 and go from 16 bytes to 9 bytes. When represented as a base64 number it can look like this: V======== (depending on which glyphs you use to represent your base.). This is 9 bytes instead of 16, and while this is a savings almost to 50%, it can represent a much larger savings.

Screenshot from 2021-09-14 15-52-57.png

Let's say for example that I have an NFT that's closer to a character in a RPG. Strength, Dexterity, Constitution, Intelligence, Wisdom, and Charisma are a standard set of integer based character attributes. Let's try and represent these statistics 1-10 in the smallest space in JSON format:

...
"s":9,
"d":9,
"c":1,
"i":0,  //0-9 instead of 1-10 to keep the bytes to 1 each.
"w":8,
"h":5,
...

That's 36 bytes! Which as we discussed earlier is more than half of that space for a layered NFT! Not only that, but if you are tracking many more things here, you'll run out of single character names like we already did with "c" and cHarisma is now represented by an "h".

"s":"9,9,1,0,8,5",

Is one more way to track these statistics and best case will approach 2 bytes per statistic. You can go into base64 here as well and get granularity up to 0-64 into two bytes. Which depending on your use case may be the best way to save space.

However, in the definition portion of a layered NFT we can specify how to store these parameters in a much more intelligent way: via prime factors

primes = [
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 
    31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
    73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
    127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
    179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
    233, 239, 241, 251, 257, 263, 269, 271, 277, 281
]

These are the first 60 prime numbers, and any combination of multiplication of these numbers results in a unique number.
Now we are going to make the largest possible number from our character stats scheme and see how small it can get:
29 x 71 x 113 x 173 x 229 x 281 = 2,590,136,759,459 ( 903,957,729,051,191 with 7 maxed out)
Which is biGBdIZ in Base64. (3DYKFLG8t with 7)
Let's put this into our JSON format now:

...
"s":"biGBdIZ",
...

We went from 36 bytes to 14 bytes, and let's add those extra 7 stats we could be tracking:
"s":"biGBdIZ,3DYKFLG8t",
24 bytes for 13 categories, or 22 bytes for 12 categories which is under the limit for the above method. There is of course a bunch of working space in here, like for example if you only track some stats from 1 to 5... the extra stat from 6 to 7 added 2 bytes but adding a new part adds at least 2 bytes. You can also store up to 6 binary values/flags in one byte of base64. What works best for your NFTs will likely be a well thought out combination to your needs.

We do want to keep our working numbers to lower than 9,007,199,254,740,991 because using the BigInt library doesn't run in constant time and could make the chain susceptible to a timing attack. For example: Placing really large numbers that you've coded your nodes to ignore, but the standard code set doesn't ignore them and therefore the standard nodes miss their reports while your nodes take over consensus.

Let's code something to find our six stats:

const stats = Base64.toNumber('biGBdIZ')
var statArr = []
for(j = 0; j < 6; j++){
    for(i = 0; i < 10; i++){
    if(primes[i + (j * 10)] % stats == 0){
        statArr.push(i)
        break;
    }
    }
}
// statArr[9,9,9,9,9,9]

Playability

This might get into some bad news. Let's look at Splinterlands and how they play a game with their NFTs. First each card is built from other cards, there is really only a merge aspect that gets tracked. Meaning, how many cards are stacked into a card to raise it to a level. Cards can be levels 1-4 for rares and 1-10 for commons. Each card of any level will have the same stats as any other card of that level.

But you're building an RPG, and your character cards may earn Strength from a Pull-Up Quest, or Constitution from an Eating Contest. This means that each way to alter a cards stats have to be some kind of code that's at least somewhat distributed or trusted. An EVM (Ethereum Virtual Machine) might be a great way to put these code snipets into consensus, or maybe you have a game server standalone that is trusted by the decentralized network to append card modifications (NOT IDEAL).

Unfortunately, just having an NFT definition won't likely include the code that will run a game. Of course a standard game engine could be made, one that gets some standardized sets of attributes for NFTs, and this could be really cool especially if you want to be able to play NFTs across multiple games. Animal Crossing comes to mind here where you can personally do many things, like knit a pattern for clothes, and make that pattern portable as well as unique.

A solution likely to be employed is building a layer 2 just for your game. One where you can HardFork new quests and Gameplay onto the chain. Much like WoW you could earn native "gold" and pay rent on your "house" that includes the space for all your in game assets, This might be a monthly payment model, or if the economy is healthy enough... fees on auctions and other in game services to pay the layer 2 miners. Only NFTs that are stored in game can be played and modified... dismantling an NFT might give some standard items like rubies and emeralds that can be used to enchant weapons and armor. Banking an NFT might involve moving it to competing cold storage layer 2s that can't modify the item, but can hold it, and transfer it back to the parent chain that only tracks it's location and a checksum to minimize space and ensure it's not tampered with.

What's Next

  • Definitions and Minting
  • Auctions and (Trustless) Transfers
Sort:  

o.Ó beyond nerdy, you really took the red pill

maybe you have a game server standalone that is trusted by the decentralized network to append card modifications (NOT IDEAL).

I would go with this. The power of Hive and custom_json is that all the important data remains available to anyone to process the way they want to. As long as some critical parts of an app's code is open-sourced, everything works fine.

Centralized servers are not ideal, but it's easy to see when the owners start taking advantage of their position. Once that happens, it's also easy to "hardfork" from their database to another centralized database that is more honest.

Provided dapps are big enough to have a good community of developers interested and small enough not to have a huge barrier of entry to anyone willing to provide their own database as a service, I think this is the best solution. This is great for games particularly.

This also avoids all the requirements about minimizing the number of bytes in an NFT. Less storage will only mean a lower barrier to entry for any storage competitor, which is good, but not as critical as the situation where we try to keep storage decentralized.

Edit - I actually think that this is the best method to leverage Hive, not just for NFTs. Centralized, open-source apps, posting custom_jsons to hive for all ownership changes in the app. This, however, rules out DeFi, as it isn't secure enough. But is nice for games.

Splinterlands is worth more than Hive was a few months ago, thinking something is just a game doesn't really get you out of any of the problems stated. The root word for finance is the same as final, it has less to do with money and more to do with trust.

While I'm clearly on the decentralize everything side of the fence, the market in general doesn't share my convictions. Fortunately any are free to do as they please :)

Splinterlands is worth more than Hive was a few months ago

That's a good point. But if you think long term DeFi will hold trillions of value, while gaming will not.

I am sure the metaverse will be bigger than I can understand currently, but if you take the bond, currency, equity and commondity markets, + whatever financial assets will spawn in a digital world and put them all in DeFi apps, there is no doubt that the total value will be orders of magnitude bigger than the gaming assets market.

So in the long term size does matter, and maybe the Splinterlands - Hive valuations only mean we need to buy more hive :)

Edit - Obvisouly decentralizing everything is awesome, but again, scalability is very hard as your posts show.

BTW @disregardfiat, in the very long term, do you think that very cheap computer hardware can solve all the scalability problems without more scalable software in blockchain consensus?

For example, what if it costs $1 to run a bitcoin node with 32 megabyte blocks and a 50 year history. What does that mean for a dpos chain?

I've been thinking about this recently, as with quantum computing we might have abundant resources.

I think that trust systems like these will be run by interested parties. Have a chain for your town, have a chain for a game, have a chain for your business, and lets them settle payments between themselves. Decentralization is not ever likely to be 7 billion people consensusing on 7 billion peoples worth of transactions. But running some hardware for your neighborhood, and things that you give your actual attention to would scale nicely... even now.

We have already been working on storing items on a layer 2 database that can be moved in and out of our multiple games.

is this post just for conversation or are you actually working on coding something?

Yes, I've been coding some NFT definitions and hoping to make or meet some portability standards. Would love to hear about your work and goals.

Well written. You tapped into some fundamental problems.

Lets assume Splinterland is Noise, just a outlayer, then Hive would have no marketshare. How could Hive redefine "NFT" in a way that Hive gains market share? Is the cheapness of dPOS really all we have? If so, we directly compete with Solana, Avalache, or L2 like Arbitrum. What is with the proof of brain aspect?

The points like cross-chain compatibility/tradeability are deffensive strategies. They defend against the point of becomming obsolete. Onchain-ness and onchain composability is high entropy domain. No rational agent would have a layer 1 NFT (autoglyphs, loot) on a chain B that is less secure than a Chain A. What could be a offensive strategy where people have to move to hive/layer2 in order to have a unique NFT expirience?

There is a very real way that all posts and comments on HIVE are NFTs. The permlink name space is finite and unique. Proof of brain does tap into this... However, Hive's proof of brain-ness has been diminished almost to the point of proof of participation. Proof of brain should be moving to layer 2, just like tokens should exist on layer 2, with NFTs as well.

In many ways I agree with you about portability being a defensive measure, but the number one defensive strat is for scaling.

I'm not sure you're familiar with dlux.io ... my dApp front end for hive. It has full proof of brain, fully decentralized, and is capable of doing anything that I've ever heard suggested. I believe the cheapness of dPos and the ability to make dApps on chain that can just as easily serve as creation/management tools, as well as games/experiences that can use NFTs available at API endpoints to be a beacon. Of course, this is all just code that can be copied, modified, and run anywhere... and that's the most common problem in the space. There really can only be one SHA PoW chain, but that's determined by the hardware capital. PoS is a different beast entirely. Economics of computation space and efficiency are the product you are selling, the lower the barrier for entry the higher the adoption.

interesting 👍

!PIZZA

@disregardfiat! I sent you a slice of $PIZZA on behalf of @soturi.

Learn more about $PIZZA Token at hive.pizza (5/10)