NEAR Protocol e Solana

(🫰 0 nL)
12 min read
To Share and +4 nLEARNs

Hoje vamos ver duas das plataformas de contratos inteligentes mais promissoras do mundo – NEAR Protocol e Solana. Embora o Ethereum ainda domine esse mercado, o fato é que sua falta de escalabilidade e altas taxas forçaram a maioria dos desenvolvedores a procurar alternativas viáveis. Near e Solana emergiram como os dois primeiros colocados.

O que é Solana?

solana foi fundada em 2017 por Anatoly Yakovenko, que já havia trabalhado na DropBox. Yakovenko, junto com Eric Williams e CTO Greg Fritzgerald, criou Solana para resolver os problemas existentes em Bitcoin e Ethereum. O projeto atraiu investimentos da Multicoin Capital, Foundation Capital, SLOW Capital, CMCC Global, Abstract Ventures e muito mais.

Pasted image 0

Características da blockchain Solana

  • 50.000 transações por segundo e tempo de criação de bloco de 0,4 segundos
  • O sistema pode fornecer 28,4 milhões de transações por segundo em uma rede de 40 gigabits.
  • Solana usa o algoritmo de consenso Proof-of-History.

Como funciona a Prova de Histórico (PoH)?

Em uma rede descentralizada que se espalha por uma grande área, o consenso é essencial. O Bitcoin usa o consenso de prova de trabalho (PoW – Proof of Work) para cuidar do consenso. Embora o método seja altamente seguro, é difícil não ignorar seu problema mais significativo – a falta de escalabilidade. Não se esqueça que o Bitcoin só pode fazer 7 transações por segundo.

Solana usa prova de história (PoH – Proof of History), em que cria registros históricos para provar que um evento ocorre durante um momento específico no tempo. Aqui estão alguns pontos que você precisa ter em mente:

  • O algoritmo usa uma função de atraso verificável de alta frequência que requer um certo número de etapas sequenciais para terminar.
  • As transações ou eventos cronometrados na rede serão designados como uma contagem única de hash a, que pode ser verificada publicamente.
  • A contagem permite que a rede saiba exatamente quando a transação ou o evento aconteceu.
  • Cada nó possui um relógio criptográfico que ajuda a rastrear o tempo da rede e a ordem dos eventos.

Devido ao PoH, a rede Solana suporta 50.000 transações por segundo durante a execução com GPUs.

O que é um Cluster Solana?

Um cluster é um conjunto de computadores de propriedade independente trabalhando juntos e pode ser visto como um sistema singular. As principais características do Cluster são as seguintes:

  • Eles ajudam a verificar a saída de programas não confiáveis ​​enviados pelo usuário.
  • Mantém um registro de qualquer transação ou evento que um usuário faz.
  • Ele rastreia quais computadores fizeram um trabalho significativo para manter a rede funcionando.
  • Ele rastreia a posse de ativos do mundo real.

Qual dos seguintes utiliza sharding?

Correct! Wrong!

Programação em Solana

Os contratos inteligentes em Solana são escritos em Rust ou C e compilados para bytecode Berkeley Packet Filter (BPF). Como existem mais ferramentas disponíveis, é recomendável que você codifique em Rust. Iniciantes devem codificar seus programas usando o framework Anchor, que simplifica a execução.

Solana tem um modelo de conta exclusivo que é semelhante aos arquivos do sistema operacional Linux. Eles podem conter quaisquer dados arbitrários e também conter metadados sobre como podem ser acessados. Tenha em mente, porém, que as contas têm um tamanho fixo e não podem ser redimensionadas.

O modelo de programação atual da Solana pode forçá-lo a mover a lógica do aplicativo para fora da cadeia ou modificar a funcionalidade para ser ineficiente e limitada pelo tamanho fixo da conta.

Qual das opções a seguir é parte integrante de Solana?

Correct! Wrong!

Exemplo de contrato

#![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,

}

O que está acontecendo no contrato?

  • Todas as contas a serem acessadas são anotadas na estrutura para cada chamada com #[derive(Accounts)].
  • As funções ajudam a inicializar os dados da conta do proprietário inicial e da Compra. Isso permite que qualquer pessoa compre por mais tokens.
  • Os dados temporários são passados ​​para os parâmetros da função. Esses parâmetros estão dentro das funções de inicialização e compra. Isso também inclui o Contexto que mantém as contas necessárias para a transação.
  • O estado do contrato está localizado na estrutura ContentRecord. Isso é anotado com #[account] para indicar que representa o layout de dados de uma conta.

O que é NEAR Protocol?

Entrando em vigor no verão de 2018, o protocolo foi projetado para criar o ambiente perfeito para aplicativos descentralizados, fornecendo velocidades mais altas, maior rendimento e melhor compatibilidade com outras blockchains. A NEAR possui uma técnica única de Sharding e apresenta um mecanismo de geração de blocos chamado “Doomslug” proposto em 2019. Doomslug permite finalidade prática ou “Doomslug”, garantindo que os blocos sejam finalizados em segundos.

O protocolo NEAR é desenvolvido pelo NEAR Collective, uma comunidade de desenvolvedores e pesquisadores que colaboram na construção do projeto. Alguns recursos importantes da NEAR são:

O que é o coletivo NEAR (NEAR Collective)?

O Coletivo NEAR inclui organizações individuais e outros colaboradores que trabalham continuamente para melhorar o Protocolo NEAR. O Coletivo trabalha em projetos como escrever o código inicial e implementação para a Rede NEAR. A NEAR é totalmente descentralizada, operando de forma independente e não pode ser desligada ou manipulada, mesmo por quem a construiu.

É uma organização sem fins lucrativos focada na criação de um ecossistema vibrante em torno da blockchain NEAR. Auxilia na coordenação das atividades de governança e desenvolvimento. O NEAR Collective tem vários projetos, sendo a NEAR blockchain apenas um dos vários projetos sob o teto do Coletivo.

Mecanismo de Consenso NEAR

O mecanismo de consenso implementado no NEAR é chamado de Nightshade. Nightshade modela o sistema como uma única blockchain. A lista de todas as transações em cada bloco é dividida em blocos físicos, um bloco por fragmento. Todos os pedaços (chunks) se acumulam em um bloco. Observe que os chunks só podem ser validados por nós que mantêm o estado desse shard.

Falando em validação, um componente chave de NEAR são os validadores. Esses validadores são responsáveis ​​por manter o consenso dentro do protocolo. Os validadores são nós especializados que precisam manter seus servidores online 100% do tempo, mantendo seus sistemas continuamente atualizados.

Aqui estão alguns pontos que você deve ter em mente sobre os validadores de rede.

  • A NEAR determina seus validadores de rede a cada nova época, elegendo-os com base em sua participação.
  • Os validadores já eleitos são reinscritos por meio de uma nova aposta automática de seus tokens mais as recompensas acumuladas.
  • Os validadores potenciais devem ter sua participação acima de um nível determinado dinamicamente.
  • Existem dois métodos que um validador pode usar para fortalecer seu staking – comprar os tokens por conta própria ou pedir emprestado por delegação de participação.
  • A recompensa que você recebe é diretamente proporcional à sua aposta – quanto maior a quantidade de tokens em staking, mais recompensas.

O consenso é baseado no consenso da cadeia mais pesada. Ou seja, uma vez que um produtor de bloco publica um bloco, ele coleta as assinaturas dos nós validadores. O peso de um bloco é então a aposta cumulativa de todos os signatários cujas assinaturas estão incluídas no bloco. O peso de uma cadeia é a soma dos pesos dos blocos. Além disso, o consenso utiliza um dispositivo de finalidade que introduz condições de corte adicionais para maior segurança da cadeia.

Doomslug” é um mecanismo de geração de blocos de qual protocolo?

Correct! Wrong!

Aurora e NEAR Protocol

A Aurora também foi lançada no NEAR Protocol, fornecendo uma Experiência da camada 2 Ethereum. Algumas das maneiras pelas quais a Aurora melhora a NEAR são:

  • Ele ajuda a aumentar a taxa de transferência para milhares de transações por segundo.
  • Um tempo de finalização de bloco de 2 segundos.
  • Crescimento do ecossistema à prova de futuro
  • Baixas taxas de transação, que são 1000 vezes mais baixas que o Ethereum.
  • Compatibilidade intransigente com Ethereum.

Exemplo de Contrato

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());
    }
}

O que está acontecendo no contrato?

Então, o que está acontecendo aqui no contrato? Vamos olhar mais de perto.

  • O contrato é definido por #[near_bindgen] no ContentTracker, é semelhante a um construtor no Solidity e é chamado quando o contrato é implantado.
  • A função de compra é anotada com #[payable].
  • O contrato inclui chamadas assíncronas na forma de Promise::new(…).transfer(…); lines.
  • A estrutura de dados LookupMap<String, ContentRecord> lida com a pesquisa de valor-chave, que acessa o armazenamento. Isso é igual ao  “mapping” do Solidity.

Conclusão

Tanto Solana quanto NEAR Protocol são contratos inteligente brilhantes,  plataformas que construíram comunidades altamente ativas. Ambos trazem recursos especiais que ajudam a combater o maior problema que assola o mundo descentralizado – a velocidade. Ambas as plataformas ainda estão crescendo e são muito promissoras.

Leave a Comment


To leave a comment you should to:


Scroll to Top