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...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Radiant is a decentralized P2P Digital Asset System and PoW UTXO Network for everyone
If you have an idea for Radiant, feel free to share it and get involved.
This Wiki is maintained by active community members who continuely show up to be reliable, timely and dedicated to the growth and health of the Radiant Blockchain and ecosystem.
The total supply of Radiant is predetermined for 21 billion RXD, with a 50,000 block emission and 2-year halving time.
Instant transactions with 0-confs
A safe block size to handle high throughput to start, designed fundamentally to achieve 10+ GB and beyond.
Radiant is a layer 1 blockchain with no secondary layers ever needed.
Unique proof-of-work consensus designed to embrace GPU/FPGA/ASICs while being more efficient than Bitcoin.
Diversified mining pools and solo operators contributing to decentralization.
Protocol designed to handle 4,000 tx/sec with default 256 MB block sizes. Miners can optimize in the future to scale linearly.
Each Radiant has 8 decimal places, and the smallest indivisible unit is called a photon. 100 million photons per RXD coin.
Fairly mined with no developer allocation, just technology for you to build with and grow.
When you create a hybrid account + UTXO Layer 1 blockchain, you get magic. Imagine no limitations on growth. Imagine fees that are fractions of a penny. Imagine a blockchain that is ready to build on at launch and not always waiting on the next update, pivot, or fix. Imagine Radiant.
Make your dreams come to life – auctions, games, tokens, apps, NFTs – anything you can think of with ultra-flexible Turing Complete smart contracts. Radiant allows creatives of all kinds to have real ownership of their digital assets and use the peer-to-peer network to monetize and exchange their creations.
Proof-of-work is the only consensus system for maximum security and efficiency. Embracing full decentralization so that no miner can stake to centralize the network. Fairly launched and community mined from the beginning. The FIPS SHA512/256 Standard is up to 50% more efficient than SHA256 on 64 bit architectures.
The Radiant Node, associated modules, and libraries were released upon launch. All source code is available as open source (MIT licensed) and comes with no warranties or guarantees of any kind. It is free to use or copy as users and developers wish.
The fuel for the network is the Radiant unit (RXD). A small amount of RXD is used to pay transaction fees to miners for processing transfers and for the execution of smart contracts.
Proof-of-Work uses energy intensive processes to secure the network but is highly efficient. This is because POW’s energy expenditure needs to be weighed against the massive energy usage of the legacy systems that POW replaces. When POW’s energy consumption is examined in the context of current wasteful legacy systems, POW is highly energy efficient and green.
The induction proof system makes it possible to efficiently compose outputs in any manner, without compromising the inherent parallelism and scalability characteristics of the UTXO based architecture.
With the novel induction proof technique, it is now possible to create globally unique identifiers and therefore implement accounts in the UTXO based architecture. The best of both worlds in emulating the account models while also providing the coin (UTXO) model that offers massive scale and parallelism.
French version of the Radiant whitepaper
The Radiant Developers
11 août 2022
radiantblockchain.org
Résumé : Le réseau Radiant est un système d'actifs numériques pair-à-pair qui permet l'échange direct de valeur sans passer par une partie centrale. Le protocole Bitcoin original [1] fournit ce qui est nécessaire pour créer un système de trésorerie électronique pair-à-pair, mais il ne possède pas la capacité de vérifier les historiques de transactions et, par conséquent, ne peut pas être utilisé pour valider des actifs numériques. Les signatures numériques et les contraintes de sortie fournissent une partie de la solution, mais les principaux avantages sont perdus si une tierce partie de confiance est encore nécessaire pour valider les actifs numériques. De manière similaire à Bitcoin, le réseau Radiant ne nécessite qu'une structure minimale et horodate les transactions dans une chaîne de preuve de travail basée sur le hachage. Nous introduisons deux techniques pour valider les actifs numériques : des références uniques et un système de preuve d'induction général à la fois opérant dans un temps et un espace constants O(1). Il est possible de composer les sorties de n'importe quelle manière, sans compromettre les caractéristiques intrinsèques de parallélisme et de performance d'une architecture basée sur les sorties de transaction non dépensées (UTXO). Par conséquent, les utilisateurs peuvent quitter et rejoindre le réseau Radiant à leur guise et être assurés de l'intégrité et de l'authenticité de leurs actifs numériques.
Le commerce avec les blockchains, ou la technologie de registre numérique (DLT), repose souvent sur des émetteurs et des gardiens agissants en tant que parties de confiance pour authentifier les actifs numériques. Bien que ces systèmes fonctionnent assez bien pour les transactions de type paiement électronique, ils souffrent toujours des faiblesses inhérentes du modèle de confiance pour les utilisations avancées. Les blockchains basées sur la machine virtuelle Ethereum (EVM) [2] sont très flexibles pour tous les types de programmes, mais les frais élevés les rendent impraticables pour les applications de micropaiement.
Ce dont nous avons besoin, c'est un système de paiement électronique pouvant être utilisé pour un système de gestion d'actifs numériques avec des frais réduits, une haute performance et des capacités de programmation avancées. Dans cet article, nous proposons une solution au problème de l'expansion et de la contraction des blockchains en utilisant deux techniques novatrices qui fournissent des références uniques et un système général de preuve par induction, ce qui permet des programmes de Turing complet [3] à travers les frontières de transaction. Le système proposé est décentralisé, utilise un mécanisme de consensus de preuve de travail comme Bitcoin, mais avec des niveaux de débit considérablement plus élevés, tout en offrant la même flexibilité que les blockchains basées sur EVM, avec des frais très bas.
Similaire à Bitcoin, nous définissons une pièce électronique comme une chaîne de signatures numériques. Ce qui distingue les transactions dans Radiant, c'est que chaque propriétaire transfère la pièce au suivant en signant numériquement un hachage de la transaction précédente, en plus des paramètres d'entrée requis pour déverrouiller la pièce. Une transaction crée également de nouvelles contraintes de verrouillage de sortie, qui peuvent inclure la clé publique du prochain propriétaire, parmi toutes les autres règles définies par l'utilisateur.
Diagram 1. Transactions Radiant.
Pour vérifier qu'une double dépense ne s'est pas produite, nous utilisons un serveur d'horodatage distribué, en utilisant un système de preuve de travail basé sur le hachage pour organiser l'historique canonique afin de déterminer quelle transaction est arrivée en premier. Les transactions sont organisées en blocs. Par convention, la première transaction, appelée "transaction de coinbase", dans un bloc est une transaction spéciale qui démarre une nouvelle pièce appartenant au créateur du bloc. Les blocs sont chaînés ensemble et organisent les transactions en un arbre de Merkle [4]. Toutes les transactions, à l'exception de la première, doivent référencer une transaction précédente formant un graphe acyclique dirigé (DAG) où toutes les pièces se connectent finalement à au moins l'une des transactions spéciales au début d'un bloc.
Diagram 2. Structure des blocs ; les transactions sont organisées dans un arbre de Merkle.
Le problème avec cette conception, dans le contexte des actifs numériques, est qu'il n'y a qu'un seul type de pièce ou d'actif numérique, et pas de concept de pièces définies par l'utilisateur (ou de types d'actifs numériques). La conception fonctionne assez bien pour les transactions électroniques de type paiement dans l'unité de compte native, mais elle ne se prête pas immédiatement à être utilisée pour d'autres types de pièces ou d'actifs numériques. Une solution courante consiste à introduire un service tel qu'un indexeur de transaction qui surveille les transactions pour détecter des séquences de données spéciales signalant la création d'un actif numérique. Le problème avec cette solution est qu'elle dépend de l'entreprise qui exécute le service, l'authenticité de l'actif numérique devant être de confiance, tout comme tout autre service sur le Web.
Nous avons besoin d'un moyen pour que les utilisateurs puissent indiquer la création de types de pièces personnalisées, mais sans dépendre d'un service de confiance pour être utilisé pour la présentation de données.
Nous définissons une pièce électronique personnalisée, ou un actif numérique, comme une chaîne de signatures électroniques. Un actif numérique est un type de pièce défini par l'utilisateur à l'aide d'un marqueur de transaction spécial, appelé une "transaction d'actif de base", pour créer ou émettre un actif numérique. De manière similaire aux transactions Coinbase, qui injectent de nouvelles pièces dans le système, la transaction d'actif de base colore ou étiquette la pièce électronique avec un identifiant unique de 36 octets pour sa durée de vie. La pièce électronique personnalisée est superposée au type de pièce de base et fonctionne de manière similaire. La transaction d'actif de base peut apparaître n'importe où dans le bloc et peut imposer toutes les règles et contraintes personnalisées décidées à l'avance.
Diagram 3. Transactions représentant des types de pièces définis par l'utilisateur — ou des actifs numériques.
Pour réaliser cela, nous devons créer un identifiant unique stable et un mécanisme de transaction pour suivre l'authenticité du type de pièce (actif numérique). Les utilisateurs du système doivent avoir la preuve que les types de pièces personnalisées ne sont pas des contrefaçons et représentent avec précision les actifs numériques.
Diagram 4. qui montre que les types de pièces personnalisées définies par l'utilisateur sont créés à partir d'une transaction spéciale de "mint". Un identifiant unique est utilisé pour classer le type de pièce.
Pour mettre en place un identificateur unique pour un type de coin, nous utilisons une transaction marqueur spéciale, appelée "transaction d'actif de base", qui agit comme le début (la création) de la chaîne de signatures numériques. Au lieu de nécessiter une nouvelle structure de données pour l'identificateur unique, nous réutilisons l'identifiant de transaction et l'index de sortie, appelé un "outpoint", comme identificateur unique pour le type de coin. Il est assuré que les outpoints (36 octets) sont aléatoires et globalement uniques.
Une instruction de programmation, appelée OP_PUSHINPUTREF, est utilisée pour attacher une référence à une sortie. L'instruction accepte exactement un paramètre de 36 octets qui doit correspondre soit 1) au point de sortie de l'une des sorties dépensées, ou 2) à la même valeur de 36 octets qui apparaît déjà dans un OP_PUSHINPUTREF spécifié précédemment dans l'une des sorties dépensées. La seule façon pour une valeur donnée d'apparaître dans une sortie de transaction est que, grâce à une transaction ancêtre, elle correspondait au point de sortie de la transaction initiale de création d'actifs. Les transactions qui spécifient une valeur qui ne répond pas à l'une ou l'autre de ces conditions sont invalides.
Diagram 5. Les identifiants uniques sont initialisés en associant un outpoint de l'une des sorties dépensées, puis sont maintenus aussi longtemps qu'au moins l'une des sorties dépensées contient le même identifiant unique dans le corps du script.
Cette simple instruction de programmation fournit un identifiant unique qui peut être utilisé comme une référence stable pour créer des règles avancées. Par exemple, différents types de pièces, des actifs numériques, peuvent maintenant dépendre d'autres types de pièces. Comme toutes les données sont locales à la transaction, via ses transactions d'entrée parent immédiates, il est facile pour les clients et les services de valider l'authenticité d'un actif numérique en temps constant O(1) et d'espace, évitant ainsi le besoin d'un service de confiance.
Il est possible de créer des identifiants uniques d'une manière alternative et de fournir également un mécanisme de preuves par induction mathématique en utilisant un algorithme de hachage de transaction modifié. En permettant aux scripts d'entrée d'accepter la transaction parent dépensée, les règles peuvent vérifier que le parent, ainsi que son grand-parent, respectent les règles requises. Le problème évident est que chaque copie complète des transactions parent est intégrée, une explosion de taille exponentielle se produit et empêche l'utilisation pratique de la technique. Ce qui est nécessaire, c'est une façon de compresser la transaction, de sorte qu'une structure de données de taille fixe puisse être utilisée à la place pour dériver le hachage de la transaction, au lieu de nécessiter le contenu complet de la transaction.
Diagram 6. Validation complète de la transaction parent, preuve par induction mathématique en intégrant les transactions parent complètes dans les entrées, entraînant une augmentation exponentielle de la taille de la transaction.
Nous pouvons y parvenir en modifiant l'algorithme de hachage de transaction utilisé dans Bitcoin, où une somme de contrôle double sha-256 est calculée à partir de la transaction sérialisée, en une nouvelle version qui résume d'abord le contenu de la transaction pour dériver le hachage. Nous introduisons l'algorithme de hachage de transaction version 3, pour le distinguer de l'utilisation des versions 1 et 2 dans Bitcoin. Le processus consiste à hacher chaque champ ou composant d'une transaction, pour obtenir un hachage intermédiaire, qui peut être utilisé comme entrée de taille fixe et ainsi éviter la croissance exponentielle de la taille de la transaction.
Nous utilisons la structure de données suivante de 112 octets, au lieu des octets de transaction sérialisés complets, qui sont à leur tour hachés en double sha-256 pour obtenir le hachage de transaction final.
Voici la structure de données de 112 octets pour l'antécédent de hachage de transaction de version 3, qui est utilisée à la place des octets de transaction sérialisés complets :
Champs d'antécédents de hachage de transaction de version 3 :
nVersion (= 3) de la transaction (4 octets en petit endian)
nTotalInputs (4 octets en petit endian)
hashPrevoutInputs (32 octets de hachage)
hashSequence (32 octets de hachage)
nTotalOutputs (4 octets en petit endian)
hashOutputHashes (32 octets de hachage)
nLocktime de la transaction (4 octets en petit endian)
En utilisant l'algorithme de hachage de transaction pour les transactions de version 3, nous sommes en mesure d'intégrer la transaction parent et la transaction grand-parent à chaque étape d'une preuve d'induction mathématique pour éviter une augmentation de la taille de la transaction, et pouvons appliquer toutes les règles nécessaires.
Diagram 7. Validation compressée de la transaction parent, preuve par induction mathématique en intégrant la structure de données d'antécédent de hachage de transaction de version 3 de la transaction parent et de la transaction grand-parent pour appliquer des règles et des contraintes arbitraires.
La topologie du réseau est un graphe presque complet, dans lequel chaque nœud de minage est connecté à tous les autres nœuds de minage. Les étapes pour exécuter le réseau sont les mêmes que pour Bitcoin, avec quelques distinctions pour les différents types de nœuds : les nœuds de minage, les nœuds agents et les nœuds d'archives. Les nœuds de minage sont les éditeurs actifs de blocs et maintiennent le consensus avec tous les autres nœuds, les nœuds d'archives fournissent des données de bloc historiques, et les nœuds agents sont conçus pour filtrer les blocs et suivre les transactions d'intérêt pour les applications qu'ils servent. Les nœuds d'archives et les nœuds agents peuvent opérer sur le même réseau pair-à-pair mais ne produisent pas de blocs. Les nœuds non-miniers tels que les nœuds d'archives et les nœuds agents sont parfois appelés "nœuds d'écoute" pour distinguer leur rôle dans le réseau.
Diagram 8. Les nœuds de minage sont bien connectés et construisent sur les blocs les uns des autres. Les nœuds d'archive stockent des blocs complets pour l'analyse historique et le démarrage. Les nœuds agents sont des nœuds d'écoute qui filtrent et stockent les transactions pour servir les clients.
Les nœuds de minage sont bien connectés dans un graphe presque complet avec d'autres nœuds de minage. Leur travail consiste à construire sur les blocs les uns des autres et à maintenir un consensus pour les quelques centaines de blocs les plus récents, ainsi qu'à maintenir l'ensemble des UTXO pour prévenir les doubles dépenses.
Les nœuds agents n'ont besoin de stocker qu'un sous-ensemble de transactions, par exemple, un type de pièce ou un actif numérique spécifique. Même avec de grands blocs, un nœud agent peut rapidement filtrer les transactions par références ou séquences de bytes spécifiques, puis stocker ces transactions pour les servir via une interface de programmation d'application. Entre agents coopérants, une racine d'arbre de Merkle peut être annoncée publiquement pour les transactions dans chaque bloc qui correspondent à un modèle prédéterminé, afin de signaler aux autres agents et aux consommateurs quelles transactions cet agent a traitées.
Les nœuds d'archive sont utilisés pour créer des copies de sauvegarde de blocs entiers pour diverses applications, notamment la conservation de données, l'analyse et l'apprentissage automatique. Étant donné que les nœuds d'archive ne sont pas directement impliqués dans le minage, ils n'ont pas les mêmes exigences de performances en temps réel et de bande passante que les nœuds de minage ou d'agents.
Nous examinons le scénario dans lequel le réseau Radiant continue de croître et ce que cela implique pour les exigences de traitement des nœuds miniers, d'archivage et d'agent. Pour comparaison, au moment de la rédaction, il y a environ 83 millions de sorties de transaction non dépensées pour la blockchain Bitcoin, pour un total d'environ 6 Go de données nécessaires pour éviter les doubles dépenses. Il est seulement nécessaire que les quelques centaines de blocs les plus récents soient conservés par les nœuds miniers, les blocs plus anciens étant disponibles auprès des nœuds d'archivage. Pour les nœuds d'agent, il est nécessaire de conserver la partition pertinente de sorties de transaction non dépensées qui concernent les applications qu'ils desservent, la mise à l'échelle étant une fonction de la bande passante et non des exigences de stockage.
Pour nos besoins, nous supposons qu'il y aura des blocs de 3 Go toutes les 5 minutes à horodater et à distribuer sur le réseau, soit environ 20 000 transactions par seconde avec une taille de transaction moyenne de 500 octets, soit environ 6 000 000 transactions par bloc. Nous montrons que pour chaque type de noeud, le réseau est capable de se développer suffisamment pour répondre à la demande mondiale. Cela équivaut à environ 1 transaction tous les 5 jours pour chacun des 8 milliards de personnes sur la planète.
Les noeuds miniers (Mining Nodes) sont les seuls types de nœuds à construire sur les blocs des autres. Pour maintenir un consensus, il suffit de synchroniser l'ensemble des sorties de transactions non dépensées (UTXO) et de ne conserver que les cent derniers blocs. Au moment de la rédaction, les disques durs bon marché à haute performance sont capables de réaliser plus de 120 000 E/S par seconde, coûtant environ 500 USD pour 280 Go, et peuvent donc gérer environ 20 000 transactions par seconde (en supposant que chaque transaction a 2 entrées et 2 sorties). Il y a 2 lectures pour les entrées, 2 mises à jour des entrées et 2 écritures pour la nouvelle sortie: 120 000 / 6 = 20 000 transactions/seconde.
Les Archive Nodes fournissent des données de blocs historiques et conviennent aux applications de machine learning, d'analyse et d'entreposage de données. Les Archive Nodes peuvent compléter le démarrage des Mining Nodes et exécuter des vérifications de cohérence périodiques sur l'ensemble des transactions non dépensées (UTXO). Au moment de la rédaction, des disques durs de 18 To sont disponibles pour environ 350 USD. En supposant 3 Go de données toutes les 5 minutes, cela équivaut à une exigence de stockage de 732 Go par jour, soit environ 22 To par mois. Le coût matériel pour une année est de 15 disques durs, avec une capacité de 18 To, pour un coût incrémentiel annuel de 5 000 USD.
Les nœuds d'agent se mettent à l'échelle de la manière la plus facile parmi les types de nœuds car ils ne traitent que les types de transactions pertinents pour les applications qu'ils servent. Par conséquent, les nœuds d'agent peuvent aller d'un serveur web à un appareil IoT léger avec des capacités de traitement et de stockage limitées, et pourtant suivre le rythme des blocs de 3 Go, ou 20 000 transactions par seconde. Par exemple, une entreprise peut souhaiter suivre l'utilisation de ses points de fidélité, créés en tant qu'actif numérique, et n'a donc besoin de sélectionner qu'un petit sous-ensemble de mises à jour de transactions de chaque bloc qui correspondent à l'identifiant unique de ce type de pièce.
Au moment de la rédaction, un dispositif informatique commercial, le Raspberry Pi 4, est vendu environ 275 USD, il dispose d'un processeur quadcore de 1,5 GHz et de 4 Go de RAM, qui peut être utilisé pour filtrer rapidement et éliminer les transactions non pertinentes à une vitesse de 5 000 transactions par cœur. Bien sûr, il ne s'agit là que d'un exemple de la facilité à traiter de grands blocs, dans une application Web typique, il peut y avoir beaucoup plus de cœurs disponibles.
La vitesse de bande passante médiane des 25 premiers pays dépasse 100 Mb/s, soit environ 10 Mo/seconde de téléchargement, de nombreux fournisseurs de services Internet offrant des téléchargements illimités. Les exigences en bande passante pour des blocs de 3 Go toutes les 5 minutes sont d'environ 10 Mo/seconde pour un total de 22 To par mois. Des hiérarchies de nœuds Agent peuvent également être créées pour réduire les exigences totales de bande passante pour les nœuds Agent ayant une capacité de bande passante plus faible.
Nous avons proposé un système de gestion d'actifs numériques sans avoir besoin de faire confiance à une tierce partie. Nous avons commencé par les blocs de base de pièces faites à partir de signatures numériques, qui fournissent un contrôle fort de la propriété. À partir des règles et des incitations nécessaires, nous avons introduit deux méthodes novatrices pour authentifier et suivre les actifs numériques en temps et en espace constants O(1). Les deux méthodes fournissent indépendamment un système de preuve par induction mathématique général qui peut encoder n'importe quelle configuration d'actifs numériques possible. Le système Turing est complet dans et entre les limites de transaction, sans avoir besoin de couches secondaires. Radiant est une conception révolutionnaire qui offre les avantages de performance et de parallélisme d'une blockchain de sortie de transaction non dépensée (UTXO), mais avec la capacité de contracter des blockchains basées sur des comptes en utilisant la machine virtuelle Ethereum (EVM).
[1] Satoshi Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System" URL
https://bitcoin.org/bitcoin.pdf, 2009.
[2] Vitalik Buterin, "Ethereum: A Next-Generation Smart Contract and Decentralized
Application Platform." URL https://ethereum.org/en/whitepaper/, 2014.
[3] Wikipedia contributors. "Turing completeness." Wikipedia, The Free Encyclopedia.
Wikipedia, The Free Encyclopedia, URL https://en.wikipedia.org/wiki/Turing_completeness,
21 Jul. 2022
[4] R.C. Merkle, "Protocols for public key cryptosystems," In Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, pages 122-133, April 1980.
[5] Britannica, T. Editors of Encyclopaedia. "mathematical induction." Encyclopedia Britannica, URL https://www.britannica.com/science/mathematical-induction, 2018
The Radiant Developers
August 11, 2022
radiantblockchain.org
Abstract. The Radiant network is a peer-to-peer digital asset system that enables direct exchange of value without going through a central party. The original Bitcoin[1] protocol provides what is needed to create a peer-to-peer electronic cash system, but lacks the ability to verify transaction histories and therefore, cannot be used to validate digital assets. Digital signatures and output constraints provide part of the solution, but the main benefits are lost if a trusted third party is still required to validate digital assets. Similarly to Bitcoin, the Radiant network requires minimal structure, and timestamps transactions into an ongoing hash-based chain of proof-of-work. We introduce two techniques to validate digital assets: unique references and a general purpose induction proof system both of which operate in constant O(1) time and space. It is possible to compose outputs in any manner, without compromising the inherent parallelism and performance characteristics of an unspent transaction output (UTXO) based architecture. Therefore, users can leave and rejoin the Radiant network at will and be assured of the integrity and authenticity of their digital assets.
Commerce with blockchains, or digital ledger technology (DLT), in many cases relies on issuers and custodians serving as trusted parties to authenticate digital assets. While those systems work well enough for electronic payment-like transactions, they still suffer from the inherent weaknesses of the trust based model for advanced uses. The Ethereum Virtual Machine (EVM) [2] based blockchains are very flexible for all kinds of programs, but the high fees makes use for micropayment applications impractical.
What is needed is an electronic payment system that can be used for digital asset management system with low fees, high performance, and advanced programming capabilities. In this paper, we propose a solution to the problem of blockchain scaling and contracting using two novel techniques which provide unique references and a general induction proof system, which makes Turing Complete [3] programs across transaction boundaries possible. The system proposed is decentralized, uses a proof-of-work consensus mechanism like Bitcoin, but with significantly higher levels of throughput, while providing the same flexibility of EVM-based blockchains, with very low fees.
Similar to Bitcoin, we define an electronic coin as a chain of digital signatures. Where transactions in Radiant differ is that each owner transfers the coin to the next by digitally signing a hash of the previous transaction in addition to the required input params to unlock the coin. A transaction also creates new output locking constraints, which may include the public key of the next owner, amongst any other rules defined by the user.
Diagram 1. Radiant Transactions.\
To verify that a double-spend did not occur, we use a distributed timestamp server, using a hash-based proof-of-work system to organize the canonical history to determine which transaction arrived first. The transactions are organized into blocks. As a matter of convention, the first transaction, called a "coinbase transaction", in a block is a special transaction that starts a new coin owned by the creator of the block. Blocks are chained together and organize transactions into a Merkle Tree [4]. All transactions, with the exception of the first, must reference a previous transaction forming a directed acyclic graph (DAG) where all coins eventually connect back to at least one of the special transactions at the beginning of a block.
Diagram 2. Block Structure; transactions are organized into a Merkle Tree.\
The problem with this design, in the context of digital assets, is that there is only one type of coin, or digital asset, and no concept of user-defined coins (or digital asset types). The design works well enough for electronic payment-like transactions in the native unit of account, however it does not immediately lend itself to be used for other types of coins or digital assets. A common solution is to introduce a service such as a transaction indexer which monitors transactions for special data sequences to signify the creation of a digital asset. The problem with this solution is that it depends on the company running the service, with digital asset authenticity needing to be trusted, just like any other service on the web.
We need a way for the users to indicate the creation of custom coin types, but not rely on a trusted service to be used for data presentation.
We define a custom electronic coin, or digital asset, as a chain of digital signatures. A digital asset is a user-defined coin type using a special transaction marker, called an "assetbase transaction", to create or mint a digital asset. Similar to coinbase transactions, which inject new coins into the system, the assetbase transaction colors or tags the electronic coin with a unique 36-byte identifier for it's lifetime. The custom electronic coin is overlayed on top of the base coin type and functions in a similar manner. The assetbase transaction can appear anywhere in the block and may enforce any custom rules and constraints decided upfront.
Diagram 3. Transactions representing user-defined coin types — or digital assets.\
To accomplish this we need to create a stable unique identifier and a transaction mechanism to track the authenticity of the coin type (digital asset). The users of the system need to have proof that custom coin types are not forgeries and accurately represent the digital assets.
Diagram 4. Custom user-defined coin types are defined from a special mint transaction. A unique identifier is used to classify the coin type.\
To implement a unique identifier for a coin type, we use a special marker transaction, called "assetbase transaction", which acts as the start (mint) of the chain of digital signatures. Rather than require a new data-structure for the unique identifier, we reuse the transaction identifier and output index, called an "outpoint", as the unique identifier for the coin type. It is assured that outpoints (36-bytes) are random and globally unique.
A programming instruction, called OP_PUSHINPUTREF
, is used to attach a reference to an output. The instruction accepts exactly one 36-byte parameter which must match either 1) the outpoint of one of the outputs being spent, or 2) the same 36-byte value already appears in a previously specified OP_PUSHINPUTREF
in one of the outputs being spent. The only way for any given value to appear in a transaction output is that, through some ancestor transaction, it matched the outpoint from the initial minting assetbase transaction. Transactions that specify a value which do not meet either condition are invalid.
Diagram 5. Unique identifiers are initialized by matching an outpoint of one of the outputs being spent, and then maintained as long as at least one of the outputs being spent contains the same unique identifier in the script body.\
This simple programming instruction provides a unique identifier which can be used as a stable reference to create advanced rules. For example, different coin types, digital assets, can now depend on other coin types. Since all of the data is local to the transaction, via it's immediate parent input transactions, it is easy for clients and services to validate the authenticity of a digital asset in O(1) constant time and space, avoiding the need for a trusted service.
It is possible to create unique identifiers in an alternative manner and also provide a mechanism for mathematical induction [5] proofs using a modified transaction hash algorithm. By allowing input scripts to accept the parent transaction being spent, the rules can verify that the parent, and it's grand-parent conform to the required rules. The obvious problem is that as each full copy of the parent transactions are embedded, an exponential size explosion occurs and prevents the practical use of the technique. What is needed is a way to compress the transaction, so that a fixed sized data-structure can be used instead to derive the transaction hash, instead of requiring the full transaction contents.
Diagram 6. Full parent transaction validation, mathematical induction proof by embedding the full parent transactions into the inputs resulting in exponential transaction size increase.\
We can accomplish it by modifying the transaction hash algorithm used in Bitcoin, wherein a double sha-256 digest is calculated from the serialized transaction, into a new version that first summarizes the transaction contents to derive the hash. We introduce transaction hash algorithm version 3, to distinguish it from the use of version 1 and version 2 in Bitcoin. The process is to hash each field, or component of a transaction, to an intermediate hash, which can be used as a fixed size input and thereby avoid the exponential transaction size growth.
We use the following 112-byte data-structure, instead of the complete serialized transaction bytes, which in turn is double sha-256 hashed to finally obtain the transaction hash.
Transaction Version 3 Hash Preimage Fields:
nVersion(=3) of the transaction (4 byte little endian)
nTotalInputs (4 byte little endian)
hashPrevoutInputs (32 byte hash)
hashSequence (32 byte hash)
nTotalOutputs (4 byte little endian)
hashOutputHashes (32 byte hash)
nLocktime of the transaction (4 byte little endian)
By using the transaction hash algorithm for version 3 transactions, we are able to embed the parent and grand-parent transaction in each step of a mathematical induction proof to prevent transaction size increase, and can enforce any rules needed.
Diagram 7. Compressed parent transaction validation, mathematical induction proof by embedding the transaction hash version 3 preimage data-structure of the parent and grand-parent to enforce arbitrary rules and constraints.\
The network topology is a nearly complete graph, wherein every Mining Node is connected to every other Mining Node. The steps to run the network are the same as Bitcoin, with some distinctions for different node types: Mining Nodes, Agent Nodes, Archive Nodes. Mining Nodes are the active publishers of blocks and maintain consensus with all other nodes, Archive Nodes serve historical block data, and Agent Nodes are designed to filter blocks and track transactions of interest to the applications they serve. Archive and Agent Nodes may operate on the same peer-to-peer network and yet do not produce blocks. The non-Mining Nodes such as Archive and Agent Nodes are sometimes referred to as "listener nodes" to distinguish their role in the network.
Diagram 8. Mining Nodes are well-connected and build on top of each other's blocks. Archive nodes store complete blocks for historical analysis and bootstrapping purposes. Agent nodes are listener nodes which filter and store transactions to serve clients.\
Mining Nodes are well-connected into a nearly complete graph between other Mining Nodes. Their job is to build on top of each other's blocks and maintain consensus for the most recent few hundred blocks, and maintain the UTXO set for the prevention of double-spending.
Agent Nodes only need to store a subset transactions, for example, a specific coin type or digital asset. Even with large blocks, an Agent Node can quickly filter transactions by references or specific byte-sequences, then store those transactions to serve via an application programmer interface. Between cooperating agents, a Merkle Tree root hash can be publicly announced for the transactions in each block that match a pre-determined pattern to signal to other Agents and consumers which transactions that Agent has processed.
Archive Nodes are used to create backup copies of entire blocks for various applications including data warehousing, analytics and machine learning. Since Archive Nodes are not involved directly in mining, they do not have the same real-time performance and bandwidth requirements as Mining or Agent Nodes.
We consider the scenario where the Radiant network continues to grow and what it entails for the processing requirements of Mining, Archive and Agent Nodes. For comparison, at the time of writing, there are about 83 million unspent transaction outputs for the Bitcoin blockchain, for a total of about 6 GB of necessary data to prevent double spends. It is only necessary that the most recent few hundred blocks are kept by Mining Nodes, with older blocks being available from Archive Nodes. For Agent Nodes, it is necessary to keep the relevant partition of unspent transaction outputs that pertain to the applications they serve, scaling is a function of bandwidth and not storage requirements.
For our purposes, we assume that there will be 3 GB sized blocks every 5 minutes to be timestamped and distributed across the network, or about 20,000 transactions per second with the average transaction size of 500 bytes, or about 6,000,000 transactions per block. We show that for each type of node, the network is able to adequately scale to meet global demand. This equals about 1 transaction every 5 days for each of the 8 billion people on the planet.
Mining Nodes are the only node type which build on top of each other's blocks. To maintain consensus, it is sufficient to synchronize the unspent transaction output (UTXO) set, and only maintain about the last hundred blocks. At the time of writing, high performance commodity solid-state drives are capable of achieving upwards of 120,000 IOPS, costing about $500 USD for 280 GB, and can therefore handle about 20,000 transactions per second (assuming each transaction has 2 inputs and 2 outputs). There are 2 reads for inputs, 2 updates to the inputs, and 2 writes for the new output: 120,000 / 6 = 20,000 transactions/second.
Archive Nodes provide historical block data and are suitable for machine learning, analytics, and data warehousing applications. The Archive Nodes may supplement bootstrapping of Mining Nodes and to run periodic consistency checks on the UTXO set. At the time of writing, commodity hard disks of 18 TB are available for about $350 USD. Assuming 3 GB of data every 5 minutes equals 732 GB of data storage requirement per day, or about 22 TB per month. The hardware cost for a year is 15 hard drives, with 18 TB capacity, for a yearly incremental cost of $5,000 USD.
Agent Nodes scale most easily amongst the node types because they only process the relevant transaction types for the applications they serve. As a result the Agent Nodes can range from a web server to a lightweight IoT device with limited processing and storage capabilities, and yet still keep peace with 3 GB blocks, or 20,000 transactions per second. For example, a company may wish to track the usage of it's loyalty points, created as a digital asset, and therefore only need to select a small subset of transaction updates from each block that match the unique identifier for that coin type.
At the time of writing, a commercial computing device, Raspberry Pi 4, sells for about $275 USD which has a quadcore 1.5 GHZ processor and 4 GB of RAM, which can be used to quickly filter, and discard irrelevant transactions, at a rate of 5,000 transactions per core. Of course, this is just an example of how reasonable it is to process large blocks, in a typical web application may have many more cores available.
The median bandwidth speed of the top 25 countries exceeds 100 MBPS, or about 10 MB/second download, with many internet service providers offering unlimited downloads. The bandwidth requirements for 3 GB blocks every 5 minutes is about 10 MB/second for a total of 22 TB per month. Hierarchies of Agent Nodes can also be created to filter down the total bandwidth requirements for Agent Nodes with lower bandwidth capacity.
We have proposed a system for digital asset management without relying on trust. We started with the basic building blocks of coins made from digital signatures, which provides strong control of ownership. From the needed rules and incentives, we introduced two novel methods for authenticating and tracking digital assets in constant O(1) time and space. Both methods independently provide a general mathematical induction proof system which can encode any possible digital asset configuration. The system is Turing Complete within and across transaction boundaries, without need for secondary layers. Radiant is a breakthrough design which provides the performance and paralellism benefits of an unspent transaction output (UTXO) blockchain, but with the contracting ability of account-based blockchains based on the Ethereum Virtual Machine (EVM).
[1] Satoshi Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System" URL https://bitcoin.org/bitcoin.pdf, 2009.
[2] Vitalik Buterin, "Ethereum: A Next-Generation Smart Contract and Decentralized Application Platform." URL https://ethereum.org/en/whitepaper/, 2014.
[3] Wikipedia contributors. "Turing completeness." Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, URL https://en.wikipedia.org/wiki/Turing_completeness, 21 Jul. 2022
[4] R.C. Merkle, "Protocols for public key cryptosystems," In Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, pages 122-133, April 1980.
[5] Britannica, T. Editors of Encyclopaedia. "mathematical induction." Encyclopedia Britannica, URL https://www.britannica.com/science/mathematical-induction, 2018
The induction proof system is a method used in the Radiant blockchain to ensure the authenticity and traceability of digital assets. It verifies that each transaction is linked back to a valid genesis transaction, preventing forgery and ensuring that all assets are genuine.
The induction proof system works by including references to parent and grandparent transactions in each new transaction. These references create a chain of trust, where each transaction can be verified against its predecessors, all the way back to the original genesis transaction.
The induction proof system is important because it provides a secure and efficient way to validate digital assets without relying on trusted third parties. It ensures that all assets on the Radiant blockchain are genuine and prevents double-spending and forgery.
Unique identifiers are like serial numbers for digital assets. They help track the asset's journey from the genesis transaction through all subsequent transactions. Each transaction output has a unique identifier, ensuring that the asset's lineage can be verified.
The Radiant blockchain uses a compressed transaction hash algorithm to summarize transaction contents into a fixed-size data structure. This prevents the exponential growth in transaction size that would occur if full copies of parent transactions were included in each new transaction.
A genesis transaction is the original creation of a digital asset on the Radiant blockchain. It serves as the starting point for the asset's lineage and is referenced in all subsequent transactions to verify authenticity.
To validate a transaction, you need to check the references to its parent and grandparent transactions. By verifying these references, you can ensure that the transaction is genuine and traceable back to the genesis transaction.
Opcodes are programming instructions used in the Radiant blockchain to manage and validate transaction references. Examples include OP_PUSHINPUTREF
, OP_REQUIREINPUTREF
, and OP_DISALLOWPUSHINPUTREF
. These Opcodes help enforce rules and ensure the authenticity of transactions.
Yes, the induction proof system can be used to create and validate smart contracts on the Radiant blockchain. By ensuring the authenticity and traceability of transaction outputs, it supports the creation of complex contracts and digital assets.
The induction proof system enhances security by creating a chain of trust for each transaction. This makes it nearly impossible to forge or duplicate assets, as each transaction must be verified against its predecessors.
Practical applications of the induction proof system include digital asset management, creation of fungible and non-fungible tokens (NFTs), and implementation of complex smart contracts. It ensures the authenticity and traceability of these assets, making them secure and reliable.
The Radiant blockchain's use of the induction proof system and compressed transaction hashes allows for efficient and secure transaction validation. This provides a significant advantage over other blockchains that may rely on trusted third parties or less efficient validation methods.
Radiant is a peer-to-peer programmable digital asset system, derived from a fork of the Bitcoin Cash (BCH) genesis block. It introduces new Opcodes that enable Turing completeness and mathematical induction proofs, effectively addressing the "back to genesis" problem. This innovative design combines the performance and parallelism advantages of an Unspent Transaction Output (UTXO) blockchain with the contract capabilities found in Ethereum-based blockchains, specifically the Ethereum Virtual Machine (EVM).
Powered by Proof of Work (PoW)
Supports Smart Contracts
Launched fairly
Utilizes a robust hashing algorithm, SHA512256d
Implements the ASERT DAA (Difficulty Adjustment Algorithm)
Genesis Date: June 20, 2022, 02:42:50 GMT+0000
Block Time: 300 seconds (5 minutes)
Halving: Every 2 years (every 210,000 blocks)
Subsidy Emission: 50,000 per block (Now 25,000 per block)
Total Coins: 21 billion, divisible into 8 decimal places (100 million photons per RXD)
Radiant stands out for several reasons:
Induction Proofs that solve the "back-to-genesis" problem without the need for indexers.
Account Emulation, enabling Ethereum Virtual Machine (EVM)-like applications.
A Turing-complete scripting language known as RadiantScript.
The "0-conf" feature for instant transactions.
A Split Node System designed for scalability.
Radiant was launched as a 100% PoW blockchain, ready for use, without any involvement of investors, ICOs, premining, or coin allocations. Mining guides and instructions, including how to mine with rented hash power, were publicly released by Atoshi, Radiant's developer, ensuring that everyone had equal access to RXD coins from day one.
Radiant aims to be a scalable and flexible blockchain technology, not primarily designed for investment purposes or generating profits from RXD coin holdings. Similar to Bitcoin, which was created as a peer-to-peer electronic cash system, Radiant was designed as a peer-to-peer programmable digital asset system. While you can still acquire RXD coins from exchanges, it's essential to understand that there are no guarantees of further development. Always perform your research (DYOR) and exercise caution when considering any investment.
BTC civil wars divided blockchain enthusiasts into small-block and big-block proponents. In BTC, small-blocks won and big-block proponents forked it to create BCH. BCH still ended deviating from what BTC was supposed to be based on what is stated in the Bitcoin Whitepaper.
Another fork (BSV) was made, aiming to make it as close as possible to the original BTC proposed by Satoshi Nakamoto. This version of Bitcoin is still far from perfect as it has to rely on third party indexers to function properly. Additionally, its associations with an individual who claims to be Satoshi Nakamoto who has initiated legal actions against some blockchain projects, raised concerns about potential legal challenges.
This made BCH a more favorable choice for Radiant's development.
SHA512256d is a hashing algorithm that applies SHA-512 and truncates its 512-bit output to 256 bits. While SHA-256 is already secure, Radiant selected SHA512256d to provide a robust, battle-tested foundation for a blockchain designed for ASIC compatibility. By leveraging SHA-512's efficient 64-bit operations and widespread hardware support, SHA512256d optimizes performance on 64-bit processors, enhancing ASIC development and integration. This approach delivers efficient mining and scalable blockchain validation, outperforming more computationally demanding algorithms.
Radiant was specifically designed to transition from GPU mining to ASIC mining for enhanced scalability and efficiency. The chosen SHA512/256d algorithm simplifies ASIC manufacturing.
A 5-minute block time offers faster transaction confirmations compared to Bitcoin (BTC) while maintaining stability and security by minimizing orphan blocks. With block sizes of up to 256MB and the potential for even larger blocks, selecting the right block time is essential. In Radiant, the block time, thanks to its features, does not directly limit transactions per second or transaction speed.
Radiant has a total maximum supply of 21 billion RXD, with a Proof of Work emission schedule emitting block rewards to miners every 5 minutes (300 seconds), with block rewards halving every 2 years.
Beginning with its Genesis Block on the 20th of June 2022, Radiant's initial block reward was 50,000 RXD per block, and Radiant's first halving event occurred on the 19th April 2024, halving to 25,000 RXD.
The next halving event for Radiant will occur around the middle of April 2026, reducing the block rewards to 12,500 RXD per block.
2022
Genesis
50,000 RXD
0
0
2024
1st
25,000 RXD
210,000
10,500,000,000 RXD
2026
2nd
12,500 RXD
420,000
15,750,000,000 RXD
2028
3rd
6,250 RXD
630,000
18,375,000,000 RXD
2030
4th
3,125 RXD
840,000
19,687,500,000 RXD
2032
5th
1,552.5 RXD
1,050,000
20,343,750,000 RXD
2034
6th
781.25 RXD
1,260,000
20,671,875,000 RXD
2036
7th
390.625 RXD
1,470,000
20,835,937,500 RXD
2038
8th
195.3125 RXD
1,680,000
20,917,968,750 RXD
Radiant will effectively have 0 block rewards within the year 2108, when the block reward falls below 1 photon (1/100,000,000 RXD) after the 43rd halving.
With the current block size of 256MB, Radiant is capable of doing 4,000 TPS (Transaction Per Second). If needed, miners can optimize in the future to scale linearly. The Radiant Blockchain is designed to scale towards 500,000+ TPS.
Radiant's tokenomics, with a 21 billion coin supply and 8 decimal places (100 million photons per RXD coin), positions it well for tokenizing digital and real-world assets while ensuring ample availability of RXD for both micro and macro transactions. The block time, block reward, and bi-yearly halvings serve as incentives attractive to miners and investors alike.
In blockchain terms, the "back-to-genesis" problem refers to the ability to validate that all coins, transactions, and digital assets can be traced back to the genesis block. Radiant successfully solves this problem, enabling it to operate as a truly decentralized and permissionless digital asset system without relying on external third-party indexers.
Turing completeness, in the context of a programming language, signifies that there are no limits to the types of computations that can be performed. Radiant's Turing completeness allows for highly flexible smart contract capabilities similar to those of Ethereum but without the scalability issues and high gas costs. This feature makes Radiant a unique and groundbreaking blockchain, capable of supporting a wide range of cryptocurrency and blockchain technology use cases.
Radiant, while Turing complete, does not incorporate loops. Loops must be unrolled to the maximum number of iterations required. This design simplifies and secures script execution, allowing fees to be calculated per byte. This discourages malicious actors from creating overly complex or inefficient scripts, as they would incur higher fees.
A 0-conf transaction is one broadcasted to the blockchain but not yet included in a block (i.e., 5 minutes have not passed). These transactions are useful and safe for microtransactions. Thanks to induction proofs, recipients of 0-conf transactions can be confident that the sender indeed owns the funds being transferred. However, there is a minor risk of double-spending in such transactions.
For small transactions, the potential reward for attempting a double-spending attack is typically much lower than the cost of acquiring mining hardware, electricity, and competing with the network's hash rate. In practice, it's not economically rational for an attacker to invest significant resources in double-spending small transactions.
For larger transactions, it's advisable to wait for inclusion in a block, which provides increasing security with each additional block confirmation.
Radiant does not have RBF implemented. Radiant's decision to exclude Replace-by-Fee is a strategic choice that enhances transaction security, reduces double spend risks, and simplifies the user experience.
By prioritizing transaction finality and promoting responsible fee management, Radiant fosters a more secure and reliable blockchain environment.
This approach aligns with its commitment to maintaining a robust, miner-driven network that users can trust for fast, low cost, and dependable transactions.
In the world of blockchains, transaction security and network reliability are paramount. One feature that often sparks debate is Replace-by-Fee (RBF) vs, First In First Out (FIFO). While some blockchains implement RBF to allow users to replace a pending transaction with a new one that includes a higher fee, Radiant has opted not to include this feature.
Here's why this decision benefits the Radiant network and its users:
By not supporting RBF, Radiant ensures a higher degree of transaction finality once a transaction is broadcast to the network. This means that once a transaction is sent, it's committed to the network's mempool, reducing the risk of the transaction being replaced or tampered with. This provides more confidence to recipients, particularly in situations where quick transaction acknowledgment is essential.
RBF can be exploited for double spend attacks, especially in low-confirmation transactions. For instance, a user could broadcast a low-fee transaction to one party, then replace it with a higher-fee transaction to a different party, attempting to defraud the first recipient. To mitigate these risks, many businesses and users wait for several confirmations before considering a transaction final, especially for larger amounts. Radiant's decision to exclude RBF minimizes this risk, making it safer for merchants and users to accept zero or low-confirmation transactions without the fear of an attack.
Excluding RBF simplifies the transaction process for users and developers. With RBF, users have to be cautious about transaction replaceability, potentially leading to confusion or errors. Radiant's straightforward approach means that once a transaction is sent, users can have confidence that it won't be replaced, leading to a more predictable transaction experience.
Without RBF, users are encouraged to consider transaction fees carefully before broadcasting. This helps prevent network congestion caused by users continually adjusting fees to prioritize their transactions. It fosters a more balanced network usage where users evaluate the urgency of their transactions in relation to current network conditions, promoting a healthier fee market. Miners can still choose to process higher fee transactions at will, but the volume and speed of putting more transactions in a block is more valuable and hence important in a scalable network.
Radiant's Proof of Work consensus mechanism relies on the security provided by miners who validate and add transactions to the blockchain. By not having RBF, Radiant reinforces the trust in its PoW system, ensuring that transactions are treated as irreversible once included in a block. This aligns with the core principles of PoW, where the longest chain and the work behind it determine the network's state.
Bitcoin originally operated on a First-In-First-Out (FIFO) basis for transaction processing within the mempool. This means that transactions were typically processed in the order they were received by the network, regardless of the transaction fee. Miners would include the earliest transactions in the next block, provided they met the standard criteria for validity and size. Networks like Radiant that focus on true scalability by having adequate block space and faster block production will not suffer the same fate as size constrained and artificially limited networks. So the need for something like RBF is negated.
Radiant employs a Split Node System to accommodate its big-block design and scalability needs. Nodes in Radiant can operate in three different ways:
Mining Nodes: Lightweight, non-resource-intensive nodes dedicated to mining.
Agent Nodes: Contain essential information required for specific decentralized applications (dApps) and smart contracts.
Archival Nodes: Store the complete blockchain for comprehensive data access.
Radiant was bootstrapped and introduced to the world by an individual or group of individuals using the pseudonym "Atoshi." Similar to the anonymous creation of Bitcoin by Satoshi Nakamoto, Atoshi delivered a fully functional product without making any promises or guarantees, allowing the community to shape its future.
Check the Radiant node deployment guides
No, Radiant is a 100% PoW Blockchain. The only way to get RXD is through mining.
You can access your RXD through:
You can access your RXD through:
Software
Hardware
The current toolbox available to help developers build on Radiant is:
Genesis Hash:
Radiant now has ASIC miners publically available on the market as of September 5th 2024. The first manufacturer to announce a Radiant compatible SHA512/256d ASIC miner was DragonBall Miner, with the .
ICERIVER was the second manufacturer to release an ASIC miner for Radiant, with the .
A step-by-step guide on .
Radiant's initial GPU mining guide when it was first launched can be found on .
Open source desktop wallet based off the popular BTC wallet upgraded for RXD.
Mobile and desktop wallet compatible with 0-conf transactions.
A multi platform wallet developed by Radiant community developers, compatible with digital asset minting (Glyph Protocol assets).
Install via the Chrome Web Store.
Slim as a bank card, secure as a bank vault.
Radiant JavaScript Library.
Rust/WASM Library to interact with Radiant.
Fork of CashScript with support for Radiant Opcodes to create complex smart contracts.
Create Fungible Tokens, Non-Fungible Tokens, or Smart Contracts by utilizing digital signatures on Photons, the sub-units of Radiant's coin, RXD.
A non-custodial wallet for minting and transferring tokens, following the Glyphs Protocol. The code runs completely client side and only requires a connection to an ElectrumX server.
Utilize the Photonic Wallet extension available at the Chrome Web Store.
A powerful and easy-to-integrate solution for merchants looking to accept payments on the Radiant (RXD) blockchain.
Easy to follow guide on how to setup and run a Radiant Node and ElectrumX Server.
Learn the technical details on how the Glyphs Protocol works on Radiant.
Website:
Whitepaper:
System Design:
GitHub Community - Active:
GitHub Initial - Archived:
Radiant Node:
RadiantJS:
RXD.WASM/RXD-RS:
RadiantScript:
Muon Pay SDK:
Docker for Radiant Node:
Glyph Miner:
Photonic Wallet:
Radiant ElectrumX:
Faucet - Mainnet:
Faucet - Testnet:
Faucet Games - Mainnet:
Explorer 1:
Explorer 2:
Explorer 3:
Explorer 4:
Explorer 5:
Top 100 RXD Wallets:
Mempool Summary:
Transaction Stats:
Block Stats:
Explorer:
Explorer:
Discord - Main:
Discord - RXDDapps:
Telegram - Main:
Telegram - Traders:
Medium - Community:
Medium - Radiant Foundation:
Medium - Initial:
Reddit - Main:
Reddit - Initial:
X - Community:
X - Planet_Radiant:
X - RadiantFoundation:
X - Initial:
Bitcointalk:
RXDDapps:
Radiant Foundation:
Electron Wallet 0.1.4 - Win / Linux / Mac:
ChainBow Wallet 2.1.1 - iOS
ChainBow Wallet 2.1.1 - Android
Tangem Hardware Wallet - Mobile with NFC:
Photonic Wallet - Web App:
Photonic Wallet - Extension:
Photonic Wallet - Source:
CoinEx RXD/USDT:
CoinEx RXD/BTC:
MEXC RXD/USDT:
TradeOgre RXD/USDT:
TradeOgre RXD/BTC:
NonKYC RXD/USDT:
XT RXD/USDT:
CoinMarketCap:
CoinGecko:
CoinPaprika:
LiveCoinWatch:
CoinCodex:
CryptoRank:
RXD/USDT Chart:
CryptoCompare:
CoinCarp:
Glyph Miner:
Photonic Wallet:
Server-Status:
MiningPoolStats Rank:
HumPool:
Vipor:
Rplant Pool:
BlockMinerz:
Kryptex:
WoolyPooly:
RXD SoloPool:
ZergPool:
TW-Pool:
HashPool:
9kpool:
WhalePool:
Satopool:
ICERIVER RXD RX0 ASIC:
DragonBall A11 Dual ASIC:
ccminer+hiveos (NVIDIA):
rad-bfgminer (AMD/NVIDIA):
srbminer(AMD):
bzminer:
Rigel (NVIDIA):
wildrig:
MiningPoolStats:
Minerstats:
Hashrateno:
Whattomine:
Javanese version of the Radiant whitepaper
Kabeh Pangembang Radiant
11 Agustus, 2022
radiantblockchain.org
Abstrak. Radiant Network punika sistem aset digital peer-to-peer bisa ijol-ijolan tandha kanthi cara langsung tanpa liwat pesta tengah. Protokol asline Bitcoin [1] nyedhiyakake apa sing dibutuhake Kanggo gawe sistem kas elektronik peer-to-peer, nanging Ora duweke kabisan Kanggo ngecek sajarah transaksi lan mulane iku, ora saget digunakake Kanggo validasi aset digitale. Tandha digital lan wates output menehi bagean saka solusi, nanging entuk manfaat utama wis ilang Yen pesta sing dipercaya _ Isih dibutuhake Kanggo validasi aset digital . Serupa karo Bitcoin, jaringan Radiant mbutuhake struktur minimal , lan cathetan wektu transaksi kanggo ing rante bukti Kerja adhedhasar hashes medium lumaku . We introduce kalih teknik Kanggo validasi aset digital : referensi unik lan sistem bukti induksi objektif sing umum loro-lorone operate ing papan lan wektu O( 1) konstanta . Iku bisa Kanggo nyipta output karo cara apa wae , tanpa kurban ciri paralelisme inheren lan kinerja _ saka arsitektur adhedhasar output transaksi _ Ora digunakake (UTXO). amarga_ _ iku , pangguna saget metu lan melu bali karo Jaringan sumringah ing bakal ati lan yakin bakal integritas lan keasliane aset digitale .
Dagang karo blockchain, utawa teknologi ledger digital (DLT), ing akeh kasus gumantung marang sing ngetokake sekuritas lan kustodian sing dadi pihak sing dipercaya kanggo otentikasi aset digital. Nalika sistem kasebut bisa digunakake kanthi becik kanggo transaksi kayata pembayaran elektronik, dheweke isih nandhang kelemahane. -model adhedhasar kanggo majeng nggunakake. Mesin Virtual Ethereum (EVM) berbasis Blockchain [2] fleksibel banget kanggo kabeh jinis program, nanging biaya sing dhuwur nggawe aplikasi micropayment ora praktis. Sing dibutuhake yaiku sistem pembayaran elektronik sing bisa digunakake kanggo biaya sing murah, dhuwur- kinerja sistem manajemen aset digital, lan kemampuan pemrograman tingkat nglakokaké. Ing makalah iki, kita ngusulake solusi kanggo masalah skala lan kontrak blokchain nggunakake rong teknik anyar sing nyedhiyakake referensi unik lan sistem bukti induksi umum, sing ndadekake program Turing Complete [3] ngliwati wates transaksi bisa. Sistem sing diusulake didesentralisasi, nggunakake mekanisme konsensus bukti-kerja kaya Bitcoin, nanging kanthi tingkat throughput sing luwih dhuwur, nalika nyedhiyakake keluwesan sing padha karo blockchain berbasis EVM, kanthi biaya sing murah banget.
Kaya Bitcoin, kita nemtokake koin elektronik minangka seri tandha asta digital. Yen transaksi ing Radiant beda-beda yaiku saben pemilik nransfer dhuwit recehan menyang sabanjure kanthi menehi tandha digital hash saka transaksi sadurunge saliyane parameter input sing dibutuhake kanggo mbukak kunci koin kasebut. Transaksi uga nggawe watesan ngunci output anyar, sing bisa uga kalebu kunci umum saka pemilik sabanjure, ing antarane aturan sing ditemtokake pangguna liyane.
Diagram 1. Transaksi Radiant.
Kanggo verifikasi manawa mbuwang kaping pindho ora kedadeyan, kita nggunakake server timestamp sing disebarake, nggunakake sistem bukti kerja adhedhasar hash kanggo nyetel riwayat kanonik kanggo nemtokake transaksi sing teka dhisik. Transaksi diatur dadi blok. Miturut konvensi, transaksi pisanan, sing diarani "transaksi berbasis koin", ing blok minangka transaksi khusus sing miwiti koin anyar sing diduweni dening panyipta blok kasebut. Blok dirantai bebarengan lan ngatur transaksi dadi Merkle Tree [4]. Kabeh transaksi, kajaba sing pisanan, kudu ngrujuk marang transaksi sadurunge sing mbentuk grafik asiklik terarah (DAG) ing ngendi kabeh dhuwit recehan pungkasane nyambung menyang paling ora siji transaksi tartamtu ing wiwitan blok.
Diagram 2. Struktur Blok; transaksi diaturke menyang Wit Merkle.
Masalah karo desain iki, ing konteks aset digital, mung ana siji jinis koin, utawa aset digital, lan ora ana konsep koin sing ditemtokake pangguna (utawa jinis aset digital). Desain bisa uga cukup kanggo transaksi kaya pembayaran elektronik ing unit akun nyata, nanging ora langsung cocok kanggo nggunakake liyane jinis dhuwit recehan utawa aset digital. Solusi umum yaiku ngenalake layanan kayata indeksasi transaksi sing ngawasi transaksi kanggo urutan data tartamtu kanggo menehi tandha nggawe aset digital. Masalah karo solusi iki yaiku gumantung marang perusahaan sing mbukak layanan kasebut, kanthi keaslian aset digital sing kudu dipercaya, kaya layanan liyane ing web. We needed cara kanggo kedhaftar kanggo nduduhake nggawe jinis tartamtu saka duwit receh, nanging ora gumantung ing layanan dipercaya kanggo digunakake kanggo presentation data.
Kita nemtokake koin elektronik khusus, utawa aset digital, minangka seri tandha asta digital. Aset digital minangka jinis koin sing ditemtokake pangguna nggunakake token transaksi khusus, sing diarani "transaksi basis aset", kanggo nggawe utawa nggawe aset digital. Mirip karo transaksi coinbase, kang inject dhuwit recehan anyar menyang sistem, transaksi assetbase werna utawa tandha dhuwit recehan elektronik karo pengenal 36-bait unik kanggo umur. Kostume e-coin dilapisi ing ndhuwur jinis duwit receh dhasar lan bisa digunakake kanthi cara sing padha. Transaksi basis aset bisa katon ing ngendi wae ing blok kasebut lan bisa ngetrapake aturan lan watesan khusus apa wae sing diputusake sadurunge.
Diagram 3. Transaksine kuwi makili jinis duwit receh pangguna-ditetepake — utawa digital asset
Kanggo nindakake, kita kudu nggawe pengenal unik sing stabil lan mekanisme transaksi kanggo nglacak keaslian jinis koin (aset digital). Pangguna sistem kudu duwe bukti yen jinis koin tartamtu ora palsu lan kanthi akurat nggambarake aset digital kasebut.
Diagram 4. Jinis koin khusus sing ditemtokake pangguna ditemtokake saka transaksi mint khusus. Pengenal unik digunakake kanggo nggolongake jinis koin.
Kanggo aplikasi pengenal unik kanggo jinis duwit receh, kita nggunakake transaksi token khusus, disebut "transaksi basis aset", kang tumindak minangka wiwitan (mint) saka chain teken digital. Tinimbang mbutuhake struktur data anyar kanggo pengenal unik, kita nggunakake maneh pengenal transaksi lan indeks output, disebut "outpoint", minangka pengenal unik kanggo jinis duwit receh. Mesthekake yen outpoints (36-bait) iku acak lan global unik.
Instruksi pemrograman, sing diarani OP_PUSHINPUTREF
, digunakake kanggo masang referensi menyang output. Instruksi kasebut nampa persis siji parameter 36-bait sing kudu cocog karo 1) titik metu saka salah sawijining output sing digunakake, utawa 2) nilai 36-bait sing padha wis katon ing OP_PUSHINPUTREF
sing wis ditemtokake ing salah sawijining output sing digunakake. Cara mung kanggo nilai tartamtu kanggo katon ing output transaksi liwat sawetara transaksi leluhur, Nilai cocog titik metu saka transaksi basis aset minting dhisikan. Transaksi sing nemtokake nilai sing ora cocog karo kondisi apa wae ora sah.
Diagram 5. Pengenal seng unik diinisialisasi kanthi cocog karo titik metu saka salah sawijining output sing digunakake, lan banjur dijaga anggere paling ora siji output sing ditanggepi ngemot pengenal unik sing padha ing awak naskah.
Instruksi pemrograman prasaja iki nyedhiyakake pengenal unik sing bisa digunakake minangka referensi stabil kanggo nggawe aturan lanjut. Contone, macem-macem jinis dhuwit recehan, aset digital, saiki bisa gumantung ing jinis dhuwit recehan liyane. Amarga kabeh data lokal kanggo transaksi, liwat transaksi input wong tuwa langsung, gampang kanggo klien lan layanan kanggo validasi keaslian aset digital ing wektu lan papan O (1) konstan, ngindhari kabutuhan layanan sing dipercoyo.
Sampeyan bisa ngasilake pengenal unik kanthi cara alternatif lan uga nyedhiyakake mekanisme kanggo bukti induksi matematika [5] nggunakake algoritma transaksi hash sing diowahi. Kanthi ngidini skrip input nampa transaksi wong tuwa sing wis dileksanakake, aturan bisa verifikasi manawa wong tuwane, lan simbah, cocog karo syarat aturan kasebut. Masalah ketok iku minangka saben salinan lengkap saka transaksi tiyang sepah ditempelake bledosan ukuran eksponensial ana lan ngalangi nggunakake praktis saka technique. Apa sing dibutuhake yaiku cara kanggo ngompres transaksi, supaya struktur data ukuran tetep bisa digunakake kanggo ngasilake hash transaksi, tinimbang mbutuhake isi transaksi lengkap.
Diagram 6. Validasi transaksi induk seng lengkap, bukti induksi matematika kanthi ngetik transaksi induk seng lengkap menyang input sing nyebabake paningkatan eksponensial ing ukuran transaksi.
Kita bisa nindakake iki kanthi ngowahi algoritma hash transaksi sing digunakake ing Bitcoin, ing ngendi intisarine sha-256 seng gandha diitung saka transaksi serial, menyang versi anyar sing pisanan ngringkes isi transaksi kanggo nurunake hash. Kita ngenalake versi 3 saka algoritma hash transaksi, kanggo mbedakake saka versi 1 lan 2 sing digunakake ing Bitcoin. Proses kasebut minangka ciri saben lapangan, utawa komponen transaksi, dadi hash perantara, sing bisa digunakake minangka input ukuran tetep lan kanthi mangkono ngindhari pertumbuhan ukuran transaksi eksponensial.
Kita nggunakake struktur data 112-bait ing ngisor iki, tinimbang bita transaksi serialized lengkap, kang siji pindho sha-256 hash kanggo pungkasanipun njaluk hash transaksi.
Pragambar Hash Kolom Transaksi Versi 3:
nVersion(=3) transaksi (4 byte little endian)
nTotalInputs (4 byte little endian)
hashPrevoutInputs (hash 32 byte)
hashSequence (hash 32 byte)
nTotalOutputs (4 byte little endian)
hashOutputHash (hash 32 byte)
nLocktime transaksi (4 byte little endian)
Nggunakake algoritma hash transaksi kanggo versi transaksi ke 3 (ketigo), kita bisa nampilaké transaksi tiyang sepah lan simbah ing saben langkah saka bukti prabawa matématika kanggo nyegah Tambah ing ukuran transaksi, lan bisa aplikasi sembarang aturan yen perlu.
Diagram 7. Validasi transaksi induk sing dikompres, bukti induksi matematika kanthi nanem struktur data preimage hash transaksi versi 3 saka wong tuwa lan simbah kanggo ngetrapake aturan lan kendala sing sewenang-wenang
Topologi jaringan minangka grafik sing meh lengkap, ing ngendi saben Node Pertambangan disambungake karo saben Node Pertambangan liyane. Langkah-langkahe kanggo mbukak jaringane padha karo Bitcoin, kanthi sawetara beda kanggo macem-macem jinis simpul: Node Pertambangan, Node Agen, Node Arsip. Node Pertambangan minangka penerbit blok aktif lan njaga konsensus karo kabeh simpul liyane, Node Arsip iku nglayani riwayate data pemblokirane, lan Node Agen dirancang kanggo nyaring blok lan nglacak transaksi kapentingan kanggo aplikasi sing dilayani. Arsip lan Agen Node bisa beroperasi ing jaringan peer-to-peer sing padha nanging ora ngasilake blok. Node Non-Mining kayata Arsip lan Agen Node kadhangkala diarani minangka "node seng ngrungokake" kanggo mbedakake peran ing jaringane.
Diagram 8. Node Mining disambungake kanthi apik lan dibangun ing ndhuwur blok masing-masing. Node arsip nyimpen blok lengkap kanggo analisis historis lan tujuan bootstrap. Node agen minangka simpul pamireng sing nyaring lan nyimpen transaksi kanggo nglayani klien.
Node Pertambangane disambungake kanthi luwih apik menyang grafik sing meh lengkap ing antarane Node Pertambangan liyane. Tugase yaiku mbangun blok saben liyane lan njaga konsensus kanggo sawetara atus blok paling anyar, lan njaga set UTXO kanggo pencegahan belonjo kaping pindho..
Agen Node mung kudu nyimpen subset transaksine, contone jinis koin utawa aset digital seng tartamtu. Malah kanthi pamblokirane gedhe, Agen Node bisa kanthi cepet nyaring transaksine kanthi referensi tartamtu utawa pesenan byte, banjure nyimpen transaksi kasebut kanggo dilayani liwat antarmuka programmer aplikasine. Antarane agen kerja sama, Akar Wit Merkle seng muat hash bisa diumumake sacara umum kanggo transaksi ing saben blok sing cocog karo pola sing wis ditemtokake kanggo menehi sinyal menyang Agen lan konsumen liyane sing transaksi wis diproses Agen.
Node arsip digunakake kanggo nggawe salinan serep kabeh blok kanggo macem-macem aplikasi kalebu gudang data, analytics, lan pembelajaran mesin. Amarga Node Arsip ora langsung melu pertambangan, dheweke ora duwe kinerja wektu nyata lan syarat bandwidth sing padha karo Node Pertambangan utawa Agen.
Kita nimbang skenario ing ngendi jaringan Radiant terus berkembang lan apa sing dibutuhake kanggo syarate pangolahan Node Pertambangan, Arsip lan Agen. Ing comparison, ing wektu nulis, ana kira-kira 83 yuta output transaksi unspent kanggo pamblokiran Bitcoin, total watara 6 GB data dibutuhake kanggo nyegah pindho mbuwang. Mung mbutuhake sawetara atus blok paling anyar disimpen dening Mining Nodes, kanthi blok lawas sing kasedhiya saka Arsip Nodes. Kanggo Agen Nodes, penting kanggo njaga partisi sing cocog kanggo output transaksi sing ora digunakake sing ana gandhengane karo aplikasi sing dilayani, skala minangka fungsi bandwidth lan dudu syarat panyimpenane.
Kanggo tujuan kita, kita nganggep bakal ana blok 3GB saben 5 menit sing bakal diwenehi tandha wektu lan disebarake ing jaringan, utawa kira-kira 20.000 transaksi per detik kanthi ukuran transaksi rata-rata 500 bita, utawa kira-kira 6.000.000 transaksi saben blok. Kita nuduhake manawa kanggo saben jinis simpul, jaringan bisa cukup kanggo nyukupi kabutuhan global. Iki padha karo kira-kira 1 transaksi saben 5 dina kanggo saben 8 milyar wong ing planet iki.
Node Mining minangka siji-sijine jinis simpul sing dibangun ing ndhuwur blok masing-masing. Kanggo njaga konsensus, cukup kanggo nyinkronake blumbang output transaksi sing ora digunakake (UTXO), lan nahan mung atusan blok pungkasan. Ing wektu nulis, kinerja dhuwur komoditas solid-state drive saged liwat 120.000 IOPS, biaya watara $500 USD kanggo 280 GB, lan mulane bisa nangani bab 20.000 transaksi per detik (assuming saben transaksi duwe 2 input lan 2 output). Ana 2 maca kanggo input, 2 nganyari kanggo input, lan 2 nulis kanggo output anyar: 120.000/6 = 20.000 transaksi/detik.
Node arsip nyedhiyakake data blok historis lan cocok kanggo aplikasi machine learning, analytics, lan data warehousing. Arsip Node bisa nglengkapi Bootstrap Mining Nodes lan kanggo mbukak mriksa konsistensi periodik ing set UTXO. Nalika nulis, drive komoditas 18 TB kasedhiya sekitar $350 USD. Yen 3 GB data saben 5 menit padha karo 732 GB kabutuhan panyimpenan data saben dina, utawa watara 22 TB saben sasi. Biaya hardware kanggo setahun yaiku 15 drive, kanthi kapasitas 18 TB, kanthi biaya tambahan $5,000 USD.
Agent Nodes skala paling gampang saka jinis simpul amarga mung ngolah jinis transaksi sing cocog kanggo aplikasi sing dilayani. Akibaté, Agen Nodes bisa saka server web nganti piranti IoT sing entheng kanthi kemampuan pangolahan lan panyimpenan winates, nalika tetep sepi ing blok 3GB, utawa 20.000 transaksi per detik. Contone, perusahaan bisa uga pengin nglacak panggunaan poin kesetiaan, digawe minangka aset digital, lan mulane mung kudu milih sawetara nganyari transaksi saka saben blok sing cocog karo pengenal unik kanggo jinis koin kasebut.
Nalika nulis, piranti komputasi komersial, Raspberry Pi 4, didol udakara $ 275. Nduweni prosesor quadcore 1,5 GHz lan 4 GB RAM, sing ngidini kanthi cepet nyaring, lan mbuwang transaksi sing ora relevan, kanthi tingkat saka 5.000 transaksi saben inti. Mesthine, iki mung minangka conto babagan carane ngolah blok gedhe, ing aplikasi web sing khas bisa uga ana luwih akeh inti sing kasedhiya.
Kacepetan bandwidth rata-rata ing 25 negara paling dhuwur ngluwihi 100 MBPS, utawa udakara 10 MB/s download, kanthi akeh panyedhiya layanan internet sing nawakake undhuhan tanpa wates. Kebutuhan bandwidth kanggo blok 3GB saben 5 menit sekitar 10MB/s kanthi total 22TB saben wulan. Hierarki Agen Node uga bisa digawe kanggo nyaring total bandwidth syarat kanggo Agen Node kanthi kapasitas bandwidth sing luwih murah.
Kita wis ngusulake sistem manajemen aset digital tanpa ngandelake kepercayaan. Kita wes miwiti karo blok bangunan dhasar saka koin sing digawe saka tandha digital, sing nyedhiyakake kontrol kepemilikan sing kuwat. Saka aturan lan insentif sing dibutuhake, kita ngenalake rong cara anyar kanggo keasliane lan nglacak aset digital ing wektu lan papan O (1) konstan. Kaloro cara kasebut kanthi mandiri nyedhiyakake sistem bukti induksi matematika umum sing bisa ngode konfigurasi aset digital. Sistem Turing Lengkap ing lan ngliwati wates transaksi, tanpa perlu lapisan sekunder. Radiant minangka desain terobosan sing nyedhiyakake keuntungan kinerja lan paralelisme saka pamblokiran output transaksi sing ora digunakake (UTXO), nanging kanthi kemampuan kontrak blokade adhedhasar akun adhedhasar Ethereum Virtual Machine (EVM).
[1] Satoshi Nakamoto, URL "Bitcoin: Sistem Uang Elektronik Peer-to-Peer" https://bitcoin.org/bitcoin.pdf, 2009.
[2] Vitalik Buterin, "Ethereum: Kontrak Cerdas Generasi Berikutnya dan Platform Aplikasi Terdesentralisasi." URL https://ethereum.org/en/whitepaper/, 2014.
[3] Kontributor Wikipedia. "Turing kelengkapan." Wikipedia, ensiklopedia gratis. Wikipedia, Ensiklopedia Gratis, URL https://en.wikipedia.org/wiki/Turing_completeness, 21 Juli 2022
[4] RC Merkle, "Protokol untuk kriptosistem kunci publik," Dalam Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, halaman 122-133, April 1980.
[5] Britannica, T. Editor Ensiklopedia. "induksi matematika." Ensiklopedia Britannica, URL https://www.britannica.com/science/mathematical-induction, 2018
Pay to ref is a powerful new script built using Radiant's unique induction proof system. This script provides a way of composing contracts from multiple outputs, introducing efficiencies and flexibility previously very difficult on UTXO based blockchains.
The above script uses OP_REFTYPE_UTXO
to take a given ref from the stack and return the type of any ref found in the transaction's inputs. If the returned value is not equal to zero then we know the ref has been found in the inputs. We can check for any ref type or a specific type.
OP_REFTYPE_UTXO
returns one of the following:
0 - Ref not found in inputs
1 - Ref found in inputs, of normal type
2 - Ref found in inputs, of singleton type
This script can be used to break a contract up into multiple parts. For example a complex NFT contract, split into a token contract and ownership contract:
The above contract is composed of two outputs. A singleton ref has been assigned to each output. The first UTXO can only be spent if the second "control" UTXO is also an input.
We can now handle token transfers using only the P2PKH output and not have to touch the rest of the contract. Since the token contract doesn't contain the P2PKH script, only a pay to ref, it is automatically carried forward with the transfer. For wallets to support transfers of this token, they only need to handle a simple singleton + P2PKH script and not be concerned with custom functionality or parsing custom contract templates.
DIAGRAM
The two singletons are best created as a contiguous set, so if any script needs to read from another part of the contract, it can check for the existence of a ref within its own set to verify the authenticity of the input. This also makes it easy for wallets to find all parts of the contract.
In this example we have only used two outputs, but this can be extended to compose contracts from three or more outputs.
Another powerful use case is to extend a contract's functionality by permitting the UTXO to be spent alongside one of a range of refs. These contract extensions can be defined at a later date, providing a way of upgrading contracts or adding new functionality.
The developer must plan this in advance, by keeping some refs in reserve, coded into the contract so they can be deployed and distributed to users later.
For example, a contract that allows locking conditions to be delegated to an input containing any ref from a specific transaction hash. The ref index is provided as a parameter in the unlocking script:
The above script takes a ref index from the unlocking script, appends to the transaction ID to construct the ref and checks if the ref exists in an input.
Care must be taken to ensure the user remains in control of their coins and complete control is not given over to the developer. Requiring the owner's signature will ensure the developer cannot spend the coins.
The Radiant Developers
August 11, 2022
radiantblockchain.org
The Radiant network is a peer-to-peer digital asset system that enables direct exchange of value without going through a central party. The original Bitcoin[1] protocol provides what is needed to create a peer-to-peer electronic cash system, but lacks the ability to verify transaction histories and therefore cannot be used to validate digital assets. Digital signatures and output constraints provide part of the solution, but the main benefits are lost if a trusted third party is still required to validate digital assets. The Radiant network itself requires minimal structure, and operates similiarly to the Bitcoin network in timestamping transactions into an ongoing hash-based chain of proof-of-work. We introduce two techniques to validate digital assets using a general purpose induction proof system that operates in constant O(1) time and space. The induction proof system makes it possible to efficiently compose outputs in any manner, without compromising the inherent parallelism and scalability characteristics of the UTXO based architecture. Users can leave and rejoin the network at will and be assured of the integrity and authenticity of their digital assets.
Commerce with blockchains and digital ledgers has come to rely on issuers and custodians serving as trusted third parties (sometimes referred to as "bridges", "oracles", "secondary layers") to authenticate digital assets and process electronic payments. While the system works well enough for electronic payment-like transactions, it still suffers from the inherent weaknesses of the trust based model for more advanced usages of the blockchain. The high costs of transactions associated with Ethereum Virtual Machines (EVM) based blockchains is due to the limited block space and the inherent limitations of the account based model of processing.
What is needed is an electronic payment system that can also act as a digital asset management system with the performance characterstics of an unspent transaction output (UTXO) blockchain architecture, with the flexibility of an account based blockchain. In this paper, we propose a solution to the problem of blockchain scaling using two novel methods which, independently, provide a general induction proof system capable of authenticating digital assets, emulating account based blockchains, while maintaining the performance characteristics of a UTXO based blockchain such as unbounded scale and parallelism.
The original Bitcoin[1] protocol provides what is needed to create a peer-to-peer digital asset system, but lacks the ability to verify transaction histories and as a result cannot authenticate digital assets. Blockchains such as Bitcoin Cash (BCH) and Bitcoin Satoshi Vision (BSV) attempt to authenticate digital assets via trusted third parties called "oracles" which indexes the relevant transactions. Such solutions, however, prevent the possibility of advanced blockchain contracts since a trusted custodian is required. In order to solve the problem of digital asset authenticity, without using central parties, we introduce two novel methods that operate in constant O(1) time and space. The additional programming instructions creates a general purpose induction proof system. Users and applications need only to verify that the latest digital asset transfer is accepted into a block.
Radiant is the first unspent transaction output (UTXO) blockchain that solves the key problems that prevented the development of advanced contracts on other blockchains such as Bitcoin, Cardano, and Dash. This breakthrough design revolutionizes what we imagined to be possible with blockchains; Radiant is a Turing Complete high performance layer one blockchain with no need for secondary layers.
There are three problems which make it impractical to use unspent transaction output (UTXO) blockchains as a general purpose digital ledger. The first problem is the ability to arbitrarily constrain the spend conditions — or forward conditions on all descendant transactions. The second problem is how to efficiently authenticate transaction outputs to ensure they originate from a valid genesis transaction — this is an essential requirement for many programs, especially to emulate accounts and create fungible tokens. The third problem is coordination and collaboration between contracts — precise control of message passing between transaction outputs. We will show that all three problems can be solved without compromising performance or the scalability of the UTXO-based blockchain model.
The first obstacle to programming with an unspent transaction output (UTXO) blockchain was a misunderstanding of Satoshi Nakamoto's original design and programming codes available in the original Bitcoin protocol. It is not generally acknowledged but the original Bitcoin blockchain had all of the programming codes necessary for Turing Complete [2] smart contracts. The necessary programming codes were removed from the protocol in the BTC upgrades of 2015.
The method to impose constraints on spending conditions is to restore all of the original programming codes from Bitcoin and to provide a method to inspect the current transaction context. There are two ways to inspect the current transaction as a type of introspection. The first way is to push the Signature Hash (known as the "SigHash Preimage") onto the stack and use a temporary private key to generate a signature and then apply the OP_CHECKSIG
operation to validate that the expected SigHash Preimage for the current transaction is valid. The second way is to provide native introspection programming codes that push the relevant transaction component onto the stack for use in the unlocking script.
The key difference with a UTXO blockchain is there are no loops in the programming codes. However in practice any repetition can be simulated with unrolling the loop operations and replicating the logic for the necessary maximum number of repetitions. In this manner, UTXO blockchains can avoid any concept of "execution time cost" and instead estimate the execution cost by using only the transaction script size. For this reason, it is recommended that UTXO blockchains have a sufficiently large maximum transaction size, such as 2 megabytes or more to be able to accommodate any use cases that may need dozens or hundreds of loop iterations.
An electronic coin is defined as a chain of digital signatures. A coin begins at a genesis transaction called a "coinbase" transaction. To transfer a coin, the owner of the unspent output signs the coin with their private key and locks the tokens in a new output which is associated with the public key of the recipient. At each transaction a new transaction identifier and output index is used, which is globally unique. The concept of a "wallet balance" for a user is the sum total of the nominal token units controlled by the user for the unspent outputs for their corresponding public keys. Each coin in essence is uniquely identified by it's most recent unspent output. There is no inherent concept of an "account" or "coin identity".
In unspent transaction output (UTXO) blockchains the native token unit is the only class — or type and therefore a unique persistent coin identity is not neccesary. It is sufficient to have a different UTXO identity to enumerate the coins that can be spent. However, if we wish to create a different class of tokens, in other words to "color" the native tokens to represent shares, points or any other enumerable type, then we need a way to represent and efficiently validate token class membership. The term "colored coins" have been used to describe an overlay network which mints tokens from a special genesis or minting transaction — similar to the native coin is emitted from a coinbase.
A custom (or colored) digital coin is defined as a chain of digital signatures anchored at a user defined genesis output. Users may mint or create a custom coin issuance by depositing the desired number of native token units at the output and designating it as a coinbase with 36's 0x00 null bytes as the first push data of the output. The contract logic is constrained such that the subsequent spend of the output must embed the outpoint (transaction id, output index) of the genesis transaction into the first push data (where the 36 0x00 null bytes were in the genesis transaction) for the entire lifecycle of the colored coin. Following this convention combined with the contract constraints, we can see that this tecnique effectively "colors" the native token and can be identified unambiguously. Additional logic can be added according to the application needs such as how the coins are redeemed or returned back to their native token units. For example the issuer can perform the operation or the token holder can "melt" out the native token unit and effectively destroy the color classification. The technique of embedding the genesis output forms a globally unique identifier sometimes referred to as asset identifier (or assetId for short) or contract identifier (or contractId for short) that may now be used to identify the coins that belong to that coin class. This identity will form the basis of the advanced usages outlined below.
There is an outstanding problem however: How can spending transactions ensure that only coins descended from the rightful genesis transaction can be spent and not passed off into spending a forgery that was merely copied?
Recall that an unspent transaction output (UTXO) has no persistent identity, but we can give a persistent identity by following the rule that a user may designate some transaction as a genesis minting event, where the outpoint stands in as the assetId or contractId. However, using this convention it is not sufficient because an attacker can copy one of the intermediate transaction spends and begin a new (albiet forgery) chain of signatures to spoof a coin class and pass it off. Any spending transaction are unable to differentiate between a real output that originated as a valid descendent versus the forgery from a false copy. What is required is a way to enforce global uniqueness that is unobtrusive and efficient to verify inside a spending script.
We define the programming operation code (OP code) OP_PUSHINPUTREF <hash>
is defined as valid accordingly:
An OP_PUSHINPUTREF
may appear only in an output and requires exactly 36 bytes immediately after that is treated as a push onto the stack in interpretor context.
The transaction containing an output with a OP_PUSHINPUTREF
is valid if and only if the provided argument is equal to one of the inputs' outpoints being spent or at least one of the inputs' output locking script bytecode also contains the same OP_PUSHINPUTREF
argument value.
The only way an OP_PUSHINPUTREF
can first apppear in an output is if the first occurrence is equal to one of the inputs outpoints being spent. In the case of using the above "Persistent Contract Identity", this corresponds to the transaction that contains the 36 0x00 null bytes signifiying a genesis minting coinbase for a custom (colored) coin class.
We demonstrate that this simple rule is sufficient to form a globally unique identifier, and carries no overhead — as in no extra indexes or lookup tables are required. Only a transaction and it's immediate parent inputs are needed to validate authenticity — all of the data is available to the virtual machine at the time of the unlocking script evaluation and also into accepting the transaction into the mempool and subsequently into a block.
As long as at least one of the input coins has a valid 36 byte hash — either as the outpoint itself (significanty the first genesis chain of the colored coin) or as one of the scripts containing the reference, then the identity exists as a persisted identity. To terminate the lineage, simply omit passing on the reference and that terminates the ability to use that unique identifier in any other UTXO forever.
Although this single OP code is sufficient, there are a handful of additional OP codes that provide flexibility for the programmer and are described next which complement OP_PUSHINPUTREF
.
The OP_REQUIREINPUTREF
functions identically to OP_PUSHINPUTREF
except it does not pass on the reference identity to the output in which it appears. This is useful for demanding that at least one input is of a specific coin class — but without passing down the reference immediately.
To disallow the use of a OP_PUSHINPUTREF
in an output, the OP_DISALLOWPUSHINPUTREF
may be used. This is a useful OP code for smart contracts which leave open the outputs to be used in various contexts, but allows the contract creator to restrict passing down a reference, for example in custom change outputs.
Similar to OP_DISALLOWPUSHINPUTREF
, disallow specific outputs in any sibling outputs for the specific reference. This effectively prohibits using a reference in more than one output and is a way to create a singleton outpoint. By using OP_DISALLOWPUSHINPUTREFSIBLING
in an output we can create a simple and powerful Non-Fungible Token (NFT) contract which functions with SIGHASH_SINGLE
signature flag.
Provides a summary of the contents of an output being spent in the current transaction. Takes the top element of the stack which is the index of the input being spent and then pushes the hash256 of the information about the UTXO being spent: hash256(<nValue><hash256(scriptPubKey)><numRefs><hash256(sorted_list(pushInputRefs))>)
. During unlocking script evaluation, the relevant data of an UTXO is able to be accessed and incorporated into the logic.
This programming code accepts a hash256 of the 36 byte reference and pushes onto the stack the sum total of all of the inputs that matches that reference coloring. This is useful for saving data and for quickly assessing the total inputs and the values input to the transaction.
This is very useful for building a compact fungible token accounting system as we shall see below.
Another method for solving the traceability and authenticity problem is to allow the embedding of the parent transaction into an unlocking script. In this manner, we can perform induction proofs and guarantee that a transaction output originated from a valid genesis minting event.
The general principle in mathematical induction is to prove that some statement P(k) holds for k = 0, k = 1, k = 2... and so on that generally P(k) holds for P(0) and P(k + 1).
In the case of smart contracts, we wish to prove that a given transaction is valid in the base case, as in it descends from valid parent, the base case P(0), and in the inductive case that the grand parent also satisfies the condition, which is the P(k + 1) step.
With an induction proof it is impossible to forge an intermediate transaction because the grand parent transaction will not be of the required origination.
This system is not practical however because each time the output is spent a full copy of the parent (and it's parent) transaction must be embedded to calculate the transaction identifier. This leads to a factorial, or exponential, explosion in transaction size. It is not practical since after only about a dozen spends, the transaction size starts to exceed 1 GB and continues growing exponentially.
To solve this problem of exponential transaction size growth we leverage the "nVersion" field provided by the transaction format. Bitcoin has version 1 and version 2 transactions already and we simply create a version 3 that uses a different transaction identifier generation algorithm instead of hashing the entire bytes of the transaction. The version 3 transaction format is identical except the transaction id is generated from an intermediate fixed size data structure that compresseses the transaction contents into a preimage — that can be embedded in locking scripts to derive the transaction id and avoid the exponential transaction size problem.
Similar to the Signature Hash algorithm which generates a "Sighash Preimage", we produce a TxId preimage according to the following components and fields of a transaction.
nVersion of the transaction (4 byte little endian)
nTotalInputs (4 byte little endian)
hashPrevoutInputs (32 byte hash)
hashSequence (32 byte hash)
nTotalOutputs (4 byte little endian)
hashOutputHashes (32 byte hash)
nLocktime of the transaction (4 byte little endian)
Diagram 14. Transaction Identifier Version 3 Preimage\
By incrementing the nVersion field, we introduce a way to compress an entire transaction into a fixed size (128 bytes) that can be pushed onto the stack, and hashed to arrive at the Transaction identifier, and therefore solving the problem of exponential size increase from from the embedded parent transactions in the induction proofs.
Notice that this system itself is sufficient to create arbitrary induction proofs and is general purpose. This is a second method in which arbitrary induction proofs may be created in addition to the already discussed OP_PUSHINPUTREF
technique.
Building on the Transaction Id preimage the technique of segmenting the outputs, we can upgrade the default Sighash algorithm with an additional field called hashOutputsHashes
to make it easier to constrain the outputs and save space and logic.
nVersion of the transaction (4 byte little endian)
hashPrevouts (32 byte hash)
hashSequence (32 byte hash)
outpoint (32 byte hash + 4 byte little endian)
scriptCode of the input (serialized as scripts inside CTxOuts)
value of the output spent by this input (8 byte little endian)
nSequence of the input (4 byte little endian)
hashOutputsHash (32 byte hash)
hashOutputs (32 byte hash)
nLocktime of the transaction (4 byte little endian)
sighash type of the signature (4 byte little endian)
Diagram 16. Radiant Signature Hash Preimage Fields.
This is useful because the other sibling outputs do not need to be included and a hash can be used for the outputs that are not of interest. There is still the color of the push references so that we can assert whether the other outputs contain a valid color, but without requiring the full script to be pushed.
With the OP_PUSHINPUTREF
and TxId Version 3 constructs, we are in a position to define various contract collaboration design patterns. together these patterns will be used in account emulation, non-fungible tokens (NFTS), fungible tokens (FTs) and other programs.
Definition: A "Non-Fungible Token" is a uniquely-identified object in which it’s essential properties are conserved
We present a simple, yet powerful, design pattern called a Non-Fungible Token (NFT). Programs will recognize this by another name called a Singleton object. An NFT, or Singleton, guarantees that only one instance of an object can ever exist and is unique identified by a stable persistent identity. Most usages of the term Non-Fungible Token have centered around digital collectibles, however that need not be the case — the reason for that focus has to do with the high-gas fees on Ethereum and the speculative nature of digital artwork.
In the Radiant blockchain, we use the term Non-Fungible Tokens to refer to a uniquely identifable object, or colored coin, which maintains some essential properties in addition to being unambiguously traceable through the blockchain. This is a basic building block and design pattern that will appear in more complex contracts, and here we present a simple, yet very powerful, construction below to start.
Non-Fungible Token Pseudo-code:
Diagram 19. Non-Fungible Token Pseudocode
Definition: An "Account" is an object that manages a wallet balance while maintaining an addressable stable unique identifier.
One of the main difficulties in working with a UTXO-based blockchain is there is no protocol level concept of "wallet balance", and instead infrastructure providers and wallet services present a summary balance derived from the total value of all the individual outputs controlled by a key. Account-based blockchains also simplify specific types of problems and contracts, but trade-off performance and privacy to achieve it's aims.
We present a simple design pattern to emulate accounts using one or more outputs which gives the user and developer a stable unique identifier across transactions in the blockchain. It is built using the Non-Fungible Token design pattern, and demonstrates that UTXO-based blockchains are perfecty equipped to emulate accounts with the same level of control, but with much higher performance characteristics.
Recall that in the Non-Fungible Token design pattern, the stable identifier ContractId (also sometimes referred to as AssetId) is derived from the outpoint of the minting transaction. The same ContractId is used as the public account identifier and can be treated as a wallet balance. We present below pseudo code for a smart contract that implements all the method associated with accounts: deposit, withdraw, changeOwner, and close the account.
Diagram 20. Account contract pseudocode
The Fungible Token design pattern allows the same class or type of object to have more than a quantity of one. The fungible tokens can be merged together, with their values summed up into a new output, or an output can be split into two or more outputs where the total sum of the outputs is equal to the input value amount. This design pattern is useful for simulating loyalty points, tokens, and more.
We present the solution:
Radiant is a peer-to-peer digital asset system with unbounded scaling as a UTXO-based blockchain with all the flexibility and power of account-based blockchains.
Network Name: Radiant Network Abbreviation: RXD Mining Algorithm: SHA512/256 Proof-of-work Block Time: 5 minutes Initial Block Size: 128 MB, designed to achieve 10GB+ Block Reward Schedule: 50,000 RXD per block Block Reward Halvening: 2 years Maximum Supply: 21,000,000,000 RXD Decimal Places: 8 Launch Date: 2022-06-21 02:42 UTC\
We have proposed a system for digital asset management without relying on trust. We started with the basic blockchain construction of coins made from digital signatures, which provides strong control of ownership. From the needed rules and incentives, we introduced two novel methods for authenticating and tracking digital assets in constant O(1) time and space. Both methods independently provide a general induction proof system which can encode any possible digital asset configuratio. The system is Turing Complete within and across transaction boundaries, with unbounded scale, and never any need for secondary layers. Additionally we have presented three contract design patterns: Non-Fungible Token (NFT), Fungible Token (FT) and Account which emulating account based blockchains, using the UTXO based processing model. Radiant is a breakthrough design which provides the performance and paralellism benefits of an unspent transaction output (UTXO) blockchain, and with the programming sophistication of account-based blockchains, while maintaining ultra low fees and unbounded scale.
Radiant (or RXD) is a peer-to-peer electronic cash system. It uses a blockchain to distribute its ledger over a network of independent nodes so that there is no single point of failure, and no central control that might be compromised. It uses a consensus algorithm called Proof-of-Work that allows these independent nodes to approve correct transactions and reject malicious ones.
The blockchain is a data structure that is distributed over a number of independent nodes. It derives its name from the chain of blocks that it uses to store its data. All blocks include a block header with some metadata and the root of a Merkle tree - a special kind of tree that allows quick validation of data. This Merkle tree is then used to store the actual data inside these blocks. To make the chain resistant to manipulation, block headers also include a timestamp and a hash of the previous block.
Radiant and many other public blockchains use a consensus algorithm called Proof-of-Work (PoW). This algorithm works by attaching a nonce to every block header and changing this nonce until the hash of the block header matches a certain prefix. This process is called mining, and is attempted by many nodes at the same time, until one of them has found a correct solution. One of the attributes of this algorithm is that mining is very expensive, but other nodes can verify the solution very quickly.
Mining is also the process by which new coins are introduced to the total monetary supply. Miners validate transactions and secure the network, for which they are paid new coins - called the block reward - in a special transaction called a coinbase transaction. The high cost of the mining process attaches a financial risk to incorrectly validating transactions. At the same time the block reward attaches a financial reward to correctly validating transactions. This process ensures that the mutually distrusting nodes can collaborate to validate transactions.
Radiant transactions are created using chunks of RXD called transaction outputs. When these outputs are available, they are called Unspent Transaction Outputs (UTXOs). UTXOs are locked using a locking script (or scriptPubKey
) that specifies the conditions to spend the UTXO. When attempting to spend a UTXO, an unlocking script (or scriptSig
) is provided. These scripts are then executed together and the transaction is only valid if the scripts execute without errors and the resulting value is TRUE
.
The most used locking/unlocking script pattern is called Pay-to-Public-Key-Hash (P2PKH), where the locking script contains the hash of a public key and expects the unlocking script to contain a public key and transaction signature. The locking script then checks that the provided public key matches the stored hash, and that the transaction signature is valid. This pattern is used in regular Radiant wallets. And the user's balance is simply the sum of all UTXOs that can be spent by the user's public keys.
UTXOs are used as inputs to Radiant transactions and produce new UTXOs as outputs. UTXOs need to be spent in their entirety within a transaction. So whenever the user wishes to use a 10 RXD UTXO to send someone 1 RXD, they need to send 9 RXD back to themselves. Realistically, part of the funds would be reserved for transaction fees as well.
Most smart contract innovation has happened on Ethereum, but other platforms like Bitcoin and Radiant have some support for smart contracts as well. Smart contracts on every platform work differently, and the main differences between smart contracts on Ethereum and Radiant is that smart contracts on Ethereum are stateful, while those on Radiant are stateless.
This means that Ethereum contracts can record and update variables, while the variables in Radiant contracts are immutable.
The locking and unlocking scripts of regular transactions and smart contracts on Radiant are written using Radiant' transaction scripting language, creatively named Script. To avoid ambiguity, it can also be referred to as Bitcoin Script or Radiant Script. Script is a stack based assembly-like language that is intentionally not turing complete as its main use is the validation of programmable money, not general purpose computing.
Script is stateless, meaning it only uses the information contained within the locking and unlocking scripts themselves. This statelessness means that a Script can be deterministically validated on any machine. This gives increased performance and predictability, although it does limit the usefulness of the scripting language.
TODO
This is a guide to the Glyphs Protocol on the Radiant Blockchain.
Glyphs is a token standard utilizing Radiant's induction proof system and advanced scripting capabilities. Each token is identified by a Radiant reference (ref) and uses smart contracts for enforcing token transfer rules. Glyphs is a fully layer one protocol with all rules enforced by miners.
The Glyphs protocol operates efficiently with minimal indexing requirements, not requiring wallets or indexers to track each token transfer back to the mint. This allows wallets to efficiently verify tokens using SPV. This makes Glyphs a more secure, efficient and scalable system than layer two alternatives.
The protocol supports both fungible and non-fungible tokens. Fungible tokens use Radiant photons as the unit of account, with each fungible token backed by one photon. NFTs may be backed by any number of Radiant photons.
Token contracts are simple, concise and extensible, allowing composition with other custom contracts to support many complex use cases.
Glyphs is currently implemented in Photonic Wallet (Web App and Browser Extension) and Glyph Miner.
Glyphs are implemented using Radiant's UTXO model and operate in a similar way to native Radiant photons. Radiant photons are "colored" with a Radiant ref which acts like a contract identifier for the token. A token is minted by creating a UTXO containing an amount of photons, a standard token contract and a Radiant ref. The contract along with the ref is carried forward with each spend. The contract and ref remain the same for the lifetime of the token, until it is melted.
With refs enforced by miners we can be certain a token is authentic simply by verifying block headers in the same way as native photons.
Glyphs are minted using a commit/reveal procedure with token metadata contained in the reveal transaction's unlocking script. The token's ref is created from an input to the reveal transaction. Therefore a glyph's ref will always point to a commit outpoint.
The token payload in the reveal transaction contains data such as name, image, ticker, relationships to other tokens etc.
The protocol does not dictate how the mint transaction should be created. Developers may use any locking script for the commit/reveal procedure, as long as the token payload is correctly encoded in the reveal.
For each ref that is required an input must be prepared. Radiant singleton refs are used for NFTs, so each NFT requires a unique ref.
When a wallet receives a token, it extracts the ref from the script and looks up the reveal transaction on the blockchain to obtain the token data.
For example, an NFT script:
The ref a32f3628a967ce64cca282262e63879136f9c3f4f8e1125345a85c71d90b10b401000000
refers to an outpoint in a commit transaction.
The reveal will be the transaction that spent this output, with a token payload contained in the unlocking script.
Radiant's implementation of ElectrumX has been improved to simplify the process of finding the reveal transaction.
Transferring is done in much the same way as native Radiant photons. For NFTs, the UTXO is spent and the script is moved to a new output. Fungible tokens are similar, except since they use normal refs instead of singletons, token UTXOs may be split and merged.
Any number of different tokens may be provided as inputs and outputs of a transaction. Token transfer rules are all implemented in script, with token input and output values summed within script, ensuring token supply is enforced. Token UTXOs may be positioned anywhere in a transaction's inputs and outputs and there is no restriction on the number of token UTXOs. The Radiant opcodes used to sum token values operate over any number of inputs and outputs.
Acquiring and holding RXD coins is a fundamental way to support the Radiant ecosystem. Your participation in the coin and token economy helps drive growth and stability. More holders and Radiant ecosystem participants can strengthen the lindy effect. Here's why buying RXD matters:
A glyph's token data is encoded in the reveal unlocking script, identified by the string "gly" followed by a CBOR encoded token payload:
The Glyphs protocol defines standard top level fields shown below in CDDL:
Example CBOR payload:
The p
property contains an array of protocols used by the token. Current protocol identifiers are as follows:
ID
Protocol
1
Fungible token
2
Non-fungible token
3
Data storage
4
Decentralized mint
5
Mutable
Some protocols may depend on other protocols also being implemented. For example for a mineable token, a p
value of [1, 4]
must be used, indicating the token implements the FT and dmint contracts.
In addition to the main
property other files can be added to the payload. These can be either embedded or remote.
Embed:
Remote:
Example:
If a link to a remote file is used, it is recommended to include a hash so the downloaded file can be verified.
For remote images a HashStamp may be provided in the hs
property. This is a low resolution, highly compressed copy of the image in WebP format. This may be desirable for people who want to store data off-chain but still have some representation of the file on-chain. It is recommended to keep HashStamps within 64x64 pixels and quality 20 to keep size to a minimum.
HashStamps can be used by wallets to display a version of the image if downloading the file is deemed insecure, or used as a loading placeholder similar to a BlurHash.
The Glyphs protocol uses types container
and user
, for allowing the creation of collections and associating tokens to a creator. Wallets should implement these types and render the tokens accordingly.
Custom types are also permitted.
Any custom fields may be added to the payload.
Fungible tokens must be created with the protocol p
field set to 1
. This informs wallets that the token uses a standard fungible token script.
The script is a P2PKH followed by a script to enforce fungible token rules:
The script after the P2PKH must be unchanged for every transfer.
The protocol permits locking scripts other than P2PKH, such as multisig, time locks and other more complex scripts. The only requirement is that the script after the state separator is unchanged.
Tokens are transferred in a similar way to regular RXD photons. The contract and ref are carried forward with each spend and UTXOs can be split and merged. Tokens may be at any position in the inputs or outputs. A transaction may also contain any number of different tokens.
The contract permits output value sum to be less than input value sum. Melting fungible tokens only requires making the output value less than input value. The RXD photons backing the tokens are then reclaimed.
Non-fungible tokens must be created with the protocol p
field set to 2
.
The script is simply a singleton ref followed by a P2PKH or other locking script:
Radiant rules enforce that there can only ever be one instance of a singleton ref.
NFTs are transferred in a similar way to regular RXD photons. The singleton ref is carried forward with each spend and may be at any position in the transaction inputs or outputs.
Similar to fungible tokens, any number of different tokens may be present in a transaction.
Melting a non-fungible token can be done in two ways:
Omit the ref from the outputs
Spend the NFT to an unspendable op return script containing the ref
The Glyph protocol provides in
and by
arrays in the token payload for defining relationships to other tokens, such as NFT collections. Relationships can also be defined in custom properties.
For a token to be related its ref must be present in the commit transaction. Wallets must verify this by checking each related token's ref is in an output of the commit. This prevents authorized users creating relationships, such as assigning an author or adding NFTs to a collection they don't control.
Having a related token in a commit is not always practical if there are many thousands of mint transactions with the same relationship. For example, minting a large NFT collection with the same container and author tokens. To solve this a token delegate may be used.
The delegate is a temporary normal ref that links to one or more token refs such as a user or container token.
A delegate is created by a transaction containing the related tokens, and one or more outputs with the following script:
Any number of delegates may be created to simplify bulk mints.
When a wallet does not find a related token's ref in the commit transaction, it must look for delegates within the commit script. Delegate refs must be required using a OP_REQUIREINPUTREF
opcode in the commit script.
If the wallet finds required refs, it fetches the delegate creation transaction and looks for related tokens in its outputs. If the refs are found in the delegate creation transaction then the relationship is valid.
Developers are free to define their own relationships separate to the in
and by
arrays.
Tokens may be linked to any resource, either tokens or off-chain resources. This has many uses such as creating a record of a token mint or even building a decentralized redirect service.
Links are created using the loc
field which is used by wallets in a similar way to the HTTP location header.
To create a link the loc
field is set to either a number, bytes or string:
number
- Link to a token with given output index and transaction ID matching the link ref
bytes
- Link to a token given as ref bytes
string
- Link to any URI
Token payloads can be made mutable by using a mutability contract and adding protocol 5
to the p
array in the token payload.
The mutability contract must be created in the mint transaction and assigned a singleton ref with an output index one higher than the token ref (token ref + 1).
The contract uses a "pay to token" script which does not contain a P2PKH or any signature checking opcodes. The contract requires the token to be present in the transaction in order to modify the payload.
Modify mod
and seal sl
operation are implemented. Seal is called to make the token immutable and enforces burning of the mutability contract.
With a "pay to token" script, the mutability contract is always controlled by the token owner. This means every time a token is transferred to a new owner, they automatically get access to updating the token's data. The mutability output never needs to be transferred, only called to update the data.
If a wallet receives a mutable token, the most recent data can be obtained by looking up the most recent location of the mutability ref and fetching the transaction. Data is encoded similar to a token mint, with the Glyph token payload in the unlocking script.
In order to use a "pay to token" contract securely, the data must be signed. Without a signature check opcode in the contract, this must be done in a different way.
The contract requires the token owner to provide the token as an input. In the token's output it must include a hash of the mutability contract's unlocking script. This way, the token owner signs the updated data in the token output, the contract verifies it, and the transaction is not vulnerable to malleation. In addition to the unlocking script hash, the output must have an OP_REQUIREINPUTREF
requiring the mutability contract as an input. This ref + hash pair is checked by the mutability contract.
To spend the contract the following parameters must be provided in the unlocking script
To authorize this update, the token output must have the hash of the above unlocking script following an OP_REQUIREINPUTREF
. For example:
The mutability contract will verify that the hash of the provided unlocking script, along with the necessary OP_REQUIREINPUTREF
are contained in the token UTXO.
An optional final step is for the token owner to restore the token script to a standard NFT contract that can be recognized by wallets. The OP_REQUIREINPUTREF
and hash are no longer required.
Decentralized mints (dmint) are mineable tokens that can be claimed by anyone using proof-of-work. These tokens are created with protocol [1, 4]
and are locked in a layer one smart contract.
With a "pay to token" script, the mutability contract is always controlled by the token owner. This means every time a token is transferred to a new owMineable Glyphs use the follow proof-of-work algorithm:
Resulting hash must be below the target.
anyInputHash
and anyOutputHash
must be the hash of any input or output in the transaction. This allows work to be bound to the miner's address and prevents nonces being stolen. This will typically be a pay-to-public-key-hash but any script can be used. The contract will verify these scripts exist.
Radiant's implementation of ElectrumX has modifications to support Glyphs.
ElectrumX indexes each script with the ref zeroed out. The zeroed ref acts as a wildcard meaning a wallet can fetch all transactions for an address by using a ref with 36 zero bytes in the token script.
For example:
This script is hashed and can be used with listunspent
and script hash subscriptions. This prevents having to perform many queries for each token ref or having to know token refs in advance.
A glyph ref will point to an outpoint in the commit transaction, therefore this alone cannot be used to fetch the token payload. To simplify this task, the ref.get
method will return the first and last locations of a ref.
The first location will be the reveal transaction. The last location is used to track the current location of a contract.
The listunspent
method is improved to return an array of all refs contained in the script. Since refs are zeroed when querying for tokens, the wallet does not know the token ref in the returned UTXOs and would need to query each UTXO individually to determine the token.
With refs returned as part of the listunspent
response, the wallet can build scripts without the additional queries.
Spanish version of the Radiant whitepaper
11 Agosto, 2022
radiantblockchain.org
Resumen. La red Radiant es un sistema de activos digitales entre pares que permite el intercambio directo de valor sin pasar por un ente central. El protocolo original de Bitcoin[1] proporciona lo necesario para crear un sistema de dinero electrónico entre pares, pero carece de la capacidad para verificar los historiales de las transacciones y, por tanto, no puede utilizarse para validar activos digitales. Las firmas digitales y las restricciones de salida proporcionan parte de la solución, pero las principales ventajas se pierden si se sigue necesitando un tercero de confianza para validar los activos digitales. Al igual que Bitcoin, la red Radiant requiere una estructura mínima, y marca el tiempo de las transacciones en una cadena de prueba de trabajo basada en hash. Introducimos dos técnicas para validar los activos digitales: referencias únicas y un sistema de prueba de inducción de propósito general, que funcionan en tiempo y espacio constantes de O(1). Es posible componer las salidas de cualquier manera, sin comprometer el paralelismo inherente y las características de rendimiento de una arquitectura basada en la salida de transacciones no gastadas (UTXO). Por lo tanto, los usuarios pueden salir y volver a entrar en la red Radiant a voluntad y estar seguros de la integridad y autenticidad de sus activos digitales.
Los blockchains comerciales, o tecnología de libro mayor digital (DLT), se suelen basar en emisores y custodios que actúan como partes de confianza para autenticar los activos digitales. Si bien estos sistemas funcionan lo suficientemente bien para las transacciones similares a los pagos electrónicos, siguen adoleciendo de las debilidades inherentes al modelo basado en la confianza para usos avanzados. Las cadenas de bloques basadas en la máquina virtual de Ethereum (EVM) [2] son muy flexibles para todo tipo de programas, pero las elevadas tarifas hacen que su uso para aplicaciones con micropagos sea poco práctico.
Lo que se necesita es un sistema de pago electrónico que se pueda utilizar para el sistema de gestión de activos digitales con tarifas bajas, alto rendimiento y capacidades de programación avanzadas. En este documento, proponemos una solución al problema del escalado en blockchain y al uso de contratos inteligentes, utilizando dos técnicas novedosas que proporcionan referencias únicas y un sistema de prueba de inducción general, que hacen posibles los programas turing completo [3] a través de los límites de las transacciones. El sistema propuesto es descentralizado, utiliza un mecanismo de consenso de prueba de trabajo como Bitcoin, pero con un rendimiento significativamente mayor, al tiempo que proporciona la misma flexibilidad que los blockchains basados en EVM, pero con tarifas muy bajas.
Al igual que Bitcoin, definimos una moneda electrónica como una cadena de firmas digitales. La diferencia de las transacciones en Radiant es que cada propietario transfiere la moneda al siguiente firmando digitalmente un hash de la transacción anterior, además de los parámetros de entrada necesarios para desbloquear la moneda. Una transacción también crea nuevas restricciones de bloqueo de salida, que pueden incluir la clave pública del siguiente propietario, entre otras reglas definidas por el usuario.
Diagrama 1. Transacciones en Radiant.
Para verificar que no se ha producido un doble gasto, utilizamos un servidor de marcas de tiempo distribuido, que utiliza un sistema de prueba de trabajo basado en hash para organizar el historial canónico y determinar qué transacción llegó primero. Las transacciones se organizan en bloques. Por convención, la primera transacción, llamada "transacción coinbase", en un bloque es una transacción especial que inicia una nueva moneda propiedad del creador del bloque. Los bloques se encadenan y organizan las transacciones en un árbol de Merkle [4]. Todas las transacciones, a excepción de la primera, deben hacer referencia a una transacción anterior formando un gráfico acíclico dirigido (DAG) en el que todas las monedas acaban conectándose de nuevo a al menos una de las transacciones especiales del principio de un bloque.
Diagrama 2. Estructura de Bloques; las transacciones se organizan en un árbol de Merkle.
El problema de este diseño, en el contexto de los activos digitales, es que sólo hay un tipo de moneda, o activo digital, y ningún concepto de monedas definidas por el usuario (o tipos de activos digitales). El diseño funciona lo suficientemente bien para las transacciones similares a los pagos electrónicos en la unidad de cuenta nativa, sin embargo, no se presta inmediatamente a ser utilizado para otros tipos de monedas o activos digitales. Una solución común es introducir un servicio, como un indexador de transacciones, que supervise las transacciones en busca de secuencias de datos especiales que signifiquen la creación de un activo digital. El problema de esta solución es que depende de la empresa que gestiona el servicio, y la autenticidad de los activos digitales debe ser de confianza, al igual que cualquier otro servicio en la web.
Necesitamos una forma para que los usuarios indiquen la creación de tipos de moneda personalizados, pero que no dependan de un servicio de confianza para la presentación de datos.
Definimos una moneda electrónica personalizada, o activo digital, como una cadena de firmas digitales. Un activo digital es un tipo de moneda definido por el usuario que utiliza un marcador de transacción especial, llamado transacción "assetbase", para crear o acuñar un activo digital. De forma similar a las transacciones de coinbase, que inyectan nuevas monedas en el sistema, la transacción de "assetbase" colorea o etiqueta la moneda electrónica con un identificador único de 36 bytes para toda su vida. La moneda electrónica personalizada se superpone al tipo de moneda base y funciona de manera similar. La transacción de assetbase puede aparecer en cualquier parte del bloque y puede aplicar cualquier regla y restricción personalizada que se decida por adelantado.
Diagrama 3. Transacciones que representan tipos de moneda definidos por el usuario — o activos digitales.
Para lograrlo, necesitamos crear un identificador único estable y un mecanismo de transacción para rastrear la autenticidad del tipo de moneda (activo digital). Los usuarios del sistema necesitan tener pruebas de que los tipos de moneda personalizados no son falsificaciones y representan con exactitud los activos digitales.
Diagrama 4. Los tipos de moneda definidos por el usuario se definen a partir de una transacción especial de la Fábrica de Moneda. Se utiliza un identificador único para clasificar el tipo de moneda.
Para implementar un identificador único para un tipo de moneda, utilizamos una transacción marcadora especial, llamada "transacción de base de activos", que actúa como el inicio (ceca) de la cadena de firmas digitales. En lugar de requerir una nueva estructura de datos para el identificador único, reutilizamos el identificador de la transacción y el índice de salida, llamado "outpoint", como identificador único para el tipo de moneda. Se garantiza que los puntos de salida (36 bytes) son aleatorios y globalmente únicos.
Una instrucción de programación, llamada OP_PUSHINPUTREF
, se utiliza para adjuntar una referencia a una salida. La instrucción acepta exactamente un parámetro de 36 bytes que debe coincidir con 1) el punto de salida de una de las salidas que se están gastando, o 2) el mismo valor de 36 bytes que ya aparece en un OP_PUSHINPUTREF
previamente especificado en una de las salidas que se están gastando. La única manera de que un valor determinado aparezca en la salida de una transacción es que, a través de alguna transacción antecesora, coincida con el punto de salida de la transacción inicial de assetbase. Las transacciones que especifican un valor que no cumple ninguna de las dos condiciones no son válidas.
Diagrama 5. Los identificadores únicos se inician al coincidir con un punto de salida de una de las salidas que se gastan, y luego se mantienen mientras al menos una de las salidas que se gastan contenga el mismo identificador único en el cuerpo del script.
Esta sencilla instrucción de programación proporciona un identificador único que puede utilizarse como referencia estable para crear reglas avanzadas. Por ejemplo, diferentes tipos de monedas, activos digitales, pueden ahora depender de otros tipos de monedas. Dado que todos los datos son locales a la transacción, a través de sus transacciones de entrada inmediatas, es fácil para los clientes y servicios validar la autenticidad de un activo digital en O(1) tiempo y espacio constantes, evitando la necesidad de un tercero de confianza.
Es posible crear identificadores únicos de forma alternativa y también proporcionar un mecanismo para pruebas de inducción matemática [5] utilizando un algoritmo de hash de transacciones modificado. Permitiendo que los scripts de entrada acepten que se gaste la transacción padre, las reglas pueden verificar que el padre, y su abuelo, se ajustan a las reglas requeridas. El problema obvio es que a medida que se incrusta cada copia completa de las transacciones padre, se produce una explosión de tamaño exponencial que impide el uso práctico de la técnica. Lo que se necesita es una forma de comprimir la transacción, de modo que se pueda utilizar una estructura de datos de tamaño fijo para derivar el hash de la transacción, en lugar de requerir el contenido completo de la transacción.
Diagrama 6. Validación de la transacción completa de los padres, prueba de inducción matemática mediante la incorporación de las transacciones completas de los padres en las entradas, lo que resulta en un aumento exponencial del tamaño de la transacción.
Podemos lograrlo modificando el algoritmo de hash de transacciones utilizado en Bitcoin, en el que se calcula un doble hash de sha-256 a partir de la transacción serializada, en una nueva versión que primero resume el contenido de la transacción para derivar el hash. Introducimos la versión 3 del algoritmo de hash de transacciones, para distinguirlo del uso de la versión 1 y la versión 2 en Bitcoin. El proceso consiste en hacer un hash de cada campo, o componente de una transacción, a un hash intermedio, que puede ser utilizado como una entrada de tamaño fijo y así evitar el crecimiento exponencial del tamaño de la transacción.
Utilizamos la siguiente estructura de datos de 112 bytes, en lugar de los bytes completos de la transacción serializada, que a su vez se somete a un doble hash sha-256 para obtener finalmente el hash de la transacción.
Campos de preimagen Hash de la transacción versión 3:
nVersion(=3) de la transacción (4 byte little endian)
nTotalInputs (4 byte little endian)
hashPrevoutInputs (32 byte hash)
hashSequence (32 byte hash)
nTotalOutputs (4 byte little endian)
hashOutputHashes (32 byte hash)
nLocktime de la transacción (4 byte little endian)
Al utilizar el algoritmo de hash de transacciones de la versión 3, podemos incrustar la transacción del padre y del abuelo en cada paso de una prueba de inducción matemática para evitar el aumento del tamaño de la transacción, y podemos aplicar cualquier regla necesaria.
Diagrama 7. Validación comprimida de la transacción de los padres, prueba de inducción matemática mediante la incrustación de la estructura de datos de preimagen de la versión 3 del hash de la transacción de los padres y los abuelos para hacer cumplir reglas y restricciones arbitrarias.
La topología de la red es un grafo casi completo, en el que cada Nodo Minero está conectado a cualquier otro Nodo Minero. Los pasos para hacer funcionar la red son los mismos que en Bitcoin, con algunas distinciones para los diferentes tipos de nodos: Nodos Mineros, Nodos Agentes y Nodos de Archivo. Los Nodos Mineros son los que publican activamente los bloques y mantienen el consenso con todos los demás nodos, los Nodos de Archivo sirven los datos históricos de los bloques, y los Nodos de Agente están diseñados para filtrar los bloques y seguir las transacciones de interés para las aplicaciones a las que sirven. Los Nodos de Archivo y los Nodos Agentes pueden operar en la misma red peer-to-peer y, sin embargo, no producen bloques. Los nodos no mineros, como los de archivo y los de agente, se denominan a veces "nodos oyentes" para distinguir su función en la red.
Diagrama 8. Los nodos de minería están bien conectados y construyen sobre los bloques de los demás. Los nodos de archivo almacenan bloques completos para fines de análisis histórico y de arranque. Los nodos de agente son nodos de escucha que filtran y almacenan transacciones para servir a los clientes.
Los nodos mineros están bien conectados en un gráfo casi completo entre otros nodos mineros. Su trabajo es construir sobre los bloques de los demás y mantener el consenso para los últimos cientos de bloques, y mantener el conjunto UTXO para la prevención del doble gasto.
Los Nodos Agente sólo necesitan almacenar un subconjunto de transacciones, por ejemplo, un tipo de moneda o activo digital específico. Incluso con bloques grandes, un nodo agente puede filtrar rápidamente las transacciones por referencias o secuencias de bytes específicas, y luego almacenar esas transacciones para servirlas a través de una interfaz de programador de aplicaciones. Entre los agentes que cooperan, se puede anunciar públicamente el hash de la raíz del árbol de Merkle para las transacciones de cada bloque que coincidan con un patrón predeterminado para señalar a otros Agentes y consumidores con transacciones que ha procesado ese Agente
Los nodos de archivo se utilizan para crear copias de seguridad de bloques enteros para diversas aplicaciones, como el almacenamiento de datos, el análisis y el aprendizaje automático. Como los nodos de archivo no participan directamente en la minería, no tienen los mismos requisitos de rendimiento y ancho de banda en tiempo real que los nodos de minería o de agente.
Consideramos el escenario en el que la red Radiant sigue creciendo y lo que supone para los requisitos de procesamiento de los nodos de minería, archivo y agente. A modo de comparación, en el momento de escribir este artículo, hay unos 83 millones de salidas de transacciones sin gastar para el blockchain de Bitcoin, lo que supone un total de unos 6 GB de datos necesarios para evitar el doble gasto. Sólo es necesario que los Nodos Mineros conserven los cientos de bloques más recientes, estando los bloques más antiguos disponibles en los Nodos de Archivo. Para los Nodos Agentes, es necesario mantener la partición relevante de los resultados de las transacciones no gastadas que pertenecen a las aplicaciones que sirven, el escalado es una función del ancho de banda y no de los requisitos de almacenamiento.
Para nuestros propósitos, suponemos que habrá bloques de 3 GB de tamaño cada 5 minutos que se marcarán con el tiempo y se distribuirán por la red, o unas 20.000 transacciones por segundo con un tamaño medio de transacción de 500 bytes, o unos 6.000.000 de transacciones por bloque. Demostramos que para cada tipo de nodo, la red es capaz de escalar adecuadamente para satisfacer la demanda global. Esto equivale a una transacción cada 5 días para cada uno de los 8.000 millones de habitantes del planeta.
Los nodos mineros son el único tipo de nodo que construye sobre los bloques de los demás. Para mantener el consenso, basta con sincronizar el conjunto de transacciones no gastadas (UTXO) y mantener sólo unos cien bloques. En el momento de escribir este artículo, las unidades de estado sólido de alto rendimiento son capaces de alcanzar más de 120.000 IOPS, con un coste de unos 500 dólares por 280 GB, y por lo tanto pueden manejar unas 20.000 transacciones por segundo (suponiendo que cada transacción tiene 2 entradas y 2 salidas). Hay 2 lecturas para las entradas, 2 actualizaciones para las entradas y 2 escrituras para la nueva salida: 120.000 / 6 = 20.000 transacciones/segundo.
Los Nodos de Archivo proporcionan datos históricos en bloque y son adecuados para aplicaciones de aprendizaje automático, análisis y almacenamiento de datos. Los nodos de archivo pueden complementar el arranque de los nodos de minería y ejecutar comprobaciones periódicas de consistencia en el conjunto UTXO. En el momento de escribir estas líneas, se pueden adquirir discos duros básicos de 18 TB por unos 350 dólares. Suponiendo 3 GB de datos cada 5 minutos, se necesitan 732 GB de almacenamiento de datos al día, o unos 22 TB al mes. El coste de hardware para un año es de 15 discos duros, con 18 TB de capacidad, por un coste incremental anual de 5.000 USD.
Los Nodos Agentes son los que escalan más fácilmente entre los tipos de nodos porque sólo procesan los tipos de transacciones relevantes para las aplicaciones a las que sirven. Como resultado, los Nodos Agentes pueden ser desde un servidor web hasta un dispositivo IoT ligero con capacidades limitadas de procesamiento y almacenamiento, y aún así mantener la estabilidad con bloques de 3 GB, o 20.000 transacciones por segundo. Por ejemplo, una empresa puede querer hacer un seguimiento del uso de sus puntos de fidelidad, creados como un activo digital, y por lo tanto sólo necesita seleccionar un pequeño subconjunto de actualizaciones de transacciones de cada bloque que coincidan con el identificador único para ese tipo de moneda.
En el momento de escribir este artículo, un dispositivo informático comercial, Raspberry Pi 4, se vende por unos 275 dólares y tiene un procesador de cuatro núcleos a 1,5 GHZ y 4 GB de RAM, que puede utilizarse para filtrar rápidamente y descartar las transacciones irrelevantes, a un ritmo de 5.000 transacciones por núcleo. Por supuesto, esto es sólo un ejemplo de lo razonable que es procesar grandes bloques, en una aplicación web típica puede haber muchos más núcleos disponibles.
La velocidad media del ancho de banda de los 25 principales países supera los 100 MBPS, es decir, unos 10 MB/segundo de descarga, y muchos proveedores de servicios de Internet ofrecen descargas ilimitadas. Los requisitos de ancho de banda para bloques de 3 GB cada 5 minutos son de unos 10 MB/segundo para un total de 22 TB al mes. También se pueden crear jerarquías de Nodos Agentes para filtrar los requisitos totales de ancho de banda para los Nodos Agentes con menor capacidad de ancho de banda.
Hemos propuesto un sistema de gestión de activos digitales sin depender de la confianza. Empezamos con los bloques de construcción básicos de monedas hechas de firmas digitales, lo que proporciona un fuerte control de la propiedad. A partir de las reglas e incentivos necesarios, introducimos dos métodos novedosos para autenticar y rastrear los activos digitales en tiempo y espacio constantes de O(1). Ambos métodos proporcionan de forma independiente un sistema general de pruebas de inducción matemática que puede codificar cualquier configuración posible de activos digitales. El sistema es Turing completo dentro y a través de los límites de las transacciones, sin necesidad de capas secundarias. Radiant tiene un diseño innovador que proporciona las ventajas de rendimiento y paralelismo de una blockchain de salida de transacciones no gastadas (UTXO), pero con la capacidad de crear contratos inteligentes de las blockchains basadas en cuentas y basadas en la máquina virtual de Ethereum (EVM).
[1] Satoshi Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System" URL https://bitcoin.org/bitcoin.pdf, 2009.
[2] Vitalik Buterin, "Ethereum: A Next-Generation Smart Contract and Decentralized Application Platform." URL https://ethereum.org/en/whitepaper/, 2014.
[3] Wikipedia contributors. "Turing completeness." Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, URL https://en.wikipedia.org/wiki/Turing_completeness, 21 Jul. 2022
[4] R.C. Merkle, "Protocols for public key cryptosystems," In Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, pages 122-133, April 1980.
[5] Britannica, T. Editors of Encyclopaedia. "mathematical induction." Encyclopedia Britannica, URL https://www.britannica.com/science/mathematical-induction, 2018
CashScript is a high-level programming language for smart contracts on Radiant. It offers a strong abstraction layer over Radiant' native virtual machine, RadiantScript. Its syntax is based on Ethereum's smart contract language Solidity, but its functionality is very different since smart contracts on Radiant differ greatly from smart contracts on Ethereum. For a detailed comparison of them, refer to the blog post.
Token-controlled contracts revolutionize contract composition and management on Radiant, facilitating the separation of contracts into multiple UTXOs, each with distinct functionalities. With token ownership housed in its UTXO and additional UTXOs for data storage and specialized functionalities, developers can seamlessly integrate custom functionalities with standard token scripts, extending contract capabilities effortlessly.
A standard singleton + P2PKH token script:
The token output features a state script binding it to the contract input using ´OP_REQUIREINPUTREF´ , followed by the contract's script signature hash:
This script empowers complex contracts composed of multiple UTXOs, each with unique responsibilities. Token scripts maintain standard scripts easily understood by wallets but can be associated with custom contracts. Pay to token contracts can be deployed at any time to expand token functionality.
Enhanced Functionality: Contracts can be extended with custom functionalities effortlessly.
Streamlined Updates: Token transfers and data updates are segregated, simplifying history tracking.
Reduced Load: Wallets can focus on relevant transaction histories, improving efficiency.
This script can be used to break a contract up into multiple parts. For example a complex NFT contract, split into a token contract and ownership contract:
Token-controlled contracts pave the way for more flexible and manageable blockchain contracts, fostering innovation and scalability in decentralized applications.
The command line CashScript compiler cashc
can be installed from NPM.
The JavaScript SDK can be installed into your project with NPM.
While more detailed examples are available on GitHub, we show an integration of the TransferWithTimeout
contract in a JavaScript project.
After compiling the contract file to an artifact JSON with cashc, it can be imported into the CashScript SDK.
When developing smart contracts for CashScript it is useful to have the proper syntax highlighting in your code editor / IDE. If you use Visual Studio Code, there is a dedicated CashScript extension. For other editors it is recommended to install a Solidity highlighting plugin and associate it with .cash
files in your editor, since the syntaxes of the two languages are very similar.
Because of the first-class CashScript support, Visual Studio Code together with this CashScript extension is the recommended way to develop CashScript contracts.
View -> Syntax -> Open all with current extension as ... -> Solidity
This associates .cash
files with Solidity, and enables syntax highlighting for your CashScript files.
```yaml title="~/.atom/config.cson" core: customFileTypes: "source.solidity": ["cash"]
This associates .cash
files with Solidity, and enables syntax highlighting for your CashScript files.
GitHub and GitLab have syntax highlighting for Solidity built in. To associate .cash
files with Solidity highlighting, add a .gitattributes
file to your repository with the following contents:
python title=".gitattributes" *.cash linguist-language=Solidity # GitHub *.cash gitlab-language=solidity # GitLab
If your editor is not mentioned above, the steps are likely very similar. Try to find a Solidity syntax highlighting plugin for your editor of choice and find a method to associate .cash
files with this Solidity highlighting.
Covenants are all the rage in Bitcoin Cash smart contracts. But what are they, and how do you use them? In one sentence: a covenant is a constraint on how money can be spent. A simple example is creating a smart contract that may only send money to one specific address and nowhere else. The term Covenant originates in property law, where it is used to constrain the use of any object - or in the case of BCH, the use of money.
When using CashScript, you can access a lot of introspection data that can be used to inspect and constrain transaction details, such as inputs and outputs.
int this.activeInputIndex
- Index of the input that is currently under evaluation during transaction validation.
bytes this.activeBytecode
- Contract bytecode of the input that is currently under evaluation during transaction validation.
int tx.version
- Version of the transaction.
int tx.locktime
- nLocktime
field of the transaction.
int tx.inputs.length
- Number of inputs in the transaction.
int tx.inputs[i].value
- Value of a specific input (in satoshis).
bytes tx.inputs[i].lockingBytecode
- Locking bytecode (scriptPubKey
) of a specific input.
bytes tx.inputs[i].unlockingBytecode
- Unlocking bytecode (scriptSig
) of a specific input.
bytes32 tx.inputs[i].outpointTransactionHash
- Outpoint transaction hash of a specific input.
int tx.inputs[i].outpointIndex
- Outpoint index of a specific input.
int tx.inputs[i].sequenceNumber
- nSequence
number of a specific input.
int tx.outputs.length
- Number of outputs in the transaction.
int tx.outputs[i].value
- Value of a specific output (in satoshis).
bytes tx.outputs[i].lockingBytecode
- Locking bytecode (scriptPubKey
) of a specific output.
While we know the individual data fields, it's not immediately clear how this can be used to create useful smart contracts on Bitcoin Cash. But there are several constraints that can be created using these fields, most important of which are constraints on the recipients of funds, so that is what we discuss.
The contract starts by doing some checks to make sure the transaction is signed by the arbiter. Next up it checks that the full contract balance (tx.inputs[this.activeInputIndex].value
) is sent to the first output by accessing tx.outputs[0].value
. Finally it checks that the receiver of that money is either the buyer or the seller using LockingBytecodeP2PKH
and tx.outputs[0].lockingBytecode
. Note that we use a hardcoded fee as it is difficult to calculate the exact transaction fee inside the smart contract.
Besides sending money to P2PKH
addresses, it is also possible to send money to a smart contract (P2SH
) address. This can be used in the same way as a P2PKH
address if the script hash is known beforehand, but this can also be used to make sure that money has to be sent back to the current smart contract.
This is especially effective when used together with time constraints. An example is the Licho's Last Will contract. This contract puts a dead man's switch on the contract's holdings, and requires the owner to send a heartbeat to the contract every six months. If the contract hasn't received this heartbeat, an inheritor can claim the funds instead.
This contract has three functions, but only the refresh()
function uses a covenant. Again it performs necessary checks to verify that the transaction is signed by the owner, after which it checks that the entire contract balance is sent. It then uses tx.inputs[this.activeInputIndex].lockingBytecode
to access its own locking bytecode, which can be used as the locking bytecode of this output. Sending the full value back to the same contract effectively resets the tx.age
counter, so the owner of the contract needs to do this every 180 days.
The earlier examples showed sending money to only a single output of either P2PKH
or P2SH
. But there nothing preventing us from writing a contract that can send to multiple outputs, including a combination of P2PKH
and P2SH
outputs. A good example is the Licho's Mecenas contract that allows you to set up recurring payments where the recipient is able to claim the same amount every month, while the remainder has to be sent back to the contract.
This contract applies similar techniques as the previous two examples to verify the signature, although in this case it does not matter who the signer of the transaction is. Since the outputs are restricted with covenants, there is no way someone could call this function to send money anywhere but to the correct outputs.
A more advanced use case of restricting recipients is so-called simulated state. This works by restricting the recipient to a slightly amended version of the current contract. This can be done when the changes to the contract are only to its constructor parameters and when these parameters are of a known size (like bytes20
or bytes4
).
To demonstrate this we consider the Mecenas contract again, and focus on a drawback of this contract: you have to claim the funds at exactly the right moment or you're leaving money on the table. Every time you claim money from the contract, the tx.age
counter is reset, so the next claim is possible 30 days after the previous claim. So if we wait a few days to claim, these days are basically wasted.
Instead of having a pledge per 30 day period, we define a pledge per block. At any point in time we can calculate how much money the recipient has earned. Then the covenant enforces that this amount is withdrawn from the contract. The remainder is sent to a new stream that starts at the end of of the previous one. The bytecode of this new stream is computed by "cutting out" some of the existing constructor parameters in the this.activeBytecode
field and replacing them with new values. This process can be applied to the new stream until the money in the stream runs out.
In this contract we construct an "announcement" OP_RETURN
output, we reserve a part of value for the miner fee, and finally we send the remainder back to the contract.
Radiant's singleton references are ideal for the creation of NFTs. A singleton ref is a type of reference which can only ever exist in a single UTXO. A transaction is invalid if a singleton ref is pushed to more than one output. References cannot change type, so a singleton ref must be created as a singleton. Therefore we can be sure that there has only ever been one instance of a singleton ref.
The opcode for pushing a singleton ref is OP_PUSHINPUTREFSINGLETON
.
We will define a contract for an immutable NFT by adding a singleton ref to a standard P2PKH script:
Following Radiant's ref rules, the ref must match an outpoint or a ref of the same type in an input. If the ref matches an outpoint then this is the "mint" transaction. OP_PUSHINPUTREFSINGLETON
leaves the ref on the stack, and since we don't need it later in the script it is immediately dropped.
DIAGRAM
As seen in the diagram above, an outpoint in the first transaction is used to create a singleton ref. The referenced output also contains an "immutable token payload" which can be stored as a push data. This is a simple way of associating data with our token, where the token data can be fetched from the referenced output. The payload could be an image or more complex data structure. Token UTXOs are kept light weight by not carrying the payload.
This token protocol can be used for a wide variety of use cases such as tickets, coupons and collectibles. Wallet integration is simple since the script only requires a singleton ref in addition to a standard P2PKH script.
Melting a token only requires that the token be spent and the singleton ref not pushed forward. Once the singleton does not exist in a UTXO it cannot be recreated.
Singleton refs are a simple yet effective way of creating an NFT protocol. We have demonstrated how a token protocol can be created with only a small change to a standard P2PKH script. In future articles we will explore how to extend this contract to support mutable data.
Indonesian version of the Radiant whitepaper
Para Pengembang Radiant
11 Agustus, 2022
radiantblockchain.org
Abstrak. Jaringan Radiant adalah sistem aset digital peer-to-peer yang memungkinkan pertukaran nilai secara langsung tanpa melalui pihak pusat. Protokol asli Bitcoin[1] menyediakan apa yang diperlukan untuk membuat sistem kas elektronik peer-to-peer, tetapi tidak memiliki kemampuan untuk memverifikasi riwayat transaksi dan oleh karena itu, tidak dapat digunakan untuk memvalidasi aset digital. Tanda tangan digital dan batasan keluaran memberikan bagian dari solusi, tetapi manfaat utama hilang jika pihak ketiga yang tepercaya masih diperlukan untuk memvalidasi aset digital. Mirip dengan Bitcoin, jaringan Radiant membutuhkan struktur minimal, dan mencatat waktu transaksi ke dalam rantai bukti kerja berbasis hash yang sedang berlangsung. Kami memperkenalkan dua teknik untuk memvalidasi aset digital: referensi unik dan sistem bukti induksi tujuan umum yang keduanya beroperasi dalam ruang dan waktu O(1) konstan. Dimungkinkan untuk menyusun output dengan cara apa pun, tanpa mengorbankan karakteristik paralelisme dan kinerja yang melekat dari arsitektur berbasis output transaksi yang tidak terpakai (UTXO). Oleh karena itu, pengguna dapat keluar dan bergabung kembali dengan jaringan Radiant sesuka hati dan yakin akan integritas dan keaslian aset digital mereka.
Perdagangan dengan blockchain, atau teknologi buku besar digital (DLT), dalam banyak kasus bergantung pada penerbit dan kustodian yang berfungsi sebagai pihak tepercaya untuk mengautentikasi aset digital. Sementara sistem tersebut bekerja cukup baik untuk transaksi seperti pembayaran elektronik, mereka masih menderita kelemahan yang melekat pada model berbasis kepercayaan untuk tingkat lanjut menggunakan. Blockchain berbasis Ethereum Virtual Machine (EVM) [2] sangat fleksibel untuk semua jenis program, tetapi biaya tinggi membuat penggunaan aplikasi pembayaran mikro menjadi tidak praktis
Yang dibutuhkan adalah sistem pembayaran elektronik yang dapat digunakan untuk sistem manajemen aset digital dengan biaya rendah, kinerja tinggi, dan kemampuan pemrograman tingkat lanjut. Dalam makalah ini, kami mengusulkan solusi untuk masalah penskalaan dan kontrak blockchain menggunakan dua teknik baru yang memberikan referensi unik dan sistem bukti induksi umum, yang membuat program Turing Complete [3] melintasi batas transaksi menjadi mungkin. Sistem yang diusulkan terdesentralisasi, menggunakan mekanisme konsensus proof-of-work seperti Bitcoin, tetapi dengan tingkat throughput yang jauh lebih tinggi, sambil memberikan fleksibilitas yang sama dari blockchain berbasis EVM, dengan biaya yang sangat rendah.
Mirip dengan Bitcoin, kami mendefinisikan koin elektronik sebagai rangkaian tanda tangan digital. Di mana transaksi di Radiant berbeda adalah bahwa setiap pemilik mentransfer koin ke yang berikutnya dengan menandatangani hash secara digital dari transaksi sebelumnya selain parameter input yang diperlukan untuk membuka kunci koin. Sebuah transaksi juga menciptakan kendala penguncian keluaran baru, yang mungkin termasuk kunci publik dari pemilik berikutnya, di antara aturan lain yang ditentukan oleh pengguna.
Diagram 1. Transaksi Radiant.
Untuk memverifikasi bahwa pembelanjaan ganda tidak terjadi, kami menggunakan server timestamp terdistribusi, menggunakan sistem proof-of-work berbasis hash untuk mengatur riwayat kanonis guna menentukan transaksi mana yang tiba lebih dulu. Transaksi diatur ke dalam blok. Sesuai kesepakatan, transaksi pertama, yang disebut "transaksi berbasis koin", dalam sebuah blok adalah transaksi khusus yang memulai koin baru yang dimiliki oleh pembuat blok. Blok dirantai bersama dan mengatur transaksi menjadi Pohon Merkle [4]. Semua transaksi, kecuali yang pertama, harus mengacu pada transaksi sebelumnya yang membentuk grafik asiklik terarah (DAG) di mana semua koin pada akhirnya terhubung kembali ke setidaknya satu transaksi khusus di awal blok.
Diagram 2. Struktur Blok; transaksi diatur ke dalam Pohon Merkle.
Masalah dengan desain ini, dalam konteks aset digital, adalah hanya ada satu jenis koin, atau aset digital, dan tidak ada konsep koin yang ditentukan pengguna (atau jenis aset digital). Desainnya berfungsi cukup baik untuk transaksi seperti pembayaran elektronik di unit akun asli, namun tidak langsung cocok untuk digunakan untuk jenis koin atau aset digital lainnya. Solusi umum adalah dengan memperkenalkan layanan seperti pengindeks transaksi yang memantau transaksi untuk urutan data khusus untuk menandai pembuatan aset digital. Masalah dengan solusi ini adalah bergantung pada perusahaan yang menjalankan layanan, dengan keaslian aset digital yang perlu dipercaya, sama seperti layanan lain di web. Kami membutuhkan cara bagi pengguna untuk menunjukkan pembuatan jenis koin khusus, tetapi tidak bergantung pada layanan tepercaya yang akan digunakan untuk presentasi data.
Kami mendefinisikan koin elektronik khusus, atau aset digital, sebagai rangkaian tanda tangan digital. Aset digital adalah jenis koin yang ditentukan pengguna menggunakan penanda transaksi khusus, yang disebut "transaksi basis aset", untuk membuat atau mencetak aset digital. Mirip dengan transaksi coinbase, yang menyuntikkan koin baru ke dalam sistem, transaksi assetbase mewarnai atau menandai koin elektronik dengan pengidentifikasi 36-byte unik untuk seumur hidup. Koin elektronik kustom dilapisi di atas jenis koin dasar dan berfungsi dengan cara yang sama. Transaksi basis aset dapat muncul di mana saja di blok dan dapat memberlakukan aturan dan batasan khusus apa pun yang diputuskan di muka.
Diagram 3. Transaksi yang mewakili jenis koin yang ditentukan pengguna — atau digital asset
Untuk melakukannya, kita perlu membuat pengidentifikasi unik yang stabil dan mekanisme transaksi untuk melacak keaslian jenis koin (aset digital). Pengguna sistem perlu memiliki bukti bahwa jenis koin khusus bukan pemalsuan dan secara akurat mewakili aset digital.
Diagram 4. Jenis koin khusus yang ditentukan pengguna ditentukan dari transaksi mint khusus. Pengidentifikasi unik digunakan untuk mengklasifikasikan jenis koin.
Untuk menerapkan pengidentifikasi unik untuk jenis koin, kami menggunakan transaksi penanda khusus, yang disebut "transaksi basis aset", yang bertindak sebagai awal (mint) rantai tanda tangan digital. Daripada memerlukan struktur data baru untuk pengenal unik, kami menggunakan kembali pengenal transaksi dan indeks keluaran, yang disebut "outpoint", sebagai pengenal unik untuk jenis koin. Dipastikan bahwa outpoints (36-bytes) bersifat acak dan unik secara global.
Instruksi pemrograman, disebut OP_PUSHINPUTREF
, digunakan untuk melampirkan referensi ke output. Instruksi menerima tepat satu parameter 36-byte yang harus cocok dengan 1) titik keluar dari salah satu output yang digunakan, atau 2) nilai 36-byte yang sama sudah muncul di OP_PUSHINPUTREF
yang ditentukan sebelumnya di salah satu output yang digunakan . Satu-satunya cara agar nilai tertentu muncul dalam keluaran transaksi adalah melalui beberapa transaksi leluhur, nilai tersebut cocok dengan titik keluar dari transaksi basis aset pencetakan awal. Transaksi yang menentukan nilai yang tidak memenuhi salah satu syarat tidak valid.
Diagram 5. Pengidentifikasi unik diinisialisasi dengan mencocokkan titik keluar dari salah satu keluaran yang digunakan, dan kemudian dipertahankan selama setidaknya salah satu keluaran yang dikeluarkan berisi pengenal unik yang sama di badan skrip.
Instruksi pemrograman sederhana ini memberikan pengidentifikasi unik yang dapat digunakan sebagai referensi stabil untuk membuat aturan lanjutan. Misalnya, berbagai jenis koin, aset digital, kini dapat bergantung pada jenis koin lainnya. Karena semua data bersifat lokal untuk transaksi, melalui transaksi masukan induk langsung, mudah bagi klien dan layanan untuk memvalidasi keaslian aset digital dalam O(1) waktu dan ruang yang konstan, menghindari kebutuhan akan layanan tepercaya .
Dimungkinkan untuk membuat pengidentifikasi unik dengan cara alternatif dan juga menyediakan mekanisme untuk pembuktian induksi matematika [5] menggunakan algoritma hash transaksi yang dimodifikasi. Dengan mengizinkan skrip input untuk menerima transaksi induk yang dibelanjakan, aturan dapat memverifikasi bahwa induk, dan kakeknya sesuai dengan aturan yang diperlukan. Masalah yang jelas adalah bahwa karena setiap salinan lengkap dari transaksi induk disematkan, ledakan ukuran eksponensial terjadi dan mencegah penggunaan teknik secara praktis. Apa yang dibutuhkan adalah cara untuk mengompresi transaksi, sehingga struktur data berukuran tetap dapat digunakan sebagai gantinya untuk memperoleh hash transaksi, alih-alih membutuhkan konten transaksi penuh.
Diagram 6. Validasi full parent transaction, pembuktian induksi matematis dengan memasukkan full parent transaction ke dalam input yang menghasilkan peningkatan ukuran transaksi secara eksponensial.
Kita dapat melakukannya dengan memodifikasi algoritme hash transaksi yang digunakan dalam Bitcoin, di mana intisari sha-256 ganda dihitung dari transaksi berseri, menjadi versi baru yang terlebih dahulu meringkas konten transaksi untuk memperoleh hash. Kami memperkenalkan algoritma hash transaksi versi 3, untuk membedakannya dari penggunaan versi 1 dan versi 2 di Bitcoin. Prosesnya adalah mencirikan setiap bidang, atau komponen transaksi, ke hash perantara, yang dapat digunakan sebagai input ukuran tetap dan dengan demikian menghindari pertumbuhan ukuran transaksi eksponensial.
Kami menggunakan struktur data 112-byte berikut, alih-alih byte transaksi berseri lengkap, yang pada gilirannya di-hash sha-256 ganda untuk akhirnya mendapatkan hash transaksi.
Versi Transaksi 3 Kolom Hash Preimage:
nVersion(=3) transaksi (4 byte little endian)
nTotalInputs (4 byte little endian)
hashPrevoutInputs (hash 32 byte)
hashSequence (hash 32 byte)
nTotalOutputs (4 byte little endian)
hashOutputHash (hash 32 byte)
nLocktime transaksi (4 byte little endian)
Dengan menggunakan algoritme hash transaksi untuk transaksi versi 3, kami dapat menyematkan transaksi induk dan kakek-nenek di setiap langkah bukti induksi matematis untuk mencegah peningkatan ukuran transaksi, dan dapat menerapkan aturan apa pun yang diperlukan.
Diagram 7. Validasi transaksi induk terkompresi, bukti induksi matematis dengan menyematkan struktur data preimage hash transaksi versi 3 dari induk dan kakek-nenek untuk menegakkan aturan dan batasan yang sewenang-wenang
Topologi jaringan adalah grafik yang hampir lengkap, di mana setiap Node Penambangan terhubung ke setiap Node Penambangan lainnya. Langkah-langkah untuk menjalankan jaringan sama dengan Bitcoin, dengan beberapa perbedaan untuk jenis node yang berbeda: Node Penambangan, Node Agen, Node Arsip. Mining Nodes adalah penerbit blok aktif dan mempertahankan konsensus dengan semua node lain, Node Arsip melayani data blok historis, dan Node Agen dirancang untuk memfilter blok dan melacak transaksi yang menarik ke aplikasi yang mereka layani. Arsip dan Node Agen dapat beroperasi pada jaringan peer-to-peer yang sama namun tidak menghasilkan blok. Non-Mining Nodes seperti Archive dan Agent Nodes terkadang disebut sebagai "node pendengar" untuk membedakan peran mereka dalam jaringan.
Diagram 8. Node Penambangan terhubung dengan baik dan dibangun di atas blok masing-masing. Node arsip menyimpan blok lengkap untuk analisis historis dan tujuan bootstrap. Node agen adalah node pendengar yang memfilter dan menyimpan transaksi untuk melayani klien.
Node Penambangan terhubung dengan baik ke dalam grafik yang hampir lengkap antara Node Penambangan lainnya. Tugas mereka adalah membangun di atas blok satu sama lain dan mempertahankan konsensus untuk beberapa ratus blok terbaru, dan mempertahankan set UTXO untuk pencegahan pengeluaran ganda.
Agen Node hanya perlu menyimpan subset transaksi, misalnya jenis koin tertentu atau aset digital. Bahkan dengan blok besar, Agen Node dapat dengan cepat memfilter transaksi dengan referensi atau urutan byte tertentu, lalu menyimpan transaksi tersebut untuk ditayangkan melalui antarmuka pemrogram aplikasi. Di antara agen yang bekerja sama, root hash Merkle Tree dapat diumumkan secara publik untuk transaksi di setiap blok yang cocok dengan pola yang telah ditentukan sebelumnya untuk memberi sinyal kepada Agen dan konsumen lain tentang transaksi mana yang telah diproses oleh Agen.
Node Arsip digunakan untuk membuat salinan cadangan seluruh blok untuk berbagai aplikasi termasuk pergudangan data, analitik, dan pembelajaran mesin. Karena Archive Nodes tidak terlibat langsung dalam penambangan, mereka tidak memiliki persyaratan kinerja dan bandwidth real-time yang sama seperti Mining atau Agent Nodes.
Kami mempertimbangkan skenario di mana jaringan Radiant terus tumbuh dan apa yang diperlukan untuk persyaratan pemrosesan Mining, Archive, dan Agent Nodes. Sebagai perbandingan, pada saat penulisan, ada sekitar 83 juta keluaran transaksi yang tidak terpakai untuk blockchain Bitcoin, dengan total sekitar 6 GB data yang diperlukan untuk mencegah pengeluaran ganda. Hanya perlu bahwa beberapa ratus blok terbaru disimpan oleh Mining Nodes, dengan blok yang lebih lama tersedia dari Archive Nodes. Untuk Agent Nodes, penting untuk menjaga partisi yang relevan dari output transaksi yang tidak terpakai yang berkaitan dengan aplikasi yang mereka layani, penskalaan adalah fungsi bandwidth dan bukan kebutuhan penyimpanan.
Untuk tujuan kami, kami berasumsi bahwa akan ada blok berukuran 3 GB setiap 5 menit untuk diberi stempel waktu dan didistribusikan ke seluruh jaringan, atau sekitar 20.000 transaksi per detik dengan ukuran transaksi rata-rata 500 byte, atau sekitar 6.000.000 transaksi per blok. Kami menunjukkan bahwa untuk setiap jenis node, jaringan dapat diskalakan secara memadai untuk memenuhi permintaan global. Ini sama dengan sekitar 1 transaksi setiap 5 hari untuk masing-masing dari 8 miliar orang di planet ini.
Mining Nodes adalah satu-satunya tipe node yang dibangun di atas blok masing-masing. Untuk mempertahankan konsensus, cukup menyinkronkan kumpulan output transaksi yang tidak terpakai (UTXO), dan hanya mempertahankan sekitar seratus blok terakhir. Pada saat penulisan, solid-state drive komoditas kinerja tinggi mampu mencapai lebih dari 120.000 IOPS, dengan biaya sekitar $500 USD untuk 280 GB, dan karenanya dapat menangani sekitar 20.000 transaksi per detik (dengan asumsi setiap transaksi memiliki 2 input dan 2 output) . Ada 2 pembacaan untuk input, 2 pembaruan input, dan 2 penulisan untuk output baru: 120.000/6 = 20.000 transaksi/detik.
Node Arsip menyediakan data blok historis dan cocok untuk pembelajaran mesin, analitik, dan aplikasi pergudangan data. Node Arsip dapat melengkapi bootstrap Node Penambangan dan untuk menjalankan pemeriksaan konsistensi berkala pada set UTXO. Pada saat penulisan, hard disk komoditas 18 TB tersedia dengan harga sekitar $350 USD. Dengan asumsi 3 GB data setiap 5 menit sama dengan 732 GB kebutuhan penyimpanan data per hari, atau sekitar 22 TB per bulan. Biaya perangkat keras selama setahun adalah 15 hard disk, dengan kapasitas 18 TB, dengan biaya tambahan tahunan sebesar $5.000 USD.
Skala Agen Nodes paling mudah di antara jenis node karena mereka hanya memproses jenis transaksi yang relevan untuk aplikasi yang mereka layani. Hasilnya, Agent Nodes dapat berkisar dari server web hingga perangkat IoT ringan dengan kemampuan pemrosesan dan penyimpanan terbatas, namun tetap tenang dengan blok 3 GB, atau 20.000 transaksi per detik. Misalnya, perusahaan mungkin ingin melacak penggunaan poin loyalitasnya, dibuat sebagai aset digital, dan oleh karena itu hanya perlu memilih sebagian kecil pembaruan transaksi dari setiap blok yang cocok dengan pengidentifikasi unik untuk jenis koin tersebut.
Pada saat penulisan, perangkat komputasi komersial, Raspberry Pi 4, dijual seharga sekitar $275 USD yang memiliki prosesor quadcore 1,5 GHZ dan RAM 4 GB, yang dapat digunakan untuk memfilter dengan cepat, dan membuang transaksi yang tidak relevan, dengan kecepatan 5.000 transaksi per inti. Tentu saja, ini hanyalah contoh betapa masuk akal untuk memproses blok besar, dalam aplikasi web biasa mungkin ada lebih banyak inti yang tersedia.
Kecepatan bandwidth rata-rata dari 25 negara teratas melebihi 100 MBPS, atau sekitar 10 MB/detik unduhan, dengan banyak penyedia layanan internet menawarkan unduhan tanpa batas. Persyaratan bandwidth untuk blok 3 GB setiap 5 menit adalah sekitar 10 MB/detik dengan total 22 TB per bulan. Hierarki Node Agen juga dapat dibuat untuk memfilter kebutuhan total bandwidth untuk Node Agen dengan kapasitas bandwidth yang lebih rendah.
Kami telah mengusulkan sistem manajemen aset digital tanpa mengandalkan kepercayaan. Kami mulai dengan blok bangunan dasar koin yang terbuat dari tanda tangan digital, yang memberikan kontrol kepemilikan yang kuat. Dari aturan dan insentif yang diperlukan, kami memperkenalkan dua metode baru untuk mengautentikasi dan melacak aset digital dalam ruang dan waktu O(1) yang konstan. Kedua metode secara independen menyediakan sistem bukti induksi matematika umum yang dapat menyandikan konfigurasi aset digital yang memungkinkan. Sistem Turing Lengkap di dalam dan melintasi batas transaksi, tanpa perlu lapisan sekunder. Radiant adalah desain terobosan yang memberikan manfaat kinerja dan paralelisme dari blockchain output transaksi yang tidak terpakai (UTXO), tetapi dengan kemampuan kontrak dari blockchain berbasis akun berdasarkan Ethereum Virtual Machine (EVM).
[1] Satoshi Nakamoto, URL "Bitcoin: Sistem Uang Elektronik Peer-to-Peer" https://bitcoin.org/bitcoin.pdf, 2009.
[2] Vitalik Buterin, "Ethereum: Kontrak Cerdas Generasi Berikutnya dan Platform Aplikasi Terdesentralisasi." URL https://ethereum.org/en/whitepaper/, 2014.
[3] Kontributor Wikipedia. "Turing kelengkapan." Wikipedia, ensiklopedia gratis. Wikipedia, Ensiklopedia Gratis, URL https://en.wikipedia.org/wiki/Turing_completeness, 21 Juli 2022
[4] RC Merkle, "Protokol untuk kriptosistem kunci publik," Dalam Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, halaman 122-133, April 1980.
[5] Britannica, T. Editor Ensiklopedia. "induksi matematika." Ensiklopedia Britannica, URL https://www.britannica.com/science/mathematical-induction, 2018
Chinese version of the Radiant whitepaper
The Radiant Developers
2022年8月11日
radiantblockchain.org
摘要: Radiant网络是一种点对点数字资产系统,它使得价值的直接交换不需要经过中央方。原始的比特币[1]协议提供了创建点对点电子现金系统所需的内容,但缺乏验证交易历史记录的能力,因此无法用于验证数字资产。数字签名和输出约束提供了部分解决方案,但如果仍需要信任第三方来验证数字资产,则主要优势将会丧失。与比特币类似,Radiant网络需要最少的结构,并将交易时间戳为基于哈希的工作证明链。我们引入了两种技术来验证数字资产:唯一引用和通用归纳证明系统,两者都在恒定的O(1)时间和空间内运行。可以以任何方式组合输出,而不会影响未使用交易输出(UTXO)基础架构的固有并行性和性能特征。因此,用户可以随意离开和重新加入Radiant网络,并确保其数字资产的完整性和真实性。
区块链或数字账本技术(DLT)的商业应用往往依赖于发行人和保管人作为可信第三方来验证数字资产。虽然这些系统对于类似电子支付的交易足够有效,但它们仍然存在基于信任模型的固有弱点,因此不适用于高级用途。基于以太坊虚拟机(EVM)[2]的区块链非常灵活,适用于各种程序,但高额的费用使得微支付应用不切实际。
我们需要的是一个电子支付系统,它可以用作具有低费用、高性能和先进编程能力的数字资产管理系统。在本文中,我们提出了一种解决区块链扩展和合约问题的方案,使用两种新颖的技术提供唯一引用和通用归纳证明系统,使跨交易边界的图灵完备[3]程序成为可能。所提出的系统是去中心化的,使用类似比特币的工作量证明共识机制,但具有显著更高的吞吐量水平,同时提供与基于EVM的区块链相同的灵活性,费用非常低。
与比特币类似,我们将电子硬币定义为一串数字签名。Radiant中的交易不同之处在于,每个所有者通过数字签名上一个交易的哈希以及解锁硬币所需的输入参数,将硬币转移到下一个所有者。交易还可以创建新的输出锁定约束,其中可能包括下一个所有者的公钥,以及用户定义的任何其他规则。
图1 Radiant交易
为了验证双花,我们使用分布式时间戳服务器,使用基于哈希的工作量证明系统来组织规范历史,以确定哪个交易先到达。交易被组织成块。按照惯例,块中的第一个交易,称为“coinbase交易”,是一种特殊的交易,属于出块矿工挖到的新币。块被链接在一起,并将交易组织成Merkle树[4]。除了第一个交易外,所有交易都必须引用前一个交易,形成一个有向无环图(DAG),其中所有硬币最终都会连接回至少一个块开头的特殊交易。
图2 区块结构;交易组织成Merkle树
这种设计在数字资产的背景下存在的问题是,只有一种数字货币或数字资产,没有用户定义数字货币(或数字资产类型)的概念。这种设计对于以币本位计价单位进行电子支付类交易足够好,但并不立即适用于其他类型的数字货币或数字资产。一个常见的解决方案是引入一种服务,如交易索引器,它监视交易中的特殊数据序列以表示数字资产的创建。这种解决方案的问题在于它依赖于运行该服务的公司,需要像网络上的任何其他服务一样信任数字资产的真实性。
我们需要一种方法让用户指示创建自定义数字货币类型,但不依赖于可信服务用于数据呈现。
我们将自定义电子硬币或数字资产定义为一串数字签名。数字资产是一种使用特殊交易标记(称为“assetbase交易”)创建或铸造数字资产的用户自定义币类型。类似于coinbase交易,它将新币注入系统,assetbase交易用唯一的36字节标识符为其生命周期着色或标记硕子货币。自定义数字货币覆盖在基础数字货币类型之上,并以类似的方式运行。assetbase交易可以出现在块的任何位置,并且可以强制执行用户事先决定的任何自定义规则和约束。
图 3 代表用户定义币种类型或数字资产的交易
为了实现这一点,我们需要创建一个稳定的唯一标识符和一个交易机制来跟踪数字货币类型(数字资产)的真实性。系统的用户需要有证据证明自定义数字货币类型不是伪造的,并准确地代表数字资产。
图 4 自定义用户定义币种类型由特殊的铸币交易定义,使用唯一标识符来分类币种类型。
为了实现硬币类型的唯一标识符,我们使用一种特殊的标记交易,称为“assetbase交易”,它充当数字签名链的开始(铸造)。与需要新数据结构用于唯一标识符不同,我们重用交易标识符和输出索引(称为“outpoint”)作为硬币类型的唯一标识符。可以保证outpoints(36字节)是随机且全局唯一的。
一种名为OP_PUSHINPUTREF
的编程指令用于附加对输出的引用。该指令接受一个36字节的参数,该参数必须与1)正在使用的输出的outpoint之一匹配,或2)在正在使用的输出之一中先前指定的OP_PUSHINPUTREF
中已经出现相同的36字节值。任何给定值出现在交易输出中的唯一方法是,通过某个祖先交易,它与初始铸造assetbase交易的outpoint匹配。指定不符合任一条件的值的交易无效。
图 5. 唯一标识符通过匹配一个被花费的输出的输出点来初始化,并在至少一个被花费的输出在脚本体中包含相同的唯一标识符时维护。
这种简单的编程指令提供了一个唯一标识符,可以用作稳定引用来创建高级规则。例如,不同的数字货币类型、数字资产现在可以依赖于其他数字货币类型。由于所有数据都是本地交易,通过其直接父输入交易,客户端和服务很容易在O(1)常数时间和空间内验证数字资产的真实性,避免了对可信服务的需求。
可以通过另一种方式创建唯一标识符,并且还提供了一种数学归纳证明机制[5],即使用修改后的交易哈希算法。通过允许输入脚本接受正在使用的父交易,规则可以验证父交易及其祖父交易符合所需规则。明显的问题是,随着每个完整的父交易被嵌入,指数大小爆炸发生并阻止了该技术的实际使用。我们需要一种方法来压缩交易,以便可以使用固定大小的数据结构来代替派生交易哈希,而不是需要完整的交易内容。
图 6 完整的父交易验证,通过将完整的父交易嵌入到输入中进行数学归纳证明,导致事务大小呈指数级增加。
我们可以通过修改比特币中使用的交易哈希算法来实现这一点,其中从序列化交易计算双sha-256摘要,转换为新版本,该版本首先总结交易内容以派生哈希。我们引入了交易哈希算法版本3,以将其与比特币中使用的版本1和版本2区分开来。该过程是对交易的每个字段或组件进行哈希,以获得中间哈希,该中间哈希可用作固定大小的输入,从而避免了指数交易大小增长。
我们使用以下112字节的数据结构,而不是完整的序列化交易字节,然后对其进行双sha-256哈希,最终获得交易哈希。
交易版本3的哈希前像字段包括以下组成部分:
nVersion(=3) of the transaction (4 byte little endian)
nTotalInputs (4 byte little endian)
hashPrevoutInputs (32 byte hash)
hashSequence (32 byte hash)
nTotalOutputs (4 byte little endian)
hashOutputHashes (32 byte hash)
nLocktime of the transaction (4 byte little endian)
通过使用版本3交易的交易哈希算法,我们能够在每个数学归纳证明的步骤中嵌入父交易和祖父交易,以防止交易大小增加,并可以强制执行任何所需的规则。
图 7 压缩的父交易验证,通过嵌入父交易和祖父交易的事务哈希版本3的前像数据结构来进行数学归纳证明,以强制执行任意规则和约束。
网络拓扑是一个近乎完全图,其中每个挖矿节点都与其他挖矿节点相连。运行网络的步骤与比特币相同,但对于不同的节点类型有所区别:挖矿节点、代理节点、存档节点。挖矿节点是块的活跃发布者,并与所有其他节点保持一致性,存档节点提供历史块数据,代理节点旨在过滤块并跟踪它们服务的应用程序感兴趣的交易。存档和代理节点可以在同一对等网络上运行,但不产生块。非挖矿节点(如存档和代理节点)有时被称为“监听器节点”,以区分它们在网络中的角色。
图 8 挖矿节点是良好连接的,并且基于彼此的区块构建。存档节点存储完整的区块以进行历史分析和引导。代理节点是监听节点,过滤和存储交易以为客户提供服务。
挖矿节点之间相互连接,形成一个近乎完全图。它们的工作是在彼此的块上建立并维护最近几百个块的共识,并维护UTXO集以防止双重支付。
代理节点只需要存储子集交易,例如特定的硬币类型或数字资产。即使对于大型块,代理节点也可以快速通过引用或特定字节序列过滤交易,然后将这些交易存储以通过应用程序编程接口提供。在合作代理之间,可以公开宣布每个块中与预定模式匹配的交易的Merkle树根哈希,以向其他代理和消费者发出信号,表明该代理已处理了哪些交易。
存档节点用于为各种应用程序创建整个块的备份副本,包括数据仓储、分析和机器学习。存档节点可以补充挖矿节点的引导,并对UTXO集运行定期一致性检查。在撰写本文时,18 TB的商品硬盘售价约为350美元。假设每5分钟有3 GB的数据需要时间戳并分布在网络上,即每天需要732 GB的数据存储量,或每月约22 TB。硬件成本为一年15个硬盘,容量为18 TB,年度增量成本为5,000美元。
我们考虑的情景是Radiant网络继续增长,并对挖矿、存档和代理节点的处理需求产生了哪些影响。为了比较,就比特币区块链而言,在撰写本文时,大约有8300万个未使用交易输出(unspent transaction outputs),总计约占据6GB的数据用于防止双重支付。挖矿节点只需要保留最近的几百个区块,而旧区块可以从存档节点中获取。对于代理节点来说,必须保留与其所服务应用程序相关的未使用交易输出的相应部分,扩展性是基于带宽而不是存储需求的函数。
根据我们的假设,每5分钟会产生大小为3GB的区块,这些区块将被时间戳并分布到整个网络中,即每秒大约有20,000笔交易,每笔交易的平均大小为500字节,或者每个区块大约有6,000,000笔交易。对于每种类型的节点,网络能够充分扩展以满足全球需求。这相当于地球上80亿人每5天进行一笔交易。
挖矿节点是唯一构建在其他节点区块之上的节点类型。为了保持共识,只需同步未使用交易输出(UTXO)集,并仅保留最近的大约一百个区块。在撰写本文时,高性能通用固态驱动器可以实现超过120,000 IOPS,价格约为500美元,容量为280GB,因此可以处理大约每秒20,000笔交易(假设每个交易有2个输入和2个输出)。对于每笔交易,有2次读取输入、2次更新输入和2次写入新输出:120,000 / 6 = 20,000笔交易/秒。
存档节点提供历史区块数据,适用于机器学习、分析和数据仓库应用。存档节点可以为挖矿节点提供引导,并对UTXO集进行定期一致性检查。在撰写本文时,容量为18TB的通用硬盘售价约为350美元。假设每5分钟产生3GB的数据,每天需要732GB的数据存储空间,每月约为22TB。一年的硬件成本是购买15个18TB容量的硬盘,每年的增量成本约为5,000美元。
在节点类型中,代理节点最容易扩展,因为它们只处理与其所服务应用程序相关的交易类型。因此,代理节点可以从Web服务器扩展到具有有限处理和存储能力的轻量级物联网设备,同时仍能适应3GB的区块或每秒20,000笔交易。例如,一家公司可能希望跟踪其作为数字资产创建的忠诚度积分的使用情况,因此只需要从每个区块中选择与该币种唯一标识符匹配的一小部分交易更新。
在撰写本文时,一种商用计算设备Raspberry Pi 4售价约为275美元,它配备了四核1.5 GHz处理器和4GB的RAM,可用于快速过滤和丢弃不相关的交易,每个核心的处理速度可达5,000笔交易。当然,这只是一个例子,说明处理大区块是多么合理,而在典型的Web应用程序中可能还会有更多可用的核心。
排名前25位的国家中位带宽速度超过100 MBPS,即每秒下载约为10 MB,许多互联网服务提供商还提供无限下载服务。每5分钟3 GB区块的带宽需求约为每秒10 MB,总计每月22 TB。还可以创建代理节点的层次结构,以降低带宽容量较低的代理节点的总带宽需求。
我们提出了一种在不依赖信任的情况下进行数字资产管理的系统。我们从由数字签名生成的硬币这一基本构建模块开始,这提供了对所有权的强大控制。基于所需的规则和激励机制,我们引入了两种新颖的方法来在常数O(1)的时间和空间内对数字资产进行身份验证和跟踪。这两种方法都独立地提供了一个通用的数学归纳证明系统,可以编码任何可能的数字资产配置。该系统在交易边界内部和跨越交易边界具有图灵完备性,无需依赖第二层协议。Radiant是一种突破性的设计,它既具备了未使用交易输出(UTXO)区块链的性能和并行性优势,又具备了基于以太坊虚拟机(EVM)的基于账户的区块链的合约能力。
[1] Satoshi Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System" URL https://bitcoin.org/bitcoin.pdf, 2009.
[2] Vitalik Buterin, "Ethereum: A Next-Generation Smart Contract and Decentralized Application Platform." URL https://ethereum.org/en/whitepaper/, 2014.
[3] Wikipedia contributors. "Turing completeness." Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, URL https://en.wikipedia.org/wiki/Turing_completeness, 21 Jul. 2022
[4] R.C. Merkle, "Protocols for public key cryptosystems," In Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, pages 122-133, April 1980.
[5] Britannica, T. Editors of Encyclopaedia. "mathematical induction." Encyclopedia Britannica, URL https://www.britannica.com/science/mathematical-induction, 2018
Hindi version of the Radiant whitepaper
रेडियंट डेवलपर्स
August 11, 2022
radiantblockchain.org
अमूर्त. रेडिएंट नेटवर्क एक पीयर-टू-पीयर डिजिटल एसेट सिस्टम है जो केंद्रीय पार्टी के माध्यम से बिना मूल्य के प्रत्यक्ष विनिमय को सक्षम बनाता है। मूल बिटकॉइन [1] प्रोटोकॉल प्रदान करता है जो एक सहकर्मी से सहकर्मी इलेक्ट्रॉनिक कैश सिस्टम बनाने के लिए आवश्यक है, लेकिन लेनदेन इतिहास को सत्यापित करने की क्षमता का अभाव है और इसलिए, डिजिटल संपत्ति को मान्य करने के लिए उपयोग नहीं किया जा सकता है। डिजिटल हस्ताक्षर और आउटपुट बाधाएं समाधान का हिस्सा प्रदान करती हैं, लेकिन अगर किसी विश्वसनीय तृतीय पक्ष को अभी भी डिजिटल संपत्ति को मान्य करने की आवश्यकता है तो मुख्य लाभ खो जाते हैं। बिटकॉइन के समान, रेडियंट नेटवर्क को न्यूनतम संरचना की आवश्यकता होती है, और प्रूफ-ऑफ़-वर्क की चल रही हैश-आधारित श्रृंखला में टाइमस्टैम्प लेनदेन होता है। हम डिजिटल संपत्ति को मान्य करने के लिए दो तकनीकों का परिचय देते हैं: अद्वितीय संदर्भ और एक सामान्य उद्देश्य इंडक्शन प्रूफ सिस्टम, जो दोनों निरंतर O(1) समय और स्थान में काम करते हैं। एक अप्रयुक्त लेनदेन आउटपुट (यूटीएक्सओ) आधारित आर्किटेक्चर की अंतर्निहित समांतरता और प्रदर्शन विशेषताओं से समझौता किए बिना, किसी भी तरीके से आउटपुट बनाना संभव है। इसलिए, उपयोगकर्ता अपनी इच्छानुसार रेडियंट नेटवर्क को छोड़ सकते हैं और फिर से जुड़ सकते हैं और अपनी डिजिटल संपत्ति की अखंडता और प्रामाणिकता का आश्वासन दे सकते हैं।
ब्लॉकचेन, या डिजिटल लेज़र तकनीक (डीएलटी) के साथ वाणिज्य, कई मामलों में डिजिटल संपत्ति को प्रमाणित करने के लिए विश्वसनीय पार्टियों के रूप में सेवा करने वाले जारीकर्ताओं और संरक्षकों पर निर्भर करता है। हालांकि ये प्रणालियां इलेक्ट्रॉनिक भुगतान जैसे लेनदेन के लिए काफी अच्छी तरह से काम करती हैं, फिर भी वे उन्नत उपयोगों के लिए विश्वास आधारित मॉडल की अंतर्निहित कमजोरियों से ग्रस्त हैं। एथेरियम वर्चुअल मशीन (ईवीएम) [2] आधारित ब्लॉकचेन सभी प्रकार के कार्यक्रमों के लिए बहुत लचीले हैं, लेकिन उच्च शुल्क माइक्रोपेमेंट अनुप्रयोगों के लिए अव्यावहारिक है।
हमें एक इलेक्ट्रॉनिक भुगतान प्रणाली की आवश्यकता है जिसका उपयोग कम शुल्क, उच्च प्रदर्शन और उन्नत प्रोग्रामिंग क्षमताओं के साथ डिजिटल संपत्ति प्रबंधन प्रणाली के लिए किया जा सके। इस पत्र में, हम दो नई तकनीकों का उपयोग करके ब्लॉकचैन स्केलिंग और अनुबंध की समस्या का समाधान प्रस्तावित करते हैं जो अद्वितीय संदर्भ प्रदान करते हैं और एक सामान्य इंडक्शन प्रूफ सिस्टम है, जो ट्यूरिंग पूर्ण [3] प्रोग्राम को लेन-देन की सीमाओं में संभव बनाता है। प्रस्तावित प्रणाली विकेंद्रीकृत है, बिटकॉइन जैसे प्रूफ-ऑफ-वर्क सर्वसम्मति तंत्र का उपयोग करती है, लेकिन काफी उच्च स्तर के थ्रूपुट के साथ, ईवीएम-आधारित ब्लॉकचेन की समान लचीलापन प्रदान करते हुए, बहुत कम शुल्क के साथ।
बिटकॉइन के समान, हम एक इलेक्ट्रॉनिक सिक्के को डिजिटल हस्ताक्षरों की एक श्रृंखला के रूप में परिभाषित करते हैं। जहां रेडिएंट में लेन-देन भिन्न होता है, वह यह है कि प्रत्येक मालिक सिक्के को अनलॉक करने के लिए आवश्यक इनपुट पैरामेट्स के अलावा पिछले लेनदेन के हैश पर डिजिटल रूप से हस्ताक्षर करके सिक्के को स्थानांतरित करता है। लेन-देन नई आउटपुट लॉकिंग बाधाएँ भी बनाता है, जिसमें उपयोगकर्ता द्वारा परिभाषित किसी भी अन्य नियमों के बीच अगले मालिक की सार्वजनिक कुंजी शामिल हो सकती है।
Diagram 1. रेडियंट लेनदेन.
यह सत्यापित करने के लिए कि दोहरा खर्च नहीं हुआ है, हम एक वितरित टाइमस्टैम्प सर्वर का उपयोग करते हैं, एक हैश-आधारित प्रूफ-ऑफ़-वर्क सिस्टम का उपयोग करके यह निर्धारित करने के लिए कि कौन सा लेन-देन पहले हुआ है, प्रामाणिक इतिहास को व्यवस्थित करने के लिए। लेनदेन ब्लॉकों में आयोजित किए जाते हैं। परंपरा के अनुसार, पहला लेन-देन, जिसे "कॉइनबेस ट्रांजेक्शन" कहा जाता है, एक ब्लॉक में एक विशेष लेनदेन होता है जो ब्लॉक के निर्माता के स्वामित्व वाले एक नए सिक्के को शुरू करता है। ब्लॉक एक साथ जंजीर से बंधे होते हैं और लेन-देन को एक मर्कल ट्री [4] में व्यवस्थित करते हैं। सभी लेन-देन, पहले के अपवाद के साथ, एक निर्देशित विश्वकोश ग्राफ (DAG) बनाने वाले पिछले लेन-देन का संदर्भ देना चाहिए, जहां सभी सिक्के अंततः एक ब्लॉक की शुरुआत में कम से कम एक विशेष लेनदेन से जुड़ते हैं।
Diagram 2. ब्लॉक संरचना; लेन-देन मर्कल ट्री में व्यवस्थित होते हैं.
डिजिटल संपत्ति के संदर्भ में इस डिजाइन के साथ समस्या यह है कि केवल एक प्रकार का सिक्का या डिजिटल संपत्ति है, और उपयोगकर्ता-परिभाषित सिक्कों (या डिजिटल संपत्ति प्रकार) की कोई अवधारणा नहीं है। खाते की मूल इकाई में इलेक्ट्रॉनिक भुगतान जैसे लेनदेन के लिए डिजाइन काफी अच्छी तरह से काम करता है, हालांकि यह अन्य प्रकार के सिक्कों या डिजिटल संपत्ति के लिए इस्तेमाल होने के लिए तुरंत खुद को उधार नहीं देता है। एक सामान्य समाधान एक लेनदेन इंडेक्सर जैसी सेवा शुरू करना है जो डिजिटल संपत्ति के निर्माण को दर्शाने के लिए विशेष डेटा अनुक्रमों के लिए लेनदेन की निगरानी करता है। इस समाधान के साथ समस्या यह है कि यह सेवा चलाने वाली कंपनी पर निर्भर करता है, वेब पर किसी भी अन्य सेवा की तरह, डिजिटल संपत्ति की प्रामाणिकता पर भरोसा करने की आवश्यकता होती है।
हमें उपयोगकर्ताओं के लिए कस्टम सिक्का प्रकारों के निर्माण का संकेत देने के लिए एक तरीका चाहिए, लेकिन डेटा प्रस्तुति के लिए उपयोग की जाने वाली विश्वसनीय सेवा पर भरोसा नहीं करना चाहिए।
हम एक कस्टम इलेक्ट्रॉनिक सिक्के या डिजिटल संपत्ति को डिजिटल हस्ताक्षर की एक श्रृंखला के रूप में परिभाषित करते हैं। एक डिजिटल संपत्ति एक डिजिटल संपत्ति बनाने या बनाने के लिए एक विशेष लेनदेन मार्कर का उपयोग करके एक उपयोगकर्ता-परिभाषित सिक्का प्रकार है, जिसे "एसेटबेस लेनदेन" कहा जाता है। कॉइनबेस लेन-देन के समान, जो सिस्टम में नए सिक्कों को इंजेक्ट करता है, एसेटबेस ट्रांजेक्शन रंग या इलेक्ट्रॉनिक सिक्के को उसके जीवनकाल के लिए एक अद्वितीय 36-बाइट पहचानकर्ता के साथ टैग करता है। कस्टम इलेक्ट्रॉनिक सिक्के को बेस कॉइन प्रकार के शीर्ष पर ओवरले किया जाता है और समान तरीके से कार्य करता है। एसेटबेस लेन-देन ब्लॉक में कहीं भी दिखाई दे सकता है और किसी भी कस्टम नियम और बाधाओं को पहले से तय कर सकता है।
Diagram 3. उपयोगकर्ता परिभाषित सिक्का प्रकारों का प्रतिनिधित्व करने वाले लेनदेन — या डिजिटल संपत्ति.
इसे पूरा करने के लिए हमें सिक्के के प्रकार (डिजिटल संपत्ति) की प्रामाणिकता को ट्रैक करने के लिए एक स्थिर विशिष्ट पहचानकर्ता और एक लेनदेन तंत्र बनाने की आवश्यकता है। सिस्टम के उपयोगकर्ताओं को इस बात का सबूत होना चाहिए कि कस्टम सिक्का प्रकार जालसाजी नहीं हैं और डिजिटल संपत्ति का सही प्रतिनिधित्व करते हैं।
Diagram 4. कस्टम उपयोगकर्ता-परिभाषित सिक्का प्रकार एक विशेष टकसाल लेनदेन से परिभाषित होते हैं। सिक्के के प्रकार को वर्गीकृत करने के लिए एक विशिष्ट पहचानकर्ता का उपयोग किया जाता है.
किसी सिक्के के प्रकार के लिए एक विशिष्ट पहचानकर्ता को लागू करने के लिए, हम एक विशेष मार्कर लेनदेन का उपयोग करते हैं, जिसे "एसेटबेस लेनदेन" कहा जाता है, जो डिजिटल हस्ताक्षरों की श्रृंखला की शुरुआत (मिंट) के रूप में कार्य करता है। अद्वितीय पहचानकर्ता के लिए एक नए डेटा-संरचना की आवश्यकता के बजाय, हम लेन-देन पहचानकर्ता और आउटपुट इंडेक्स का पुन: उपयोग करते हैं, जिसे "आउटपॉइंट" कहा जाता है, सिक्का प्रकार के लिए अद्वितीय पहचानकर्ता के रूप में। यह आश्वासन दिया जाता है कि आउटपॉइंट्स (36-बाइट्स) यादृच्छिक और विश्व स्तर पर अद्वितीय हैं।
एक प्रोग्रामिंग निर्देश, जिसे OP_PUSHINPUTREF
कहा जाता है, का उपयोग आउटपुट के संदर्भ को जोड़ने के लिए किया जाता है। निर्देश ठीक एक 36-बाइट पैरामीटर को स्वीकार करता है जो या तो 1) खर्च किए जा रहे आउटपुट में से किसी एक के आउटपॉइंट से मेल खाना चाहिए, या 2) वही 36-बाइट मान पहले से निर्दिष्ट OP_PUSHINPUTREF
में खर्च किए जा रहे आउटपुट में से एक में दिखाई देता है . लेन-देन आउटपुट में किसी दिए गए मूल्य के प्रकट होने का एकमात्र तरीका यह है कि, कुछ पूर्वजों के लेन-देन के माध्यम से, यह प्रारंभिक माइनिंग एसेटबेस लेनदेन से आउटपॉइंट से मेल खाता है। लेन-देन जो एक मान निर्दिष्ट करते हैं जो किसी भी शर्त को पूरा नहीं करते हैं, अमान्य हैं।
Diagram 5. अद्वितीय पहचानकर्ताओं को खर्च किए जा रहे आउटपुट में से किसी एक के आउटपॉइंट से मिलान करके प्रारंभ किया जाता है, और तब तक बनाए रखा जाता है जब तक कि खर्च किए जा रहे आउटपुट में से कम से कम एक में स्क्रिप्ट बॉडी में एक ही अद्वितीय पहचानकर्ता होता है.
यह सरल प्रोग्रामिंग निर्देश एक विशिष्ट पहचानकर्ता प्रदान करता है जिसे उन्नत नियम बनाने के लिए एक स्थिर संदर्भ के रूप में उपयोग किया जा सकता है। उदाहरण के लिए, विभिन्न प्रकार के सिक्के, डिजिटल संपत्ति, अब अन्य प्रकार के सिक्कों पर निर्भर हो सकते हैं। चूंकि सभी डेटा लेन-देन के लिए स्थानीय है, इसके तत्काल मूल इनपुट लेनदेन के माध्यम से, ग्राहकों और सेवाओं के लिए O(1) निरंतर समय और स्थान में डिजिटल संपत्ति की प्रामाणिकता को मान्य करना आसान है, एक विश्वसनीय सेवा की आवश्यकता से परहेज .
एक वैकल्पिक तरीके से विशिष्ट पहचानकर्ता बनाना संभव है और एक संशोधित लेनदेन हैश एल्गोरिथम का उपयोग करके गणितीय प्रेरण [5] प्रमाण के लिए एक तंत्र भी प्रदान करता है। इनपुट स्क्रिप्ट को खर्च किए जा रहे मूल लेन-देन को स्वीकार करने की अनुमति देकर, नियम यह सत्यापित कर सकते हैं कि माता-पिता और उसके ग्रैंड-पैरेंट आवश्यक नियमों के अनुरूप हैं। स्पष्ट समस्या यह है कि मूल लेन-देन की प्रत्येक पूर्ण प्रतिलिपि एम्बेडेड होने के कारण, एक घातीय आकार विस्फोट होता है और तकनीक के व्यावहारिक उपयोग को रोकता है। लेनदेन को संपीड़ित करने का एक तरीका आवश्यक है, ताकि पूर्ण लेनदेन सामग्री की आवश्यकता के बजाय लेनदेन हैश प्राप्त करने के बजाय एक निश्चित आकार के डेटा-संरचना का उपयोग किया जा सके।
Diagram 6. पूर्ण माता-पिता लेनदेन सत्यापन, इनपुट में पूर्ण मूल लेनदेन को एम्बेड करके गणितीय प्रेरण प्रमाण जिसके परिणामस्वरूप घातीय लेनदेन आकार में वृद्धि हुई है.
हम बिटकॉइन में उपयोग किए जाने वाले लेन-देन हैश एल्गोरिथ्म को संशोधित करके इसे पूरा कर सकते हैं, जिसमें एक डबल शा-256 डाइजेस्ट की गणना क्रमबद्ध लेनदेन से की जाती है, एक नए संस्करण में जो पहले हैश प्राप्त करने के लिए लेनदेन सामग्री को सारांशित करता है। हम बिटकॉइन में संस्करण 1 और संस्करण 2 के उपयोग से इसे अलग करने के लिए लेन-देन हैश एल्गोरिथम संस्करण 3 पेश करते हैं। प्रक्रिया एक मध्यवर्ती हैश के लिए प्रत्येक क्षेत्र, या एक लेनदेन के घटक को हैश करना है, जिसे एक निश्चित आकार के इनपुट के रूप में इस्तेमाल किया जा सकता है और इस तरह घातीय लेनदेन के आकार में वृद्धि से बचा जा सकता है।
हम निम्नलिखित 112-बाइट डेटा-संरचना का उपयोग करते हैं, पूर्ण क्रमबद्ध लेन-देन बाइट्स के बजाय, जो अंत में लेनदेन हैश प्राप्त करने के लिए डबल sha-256 हैशेड है।
लेन-देन संस्करण 3 हैश प्रीइमेज फ़ील्ड:
लेन-देन का nVersion(=3) (4 बाइट थोड़ा एंडियन)
nTotalInputs (4 बाइट थोड़ा एंडियन)
हैशप्रेवाउटइनपुट्स (32 बाइट हैश)
हैशसीक्वेंस (32 बाइट हैश)
nTotalOutputs (4 बाइट थोड़ा एंडियन)
हैशऑटपुटहैश (32 बाइट हैश)
लेन-देन का लॉकटाइम (4 बाइट लिटिल एंडियन)
संस्करण 3 के लेन-देन के लिए लेन-देन हैश एल्गोरिथ्म का उपयोग करके, हम लेन-देन के आकार में वृद्धि को रोकने के लिए गणितीय प्रेरण प्रमाण के प्रत्येक चरण में माता-पिता और दादा-दादी के लेनदेन को एम्बेड करने में सक्षम हैं, और आवश्यक नियमों को लागू कर सकते हैं।
Diagram 7. कंप्रेस्ड पेरेंट ट्रांजेक्शन वैलिडेशन, मैथमैटिकल इंडक्शन प्रूफ एंबेडिंग द्वारा ट्रांजैक्शन हैश वर्जन 3 प्रीइमेज डेटा-स्ट्रक्चर ऑफ पेरेंट एंड ग्रैंड-पैरेंट ताकि मनमाने नियमों और बाधाओं को लागू किया जा सके.
नेटवर्क टोपोलॉजी एक लगभग पूरा ग्राफ है, जिसमें हर माइनिंग नोड हर दूसरे माइनिंग नोड से जुड़ा होता है। नेटवर्क चलाने के चरण बिटकॉइन के समान हैं, विभिन्न नोड प्रकारों के लिए कुछ अंतरों के साथ: माइनिंग नोड्स, एजेंट नोड्स, आर्काइव नोड्स। खनन नोड्स ब्लॉक के सक्रिय प्रकाशक हैं और अन्य सभी नोड्स के साथ आम सहमति बनाए रखते हैं, आर्काइव नोड्स ऐतिहासिक ब्लॉक डेटा की सेवा करते हैं, और एजेंट नोड्स ब्लॉक को फ़िल्टर करने और उनके द्वारा प्रदान किए जाने वाले अनुप्रयोगों के हित के लेन-देन को ट्रैक करने के लिए डिज़ाइन किए गए हैं। आर्काइव और एजेंट नोड एक ही पीयर-टू-पीयर नेटवर्क पर काम कर सकते हैं और फिर भी ब्लॉक नहीं बनाते हैं। गैर-खनन नोड्स जैसे आर्काइव और एजेंट नोड्स को कभी-कभी नेटवर्क में उनकी भूमिका को अलग करने के लिए "श्रोता नोड्स" के रूप में संदर्भित किया जाता है।
Diagram 8. खनन नोड अच्छी तरह से जुड़े हुए हैं और एक दूसरे के ब्लॉक के शीर्ष पर बने हैं। ऐतिहासिक विश्लेषण और बूटस्ट्रैपिंग उद्देश्यों के लिए आर्काइव नोड्स पूरे ब्लॉक को स्टोर करते हैं। एजेंट नोड श्रोता नोड होते हैं जो ग्राहकों की सेवा के लिए लेनदेन को फ़िल्टर और स्टोर करते हैं.
खनन नोड्स अन्य खनन नोड्स के बीच लगभग पूर्ण ग्राफ में अच्छी तरह से जुड़े हुए हैं। उनका काम एक दूसरे के ब्लॉक के शीर्ष पर निर्माण करना और हाल के कुछ सौ ब्लॉकों के लिए आम सहमति बनाए रखना है, और दोहरे खर्च की रोकथाम के लिए UTXO सेट को बनाए रखना है।
एजेंट नोड्स को केवल एक सबसेट लेनदेन को स्टोर करने की आवश्यकता होती है, उदाहरण के लिए, एक विशिष्ट सिक्का प्रकार या डिजिटल संपत्ति। बड़े ब्लॉक के साथ भी, एक एजेंट नोड संदर्भों या विशिष्ट बाइट-अनुक्रमों द्वारा लेन-देन को जल्दी से फ़िल्टर कर सकता है, फिर उन लेनदेन को एप्लिकेशन प्रोग्रामर इंटरफ़ेस के माध्यम से सेवा देने के लिए संग्रहीत करता है। सहयोगी एजेंटों के बीच, प्रत्येक ब्लॉक में लेन-देन के लिए एक मर्कल ट्री रूट हैश की सार्वजनिक रूप से घोषणा की जा सकती है जो अन्य एजेंटों और उपभोक्ताओं को संकेत देने के लिए पूर्व-निर्धारित पैटर्न से मेल खाता है कि एजेंट ने कौन से लेनदेन को संसाधित किया है।
डेटा वेयरहाउसिंग, एनालिटिक्स और मशीन लर्निंग सहित विभिन्न अनुप्रयोगों के लिए आर्काइव नोड्स का उपयोग पूरे ब्लॉक की बैकअप प्रतियां बनाने के लिए किया जाता है। चूंकि पुरालेख नोड सीधे खनन में शामिल नहीं होते हैं, इसलिए उनके पास खनन या एजेंट नोड्स के समान वास्तविक समय प्रदर्शन और बैंडविड्थ आवश्यकताएं नहीं होती हैं।
हम उस परिदृश्य पर विचार करते हैं जहां रेडियंट नेटवर्क बढ़ता रहता है और यह खनन, संग्रह और एजेंट नोड्स की प्रसंस्करण आवश्यकताओं के लिए क्या आवश्यक है। तुलना के लिए, लेखन के समय, बिटकॉइन ब्लॉकचेन के लिए लगभग 83 मिलियन अव्ययित लेनदेन आउटपुट हैं, दोहरे खर्च को रोकने के लिए कुल लगभग 6 जीबी आवश्यक डेटा के लिए। यह केवल आवश्यक है कि सबसे हाल के कुछ सौ ब्लॉकों को खनन नोड्स द्वारा रखा जाए, पुराने ब्लॉक आर्काइव नोड्स से उपलब्ध हैं। एजेंट नोड्स के लिए, अव्ययित लेन-देन आउटपुट के प्रासंगिक विभाजन को रखना आवश्यक है जो उनके द्वारा प्रदान किए जाने वाले अनुप्रयोगों से संबंधित है, स्केलिंग बैंडविड्थ का एक कार्य है न कि भंडारण आवश्यकताओं का।
हमारे उद्देश्यों के लिए, हम मानते हैं कि हर 5 मिनट में 3 जीबी आकार के ब्लॉक होंगे जिन्हें टाइमस्टैम्प किया जाएगा और पूरे नेटवर्क में वितरित किया जाएगा, या 500 बाइट्स के औसत लेनदेन आकार के साथ प्रति सेकंड लगभग 20,000 लेनदेन, या प्रति ब्लॉक लगभग 6,000,000 लेनदेन होंगे। हम दिखाते हैं कि प्रत्येक प्रकार के नोड के लिए, वैश्विक मांग को पूरा करने के लिए नेटवर्क पर्याप्त रूप से स्केल करने में सक्षम है। यह ग्रह पर 8 अरब लोगों में से प्रत्येक के लिए प्रत्येक 5 दिनों में लगभग 1 लेन-देन के बराबर है।
माइनिंग नोड एकमात्र नोड प्रकार हैं जो एक दूसरे के ब्लॉक के ऊपर निर्मित होते हैं। आम सहमति बनाए रखने के लिए, खर्च न किए गए लेन-देन आउटपुट (यूटीएक्सओ) सेट को सिंक्रनाइज़ करना और केवल लगभग पिछले सौ ब्लॉकों को बनाए रखना पर्याप्त है। लेखन के समय, उच्च प्रदर्शन कमोडिटी सॉलिड-स्टेट ड्राइव 120,000 IOPS से ऊपर की ओर प्राप्त करने में सक्षम हैं, जिसकी लागत 280 GB के लिए लगभग $500 USD है, और इसलिए प्रति सेकंड लगभग 20,000 लेनदेन को संभाल सकती है (यह मानते हुए कि प्रत्येक लेनदेन में 2 इनपुट और 2 आउटपुट हैं) . इनपुट के लिए 2 रीड, इनपुट के लिए 2 अपडेट और नए आउटपुट के लिए 2 राइट हैं: 120,000/6 = 20,000 लेनदेन/सेकंड।
आर्काइव नोड्स ऐतिहासिक ब्लॉक डेटा प्रदान करते हैं और मशीन लर्निंग, एनालिटिक्स और डेटा वेयरहाउसिंग एप्लिकेशन के लिए उपयुक्त हैं। आर्काइव नोड्स खनन नोड्स के बूटस्ट्रैपिंग को पूरक कर सकते हैं और यूटीएक्सओ सेट पर आवधिक स्थिरता जांच चला सकते हैं। लेखन के समय, 18 टीबी की कमोडिटी हार्ड डिस्क लगभग $350 USD में उपलब्ध हैं। मान लें कि हर 5 मिनट में 3 जीबी डेटा प्रतिदिन 732 जीबी डेटा स्टोरेज की आवश्यकता के बराबर है, या लगभग 22 टीबी प्रति माह। $5,000 USD की वार्षिक वृद्धिशील लागत के लिए, एक वर्ष के लिए हार्डवेयर लागत 15 हार्ड ड्राइव है, जिसमें 18 टीबी क्षमता है।
एजेंट नोड्स नोड प्रकारों के बीच सबसे आसानी से स्केल करते हैं क्योंकि वे केवल उनके द्वारा प्रदान किए जाने वाले अनुप्रयोगों के लिए प्रासंगिक लेनदेन प्रकारों को संसाधित करते हैं। परिणामस्वरूप एजेंट नोड्स एक वेब सर्वर से लेकर सीमित प्रोसेसिंग और स्टोरेज क्षमता वाले हल्के IoT डिवाइस तक हो सकते हैं, और फिर भी 3 जीबी ब्लॉक, या प्रति सेकंड 20,000 लेनदेन के साथ शांति बनाए रख सकते हैं। उदाहरण के लिए, एक कंपनी डिजिटल संपत्ति के रूप में बनाए गए अपने लॉयल्टी पॉइंट्स के उपयोग को ट्रैक करना चाह सकती है, और इसलिए प्रत्येक ब्लॉक से लेन-देन अपडेट का एक छोटा सा उपसमुच्चय चुनने की आवश्यकता होती है जो उस सिक्के के प्रकार के लिए विशिष्ट पहचानकर्ता से मेल खाता हो।
लेखन के समय, एक वाणिज्यिक कंप्यूटिंग डिवाइस, रास्पबेरी पाई 4, लगभग $275 यूएसडी में बिकता है जिसमें क्वाडकोर 1.5 गीगाहर्ट्ज प्रोसेसर और 4 जीबी रैम है, जिसका उपयोग त्वरित रूप से फ़िल्टर करने और अप्रासंगिक लेनदेन को त्यागने के लिए किया जा सकता है। प्रति कोर 5,000 लेनदेन। बेशक, यह सिर्फ एक उदाहरण है कि बड़े ब्लॉकों को संसाधित करना कितना उचित है, एक विशिष्ट वेब एप्लिकेशन में कई और कोर उपलब्ध हो सकते हैं।
शीर्ष 25 देशों की औसत बैंडविड्थ गति 100 एमबीपीएस या लगभग 10 एमबी/सेकंड डाउनलोड से अधिक है, जिसमें कई इंटरनेट सेवा प्रदाता असीमित डाउनलोड की पेशकश करते हैं। प्रत्येक 5 मिनट में 3 जीबी ब्लॉक के लिए बैंडविड्थ की आवश्यकता कुल 22 टीबी प्रति माह के लिए लगभग 10 एमबी/सेकंड है। कम बैंडविड्थ क्षमता वाले एजेंट नोड्स के लिए कुल बैंडविड्थ आवश्यकताओं को फ़िल्टर करने के लिए एजेंट नोड्स के पदानुक्रम भी बनाए जा सकते हैं।
हमने भरोसे पर भरोसा किए बिना डिजिटल संपत्ति प्रबंधन के लिए एक प्रणाली प्रस्तावित की है। हमने डिजिटल सिग्नेचर से बने सिक्कों के बुनियादी बिल्डिंग ब्लॉक्स के साथ शुरुआत की, जो स्वामित्व का मजबूत नियंत्रण प्रदान करता है। आवश्यक नियमों और प्रोत्साहनों से, हमने निरंतर O(1) समय और स्थान में डिजिटल संपत्ति को प्रमाणित करने और ट्रैक करने के लिए दो नए तरीके पेश किए। दोनों विधियाँ स्वतंत्र रूप से एक सामान्य गणितीय इंडक्शन प्रूफ सिस्टम प्रदान करती हैं जो किसी भी संभावित डिजिटल एसेट कॉन्फ़िगरेशन को एनकोड कर सकता है। सिस्टम द्वितीयक परतों की आवश्यकता के बिना लेनदेन सीमाओं के भीतर और उसके पार ट्यूरिंग पूर्ण है। दीप्तिमान एक सफल डिजाइन है जो खर्च न किए गए लेनदेन आउटपुट (यूटीएक्सओ) ब्लॉकचैन का प्रदर्शन और समानता लाभ प्रदान करता है, लेकिन एथेरियम वर्चुअल मशीन (ईवीएम) पर आधारित खाता-आधारित ब्लॉकचेन की अनुबंध क्षमता के साथ।
[1] सतोशी नाकामोटो, "बिटकॉइन: ए पीयर-टू-पीयर इलेक्ट्रॉनिक कैश सिस्टम" URL https://bitcoin.org/bitcoin.pdf, 2009.
[2] विटालिक ब्यूटिरिन, "एथेरियम: ए नेक्स्ट-जेनरेशन स्मार्ट कॉन्ट्रैक्ट एंड डिसेंट्रलाइज्ड एप्लीकेशन प्लेटफॉर्म।" URL https://ethereum.org/en/whitepaper/, 2014.
[3] विकिपीडिया योगदानकर्ता। "ट्यूरिंग पूर्णता।" विकिपीडिया, मुक्त विश्वकोश। विकिपीडिया, मुक्त विश्वकोश, URL https://en.wikipedia.org/wiki/Turing_completeness, 21 Jul. 2022
[4] आर.सी. मेर्कले, "सार्वजनिक कुंजी क्रिप्टो सिस्टम के लिए प्रोटोकॉल," In Proc. 1980 Symposium on Security and Privacy, IEEE Computer Society, pages 122-133, April 1980.
[5] ब्रिटानिका, टी. एनसाइक्लोपीडिया के संपादक। "गणितीय प्रेरण।" एनसाइक्लोपीडिया ब्रिटानिका, URL https://www.britannica.com/science/mathematical-induction, 2018
[1] Satoshi Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System" , 2009.
Peer-to-peer electronic cash was the first real use case of blockchain technology. But in recent years, smart contracts have grown in popularity. These smart contracts allow people to use the security that blockchains such as Bitcoin, Radiant and Ethereum offer and apply it to use cases other than cash. Especially Decentralised Finance (DeFi) applications such as , and have skyrocketed.
For support please join the Radiant community .
For more information including code for the mining smart contract see the .
Guide documentation sourced from
If you're interested to see what kind of things can be built with CashScript, you can look at the or . If you just want to dive into CashScript, refer to the and other pages in the documentation.
The cashc
command line interface is used to compile CashScript .cash
files into .json
artifact files. These artifacts can be imported and used by the JavaScript SDK or other libraries / applications that use CashScript. For more information on this artifact format refer to .
There are some examples available on the , that can be used to take inspiration from. Further examples of the JavaScript integration can be found on . A simple example is included below.
Tip: Read more about the CashScript language syntax in the .
Tip: Read more about the JavaScript SDK in the .
For Visual Studio Code a dedicated was developed by community contributor . This plugin works with .cash
files and supports syntax highlighting, autocompletion, snippets, linting and even integrated compilation.
The most popular Solidity plugin for Sublime Text 2/3 is . Install this plugin with , open a .cash
file and set Solidity as the syntax language in the Sublime menu bar:
The most popular Solidity plugin for Atom is . Install this plugin and add the following snippet to your Config file:
Bitcoin covenants were first proposed in a paper titled , but several other proposals have been created over the years. In May of 2022 Bitcoin Cash implemented so-called Native Introspection which enables efficient and accessible covenants.
One interesting technique in Bitcoin Cash is called blind escrow, meaning that funds are placed in an escrow contract. This contract can only release the funds to one of the escrow participants, and has no other control over the funds. Non-custodial local exchange uses OP_CHECKDATASIG
to do this, but we can also achieve something similar by restricting recipients with a covenant.
Besides these wasted days it can also be inconvenient to claim at set intervals, rather than the "streaming" model that the Ethereum project employs. Instead of set intervals, you should be able to claim funds at any time during the "money stream". Using simulated state, we can approach a similar system with BCH.
A drawback of using this "simulated state" method is that every new stream is a new contract with its own address. So additional abstractions are needed to provide a clear frontend layer for a system like this. Simulated state can be used to create much more sophisticated systems and is the main idea that powers complex solutions such as the offline payments card , and the Proof-of-Work SLP token .
A final way to restrict outputs is adding OP_RETURN
outputs to the mix. This is necessary when you want to make any SLP-based covenants, such as or the . The integration of SLP and CashScript is still in its early stages though, so that is a topic for a more advanced guide.
Right now we'll use a simpler (but also less useful) example, where we restrict a smart contract to only being able to post on the on-chain social media platform . For this we use LockingBytecodeNullData
, which works slightly different than the other LockingBytecode
objects. While regular outputs have a locking script, OP_RETURN
outputs can include different chunks of data. This is why LockingBytecode
instead takes a list of bytes
chunks.
We have discussed the main uses for covenants as they exist on Bitcoin Cash today. We've seen how we can achieve different use case by combining transaction output restrictions to P2SH
and P2PKH
outputs. We also touched on more advanced subjects such as simulated state and OP_RETURN
outputs. Covenants are the main differentiating factor for BCH smart contracts when compared to BTC, while keeping the same efficient stateless verification. If you're interested in learning more about the differences in smart contracts among BCH, BTC and ETH, read the article .
Compiled contracts can be represented by so-called artifacts. These artifacts contain all information that is needed to interact with the smart contracts on-chain. Artifacts are stored in .json
files so they can be shared and stored for later usage without having to recompile the contract.
The Radiant blockchain introduced a set of opcodes that significantly improves on the capability of the Bitcoin technology it's based on. All these opcodes will be outlined in this article.
Ref: A 36 byte reference, either of normal or singleton type. A reference is created from an input's outpoint and can be propagated with every spend of a UTXO. For a ref to exist in an output there must be a matching input ref of the same type or an input with a matching outpoint. The ref type cannot be changed once it is created.
Normal ref: A type of reference that can be propagated to one or more outputs.
Singleton ref: A type of reference that can only ever exist in a single UTXO. Cannot be propagated to multiple outputs.
State script: The part of the script before and not including an OP_STATESEPARATOR
. Useful for storing state data that can be changed by the contract.
Code script: The part of the script from and including an OP_STATESEPARATOR
. If no state separator is present, the code script is the entire script.
codeScriptHash
: The double SHA-256 of the code script.
SHA-512/256 is the hash function used by Radiant's proof of work algorithm. It is available in script as single and double hash functions. These can be used to validate Radiant block headers in script.
OP_SHA512_256
ce
bytes
hash
SHA-512/256
OP_HASH512_256
cf
bytes
hash
Double SHA-512/256
OP_PUSHINPUTREF
d0
ref
ref
Propagates a ref to an output. A ref of normal type must exist in an input or an input must have an outpoint matching the ref. Ref will be left on the stack.
OP_PUSHINPUTREFSINGLETON
d8
ref
ref
Propagates a singleton ref to an output. A ref of singleton type must exist in an input or an input must have an outpoint matching the ref. Ref will be left on the stack.
OP_REQUIREINPUTREF
d1
ref
ref
A ref of normal type must exist in an input. Ref is not propagated. Ref will be left on the stack.
OP_DISALLOWPUSHINPUTREF
d2
ref
ref
Requires a ref to not exist in any input. Leaves the ref on the stack.
OP_DISALLOWPUSHINPUTREFSIBLING
d3
ref
ref
Requires a ref to not exist in any input sibling. Leaves the ref on the stack.
OP_REFTYPE_UTXO
d9
ref
type
Get the type of a ref from transaction inputs. Returns 0 (not found), 1 (normal type) or 2 (singleton type).
OP_REFTYPE_OUTPUT
da
ref
type
Get the type of a ref from transaction outputs. Returns 0 (not found), 1 (normal type) or 2 (singleton type).
OP_REFHASHDATASUMMARY_UTXO
d4
inputIndex
summary
For the input of the given index returns a hash256 of <nValue><hash256(scriptPubKey)><numRefs><hash(sortedMap(pushRefs))>
OP_REFHASHDATASUMMARY_OUTPUT
d6
outputIndex
summary
For the output of the given index returns a hash256 of <nValue><hash256(scriptPubKey)><numRefs><hash(sortedMap(pushRefs))>
OP_REFDATASUMMARY_UTXO
e1
inputIndex
summary
Return refs used within an input. Pushes a vector of the form <ref1><ref2><ref3>...
. If an input UTXO does not contain at least one reference, then the 36 byte zeroes are pushed.
OP_REFDATASUMMARY_OUTPUT
e2
outputIndex
summary
Return refs used within an output. Pushes a vector of the form <ref1><ref2><ref3>...
. If an input UTXO does not contain at least one reference, then the 36 byte zeroes are pushed.
OP_STATESEPARATOR
bd
Separates the state script from the code script. Only one can exist in a script and it must not exist within an OP_IF. No OP_RETURN can exist in the script when used.
OP_STATESEPARATORINDEX_UTXO
be
inputIndex
separatorIndex
Returns the byte index of the state separator for an input. Returns zero if no separator exists.
OP_STATESEPARATORINDEX_OUTPUT
bf
outputIndex
separatorIndex
Returns the byte index of the state separator for an output. Returns zero if no separator exists.
OP_CODESCRIPTBYTECODE_UTXO
e9
inputIndex
bytecode
Returns the code script bytecode for an input.
OP_CODESCRIPTBYTECODE_OUTPUT
ea
outputIndex
bytecode
Returns the code script bytecode for an output.
OP_STATESCRIPTBYTECODE_UTXO
eb
inputIndex
bytecode
Returns the state script bytecode for an output. Does not include the OP_STATESEPARATOR.
OP_STATESCRIPTBYTECODE_OUTPUT
ec
outputIndex
bytecode
Returns the state script bytecode for an output. Does not include the OP_STATESEPARATOR.
These opcodes provide a set queries on inputs and outputs by ref, ref hash and code script hash. Counts and sums can be performed over many outputs with a single opcode, meaning an unrolled loop in the script is not required.
OP_REFHASHVALUESUM_UTXOS
d5
refHash
photons
Returns the total sum of photons for inputs that match a 32 byte hash of the sorted set of ref asset ids.
OP_REFHASHVALUESUM_OUTPUTS
d7
refHash
photons
Returns the total sum of photons for outputs that match a 32 byte hash of the sorted set of ref asset ids.
OP_REFVALUESUM_UTXOS
db
ref
photons
Returns the total sum of photons for inputs that contain a ref.
OP_REFVALUESUM_OUTPUTS
dc
ref
photons
Returns the total sum of photons for outputs that contain a ref.
OP_REFOUTPUTCOUNT_UTXOS
dd
ref
count
Returns the count of inputs that contain a ref.
OP_REFOUTPUTCOUNT_OUTPUTS
de
ref
count
Returns the count of outputs that contain a ref.
OP_REFOUTPUTCOUNTZEROVALUED_UTXOS
df
ref
count
Returns the count of inputs that contain a ref and contain zero photons.
OP_REFOUTPUTCOUNTZEROVALUED_OUTPUTS
e0
ref
count
Returns the count of inputs that contain a ref and contain zero photons.
OP_CODESCRIPTHASHVALUESUM_UTXOS
e3
codeScriptHash
photons
Returns the total sum of photons for inputs that have a codeScriptHash
.
OP_CODESCRIPTHASHVALUESUM_OUTPUTS
e4
codeScriptHash
photons
Returns the total sum of photons for outputs that have a codeScriptHash
.
OP_CODESCRIPTHASHOUTPUTCOUNT_UTXOS
e5
codeScriptHash
count
Returns the count of inputs that have a codeScriptHash
.
OP_CODESCRIPTHASHOUTPUTCOUNT_OUTPUTS
e6
codeScriptHash
count
Returns the count of outputs that have a codeScriptHash
.
OP_CODESCRIPTHASHZEROVALUEDOUTPUTCOUNT_UTXOS
e7
codeScriptHash
count
Returns the count of inputs that have a codeScriptHash
and contain zero photons.
OP_CODESCRIPTHASHZEROVALUEDOUTPUTCOUNT_OUTPUTS
e8
codeScriptHash
count
Returns the count of outputs that have a codeScriptHash
and contain zero photons.
An integer literal can take a suffix of either monetary or temporary units to add semantic value to these integers and to simplify arithmetic. When these units are used, the underlying integer is automatically multiplied by the value of the unit. The units sats
, finney
, bits
and bitcoin
are used to denote monetary value, while the units seconds
, minutes
, hours
, days
and weeks
are used to denote time.
Bitcoin Cash has support for different kinds of time locks, which can be used to specify time-based conditions inside Bitcoin Cash contracts. These time locks can be separated by three main attributes: location, targeting and metric. The location can be the transaction level or the contract level, but contract level locks also require you to use a corresponding transaction level lock. The targeting can be relative (e.g. at least 4 hours have passed) or absolute (e.g. the block number is at least 600,000). The metric can be blocks or seconds.
tx.time
is used to create absolute time locks. The value of tx.time
can either represent the block number of the spending transaction or its timestamp. When comparing it with values below 500,000,000
, it is treated as a blocknumber, while higher values are treated as a timestamp.
Due to limitations in the underlying Bitcoin Script, tx.time
can only be used in the following way:
tx.age
is used to create relative time locks. The value of tx.age
can either represent a number of blocks, or a number of chunks, which are 512 seconds. The corresponding transaction level time lock determines which of the two options is used.
Due to limitations in the underlying Bitcoin Script, tx.age
can only be used in the following way:
During the validation of a BCH transaction, every transaction input is evaluated in order, and the contract's code is evaluated in the context of the different inputs. this.activeInputIndex
represents the index of the input that is currently being evaluated. This can be used in conjunction with the properties under tx.inputs
.
During the validation of a BCH transaction, every transaction input is evaluated in order, and the contract's code is evaluated in the context of the different inputs. this.activeBytecode
represents the contract bytecode of the input that is currently being evaluated.
Represents the nLocktime
field of the transaction.
Represents the list of inputs of the evaluated transaction. This is an array, and cannot be used on itself. You need to access an input with a specific index and specify the properties you want to access.
Represents the number of inputs in the transaction.
Represents the value of a specific input (in satoshis).
Represents the locking bytecode (scriptPubKey
) of a specific input.
Represents the unlocking bytecode (scriptSig
) of a specific input.
Represents the outpoint transaction hash where a specific input was initially locked.
Represents the outpoint index where a specific input was initially locked.
Represents the nSequence
number of a specific input.
Represents the list of outputs of the evaluated transaction. This is an array, and cannot be used on itself. You need to access an output with a specific index and specify the properties you want to access.
Represents the number of outputs in the transaction.
Represents the value of a specific output (in satoshis).
Represents the locking bytecode (scriptPubKey
) of a specific output.
One of the main use cases of covenants is enforcing transaction outputs (where money is sent). To assist with enforcing these outputs, there is a number of LockingBytecode
objects that can be instantiated. These locking bytecodes can then be compared to the locking bytecodes of transaction outputs.
Creates new P2PKH locking bytecode for the public key hash pkh
.
Creates new P2SH locking bytecode for the script hash scriptHash
.
Creates new OP_RETURN locking bytecode with chunks
as its OP_RETURN data.
Contracts in CashScript are somewhat similar to classes in object-oriented languages. A notable difference is that there is no mutable state. So once a contract is instantiated with certain parameters, these values cannot change. Instead, functions can be called on the contract that act on the contract's values to spend money from the contract. The extension of CashScript source code files is .cash
, and the structure of these source files is explained below.
A contract file may start with a pragma directive to indicate the CashScript version the contract was written for. This ensures that a contract is not compiled with an unsupported compiler version, which could cause unintended side effects.
A CashScript constructor works slightly differently than what you might be used to in regular object-oriented languages. It is not possible to define any statements inside the constructor, as the constructor is only used to store values in the contract. Because of this limited nature, there is no separate constructor
function, but instead the parameters are specified directly on the class definition.
CashScript functions are made up of a collection of statements that determine whether money may be spent from the contract.
The most important statement of CashScript contracts is the require
statement. This statement takes a boolean expression and checks that it evaluates to true
. If it evaluates to false
instead, the transaction fails. This statement is used to ensure that the requirements are met to spend money from the contract.
Variables can be declared by specifying their type and name. All variables need to be initialised at the time of their declaration, but can be reassigned later on - unless specifying the constant
keyword. Since CashScript is strongly typed and has no type inference, it is not possible to use keywords such as var
or let
to declare variables.
After their initial declaration, any variable can be reassigned later on. However, CashScript lacks any compound assignment operators such as +=
or -=
.
The only control structures in CashScript are if
and else
statements. This is due to limitations in the underlying Bitcoin Script which prevent loops, recursion, and return
statements. If-else statements follow usual semantics known from languages like C or JavaScript.
Comments can be added anywhere in the contract file. Comment semantics are similar to languages like JavaScript or C. This means that single-line comments can be added with // ...
, while multiline comments can be added with /* ... */
.
CashScript has several functions builtin for things like cryptographic and arithmetic applications. It also includes many common operators, although some important ones are notably missing due to the limitations of the underlying Bitcoin Script.
Returns the absolute value of argument a
.
Returns the minimum value of arguments a
and b
.
Returns the maximum value of arguments a
and b
.
Returns true
if and only if x >= lower && x < upper
.
Returns the RIPEMD-160 hash of argument x
.
Returns the SHA-1 hash of argument x
.
Returns the SHA-256 hash of argument x
.
Returns the RIPEMD-160 hash of the SHA-256 hash of argument x
.
Returns the double SHA-256 hash of argument x
.
Checks that transaction signature s
is valid for the current transaction and matches with public key pk
.
Performs a multi-signature check using a list of transaction signatures and public keys.
:::note While this function can be used inside your smart contracts, it is not supported by the JavaScript SDK, so it is recommended not to use it. Instead a checkMultiSig()
call can be simulated using multiple checkSig()
calls. :::
Checks that sig s
is a valid signature for message msg
and matches with public key pk
.
An overview of all supported operators and their precedence is included below. Notable is a lack of exponentiation, since these operations are not supported by the underlying Bitcoin Script.
1
Parentheses
(<expression>)
2
Type cast
<type>(<expression>)
3
Object instantiation
new <class>(<args...>)
4
Function call
<function>(<args...>)
5
Tuple index
<tuple>[<index>]
6
Member access
<object>.<member>
7
Unary minus
-
7
Logical NOT
!
8
Multiplication, division and modulo
*
, /
, %
9
Addition and subtraction
+
, -
9
String / bytes concatenation
+
10
Numeric comparison
<
, >
, <=
, >=
11
Equality and inequality
==
, !=
12
Bitwise AND
&
13
Bitwise XOR
^
14
Bitwise OR
|
15
Logical AND
&&
16
Logical OR
||
17
Assignment
=
One interesting use case of Bitcoin Cash is using it for paper tips. With paper tips, you send a small amount of money to an address, and print the corresponding private key on a piece of paper. Then you can hand out these pieces of paper as a tip or gift to people in person. In practice, however, people might not know what to do with these gifts or they might lose or forget about it.
As an alternative, a smart contract can be used for these kinds of gifts. This smart contract allows the recipient to claim their gift at any time, but if they don't claim it in time, the sender can reclaim it.
For better or worse, HODLing and waiting for price increases is one of the main things people want to do with their cryptocurrency. But it can be difficult to hold on to your cryptocurrency when the price is going down. So to prevent weak hands from getting the best of you, it's better to store your stash in a smart contract that enforces HODLing for you.
This smart contract works by connecting with a price oracle. This price oracle is a trusted entity that publishes the BCH/USD price every block. This price is passed into the contract, and only if the price is higher than your target price you can spend the coins.
This involves some degree of trust in the price oracle, but since the oracle produces price data for everyone to use, their incentive to attack your smart contract is minimised. To improve this situation, you can also choose to connect with multiple oracle providers so you do not have to trust a single party.
Donations are a great way to support the projects you love and periodic donations can incentivise continuous improvement to the product. But platforms like Patreon generally take fees of 10%+ and don't accept cryptocurrencies. Instead you can create a peer-to-peer smart contract that allows a recipient to withdraw a specific amount every month.
The contract works by checking that a UTXO is at least 30 days old, after which it uses a covenant to enforce that the pledge
amount is sent to the recipient, while the remainder is sent back to the contract itself. By sending it back the tx.age
counter is effectively reset, meaning this process can only be repeated when another 30 days have past.
Due to the nature of covenants we have to be very specific about the outputs (amounts and destinations) of the transaction. This also means that we have to account for the special case where the remaining contract balance is lower than the pledge
amount, meaning no remainder should be sent back. Finally we have to account for a small fee that has to be taken from the contract's balance to pay the miners.
bool
: The possible values are constants true
and false
.
Operators:
!
(logical negation)
&&
(logical conjunction, “and”)
||
(logical disjunction, “or”)
==
(equality)
!=
(inequality)
int
: Signed integer of 64 bit size.
Operators:
Comparisons: <=
, <
, ==
, !=
, >=
, >
(all evaluate to bool
)
Arithmetic operators: +
, -
, unary -
, *
, /
, %
(modulo).
Note the clear lack of the **
(exponentiation) operator as well as any bitwise operators.
Dates and times are always represented as integers. To get the UTC timestamp of a date use the built-in parser to avoid any potential errors. This will take a date in the format date("YYYY-MM-DDThh:mm:ss")
and convert it to an integer timestamp.
string
: UTF8-encoded byte sequence.
Operators:
+
(concatenation)
==
(equality)
!=
(inequality)
Members:
length
: Number of characters in the string.
split(int)
: Splits the string at the specified index and returns a tuple with the two resulting strings.
reverse()
: Reverses the string.
bytes
: Byte sequence. Can optionally be bound to a byte length by specifying e.g. bytes4
, bytes32
, bytes64
. It is also possible to use byte
as an alias for bytes1
.
Operators:
+
(concatenation)
==
(equality)
!=
(inequality)
Members:
length
: Number of bytes in the sequence.
split(int)
: Splits the byte sequence at the specified index and returns a tuple with the two resulting byte sequences.
reverse()
: Reverses the byte sequence.
Some byte sequences hold specific meanings inside Bitcoin Cash contracts. These have been granted their own types separate from the regular bytes
type.
pubkey
: Byte sequence representing a public key. Generally 33 bytes long.
Operators:
==
(equality)
!=
(inequality)
sig
: Byte sequence representing a transaction signature. Generally 65 bytes long.
Operators:
==
(equality)
!=
(inequality)
datasig
: Byte sequence representing a data signature. Generally 64 bytes long.
Operators:
==
(equality)
!=
(inequality)
Arrays are not assignable and can only be used with the checkMultisig
function using the following syntax:
Tuples are the type that is returned when calling the split
member function on a string
or bytes
type. Their first or second element can be accessed through an indexing syntax similar to other languages:
It is also possible to assign both sides of the tuple at once with a destructuring syntax:
Type casting can be done both explicitly and implicitly as illustrated below. pubkey
, sig
and datasig
can be implicitly cast to bytes
, meaning they can be used anywhere where you would normally use a bytes
type. Explicit type casting can be done with a broader range of types, but is still limited. The syntax of this explicit type casting is illustrated below. Note that you can also cast to bounded bytes
types.
See the following table for information on which types can be cast to other which other types.
The to()
function allows you to add outputs to the transaction. Either a single pair to/amount
pair can be provided, or a list of them. This function can be called any number of times, and the provided outputs will be added to the list of earlier added outputs.
The withOpReturn()
function allows you to add OP_RETURN
outputs to the transaction. The chunks
parameter can include regular UTF-8 encoded strings, or hex strings prefixed with 0x
. This function can be called any number of times, and the provided outputs will be added to the list of earlier added outputs.
The from()
function allows you to provide a hardcoded list of contract UTXOs to be used in the transaction. This overrides the regular UTXO selection performed by the CashScript SDK, so no further selection will be performed on the provided UTXOs. This function can be called any number of times, and the provided UTXOs will be added to the list of earlier added UTXOs.
The withFeePerByte()
function allows you to specify the fee per per bytes for the transaction. By default the fee per bytes is set to 1.0 satoshis, which is nearly always enough to be included in the next block. So it's generally not necessary to change this.
The withHardcodedFee()
function allows you to specify a hardcoded fee to the transaction. By default the transaction fee is automatically calculated by the CashScript SDK, but there are certain use cases where the smart contract relies on a hardcoded fee.
The withMinChange()
function allows you to set a threshold for including a change output. Any remaining amount under this threshold will be added to the transaction fee instead.
The withoutChange()
function allows you to disable the change output. The remaining amount will be added to the transaction fee instead. This is equivalent to withMinChange(Number.MAX_VALUE)
.
The withTime()
function allows you to specify the minimum block number that the transaction can be included in. The time
parameter will be the value of tx.time
inside the smart contract.
After completing a transaction, the send()
function can be used to send the transaction to the BCH network. An incomplete transaction cannot be sent.
After completing a transaction, the build()
function can be used to build the entire transaction and return the signed transaction hex string. This can then be imported into other libraries or applications as necessary.
Transactions can fail for a number of reasons. Most of these are related to the execution of the smart contract (e.g. wrong parameters or a bug in the contract code). But errors can also occur because of other reasons (e.g. a fee that's too low or the same transaction already exists in the mempool). To facilitate error handling in your applications, the CashScript SDK provides an enum of different reasons for a failure.
This Reason
enum only includes errors that are related to smart contract execution, so other reasons have to be caught separately. Besides the Reason
enum, there are also several error classes that can be caught and acted on:
FailedRequireError
, signifies a failed require statement. This includes the following reasons:
Reason.EVAL_FALSE
Reason.VERIFY
Reason.EQUALVERIFY
Reason.CHECKMULTISIGVERIFY
Reason.CHECKSIGVERIFY
Reason.CHECKDATASIGVERIFY
Reason.NUMEQUALVERIFY
FailedTimeCheckError
, signifies a failed time check using tx.time
or tx.age
. This includes the following reasons:
Reason.NEGATIVE_LOCKTIME
Reason.UNSATISFIED_LOCKTIME
FailedSigCHeckError
, signifies a failed signature check. This includes the following reasons:
Reason.SIG_COUNT
Reason.PUBKEY_COUNT
Reason.SIG_HASHTYPE
Reason.SIG_DER
Reason.SIG_HIGH_S
Reason.SIG_NULLFAIL
Reason.SIG_BADLENGTH
Reason.SIG_NONSCHNORR
FailedTransactionError
, signifies a general fallback error. This includes all remaining reasons listed in the Reason
enum as well as any other reasons unrelated to the smart contract execution.
```solidity title="TransferWithTimeout.cash" contract TransferWithTimeout(pubkey sender, pubkey recipient, int timeout) { function transfer(sig recipientSig) { require(checkSig(recipientSig, recipient)); }
}
To ensure that this leftover money does not get lost in the contract, the contract performs an extra check, and adds the remainder to the transaction fee if it's too low.
```solidity title="Announcement.cash" pragma cashscript ^0.7.0;
// This contract enforces making an announcement on Memo.cash and sending the // remaining balance back to the contract. contract Announcement() { function announce() { // Create the memo.cash announcement output bytes announcement = new LockingBytecodeNullData([ 0x6d02, bytes('A contract may not injure a human being or, ' + 'through inaction, allow a human being to come to harm.') ]);
}
Caution: Be careful when using these units in precise calendar calculations though, because not every year equals 365 days and not even every minute has 60 seconds because of .
It can be difficult to fully grasp the intricacies of time locks, so if you're starting out it is recommended to start off with the simplest version: absolute block-based time locks. If you do want to dive into the more advanced uses of time locks, James Prestwich wrote that also fully applies to Bitcoin Cash.
Because of the way time locks work, a corresponding time lock needs to be added to the transaction. The CashScript SDK automatically sets this transaction level time lock to the most recent block number, as this is the most common use case. If you need to use a different block number or timestamp, this should be passed into the CashScript SDK using the function. If the default matches your use case, no additional actions are required.
Because of the way time locks work, a corresponding time lock needs to be added to the transaction. This can be done in the CashScript SDK using the function. However, the value passed into this function will always be treated as a number of blocks, so it is currently not supported to use tx.age
as a number of second chunks.
Introspection functionality is used to create covenant contracts. Covenants are a technique used to put constraints on spending the money inside a smart contract. The main use case of this is limiting the addresses where money can be sent and the amount sent. To explore the possible uses of covenants inside smart contracts, read the .
Represents the version of the current transaction. Different transaction versions can have differences in functionality. Currently only version 1 and 2 exist, where only version 2 has support for .
Note: tx.locktime
is similar to the global variable. It is recommended to only use tx.locktime
for adding nLocktime
to simulated state and in all other cases.
Note: The pragma directive follows regular .
The main construct in a CashScript contract is the function. A contract can contain one or multiple functions that can be executed to trigger transactions that spend money from the contract. In the basics the result of a function is just a yes or no answer to the question 'Can money be sent out of this contract?'. But by using a technique called covenants, it is possible to specify other conditions, like restricting where money can be sent. To read more about this technique, refer to the .
Caution: All signature checking functions must comply with the rule. This means that if you want to use the output of a signature check inside the condition of an if-statement, the input signature needs to either be correct, or an empty byte array. When you use an incorrect signature as an input, the script will fail.
An extensive collection of examples is available in the . Below we discuss a few of these examples in more details and go through the functionality.
CashScript is a statically typed language, which means that the type of each variable needs to be specified. Types can also be implicitly or explicitly cast to other types. For a quick reference of the various casting possibilities, see .
When calling a contract function on a Contract object, an incomplete Transaction object is returned. This transaction can be completed by providing a number of outputs using the or functions. Other chained functions are included to set other transaction parameters.
Most of the available transaction options are only useful in very specific use cases, but the functions , and are commonly used. is also commonly used with covenant contracts.
The withAge()
function allows you to specify the minimum age of the transaction inputs. This is necessary if you want to to use the tx.age
CashScript functionality, and the age
parameter passed into this function will be the value of tx.age
inside the smart contract. For more information, refer to .
Tip: If the transaction fails, a meep command is automatically returned. This command can be used to debug the transaction using the
After completing a transaction, the meep()
function can be used to return the required debugging command for the . This command string can then be used to debug the transaction.
An extensive collection of examples is available in the . Below we discuss a few of these examples in more details. These examples focus mainly on the use of the SDK, while the in the language section focuses more on the CashScript syntax.
The idea of this smart contract is explained on the . The gist is that it allows you to send an amount of BCH to someone, but if they don't claim the sent amount, it can be recovered by the sender.
is a Twitter-like social network based on Bitcoin Cash. It uses OP_RETURN
outputs to post messages on-chain. By using a covenant we can create an example contract whose only job is to post Isaac Asimov's first law of smart contracts to Memo.cash. Just to remind its fellow smart contracts.
This contract expects a hardcoded transaction fee of 1000 satoshis. This is necessary due to the nature of covenants (See the for more information on this). The remaining balance after this transaction fee might end up being lower than 1000 satoshis, which means that the contract does not have enough leftover to make another announcement.
int
bytes, bool
bool
int
string
bytes
bytes
sig, pubkey, int
pubkey
bytes
bytes
sig
bytes
bytes
datasig
bytes
bytes
Map是一种非常常用的数据结构。sCrypt 的标准库提供了一个实现了 Map
数据结构的库合约 HashedMap
。概念上与java中的map,python中的字典类型类似,但在使用上有一些区别。
在 HashedMap
中, key
和 value
的类型没有限制,可以是整型、字节、布尔等基本数据类型,也可以是数组、结构体等复杂数据结构。定义 HashedMap
的语法如下:
完整定义
右边简写定义
使用 auto
关键字定义
data()
方法可以将 HashedMap
序列化成 bytes
字节。scryptlib 也提供了对应的 toData(map)
函数。用来在链外序列化 map。
下面是一个将 HashedMap
作为状态的有状态合约。
HashedMap
合约提供了很多有用的方法,添加键值对(key-value)可以使用 HashedMap
合约的 set(K key, V val, int keyIndex)
方法。与其它语言的 map
不同的是添加键值需要传递 keyIndex
参数。该参数可以通过 scryptlib
提供的 findKeyIndex
函数在链下计算。首先我们需要在链外维护一个和链上保存同步的 map
,并把要添加的元素先添加到该 map
中,然后使用 findKeyIndex
计算出 keyIndex
。
如果把所有元素添加到添加到 map
之后,再开始计算 keyIndex
,那需要先将 map
转换成有序的数组。 使用以下代码可以直接转换:
更新元素和添加元素一样,都使用 HashedMap
合约的 set(K key, V val, int keyIndex)
方法。
使用 HashedMap
合约的 delete(K key, int keyIndex)
方法来删除元素。如果删除的元素不存在会返回失败。同样需要在链外使用 findKeyIndex(map, key)
函数来计算 keyIndex
。
HashedMap
只存储 key
和 value
的哈希。无法通过 HashedMap
的序列化 data
反序列出原始的键值对。这对于一些注重隐私性的应用场景很有帮助。
可以通过从外部传入原始键值对,并调用 canGet(key, val, keyIndex)
接口来检查是否包含某个键值对。
或者通过 has(key, keyIndex)
接口检查是否包含某个键。
Map is a very commonly used data structure. sCrypt's standard library provides a library contract HashedMap
that implements the Map
data structure. The concept is similar to the map in java and the dictionary in python, but there are some differences in usage.
In HashedMap
, there are no restrictions on the types of key
and value
. They can be basic data types such as integers, bytes, and booleans, or they can be complex data structures such as arrays and structures. The syntax for defining HashedMap
is as follows:
Full definition
Abbreviated definition on the right
Use the auto
keyword definition
The data()
method can serialize HashedMap
into bytes
. scryptlib also provides the corresponding toData(map)
function. Used to serialize the HashedMap off-chain.
Below is a stateful contract with HashedMap as the state.
The HashedMap
contract provides many useful methods. To add key-value pairs, you can use the set(K key, V val, int keyIndex)
method of the HashedMap
contract. Unlike map
in other languages, adding key-value pairs requires passing the keyIndex
parameter, which can be calculated off-chain by the findKeyIndex
function provided by scryptlib. First, we need to maintain a map outside the chain that is synchronized with the chain, and add the elements to be added to the map first. Then use findKeyIndex
to calculate keyIndex
.
If you add all the elements to the map
before starting to calculate the keyIndex
, you need to convert the map
into an ordered array first. Use the following code to convert directly:
Updating elements is the same as adding elements, using the set(K key, V val, int keyIndex)
method of the HashedMap
contract.
Use the delete(K key, int keyIndex)
method of the HashedMap
contract to delete elements. If the deleted element does not exist, it will return failure. It is also necessary to use the findKeyIndex(map, key)
function outside the chain to calculate the keyIndex
.
HashedMap
only stores the hash of key
and value
. It is not possible to deserialize the original key-value pairs through the serialization of data
of HashedMap
. This is very helpful for some privacy-focused application scenarios. You can pass in the original key-value pair from the outside and call the canGet(key, val, keyIndex)
interface to check whether a key-value pair is included.
Or check whether a key is included through the has(key, keyIndex)
interface.
Before interacting with smart contracts on the BCH network, the CashScript SDK needs to instantiate a Contract
object. This is done by providing the contract's information and constructor arguments. After this instantiation, the CashScript SDK can interact with BCH contracts.
The Contract
class is used to represent a CashScript contract in a JavaScript object. These objects can be used to retrieve information such as the contract's address and balance. They can be used to interact with the contract by calling the contract's functions.
A CashScript contract can be instantiated by providing an Artifact
object, a list of constructor arguments, and optionally a NetworkProvider
.
A contract's address can be retrieved through the address
member field.
The number of opcodes in the contract's bytecode can be retrieved through the opcount
member field. This is useful to ensure that the contract is not too big, since Bitcoin Cash smart contracts can contain a maximum of 201 opcodes.
The size of the contract's bytecode in bytes can be retrieved through the bytesize
member field. This is useful to ensure that the contract is not too big, since Bitcoin Cash smart contracts can be 520 bytes at most.
Returns the contract's redeem script encoded as a hex string.
Returns the total balance of the contract in satoshis. Both confirmed and unconfirmed balance is included in this figure.
Returns all UTXOs that can be spent by the contract. Both confirmed and unconfirmed UTXOs are included.
The main way to use smart contracts once they have been instantiated is through the functions defined in the CashScript source code. These functions can be found by their name under functions
member field of a contract object. To call these functions, the parameters need to match ones defined in the CashScript code.
You may notice the SignatureTemplate
object in the example above. When a contract function has a sig
parameter, it requires a cryptographic signature over the spending transaction. But to generate this signature, the transaction needs to be built first, which is not yet the case when a contract function is first called.
The CashScript SDK needs to connect to the BCH network to perform certain operations, like retrieving the contract's balance, or sending transactions. All network functionality that the CashScript SDK needs is encapsulated in a network provider. This allows different network providers to be used and makes it easy to swap out dependencies.
The BitcoinRpcNetworkProvider uses a direct connection to a BCH node. Note that a regular node does not have indexing, so any address of interest (e.g. the contract address) need to be registered by the node before sending any funds to those addresses. Because of this it is recommended to use a different network provider unless you have a specific reason to use the RPC provider.
Example
A big strength of the NetworkProvider setup is that it allows you to implement custom providers. So if new BCH libraries are created in the future, it is simple to use them with CashScript. This also potentially enables the CashScript SDK to be used with other (partially) compatible networks, such as BTC or BSV.
Generally CashScript contracts are compiled to an Artifact JSON file using the CLI compiler. As an alternative to this, CashScript contracts can be compiled from within JavaScript apps using the cashc
package. This package needs to be installed separately and exports two compilation functions.
Compiles a CashScript contract from a source file. This is the recommended compile method if you're using Node.js and you have a source file available.
Compiles a CashScript contract from a source code string. This is the recommended compile method if you're building a webapp, because compileFile()
only works from a Node.js context. This is also the recommended method if no source file is locally available (e.g. the source code is retrieved with a REST API).
The older preimage-based introspection/covenants have been replaced with the newly supported native introspection/covenants. This has significant consequences for any existing covenant contracts, but in general this native introspection makes covenants more accessible, flexible and efficient. See below for a list of changes. In some cases there is no one to one mapping between the old introspection and the new introspection methods, so the logic of the smart contracts will need to be refactored as well.
tx.version
and tx.locktime
used to be bytes4
, but are now int
.
tx.hashtype
has been removed and can no longer be accessed.
tx.hashPrevouts
and tx.outpoint
have been removed. Instead, the outpoints of individual inputs can be accessed with tx.inputs[i].outpointTransactionHash
and tx.inputs[i].outpointIndex
. The index of the active input can be accessed with this.activeInputIndex
.
tx.hashSequence
and tx.sequence
have been removed. Instead, the sequence numbers of individual inputs can be accessed with tx.inputs[i].sequenceNumber
. The index of the active input can be accessed with this.activeInputIndex
.
tx.bytecode
has been renamed to this.activeBytecode
tx.value
has been removed. Instead, the value of individual inputs can be accessed with tx.inputs[i].value
. The index of the active input can be accessed with this.activeInputIndex
.
tx.hashOutputs
has been removed. Instead, the value and locking bytecode of individual outputs can be accessed separately with tx.outputs[i].value
and tx.outputs[i].lockingBytecode
.
Additionally, it is now possible to access the number of inputs and outputs with tx.inputs.length
and tx.outputs.length
. It is also possible to access individual inputs' locking bytecode and unlocking bytecode with tx.inputs[i].lockingBytecode
and tx.inputs[i].unlockingBytecode
. It is also no longer a requirement to have a signature check somewhere in the contract in order to use this introspection/covenant functionality.
OutputP2PKH
, OutputP2SH
and OutputNullData
have been replaced by LockingBytecodeP2PKH
, LockingBytecodeP2SH
and LockingBytecodeNullData
respectively. These new classes only produce the locking bytecode, rather than the full output (including value). This means that the locking bytecode and value of outputs need to be checked separately.
Casting from sig
to datasig
has been removed since that was only useful for old-style covenants. If, for any reason, you do want to cast a sig to a datasig you will need to manually cut the hashtype
off the end and update datasig(s)
to s.split(s.length - 1)[0]
.
Since the new covenant functionality is very different from the existing, it may be useful to see a complex covenant contract refactored from the old way to the new way.
```solidity title="Mecenas.cash v0.6.0" pragma cashscript ^0.6.0;
contract Mecenas(bytes20 recipient, bytes20 funder, int pledge, int period) { function receive(pubkey pk, sig s) { require(checkSig(s, pk)); require(tx.age >= period);
}
The exports for library usage of cashc
have been updated. All utility-type exports have been moved to the @cashscript/utils
package, but they are still accessible from the utils
export from cashc
. Note that the recommended use of cashc
is still the CLI, not the NPM package.
In v0.5 you could encode a string like this:
While for v0.6 you'd need to use the utils
export or @cashscript/utils
:
Compilation functions used to be exported as part of the CashCompiler
object, but are now exported as standalone functions.
In v0.5 compilation looked like this:
In v0.6, this needs to be changed to this:
The CashScript SDK no longer depends on cashc
and no longer exports the CashCompiler
object. This reflects the recommended usage where the CLI is used for compilation and the artifact JSON is saved. Then this artifact JSON can be imported into the CashScript SDK. If you prefer to compile your contracts from code, you need to add cashc
as a dependency and use its compilation functionality.
The contract instantiation flow has been refactored to enable compatibility with more BCH libraries and simplify the different classes involved.
In v0.4 a contract could be compiled or imported using Contract.compile()
or Contract.import()
, which returned a Contract object. On that Contract object contract.new(...args)
could be called, which returned an Instance object. In the v0.5 release, the Contract and Instance objects have been merged and simplified, while the compilation has been extracted into its own class.
In v0.4, contract instantiation looked like this:
In v0.5, this needs to be changed to look like this:
Transaction object's .send()
function now returns either a libauth Transaction or raw hex string rather than a BITBOX Transaction. If it is necessary, the raw hex string can be imported into libraries such as BITBOX to achieve similar functionality as before.
In v0.4.1, Sig
was deprecated in favour of SignatureTemplate
. In v0.5.0, the deprecated class has been removed. All occurrences of Sig
should be replaced with SignatureTemplate
.
In v0.3, casting an int
type to a bytes
would perform an NUM2BIN
operation, padding the value to 8 bytes. This made bytes(10)
equivalent to bytes8(10)
. From v0.4.0 onwards, casting to an unbounded bytes
type is only a semantic cast, indicating that the int
value should be treated as a bytes
value.
If you need the old behaviour, you should change all occurrences of bytes(x)
to bytes8(x)
.
The entire Transaction
flow has been refactored to a more fluent chained TransactionBuilder API.
All occurrences of .send(to, amount)
should be replaced with .to(to, amount).send()
.
All occurrences of .send(outputs)
should be replaced with .to(outputs).send()
.
Alternatively, the list of outputs
can be split up between several .to()
calls.
If any of the outputs contain opReturn
outputs, these should be added separately using .withOpReturn(chunks)
The same transformations are applicable to all .meep()
calls.
The meep()
function previously logged the meep command automatically, but now it returns the command as a string, so you should console.log()
the command separately.
All transaction options previously included in the TxOptions
object should now be provided using chained functions.
The time
option should be provided using the .withTime(time)
function.
The age
option should be provided using the .withAge(age)
function.
The fee
option should be provided using the .withHardcodedFee(fee)
function.
The minChange
option should be provided using the .withMinChange(minChange)
function.
In v0.2.2, Contract.fromCashFile()
and Contract.fromArtifact()
were deprecated in favour of Contract.compile()
and Contract.import()
. In v0.4.0, the deprecated functions have been removed.
All occurrences of Contract.fromCashFile()
should be replaced with Contract.compile()
.
All occurrences of Contract.fromArtifact()
should be replaced with Contract.import()
.
OP_CODESEPARATOR
The signature checked by OP_CHECKSIG
is the signature of the hash of the preimage. The preimage contains outputs of the entire transaction, input and the locking script. Usually the locking script is complete. But if OP_CHECKSIG
has executed OP_CODESEPARATOR
before, then the preimage only contains the locking script from the position of the most recently executed OP_CODESEPARATOR
until the end of the script, that is, only part of the locking script is included. Using this feature can be used to reduce the size of the preimage, thereby reducing the size of the entire transaction.
The sCrypt standard library Tx
provides the following functions to check this preimage that only contains partial locking scripts:
Tx.checkPreimageOCS
The preimage to be checked only contains part of the locking script. The signature type checked by default is SigHash.ALL | SigHash.FORKID
, and does not support custom signature type.
Tx.checkPreimageSigHashTypeOCS
Support custom signature type
Tx.checkPreimageAdvancedOCS
Support custom signature type and custom temporary key
Tx.checkPreimageOptOCS
Optimized version of Tx.checkPreimageOCS
Tx.checkPreimageOptOCS_
Optimized version of Tx.checkPreimageOCS
, support custom signature type
The following is an example of using Tx.checkPreimageOCS()
to check the preimage:
The following is an example of how to deploy and call the CheckLockTimeVerifyOCS
contract:
When using getPreimage
to calculate the preimage, the entire lock script cannot be passed. Need to use subScript(opsIndex: number)
to tailor the locking script. The parameter index
is the index of OP_CODESEPARATOR
in this script, which is the number of OP_CODESEPARATOR
. It should be noted that this function does not consider dynamic execution.
:bug: Fix a bug with chipnet connection
:hammer_and_wrench: Internal refactoring
:bug: Fix a bug with ESM exports
:sparkles: Add "chipnet"
network option to ElectrumNetworkProvider, used to connect to the May 2023 testnet.
:hammer_and_wrench: Renamed network options "testnet"
& "staging"
to "testnet3"
and "testnet4"
respectively. Old options will be removed in a future release.
:bug: Fix bug where contracts using checkMultiSig()
were unspendable.
:sparkles: Add signatureAlgorithm
parameter to SignatureTemplate
to allow ECDSA signatures.
:bug: Fix bug where 64bit integers could not be decoded.
:sparkles: Add destructuring assignments, e.g. bytes2 left, bytes1 right = 0x123456.split(2)
:sparkles: Add constant keyword, e.g. int constant x = 10;
:sparkles: Add multiplication, e.g. int x = 5 * 5
:sparkles: Add native introspection/covenants
:boom: BREAKING: Remove all old introspection/covenant functionality (tx.version
, tx.hashPrevouts
, tx.hashSequence
, tx.outpoint
, tx.bytecode
, tx.value
, tx.sequence
, tx.hashOutputs
, tx.locktime
, tx.hashtype
, OutputP2PKH
, OutputP2SH
, OutputNullData
)
:boom: BREAKING: Remove sig
to datasig
casting since this was only useful for old covenants
:bug: Fix ESM build
:sparkles: Add "staging"
network option to ElectrumNetworkProvider, used to connect to the May 2022 testnet
:hammer_and_wrench: Deprecate old introspection/covenant functionality. You can still use pre-0.7 contracts with the new SDK, but this support will be removed in a future release.
:boom: BREAKING: arguments of type datasig
must be 64 bytes in length, effectively enforcing Schnorr
:bug: Fix ESM build
:bug: Small fixes
:bug: Fix cashc
version
:sparkles: Add byte
type alias for bytes1
:hammer_and_wrench: Use ES2015 for the "module" output for better compatibility
:bug: Fix typing issue with BitcoinRpcNetworkProvider
:bug: Fix bug with incorrect fee calculation when providing custom fee per byte
:sparkles: Add date literal (gets converted to int timestamp)
:hammer_and_wrench: Update ParseError messages
:bug: The final statement in a contract now MUST be a require statement (in all branches)
:bug: Empty contracts and functions are now considered invalid
:bug: Fix bug where certain covenants could become unspendable due to incorrect bytesize calculation
:boom: BREAKING: Remove --args
parameter from the CLI, since this is too error prone with the recent changes in mind
:boom: BREAKING: Restructure exports
:sparkles: Add BitcoinRpcNetworkProvider that connects to a BCH node RPC
:boom: BREAKING: Remove dependency on cashc
and remove CashCompiler
export
:bug: Better error reporting for parsing/lexing errors
:bug: Make compiler fail early when encountering lexing/parsing errors, rather than performing error recovery
:bug: Allow empty hex literals (i.e. 0x
)
:sparkles: Add 'regtest'
as a possible network for NetworkProviders.
:package: Add dual build system (CommonJS and ES Modules) to accommodate tree-shaking.
:sparkles: Add getRedeemScriptHex()
function to the Contract
class.
:bug: Fix a bug where transaction locktime could not specifically be set to 0.
:bug: Fix a bug where signature buffers were not checked for size.
:bug: Fix a bug where an incorrect error message was displayed in Firefox when an incompatible pragma version was used.
:sparkles: The .send()
function now returns a TransactionDetails
object. This extends the libauth Transaction
with added txid
and hex
fields.
Because it extends the previous return type, this is backwards compatible.
Since this now returns the transaction hex as a field, using .send(true)
to return the transaction hex is deprecated and will be removed in a future release.
:bug: Improve reliability of the ElectrumNetworkProvider
when sending multiple concurrent requests.
CashScript used to be very tightly coupled with BITBOX. This proved to be problematic after maintenance for BITBOX was stopped. The main objective of this update is to allow CashScript to be used with many different BCH libraries.
:sparkles: Add withoutChange()
function to disable change outputs for a transaction.
:sparkles: SignatureTemplate
can now be used with BITBOX keypairs, bitcore-lib-cash
private keys, WIF strings, and raw private key buffers, rather than only BITBOX.
:boom: Remove Sig
alias for SignatureTemplate
that was deprecated in v0.4.1.
:boom: BREAKING: Refactor contract instantiation flow
A contract is now instantiated by providing a compiled artifact, constructor arguments and an optional network provider.
:boom: BREAKING: Remove the artifacts 'networks'
field and .deployed()
functionality, This proved to be confusing and is better suited to be handled outside of the CashScript SDK.
:boom: BREAKING: .send()
now returns a libauth Transaction instead of a BITBOX Transaction object. Alternatively a raw
flag can be passed into the function to return a raw hex string.
:hammer_and_wrench: Removed BITBOX as a dependency in favour of libauth for utility functions.
:bug: Fix a bug where covenants would not always get verified correctly when the first require(checkSig(...))
statement was inside a branch.
:racehorse: Add compiler optimisations.
Re-add README files to NPM that were accidentally removed in the v0.4.0 release.
:racehorse: Add optimisations to bitwise operators.
:shell: New CLI arguments.
Add --opcount|-c
flag that displays the number of opcodes in the compiled bytecode.
Add --size|-s
flag that displays the size in bytes of the compiled bytecode.
:symbols: Add trailing comma support.
:name_badge: Rename Sig
to SignatureTemplate
to better convey its meaning.
Sig
still exists for backward compatibility, but is deprecated and will be removed in a later release.
:sparkles: Add .reverse()
member function to bytes
and string
types.
:sparkles: Add bitwise operators &
, ^
, |
.
:sparkles: Allow casting int
to variable size bytes
based on size
parameter.
:boom: BREAKING: Casting from int
to unbounded bytes
type now does not perform OP_NUM2BIN
. Instead it is a purely semantic cast to signal that an integer value should be treated as a bytes value.
:horse_racing: Compiler optimisations.
Use NUMEQUALVERIFY
for the final function in a contract.
Only drop the final VERIFY
if the remaining stack size is less than 5.
Pre-calculate OutputNullData
argument size.
:bug: Fix a bug where return type of sha1
was incorrectly marked as bytes32
.
:bug: Data.decodeBool
only treated numerical zero as false, now any zero-representation is considered false (e.g. 0x0000, -0, ...).
:sparkles: Add ability to provide hardcoded inputs to the transaction rather than use CashScript's coin selection.
:boom: BREAKING: Refactor the transaction flow to a fluent API
Remove the TxOptions
argument and other arguments to the Transaction send()
function.
Instead these parameters are passed in through fluent functions from()
, to()
, withOpReturn()
, withAge()
, withTime()
, withHardcodedFee()
, withFeePerByte()
and withMinChange()
.
After specifying at least one output with either to()
or withOpReturn()
the transaction is ready. From here the transaction can be sent to the network with the send()
function, the transaction hex can be returned with the build()
function, or the meep debugging command can be returned with the meep()
function.
:boom: Remove Contract.fromCashFile()
and Contract.fromArtifact()
which were deprecated in favour or Contract.compile()
and Contract.import()
in v0.2.2.
:bug: Fix bug where variables could not reliably be used inside OutputNullData
instantiation.
:sparkles: Add OutputNullData(bytes[] chunks)
, an output type to enforce OP_RETURN
outputs.
:shell: CLI improvements
The --output|-o
flag is now optional, if it is omitted or manually set to -
, the artifact will be written to stdout rather than a file.
Add --asm|-A
flag that outputs only Script in ASM format instead of a full JSON artifact.
Add --hex|-h
flag that outputs only Script in hex format instead of a full JSON artifact.
Add --args|-a
flag that allows you to specify constructor arguments that are added to the generated bytecode.
:warning: The CLI does not perform type checking on these arguments, so it is recommended to use the CashScript SDK for type safety.
:bug: Fix a compilation bug that allowed compilation of "unverified covenants" (#56).
:bug: Fix a compilation bug that allowed compilation of OutputP2PKH(...)
without new
keyword (#57).
:globe_with_meridians: Browser support! You can now use CashScript inside web projects. Filesystem-based functionality such as compilation from file are not supported due to the nature of web, so CashScript files have to be read in a different way (e.g. Fetch API) and then passed into the CashScript SDK.
:purse: Add minChange
to transaction options. If this minChange
is not reached, the change will be added to the transaction fee instead.
:warning: Add warnings when a contract exceeds 201 opcodes or 520 bytes.
:bug: Fix a bug where an incorrect number of items were dropped from the stack after execution of a branch.
:sparkles: Improve error handling.
Further specified FailedTransactionError
into FailedRequireError
, FailedSigCheckError
, FailedTimeCheckError
and a general fallback FailedTransactionError
.
Add Reason
enum with all possible reasons for a Script failure - can be used to catch specific errors.
:mag: Add instance.opcount
and instance.bytesize
fields to all contract instances.
:bug: Fix a bug where the size of a preimage was not accounted for in fee calculation for covenants.
:sparkles: Covenants abstraction! All individual preimage fields can be accessed without manual decoding, passing, and verification.
Available fields: tx.version
, tx.hashPrevouts
, tx.hashSequence
, tx.outpoint
, tx.bytecode
, tx.value
, tx.sequence
, tx.hashOutputs
, tx.locktime
, tx.hashtype
.
When any of these fields is used inside a function, this function is marked covenant: true
, and requires a preimage as parameter (automatically passed by CashScript SDK).
The correct fields are efficiently cut out of the preimage and made available.
The first occurrence of require(checkSig(sig, pubkey));
is identified, and preimage verification is inserted using the same sig/pubkey. Important: if you have multiple checkSig
statements, keep in mind that the first will be used for verification.
Automatically cuts off VarInt from scriptCode
, so tx.bytecode
contains the actual contract bytecode.
:sparkles: Output instantiation! Automatically construct output formats for covenant transactions.
new OutputP2PKH(bytes8 amount, bytes20 pkh)
new OutputP2SH(bytes8 amount, bytes20 scriptHash)
:bug: Fix bug with invalid output when the final statement in a contract is an if-statement.
:sparkles: Add fee
option to TransactionOptions. This allows you to specify a hardcoded fee for your transaction.
:sparkles: Automatically pass in sighash preimage into covenant functions. Important: uses the hashtype of the first signature in the parameters for generation of this preimage.
:dizzy: Better fee estimation for transactions with many inputs.
:bug: Fix a bug where unequal bytes types (e.g. bytes3
& bytes8
) could not be concatenated together, as they were considered different types.
:bug: Remove minimaldata encoding in OP_RETURN
outputs that caused incompatibility with SLP.
:name_badge: Renamed Contract.fromCashFile
to Contract.compile
.
The new function allows to pass in a path to a .cash
file, or a string of the contract source code.
Contract.fromCashFile
still exists for backward compatibility, but is deprecated and will be removed in a later release.
:name_badge: Renamed Contract.fromArtifact
to Contract.import
.
The new function allows to pass in a path to a .json
artifact file, or a JSON object of the artifact.
Contract.fromArtifact
still exists for backward compatibility, but is deprecated and will be removed in a later release.
:hammer_and_wrench: instance.export
's file
argument is now optional.
If it is provided, the artifact is written to the file, if not, it is returned as an object.
:sparkles: Support bytes
types with bounded size, e.g. bytes1
, bytes13
, bytes32
.
:bug: Fix bug in bytecode optimisation
:sparkles: Support bytes
types with bounded size, e.g. bytes1
, bytes13
, bytes32
.
:bird: Automatically output meep command on failed transaction error.
:hammer: Make the hashtype
parameter in signature placeholders optional.
:racehorse: Implement compiler optimisations
For the final use of a variable, it is retrieved with OP_ROLL
rather than OP_PICK
. This removes the need to clean the stack at the end of a contract.
Final OP_VERIFY OP_TRUE
is removed as there is an implicit OP_VERIFY
at the end of a Script.
OP_VERIFY
is merged with preceding opcode where applicable.
Shallow OP_PICK
and OP_ROLL
are replaced by hardcoded opcodes (e.g. OP_SWAP
, OP_DUP
).
Several other bytecode optimisations.
:sparkles: Add pragma
keyword to specify intended compiler version.
Example: pragma cashscript ^0.2.0;
Contract fails to compile when compiler version does not satisfy constraints.
:rotating_light: Add CashProof for all individual bytecode optimisations and for example contracts from 0.1.2 to 0.2.0.
:bug: Add "default case" for function selection that fixes a vulnerability where people could spend funds by not calling any function.
:arrow_up: Update dependencies.
:arrow_up: Update cashc
and other dependencies.
:sparkles: Add support for OP_RETURN
outputs.
:bug: Improved error handling.
:bug: Poll for transaction details to make sure it's available.
:fire: Enable optional mainnet - NOT RECOMMENDED
:hammer: UTXO selection refactor
:rotating_light: Improve Transaction testing
:bug: Bug fixes with incorrect parameter encoding for string/bool/int types.
:tada: Initial release.
Javascript/TypeScript SDK for integration of Radiant (RAD RXD) Blockchain Smart Contracts written in the sCrypt language.
You can install scryptlib
in your project as below:
A smart contract is compiled to a locking script template. A contract function call is transformed to an unlocking script. Developers are responsible for setting the locking and unlocking scripts of a transaction properly before sending it to the Bitcoin network. This may include some actions described below:
Instantiate locking script: replace the constructor formal parameters, represented by placeholders in the locking script template, with actual parameters/arguments to form the complete locking script.
Assemble unlocking script: convert the arguments of a contract function call to script format and concatenate them to form the unlocking script.
By using scryptlib
, both scripts can be obtained with ease.
The compiler output results in a JSON file. It’s a representation used to build locking and unlocking scripts. We call this file a contract description file.
There are three ways to generate this file (named as xxx_desc.json
):
Use the function compile
programmatically:
compileAsync
is the asynchronous version of the function compile
Run npx
command in CLI:
All basic types of the sCrypt language have their corresponding javascript classes in scryptlib. In this way, the type of parameters could be checked and potential bugs can be detected before running.
int
new Int(1)
or number
or bigint
bool
new Bool(true)
or boolean
bytes
new Bytes('0001')
or new String("hello world 😊")
PubKey
new PubKey('0001')
PrivKey
new PrivKey(1)
Sig
new Sig('0001')
Ripemd160
new Ripemd160('0001')
Sha1
new Sha1('0001')
Sha256
new Sha256('0001')
SigHashType
new SigHashType('01')
SigHashPreimage
new SigHashPreimage('010001')
OpCodeType
new OpCodeType('76')
scryptlib uses javascript array to represent the array types of the sCrypt language.
Composite types, including structs and type aliases, are dynamically generated by buildTypeClasses
. When creating a structure, all members must specify values. Use dot to access structure members.
Structure and type aliases defined in sCrypt:
Access Structure and type aliases by SDK :
Library is another composite types. When the constructor parameter of the contract contains library, we need to create library through sdk.
Library defined in sCrypt:
Access Library by SDK :
As you can see, creating a library instance is similar to creating a contract instance. Sometimes the constructor parameters of the library may be generic types. At this time, the sdk will deduce the generic type based on the constructor arguments you pass.
Both deploying a contract and calling a contract function are achieved by sending a transaction. Generally speaking,
deploying a contract needs the locking script in the output of this transaction to be set properly;
calling a contract function needs the unlocking script in the input of this transaction to be set properly.
There are 2 steps.
You can use the description file to build a reflected contract class in Javascript/TypeScript like this:
To create an instance of the contract class, for example:
To get the locking script, use:
To get the unlocking script, just call the function and turn the result to bsv.Script
object, for example:
A useful method verify(txContext)
is provided for each contract function call. It would execute the function call with the given context locally. The txContext
argument provides some context information of the current transaction, needed only if signature is checked inside the contract.
It returns an object:
It usually appears in unit tests, like:
Use the initial state to instantiate the contract and read the state by accessing the properties of the contract instance.
Then use instance.getNewStateScript()
to get a locking script that includes the new state. It accepts an object as a parameter. Each key of the object is the name of a state property, and each value is the value of the state property. You should provide all state properties in the object.
You can also access the state of the contract by accessing the properties of the instance.
Assembly variables can be replaced with literal Script in ASM format using replace()
. Each variable is prefixed by its unique scope, namely, the contract and the function it is under.
In addition to using a constructor to create a contract, you can also use a raw transaction to construct it.
Some contracts use Bigint
to construct or unlock. but some browsers do not support Bigint
, such as IE11. In this case, we use strings to build Bigint
.
Note: Modified to use @radiantblockchian/radjs for testnet/superAssetR100.js
Contract Development and Test
Contract Integration and Application Launch
For each contract x
, a source file is at contracts/x.scrypt
, a test file is at tests/js/x.scrypttest.js
, and a deployment file is at testnet/x.js
.
The major steps to write a sCrypt test are exemplified by tests/demo.scrypttest.js
.
Use the imported function buildContractClass
to get a reflected contract, which has same properties and methods as defined in the specified sCrypt contract.
Note that demo_desc.json
is the description file name of the compiled contract, which will be generated automatically if you run npm run watch
and its name follows the rule $contractName_desc.json
.
Initialize the contract.
Write tests for the instantiated contract as you would do in Javascript.
Run unit tests file within the editor/explorer context menu.
Tests could also be run from the console by executing npm test
, just like regular Javascript/TypeScript tests.
Provide a private key with funds in privateKey.js
Deploy a contract and call its function by issuing
Output like the following will appear in the console. And you have successfully deployed a contract and called its function on Bitcoin. Sweet!
It is strongly recommended to test your contract on testnet first, before deploying it on mainnet. By default, deployment is on testnet. To switch to mainnet, simply modify API_PREFIX
in helper.js
.
IDE provides a universal UI interface. You can deploy the contract with one click by simply filling in the relevant parameters. You can call the public function of the contract with the click of a button without writing a line of code.
The Electron wallet is recommended for general receiving and sending uses. It uses Electrumx as to connect to the Radiant node.
What you will see in this guide:
Downloading Wallet
Seed generation for the wallet.
Basics for sending and receiving.
For this guide I recommend the portable version because it does not require installation. This allows you to move it to another pc or make a backup in a simple way.
MACOS: Electron-Radiant-v0.x.x-macosx.dmg
WIN PORTABLE: Electron-Radiant-v0.x.x-portable.exe
WIN INSTALL: Electron-Radiant-v0.x.x-setup.exe
LINUX PORTABLE: Electron-Radiant-v0.x.x-x86_64.AppImage
The first time it is run, it will be necessary to accept the Windows warning. It is also possible that the antivirus says that it may have a Trojan, but it is a false-positive.
And click in Run anyway
Two icons appear in the installation. The standard version, which is the Mainnet and the Testnet, which is the testnet network.
The next step is to indicate how to connect the wallet. By default it is correct
Now it is time to create a new wallet and it is necessary to give it a name. To load a backup, it would be necessary to load the file of the wallet
Radiant only works with standard wallets, which is the one to dial. To retrieve a specific private key, it would be option 3
In the next step we have two important options to choose from. Restore a wallet with the saved words or generate a new one.
In this case we select a new one:
Create new seed
Restore seed.
The words that appear will be the seed of the new portfolio. It is necessary and obligatory to write them down or copy them to a file. If they are lost, you will lose access to any radiant in the addresses of the portfolio.
IMPORTANT: MAKE SEVERAL BACKUP COPIES OF THESE WORDS
To ensure that the words are copied correctly, you are asked to enter them all in the following step
And the last step is to generate a password that encrypts the wallet.
Status of TX.
Transaction date.
Address label.
Amount of RXD of the transaction.
Overall balance of the transaction.
Destination address
Name of the address.
Send button.
Bar to establish network commission.
Amount to send
If you have entered a password in the wallet, you need to enter it to make a transaction.
Once everything is filled in correctly, the transaction is displayed.
In history appears this transaction as shown in the image and the transaction will appear in the next block that is generated (about 5 minutes).
Coin input
Coin output
Address not used to receive new funds
his address will always be one that has never received funds.
Name to be added to the address
The first 20 addresses of the wallet and the amount of coins in each one. In change
Here you can see all received and unspent transactions.
Addresses to receive
Number of coins per address
If the connectivity button is red, you can fix it by clicking on it and checking the servers to which you are connected.
In server all servers are loaded and can be added if necessary.
Here are the servers you can connect to
ACTUAL SERVERS
If you want to run the electrum version there is no need to also run the pure node container.
Under Docker commands you can see a command to fetch the image so that you store it locally. If you know what image you want there is no need to do this manually. When we run the image and Docker can't find it locally it will search Docker Hub for it.
The command for starting the node container is:
You might not need to sudo if you have given docker sudo rights. The -itd tag is to run the container interactively, with tty (terminal) and detatched (background). The last bit is the reference to the image you want to run.
The name tag is optional, but makes it easier when we specify it when we want to inspect the container and when we stop it.
If it is the first time you run the command and dont have the image locally you will see the download progress. This is only for when you fetch new images. The second time you run it it will be much faster as you already have the image. When you run the command you should see a hash, and that means the container started.
The command for starting the node + electrum container is:
You can run this to see what containers are currently running:
and you can run this to see all containers that has been ran:
Acces the container to inspect and troubleshoot: We can access the terminal of the running container to inspect and troubleshoot it using this command:
This will open up the terminal in the container and we can run commands to see that everything runs as expected. You will see a # symbol meaning we are in the terminal of the node. Now we can run:
To go back out of the container simply use runexit
inside the container.
We now have a functional radiant node up and running, but why stop there? We can easilly run multiple nodes at once. Just start another node using the same image (but different name). This will spawn a new container with a new node running. For example:
We can now use
to see that we have two nodes running.
When its time to stop the container we simply run:
"radiantnode" is the name we specified when we started the first container. To stop the second container we started:
To stop the node + electrum:
下面是一个实现部署合约功能的函数。任意类型的合约都可以使用该函数来部署。
调用合约公共函数时分两种情况: 1. 该公共函数不包含 SigHashPreimage
类型的参数 2. 改公共函数包含 SigHashPreimage
类型的参数
SigHashPreimage
如果合约的公共函数不包含 SigHashPreimage
类型的参数,则构造调用合约的交易比较简单。一般可以按照以下步骤构建交易:
通过 createInputFromPrevTx(tx, outputIndex)
从合约所在的交易创建输入,并添加到交易中。
使用 change(address)
添加一个找零输出。
使用 setInputScript(inputIndex, (tx, output) => bsv.Script)
为步骤 1 添加的输入设置解锁脚本。
调用 seal()
封印交易,同时自动计算出正确的交易费用和找零余额。
SigHashPreimage
如果合约的公共函数包含 SigHashPreimage
类型的参数,则构造调用合约的交易比较复杂。因为解锁脚本的大小影响到交易费用的计算,从而影响输出中的 satoshis
余额。输出中的 satoshis
余额又会影响 SigHashPreimage
的计算。使用 scryptlib 的链式 APIs 隐藏了处理这些繁琐计算的细节。 你只需按照以下方式来构造交易:
交易费用是由合约里的余额支付:
这种情况下不包含独立的找零输出。所有输出的余额在构造交易之前是未知的。交易费用会影响所有输出的余额的计算。
通过 createInputFromPrevTx(tx, outputIndex)
从合约所在的交易创建输入,并添加到交易中。
使用 setOutput(outputIndex, (tx) => bsv.Transaction.Output)
添加一个或多个输出。输出的余额通常需要减去交易费用;
javascript const newAmount = amount - tx.getEstimateFee();
使用 setInputScript(inputIndex, (tx, output) => bsv.Script)
为步骤 1 添加的输入设置解锁脚本。解锁参数通常包含一个指定合约新余额的参数,其计算方式与上一步相同。
调用 seal()
封印交易,同时自动计算出正确的交易费用和找零余额。
交易费用是通过添加其它输入来支付:
这种情况下包含一个独立的找零输出。其它输出的余额一般是可以在构造交易之前计算出来的。交易费用只会影响找零输出的计算。
通过 createInputFromPrevTx(tx, outputIndex)
从合约所在的交易创建输入,并添加到交易中。
通过 from([utxo])
来添加用于支付交易费用的输入。
使用 addOutput()
添加一个或多个的输出(根据合约业务逻辑添加)。
使用 change(address)
添加一个找零输出。
使用 setInputScript(inputIndex, (tx, output) => bsv.Script)
为步骤 1 添加的输入设置解锁脚本。解锁参数通常包含一个指定找零余额的参数,该参数可以通过 tx.getChangeAmount()
来获取。
使用 sign(privateKey)
来签名所有添加用于支付交易费用的输入。
调用 seal()
封印交易,同时自动计算出正确的交易费用和找零余额。
The Electron wallet uses BIP39 to store the wallet keys. Samara and Chainbow also use BIP39 to host these keys, making all these wallets compatible with each other.
It is very important to have these words stored securely, as without them it is not possible to retrieve the stored funds. More information about BIP39
Create new wallet
Select a name for this restore wallet.
Select standard wallet
Specify that we already have a seed.
Write the saved seed in the box with the same saved word order.
Specify the derivation of the addresses. If it has not been changed, leave the default with: m/44'/0'/0'
Specifying a good password to the restored wallet.
Finally, the restored wallet data should be displayed on the screen.
One way to implement state in contract is dividing the contract in the locking script into two parts: data and code. Data part is the state. Code part contains the business logic of a contract that encodes rules for state transition.
OP_RETURN
data of the contract locking script can be accessed by using an accessor named dataPart
, for example:
After that, the counter.lockingScript
would include the data part automatically. You can use it to calculate preimage.
If you want to access the code part of the contract's locking script including the trailing OP_RETURN
, use:
The following is a function that deploys any type of contracts.
There are two cases when calling a public function of a contract: 1. The function takes a parameter of type SigHashPreimage
2. No SigHashPreimage
parameter.
SigHashPreimage
If the public function of the contract being called does not contain parameter of type SigHashPreimage
, it is relatively simple to build a transaction calling it. Generally, you can build a transaction according to the following steps:
Create an input from a previous transaction where the contract is located by createInputFromPrevTx(tx, outputIndex)
and add it to the transaction.
Use change(address)
to add a change output.
Use setInputScript(inputIndex, (tx, output) => bsv.Script)
to set the unlocking script for the input added in step 1.
Call seal()
to finalize the transaction, and automatically calculate the correct transaction fee and change balance.
SigHashPreimage
If the public function of the contract contains parameters of type SigHashPreimage
, it is more complicated to build the transaction calling it. This is because unlocking script containing SigHashPreimage
affects the calculation of transaction fee and thus the satoshis
amount in the output. In turn, satoshis
affects the calculation of SigHashPreimage
. The chained APIs provided by scryptlib hides the details of processing these inter-dependent calculations. You only need to build the transaction in the following way:
1. Transaction fees paid by the bitcoins locked in the contract:
In this case, no separate change output is included. The balances of all outputs are unknown before the transaction is built. Transaction fees will affect the calculation of all output balances.
Create an input from the transaction where the contract is located by createInputFromPrevTx(tx, outputIndex)
and add it to the transaction.
Use setOutput(outputIndex, (tx) => bsv.Transaction.Output)
to add one or more outputs. The output balance usually needs to subtract transaction fee;
javascript const newAmount = amount - tx.getEstimateFee();
Use setInputScript(inputIndex, (tx, output) => bsv.Script)
to set the unlocking script for the input added in step 1. The unlocking parameter usually contains a parameter that specifies the new balance of the contract and its calculation is the same as the previous step.
Call seal()
to finalize the transaction and automatically calculate the correct transaction fee and change amount.
2. Transaction fees paid by adding other inputs:
In this case, a separate change output is included. The balance of other outputs can generally be calculated before the transaction is built. Transaction fees only affect the calculation of change output.
Create an input from the transaction where the contract is located by createInputFromPrevTx(tx, outputIndex)
and add it to the transaction
Use from([utxo])
to add inputs used to pay transaction fee.
Use addOutput()
to add one or more outputs (add according to the contract business logic).
Use change(address)
to add a change output.
Use setInputScript(inputIndex, (tx, output) => bsv.Script)
to set the unlocking script for the input added in step 1. The unlocking parameters usually contains a parameter that specifies the change amount, which can be obtained through tx.getChangeAmount()
.
Use sign(privateKey)
to sign all inputs added to pay transaction fee.
Call seal()
to finalize the transaction.
An Artifact
object is the result of compiling a CashScript contract. See the for more information on Artifacts. Compilation can be done using the standalone or programmatically with the cashc
NPM package (see ).
A NetworkProvider
is used to manage network operations for the CashScript contract. By default, a mainnet ElectrumNetworkProvider
is used, but alternative network providers can be used. See the section on below.
These contract functions return an incomplete Transaction
object, which needs to be completed by providing outputs of the transaction. More information about sending transactions is found on the page.
So in the place of a signature, a SignatureTemplate
can be passed, which will automatically generate the correct signature using the signer
parameter. This signer can be any representation of a private key, including , , , or raw private key buffers. This ensures that any BCH library can be used.
The ElectrumNetworkProvider uses to connect to the BCH network. This is the recommended provider for most use cases and is used as the default when no other provider is provided. Both network
and electrum
parameters are optional, and they default to mainnet and a 2-of-3 ElectrumCluster with a number of reliable electrum servers.
The FullStackNetworkProvider uses ' infrastructure to connect to the BCH network. FullStack.cash' offers dedicated infrastructure and support plans for larger projects. Both network
and bchjs
parameters are mandatory, where bchjs
is an instance of FullStack.cash' .
The BitboxNetworkProvider uses Bitcoin.com's to connect to the BCH network. Because BITBOX is no longer officially maintained it is not recommended to use this network provider, and it is only available for compatibility with older projects. Both network
and bitbox
parameters are mandatory, where bitbox
is a BITBOX instance.
Most importantly, it is now possible to access specific data for all individual inputs and outputs, rather than e.g. working with hashes of the outputs (tx.hashOutputs
). This offers more flexibility around the data you want to enforce. For more information about this new native introspection functionality, refer to the section of the documentation, the and the .
See the for an overview of other new changes.
See the for an overview of other new changes.
The size for executing this contract is 288
bytes, which contains a preimage with 201
size, and the size for executing the contract using the Tx.checkPreimage()
version is 1005
bytes, which contains a preimage with 915
size. The functions of these two contracts are exactly the same, but the transaction size is optimized by 80%
.
See the for details on migrating from the old introspection to the new native introspection methods.
:boom: BREAKING: Covenants using tx.bytecode
now include a placeholder OP_NOP
that gets replaced when constructor arguments are provided in the CashScript SDK. If you're not using the CashScript SDK, refer to the to see the steps required to do so manually.
Anyone can implement the NetworkProvider interface to create a custom provider. The CashScript SDK offers three providers out of the box: one based on electrum-cash (default), one based on FullStack.cash' infrastructure, and one based on BITBOX. See the for details.
See the for details on migrating from the old contract instantiation flow.
This update contains several breaking changes. See the for a full migration guide.
PLEASE NOTE: This is a fork of scryptlib as a convenience that contains the patches to the included bsv.js lib directly Alternatively, the regular scryptlib may be used along with radjs radiantjs https://github.com/RadiantBlockchain/radjs (latest) or and not using the bundled bsv in scryptlib.
Use to compile manually;
make building transactions super easy.
sCrypt offers . Declare any property that is part of the state with a decorator @state
in a contract, for example:
You can also maintain state manually to, for example, optimize your contract or use customized state de/serialization .
You could find more examples using scryptlib
in the repository.
Make sure you have the installed. sCrypt IDE is a tool for developers to write, test, deploy, call, and debug sCrypt smart contracts.
is a high-level programming language for writing smart contracts on Bitcoin SV. This project provides examples to help developers learn and integrate sCrypt smart contracts to their Javascript-based projects. Our recommended procedure of developing smart contract based applications is as follows:
After developing and unit testing the smart contracts, the next step is to integrate them into your application which is written in other languages such as Javascript or Python. Integration tests should be run on Bitcoin SV or before launching the application to the public on mainnet.
Install and import / require , which is a javascript SDK for integrating sCrypt smart contract.
Before deploying a contract, make sure the latest contract has been compiled to a , which is what will get deployed. This could be done automatically by running a daemon process with command npm run watch
. It will monitor a contract file's change and recompile it when necessary. All generated description files are located at testnet/fixture/autoGen
. Make sure it's up to date with the contract before deployment.
URL:
The process for installing docker engine depends on your operating system. Refer to and look up instructions for your OS.
You can browse for images that you might find use for. At the time of writing there are two options for running a Radiant node: just the node and the node with electrum.
The image for just the node: .
The image for the node + electrum: .
to see that our node is running. You can see other useful commands to run on the node in the .
在部署合约和调用合约的过程中,通常需要计算交易费用和找零输出。在不知道解锁脚本大小的情况,很难准确地计算交易费用以及找零输出。scryptlib 扩展了 库, 提供一套链式 APIs 来构造交易。使得即使在这种情况下,计算交易费用和找零都变得简单。
BIP39:
sCrypt offers . Let us look at a simple example of a stateful contract: a counter contract tracking how many times its function increment()
has been called. Its code is shown below with comments inline.
Chained APIs
When deploying and calling a contract, it is often necessary to calculate the transaction fee and the change output. Without knowing the size of the unlocking script, it is difficult to calculate both. scryptlib extends the library and provides a set of chained APIs to simplify building transactions in these cases.
1. History
All transactions from all addresses
2. Send
To send coins to an address
3. Receive
Address to receive coins and it will always be an unused one.
4. Addresses
The first 20 seed directions. All are valid for receiving and sending
5. Coins
The UTXO of each reception
6. Contacts
Addresses targeted for reuse
setInputScript
设置输入的解锁脚本
1. inputIndex
输入索引
2. (tx, output) => bsv.Script
返回解锁脚本的回调函数
setOutput
将输出添加到指定索引
1. outputIndex
输出索引
2. (tx) => bsv.Transaction.Output
返回一个输出的回调函数
setLockTime
设置交易的 nLockTime
1. nLockTime
setInputSequence
设置输入的 sequenceNumber
1. inputIndex
输入索引
2. sequenceNumber
seal
封印交易,封印后的交易不能再修改
-
getChangeAmount
获取找零输出的余额
-
getEstimateFee
根据交易大小和设置的费率评估出交易费用
-
checkFeeRate
检查交易的费用是否满足设置的费率
1. feePerKb
费率, satoshis 每 KB
prevouts
返回所有输入点的序列化串
-
setInputScript
Set input unlocking script
1. inputIndex
Input index
2. (tx, output) => bsv.Script
A callback function returns the unlocking script of the input
setOutput
Add output to the specified index
1. outputIndex
Output index
2. (tx) => bsv.Transaction.Output
A callback function returns the output
setLockTime
Set the transaction's nLockTime
1. nLockTime
setInputSequence
Set the sequenceNumber
1. inputIndex
Input index
2. sequenceNumber
seal
Seal transactions. Transactions after sealing can no longer be modified
-
getChangeAmount
Get the balance of the change output
-
getEstimateFee
Estimate transaction fee based on transaction size and fee rate
-
checkFeeRate
Check whether the transaction fee meets the fee rate
1. feePerKb
fee rate, satoshis per KB
prevouts
returns the serialization of all input outpoints
-
OP_CODESEPARATOR
下的 preimage 原象OP_CHECKSIG
检查的签名是对 preimage 原象的哈希的签名。原象包含整个交易的输出、输入和锁定脚本。通常锁定脚本是完整的。但是如果 OP_CHECKSIG
之前执行了 OP_CODESEPARATOR
,那么原象只包含锁定脚本从最近执行的 OP_CODESEPARATOR
的位置直到脚本结束,即只包含部分锁定脚本。利用这个特性,可以用来减少原象的大小,从而减少整个交易的大小。
sCrypt 标准库 Tx
提供了以下函数来检查这种只包含部分锁定脚本的原象:
Tx.checkPreimageOCS
检查的原象只包含部分锁定脚本的,默认检查的签名类型是 SigHash.ALL | SigHash.FORKID
,不支持选择签名类型
Tx.checkPreimageSigHashTypeOCS
支持选择签名类型
Tx.checkPreimageAdvancedOCS
持选择签名类型以及自定义临时密钥
Tx.checkPreimageOptOCS
优化版的 Tx.checkPreimageOCS
Tx.checkPreimageOptOCS_
优化版的 Tx.checkPreimageOCS
,支持选择签名类型
下面是一个使用 Tx.checkPreimageOCS()
来检查原象的例子:
下面是如何部署和调用使用 CheckLockTimeVerifyOCS
合约的例子:
在使用 getPreimage
计算原象时,不能传递整个锁定脚本了。需要使用 subScript(opsIndex: number)
来裁剪锁定脚本。其参数 index
是本脚本中 OP_CODESEPARATOR
的索引,即第几个 OP_CODESEPARATOR
。需要注意的是,该函数没有考虑动态执行的情况。
Small guide to compile the Radiant node and use its commands
Necessary libraries and applications to compile the node:
Download radiant node source code to compile:
Once you have downloaded the source code, enter the generated folder, create the build folder and enter inside it
Two options to compile (QT does not work properly):
No QT (recommend)
No wallet, no QT
Once everything is configured, proceed to compile with ninja and wait a few minutes.
The result will be generated in the src folder src/radiantd src/radiantd src/radiant-cli src/radiant-wallet
To run the node from any location, we can copy the file to a system directory
Copy main data to the configuration file
START NODE: radiantd
STOP NODE: radiant-cli stop
NODE INFO: radiant-cli -getinfo
NODE SYNCHRONISM: radiant-cli getblockchaininfo
CONNECTIVITY: radiant-cli getnetworkinfo
WALLET STATUS: radiant-cli getwalletinfo
CREATE NEW ADDRESS: radiant-cli getnewaddress "Principal"
GET PRIVATE ADDRESS KEY:radiant-cli dumpprivkey Direccion_Generada
IMPORT PRIVATE KEY: radiant-cli importprivkey L1NLnbPQWaE3sDMedHgHy9q3wMjzZ2HCRAtgfQqfwXppAvnPBeit Test
WALLET ADDRESSES: radiant-cli listreceivedbyaddress 1 true
To start your node in testnet run the following command
You probably need to establish a connection to a node already running on testnet. You can check if you have any connections and if the node is synching by checking
If you dont have any connections and the block count is 0 you will need to manually connect to a testnet node. To find nodes already running head on over to https://explorer-testnet.radiantblockchain.org/peers. There you will find a list over IPs that you can connect to. Choose one and replace the x'ed out IP in the command:
Now you should be able to see the connections and the node will sync.
执行这个合约的 大小是 288
字节,包含一个 288
字节的 preimage 原象。 而执行使用 Tx.checkPreimage()
版本的 合约的 大小是 1005
字节,包含一个 915
字节的 preimage 原象。 这两个合约的功能是完全一样的,但是交易的大小却优化了 80%
。
Radiant node source code:
Original guide to compile in Ubuntu:
Create multisign with 3 wallets and 2 need signers (3 of 2)
One of the new features of ZEUS and Electron Wallet 0.1.3 is the ability to use multi-signature wallets. Here is a basic process of its use.
Latest version of Electron Wallet. In this example I'm using version 0.1.3
SO compatible with wallet: Wndows, Linux and Mac.
Other wallets or persons to sign
The first step is to create a new wallet. In this guide, a test will be done with 3 wallets where it will only be necessary to sign with two of them.
Select Multi-signature wallet
In this section is where you select the type of multi-signature wallet. It is possible to make multiple possible variants, but here we will do the usual 2 out of 3.
Total cosigners: 3
Requiere signatures: 2
For the example I will create 3 wallets with 3 new seeds
Very important to make a secure copy of the words or the funds in the generated wallet could be lost.
Master public key is what you need to add to the other wallets to form the multisign wallet.
When adding cosigners it is necessary that the other two wallets tell you their master public key to continue creating the multisign wallet.
IMPORTANT: Never pass the seed to anyone, only the master public key.
Create a good password to encrypt your wallet
These are the data for the wallet that I have created for the guide and can be used to review it
SEED 1: tumble cage van bind device party shoe rail valid canal witness dial
masterpub-key: xpub6CCA12nJkoBPVtZUswdEnVT9LR87zxutoKpSpA4crx9khyuupX4qsuWyswbZub63Dqhz7hRYfRZt4oPd6D9yherrjUYcmQmdguas99FcW5x
SEED 2: avocado tuition asthma wine solar garbage limb play example hybrid unaware loud
masterpub-key: xpub6D2CVbotwBsk7czNJQjKKWWa993PjTBJHG9fHV54yXoiPVPCZZwp6JNYUFD2PJQWfUAgjqueVwwx8nqfspGHYfmRj6FN1LCNz3wmK3hGiNR
SEED 3: drift kitten flash alter update program island slide leisure youth spider diet
masterpub-key: xpub6DJgWZhSCwU8VWQxnzpUky18gH9ZtvesYac2rVsbuyyeDyVsBxdgXF3GUDiic73eFsf5ioZTgwKRwyv4HLACjmnKQS3Pn4j9zhWFce3hmiG
The three wallets would look as shown in the image. The addresses of all the multi-signature wallets start with 3, this is correct.
When receiving funds in the first direction, all wallets display the message to receive funds at the same time.
And here you would see it in the wallets
Now it's time for the sending process with the signature of two wallets. A destination address is selected and the amount to be sent. This part does not change.
The change is made when you click on send and a window appears with the transaction data. You can see that there is a signature of two and that it has been transferred to the network.
For the signature in another of the two wallets, it is necessary to copy the transaction as shown in the picture below
And in the wallet of one of the other two wallets go to: TOOLS > LOAD TRANSACTION > FROM TEXT
Here is pasted the transaction copied from the wallet that generated the sending
Once accepted, a window with the transaction will pop up. Check that everything is OK and then click on Sign and Broadcast to send to the network.
If all goes well, the window with the generated TX will be displayed
And in all the wallets you will be able to see how the funds go to the selected address.
In wallet information appears data of the wallets involved in the multi-signature.
Fin
And this is the process for multisigning in Radiant from Electron-Wallet 0.1.3
Antares
I have sent 10.5 rxd for testing to the address: 3Be9yJ3qBuHVwEsCbptmxVykRhQcXwThC4
TX: