Cadeia de caixa de plasma como uma solução para o trilema da escalabilidade de blockchain

Boa tarde, queridos leitores!

Este artigo é sobre a cadeia de caixa de plasma e esclarece os seguintes tópicos:

  • o trilema da escalabilidade e os métodos para sua solução;
  • estruturas de dados da cadeia filho e sua exibição na cadeia raiz;
  • implementação de insumos para a cadeia raiz;
  • implementação da retirada da cadeia radicular.

O Opporty usou a linguagem de programação Javascript para implementar a cadeia filho, bem como o Solidity para a cadeia raiz. Exemplos de código são fornecidos nesses idiomas.



A blockchain e a descentralização possibilitam otimizar e melhorar o trabalho de quase todas as esferas da vida em que a Internet e as tecnologias da informação são usadas. Eles aumentam a confiabilidade, a eficiência financeira e também facilitam a digitalização de coisas e bens reais.

Contratos inteligentes trazem lógica de negócios para redes descentralizadas. Isso permite criar novos aplicativos DAPP.

A execução de contratos inteligentes e a operação rápida de aplicativos com um banco de dados distribuído só podem ser possíveis se a condição de escalabilidade for atendida.

As cadeias de blocos descentralizadas modernas têm várias desvantagens. O principal é a escalabilidade. O Ethereum processa cerca de 20 tx / s. Isso não é suficiente nas realidades financeiras modernas. Ao mesmo tempo, o Ethereum tem o mais alto nível possível de proteção contra hackers e falhas de rede. Outras criptomoedas e sistemas construídos no blockchain não possuem um alto grau de descentralização, o que reduz a confiança na rede.

O trilema da escalabilidade


Há um trilema de escalabilidade de blockchain que inclui três componentes:

  • descentralização;
  • segurança
  • escalabilidade.

Descentralização no Trilemma


A descentralização, como o termo implica, reflete o grau de diversificação da propriedade da atividade na blockchain, bem como o grau de diversificação da criação de blocos e da geração de novas entradas no razão.

Para maior clareza, é necessário falar sobre as organizações mais centralizadas. Geralmente, um banco de dados simples é usado em vez do blockchain. Essa organização é administrada por administradores especiais. Todas as transações podem ser canceladas por intervenção manual.

Em redes totalmente descentralizadas, cada usuário pode participar da construção de uma rede.

A consequência mais importante da descentralização é que a maior parte do valor vai para a comunidade envolvida na criação da blockchain. Não há uma equipe intermediária de gerentes que recebam todos os benefícios, em vez daqueles que geram a própria estrutura de rede. De fato, a maioria dos projetos de criptografia é de propriedade exclusiva de seus colaboradores ou usuários, não dos fundadores. Este é obviamente um modelo mais atraente para quem não é fundador.

Segurança no Trilemma


É sobre a capacidade do blockchain de suportar ataques de fontes externas e manter o sistema em um estado inalterado. A maioria das blockchains está sujeita a muitas ameaças potenciais à segurança. É imperativo conhecer os vetores de ataque e opções de defesa mais comuns.

Nesse caso, descentralização e segurança andam de mãos dadas. Quanto mais nós, menos a rede depende do lado centralizado e, portanto, o risco de ter um ponto central de falha. No entanto, existem muitos outros vetores de ataque que representam uma ameaça para redes descentralizadas, incluindo:
> 50% de ataque - um objeto que possui mais de 50% do número total de tokens não pagos realmente possui a rede;
> Sybil Attack - o usuário pode gerar muitos identificadores no sistema para controlar efetivamente uma parcela significativa da propriedade e / ou tomada de decisão na rede;
> DDoS - um ataque de negação de serviço distribuído (DDoS) ocorre quando existe a intenção de interromper o tráfego na rede, enchendo a rede com transações maliciosas;
> Ataque de conluio - um ou vários objetos (ou nós) decidem se unir para executar qualquer operação maliciosa na rede.

Escalabilidade no Trilemma


O grau de escalabilidade é importante porque determina a taxa de transferência final, ou seja, o limite superior do tamanho da rede. A pergunta mais importante a ser feita ao avaliar uma rede é: "Quantos usuários esse sistema suporta?" Atualmente, o Bitcoin tem entre 2,9 e 5,8 milhões de portadores de carteira. A EOS tem vários milhares de membros.

Escalabilidade e descentralização podem coexistir, mas a segurança é reduzida. Os desenvolvedores escolhem as plataformas que melhor atendem às suas necessidades. Usuários fazem o mesmo. As opiniões dos dois lados às vezes diferem. Alguns usuários estão dispostos a sacrificar a segurança pela escalabilidade, outros estão dispostos a sacrificar a escalabilidade pela segurança, mas o equilíbrio é muito mais difícil.

"Santo Graal" na tecnologia blockchain


Por definição, uma blockchain possui apenas duas das três propriedades a seguir:

  • Descentralização (cada participante tem acesso apenas aos recursos O ©, ou seja, a um laptop comum ou a um pequeno VPS);
  • Escalabilidade (capacidade de processar transações O (n)> O ©);
  • Segurança (proteção contra invasores usando recursos O (n)).


Verde: um estado equilibrado de três condições.
Vermelho: segurança forte, mas descentralização e escalabilidade limitadas.
Azul: a eficiência é alta, mas a segurança e a descentralização são limitadas.
Preto: a descentralização é alta, mas não há aspectos de escalabilidade e segurança.
Cinza: descentralização total, com qualidades mínimas ou ausentes de segurança e escalabilidade.
Violeta: equilíbrio igual entre segurança e escalabilidade, a rejeição da descentralização.

O "santo graal" na tecnologia blockchain significa combinar os três aspectos.
Na maioria dos projetos atuais que trabalham com criptomoedas, duas propriedades básicas são obtidas: descentralização e segurança. A escalabilidade sofre.

Soluções promissoras para o trilema


Prova de participação (PoS)


A Prova de Estaca (PoS) fornece aprimoramentos em potencial de escalabilidade. O POS substitui a mineração de criptomoeda com base no sistema de Prova de Trabalho (PoW). A escolha do validador é muito rápida - de maneira determinística. Ao mesmo tempo, não há custo de energia e é ecológico.

Sidechains


Na rede virtual Ethereum, existe a possibilidade de criar uma rede lateral na qual o projeto possa processar suas transações individuais e, em seguida, registrar apenas os resultados iniciais e finais na rede Ethereum. Isso reduz a carga no EVM, mas oferece mais confiança no gerenciamento da cadeia lateral. Assim, a confiança em terceiros reduz a descentralização.

Sharding


O sharding divide as transações em pedaços menores de dados. Em vez de cada nó individual na rede processar transações inteiras, os nós são divididos em grupos e esses grupos de nós processam determinadas partes de dados. Mais tarde, durante o processamento, esses dados são re-assimilados para armazenamento permanente na blockchain.

Aumentar tamanho do bloco


Litecoin e Bitcoin Cash (BCH) são "garfos" para a blockchain Bitcoin. Bifurcação basicamente copia uma blockchain. Após a ramificação, você pode fazer alterações. LTC e BCH aumentaram o tamanho de cada bloco, o que permitiu armazenar mais transações por bloco, aumentando assim a velocidade de processamento das transações.

Rede Lightning


A primeira solução da cadeia lateral foi um raio. A idéia principal da Lightning Network é que nem todas as transações devem ser registradas no blockchain, pois isso sobrecarrega a rede. Se os usuários transferirem fundos um para o outro várias vezes, o registro de cada transferência é opcional. Basta abrir um tipo de canal de pagamento e anotar os dados sobre sua abertura no blockchain. Este canal permanecerá aberto conforme necessário. Quando for necessário fechá-lo, o resultado de todas as transações feitas neste canal é simplesmente gravado no blockchain. Seguindo essa ideia, você pode criar uma rede inteira de canais para pagamentos. Em seguida, as transações na blockchain serão usadas com muito menos frequência.

