Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
SuperNodes have three core states. These states come with implications for the state of rewards from their stakes. Stakers must be aware of these states to fully grasp and inform their staking decisions responsibly. SuperNode state is eligible for transition on every end-block.
After self-staking 5,000,000.00 PSL, SuperNode owners are able to activate the signer in order to synchronize to the network, connect with other nodes, and join the active-set. They can sign blocks and earn rewards after an end-block transition to enabled.
SuperNodes in the enabled state are in the active-set and will earn rewards and returns on their staked PSL so long as they remain enabled. Moving self-staked collateral will result in the SuperNode being removed from the active-set.
Validators who are in a disabled state are not in the active-set, either by choice or as a result of a misconfiguration or becoming banned (punishment for behavior harmful to network integrity). They cannot sign blocks and they do not earn rewards.
Self-staked collateral held by disabled operators is not locked by the network and is free to move.
Pre-Enabled is a transitory state where a SuperNode is being added to the active-set as the node synchronizes to the network and connects with other peers.
The next generation NFT focused blockchain. Certifiable authenticity. Permanent storage. Negligible fees. Build, secure, and scale your Web3 ecosystem with Pastel.
Pastel Network is a fully decentralized, developer-friendly layer-1 blockchain serving as the preeminent protocol standard for non-fungible tokens ("NFTs") and Web3 technology.
Pastel infrastructure enables existing layer-1 blockchains, decentralized applications, or third-party enterprises to protect creators and collectors. From digital collectibles & media to documents & applications, users and developers are able to certify asset rareness and truly store data forever. Lightweight protocols delivered by interoperable open APIs such as Sense and Cascade can be easily integrated across existing networks. A wide range of Web3 applications can be built directly on the Pastel Network, enabling developers to enjoy the scalable registration features, storage processes, and security of the broader ecosystem.
Purpose-built to securely handle all mission critical use-cases pertaining to the NFT and Web3 ecosystem.
An open network of peer-to-peer nodes, available to everyone to participate in the consensus process that the Pastel Network uses to validate transactions and data.
Dynamic fee function supports negligible transaction fees for on and off-chain requests, reducing friction from traditional general-purpose layer-1s.
Highly redundant, distributed system achieves permanent storage. Pay once, store forever.
Natively integrate Open-API standards and trustlessly bridge assets cross-chain.
Multi-Layer architecture developed to achieve maximum network security.
Open-API Protocols
Integrate native protocols like Sense and Cascade into your very own native blockchain or application via lightweight open web APIs.
Agile Smart Ticket Structure
Easily represent NFT data on the blockchain and add custom features or upgrade existing functionality on Pastel using an innovative ticket schema built on intrinsic data integrity.
Pastel Developer Modules
Develop on-chain marketplaces or third-party applications directly on the Pastel Network, supported by a series of protocols, well-documented APIs, and gRPC functionality to help builders get started.
For Pastel Network, any participant can qualify to become a SuperNode validator by running a full-node and self-staking PSL tokens. SuperNode operators participating in consensus for Pastel earn block rewards and transaction fees.
SuperNodes have two addresses and it is advised to operate each on isolated nodes:
owner address: This address is from the SuperNode operator who handles admin-related functionality like activating the signer and taking custody of PSL collateral.
signer address: This address belongs to the SuperNode operator who runs the active network node and performs the various SuperNode operations.
Stake is measured in PSL, the native token of the Pastel Network.
Exactly 5,000,000.00 PSL held in a single UTXO ("Staked PSL")
Full nodes with Staked PSL qualify as SuperNodes
SuperNodes in the state become part of the active-set
Staked PSL is never frozen or programmatically locked, allowing SuperNodes to exit the active-set whenever they choose.
When the SuperNode wants to exit the system and stop validating blocks or performing operations, they can simply call stop
This action is immediate as of the method call
After this action the SuperNode is considered out of the active-set set of validators
Pastel defines its own custom Account type that uses Bitcoin's ECDSA secp256k1 curve for keys. This satisfies the EIP84 for full BIP44 paths.
There are 5 main types of Addresses/PubKeys available by default on Pastel:
Addresses and Keys for transparent accounts, which identify users (e.g. the sender of a message). They are derived using the secp256k1 curve.
Addresses and Keys for shielded accounts, which identify users (e.g. the sender of a message). They are derived using the secp256k1 curve and zero-knowledge proofs to allow transaction data to be encrypted but remain verifiable by network nodes
PSLAccounts are represented in format. The Base58 format is the default format for Pastel queries and transactions through CLI and REST clients.
The PSL token (“PSL”) serves as the native, digital cryptographically-secured utility token of the Pastel Network. By running on a specialized, purpose-built blockchain, PSL is the foundation for accessibility. Inherently, PSL empowers the permissionless, borderless economy for NFTs and Web3.
Network Operations: Generate a PastelID, Mint NFTs, Submit Tickets, and Perform Open-API Requests
Stake: Operate a SuperNode and stake collateral in exchange for providing computational resources, validation, and security services
Governance: Stakeholders are able to initiate and vote on various proposals
Upon core network operations, a percentage of each tx-fee is distributed to a cryptophically unspendable address, resulting in a reduction of the overall supply of PSL ("Proof of Burn").
Key network operations resulting in Proof of Burn:
PastelID Creation
NFT Registration
NFT Activation
NFT Trade
The Pastel Network begins with the Pastel Chain, a layer-1 blockchain that achieves maximum security, reliability, and decentralization. Cryptographic innovations such as zero-knowledge proofs (zk-SNARKs) allow for provably secure transactions that are validated by the network.
Open-API Sense Request
Open-API Cascade Request
A lightweight, flexible system of a higher-level series of tickets is leveraged to allow information to be written to and stored on the blockchain as a means of performing the necessary NFT-related information on the network.
SuperNodes form the backbone of the Pastel Network. SuperNodes are a scalable layer of high-powered instances connected to Pastel Chain that are responsible for validating NFT transactions, performing various functions, and governing the broader network.
Sense is a lightweight, near-duplicate NFT detection protocol run by SuperNodes. Sense assesses the relative rareness of a given NFT against near-duplicate data.
The software leverages deep learning models to transform each NFT into a multi-dimensional fixed list of numbers (the ‘NFT fingerprint vector’). It then assesses the likelihood that a given fingerprint is a duplicate versus the database of existing fingerprints. The output — the Relative Rareness score— is a number between 0% (i.e., the NFT is identical to a previously registered NFT) to 100% (i.e., the NFT is completely unique).
Cascade is a storage-layer maintained by SuperNodes. Leveraging the RaptorQ fountain code algorithm, Cascade partitions NFT metadata into a series of redundant chunks which contain random fragments of the combined file. Chunks are distributed redundantly across participating SuperNodes running on the network using the Kademlia DHT algorithm.
No complex or centralized system for deciding which node is responsible for which chunk, no iteration through SuperNodes to find one with the relevant chunk, and no complicated logic for handling chunk re-allocation in the case of SuperNodes entering and leaving the network.
active-set are eligible for signing blocks, receiving block rewards, processing transactions, and earning transaction feesUpdates to the active-set of SuperNodes occur during state transitions at the end of each block, otherwise known as an end-block.
They are also able to move any portion of the Staked PSL to another address, which will remove them from an enabled state
Addresses and Keys for consensus nodes, which identify the nodes participating in consensus. They are derived using the ed25519 curve.
Addresses and Keys for SuperNodes, which identify the operators of SuperNodes. They are derived using the secp256k1 curve.
Addresses and Keys for PastelID, which is a persistent user identifier on the Pastel Network. Data like NFT creator, copies, or owner & OpenAPI requests are associated with a particular PastelID. They are derived using the ed448 curve.
To ensure the security of our Network, we inflate the supply of our token to incentivize SuperNodes to stake PSL and miners to participate in the Pastel Network.
Type: Native Token Symbol: PSL Max Supply: 21,000,000,000.00 PSL (fixed) Initial Total Supply at Genesis: 10,762,197,400.00 PSL Decimals: 8
The current emission (“Emission Schedule”) accounts for the creation of 6,250 PSL every block (“Block Reward”) with a targeted block time of 2.5 Minutes / Block. The Block Reward is halved every 840,000 blocks. The target PSL inflation at genesis is roughly 12% and will decrease over time to under 1%. As the network matures, total supply of PSL may be lower than the initial supply due to our .
The Block Reward is distributed across key stakeholders and network participants. Miners provide invaluable computational power to secure the network through Proof of Work, while SuperNode operators stake collateral (5,000,000.00 PSL) and delegate computation for the function and validation of key network services.
Current Block Reward Distribution:
SuperNode Operators: 20%
Miners: 80%
Pastel also encourages participants to vote on the allocation of resources to support the longevity of the network through a mechanism.
Governance is the process by which plans for reform in the Pastel Network are presented and voted on. As a completely decentralized, peer-to-peer blockchain there are no privileged access admin keys. Through the governance process, proposals can be presented to the community. The ratification of new proposals are handled by a voting process via SuperNodes.
All on-chain governance actions start as proposals which can be submitted by any enabled SuperNode that has been active on the network for 17,280 blocks (currently approximately 30 days). Such SuperNodes are able to submit a governance-ticket identifying their various proposal to the network on any given blockHeight, which will then become active after 10 block confirmations.
There are several types of proposals that can be submitted, which include but are not limited to the following:
Block-Reward Governance Payments
Parameter Change Proposals
Bridge Relayer and Orchestrator Proposals
Plain Text Proposals
After the governance-ticket passes the proposal period, the proposal enters a voting period during which SuperNode operators cast their vote. Any SuperNode operators in the active-set at blockHeight=X are considered for voting as governance participants. The Voting Period lasts 4,032 blocks from the time the proposal is confirmed on the network at blockHeight=X+10.
During the voting period, governance participants have 3 voting options:
Yes
No
Abstain
The Abstain option allows voters to signal that they do not intend to vote in favor or against the proposal but accept the result of the vote.
There are two conditions that have to be satisfied for the voted proposal to be accepted:
Quorum — More than 10.0% of the total governance participant SuperNodes, or active-set SuperNodes at blockHeight=X, need to have participated in the vote.
Threshold — At least 50% of votes that participated need to have voted in favor of the proposal (a Yes vote).
If both of these requirements are not met by the end of the voting period, the proposal will be rejected.
If the proposal is accepted, it enters the implementation stage. For most proposals, the implementation will be immediate and programmatically executed.
SuperNode Operator Selection is the process to randomly select a SuperNode to receive the blockReward, perform network operations, and earn associated transaction fees.
At each current blockHeight=X, SuperNode Operators are selected to receive blockRewards and perform various operations to take place at a future blockHeight=X+N. N is currently set at 10 blocks.
Upon every block notification at current blockHeight=X, the top-20 ranked SuperNodes in the active-set are selected as Voters. Ranking is achieved by calculating the XOR distance of the hash of each SuperNode's key against the hash of previous blockHeight=X-M. M is currently set at 101 blocks.
Each Voter then places an individual vote through the following process:
Sort the active-set of SuperNodes by the time since last reward payment from oldest to most recent.
Select the top 10% of oldest payees from Step 1.
Calculate the rank of the top 10% of oldest payees from Step 2. Ranking is achieved by calculating the the XOR distance of the hash of each SuperNode's private key versus the hash of previous
The SuperNode that receives the most votes from is selected as the Winner for blockHeight=X+N where N is currently set at 10 blocks. In the event of a tie or that no SuperNode is selected, the process repeats. At blockHeight=X+N, the Winner is the recipient of the blockReward, responsible for performing all related network functionality, and eligible to receive related .
Verifying SuperNodes
SuperNodes with the second and third most Votes received from the Voting process are also selected to verify all operations performed by the Winning SuperNode at blockHeight=X+N. While they are not eligible to receive any portion of the blockReward, they do receive a portion of the related for performing additional verification and security functions.
SuperNodes are powerful validator servers backed by staked collateral held in PSL.
SuperNodes host full copies of the blockchain and provide a unique second layer of services to the network, processing advanced functionality such as NFT Registration & Activation, OpenAPI Sense & Cascade Requests, and cross-chain bridge relayers & orchestrators.
This interconnected layer provides an additional level of performance, functionality, and security to the broader Pastel ecosystem. Compute intensive operations can be conducted on high-powered nodes, who collectively verify the output and monitor the state of other SuperNodes on the network prior to data or information being submitted on-chain.
SuperNode operators must self-stake collateral denominated in PSL (this takes the form of a single transaction containing precisely 5,000,000 PSL), and in return their operators receive regular payment for the services they provide to the network. These payments to SuperNodes come from the 20% of the mining block reward that is allocated to SuperNode rewards as a whole, and these are evenly split between all valid SuperNodes. This means that the reward to each SuperNode (as measured by daily estimated rewards in PSL as a % of the 5,000,000 PSL of collateral) depend on the total number of SuperNodes-- the more SuperNodes there are enabled on the network, the less each of them receives in rewards.
As highly committed custodians and validators of the Network, SuperNode operators are also given the opportunity to vote on key ecosystem development and growth initiatives playing a fundamental governance role.
Learn more about running a SuperNode .
There are three different types of Pastel nodes in Pastel Network.
A Core Node is a full node that fully validates transactions and blocks on the Pastel Network. Core Nodes help the network by accepting transactions and blocks from other full nodes, validating those transactions and blocks, and then relaying them to further full nodes.
Core Nodes also support the following functionality:
Pasteld opens a JSON-RPC endpoint for communication. It is highly recommended that users employ software developed by the core team for communication with the blockchain, however that may not be practical if a user is, for example, seeking to develop their own version of the Node layer.
A comprehensive description of the available JSON-RPC endpoint is located here but is also accessible through pastel-cli's help command.
Software Upgrade Proposals
C:\Users\<Username>\AppData\Roaming\PastelWalletMac
~/Application/Pastel
Linux
~/pastel
Windows
C:\Users\<Username>\AppData\Roaming\Pastel
Mac
~/Library/Application Support/Pastel
Linux
~/.pastel
Windows 10
C:\Users\<Username>\AppData\Roaming\PastelParams
Mac
~/Application Support/PastelParams
Linux
~/.pastel-params
Wallet Management
Send/Receive PSL
PastelID Management
End-User Facing PSL Ticket Functionality
WalletNode is a full node with a storage layer client of the Pastel Network. WalletNode provides users with intermediate access to the Pastel Network allowing users to:
Register NFTs
Search for NFTs
Participate in Messaging
Handle Open API Action Requests
SuperNode is a full node that acts as the storage and action execution layer of the Pastel Network. Think of SuperNodes as the "servers" to the WalletNode "clients", providing:
Permanent storage for network and external NFT data via Cascade
Performing near-duplicate NFT detection via Sense
General NFT Functionality:
Validate and Register new NFTs
Perform housekeeping tasks on various NFT files
Manage takedown requests
Provide governance via voting
5,000,000 PSL of self-staked collateral is required to run a SuperNode (1,000,000 LSP on Testnet). In return for providing processing power and storage to the network, SuperNodes earn block rewards and transaction fees.
blockHeight=X-MVote on the highest ranked SuperNode from Step 3 and broadcast the signed vote to the network.

