Aujourd’hui, examinons deux des plates-formes de contrats intelligents les plus prometteuses au monde — Near Protocol et Solana. Bien qu’Ethereum domine toujours ce marché, le fait est que son manque d’évolutivité et ses frais élevés ont contraint la plupart des développeurs à rechercher des alternatives viables. Near et Solana sont devenus les deux premiers.
Qu’est-ce que Solana ?
Solana a été fondée en 2017 par Anatoly Yakovenko, qui avait auparavant travaillé chez DropBox. Yakovenko, avec Eric Williams et CTO Greg Fritzgerald, a créé Solana pour résoudre les problèmes existants dans Bitcoin et Ethereum. Le projet a attiré des investissements de Multicoin Capital, Foundation Capital, SLOW Capital, CMCC Global, Abstract Ventures, etc.
Caractéristiques de la blockchain Solana
- 50 000 transactions par seconde et 0,4 seconde de temps de bloc
- Le système peut fournir 28,4 millions de transactions par seconde sur un réseau de 40 gigabits.
- Solana utilise l’algorithme de consensus Proof-of-History.
Comment fonctionne la preuve d’histoire (PoH) ?
Dans un réseau décentralisé qui s’étend sur un vaste territoire, le consensus est essentiel. Bitcoin utilise le consensus de preuve de travail (PoW) pour prendre en charge le consensus. Bien que la méthode soit hautement sécurisée, il est difficile de ne pas ignorer son problème le plus important : le manque d’évolutivité. N’oubliez pas que Bitcoin ne peut effectuer que 7 transactions par seconde.
Solana utilise la preuve de l’histoire, dans laquelle il crée des enregistrements historiques pour prouver qu’un événement se produit à un moment précis. Voici quelques points que vous devez garder à l’esprit :
- L’algorithme utilise une fonction de délai vérifiable à haute fréquence qui nécessite un certain nombre d’étapes séquentielles pour terminer.
- Les transactions ou les événements cadencés au sein du réseau seront désignés par un compte de hachage unique, qui peut être vérifié publiquement.
- Le comptage permet au réseau de savoir exactement quand la transaction ou l’événement a eu lieu.
- Chaque nœud possède une horloge cryptographique qui permet de suivre l’heure du réseau et l’ordre des événements.
En raison de PoH, le réseau Solana prend en charge 50 000 transactions par seconde lors de l’exécution avec des GPU.
Qu’est-ce qu’un cluster Solana ?
Un cluster est un ensemble d’ordinateurs indépendants qui fonctionnent ensemble et peuvent être considérés comme un système singulier. Les principales caractéristiques du cluster sont les suivantes :
- Ils aident à vérifier la sortie de programmes non fiables soumis par les utilisateurs.
- Ils aident à vérifier la sortie de programmes non fiables soumis par les utilisateurs.
- Il garde une trace des ordinateurs qui ont fait un travail significatif pour maintenir le réseau en marche.
- Il garde une trace de la possession d’actifs du monde réel.
Which of the following utilizes sharding?
Programmation en Solana
Les contrats intelligents dans Solana sont écrits en Rust ou C et compilés dans le bytecode Berkeley Packet Filter (BPF). Comme il y a plus d’outils disponibles, il est recommandé de coder en Rust. Les débutants doivent coder leurs programmes en utilisant le framework Anchor, ce qui simplifie l’exécution.
Solana a un modèle de compte unique qui est similaire aux fichiers du système d’exploitation Linux. Ils peuvent contenir des données arbitraires et contenir également des métadonnées sur la façon dont ils peuvent être consultés. Gardez cependant à l’esprit que les comptes ont une taille fixe et ne peuvent pas être redimensionnés.
Le modèle de programmation actuel de Solana peut vous obliger à déplacer la logique d’application hors chaîne ou à modifier la fonctionnalité pour qu’elle soit inefficace et limitée par la taille fixe du compte.
Which of the following is an integral part of Solana?
Exemple de contrat
#![feature(proc_macro_hygiene)] use anchor_lang::prelude::*; use anchor_spl::token::{self, TokenAccount, Transfer}; #[program] pub mod plutocratic_hosting { use super::*; /// Initialize a new contract with initialized content. #[access_control(Initialize::validate(&ctx, nonce))] pub fn initialize( ctx: Context<Initialize>, price: u64, content: String, nonce: u8, ) -> ProgramResult { // Transfer funds to the contract vault. let cpi_accounts = Transfer { from: ctx.accounts.from.to_account_info().clone(), to: ctx.accounts.vault.to_account_info().clone(), authority: ctx.accounts.owner.clone(), }; let cpi_program = ctx.accounts.token_program.clone(); let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); token::transfer(cpi_ctx, price)?; // Initialize the content data. let content_record = &mut ctx.accounts.content; content_record.price = price; content_record.content = content; content_record.nonce = nonce; content_record.owner = *ctx.accounts.owner.to_account_info().key; content_record.vault = *ctx.accounts.vault.to_account_info().key; Ok(()) } /// Purchase content address for new price, if transferring more tokens. #[access_control(check_funds(&ctx.accounts.content, price))] pub fn purchase(ctx: Context<Purchase>, price: u64, content: String) -> ProgramResult { // Transfer funds from contract back to owner. let seeds = &[ ctx.accounts.content.to_account_info().key.as_ref(), &[ctx.accounts.content.nonce], ]; let signer = &[&seeds[..]]; let cpi_accounts = Transfer { from: ctx.accounts.vault.to_account_info().clone(), to: ctx.accounts.owner_token.to_account_info().clone(), authority: ctx.accounts.contract_signer.clone(), }; let cpi_program = ctx.accounts.token_program.clone(); let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer); token::transfer(cpi_ctx, ctx.accounts.content.price)?; // Transfer funds from new owner to contract. let cpi_accounts = Transfer { from: ctx.accounts.new_owner_token.to_account_info().clone(), to: ctx.accounts.vault.to_account_info().clone(), authority: ctx.accounts.new_owner.clone(), }; let cpi_program = ctx.accounts.token_program.clone(); let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); token::transfer(cpi_ctx, price)?; // Overwrite content let content_record = &mut ctx.accounts.content; content_record.price = price; content_record.content = content; content_record.owner = *ctx.accounts.new_owner.to_account_info().key; Ok(()) } } #[account] pub struct ContentRecord { /// Price at which the current content is owned. pub price: u64, /// Content Data. pub content: String, /// Public key of current owner of the content. pub owner: Pubkey, /// Address for token program of funds locked in contract. pub vault: Pubkey, /// Nonce for the content, to create valid program derived addresses. pub nonce: u8, } #[derive(Accounts)] pub struct Initialize<'info> { #[account(init)] content: ProgramAccount<'info, ContentRecord>, #[account(mut, "&vault.owner == contract_signer.key")] vault: CpiAccount<'info, TokenAccount>, /// Program derived address for the contract. contract_signer: AccountInfo<'info>, /// Token account the contract is made from. #[account(mut, has_one = owner)] from: CpiAccount<'info, TokenAccount>, /// Owner of the `from` token account. owner: AccountInfo<'info>, token_program: AccountInfo<'info>, rent: Sysvar<'info, Rent>, } impl<'info> Initialize<'info> { pub fn validate(ctx: &Context<Self>, nonce: u8) -> Result<()> { let signer = Pubkey::create_program_address( &[ ctx.accounts.content.to_account_info().key.as_ref(), &[nonce], ], ctx.program_id, ) .map_err(|_| ErrorCode::InvalidNonce)?; if &signer != ctx.accounts.contract_signer.to_account_info().key { return Err(ErrorCode::InvalidSigner.into()); } Ok(()) } } #[derive(Accounts)] pub struct Purchase<'info> { #[account(mut, has_one = vault)] content: ProgramAccount<'info, ContentRecord>, #[account(mut)] vault: CpiAccount<'info, TokenAccount>, #[account(seeds = [ content.to_account_info().key.as_ref(), &[content.nonce], ])] contract_signer: AccountInfo<'info>, #[account(mut, has_one = owner)] owner_token: CpiAccount<'info, TokenAccount>, #[account(mut)] new_owner_token: CpiAccount<'info, TokenAccount>, #[account(signer)] new_owner: AccountInfo<'info>, owner: AccountInfo<'info>, token_program: AccountInfo<'info>, } fn check_funds(check: &ContentRecord, new_price: u64) -> Result<()> { if check.price >= new_price { return Err(ErrorCode::InsufficientFunds.into()); } Ok(()) } #[error] pub enum ErrorCode { #[msg("The given nonce does not create a valid program derived address.")] InvalidNonce, #[msg("The derived signer does not match that which was given.")] InvalidSigner, #[msg("Insufficient funds provided to purchase route.")] InsufficientFunds, }
Que se passe-t-il dans le contrat ?
-
Tous les comptes auxquels accéder sont annotés dans la structure pour chaque appel avec #[derive(Accounts)].
-
Les fonctions aident à initialiser les données de compte pour le propriétaire initial et l’achat. Cela permet à n’importe qui de l’acheter pour plus de jetons.
-
Les données temporaires sont passées dans les paramètres de la fonction. Ces paramètres sont à l’intérieur des fonctions d’initialisation et d’achat. Cela inclut également le contexte de tenue des comptes requis pour la transaction.
-
L’état du contrat est situé dans la structure ContentRecord. Ceci est en outre annoté avec #[compte] pour indiquer qu’il représente la présentation des données pour un compte.
Qu’est-ce que le protocole NEAR ?
Créé à l’été 2018, le protocole a été conçu pour créer l’environnement parfait pour les applications décentralisées en offrant des vitesses plus élevées, un débit plus élevé et une meilleure compatibilité avec d’autres chaînes. NEAR a une technique de partage unique et introduit un mécanisme de génération de blocs appelé « Doomslug » proposé en 2019. Doomslug permet une finalité pratique ou « Doomslug », garantissant que les blocs reçoivent la finalité en quelques secondes.
Le protocole NEAR est développé par le NEAR Collective, une communauté de développeurs et de chercheurs collaborant à la construction du projet. Certaines caractéristiques essentielles de NEAR sont :
- NEAR est un système partitionné qui permet une évolutivité infinie.
- Un protocole facile à utiliser, NEAR permet aux développeurs de créer des applications facilement et rapidement.
- NEAR n’est pas une chaîne latérale mais un protocole de couche 1.
- Les dApps créées à l’aide de NEAR s’exécutent au-dessus de la couche NEAR sous-jacente.
Qu’est-ce que la collectivité NEAR ?
La collectivité NEAR comprend des organisations individuelles et d’autres contributeurs qui travaillent en permanence à l’amélioration du protocole NEAR. La collectivité travaille sur des projets tels que l’écriture du code initial et la mise en œuvre pour le réseau NEAR. NEAR est entièrement décentralisé, fonctionne de manière indépendante et ne peut pas être arrêté ou manipulé, même par ceux qui l’ont construit.
C’est une organisation à but non lucratif qui se concentre sur la création d’un écosystème dynamique autour de la blockchain NEAR. Il aide à la coordination des activités de gouvernance et de développement. La collectivité NEAR a plusieurs projets, la blockchain NEAR n’étant qu’un des nombreux projets sous l’égide de la collectivité.
Mécanisme de NEAR Consensus
Le mécanisme de consensus mis en place sur NEAR s’appelle Nightshade. Nightshade modélise le système comme une seule blockchain. La liste de toutes les transactions dans chaque bloc est divisée en morceaux physiques, un morceau par fragment. Tous les morceaux s’accumulent dans un bloc. Notez que les morceaux ne peuvent être validés que par des nœuds qui conservent l’état de cette partition.
En parlant de validation, un élément clé de NEAR sont les validateurs. Ces validateurs sont responsables du maintien du consensus au sein du protocole. Les validateurs sont des nœuds spécialisés qui doivent maintenir leurs serveurs en ligne à 100 % tout en maintenant leurs systèmes à jour en permanence.
Voici quelques points que vous devez garder à l’esprit concernant les validateurs de réseau.
-
NEAR détermine ses validateurs de réseau à chaque nouvelle époque, en les élisant en fonction de leur enjeu.
-
Les validateurs déjà élus sont réinscrits en rejouant automatiquement leurs jetons plus les récompenses accumulées.
-
Les validateurs potentiels doivent avoir leur mise au-dessus d’un niveau déterminé dynamiquement.
-
Un validateur peut utiliser deux méthodes pour renforcer sa participation : acheter les jetons lui-même ou emprunter via une délégation de participation.
-
La récompense que vous recevez est directement proportionnelle à votre mise : plus votre mise, plus vos récompenses.
Le consensus est basé sur le consensus de la chaîne la plus lourde. Cela signifie qu’une fois qu’un producteur de bloc publie un bloc, il collecte les signatures des nœuds de validation. Le poids d’un bloc est alors la mise cumulée de tous les signataires dont les signatures sont incluses dans le bloc. Le poids d’une chaîne est la somme des poids des blocs. De plus, le consensus utilise un gadget de finalité qui introduit des conditions de réduction supplémentaires pour une sécurité de chaîne plus élevée.
Doomslug” is a block generation mechanism of which protocol?
Protocole Aurora et NEAR
Aurora a également lancé le protocole NEAR, offrant une expérience Ethereum Layer-2. Certaines des façons dont Aurora améliore NEAR sont :
- Il aide à augmenter le débit à des milliers de transactions par seconde.
- Un temps de finalité de bloc de 2 secondes.
- Croissance de l’écosystème à l’épreuve du temps
- Frais de transaction faibles, qui sont 1000 fois inférieurs à ceux d’Ethereum.
- Compatibilité sans compromis avec Ethereum.
Exemple de contrat
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::collections::LookupMap; use near_sdk::{env, near_bindgen, AccountId, Balance, Promise}; #[global_allocator] static ALLOC: near_sdk::wee_alloc::WeeAlloc = near_sdk::wee_alloc::WeeAlloc::INIT; #[derive(BorshDeserialize, BorshSerialize)] pub struct ContentRecord { pub price: Balance, pub content: String, pub owner: AccountId, } #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct ContentTracker { values: LookupMap<String, ContentRecord>, contract_owner: AccountId, } impl Default for ContentTracker { fn default() -> Self { let contract_owner = env::predecessor_account_id(); Self { values: LookupMap::new(b"v".to_vec()), contract_owner, } } } #[near_bindgen] impl ContentTracker { /// Gets content at a given route. pub fn get_route(&self, route: String) -> Option<String> { self.values.get(&route).map(|v| v.content) } /// Purchases a route based on funds sent to the contract. #[payable] pub fn purchase(&mut self, route: String, content: String) { let deposit = env::attached_deposit(); assert!(deposit > 0); if let Some(entry) = self.values.get(&route) { assert!( deposit > entry.price, "Not enough deposit to purchase route, price: {} deposit: {}", entry.price, deposit ); // Refund purchase to existing owner Promise::new(entry.owner).transfer(entry.price); } // Update record for the contract state. self.values.insert( &route, &ContentRecord { price: deposit, content, owner: env::predecessor_account_id(), }, ); } /// Allows owner of the contract withdraw funds. pub fn withdraw(&mut self) { assert_eq!(env::predecessor_account_id(), self.contract_owner); // Send the contract funds to the contract owner Promise::new(self.contract_owner.clone()).transfer(env::account_balance()); } }
Que se passe-t-il dans le contrat ?
Alors, que se passe-t-il ici dans le contrat? Regardons de plus près.
- Le contrat est défini par #[near_bindgen] dans le ContentTracker, il est similaire à un constructeur dans Solidity et est appelé lorsque le contrat est déployé
- La fonction d’achat est annotée avec #[payable].
- Le contrat comprend des appels asynchrones sous forme de Promise::new(…).transfer(…); lignes.
- La structure de données LookupMap<String, ContentRecord> gère la recherche clé-valeur, qui accède au stockage. Ceci est égal à la « cartographie » de Solidité.
Conclusion
Solana et NEAR Protocol sont tous deux de brillantes plateformes de contrats intelligents qui ont construit des communautés très actives. Les deux apportent des fonctionnalités spéciales qui aident à combattre le plus gros problème qui afflige le monde décentralisé — la vitesse. Les deux plates-formes sont encore en croissance et ont beaucoup de promesses.