Um canal de pagamento é apenas uma combinação de várias transações. Um canal pode ser fechado por qualquer um de seus membros. Essa ação será como abrir um cofre, que permite pegar os fundos pertencentes aos participantes e anotar os dados de sua transferência para o blockchain.
Essa tecnologia se torna realmente poderosa quando vários desses canais são combinados em uma rede chamada The Lightning Network. Esta rede é construída especialmente para Bitcoin.

Rede Raiden


Para a Ethereum, a contraparte mais conhecida do Lightning é a Rede Raiden.
Esta é uma solução para dimensionar fora do blockchain principal. É compatível com a transferência de tokens ERC-20 em canais de pagamento bidirecionais.

Sua arquitetura básica é complexa, mas a interação com o Raiden exige que os desenvolvedores interajam apenas com a API para criar aplicativos escaláveis ​​no Raiden.

O Raiden foi projetado para fornecer pagamentos instantâneos e baixas comissões, aumentar a confidencialidade da transação e micropagamentos. A maioria dos canais de pagamento existe fora da rede e apenas ocasionalmente forma transações dentro da cadeia raiz, o que reduz significativamente a taxa de transferência da cadeia filha.

Solução ideal


Os ideólogos de raios criaram um novo conceito de cadeia de crianças que resolve problemas de velocidade da cadeia de blocos.

O Opporty praticamente implementa o conceito de Plasma e Plasma Cash.

O plasma é um conjunto de contratos inteligentes que são executados no topo da cadeia raiz do Ethereum e consistem em uma rede de cadeias filho conectadas à cadeia raiz em uma estrutura hierárquica em árvore.

Ou seja, a segurança do rootchain Ethereum é usada para otimizar a escalabilidade.

Dinheiro de plasma: opção oportuna


O Opporty usa a implementação do Plasma Cash na primeira versão.

Este modelo é a implementação de plasma mais eficaz em termos de escalabilidade.
O Plasma Cash é um sistema baseado no uso de identificadores exclusivos para cada token na cadeia Plasma. Ou seja, a NFT é aplicada e os tokens na rede recebem números de série exclusivos.

Características do dinheiro de plasma:

  • Validação fragmentada no lado do cliente - os clientes precisam apenas monitorar sua cadeia de plasma para obter seus tokens. Isso significa que o rendimento da transação pode aumentar sem aumentar a carga em usuários individuais.
  • Simplificação da saída em massa - as saídas em massa tornam-se menos uma ameaça para a rede, pois o ladrão deve enviar uma transação de saída para cada token que ele deseja roubar.
  • Não há confirmações bidirecionais - as transações não exigem mais envio e confirmação em duas etapas. Em vez disso, uma transação pode ser gasta assim que incluída na cadeia principal.

Desvantagem:

Denominações grandes de tokens - como cada número de série deve ser atribuído a um token, é impossível produzir tokens arbitrariamente pequenos. Isso se deve ao fato de que, em algum momento, o valor da compra do token será maior que o valor do próprio token.

Estrutura da transação em dinheiro plasma oportuno


O Javascript usado oportuno para implementar childchain. Cada transação no Opporty Plasma Cash é uma estrutura semelhante:

const transactionFields = [ {name: 'prevHash'}, {name: 'prevBlock', int: true, default: 0}, {name: 'tokenId', isDecimal: true}, {name: 'newOwner'}, {name: 'type'}, {name: 'signature'}, ] 

Os principais elementos aqui são um link para o bloco prevBlock anterior (é necessário mover-se pela cadeia de blocos), o identificador de tokenId tokenId (deve ser exclusivo) e também newOwner, o último proprietário do token.

Além disso, para montar o bloco e obter o hash da cadeia raiz, é usado um tipo especial da árvore Patricia Merkle Trie. A mesma árvore é usada no Ethereum. Tem uma aparência compactada. Ao mesmo tempo, você ainda pode receber provas de inclusão ou não inclusão de uma transação em um bloco.
Assinatura é uma assinatura em curvas elípticas.

Uma transação que gasta um token com um determinado tokenId é válida apenas se for incluída na árvore Merkle na posição tokenId, ou seja, para cada token na árvore Merkle há apenas um "local" que gasta esse token onde transações são permitidas. Esse formato permite que os usuários verifiquem o histórico completo da cadeia de plasma, além de provar e refutar a propriedade de tokens específicos.

Para gastar um token, você precisa validar a cadeia, verificar se há blocos ausentes e só então assinar novamente a transação junto com todo o histórico.

O bloco é o seguinte:

 const blockFields = [ {name: 'prevHash'}, {name: 'blockNum', isDecimal: true}, {name: 'transactions'}, {name: 'merkleRoot'}, {name: 'time'} ] 

Em um nível básico, uma blockchain é simplesmente uma cadeia de blocos com um link para o bloco anterior. Essa estrutura torna possível obter a propriedade de imutabilidade, ou seja, não reescrever o histórico. O merkleRoot torna possível escrever pontos de verificação na cadeia raiz.

Na cadeia raiz, no nível do contrato inteligente, é assim (linguagem Solidity):

 /* * Block structure (represents one block in a chain) */ struct Block { uint block_num; bytes32 merkle_root; uint time; /* * Transaction structure (decoded from RLP form) */ struct Transaction { bytes32 prevhash; uint prev_block; uint token_id; address new_owner; } 

A codificação é realizada usando as funções de codificação / decodificação - serialização / desserialização de RLP.

Maneiras de entrar no Plasma Cash


Qualquer pessoa pode depositar fundos no Plasma Cash simplesmente transferindo o éter para um contrato inteligente. Como resultado, um token OPP será recebido em uma posição tokenId específica.

Aqui está a implementação no Solidity:

 function deposit() public payable { uint token_id = uint(keccak256(msg.sender, msg.value, deposit_blk)); // token.index = deposit_blk; tokens[token_id] = msg.value; deposit_blk += 1; emit DepositAdded(msg.sender, msg.value, token_id, current_blk); } 

Ou seja, tokenId é gerado como um número aleatório (hash). Em seguida, é gerado um evento que é verificado na cadeia filho.

Formas de retirar para o Plasma Cash


Cada pessoa pode retirar seu token fornecendo as duas últimas transações no histórico de propriedade do token.

Implementação de saída da cadeia raiz:

 function startExit(uint block_num, bytes tx1, bytes tx0, bytes proof1, bytes proof0) public returns (uint exit_id) { require(checkPatriciaProof(keccak256(tx1), childChain[block_num].merkle_root, proof1)); bytes32 prev_hash; uint prev_blk; uint token_id; address new_owner; (prev_hash, prev_blk, token_id, new_owner,) = getTransactionFromRLP(tx1); require(msg.sender == new_owner); require(tokens[token_id] > 0); bytes32 hashPrevTx = keccak256(tx0); require(checkPatriciaProof(hashPrevTx, childChain[prev_blk].merkle_root, proof0)); require(prev_hash == hashPrevTx); Exit storage record = exitRecords[token_id]; require(record.block_num == 0); record.block_num = block_num; record.new_owner = msg.sender; record.prev_block = prev_blk; if (childChain[block_num].time > block.timestamp - week) record.priority = childChain[block_num].time; else record.priority = block.timestamp - week; exits.add(record.priority); exit_ids[record.priority].push(token_id); emit ExitAdded(msg.sender, record.priority, token_id); return token_id; } 

Primeiro, duas transações são verificadas. Se o usuário atual for o proprietário da transação, basta adicionar sua saída à estrutura e deixar duas semanas para a oportunidade de contestar a saída.

A conclusão pode ser contestada de três maneiras:

  • Fornecendo confirmação de gastos em transações:

 function challengeSpent(uint exit_id, uint blk_num, bytes tx1, bytes proof) public { require(checkPatriciaProof(keccak256(tx1), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); uint prev_block; uint token_id; (, prev_block , token_id, ) = getTransactionFromRLP(tx1); require(tokens[token_id] > 0); require(prev_block == record.block_num && record.block_num < blk_num); require(token_id == exit_id); exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); } 

Se houver uma transação que já esteja gastando o token exibido, essa retirada será cancelada!

  • Comprovação de despesas para a transação anterior:

 /* * Challenge exit by providing * a proof of a transaction spending P(C) that appears before C */ function challengeDoubleSpend(uint exit_id, uint blk_num, bytes tx1, bytes proof) public { require(checkPatriciaProof(keccak256(tx1), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); // bytes32 prev_hash; uint prev_block; uint token_id; (, prev_block , token_id, ) = getTransactionFromRLP(tx1); require(tokens[token_id] > 0); // check if token double spent require(prev_block == record.prev_block && blk_num < record.block_num); // require(token_id == exit_id); exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); } 

É a mesma verificação como se o token tivesse sido gasto antes da retirada. Primeiro, verifique se há uma transação no hash raiz. Em seguida, excluiremos a saída, se ela já tiver sido gasta.

  • fornecendo uma transação no histórico de transações do token antes dele.

Esta pode ser uma história errada, por isso você precisa confirmá-la com uma transação filho:

 // */ function challengeInvalidHistory(uint exit_id, uint blk_num, bytes tx0, bytes proof) public { // check if proof is valid require(checkPatriciaProof(keccak256(tx0), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); bytes32 prev_hash; uint token_id; (prev_hash, , token_id, ) = getTransactionFromRLP(tx0); //require(exit_id == token_id); require(tokens[token_id] > 0); // transaction should be before exit tx in history require(blk_num < record.block_num - 1); challenged[exit_id] = blk_num; emit ChallengedInvalidHistory(exit_id, token_id); } 

A chamada do primeiro e do segundo scripts bloqueia a saída imediatamente.

A chamada para o terceiro cenário pode ser atendida fornecendo um descendente direto. Ele deve ser igual ou antes da transação pai.

 /* * Respond to invalid history challenge by providing * the direct child of C*, which must be either equal to or before P( C ) */ function respondChallenge(uint exit_id, uint blk_num, bytes childtx, bytes proof) public { require(challenged[exit_id] > 0); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); require(checkPatriciaProof(keccak256(childtx), childChain[blk_num].merkle_root, proof)); // get transaction from rlpencoded form bytes32 prev_hash; uint prev_block; uint token_id; (prev_hash, prev_block, token_id, ) = getTransactionFromRLP(childtx); // if direct child if (prev_block == challenged[exit_id] ) { if (blk_num <= record.prev_block && token_id == exit_id ) { delete challenged[exit_id]; emit ExitRespondedEvent(exit_id); } else { exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); } } } 

Ou seja, se a transação filho correta for recebida, a saída será contestada e permanecerá na fila!
Após a construção de parte do protocolo Opporty Plasma Cash, foi feita a seguinte conclusão:
Este protocolo fornece segurança através da cadeia raiz do Ethereum.

Ao complicar os procedimentos de entrada e saída da cadeia raiz e da compressão do estado (blocos de transação), todos os métodos de saída e entrada na cadeia raiz foram considerados e as estruturas básicas de dados: transações e blocos foram investigados.

Usando a cadeia lateral baseada na rede Ethereum, você pode acelerar significativamente as transações. O Opporty recebeu até 300.000 transações por segundo em um único operador. Isso é muito mais do que os atuais sistemas de pagamento podem oferecer.

Apesar de alguns problemas de disponibilidade de dados, a operadora fornece um alto nível de estabilidade do blockchain e possibilita a realização de transações comerciais internacionais eficazes.

O Plasma Cash traz um enorme aumento na escalabilidade. Portanto, o Opporty usa o plasma como parte de seu protocolo PoE.

Links úteis


  1. Plasma de papel branco
  2. Hub Git
  3. Casos de uso e descrição da arquitetura
  4. Papel de rede relâmpago

Source: https://habr.com/ru/post/pt457518/


All Articles