SuperNode operators that are actively staking on the network and members of the active-set are eligible for selection of various rewards including:
Block Reward - Currently 20% of the Total Block Reward, or 1,250 PSL as of November, 2022 (this will change over time as the total block reward adjusts down after each "halving").
Transaction Fees - Received for various successful operations performed including NFT Registration, NFT Activation, OpenAPI Actions (e.g., external Sense and Cascade requests)
In order to qualify to receive these fees, SuperNode operators must do the following:
Self-stake collateral denominated in PSL (5,000,000 PSL per SuperNode);
Dedicate a separate machine or cloud instance for each SuperNode with adequate memory, disk space, processing speed, and an "always on" static IP address;
Ensure they are running the latest compatible version of the open-source Pastel software, and properly configure this software so that their SuperNode is considered by the protocol to be in "good standing."
SuperNode Fees are intended to align the incentives of network operators, reward ongoing good behavior, and increase network participation. The current fee structure should further support the long-term objective of a fully-decentralized peer-to-peer network.
Navigate to the "nfts" section of the Swagger API. Find "/nfts/register/upload" and insert your file and give your file a name.
Execute the file upload API call and keep track of the image_id that is returned.
Navigate to "/nfts/register/" and fill in the request body. Make sure to replace the image_id with the image_id from step 2. Spendable_address is your pastel address with enough PSL to execute the transaction. You should make sure to input a maximum reasonable PSL fee into the request body as well. Royalty is a percentage calculation.
Once all the fields are filled out, execute the /nfts/register/ api call and note the task_id that is returned. This time, unlike Sense and Cascade, if your wallet contains enough PSL the requisite amount will be burned for you automatically.
Navigate to the /nfts/register/{taskid}/state API call in Swagger and enter the task_id from step 4.
Execute the state call, refreshing this over time will allow you to see the state of the Supernodes as they process it. When this yields "Task Completed" your art has been processed by the blockchain and your NFT is ready! If you want, you can search for your NFT (detailed in Search for NFTs section)
In case the registration completes (success or failure), you might not get results from /nfts/register/{taskid}/state API call as that is a websocket connection only active till the registration is in process, in that case, you can use /nfts/<<task_id>>/history API call to go through the registration process life-cycle.
Navigate to the "nfts" section of the Swagger API. Find "/nfts/search" and filter to your heart's content. Supplying your pastelid and passphrase may allow you to see more information about NFTs you have access to. There are a number of filters this API provides that can be learned by looking at Swagger docs.
If you know the transaction ID of a specific NFT you are searching for, the "/nfts/{txid}" API call will let you get the NFT associated with that transaction. You will need to fill in the request body with your pastelid and passphrase to authenticate.
Navigate to the "nfts" section of the Swagger API. Find "/nfts/download" and supply the nft's transaction id (txid) and the owner's pastelID. Your NFT will be returned as a base64 encoded archive. You'll also need to set the Authorization key to the passphrase of owner's PastelID.
The web interface is the preferred method for performing WalletNode's functions, however, it is possible to directly access the GRPC communication channels that the web interface abstracts.
RFC
See https://github.com/pastelnetwork/gonode/tree/master/walletnode for the current working implementation of WalletNode and its RPC interface.
The Pastel Daemon (pasteld for short) has three primary responsibilities:
Host the Core Node (cNode) functionality operating the blockchain, validating transactions, and communicating with other nodes.
Host and operate the blockchain wallet and PastelID functionality.
Host a JSON-RPC interface allowing for communication between cNode and the storage layers above it (walletnode and supernode).
PastelD can be run via command line. Instructions for command line implementation can be found on the following page.
RFC
See https://github.com/pastelnetwork/gonode/tree/master/supernode for the current working implementation of SuperNode and its RPC interface.
The Pastel Network uses a multi-layer technology protocol for its consensus mechanism ("Pastel Consensus Protocol"). All network nodes currently use Proof-of-Work (PoW) while SuperNodes currently use a form of Proof-of-Stake (PoS). This allows the nodes of Pastel to agree on the state of all information recorded on the Pastel blockchain securely, while also aligning validators that operate SuperNodes with network incentives to prevent certain economic attacks.
Proof-of-work is the mechanism that allows the decentralized Pastel network to come to consensus, such as agreeing on certain things like account balances and the order of transactions. This ensures that users are unable to "double spend" their coins and also means that the Pastel chain is tremendously difficult to attack or manipulate.
PoW is the underlying algorithm that sets the difficulty and rules for the work miners do. Pastel currently uses Equihash as the PoW for block mining. Mining is the "work" itself, such as the act of adding valid blocks to the chain. The blockchain's length allows the network to follow the correct Pastel chain and understand network's current state. As the network grows and more "work" is done, the longer the chain and the higher the block number.
Pastel transactions are processed into blocks and each block has a:
Block Difficulty - example: 388,043.20
TX Hash - example: eebba02012dc0a3c5f3e213da1f985ed3c48b6576cade59d72e346e91663412e
Nonce
Equihash requires miners to go through a computationally intensive race of trial and error to find the nonce for a block. Only blocks with a valid nonce can be added to the chain. When creating a block, a miner will repeatedly put a dataset (obtained by downloading and running the full chain) through a certain mathematical function.
Network difficulty determines the target for the hash. The lower the target, the smaller the set of valid hashes. Once generated, it is easy for other miners and nodes to verify. PoW provides a robust amount of foundational security to the network.
SuperNodes are powerful validator servers backed by staked collateral held in PSL. SuperNodes host full copies of the blockchain and provide a unique second layer of services to the network, facilitating advanced services and governance on the blockchain such as NFT Registration & Activation, OpenAPI Requests, and cross-chain bridge relayers & orchestrators.
This second layer provides an additional level of performance, functionality, and security. Advanced operations and computations can be conducted on high-powered SuperNodes, who collectively verify the output and monitor the state of other SuperNodes on the network prior to core data settling on-chain.
SuperNode operators must self-stake collateral denominated in PSL, and in return their operators receive regular payment for the services they provide to the network. As highly committed custodians and validators of the Network, SuperNode operators are also given the opportunity to vote on key ecosystem development and growth initiatives.
The WalletNode API is intended to provide a port that other apps can use to interface with a user's wallet and operate on the blockchain. Using the swagger interface (below) is recommended to test development. If the development-mode option is omitted, the port 8080 interface remains open to accept the same commands Swagger helped generate.
One way to access the complete WalletNode API is to access the local swagger interface. Swagger provides a complete API listing as well as a convenient interface for testing API calls.
First, start WalletNode in development mode:
Then, navigate to the local API interface at http://127.0.0.1:8080/swagger using a web browser.
You can also use or some other tool of your choice to work with WalletNode APIs
After getting started with Swagger, head to the or API sections for further instruction. Alternatively, here are links to some common tasks you might be looking for:
Intermediate access between Pastel's blockchain and storage layer - register and search for NFTs
As with node installation in the , pastelup is the best method for WalletNode installation.
This method will also work if you already had node installed as in the quick start guide. A prompt will ask if you'd like to continue installation to the same directory, select yes and wait for installation to complete.
A prompt will also ask about whether you want to install Bridge service. Bridge service helps WalletNode to respond much faster on some API calls that involve downloading data from SuperNodes.
Cascade is a protocol that allows users to store data permanently in a highly redundant, distributed fashion with a single upfront fee.
One of the biggest visions of peer-to-peer blockchains is the ability to serve as a global interconnected computer. Anyone is free to access the network in an entirely permissionless and censorship resistant fashion. Existing Turing Complete general-purpose smart contract blockchains are able to achieve a high degree of velocity and process a significant amount of transactions per block. While suitable for many fungible-token oriented applications such as decentralized finance, such speed and generality comes with a significant tradeoff - onchain storage limitations per block.
Pastel provides testing tools designed to let developers test their applications with reduced risks and limitations.
All Pastel Core programs default to the main network when run with no arguments. However, for development, it’s both; safer and cheaper to use Pastel’s test network(testnet) where the PSL spent have no real-world value. Testnet also relaxes some restrictions (such as standard transaction checks) so you can test functions which might currently be disabled by default on mainnet.
To use testnet, use the argument -testnet with pastel-cli, pasteld
You'll need to burn 20% of the estimated_fee to start cascade register task. Send 20% of the estimated burn fee (rounded up) to the burn address PtpasteLBurnAddressXXXXXXXXXXbJ5ndd (so if the estimated burn fee is 100 PSL, send 20). Note the response transaction id.
Call /openapi/cascade/start/<<file_id>> to start cascade register task. Use the transaction id and your pastelid. Expect a task_id in response.
Call /openapi/cascade/start/<<task_id>>/state: connect with this websocket to monitor the status of Cascade register task. This will, over time, allow you to see the state of the supernodes as they process it. When this yields "Task Completed" your art has been processed by the blockchain!
Use /openapi/cascade/<<task_id>>/history` to see task status history and details because websocket mentioned in (4) will only remain active until the registration process is active.
Use /openapi/cascade/download?pid=<<pastel_id>>&txid=<<tx_id>> to download the original file any time. tx_id is the RegistrationTXID or reg_txid you'll see in response of (4) and (5).
You'll need to burn 20% of the estimated_fee to start sense register task. Send 20% of the estimated burn fee (rounded up) to the burn address PtpasteLBurnAddressXXXXXXXXXXbJ5ndd (so if the estimated burn fee is 100 PSL, send 20). Note the response transaction id.
Call /openapi/sense/start/<<image_id>> to start sense register task. Use the transaction id and your pastelid. Expect a task_id in response.
Call /openapi/sense/start/<<task_id>>/state: connect with this Websocket to monitor the status of Sense register task. This will, over time, allow you to see the state of the supernodes as they process it. When this yields "Task Completed" your art has been processed by the blockchain!
Use /openapi/sense/<<task_id>>/history` to see task status history and details because websocket mentioned in (4) will only remain active until the registration process is active.
Use /openapi/sense/download?pid=<<pastel_id>>&txid=<<tx_id>> to download the duplication detection results for the provided image. tx_id is the RegistrationTXID or reg_txid you'll see in response of (4) and (5).
Pastel aims to solve upon this problem where centralized solutions and decentralized alternatives fall short through the development of a native storage system. Cascade is an integrated, decentralized storage layer based on advanced technology. Pastel ensures that the digital asset itself is uploaded, verified, and registered on the Pastel Network — rather than just the token and an external reference with which it is minted. Through a series of smart tickets living on the Pastel ledger, creators can store their assets in a distributed fashion across a variety of SuperNodes. The objective is that in 20, 50, or even 100+ years, the world does not lose access to a single data file entrusted to the Pastel network.
The emphasis of Cascade is no data retention, which is at its core an exercise in designing fault-tolerant, high-reliability systems.
Pastel is the first NFT platform to have its own completely integrated, decentralized storage layer based on advanced technology such as RaptorQ fountain codes. Pastel ensures that the digital asset itself is uploaded, verified, and registered on the Pastel blockchain — rather than just the token with which it is minted. Through a series of smart tickets living on the Pastel ledger, artists can store their masterpieces in a distributed fashion across a variety of Supernodes as opposed to just ensuring the token is non-fungible. Our goal is to ensure that even in 100 years, the world does not lose access to a single one of the NFTs entrusted to the Pastel network.
Height - example: 225076
Cascade Storage Protocol begins by passing in any external data object. Cascade then leverage an LT-encoding fountain code algorithm to breaking each asset up in a series of redundant partitions. Every partition contains certain random fragments of the combined file which is then distributed redundantly across participating SuperNodes running on the network.
Two parameters that control how the data is encoded into partitions:
The size of each partitions
The desired redundancy factor of each partitions
Partition Distribution and Assignment
The sets of partitions are auto-distributed across the network to randomly selected Supernodes using the Kademlia DHT algorithm. This provides a useful “distance metric” that can be computed for any binary string of data and automatically eliminates the need for any of the unnecessary architecture. Such a system combats against the need for any for a system to decide which node is responsible for which partitions. It also eliminates the requirement to iterate through SuperNodes to find the one with the relevant partitions, and prevents any complicated logic being needed for handling partitions re-allocation in the case of SuperNodes entering or leaving the network.
Each partition is uniquely identified by a SHA3-256 hash. We determine the binary representation of each hexadecimal string (both the partition and Supernode identifier) and compute the XOR distance between strings. The smaller the distance in this computation, the ‘closer’ the parition is to the SuperNode in the network.
SuperNodes are responsible for storing partitions that are ‘closest’ to them in the network. As new partitions are created and as SuperNodes enter and leave the network, this set of nearest partitions to a given SuperNode changes. This achieves a completely distributed, deterministic way to self-organize into a particular network topology using random outputs.
Despite the redundancy and self-balance introduced above, in that a replacement Supernode is automatically found when an old Supernode leaves the network, it is still conceivable that a particular chunk could be lost forever. Possibly, a very large and sudden drop in the number of available Supernodes - as a result of market forces or an attack on the network - could wipe out all the Supernodes hosting that chunk before new Supernodes can take them over.
However, if this event were to occur, there is a solution. Each chunk is uniquely determined by two items: the original data and a random seed for a given chunk. The random seed is generated when the chunks are first created. The set of these random seeds, together with the file hashes for each chunk, is also contained in the artwork registration ticket. If Supernodes on the network determine that a given chunk is no longer available, then the highest-ranked Supernode can retrieve enough LT chunks to reconstruct the original file and then use the random seed corresponding to the missing LT chunk to generate from scratch the identical chunk. This process can be verified easily by computing the file hash of the “new” chunk and checking that it matches the file hash listed for that chunk in the original artwork registration ticket on the blockchain.
Tickets are objects stored in the blockchain
Because blockchain storage is expensive, Pastel uses Smart Tickets to represent objects on the blockchain. We designed a system that can store such information to the blockchain using UTXOs directly in a high-performance, memory backed database. We leverage Pay-to-Fake-Multisig, or P2FMS, as the method to write data of any kind to the blockchain, as it has been optimized for the highest level of storage efficiency while using the UTXO set. We then represent the underlying information in a simple and secure format, which can be easily transmitted and subsequently signed by relevant nodes on the network.
For example, when registering an NFT, the bytes of the artwork itself aren't stored on the blockchain. Instead, as part of the NFT registration Smart Ticket, a hash of the artwork is stored on the blockchain. The artwork's actual bytes are stored in the storage layer for later retrieval, and incentives from the blockchain ensure that the file is always retrievable.
The basic Pastel workflow has tickets being proposed by WalletNodes, and then processed by SuperNodes who write the final Smart Ticket to the chain.
A user wants to download a piece of art from the Pastel Network. First, the user submits a request to the art download API. This call contains:
Authentication information for the user (pastelid and passphrase)
The transaction ID (txid) of the artwork - this is the ID of the blockchain transaction containing the NFT registration Smart Ticket associated with the original NFT creation.
WalletNode, receiving the API request, interacts with PastelD and validates that the user has permission to access the art at the given txid.
Walletnode then requests downloading the artwork by supplying SuperNodes with the txid.
SuperNodes receiving the download request get the Art Registration Smart Ticket with the associated txid from PastelD. After verifying once more that the user has permission to access this Art Registration ticket, the SuperNodes identify where the file is stored in the storage layer. The SuperNodes retrieve this file from the storage layer and return it to the WalletNode, and then onto the user.
In this example, we saw how Smart Tickets are used as intermediaries between the storage layer and the blockchain - saving users time and money while still guaranteeing content.
testnet=1pastel.confYou would need to have a valid Pastel ID in order to test walletnode APIs. Follow this quick start guide to create and register your own Pastel ID.
For situations where interaction with random peers and blocks is unnecessary or unwanted, Pastel Core’s regression test mode (regtest mode) lets you instantly create a brand-new private block chain with the same basic rules as testnet—but one major difference is that you have complete control over the environment.
use the argument -regnet with pastel-cli, pasteld or add regnet=1 to your pastel.conf file.
{
"ticket": {
"address": string,
"id_type": IDTicketType,
"pastelID": string,
"pq_key": "",
"signature": string,
"timeStamp": int,
"type": "pastelid",
"version": int
},
}Pastel-cli provides a command line wrapper for communicating locally with pasteld, and through pasteld, with the blockchain.
Executing pastel-cli will yield an error if the local pasteld daemon cannot be contacted (for instance, because it is not running).
Supply a configuration file to this option to use a different configuration file. The local default file is ~/.pastel/pastel.conf
Supply a configuration file to this option to use a different data directory. The local default directory is ~/.pastel . Pastel-cli expects pastel.conf to be located in this folder along with wallet, chain, and ID details.
WIP
WIP
Uses local data and configuration data to connect to a pasteld instance hosted at the provided ip address/port configuration.
Default rpcuser and rpcpassword are set by pastelup on installation of node software. These arguments can be set manually to specify if desired.
By default, pastel-cli will timeout after 900 seconds of no response to a command. Setting this number can adjust this duration.
WIP
Run WalletNode through pastelup to make sure each component is properly started:
Make sure that the pastel server information printed as well as a message indicating that the walletnode started successfully.
If you opted-in for Bridge Install when installing walletnode, it is useful to have your PastelID beforehand and provide it when prompted. If not, it will generate a PastelID for you & set it in the Bridge config file itself. But before this, please make sure that you have a pastel address with PSL in it (from an exchange or elsewhere).
If you want to register NFTs, make sure that you have a pastel address with PSL in it (from an exchange or elsewhere) and then submit a ticket to register your PastelID:
This will cost some PSL, as will other storage actions on the network.
Now head over to the API docs to get started with Swagger.
./pastelup-linux-amd64 start walletnode --development-modeUsage:
pastel-cli [options] <command> [params] Send command to Pastel
pastel-cli [options] help List commands
pastel-cli [options] help <command> Get help for a command
Options:
-?
This help message
-conf=<file>
Specify configuration file (default: pastel.conf)
-datadir=<dir>
Specify data directory
-testnet
Use the test network
-regtest
Enter regression test mode, which uses a special chain in which blocks
can be solved instantly. This is intended for regression testing tools
and app development.
-rpcconnect=<ip>
Send commands to node running on <ip> (default: 127.0.0.1)
-rpcport=<port>
Connect to JSON-RPC on <port> (default: 9932 or testnet: 19932)
-rpcwait
Wait for RPC server to start
-rpcuser=<user>
Username for JSON-RPC connections
-rpcpassword=<pw>
Password for JSON-RPC connections
-rpcclienttimeout=<n>
Timeout in seconds during HTTP requests, or 0 for no timeout. (default:
900)
-stdin
Read extra arguments from standard input, one per line until EOF/Ctrl-D
(recommended for sensitive information such as passphrases)./pastelup-linux-amd64 install walletnode -r latest./pastelup-linux-amd64 start walletnode./pastel-cli tickets register id personal <pastelid> <passphrase> <address>PastelUp is Pastel Network's software for interfacing with our distributed blockchain software and is the best way to get started using Pastel. It functions as a utility wrapper for the node-operating binaries that communicate with the blockchain.
PastelUp installs, updates, and starts/stops the Pastel daemon (pastelD), as well as everything needed for the storage layer to operate (e.g., WalletNode, SuperNode)
Download the latest release of PastelUp from or directly via:
You can install PastelUp from the terminal as follows (make sure to change the url below to reflect the latest version number for PastelUp):
This command will install pasteld and pastel-cli in /home/<username>/pastel/
For testnet add flag `-n=testnet`
After installing the node:
You should see some output that looks like:
Change directories to the pasteld/pastel-cli installation location (Default /home/<username>/pastel/)
Use pastel-cli to connect to a running node:
This will print the number of nodes you're connected to. This might not work right away if you're just connecting to the network, but will work as your node is syncing to the main network.
You will need a Pastel address to send and receive PSL, and a PastelID to create NFTs. Your PastelID is used as a unique identifier to allow other Pastel users to identify creators and holders of assets. You might want multiple wallets, but you probably only want one PastelID.
Navigate to your pasteld/pastel-cli installation location (Default /home/<username>/pastel/). Then use pastel-cli to get a new chain address:
Backing up that pastel address with:
Will allow you to import that key at a later date with:
Next you should get a pastelID so you can identify your art on the network. Once again, use pastel-cli:
You will see a much larger key has printed to the console. You must register this newly generated pastel ID on the network in order to be able to use the APIs.
Register the artist with network:
./pastel-cli tickets register id <artist-pastel-id> "passphrase" <artist-address>
You would need 1000 PSL to be able to register your ID on the network.
On Testnet you can use to get the required LSP
To recover your pastelID for your wallet at a later date, you can import the key in combination with your passphrase:
Should yield output similar to:
Make Sure your node is synced with the Network
In order to be able to do anything useful on the Pastel Network, please make sure that your node is synced fully with the network. One way of making sure is to use `mnsync status` API
./pastel-cli mnsync status
Should yield output similar to:
The core node functionality above will connect you to the blockchain, but to get started using Pastel to register and search for art, you should get connected to the layer built on top of PSL, beginning with walletnode.
Head on over to to get started.
Sense: A Near-Duplicate NFT Detection Protocol on the Pastel Network.
Sense is a lightweight protocol on the Pastel Network, built to assess the relative rareness of a given NFT against near-duplicate meta-data. Sense can recognize even the most subtle similarities between two digital collectibles, even if one has been transformed. The protocol goes beyond the standard “digital fingerprint” approach to establishing the rareness of an NFT, and actually looks at the rareness of the pixel patterns in data. While digital fingerprints do allow users to verify that an NFT was created by a particular creator, this is a fairly weak form of rareness. Sense solves this problem by assigning a ‘Relative Rareness Score’ to quantify how rare an NFT is relative to all NFTs in the underlying dataset.
This score is a number between 0% (i.e., the NFT is identical to an existing NFT) to 100% (i.e., the NFT is not even similar to any known NFT). There are two properties of Sense’s rareness scores that make it far more powerful and useful than existing techniques:
It does not require an NFT to be an exact duplicate; in fact, the NFT data can be transformed in all sorts of complex ways and still be detected as being a “near-duplicate” of an existing NFT. For instance, the data could be cropped, rotated, stretched, flipped, have colors changes, have random noise added, be inverted, etc., and the system will still “see through” these superficial changes.
It allows for much more gradation of rareness; rather than reducing the question to a binary “yes/no,” the output provides for a well-defined rareness score to the nearest hundredth of a percent, providing useful information about how visually similar each NFT is compared to all known NFTs on the blockchain.
wget https://github.com/pastelnetwork/pastelup/releases/download/v1.1.3/pastelup-linux-amd64
chmod 755 pastelup-linux-amd64./pastelup-linux-amd64 install node -r latest./pastelup-linux-amd64 install node -r latest -n=testnet./pastelup-linux-amd64 start node./pastel-cli getconnectioncount./pastel-cli getnewaddress./pastel-cli dumpprivkey <address you just printed>./pastel-cli importprivkey <private key you just printed>./pastel-cli pastelid newkey "<passphrase>"./pastel-cli pastelid importkey "<key>" "<passphrase>"./pastelup-linux-amd64 stop node./pastelup-linux-amd64 update node -r latest
If you'd like to store files on the blockchain, but not necessarily make an NFT or perform dupe-detection, you can use the Cascade API interface.
Users or Applications can make use of Pastel's storage layer via our Walletnode application. We've already discussed how to install and run walletnode in previous section & How you can create your PastelID which is required to work with the APIs here.
Once you have walletnode up & running and also have a registered PastelID, you can follow these steps.
Call endpoint /openapi/cascade/upload to upload the file and get file_id and estimated_fee
You'll need to burn 20% of the estimated_fee to start cascade register task. Send 20% of the estimated burn fee (rounded up) to the burn address PtpasteLBurnAddressXXXXXXXXXXbJ5ndd (so if the estimated burn fee is 100 PSL, send 20). Note the response transaction id.
Call /openapi/cascade/start/<<file_id>> to start cascade register task. Use the transaction id and your pastelid. Expect a task_id in response.
Call /openapi/cascade/start/<<task_id>>/state: connect with this websocket to monitor the status of Cascade register task. This will, over time, allow you to see the state of the supernodes as they process it. When this yields "Task Completed" your art has been processed by the blockchain!
Use /openapi/cascade/<<task_id>>/history` to see task status history and details because websocket mentioned in (4) will only remain active until the registration process is active.
Use /openapi/cascade/download?pid=<<pastel_id>>&txid=<<tx_id>> to download the original file any time. tx_id is the RegistrationTXID or reg_txid you'll see in response of (4) and (5).
Any existing platform, project, or protocol can use Pastel's storage layer to store any type of file(s) in a secure & decentralized way - without needing to migrate their existing backend infrastructure.
The user first creates a PastelID for their underlying project, which will be used to submit all Cascade Requests API calls on the Pastel Network. Each call submits a request via HTTP to walletnode which in turn communicates with the network of Pastel SuperNodes viagRPC to store user's file in the network's storage layer.
The process begins with File upload call through walletnode. It returns file ID and estimated fee. The user first needs to burn 20% of the returned fee to the burn address PtpasteLBurnAddressXXXXXXXXXXbJ5ndd. The TxID of this transaction is used in the subsequent API call which starts the process. The user can access the file anytime after the process completes successfully.
WalletNode, upon receiving cascade request, connects with the network of SuperNodes and then sends requests to connected SuperNodes to verify if the request is a valid one. Mainly, SuperNodes verify the Burn TxID (The TxID of the 20% burn of estimated fee that the user or connecting app needs to do). After that, WalletNode uploads the file to connected SuperNodes for further processing and then generates RaptorQ Identifier files, calculates hash of the data file and size of the file as the fee is multiple of the size of the file in Megabytes. WalletNode then creates an action ticket and signs & sends it to connected SuperNodes.
SupeNodes, on the other hand, creates action registration ticket as mentioned .
Action registration ticket contains following data
PastelID of the caller.
Current Block number & Block Hash.
Action type (cascade or sense). cascade in this case.
Signatures of the SuperNodes taking part in the process.
This action registration ticket is sent to blockchain for registration of this cascade action. Walletnode then waits until there are confirmations from enough nodes about the action registration.
Action activation ticket has the following data
TxID of the Action Registration ticket.
PastelID of the action caller
Ticket storage fee in PSL, should match the storage fee from the Action Registration Ticket
Base64-encoded signature of the ticket created using the Action Caller's Pastel ID
Once it gets enough confirmations on action registration ticket, WalletNode then creates corresponding Action Activation ticket and wait for enough confirmations from Blockchain before it marks the cascade request as a successful one.
Once the process is completed successfully, the user's file is stored on Pastel's storage layer in a secure & decentralized way and it can be retrieved anytime in its original shape & form.
This document describes how Sense can be used and configured across various external backends.
Users or Applications can make use of our state-of-the-art duplication detection algorithms via our Walletnode application. We've already discussed how to install and run walletnode in & How you can create your PastelID which is required to work with the APIs .
Once you have walletnode up & running and also have a registered PastelID, you can follow these steps.
Storage Fee in PSL.
Key: a unique value to identify this ticket.
Label: the BurnTxID of the initial 20% burn transaction.
Block at which Action was called (Action Registration ticket was created)
Sense Webpage
Sense Demo
Documentation
Release Files
Explorer
Explorer API
OpenNode
RPC Docs
Mining Pool
Explorer
LSP Faucet
OpenNode
Mining Pool
/openapi/sense/upload API to upload the image and get image_id and estimated_feeYou'll need to burn 20% of the estimated_fee to start sense register task. Send 20% of the estimated burn fee (rounded up) to the burn address PtpasteLBurnAddressXXXXXXXXXXbJ5ndd (so if the estimated burn fee is 100 PSL, send 20). Note the response transaction id.
Call /openapi/sense/start/<<image_id>> to start sense register task. Use the transaction id and your pastelid. Expect a task_id in response.
Call /openapi/sense/start/<<task_id>>/state: connect with this Websocket to monitor the status of Sense register task. This will, over time, allow you to see the state of the supernodes as they process it. When this yields "Task Completed" your art has been processed by the blockchain!
Use /openapi/sense/<<task_id>>/history` to see task status history and details because websocket mentioned in (4) will only remain active until the registration process is active.
Use /openapi/sense/download?pid=<<pastel_id>>&txid=<<tx_id>> to download the duplication detection results for the provided image. tx_id is the RegistrationTXID or reg_txid you'll see in response of (4) and (5).
Any existing platform, project, or protocol can access the NFT fingerprints and their relative rareness scores, and add such to a registry of NFTs as a way to timestamp or “claim” the underlying data in a decentralized, trust-less way - without needing to migrate their existing backend infrastructure.
The user first creates a PastelID for their underlying project, which will be used to submit all Sense Requests API calls on the Pastel Network. Each call submits a request via HTTP to walletnode which in turn communicates with the network of Pastel SuperNodes viagRPC, which then return the Relative Rareness Score in a JSON.
The process begins with Image upload call through walletnode. It returns and image ID and estimated fee. The user first needs to burn 20% of the returned fee to the burn address PtpasteLBurnAddressXXXXXXXXXXbJ5ndd. The TxID of this transaction is used in the subsequent API call which starts the process. The user can download the JSON results once the process completes.
Each time the user calls Sene API,the NFT is passed and added to a dedicated SQLite database hosted by the SuperNodes on Pastel. The JSON results returned from the API request are compared among the multiple SuperNodes randomly assigned to perform such calculations. If each result matches, the top-ranked SuperNode adds the JSON file to Pastel's Storage Layer via Kademlia. We then create a new Pastel Blockchain ticket, the Action_Registration_Ticket, which is signed by both the user's PastelID and the PastelIDs of each SuperNode that handled the request. This Pastel Blockchain ticket contains the SHA3-256 hash of the JSON file in Kademlia containing the results of running the Sense Protocol on the NFT as well as the SHA3-256 hash of the original NFT data. The same NFT hash is included in the JSON metadata of the corresponding NFT on the user's platform.
Once the Sense Protocol is completed by the Supernodes, they create and sign the Action_Registration_Ticket with their PastelIDs. The user then signs the Action_Registration_Ticket with the user's PastelID, at which point the final signed Action_Registration_Ticket would be written to the Pastel blockchain by the Supernodes which counter-signed it.
At this point, the user has a sense Action_Registration_Ticket on Pastel. The NFT provided by the user also has its own fingerprint vector added to the SQLite database. Thus, the next time that relatively same image is submitted to Pastel in a new sense Action_Registration_Ticket , the new NFT would result in a lower relative rareness score as it would be compared to the previous ticket for the similar NFT. In addition, the other data resulting from running the Sense Protocol on the image, such as the rareness score and the NFT perceptual hashes, would all be stored in Kademlia in a JSON file. To ensure redundancy, we create several variants of this JSON by adding a nonce to the end of each one, resulting in a different SHA3-256 hash for each copy, which are then all stored in Kademlia separately.
Because only Supernodes in Pastel can directly access Kademlia, we could set up some public-facing servers that are also Pastel Supernodes with a REST API that would respond to public requests; in these requests, users could submit an image file hash and get as a result the corresponding JSON file from Kademlia, assuming that this particular image had been submitted previously. But to avoid needing to rely on some external service, Rarible might elect to set up their own Pastel Walletnode so that they could set up an API like that on their own and cover the cost of serving it at scale.
PastelID of the caller.
Current Block number & Block Hash.
Action type (cascade or sense). sense in this case.
Signatures of the SuperNodes taking part in the process.
Storage Fee in PSL.
Key: a unique value to identify this ticket.
Label: the BurnTxID of the initial 20% burn transaction.
Action registration ticket contains following data
Action activation ticket has the following data
TxID of the Action Registration ticket.
PastelID of the action caller
Ticket storage fee in PSL, should match the storage fee from the Action Registration Ticket
Base64-encoded signature of the ticket created using the Action Caller's Pastel ID
Block at which Action was called (Action Registration ticket was created)
Once it gets enough confirmations on action registration ticket, WalletNode then creates corresponding Action Activation ticket and wait for enough confirmations from Blockchain before it marks the cascade request as a successful one.
Once the process is completed successfully, the user can download the results in JSON using Walletnode's download API for Sense.
Fees are calculated and charged to the user during various message executions on the network. Types of fees on network include fixed and variable.
Fixed fees are incurred by users during simple transactions that require minimal computational effort as a way to deter bad-acting users from spamming the network. Fixed fees are burnt following a mechanism and are required for any action on the network, including:
Creating or modifying a "user name".
NFT Registration
NFT Transfer
Sense and Cascade Transfers
Variable fees are charged to users proportionate to the amount of compute or storage resources required to execute specific operations. Variable fees on Pastel leverage a mechanism that automatically adjusts relative to network difficulty and computational resources in order to keep them reasonable despite large changes in the dollar value of Pastel's native PSL currency token. Variable fees are either burnt or distributed to the SuperNodes that process a user's requests and include:
NFT Activation
NFT Offer, Accept
Sense API (i.e., Pastel's near-duplicate image detection system)
Cascade API (i.e., the underlying storage layer of Pastel)
Sense and Cascade Offer, Accept
Create Pastel ID
1,000
Burnt by User
User Name Change (first change)
100
Burnt by User
User Name Change (any subsequent changes)
5,000
Burnt by User
Network Storage Fee per MB is calculated as the "Trimean" of the specified network fees of all ENABLED SuperNodes. The Trimean simply drops the bottom and top quartile before averaging the results in the 50th to 75th percentile, which results in a more robust estimate that can't be distorted by excessively high or low specified fee levels; this prevents malicious SuperNodes from manipulating fee levels to impractical levels that are either too low to offset the cost of providing the service or too high to make sense for users. The default Network Fee per MB is set to 50 PSL, although individual SuperNodes can modify this for their own nodes.
Ticket Storage Fee per KB is calculated as an average of NFT Ticket Storage Fees of all ENABLED SuperNodes. Default Ticket Storage Fee is 3 PSL per KB.
Pastel makes use of various configuration files to start & then keep the services functioning properly.
Below is the list of configuration files along with description and samples.
This file is used by pasteld for simple node settings. Its default location is pastel config directory. Here's a sample file
This file is used by pasteld for masternode specific settings
As the name implies, this is used by supernode service
As the name implies, this is used by walletnode service. Its default location is pastel config directory.
This is used by hermes service. Hermes service runs on supernodes.
This is used by bridge service. Bridge Service is used with walletnode service as an option to speed up thumbnails retrieval as part of retrieving NFT data from walletnode APIs
server=1
listen=1
rpcuser=5pa4HxyM
rpcpassword=q20stoBEctqQN2o
rpcport=19932
testnet=1
addnode=18.112.12.211NFT Registration
10
Burnt by Registering SuperNode
NFT Activation (Fixed)
10
Burnt by User
NFT Activation (Variable)
NFT Image Storage (1):
50 PSL / 1 MB
+
NFT Ticket Storage (2):
3 PSL / 1 KB
54% to Registering Principal SuperNode
36% split between two Verifying SuperNodes (18% to each)
10% Burnt
NFT Offer
2% of Sale Price, minimum 10 PSL
Burnt by the current NFT owner
NFT Accept
1% of Sale Price,
minimum 10 PSL
Burnt by the new NFT owner
NFT Transfer (Fixed)
10
Burnt by the current NFT owner
OpenAPI-Sense Registration
(Fixed)
10
Burnt by User
OpenAPI-Sense Activation
(Fixed)
10
Burnt by User
OpenAPI-Sense (Variable)
Sense API by Image Size:
10 PSL / MB
+
Image Storage (1):
250
+
Sense Ticket Storage (2):
15
48% to Registering Principal SuperNode
32% split between two Verifying SuperNodes (16% to each)
20% Burnt
OpenAPI-Cascade
Registration
(Fixed)
10
Burnt by User
OpenAPI-Cascade
Activation
(Fixed)
10
Burnt by User
OpenAPI-Cascade (Variable)
Cascade Data Storage:
50 PSL / 1 MB
+
Cascade Ticket Storage (2):
15
48% to Registering Principal SuperNode
32% split between two Verifying SuperNodes (16% to each)
20% Burnt
OpenAPI-Sense and Cascade Offer
2% of Variable Price,
minimum 10 PSL
Burnt by the current owner
OpenAPI-Sense and Cascade Accept
1% of Variable Price,
minimum 10 PSL
Burnt by the new owner
OpenAPI-Sense and Cascade Transfer
10
Burnt by the current owner
{
"my-masternode-name": {
"extAddress": "1.23.456.789:14444",
"extCfg": "",
"extKey": "jXYj8SueWC7q19cknwWVykjZZR7boK8BF1v7abqpf7Nn4CJqdQL4wPwZJr9XNpynezcJ2Vw3c7L3G5mQoVkxMp",
"extP2P": "1.23.456.789:14445",
"mnAddress": "1.23.456.789:19933",
"mnPrivKey": "93Tyo5C6K7wpoS6EvaKVjmC84LdcDTq1gkFw2c4ioJ9CLB2GaCi",
"outIndex": "1",
"txid": "c8a3e1ef635f692eb3bb079bcf9eff479abe17ccb2b1936335f9229eef8b75cb"
}
}
log-config:
log-file: # e.g: logs.json - by default, logs are only written to stdout
log-compress: true # compress log or not
log-max-size-mb: 100 # maximum log file size before rotate to new file
log-max-age-days: 3 # maximum duration to retain old log files based on the timestamp encoded in their filename
log-max-backups: 10 # set the maximum number of old log files to retain
log-levels: # log level of individual files
common: debug
p2p: debug
metadb: info
dd: info
temp-dir:
work-dir:
rq-files-dir:
dd-service-dir:
node:
pastel_id: <<pastel_id>>
pass_phrase: <<passphrase>>
server:
listen_addresses: "0.0.0.0"
port: 14444
p2p:
listen_address: "0.0.0.0"
port: 14445
data_dir: "p2p-data"
raptorq:
host: "rq-server-1"
port: 50051
dd-server:
host: "dd-server-1"
port: 50052
dd-temp-file-dir: "dd-server"
log-config:
log-level: info
log-file: /home/user/.pastel/walletnode.log
log-compress: true
log-max-size-mb: 100
log-max-age-days: 3
log-max-backups: 10
quiet: false
temp-dir: /home/user/.pastel/tmp
work-dir: /home/user/.pastel
rq-files-dir: /home/user/.pastel/rqfiles
node:
api:
hostname: "localhost"
port: 8080
burn_address: <<burn_address>>
raptorq:
host: "localhost"
port: 50051
bridge:
address: "localhost"
port: 60061
switch: false // use bridge service or not.
//If true, bridge service must be available.log-config:
log-file: # e.g: logs.json - by default, logs are only written to stdout
log-compress: true # compress log or not
log-max-size-mb: 100 # maximum log file size before rotate to new file
log-max-age-days: 3 # maximum duration to retain old log files based on the timestamp encoded in their filename
log-max-backups: 10 # set the maximum number of old log files to retain
log-levels: # log level of individual files
common: debug
p2p: debug
metadb: info
dd: info
work-dir:
rq-files-dir:
dd-service-dir:
quiet: false
pastel_id: <<pastel_id>>
pass_phrase: <<passphrase>>
sn_host: "localhost"
sn_port: 14444log-config:
log-level: info
log-file: /home/user/.pastel/bridge.log
log-compress: true
log-max-size-mb: 100
log-max-age-days: 3
log-max-backups: 10
quiet: false
temp-dir: /home/user/.pastel/tmp
work-dir: /home/user/.pastel
download:
pastelid: <<pastel_id>>
passphrase: <<passphrase>>
connection_refresh_timeout: 300
connections: 10
server:
listen_addresses: 127.0.0.1
port: 60061


nft_ticket is base64 encoding of the following JSON, as a string:This JSON is created by WalletNode during the New NFT Registration process
app_ticket is ascii85 of the following JSON, as a string:This JSON is created by WalletNode during the New Art Registration process
Dupe detection service - dd-service outputs data as json (dd_and_fingerprints) in the following format
WalletNode calculates IDs for dd_and_fingerprints_ids field of app_ticket as:
Base58(SHA3_256(compressed(Base64(dd_and_fingerprints).Base64(signatureSN1).Base64(signatureSN2).Base64(signatureSN3).counter)))
Where:
dd_and_fingerpints, is data returned by dd-service
signatureSN1-3, is Supernode's signatures of dd_and_fingerpints data
counter, is number in the range from dd_and_fingerprints_ic to dd_and_fingerprints_ic + dd_and_fingerprints_max
All three parts are concatenated together using "." as separator
raptorQ service - rq-service outputs rq-symbols's id's in the following format
WalletNode calculates IDs for rq_ids field of app_ticket as:
Base58(SHA3-256(compress(Base64(rq_ids).Base64(signature).counter)))
Where:
rq-service-data, is data created by rq-service
signature, is creators signature over rq-service-data
counter, is number in the range from rq_ids_ic to rq_ids_ic + rq_ids_max
All three parts are concatenated together using "." as separator
signatures are the following JSON object:All signatures here are of
nft_ticket
principalelement is created by WalletNode before sending ticket to SuperNodes for further processing
mn2andmn3elements are created by SuperNode 2 and SuperNode 3 respectfully
signatureelements are created by cNode on the SuperNode 1 as part of cNode API calltickets register nft, and MUST not be passed into the call
Ticket is written into blockchain by the cNode API tickets register nft:
here,
key1 is unique human readable extract from fingerprints
key2 is anything else that can be used as secondary key
Ticket representation inside blockchain:
Ticket is written into the blockchain by the cNode API tickets register act:
Ticket representation inside blockchain:
Ticket is written into the blockchain by the cNode API tickets register sell:
Ticket representation inside blockchain:
Ticket is written into the blockchain by the cNode API tickets register buy:
Ticket representation inside blockchain:
Ticket is written into the blockchain by the cNode API tickets register trade:
A detailed technical background on how the Sense Protocol works.
Effective “near-duplicate image detection” is an open research problem in computer vision, given the fact that visual data is extremely high dimensional. Even a relatively tiny 100kb jpeg file can easily comprise 500,000 or more pixels, each of which has a red, green, and blue component. Moreover, someone could edit that jpeg file in Photoshop in such a way that would seem immediately recognizable to a human observer as a simple derivative of the original image, but nevertheless end up changing every single one of those pixels, perhaps in highly complex ways that leave little of the original structure intact at the level of the individual pixels.
Senses solves this problem by dramatically reducing the dimensions involved, while still retaining the high-level structural content of the data. The compressed representation becomes the NFT fingerprint, a list of numbers vs. the original pixel data, that is robust to various transformations. In this manner, even if we compare the fingerprint of a candidate NFT which is simply another known NFT with random noise, it will look suspiciously similar to the fingerprint of the original NFT. By quantifying this similarity, we achieve a measure that we can use as a relative known rareness score.
By leveraging a variety of well-trained deep neural net models comprising tens of millions of artificial “neurons,” we can achieve exceptional results on very complex data classification tasks. When each model is parsed a particular data, it generates a list of N numbers in a particular order, which we refer to as the NFT fingerprint vector for a given image and model. An analogy of the vector is as follows: We take a human subject and scan their brain in real-time to see exactly what nerve cells are active at any time, and how activated each one is. We then show the human subject the candidate NFT and record the results of the activation pattern in their brain as a series of numbers. Similar to how a human brain works, what the model “sees” is not just some mechanical description of the precise pixels, but rather a high-level depiction of the NFT contents. This ability to capture the “high-level abstract content” of the NFT is what makes these representations so powerful.
In order to construct the NFT fingerprint vector, we leverage a number of well-defined models. Each model requires a unique pre-processing pipeline applied to the NFT, such as resizing and pixel representation. We then obtain the NFT fingerprint vector as an output from each of the individual models, which is then concatenated into a single large fingerprint vector consisting of exactly 10,048 decimal numbers. The output below demonstrates the first 16 numbers of a fingerprint vector for a particular NFT:
Notably, certain of the entries in the example above are exactly zero which shows that there is real structure to each fingerprint. If a certain feature is not detected in the input data, then some of the outputs will be ‘switched’ off. In any case, we have now transferred input data into a fingerprint vector – a process which takes less than a few seconds to complete.
Near-Duplicate Detection
Once we have a representation of data that serves as the NFT fingerprint, we are able to more accurately assess the relative rareness of each fingerprint within the dataset. For example, consider the two scenarios below:
Scenario 1: Two Dissimilar Images:
Scenario 2: Similar Images:
For the relative rareness score to be useful, we need to calculate a similarity score that would result in the images in Scenario 1 having a fairly low similarity score (note that, even if the subjects are very different, if the images were made by the same creator using similar techniques, they still might have a higher similarity score than if we compared them to a completely different image) while in Scenario 2, each of those images should have a very high similar score. Also observe how in Scenario 2, every single pixel is changed meaningfully from its original value.
The NFT fingerprint vectors are robust to simple transformation and describing similarity that looks into the fingerprints at a deeper level. We leverage various tools in the form of different correlation measures and statistical dependency measures. We compute the correlation between a candidate NFT fingerprint and the entire database of many hundreds of thousand or millions of NFTs in just a few seconds. As a result, we take a candidate NFT fingerprint vector and return a list of correlation measures comparing it to the fingerprints of all previously registered NFTs in the system.
To reliably identify near-duplicate with a reasonable confidence interval, we leverage a variety of functions and correlation measures — some of which are fairly advanced and computationally intensive. For example, the system relies on correlation measures that operate on the ranks of data rather than the data values themselves, and on similarity measures of statistical dependency. Essentially, these measures inform us about how “suspiciously similar” two fingerprint vectors are. Put another way, they enable us to measure how improbably it would be to find such particular patterns between the fingerprints if we were really looking at “random” or unrelated data. We combat the issue of false negatives by employing several differentiated, varied, and powerful similarity measures.
Optimization Techniques
We then optimize the performance of the system to minimize false negatives and false positives alike by employing additional techniques.
In one instance, we assess all Pearson correlation scores for all registered NFTs versus the candidate NFT, and then compare the value of the maximum correlation of any registered NFT to the 99.99th percentile correlation across all registered NFT. The percentage increase in the maximum correlation versus the 99.99th correlation (i.e., Pearson Gain), can tell you some very useful information if it’s large enough. For example, suppose that there are 10,000 registered fingerprints such that there are 10,000 correlation scores, sorted in descending order. We compare the maximum to the 99.99th percentile score – suppose that the top score is 86.00%, and the second score is 65.00%, implying a Pearson Gain of 86.00%/65.00% - 1 = 32.3%. This signifies that exactly one had a much higher correlation than the rest of the dataset. Extending this across the entire dataset, we can identify correlation across broad clusters of NFT data objects. Implementing this requirement drastically improves the threshold of confidence in our system.
The system as outlined accurately quantifies a similarity score on a spectrum of 0.00% - 100.00% rather than a binary 0-1 in a way that resembles human intuition. We combine the results of the process described above to generate various “sub-scores” which is transformed to a single number between 0.00% - 100.00%. One sub-score sums up the various similarity measures and compares the sum to the “maximum” if the NFTs were the same, essentially averaging the result of the different similarity measures to the extent they are available. We combine the sub-scores across each methodology to compute the Combined Relative Rareness Score.
Machine Learning Makes It Even Better
We employ a parallel approach using machine learning to further optimize our approach. We start with a universe of known NFT files, such as open data from OpenSea. We then segregate a certain percentage of the data as registered NFTs and compute their NFT fingerprint vector. We take the remaining data as un-known true originals - that is, we do not compute their NFT fingerprint vector, and we know that none of these NFTs are in our database. Finally, we generate a large corpus of artificially generated near-duplicate NFTs through transformation techniques as shown in the examples below:
Then, we apply our entire Sense protocol to the transformations. We select a known near-duplicate NFT, compute its fingerprint vector, and apply our funnel of correlation measures to compare it to all registered NFTs. Next, we select an original NFT that we know should not be identified as a near-duplicate of any registered NFT and apply the same process. For each of these, we can observe how many registered fingerprints make it to the “last stage” of the funnel. Rather than track the Combined Relative Rareness Score, we apply a binary label of 1 to the artificial near-duplicate NFTs and 0 to the true originals. We then model our input data against the various similarity measures and sub-scores we compute for each image.
This methodology enables us to then make use of machine learning training, or supervised learning. Given a row of data which signifies the maximum correlation scores of the candidate NFT versus all the registered NFT fingerprints, we predict whether the label is a 1 (i.e., duplicate) or a 0 (i.e., original) using various approaches. For example, we build random forest classifier that uses an ensemble of decision trees to predict the label from the input data via XGBoost. We also construct a deep neural network classifier using Keras applications that predicts the label from the input data. Each of the models are nuanced and provide different degrees of gradations. We combine each score produce a final Overall Average Score, which is far more precise and maps closer to human intuition than any individual score.
Putting it All Together with Examples
The following are results demonstrating the actual protocol running on example NFTs from the test corpus
1. Modification of a known NFT with random noise
First, we begin by modifying a known NFT by adding random noise, to an extent that would more than enough to cause Google’s reverse image search to not find any matches at all. In this example, the system accurately classifies it, assigning it a fairly low overall average rareness score of ~28.82% Note that the system was also able to correctly identify the exact registered image that the candidate image was derived from.
2. Modification of a known NFT through modification
Here is another example of a near-duplicate where it’s a “stretched” version of a registered image; in this case, the overall average rareness score is just 0.087, which is quite low; if we were to use an actually identical image, the score would be closer to 0.0:
Perhaps most impressive of these examples is applying the system to a near-duplicate that uses a “contour” or edge detection filter on a registered image; the system gives this an overall average rareness score of just ~0.15 despite it looking dramatically different versus the original:
Rareness on the Internet
We leverage existing open-source functionality, such as Google’s Reserve Image Search, to crawl and index websites and assess rareness relative to what is known to the internet. These tools provide results which is described as “visually similar” data such as shown below:
It has been indexed by various websites and Google is able to find the exact image. The same applies to an NFT “series” where there are dozens or even thousands of extremely similar images created as part of a series. When a user attempts to register a new NFT on Pastel Network, in addition to running the standard Pastel, assess its relative rarness to the internet (note that this is done in a fully decentralized way, with multiple randomly selected Pastel Supernodes conducting the same search and ensuring that their results all match exactly, just as the Pastel rareness score is computed by multiple Supernodes independently and the results checked for consistency):
If an artist has created a genuinely new image and never shared this image before online, then they can first register it on Pastel Network, and they will receive the highest level of “certified rareness” available on the system: the resulting NFT will be rare on Pastel and rare on the internet, and both of these metrics are written into the immutable NFT registration ticket that is part of the Pastel Blockchain. If that image is subsequently shared on social media or other websites, then the rareness scores of the Pastel NFT will not change—the only thing that matters is how rare it was at the time it was registered on Pastel.
Concluding Remarks
If you think about it, this is a much, much stronger concept of what it means for a digital image to be “rare”: not only can we verify the authenticity and provenance using the creator’s digital signatures (like all NFT systems in use), but we can go much further, and actually assess how rare the underlying pixel patterns of the image are, both on Pastel Network itself as well as on the broader internet. If value is largely a function of rareness/scarcity, we believe that this additional layer of authentication of rareness will result in better valuations for NFT creators. After all, if another creator makes a similar NFT in the future, they will still be able to register it on Pastel, but it won’t achieve anything close to the rareness score of the original image.
Furthermore, even if the original creator themselves try to create another very similar or identical NFT in the future, this subsequent NFT will not have the rareness score of the creator’s first and original NFT. This protects NFT buyers from “inflation” caused by the creator, which is something that an NFT system based only on verifying digital signatures can’t really do, since the second or third “highly similar” or identical NFT would still appear to be totally legitimate because it is correctly signed by the artist— despite the fact that it’s a “knock off” of the original.
How It Works
Each SuperNode on Pastel running Ubuntu 20.04 has a handful of support directories to exist on the local machine.
The fingerprint database (which uses SQLite as the database system) file is “seeded” with several thousand NFT fingerprints. An example database file can be downloaded which contains several thousand image fingerprints. In addition, there are pre-trained classifiers such as XGBoost and Keras that are downloaded and trained by the client.
The client then simply runs the Python file, which will loop and monitor the “dupe_detection_input_files” folder for new NFT files. If the user uploads new data into this folder, the process will wait for the file to finish uploading over and will then proceed with the analysis automatically. First it will compute the rareness score, and then it will compute the “internet rareness score.”
Finally, the process will compute a series of perceptual hashes. The perceptual hashes are used to scale the system in the case when a candidate NFT is a near exact duplicate of an already registered NFT; in effect, if the hash-based system uncovers a duplicate, we can skip over the computationally intensive process and go straight to giving the image a rareness score of zero. We use a variety of image hashing algorithms, including the “pdq” algorithm from Facebook Research and the “NeuralHash” algorithm from Apple, as well as more traditional methods.
When the process finishes, it generates a json output file in the folder “dupe_detection_output_files”, where the file name is the first 10 characters of the SHA3-256 hash of the image file. For example:
The contents of this file is as follows (the final element in the json file, “image_fingerprint_of_candidate_image_file,” has been shortened below for space reasons since it consists of 10,048 numbers):
Scalability:
The current architecture of Pastel’s Dupe Detection system can scale up to several hundred thousand images. The main limiting factor is that the machine running the dupe detection code must keep a table of all registered images in memory.
However, there is a very straightforward approach to scaling the system up to millions of images, which is essentially to use what is known as “”. The basic idea is as follows:
Each Supernode (“SN”) has an identifier used as its name in the Pastel Network. By using the concept of , we can associate each SN with a particular subset of the space of all previously registered images. These associations would not be disjoint: that is, the same images would be assigned to at least 3 SNs so that we can compare the results of these machines to see that they all match.
Each SN is responsible for computing the correlations/dependency scores for the candidate image compared to the subset of all registered images which the SN is responsible for. After this is done, these correlation scores are shared with other SNs in the network, and the results from the SNs that have been assigned the same subset of images are compared to check for consistency.
The verified results from each group of SNs are all sent to the 3 top ranked Supernodes, which combine the results and then finish the computation. This avoids the limiting factor mentioned above, which is the current requirement for the full table of registered fingerprints to reside in memory at once on a single machine. The results of the overall computation from each of the three top ranked SNs are compared by all SNs to check for consistency, and if they match, the results are written to the blockchain as usual.
{
"ticket": {
"type": "nft-reg",
"nft_ticket": bytes, // NFT ticket (encoded with base64), see below
"version": integer, // version, 0 now
"signatures": object, // signatures, see below
"key1": string, // Unique key
"key2": string, // Second unique key
"creator_height": int, // Block height at which NFT Ticket was created
// it is used to check if the SN that created
// this ticket was indeed in the list of top 10 SN
// at the moment of registration
"total_copies": int, // Number of available copies in NFT
"royalty": float, // Royalty %
"royalty_address": string, // Address to pay royalty
"green": boolean, // Indicate whether there green payment
"storage_fee": int, // Registration fee, in PSL
}
}{
"nft_ticket_version": integer // 1
"author": string, // PastelID of the author (creator)
"blocknum": integer, // Block height at which NFT Ticket was created
// it is used to check if the SN that created
// this ticket was indeed in the list of top 10 SN
// at the moment of registration
"block_hash": bytes // Same as above, but block hash
"copies": integer, // Number of available copies in NFT
"royalty": float, // Royalty %
"green": bool, // Indicate whether there green payment
"app_ticket": bytes, // Application specific ticket data (as ascii85)
}{
"creator_name": string,
"creator_website": string,
"creator_written_statement": string,
"nft_title": string,
"nft_type": string,
"nft_series_name": string,
"nft_creation_video_youtube_url": string,
"nft_keyword_set": string,
"total_copies": integer, // number of copies, same as in NFT Ticket
"preview_hash": bytes, // hash of the preview thumbnail !!!!SHA3-256!!!!
"thumbnail1_hash": bytes, // hash of the thumbnail 1 !!!!SHA3-256!!!!
"thumbnail2_hash": bytes, // hash of the thumbnail 2 !!!!SHA3-256!!!!
"data_hash": bytes, // hash of the image (or any other asset) that this ticket represents !!!!SHA3-256!!!!
// dupe detection and fingerprints files IDs, these IDs link ticket to data in P2P storage
"dd_and_fingerprints_ic": integer, // initial value of the counter for dd_and_fingerprints files
"dd_and_fingerprints_max": integer, // maximum number of dd_and_fingerprints files (current default is 50)
"dd_and_fingerprints_ids": [list of strings], // list of IDs of dd_and_fingerprints files in Kademlia
// raptorq ids files IDs, these IDs link ticket to data in P2P storage
"rq_ic": integer, // initial value of the counter for rq_ids files
"rq_max": integer, // maximum number of dd_and_fp files (current default is 50)
"rq_ids": [list of strings], // list of IDs of of rq-ids files in Kademlia
"rq_oti": [array of 12 bytes], // raptorq CommonOTI and SchemeSpecificOTI
}{
"block": string // block_hash from NFT ticket
"principal": string // PastelID of the author from NFT ticket
"dupe_detection_system_version": string,
"is_likely_dupe": bool,
"is_rare_on_internet": bool,
"rareness_scores": {
"combined_rareness_score": float, // 0 to 1
"xgboost_predicted_rareness_score": float, // 0 to 1
"nn_predicted_rareness_score": float, // 0 to 1
"overall_average_rareness_score": float, // 0 to 1
},
"internet_rareness": {
"matches_found_on_first_page": uint32,
"number_of_pages_of_results": uint32,
"url_of_first_match_in_page": string,
},
"open_nsfw_score": float, // 0 to 1
"alternative_nsfw_scores": {
"drawings": float, // 0 to 1
"hentai": float, // 0 to 1
"neutral": float, // 0 to 1
"porn": float, // 0 to 1
"sexy": float, // 0 to 1
},
"image_fingerprint_of_candidate_image_file": [float], // array with fingerprints values
"fingerprints_stat": {
"number_of_fingerprints_requiring_further_testing_1": uint32,
"number_of_fingerprints_requiring_further_testing_2": uint32,
"number_of_fingerprints_requiring_further_testing_3": uint32,
"number_of_fingerprints_requiring_further_testing_4": uint32,
"number_of_fingerprints_requiring_further_testing_5": uint32,
"number_of_fingerprints_requiring_further_testing_6": uint32,
"number_of_fingerprints_of_suspected_dupes": uint32,
},
"hash_of_candidate_image_file": string,
"perceptual_image_hashes": {
"pdq_hash": string,
"perceptual_hash": string,
"average_hash": string,
"difference_hash": string,
"neuralhash_hash": string,
},
"perceptual_hash_overlap_count": uint32,
"maxes": {
"pearson_max": float, // 0 to 1
"spearman_max": float, // 0 to 1
"kendall_max": float, // 0 to 1
"hoeffding_max": float, // 0 to 1
"mutual_information_max": float, // 0 to 1
"hsic_max": float, // 0 to 1
"xgbimportance_max": float, // 0 to 1
},
"percentile": {
"pearson_top_1_bps_percentile": float, // 0 to 1
"spearman_top_1_bps_percentile": float, // 0 to 1
"kendall_top_1_bps_percentile": float, // 0 to 1
"hoeffding_top_10_bps_percentile": float, // 0 to 1
"mutual_information_top_100_bps_percentile": float, // 0 to 1
"hsic_top_100_bps_percentile": float, // 0 to 1
"xgbimportance_top_100_bps_percentile": float, // 0 to 1
},
}BLOCK_HASH
PASTELID
raptroq id1 // raptorq symbol identifiers - ID of that symbol file in Kademlia - !!!!SHA3-256 of symbol block!!!!
...
raptroq idN{
"principal" : { "PastelID" : "signature" },
"mn2" : { "PastelID" : "signature" },
"mn3" : { "PastelID" : "signature" }
}tickets register nft "nft_ticket" "{signatures}" "pastelid of MN 1" "passphrase" "key1" "key2" fee"ticket": {
"type": "nft-act",
"version": integer, // version of the blockchain representation of ticket, 0 now
"pastelID": string, // PastelID of the creator
"reg_txid": string, // tnx with registration ticket in it
"creator_height": int, // block at which artist created Art Ticket,
// is used to check if the MN that created art registration ticket was indeed the top MN when the artist created ticket
"storage_fee": int, // should match the storage fee from the Art Ticket
"signature": bytes // Signature of the ticket created using the MasterNode's private key
}tickets register act "txid-of-nft-reg-ticket" creator_height-fromart-reg-ticket fee "PastelID-of-the-creator" "passphrase""ticket": {
"type": "nft-sell",
"version": integer, // version of the blockchain representation of ticket, 0 now
"pastelID": string, // PastelID of the nft owner - either 1) the original creator; or 2) a previous buyer,
// should be the same in either 1) art activation ticket or 2) trade ticket
"nft_txid": int, // txid with either 1) art activation ticket or 2) trade ticket in it
"copy_number": int,
"asked_price": int,
"valid_after": int,
"valid_before": int,
"signature": bytes
}tickets register sell "txid-of-art-to-sell-act-or-trade" price "PastelID-of-the-seller-artist-or-owner" "passphrase""ticket": {
"type": "nft-buy",
"version": integer, // version of the blockchain representation of ticket, 0 now
"pastelID": string, //PastelID of the buyer
"sell_txid": int, //txid with sale ticket
"price": int,
"signature": bytes
},tickets register buy "txid-of-sell-ticket" price "PastelID-of-the-buyer" "passphrase""ticket": {
"type": "nft-trade",
"version": integer, // version of the blockchain representation of ticket, 0 now
"pastelID": string, // PastelID of the buyer
"sell_txid": bytes, // txid with sale ticket
"buy_txid": bytes, // txid with buy ticket
"nft_txid": bytes, // txid with either 1) art activation ticket or 2) trade ticket in it
"registration_txid": bytes, // txid of nft-reg ticket
"copy_serial_nr": int,
"signature": ""
},tickets register trade "txid-of-art-to-sell-ticket" "txid-of-art-to-buy-ticket" "PastelID-of-the-buyer" "passphrase"00d201498d.json{
"dupe_detection_system_version": "1.0",
"hash_of_candidate_image_file": "00d201498d114d3ecddc8c3a53e0a50605cfc4f7f00d0b51a035435b933597de",
"is_likely_dupe": 0,
"overall_average_rareness_score": 0.9397604155043761,
"is_rare_on_internet": 0,
"matches_found_on_first_page": 3,
"number_of_pages_of_results": 2,
"url_of_first_match_in_page": "https://www.wga.hu/art/l/le_pautr/jean/vasecart.jpg",
"open_nsfw_score": 0.003387457923963666,
"alternative_nsfw_scores": {"drawings": 0.0073842271231114864, "hentai": 0.01797575317323208, "neutral": 0.9581771492958069, "porn": 0.006965779699385166, "sexy": 0.0094971414655447},
"image_hashes": {"pdq_hash": "81d39ce6434f5993850c671d5c93b27cfa3098c3a37c79c95fd2262e68ac55d1", "perceptual_hash": "a5451a3aa5c99f65", "average_hash": "0426727343862107", "difference_hash": "8d6cc686862ce9af", "neuralhash_hash": "a8d5bdc438dbe150084b56d2"},
"image_fingerprint_of_candidate_image_file": "[0.056579, 0.109756, 0.0, 0.158492, 0.110712, 0.012927, 0.015477, 0.084702, 0.099882, 0.0, 0.078663, 0.0, 0.016425, 0.149021, 0.020405, 0.059796, 0.083588, 0.013133, 0.228209, 0.063899, 0.014951, 0.091711, 0.341302, 0.522906, 0.097734, 0.0, 0.00687, 0.310707, 0.0, 0.028732, 0.214935, 0.021326, 0.0, 0.388309, 0.065243, 0.058431, 0.0, 0.042438, 0.009509, 0.016926, 0.0, 0.350938, 0.14472, 0.589144, 0.066582, 0.0, 0.323072, 0.120469, 0.026063, 0.025556, 0.141907, 0.042398, 0.191165, 0.002123, 0.002837, 0.0, 0.02315, 0.066923, 0.0, 0.011117, 0.246654, 0.040481, 0.358261, 0.01947, 0.0, 0.135538, 0.009615, 0.805166, 0.978006, 0.013197, 0.011743, 0.283975, 0.033605, 0.017279, 0.026492, 1.084193, 0.006202, 0.092191, 0.078222, 0.0, 0.052481, 0.062024, 0.332504, 0.000604, 0.077192, 0.193348, 0.0, 0.069321, 0.352793, 0.605095, 0.058262, 0.013841, 0.007915, 0.013669, 0.00566, 0.04206, 0.127357, 0.04133, 0.0, 0.005327, 0.063609, 0.022147, 0.153966, 0.028455, 0.03533, 0.0, 0.020421, 0.26342, 0.175068, 0.003393, 0.026402, 0.393135, 0.0, 0.0, 0.007716, 0.001161, 0.186909, 0.203077, 0.305026, 0.08402, 0.0371, 0.030906, 0.0, 0.060036, 0.624638, 0.0, 0.020841, 0.025119, 0.184153, 0.137958, 0.009377, 0.0, 0.005594, 0.062099, 0.149404, 0.0, 0.045819, 0.0339, 0.002693, 0.090199, 0.084438, 0.0, 0.227536, 0.179836, 0.0, 0.09364, 0.310067, 0.098588, 0.142352, 0.066611, 0.010845, 0.000455, 0.087193, 0.844169, 0.085764, 0.0029, 0.207578, 0.133594, 0.002522, 0.067086, 0.002372, 0.019251, 0.494216, 0.624162, 0.147177, 0.387841, 0.0, 0.00963, 0.012226, 0.0, 0.378049, 0.014449, 0.0, 0.012109, 0.096378, 0.637857, 0.011338, 0.150649, 0.040651, 0.0, 0.001713, 0.026373, 0.0, 0.061575, 0.008461, 0.00419, 0.046126, 0.005168, 0.00579, 0.008191, 0.023201, 0.0, 0.615299, 0.011685, 0.063947, 0.149248, 0.071455, 0.085484, 0.524882, 0.0, 0.008495, 0.782741, 0.036431, 0.142216, 0.007157, 0.307816, 0.933184, 0.152829, 0.003724, 0.14124, 0.00792, 0.019588, 0.224101...]"
}Usage:
pasteld [options] Start Pastel Daemon
Options:
-?
This help message
-alerts
Receive and display P2P network alerts (default: 1)
-alertnotify=<cmd>
Execute command when a relevant alert is received or we see a really
long fork (%s in cmd is replaced by message)
-blocknotify=<cmd>
Execute command when the best block changes (%s in cmd is replaced by
block hash)
-checkblocks=<n>
How many blocks to check at startup (default: 288, 0 = all)
-checklevel=<n>
How thorough the block verification of -checkblocks is (0-4, default: 3)
-conf=<file>
Specify configuration file (default: pastel.conf)
-daemon
Run in the background as a daemon and accept commands
-datadir=<dir>
Specify data directory
-exportdir=<dir>
Specify directory to be used when exporting data
-dbcache=<n>
Set database cache size in megabytes (4 to 16384, default: 450)
-loadblock=<file>
Imports blocks from external blk000??.dat file on startup
-maxorphantx=<n>
Keep at most <n> unconnectable transactions in memory (default: 100)
-par=<n>
Set the number of script verification threads (-16 to 16, 0 = auto, <0 =
leave that many cores free, default: 0)
-pid=<file>
Specify pid file (default: pasteld.pid)
-prune=<n>
Reduce storage requirements by pruning (deleting) old blocks. This mode
disables wallet support and is incompatible with -txindex. Warning:
Reverting this setting requires re-downloading the entire blockchain.
(default: 0 = disable pruning blocks, >550 = target size in MiB to use
for block files)
-reindex
Rebuild block chain index from current blk000??.dat files on startup
-sysperms
Create new files with system default permissions, instead of umask 077
(only effective with disabled wallet functionality)
-txindex
Maintain a full transaction index, used by the getrawtransaction rpc
call (default: 0)
Connection options:
-addnode=<ip>
Add a node to connect to and attempt to keep the connection open
-banscore=<n>
Threshold for disconnecting misbehaving peers (default: 100)
-bantime=<n>
Number of seconds to keep misbehaving peers from reconnecting (default:
86400)
-bind=<addr>
Bind to given address and always listen on it. Use [host]:port notation
for IPv6
-connect=<ip>
Connect only to the specified node(s)
-discover
Discover own IP addresses (default: 1 when listening and no -externalip
or -proxy)
-dns
Allow DNS lookups for -addnode, -seednode and -connect (default: 1)
-dnsseed
Query for peer addresses via DNS lookup, if low on addresses (default: 1
unless -connect)
-externalip=<ip>
Specify your own public address
-forcednsseed
Always query for peer addresses via DNS lookup (default: 0)
-listen
Accept connections from outside (default: 1 if no -proxy or -connect)
-listenonion
Automatically create Tor hidden service (default: 1)
-maxconnections=<n>
Maintain at most <n> connections to peers (default: 125)
-maxreceivebuffer=<n>
Maximum per-connection receive buffer, <n>*1000 bytes (default: 5000)
-maxsendbuffer=<n>
Maximum per-connection send buffer, <n>*1000 bytes (default: 1000)
-onion=<ip:port>
Use separate SOCKS5 proxy to reach peers via Tor hidden services
(default: -proxy)
-onlynet=<net>
Only connect to nodes in network <net> (ipv4, ipv6 or onion)
-permitbaremultisig
Relay non-P2SH multisig (default: 1)
-port=<port>
Listen for connections on <port> (default: 9933 or testnet: 19933)
-peerbloomfilters
Support filtering of blocks and transaction with Bloom filters (default:
1)
-proxy=<ip:port>
Connect through SOCKS5 proxy
-proxyrandomize
Randomize credentials for every proxy connection. This enables Tor
stream isolation (default: 1)
-seednode=<ip>
Connect to a node to retrieve peer addresses, and disconnect
-timeout=<n>
Specify connection timeout in milliseconds (minimum: 1, default: 5000)
-torcontrol=<ip>:<port>
Tor control port to use if onion listening enabled (default:
127.0.0.1:9051)
-torpassword=<pass>
Tor control port password (default: empty)
-whitebind=<addr>
Bind to given address and whitelist peers connecting to it. Use
[host]:port notation for IPv6
-whitelist=<netmask>
Whitelist peers connecting from the given netmask or IP address. Can be
specified multiple times. Whitelisted peers cannot be DoS banned and
their transactions are always relayed, even if they are already in the
mempool, useful e.g. for a gateway
Wallet options:
-disablewallet
Do not load the wallet and disable wallet RPC calls
-keypool=<n>
Set key pool size to <n> (default: 100)
-paytxfee=<amt>
Fee (in PSL/kB) to add to transactions you send (default: 0.00)
-rescan
Rescan the block chain for missing wallet transactions on startup
-salvagewallet
Attempt to recover private keys from a corrupt wallet.dat on startup
-sendfreetransactions
Send transactions as zero-fee transactions if possible (default: 0)
-spendzeroconfchange
Spend unconfirmed change when sending transactions (default: 1)
-txconfirmtarget=<n>
If paytxfee is not set, include enough fee so transactions begin
confirmation on average within n blocks (default: 2)
-txexpirydelta
Set the number of blocks after which a transaction that has not been
mined will become invalid (min: 4, default: 20)
-maxtxfee=<amt>
Maximum total fees (in PSL) to use in a single wallet transaction;
setting this too low may abort large transactions (default: 0.10)
-upgradewallet
Upgrade wallet to latest format on startup
-wallet=<file>
Specify wallet file (within data directory) (default: wallet.dat)
-walletbroadcast
Make the wallet broadcast transactions (default: 1)
-walletnotify=<cmd>
Execute command when a wallet transaction changes (%s in cmd is replaced
by TxID)
-zapwallettxes=<mode>
Delete all wallet transactions and only recover those parts of the
blockchain through -rescan on startup (1 = keep tx meta data e.g.
account owner and payment request information, 2 = drop tx meta data)
ZeroMQ notification options:
-zmqpubhashblock=<address>
Enable publish hash block in <address>
-zmqpubhashtx=<address>
Enable publish hash transaction in <address>
-zmqpubrawblock=<address>
Enable publish raw block in <address>
-zmqpubrawtx=<address>
Enable publish raw transaction in <address>
Debugging/Testing options:
-debug=<category>
Output debugging information (default: 0, supplying <category> is
optional). If <category> is not supplied or if <category> = 1, output
all debugging information. <category> can be: addrman, alert, bench,
coindb, compress, db, estimatefee, http, libevent, lock, mempool, net,
partitioncheck, pow, proxy, prune, rand, reindex, rpc, selectcoins, tor,
zmq, zrpc, zrpcunsafe (implies zrpc).
-experimentalfeatures
Enable use of experimental features
-help-debug
Show all debugging options (usage: --help -help-debug)
-logips
Include IP addresses in debug output (default: 0)
-logtimestamps
Prepend debug output with timestamp (default: 1)
-minrelaytxfee=<amt>
Fees (in PSL/kB) smaller than this are considered zero fee for relaying
(default: 0.001)
-printtoconsole
Send trace/debug info to console instead of debug.log file
-shrinkdebugfile
Shrink debug.log file on client startup (default: 1 when no -debug)
-testnet
Use the test network
Node relay options:
-datacarrier
Relay and mine data carrier transactions (default: 1)
-datacarriersize
Maximum size of data in data carrier transactions we relay and mine
(default: 80)
Block creation options:
-blockminsize=<n>
Set minimum block size in bytes (default: 0)
-blockmaxsize=<n>
Set maximum block size in bytes (default: 2000000)
-blockprioritysize=<n>
Set maximum size of high-priority/low-fee transactions in bytes
(default: 1000000)
RPC server options:
-server
Accept command line and JSON-RPC commands
-rest
Accept public REST requests (default: 0)
-rpcbind=<addr>
Bind to given address to listen for JSON-RPC connections. Use
[host]:port notation for IPv6. This option can be specified multiple
times (default: bind to all interfaces)
-rpcuser=<user>
Username for JSON-RPC connections
-rpcpassword=<pw>
Password for JSON-RPC connections
-rpcport=<port>
Listen for JSON-RPC connections on <port> (default: 9932 or testnet:
19932)
-rpcallowip=<ip>
Allow JSON-RPC connections from specified source. Valid for <ip> are a
single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0)
or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified
multiple times
-rpcthreads=<n>
Set the number of threads to service RPC calls (default: 4)
Metrics Options (only if -daemon and -printtoconsole are not set):
-showmetrics
Show metrics on stdout (default: 1 if running in a console, 0 otherwise)
-metricsui
Set to 1 for a persistent metrics screen, 0 for sequential metrics
output (default: 1 if running in a console, 0 otherwise)
-metricsrefreshtime
Number of seconds between metrics refreshes (default: 1 if running in a
console, 600 otherwise)

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
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.
This ticket is used to register personal or SuperNode Pastel ID.
This ticket is used to associate user name with the .
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 transaction (txid). If any of the optional fields (copies, royalty, green) are missing - they are retrieved from the pointed by "nft_collection_txid".
This ticket activates NFT previously registered with .
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 should be used to register NFT as part of the NFT collection. "nft_collection_txid" field in the should point to the transaction id (txid) of this . "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.
This ticket activates the NFT Collection previously registered with .
This ticket is used to set royalty payments for the specific NFT.
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
This ticket activates the Action (Sense or Cascade) previously registered with . Same ticket structure is used to activate different action types: Sense or Cascade.
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.
Same ticket structure is used for both NFT and Action (Sense and Cascade) tickets.
Same ticket structure is used for both NFT and Action (Sense and Cascade) tickets.
NFT Registration and Activation
Offers, Accepts and Transfers
NFT Digital Fingerprints via Sense
NFT Storage Symbols via Cascade
{
"ticket": {
"type": "pastelid", // Pastel ID Registration ticket type
"version": int, // ticket version (0 or 1)
"pastelID": string, // registered Pastel ID (base58-encoded public key)
"pq_key": bytes, // Legendre Post-Quantum LegRoast public key, base58-encoded
"address": string, // funding address associated with this Pastel ID
"timeStamp": string, // Pastel ID registration timestamp
"signature": bytes, // base64-encoded signature of the ticket created using the Pastel ID
"id_type": string // Pastel ID type: personal or SuperNode
}
}{
"ticket": {
"type": "username-change", // UserNameChange ticket type
"version": int, // ticket version (1)
"pastelID": string, // Pastel ID the user is associated with
"username": string, // User name
"fee": int64, // User name change fee in PSL
"signature": bytes // base64-encoded signature of the ticket created using the registered Pastel ID
}
}{
"ticket": {
"type": "nft-reg", // NFT Registration ticket type
"version": int, // ticket version (1 or 2)
"nft_ticket": bytes, // base64-encoded NFT ticket data
"signatures": object, // base64-encoded signatures and Pastel IDs of the signers
"key": string, // unique key (32-bytes, base32-encoded)
"label": string, // label to use for searching the ticket
"creator_height": uint, // block height at which the ticket was created
"total_copies": int, // number of NFT copies that can be created
"royalty": float, // royalty fee, how much creator should get on all future resales
"royalty_address": string, // royalty payee t-address if royalty fee is defined or empty string
"green": bool, // true if there is a Green NFT payment, false - otherwise
"storage_fee": int64 // ticket storage fee in PSL
}
}{
"principal": { "<principal Pastel ID>": "<principal signature>" },
"mn1": { "<MN1 Pastel ID>": "<mn1 signature>" },
"mn2": { "<MN2 Pastel ID>": "<mn2 signature>" },
"mn3": { "<MN3 Pastel ID>": "<mn3 signature>" }
}{
"nft_ticket_version": int,// ticket version (1 or 2)
"author": string, // Pastel ID of the NFT creator
"blocknum": uint, // block height at which the ticket was created
"block_hash": bytes // hash of the top block when the ticket was created
"copies": int, // number of NFT copies that can be created, optional in v2
"royalty": float, // royalty fee, how much creator should get on all future resales, optional in v2
"green": bool, // true if there is a Green NFT payment, false - otherwise, optional in v2
"nft_collection_txid": bytes, // transaction id of the NFT Collection this NFT belongs to, v2 only, optional, can be empty
"app_ticket": bytes // ascii85-encoded application ticket, parsed by the cnode only for search capability
}{
"creator_name": string,
"creator_website": string,
"creator_written_statement": string,
"nft_title": string,
"nft_type": string,
"nft_series_name": string,
"nft_creation_video_youtube_url": string,
"nft_keyword_set": string,
"total_copies": int, // number of copies, same as in NFT Ticket
"preview_hash": bytes, // hash of the preview thumbnail !!!!SHA3-256!!!!
"thumbnail1_hash": bytes, // hash of the thumbnail !!!!SHA3-256!!!!
"thumbnail2_hash": bytes, // hash of the thumbnail !!!!SHA3-256!!!!
"data_hash": bytes, // hash of the image (or any other asset) that this ticket represents !!!!SHA3-256!!!!
"original_file_size_in_bytes": int, // size of original file in bytes
"file_type": string, // file type e.g image/jpeg
"make_publicly_accessible": bool, // whether the owner wanted to make it public
// dupe detection and fingerprints files IDs
"dd_and_fingerprints_ic": int, // initial value of the counter for dd_and_fp files
"dd_and_fingerprints_max": int, // maximum number of dd_and_fp files (current default is 50)
"dd_and_fingerprints_ids": [list of strings], // list of IDs of dd_and_fingerprints files in Kademlia
// raptorq ids files IDs
"rq_ic": int, // initial value of the counter for rq_ids files
"rq_max": int, // maximum number of rq_ids files (current default is 50)
"rq_ids": [list of strings], // list of IDs of of rq-ids files in Kademlia
"rq_oti": [array of 12 bytes], // raptorq CommonOTI and SchemeSpecificOTI
}{
"ticket": {
"type": "nft-act", // NFT Activation ticket type
"version": int, // ticket version (0)
"pastelID": string, // Pastel ID of the creator
"reg_txid": string, // transaction id (txid) of the NFT Registration ticket
"creator_height": int, // block height at which the ticket was created
"storage_fee": int64, // ticket storage fee in PSL, should match the fee from NFT Registration Ticket
"signature": bytes // base64-encoded signature of the ticket created using the Creator's Pastel ID
}
}{
"ticket": {
"type": "nft-collection-reg", // NFT Collection Registration ticket type
"version": int, // ticket version (1)
"nft_collection_ticket": bytes, // base64-encoded NFT Collection ticket data
"signatures": object, // base64-encoded signatures and Pastel IDs of the signers
"permitted_users": [ // list of Pastel IDs that are permitted to register an NFT as part of this collection
"pastelID1",
"pastelID2",
...
],
"key": string, // unique key (32-bytes, base32-encoded)
"label": string, // label to use for searching the ticket
"creator_height": uint, // block height at which the ticket was created
"closing_height": uint, // a "closing" block height after which no new NFTs would be allowed to be added to this collection
"nft_max_count": uint, // number of NFT copies that can be created
"nft_copy_count": uint, // default number of copies for all NFTs in a collection
"royalty": float, // royalty fee, how much creator should get on all future resales (common for all NFTs in a collection)
"royalty_address": string, // royalty payee t-address if royalty fee is defined or empty string
"green": bool, // true if there is a Green NFT payment, false - otherwise (common for all NFTs in a collection)
"storage_fee": int64 // ticket storage fee in PSL
}
}{
"principal": { "<principal Pastel ID>": "<principal signature>" },
"mn1": { "<MN1 Pastel ID>": "<mn1 signature>" },
"mn2": { "<MN2 Pastel ID>": "<mn2 signature>" },
"mn3": { "<MN3 Pastel ID>": "<mn3 signature>" }
}{
"nft_collection_ticket_version": int, // ticket version (1)
"nft_collection_name": string, // The name of the NFT collection
"creator": string, // Pastel ID of the NFT collection's creator
"permitted_users": [ // list of Pastel IDs that are permitted to register an NFT as part of this collection
"pastelID1",
"pastelID2",
...
]
"blocknum": uint, // block number when the ticket was created - this is to map the ticket to the MNs that should process it
"block_hash": string, // hash of the top block when the ticket was created - this is to map the ticket to the MNs that should process it
"closing_height": uint, // a "closing" block height after which no new NFTs would be allowed to be added to this collection
"nft_max_count": uint, // max number of NFTs allowed in this collection
"nft_copy_count": uint, // default number of copies for all NFTs in a collection
"royalty": float, // royalty fee, how much creators should get on all future resales (common for all NFTs in a collection)
"green": boolean, // true if there is a Green NFT payment, false - otherwise (common for all NFTs in a collection)
"app_ticket": bytes // ascii85-encoded application ticket, parsed by the cnode only for search capability
}{
"ticket": {
"type": "nft-collection-act", // NFT Collection Activation ticket type
"version": int, // ticket version (1)
"pastelID": string, // Pastel ID of the NFT Collection's creator
"reg_txid": string, // transaction id (txid) of the NFT Collection Registration ticket
"creator_height": uint, // block height at which the ticket was created
"storage_fee": int, // storage fee in PSL
"signature": bytes // base64-encoded signature of the ticket created using the Creator's Pastel ID
}
}{
"ticket": {
"type": "nft-royalty", // NFT Royalty ticket type
"version": int, // ticket version (1)
"pastelID": string, // Pastel ID of the previous royalty recipient
"new_pastelID": string, // Pastel ID of the new royalty recipient
"nft_txid": string, // transaction id (txid) of the NFT for royalty payments
"signature": bytes // base64-encoded signature of the ticket created using the previous Pastel ID
}
}{
"ticket": {
"type": "action-reg", // Action Registration ticket type
"action_ticket": bytes, // base64-encoded external action ticket
"action_type": string, // action type (sense, cascade)
"version": int, // version of the blockchain representation of ticket (1)
"signatures": object, // signatures, see below
"key": string, // unique key (32-bytes, base32-encoded)
"label": string, // label to use for searching the ticket
"called_at": uint, // block at which action was requested
"storage_fee": int64 // storage fee in PSL
}
}{
"action_ticket_version": int // ticket version (1)
"action_type": string, // action type (sense, cascade)
"caller": string, // Pastel ID of the action caller
"blocknum": uint, // block number when the ticket was created
"block_hash": bytes, // hash of the top block when the ticket was created
"api_ticket": bytes // ascii85-encoded application ticket
// actual structure of app_ticket is different for different API and is not parsed by pasteld !!!!
}{
"data_hash": bytes, // hash of duplication data & fingerprints file
"dd_and_fingerprints_ic": int, // initial value of the counter for dd_and_fp files
"dd_and_fingerprints_max": int, // maximum number of dd_and_fp files (current default is 50)
"dd_and_fingerprints_ids": [list of strings], // list of IDs of dd_and_fingerprints files in Kademlia
}{
"data_hash": bytes, // hash of the file
"filename": string // name of the file
"rq_ic": int, // initial value of the counter for rq_ids files
"rq_max": int, // maximum number of rq_id files (current default is 50)
"rq_ids": [list of strings], // list of IDs of of rq-ids files in Kademlia
"rq_oti": [array of 12 bytes], // raptorq CommonOTI and SchemeSpecificOTI
"original_file_size_in_bytes": int, // size of original file in bytes
"file_type": string, // file type e.g image/jpeg
"make_publicly_accessible": bool, // whether the owner wanted to make it public
}{
"principal": { "<principal Pastel ID>": "<principal signature>" },
"mn1": { "<MN1 Pastel ID>": "<mn1 signature>" },
"mn2": { "<MN2 Pastel ID>": "<mn2 signature>" },
"mn3": { "<MN3 Pastel ID>": "<mn3 signature>" }
}{
"ticket": {
"type": "action-act", // Action Activation ticket type
"version": int, // ticket version (1)
"pastelID": string, // Pastel ID of the Action caller
"reg_txid": string, // txid of the Action Registration ticket
"called_at": uint, // block at which Action was called (Action Registration ticket was created)
"storage_fee": int64, // ticket storage fee in PSL, should match the storage fee from the Action Registration Ticket
"signature": bytes // base64-encoded signature of the ticket created using the Action Caller's Pastel ID
}
}{
"ticket": {
"type": "offer", // Offer ticket type
"version": int, // ticket version (0)
"pastelID": string, // Pastel ID of the item owner, either an original creator or a previous owner
"item_txid": string, // either item activation or transfer ticket txid
"copy_number": ushort, // item copy number
"asked_price": uint, // item asked price in PSL
"valid_after": uint, // block height after which the item offer will be active
"valid_before": uint, // block height after which the item offer will expire
"locked_recipient": string, // Pastel ID of intended recipient of the item - new owner, "not defined" if empty
"signature": bytes // base64-encoded signature of the ticket created using the item owner's Pastel ID
},
}{
"ticket": {
"type": "accept", // Accept ticket type
"version": int, // ticket version (0)
"pastelID": string, // Pastel ID of the new owner of the item
// should be the same as "locked_recipient" if defined in Offer ticket
"offer_txid": string, // transaction id (txid) of the Offer ticket
"price": uint, // accepted price of the item in PSL
"signature": bytes // base64-encoded signature of the ticket created using Pastel ID of the new owner
}
}{
"ticket": {
"type": "transfer", // Transfer ticket type
"version": int, // ticket version (0)
"pastelID": string, // Pastel ID of the new owner of the item
"offer_txid": string, // transaction id (txid) of the Offer ticket
"accept_txid": string, // transaction id (txid) of the Accept ticket
"item_txid": string, // transaction id (txid) of either:
// 1) NFT or Action Activation ticket
// 2) Transfer ticket
"registration_txid": string, // transaction id (txid) of the item's registration ticket
"copy_serial_nr": string, // item copy number (from the Offer ticket)
"signature": bytes // base64-encoded signature of the ticket created using Pastel ID of the new owner
}
}


