Smart Ticket Structure
A series of blockchain tickets perform all of the necessary NFT-related information on the network, providing for much of the functionality and flexibility of standard smart-contract architectures, but in a manner that is much easier to reason about when analyzing the behavior and security of the overall system. This is because we are dealing with static data fields instead of arbitrarily complex code that must execute in some environment. Instead, the code for interacting with the data fields and performing computations on them are done in the underlying protocol (i.e., inside the pasteld daemon or the Walletnode/Supernode Golang programs) and not in a shared virtual machine like in the Ethereum Virtual Machine.
Information is stored in the blockchain using the same kind of coin UTXOs as are used in the underlying coin transactions (i.e., to send PSL from one address to another), and are thus ultimately stored in a high-performance, memory backed database. The "Pay-to-Fake-Multisig" ("P2FMS") approach can record arbitrary data by sending a small amount of coin to a long set of "fake addresses,"
By "fake," we mean that they are not addresses in the usual sense, since we do not know the corresponding private keys for these addresses and thus the coins sent to those addresses can never be spent. The point is that, although these addresses follow the rules required of addresses so that they are syntactically valid, they are used merely as "vessels" for containing arbitrary strings of data. Essentially, if you want to store a file in this way, you take the file and split it into many small chunks. Then each of these small chunks is embedded into a fake address, and a small amount of PSL is sent to each of the resulting fake addresses (doing this in the form of a "multisig" wallet simply allows us to cram more data into a single transaction in a way that uses space more efficiently).
Then, if you later want to retrieve the data, you can simply look up the TXID of the transaction directly in the blockchain data and retrieve the list of addresses. These addresses can then be decoded and the original stored file reconstructed by inverting the process used to generate the fake addresses in the first place. If effect, we are "abusing" the existing blockchain code by putting it to a purpose for which it was never designed, but which it can be made to do.
While this results in some expected degree of inefficiency, this is offset by various benefits. Largest among these benefits is that we do not need to muck around at all with the underlying coin code, which is highly secure, refined C++ that has been developed over the course of ~12+ years by the Bitcoin Core development team, with the largest "bug bounty" in history ensuring that everything is totally rock solid and reliable. Instead, we simply inherit all these properties in our ticketing system, since in the end, the tickets are merely coin transaction at a low level. Thus tickets are just as difficult to "fake" as it would be to counterfeit a Bitcoin, and they are just as immutable and final as a Bitcoin transaction. This approach provides us with a powerful and generic framework for encapsulating all sorts of structure, features, and functionality.
In the original design of this system, various tickets contained all required data fields which were all written directly to the blockchain, such as:
User Information
Creator or Collector Pastel ID
NFT Title, Description, and Copies
NFT Collections
NFT Registration and Activation
Offers, Accepts and Transfers
NFT Digital Fingerprints via Sense
NFT Storage Symbols via Cascade
However, we soon realized that this approach was not particularly scalable, particular when it came to the storage layer. In that case, a large file stored in the storage layer could result in many thousands of small file chunks, and the hash of each of these chunks would need to be included in the tickets. This would quickly clog up the UTXO set and fill up blocks. Instead, we have refined our approach to rely on the storage layer as an intermediate layer. That is, instead of including all of the hashes for every small file chunk corresponding to a stored file directly in the blockchain ticket, we created a new "metadata file" which contained all of these hashes, and stored that in the file storage layer. Then we could simply include the single hash of this metadata file in the actual blockchain ticket. The benefits of this refined approach are as follows:
It results in far less data being stored in the all-important blockchain UTXO set, leading to far better long-term scalability and performance.
It still retains much of the underlying security and immutability as the "naïve" approach, since the hash of the metadata file is stored directly in the blockchain in the UTXO set, and as long as the metadata file can be reliably retrieved from the storage layer, every node can independently verify that the hash matches the hash from the UTXO set.
In addition to the storage layer related fields, the benefits of the refined approach are also highly relevant to duplicate image detection related tickets, where storing a large vector of ~5,000 floating point numbers for every registered image would also quickly become impossible to manage. The "two tier" strategy of utilizing intermediate metadata files stored in the Pastel storage layer solves this problem in an elegant way.
Sample Ticket Structures:
Pastel ID Registration Ticket
This ticket is used to register personal or SuperNode Pastel ID.
User Name Change Ticket
This ticket is used to associate user name with the registered Pastel ID.
NFT Registration Ticket:
This ticket registers new NFT.
"signatures" is the following JSON object, that defines Pastel IDs and base64-encoded signatures of the NFT creator (principal) and three top SuperNodes for the block height at which ticket was created:
"nft_ticket" is the following JSON object, base64-encoded as a string:
Where app_ticket is the following JSON object, ascii85-encoded as a string:
NFT Registration Ticket version 2 adds support for the NFT Collections. The following fields in nft_ticket v2 are optional: "copies", "royalty", "green", "nft_collection_txid". If the NFT belongs to the NFT Collection, "nft_collection_txid" points to the NFT Collection Registration ticket transaction (txid). If any of the optional fields (copies, royalty, green) are missing - they are retrieved from the NFT Collection Registration ticket pointed by "nft_collection_txid".
NFT Activation Ticket:
This ticket activates NFT previously registered with NFT Registration Ticket.
NFT Collection Registration Ticket
This ticket registers new NFT collection.
"signatures" is the following JSON object, that defines Pastel IDs and base64-encoded signatures of the NFT creator (principal) and three top SuperNodes for the block height at which ticket was created:
"nft_collection_ticket" is the following JSON object, base64-encoded as a string:
Version 2 of the NFT Registration ticket should be used to register NFT as part of the NFT collection. "nft_collection_txid" field in the NFT Registration ticket should point to the transaction id (txid) of this NFT Collection Registration ticket. "nft_copy_count", "royalty" and "green" fields are common for all NFTs in the collection, but can be redefined for the specific NFTs. Only users with Pastel IDs from "permitted_users" list can register NFTs in this collection.
NFT Collection Activation Ticket
This ticket activates the NFT Collection previously registered with NFT Collection Registration Ticket.
NFT Royalty Ticket
This ticket is used to set royalty payments for the specific NFT.
Action Registration Ticket
Same ticket structure is used for different action types: Sense and Cascade.
Where "action_ticket" is an external base64-encoded JSON as a string:
Where "api_ticket" could be one of the following JSON object, ascii85-encoded as a string:
a) if action_type is sense
b) if action_type is cascade
Where "signature" is the following JSON object
Action Activation Ticket
This ticket activates the Action (Sense or Cascade) previously registered with Action Registration Ticket. Same ticket structure is used to activate different action types: Sense or Cascade.
Offer Ticket
Same ticket structure is used for both NFT and Action (Sense and Cascade) tickets.
Primary key to search for Offer tickets has the following format: "<item_txid>:<copy_number>". "valid_after" defines a block height (inclusive) after which this offer will be active, if 0 - offer will be active upon registration. "valid_before" defines a block height (inclusive) after which the item offer will expire, if 0 - offer will never expire. New owner can be specified in the Offer Ticket in the "locked_recipient" field.
Accept Ticket
Same ticket structure is used for both NFT and Action (Sense and Cascade) tickets.
Transfer Ticket:
Same ticket structure is used for both NFT and Action (Sense and Cascade) tickets.
Last updated
Was this helpful?