Welcome to the Supernode Setup Guide! This document is designed to help you set up a Supernode on the Pastel Network, regardless of your technical expertise. Simply follow these step-by-step instructions.
Supernodes on the Pastel Network can be operated in one of two configurations:
Single Node (HOT Mode): The wallet containing a collateral transaction of 5M PSL on Mainnet (1M LSP on Testnet) is hosted on the same server as the Supernode.
Dual Node (HOT/COLD Mode): The wallet with the collateral transaction is stored on a separate host (cold wallet) from the Supernode.
While the HOT/COLD mode is considered more secure, it is vital to maintain the security of your Supernode host irrespective of the selected setup.
Prerequisite: Supernode must be installed on a Linux OS.
Replace placeholders with appropriate values!
pastelUp:NOTE: Execute all commands on the remote host.
For Mainnet:
For Testnet:
This installs the following applications:
pasteld
pastel-cli
rq-server
This will start pasteld as simple node. You can check status if sync by:
The responce will look like this:
Chek Pastel Explorer for the current top block, here:
Mainnet = ``
Testnet - ``
Wait until your node reaches the top.
This step is optional, when you run
pastelup-linux-amd64 initit will offer to create an address and will wait until you send collaterral to it.
This will return new address. You should send exact amount of colateral amount in a single transaction:
Mainnet - 5'000'000 PSL
Testnet - 1'000'000 LSP
Remember txid and vout of the output from transaction that sends the collateral amount.
You can also find out txid and vout by running on your remote host:
Note: You only need to initialize once upon the first installation of Supernode. Skip this step if your Supernode is already initialized.
SN-name is the node alias in masternode.conf.
--activate is optional to immediately active your node. Otherwise, you can activate it at any point with:
pastel-cli masternode start-alias <SN-name>
Initialization of your Supernode will:
Ask for a passphrase
Create and register a new Supernode PastelID
Ask for collateral transaction txid and vout index
If no collateral was sent yet, it will offer to create new address and will wait until collateral is sent to it and the transaction is confirmed
Alternatively, you can initialize your Supernode if you know the collateral transaction txid and vout index with the following command:
./pastelup-linux-amd64 init supernode --new --name=<SN-name> --txid=<txid> --ind=<vout index> --activate
After initialization, check the Supernode status:
Verify that this returns masternode successfully started.
NOTE: You do not need to start Supernode right after initialization. Start only if the Supernode was previously stopped.
The above command will start the following services:
pasteld
rq-server
dd-server
NOTE: Execute all commands on the remote host.
masternode status should return similar to the following:
pastelid list should return similar to the following:
NOTE: Be sure to securely store your PastelID!
In order to continue and register your PastelID on the blockchain, you will need some available funds in the Supernode wallet. We recommend at least 2000 PSL on Mainnet (1000 LSP on Testnet).
Now, you are ready to register your PastelID:
Replace the placeholders with the appropriate values!
Check Supernode status:
masternode status should return similar to the following:
Congratulations, your SuperNode is successfully running! You can now exit your SSH session.
A 5 million PSL stake is required to operate a SuperNode. In order to avoid anything happening to that 5 million PSL, the recommended strategy is to keep these funds on the node that is turned off and in a more secure location than on a publicly accessible server. Thus, we use two SuperNode installations:
One cold node where the 5 million PSL stays, that is only on for a brief activation window and then disconnected
One hot node that actually operates on the network, but doesn't have 5 million PSL in its wallet
In order for this to occur, the cold node must vouch for the hot node, indicating that the owner of the hot node has properly staked 5 million PSL.
Prerequisites
Two nodes (computers)
HOT node - this can be cloud instance on some cloud provider. This host MUST have - Ubuntu 22.04 installed
COLD node - more secure located computer - local laptop or desktop is recommended, but still can be cloud instance that will be shutdown after SuperNode on HOT node set, initialized and started. This host can be Windows, MacOS or Ubuntu 22.04
As with node installation in the , pastelup is the best method for SuperNode installation.
NOTE: All commands should be executed on the COLD node!
pastel upFor MacOS
For Linux
For Windows (from PowerShell)
This method will also work if you already had node installed as in the quick start guide. A prompt will ask if you'd like to continue installation to the same directory, select yes and wait for installation to complete.
Windows:
MacOS:
Linux:
NOTE: All commands should be executed on the COLD node!
Replace the placeholders with the appropriate values!
Replace the placeholders with the appropriate values!
During initialization, you will be prompted to either search for an existing collateral transaction or create a new address and send PLS (mainnet) or LSP (testnet) to it. You will also need to provide a passphrase for the new PastelID.
WRITE DOWN PASSPHRASE YOU ENTERD HERE! (<PASSPHRASE>)
You won't be able to recover it later!!!
NOTE: All commands should be executed on the COLD node!
Replace the placeholders with the appropriate values!
MacOS:
Linux:
Windows:
NOTE: All commands should be executed on the HOT node!
Replace the placeholders with the appropriate values!
Status should be something like that:
And PastelID list:
Remember, or better write down your SuperNodes PastelID
Next you will have to register PastelID in the blockchain. That requires some available funds (slightly more then 1000PSL - we recommend at least 2000PSL) in the SuperNode wallet.
Check balance:
If that returns 0 or anything less then 200PSL, you will need to generate new address and send some coins to it from your other walet.
Remember, or better write down your address (<ADDRESS>)
Send some coins to that address from another host with balance
Wait until coins get available, checking periodically with getbalance command.
After funds get avaialiable, run the following command
Replace the placeholders with the appropriate values!
Check status again:
This time it should be something like that:
You can exit your SSH session to HOT node after that. You SuperNodes is running!
NOTE: All commands should be executed on the COLD node!
To simplify management of SuperNode it is recommended to set it up as systems service. Follow the steps to do that
Before setting up SuperNode's applications as systemd services, you first need to stop them
TIP: Instead of this command, you can add flag
--startto the previous one
dd-serverhermes
supernode
Create a masternode.conf file and add configuration against the provided node alias --name
Start pasteld as Supernode
Active pasteld as Supdernode
Start rq-server, dd-server, hermes, and supernode services
hermessupernode
5,000,000 PSL that will be used as collateral in some outside wallet
ssh <SSH_USER_OF_HOT_NODE>@<IP_ADDRESS_OF_HOT_NODE> -i <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>wget https://download.pastel.network/#latest-release/pastelup/pastelup-linux-amd64./pastelup-linux-amd64 install supernode -n=mainnet./pastelup-linux-amd64 install supernode -n=testnet./pastelup-linux-amd64 start node./pastel/paslte-cli getinfo{
"version": 2010001,
"protocolversion": 170010,
"walletversion": 60000,
"balance": 0.00000,
"blocks": 1354,
"timeoffset": 0,
"connections": 7,
"proxy": "",
"difficulty": 1,
"chain": "testnet",
"keypoololdest": 1705034659,
"keypoolsize": 101,
"paytxfee": 0.00000,
"relayfee": 0.00100,
"errors": ""
}./pastel/paslte-cli getnewaddress./pastel/paslte-cli masternode outputs ./pastelup-linux-amd64 init supernode --new --name=<SN-name> --activatepastel-cli masternode status./pastelup-linux-amd64 start supernode./pastel/pastel-cli masternode status
./pastel/pastel-cli pastelid list{
"outpoint": "0000000000000000000000000000000000000000000000000000000000000000-0",
"service": "<IP_ADDRESS_OF_HOT_NODE>:9933",
"status": "Not capable masternode: Masternode not in masternode list"
}[
{
"PastelID": "<YOUR_SN_PASTELID>",
"legRoastKey": "..."
}
]./pastel/pastel-cli getbalance./pastel/pastel-cli tickets register mnid <YOUR_SN_PASTELID> <PASSPHRASE> <ADDRESS>./pastel/pastel-cli masternode status{
"outpoint": "...",
"service": "<IP_ADDRESS_OF_HOT_NODE>:9933",
"payee": "...",
"extAddress": "<IP_ADDRESS_OF_HOT_NODE>:4444",
"extP2P": "<IP_ADDRESS_OF_HOT_NODE>:4445",
"extKey": "<YOUR_SN_PASTELID>",
"extCfg": "",
"alias": "<SN_name>",
"status": "Masternode successfully started"
}wget https://download.pastel.network/#latest-release/pastelup/pastelup-darwin-amd64wget https://download.pastel.network/#latest-release/pastelup/pastelup-linux-amd64Invoke-WebRequest -Uri https://download.pastel.network/latest-release/pastelup/pastelup-win-amd64.exe -OutFile pastelup-win-amd64.exe./pastelup-darwin-amd64 install node -n testnet./pastelup-linux-amd64 install node -n testnetpastelup-win-amd64 install node -n testnet./pastelup-darwin-amd64 start node./pastelup-linux-amd64 start nodepastelup-win-amd64 start node~/Applications/PastelWallet/pastel-cli mnsync status%userprofile%\AppData\Roaming\PastelWallet\pastel-cli mnsync status~/pastel/pastel-cli mnsync status./pastelup-darwin-amd64 install supernode remote -n testnet--ssh-ip <IP_ADDRESS_OF_HOT_NODE> --ssh-user <SSH_USER_OF_HOT_NODE> --ssh-key <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>./pastelup-darwin-amd64 init supernode coldhot --new --name <SN_name> --ssh-ip <IP_ADDRESS_OF_HOT_NODE> --ssh-user <SSH_USER_OF_HOT_NODE> --ssh-key <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>~/Applications/PastelWallet/pastel-cli masternode start-alias <SN_name>./pastel-cli masternode start-alias <SN_name>%userprofile%\AppData\Roaming\PastelWallet\pastel-cli masternode start-alias <SN_name>ssh <SSH_USER_OF_HOT_NODE>@<IP_ADDRESS_OF_HOT_NODE> -i <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>./pastel/pastel-cli masternode status
./pastel/pastel-cli pastelid list{
"outpoint": "0000000000000000000000000000000000000000000000000000000000000000-0",
"service": "<IP_ADDRESS_OF_HOT_NODE>:9933",
"status": "Not capable masternode: Masternode not in masternode list"
}[
{
"PastelID": "<YOUR_SN_PASTELID>",
"legRoastKey": "..."
}
]./pastel/pastel-cli getbalance./pastel/pastel-cli getnewaddress./pastel/pastel-cli tickets register mnid <YOUR_SN_PASTELID> <PASSPHRASE> <ADDRESS>./pastel/pastel-cli masternode status{
"outpoint": "...",
"service": "<IP_ADDRESS_OF_HOT_NODE>:9933",
"payee": "...",
"extAddress": "<IP_ADDRESS_OF_HOT_NODE>:4444",
"extP2P": "<IP_ADDRESS_OF_HOT_NODE>:4445",
"extKey": "<YOUR_SN_PASTELID>",
"extCfg": "",
"alias": "<SN_name>",
"status": "Masternode successfully started"
}./pastelup-darwin-amd64 stop supernode remote --ssh-ip <IP_ADDRESS_OF_HOT_NODE> --ssh-user <SSH_USER_OF_HOT_NODE> --ssh-key <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>./pastelup-darwin-amd64 update install-service remote --solution supernode --autostart --ssh-ip <IP_ADDRESS_OF_HOT_NODE> --ssh-user <SSH_USER_OF_HOT_NODE> --ssh-key <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>./pastelup-darwin-amd64 start supernode remote --ssh-ip <IP_ADDRESS_OF_HOT_NODE> --ssh-user <SSH_USER_OF_HOT_NODE> --ssh-key <PATH_TO_HOT_NODE_SSH_PRIVATE_KEY_FILE>
















