O que devemos construir uma blockchain?

Toda a história da humanidade é uma libertação contínua das cadeias e a criação de novas, ainda mais fortes. (Autor anônimo)

Analisando vários projetos de blockchain (Bitshares, Hyperledger, Exonum, Ethereum, Bitcoin etc.), entendo que, do ponto de vista técnico, todos eles são construídos com os mesmos princípios. As cadeias de blocos se assemelham a casas que, por toda a sua variedade de designs, decoração e designações, têm uma fundação, paredes, teto, janelas, portas, que são conectadas umas às outras de determinadas maneiras. E se você entender os princípios básicos do projeto de construção, conhecer as propriedades dos materiais utilizados, poderá determinar o objetivo de uma casa em particular. Atualmente, surgiu uma situação com o blockchain que todo mundo já ouviu falar, mas poucos entendem a arquitetura e os princípios do trabalho. Portanto, surge um mal-entendido sobre o que e como faz sentido usar as tecnologias blockchain.

Neste artigo, analisaremos as propriedades e os princípios comuns a todas as blockchains. A seguir, examinamos as tarefas que podem ser resolvidas usando o blockchain e, para consolidar o material , construiremos um pequeno , mas real, blockchain em nosso site virtual!

Então, vamos lembrar que problemas o blockchain resolveu originalmente.

Estou certo de que muitos dirão sobre um banco de dados distribuído, descentralizado, público e imutável. Mas por que tudo isso era necessário?

Prefiro começar a estudar qualquer tecnologia lendo os padrões, pois todos os artigos e livros sobre o tópico em estudo são baseados neles. No entanto, atualmente não existem padrões de blockchain; apenas comitês foram criados na ISO para seu desenvolvimento. Atualmente, cada projeto público de blockchain tem seu próprio white paper, que é essencialmente uma tarefa técnica. O primeiro projeto de blockchain conhecido é a rede Bitcoin. Vamos ao site oficial da rede e vemos como tudo começou.

Desafio Blockchain


Portanto, a tarefa que o blockchain resolveu na rede pioneira do Bitcoin é fazer uma transferência confiável da propriedade dos ativos digitais em um ambiente não confiável sem intermediários. Por exemplo, em uma rede Bitcoin, um ativo digital é uma moeda digital de bitcoin. E todas as soluções técnicas do Bitcoin e outras blockchains se resumem a resolver esse problema.

Problemas de Blockchain


Suponha que uma determinada organização financeira diga que construiu uma rede em todo o mundo com a qual você pode transferir dinheiro para qualquer pessoa. Você acreditaria nela? Se essa organização é Visa ou MasterCard, provavelmente, acredite, mas se, relativamente falando, AnonymousWorldMoney, provavelmente não. Porque assim? Mas porque sabemos muito bem como os sistemas distribuídos são feitos por empresas privadas, para quais propósitos e a que isso pode levar. Vamos considerar com mais detalhes os problemas desses sistemas e como eles podem ser resolvidos usando as tecnologias blockchain.

Suponha que, no AnonymousWorldMoney condicional, haja servidores com bancos de dados, e é bom que haja vários deles em diferentes datacenters. Quando o remetente transfere o dinheiro, é registrada uma transação que é replicada para todos os servidores e o dinheiro chega ao destinatário.

imagem

Em um mundo ideal, esse esquema funciona muito bem, mas em nosso próprio país, surgem os seguintes problemas:

  1. O problema de identificar participantes, por um lado, e a necessidade de anonimato das transações, por outro. I.e. é necessário transferir dinheiro para um destinatário específico e para que ninguém saiba sobre essa transação, exceto os participantes na transação. Os bancos têm números de conta e cartões bancários vinculados a uma pessoa física ou jurídica específica e o sigilo bancário protege as informações da transação. E quem garante que o AnonymousWorldMoney condicional não use dados pessoais e informações de transações para seus próprios fins?
  2. Como garantir que o destinatário recebeu exatamente o valor transferido para ele? Relativamente falando, o remetente transferiu US $ 100 e o destinatário recebeu US $ 10. O remetente chega ao escritório da AnonymousWorldMoney com seu recibo e o funcionário mostra sua versão, que diz que o remetente transferiu apenas US $ 10.
  3. Um problema de ambiente não confiável, como fraude, chamado gasto duplo. Um participante inescrupuloso pode gastar seu saldo várias vezes até que o pagamento seja replicado para todos os servidores. Obviamente , ninguém cancelou o teorema da PAC , e a coerência será finalmente alcançada, mas alguém não receberá dinheiro pelos serviços ou bens prestados. Portanto, se não houver confiança completa na organização de pagamento ou nos participantes das transações, será necessário construir uma rede baseada não na confiança, mas na criptografia.
  4. O AnonymousWorldMoney condicional possui um número finito de servidores que podem ficar indisponíveis involuntariamente ou por intenção maliciosa.
  5. AnonymousWorldMoney terá sua comissão tangível.
  6. A capacidade de controlar. No processo de exploração do Bitcoin, descobriu-se que as pessoas querem não apenas transferir moedas umas para as outras, mas também verificar várias condições de transação, programar cenários de trabalho, executar ações automaticamente, dependendo das condições, etc.

Como o blockchain resolve esses problemas


  1. Os participantes são identificados usando um par de chaves: privado e público, e o algoritmo de assinatura digital identifica exclusivamente o remetente e o destinatário, deixando suas identidades anônimas.
  2. As transações são coletadas em blocos, o hash do bloco é calculado e registrado no próximo bloco. Essa sequência de escrita de hashes em blocos deu o nome de tecnologia blockchain e também torna impossível alterar / excluir discretamente blocos ou transações individuais de blocos. Assim, se uma transação cair no blockchain, você pode ter certeza de que seus dados permanecerão inalterados.
  3. A fraude de gastos duplos é evitada através do consenso na rede sobre quais dados devem ser considerados corretos e quais devem ser descartados. Na rede Bitcoin, o consenso é alcançado através da prova de PoW (Prova de Trabalho).
  4. A confiabilidade do funcionamento da rede é alcançada pelo fato de o blockchain ser público, onde cada participante pode lançar seu próprio nó, obter uma cópia completa do blockchain e, além disso, começar a verificar independentemente se as transações estão corretas. Deve-se observar que as blockchains modernas permitem criar não apenas blockchains públicas (abertas), mas também privadas (fechadas), além de usar esquemas combinados.
  5. Eu não vou me livrar completamente da comissão na blockchain, porque você precisa pagar às pessoas que suportam a rede, mas no blockchain a necessidade da comissão é tão convincente que não há dúvida sobre sua necessidade.
  6. As blockchains modernas têm a capacidade de implementar a lógica de negócios, chamada Smart Contracts na blockchain. A lógica dos contratos inteligentes é implementada em várias linguagens de alto nível.

A seguir, consideramos essas soluções em mais detalhes.

Arquitetura Blockchain


Componentes Blockchain


Cada participante pode executar seu nó com uma cópia completa do blockchain (nó completo). Nós completos que podem registrar transações na blockchain são chamados nós de consenso (testemunha) ou mineradores. Nós completos que apenas verificam a correção das transações são chamados nós de auditoria . Os clientes Light não armazenam cópias completas do blockchain, mas interagem com a rede usando nós completos.
A maioria dos usuários usa clientes leves ou carteiras da Web para concluir transações. Todos os nós estão conectados um ao outro. Com esse conjunto de elementos, a arquitetura de rede se torna mais estável:

imagem

Ciclo de vida da transação


Vamos dar uma olhada no ciclo de vida da transação e analisá-lo em partes:

imagem

Tecnologia Blockchain


Vamos nos debruçar com mais detalhes sobre soluções técnicas e seus relacionamentos entre si.

Identificação


Cada transação de blockchain deve ser assinada digitalmente. Portanto, para concluir a transação, cada participante deve ter um par de chaves: privado / público. Às vezes, um par de chaves é chamado de carteira, porque As chaves são associadas exclusivamente ao endereço digital exclusivo e ao saldo do participante. Na realidade, chaves e endereços são apenas cadeias de números em diferentes sistemas numéricos. Exemplos de chaves e endereços de carteira:

Private key: 0a78194a8a893b8baac7c09b6a4a4b4b161b2f80a126cbb79bde231a4567420f Public key: 0579b478952214d7cddac32ac9dc522c821a4489bc10aac3a81b9d1cd7a92e57ba Address: 0x3814JnJpGnt5tB2GD1qfKP709W3KbRdfb27V 

Para criar uma assinatura digital em cadeias de bloco, é utilizado um algoritmo baseado em curvas elípticas: Algoritmo de assinatura digital de curva elíptica (ECDSA). Para sua operação, a chave privada (número de 256 bits) geralmente é obtida aleatoriamente. O número de opções de chave é 2, com a potência de 256, para que possamos falar sobre a impossibilidade prática de combinar valores de chave privada.

Além disso, a chave pública é obtida a partir da chave privada, multiplicando seu valor pelas coordenadas do ponto localizado na curva elíptica, como resultado das quais as coordenadas do novo ponto da mesma curva são obtidas. Esta ação garante que você receba um par de chaves adequado para assinar transações digitalmente. Por fim, o endereço da carteira é calculado exclusivamente a partir da chave pública.

Existem muitos artigos com detalhes sobre a criptografia usada na blockchain, por exemplo: Bitcoin em poucas palavras - Criptografia

A chave privada deve ser mantida em segredo e segura. A chave pública é conhecida por todos. Se a chave privada for perdida, o acesso ao ativo (moedas) não poderá ser restaurado e o dinheiro será perdido para sempre. Portanto, a tarefa de armazenamento confiável de chaves privadas é extremamente relevante, porque este não é um banco em que você sempre pode vir com um passaporte e restaurar sua conta. Existe uma indústria inteira para a produção das chamadas carteiras criptográficas frias, semelhantes às unidades flash:

imagem

ou você pode usar métodos mais confiáveis, como um exemplo, para eliminar o valor da chave privada nos tokens:

imagem

Transações


Para obter mais informações sobre a estrutura da transação, consulte o artigo Bitcoin em poucas palavras - transação . É importante entendermos que cada transação tem pelo menos os seguintes dados:

 From: 0x48C89c341C5960Ca2Bf3732D6D8a0F4f89Cc4368 -    To: 0x367adb7894334678b90fe7882a5b06f7fbc783a -    Value: 0.0001 -   Transaction Hash: 0x617ede331e8a99f46a363b32b239542bb4006e4fa9a2727a6636ffe3eb095cef -   

Em seguida, a transação é assinada com uma chave privada e enviada (veja detalhes sobre a operação do Bitcoin em um protocolo resumido ) a todos os nós no blockchain que verificam a validade das transações. O algoritmo de verificação de transação não é trivial e inclui duas dúzias de etapas .

Blocos de transação


Após verificar a validade das transações, os nós formam blocos a partir deles. Além das transações, o hash do bloco anterior, um número (contador Nonce) é gravado no bloco e o hash do bloco atual é calculado usando o algoritmo SHA-256. Um hash deve ter estabelecido condições de complexidade. Por exemplo, em uma rede Bitcoin, a complexidade do hash muda automaticamente a cada 2 semanas, dependendo da capacidade da rede, para que o bloco seja gerado aproximadamente a cada 10 minutos. A complexidade é determinada pela seguinte condição: o hash encontrado deve ser menor que um número predeterminado. Se essa condição não for atendida, 1 será adicionado ao Nonce e o cálculo do hash será repetido. Para selecionar o hash, o campo Nonce é usado, porque esses são os únicos dados no bloco que podem ser alterados; o restante deve permanecer inalterado. O hash correto deve ter um certo número de zeros no início, por exemplo, um dos hashes reais:

 000000000000000000000bf03212e7dd1176f52f816fa395fc9b93c44bc11f91 

A descoberta bem-sucedida de um hash é uma prova do trabalho realizado (Proof-of-Work, PoW) para redes Bitcoin ou Ethereum. O processo de encontrar hashes é chamado de mineração, por analogia com a mineração de ouro. O nome determina com precisão a essência do processo, porque existe uma simples enumeração de opções e, se alguém encontrou um hash adequado, isso é realmente uma boa sorte. Isto é como encontrar uma pepita de ouro real em toneladas de ganga. A recompensa para o bloco agora é 12,5 BTC e se você multiplicar US $ 3900 pela taxa de câmbio atual do bitcoin, receberá mais de um quilograma de ouro puro. Há algo para lutar!

Após encontrar com êxito o hash, o bloco e o próprio hash encontrado são gravados no blockchain no próximo bloco. Para obter mais informações sobre a estrutura dos blocos, consulte o artigo Bitcoin em poucas palavras - Blockchain , e abaixo darei um diagrama simplificado:

imagem

O blockchain começa com um bloco que ainda não possui um hash do bloco anterior. Existe apenas um desses blocos na blockchain e tem seu próprio nome, bloco Genesis. Os blocos restantes têm a mesma estrutura e diferem apenas no número de transações. Transações reais e blocos atualmente criados no Bitcoin ou Ethereum podem ser visualizados no Block Explorer .

O tamanho dos blocos no Bitcoin é limitado a 1 MB e com uma quantidade mínima de informações em uma transação de cerca de 200 bytes, o máximo em um bloco pode ser de cerca de 6.000 transações. A partir daqui, a propósito, é o desempenho do Bitcoin, do qual todos riem: um bloco é gerado aproximadamente a cada 10 minutos * 60 segundos = 600 segundos, o que fornece um desempenho formal de cerca de 10 TPS. Embora na realidade - isso não é desempenho, mas um algoritmo de trabalho conscientemente implementado. A Ethereum acabou de fazer o tempo de geração de blocos de 15 segundos para a competição. e a produtividade decolou formalmente. Portanto, em blockchains usando PoW como um consenso, geralmente não faz sentido comparar o desempenho, porque depende diretamente da complexidade do cálculo do cache, que pode ser atribuído a qualquer um.

Forquilhas


E o que acontece se, por exemplo, vários nós encontrarem hashes que atendam às condições de complexidade, mas tenham significados diferentes (em outras palavras, chegarem a um consenso diferente) e gravarem blocos no blockchain? Vamos ver como a blockchain se protege dessa situação. Nesse caso, o chamado fork ('fork') ocorre e a blockchain tem duas versões da cadeia:

imagem

O que acontece depois? Além disso, parte da rede começa a trabalhar no bloco N + 2 de uma cadeia e parte de outra:

imagem

Alguns desses blocos serão encontrados anteriormente e enviados para o blockchain e, de acordo com as regras, o blockchain terá que mudar para uma cadeia mais longa e cancelar todas as transações do bloco alternativo:

imagem

Ao mesmo tempo, uma situação pode surgir quando a transação do participante estava em apenas um dos blocos da bifurcação, que foi cancelada. Portanto, para garantir que a transação desejada seja registrada na blockchain, há uma recomendação geral - antes de confiar na transação, você deve esperar até que os próximos blocos sejam adicionados à blockchain. As recomendações sobre quantos blocos aguardar por diferentes cadeias de blocos variam. Por exemplo, para uma rede Bitcoin, o mínimo é 2 blocos, o máximo é 6.

A mesma imagem com um garfo de blocos também será observada com o chamado ataque de 51% - é quando um grupo de mineradores tentará desenvolver uma cadeia de blocos alternativa, buscando cancelar a cadeia com suas transações fraudulentas. Embora atualmente, em vez de fraude, seja mais lucrativo gastar seu poder em mineração honesta.

Consenso


Para escrever um bloco na blockchain, a rede deve chegar a um consenso. Lembremos a tarefa de obter consenso nas redes de comunicação por computador. O problema é formulado como a tarefa dos BFT dos generais bizantinos ( tolerância a falhas bizantinas ). Omitindo uma descrição pictórica dos problemas do exército bizantino, o problema pode ser formulado da seguinte maneira: como os nós da rede podem obter um resultado comum se alguns nós da rede os distorcem conscientemente. Os algoritmos existentes para resolver o problema da BFT mostram que a rede pode funcionar corretamente se os fraudadores forem menores que 1/3. Por que o consenso de BFT não foi aplicado na rede Bitcoin? Por que usar o PoW? Existem várias razões:

  • A BFT funciona bem com um pequeno conjunto fixo de nós e, no blockchain público, o número de nós é imprevisível e, além disso, os nós podem ser ativados e desativados arbitrariamente.
  • É necessário motivar as pessoas a lançar nós blockchain. Para fazer isso, as pessoas devem receber recompensas. Na BFT, não há formalmente nada para receber uma recompensa, mas o que é uma recompensa no PoW é compreensível para todos em um nível intuitivo: para a eletricidade consumida pelo processador no processo de encontrar o hash do bloco.

Além do PoW, há vários outros consensos usados ​​em blockchains modernas, por exemplo:

  • PoS (Prova de Participação) - na blockchain Hyperledger
  • DPoS (Prova de Participação Delegada) - na blockchain BitShares
  • Modificações da BFT: SBFT (BFT simplificada) e PBFT (BFT prática), por exemplo, na blockchain Exonum

Vamos nos concentrar no consenso de PoS, porque é o PoS e suas variantes que são mais amplamente utilizados em blockchains particulares. Por que em particular? Por um lado, as características do PoS são melhores que o PoW, porque Para obter consenso, são necessários menos recursos de computação, o que significa que a velocidade de gravação de dados no blockchain aumenta. Mas, por outro lado, o PoS tem mais oportunidades de fraude, portanto, para neutralizar isso, todos os participantes da blockchain devem ser conhecidos.

O consenso de PoS é baseado na escolha de um nó que pode escrever um bloco com transações na blockchain, dependendo da quantidade de fundos na conta, ou melhor, não na conta, mas na promessa, ou seja, quanto mais dinheiro você tiver na promessa, maior a probabilidade da rede escolher o seu nó para registrar o bloco. O depósito não será devolvido se a unidade for inválida. Assim, a proteção contra fraude é implementada. As seguintes variações de PoS estão disponíveis:

  • O PoS delegado por consenso (DPoS) divide os participantes em "votação" e "validação". Os titulares de moedas (participantes da votação) delegam seu direito de verificar e registrar transações na blockchain para outros participantes. Assim, os validadores realizam todo o trabalho de computação e são recompensados ​​por isso, e a presença dos participantes da votação garante a honestidade dos validadores, porque eles podem ser alterados a qualquer momento.
  • O consenso LPoS (Leasing Proof of Stake) permite que você alugue seus fundos para outros nós, para que eles tenham uma melhor chance de verificar os blocos. T.O. você pode obter uma comissão pelas transações, sem participar da verificação da transação e bloquear a mineração.

Ainda há vários consensos que ainda não se espalharam, simplesmente os listarei aqui para obter informações e uma visão geral dos algoritmos de consenso em si pode ser encontrada, por exemplo, no artigo: Algoritmos de consenso no Blockchain

  • PoET (tempo de prova do tempo decorrido)
  • PoC (Prova de capacidade)
  • PoB (Prova de Queimadura)
  • PoWeight (prova de peso)
  • PoA (Prova de Atividade) - PoW + PoS
  • PoI (Prova de Importação)

Modelos de confiabilidade e implantação de blockchain


Blockchain público

A estabilidade de Public ou outro nome para blockchain sem permissão é alcançada pelo fato de que todos podem conectar e visualizar informações ou até mesmo conectar seu próprio nó, e a confiança é construída com base no consenso de PoW.

Blockchain privado

Blockchain privado ou privado com permissão . Nessas cadeias de bloqueio, apenas um determinado grupo de participantes (organizações ou pessoas) tem acesso à informação. Essas cadeias de blocos são construídas por organizações para aumentar o lucro ou a eficiência geral. Sua confiabilidade é garantida pelos objetivos comuns dos participantes e pelos algoritmos de consenso de PoS e BFT.

Consórcio Blockchain

consórcio ou blockchain com permissão pública . Essas são cadeias de bloco que todos podem conectar para visualizar, mas um participante pode adicionar informações ou conectar seu site apenas com a permissão de outros participantes. Essas cadeias de blocos são construídas por organizações para aumentar a confiança por parte dos clientes ou consumidores de produtos ou da sociedade como um todo. Aqui, a confiabilidade também é alcançada pela presença de confiança entre os participantes e os mesmos algoritmos de consenso de PoS e BFT.

Contratos inteligentes


As blockchains implementadas após o Bitcoin adicionaram, em um grau ou outro, a capacidade de executar contratos inteligentes. Em essência, um contrato inteligente é uma transação na qual o código do programa é colocado para execução. Os contratos inteligentes na rede Ethereum são executados no EVM (Ethereum Virtual Machine). Para iniciar a execução de um contrato inteligente, ele deve ser explicitamente lançado por outra transação, ou as pré-condições para execução devem ser atendidas. Os resultados da implementação do contrato inteligente também são registrados na blockchain. Obter dados de fora da blockchain é possível, mas extremamente limitado.

Que lógica de negócios pode ser implementada usando um contrato inteligente? De fato, não há muitos, por exemplo, verificando condições de acordo com os dados da blockchain, alterando os proprietários de ativos digitais dependendo dessas condições, gravando dados no armazenamento permanente dentro da blockchain. A lógica é implementada em uma linguagem especial de alto nível, Solidity.

Um exemplo clássico de funcionalidade implementada usando contratos inteligentes é a questão de tokens para ICOs. Por exemplo, implementei um contrato inteligente para o lançamento de um modesto 500 milhões de AlexToken. O link no Etherscan é

Código fonte do contrato inteligente do Solidity
 pragma solidity ^0.4.23; library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. **/ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { if (a == 0) { return 0; } c = a * b; assert(c / a == b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. **/ function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ // uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return a / b; } /** * @dev Subtracts two numbers, throws on overflow (ie if subtrahend is greater than minuend). **/ function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } /** * @dev Adds two numbers, throws on overflow. **/ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } } /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". **/ contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender account. **/ constructor() public { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. **/ modifier onlyOwner() { require(msg.sender == owner); _; } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. **/ function transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0)); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } } /** * @title ERC20Basic interface * @dev Basic ERC20 interface **/ contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 **/ contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Approval(address indexed owner, address indexed spender, uint256 value); } /** * @title Basic token * @dev Basic version of StandardToken, with no allowances. **/ contract BasicToken is ERC20Basic { using SafeMath for uint256; mapping(address => uint256) balances; uint256 totalSupply_; /** * @dev total number of tokens in existence **/ function totalSupply() public view returns (uint256) { return totalSupply_; } /** * @dev transfer token for a specified address * @param _to The address to transfer to. * @param _value The amount to be transferred. **/ function transfer(address _to, uint256 _value) public returns (bool) { require(_to != address(0)); require(_value <= balances[msg.sender]); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); return true; } /** * @dev Gets the balance of the specified address. * @param _owner The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. **/ function balanceOf(address _owner) public view returns (uint256) { return balances[_owner]; } } contract StandardToken is ERC20, BasicToken { mapping (address => mapping (address => uint256)) internal allowed; /** * @dev Transfer tokens from one address to another * @param _from address The address which you want to send tokens from * @param _to address The address which you want to transfer to * @param _value uint256 the amount of tokens to be transferred **/ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { require(_to != address(0)); require(_value <= balances[_from]); require(_value <= allowed[_from][msg.sender]); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param _spender The address which will spend the funds. * @param _value The amount of tokens to be spent. **/ function approve(address _spender, uint256 _value) public returns (bool) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param _owner address The address which owns the funds. * @param _spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. **/ function allowance(address _owner, address _spender) public view returns (uint256) { return allowed[_owner][_spender]; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * * approve should be called when allowed[_spender] == 0. To increment * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. **/ function increaseApproval(address _spender, uint _addedValue) public returns (bool) { allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * * approve should be called when allowed[_spender] == 0. To decrement * allowed value is better to use this function to avoid 2 calls (and wait until * the first transaction is mined) * From MonolithDAO Token.sol * @param _spender The address which will spend the funds. * @param _subtractedValue The amount of tokens to decrease the allowance by. **/ function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } } /** * @title Configurable * @dev Configurable varriables of the contract **/ contract Configurable { uint256 public constant cap = 1000000000*10**18; uint256 public constant basePrice = 100*10**18; // tokens per 1 ether uint256 public tokensSold = 0; uint256 public constant tokenReserve = 500000000*10**18; uint256 public remainingTokens = 0; } /** * @title CrowdsaleToken * @dev Contract to preform crowd sale with token **/ contract CrowdsaleToken is StandardToken, Configurable, Ownable { /** * @dev enum of current crowd sale state **/ enum Stages { none, icoStart, icoEnd } Stages currentStage; /** * @dev constructor of CrowdsaleToken **/ constructor() public { currentStage = Stages.none; balances[owner] = balances[owner].add(tokenReserve); totalSupply_ = totalSupply_.add(tokenReserve); remainingTokens = cap; emit Transfer(address(this), owner, tokenReserve); } /** * @dev fallback function to send ether to for Crowd sale **/ function () public payable { require(currentStage == Stages.icoStart); require(msg.value > 0); require(remainingTokens > 0); uint256 weiAmount = msg.value; // Calculate tokens to sell uint256 tokens = weiAmount.mul(basePrice).div(1 ether); uint256 returnWei = 0; if(tokensSold.add(tokens) > cap){ uint256 newTokens = cap.sub(tokensSold); uint256 newWei = newTokens.div(basePrice).mul(1 ether); returnWei = weiAmount.sub(newWei); weiAmount = newWei; tokens = newTokens; } tokensSold = tokensSold.add(tokens); // Increment raised amount remainingTokens = cap.sub(tokensSold); if(returnWei > 0){ msg.sender.transfer(returnWei); emit Transfer(address(this), msg.sender, returnWei); } balances[msg.sender] = balances[msg.sender].add(tokens); emit Transfer(address(this), msg.sender, tokens); totalSupply_ = totalSupply_.add(tokens); owner.transfer(weiAmount);// Send money to owner } /** * @dev startIco starts the public ICO **/ function startIco() public onlyOwner { require(currentStage != Stages.icoEnd); currentStage = Stages.icoStart; } /** * @dev endIco closes down the ICO **/ function endIco() internal { currentStage = Stages.icoEnd; // Transfer any remaining tokens if(remainingTokens > 0) balances[owner] = balances[owner].add(remainingTokens); // transfer any remaining ETH balance in the contract to the owner owner.transfer(address(this).balance); } /** * @dev finalizeIco closes down the ICO and sets needed varriables **/ function finalizeIco() public onlyOwner { require(currentStage != Stages.icoEnd); endIco(); } } /** * @title LavevelToken * @dev Contract to create the Lavevel Token **/ contract AlexToken is CrowdsaleToken { string public constant name = "AlexToken"; string public constant symbol = "ALT"; uint32 public constant decimals = 18; } 

e representação binária de como a rede a vê
60806040526000600355600060045533600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600560146101000a81548160ff021916908360028111156200006f57fe5b0217905550620001036b019d971e4fe8401e74000000600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200024a6401000000000262000b1d179091906401000000009004565b600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550620001986b019d971e4fe8401e740000006001546200024a6401000000000262000b1d179091906401000000009004565b6001819055506b033b2e3c9fd0803ce8000000600481905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6b019d971e4fe8401e740000006040518082815260200191505060405180910390a362000267565b600081830190508281101515156200025e57fe5b80905092915050565b611cb880620002776000396000f300608060405260043610610112576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146104c7578063095ea7b31461055757806318160ddd146105bc57806323b872dd146105e7578063313ce5671461066c578063355274ea146106a3578063518ab2a8146106ce57806366188463146106f957806370a082311461075e57806389311e6f146107b55780638da5cb5b146107cc578063903a3ef61461082357806395d89b411461083a578063a9059cbb146108ca578063bf5839031461092f578063c7876ea41461095a578063cbcb317114610985578063d73dd623146109b0578063dd62ed3e14610a15578063f2fde38b14610a8c575b60008060008060006001600281111561012757fe5b600560149054906101000a900460ff16600281111561014257fe5b14151561014e57600080fd5b60003411151561015d57600080fd5b600060045411151561016e57600080fd5b3494506101a7670de0b6b3a764000061019968056bc75e2d6310000088610acf90919063ffffffff16565b610b0790919063ffffffff16565b9350600092506b033b2e3c9fd0803ce80000006101cf85600354610b1d90919063ffffffff16565b111561024c576101f66003546b033b2e3c9fd0803ce8000000610b3990919063ffffffff16565b915061022e670de0b6b3a764000061022068056bc75e2d6310000085610b0790919063ffffffff16565b610acf90919063ffffffff16565b90506102438186610b3990919063ffffffff16565b92508094508193505b61026184600354610b1d90919063ffffffff16565b6003819055506102886003546b033b2e3c9fd0803ce8000000610b3990919063ffffffff16565b6004819055506000831115610344573373ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050501580156102dd573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a35b610395846000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b1d90919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040518082815260200191505060405180910390a361045184600154610b1d90919063ffffffff16565b600181905550600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc869081150290604051600060405180830381858888f193505050501580156104bf573d6000803e3d6000fd5b505050505050005b3480156104d357600080fd5b506104dc610b52565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561051c578082015181840152602081019050610501565b50505050905090810190601f1680156105495780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561056357600080fd5b506105a2600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b8b565b604051808215151515815260200191505060405180910390f35b3480156105c857600080fd5b506105d1610c7d565b6040518082815260200191505060405180910390f35b3480156105f357600080fd5b50610652600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c87565b604051808215151515815260200191505060405180910390f35b34801561067857600080fd5b50610681611041565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b3480156106af57600080fd5b506106b8611046565b6040518082815260200191505060405180910390f35b3480156106da57600080fd5b506106e3611056565b6040518082815260200191505060405180910390f35b34801561070557600080fd5b50610744600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061105c565b604051808215151515815260200191505060405180910390f35b34801561076a57600080fd5b5061079f600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506112ed565b6040518082815260200191505060405180910390f35b3480156107c157600080fd5b506107ca611335565b005b3480156107d857600080fd5b506107e16113eb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561082f57600080fd5b50610838611411565b005b34801561084657600080fd5b5061084f6114ab565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561088f578082015181840152602081019050610874565b50505050905090810190601f1680156108bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108d657600080fd5b50610915600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506114e4565b604051808215151515815260200191505060405180910390f35b34801561093b57600080fd5b50610944611703565b6040518082815260200191505060405180910390f35b34801561096657600080fd5b5061096f611709565b6040518082815260200191505060405180910390f35b34801561099157600080fd5b5061099a611716565b6040518082815260200191505060405180910390f35b3480156109bc57600080fd5b506109fb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611726565b604051808215151515815260200191505060405180910390f35b348015610a2157600080fd5b50610a76600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611922565b6040518082815260200191505060405180910390f35b348015610a9857600080fd5b50610acd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506119a9565b005b600080831415610ae25760009050610b01565b8183029050818382811515610af357fe5b04141515610afd57fe5b8090505b92915050565b60008183811515610b1457fe5b04905092915050565b60008183019050828110151515610b3057fe5b80905092915050565b6000828211151515610b4757fe5b818303905092915050565b6040805190810160405280600981526020017f416c6578546f6b656e000000000000000000000000000000000000000000000081525081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b6000600154905090565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610cc457600080fd5b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610d1157600080fd5b600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548211151515610d9c57600080fd5b610ded826000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b3990919063ffffffff16565b6000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610e80826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b1d90919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610f5182600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b3990919063ffffffff16565b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b601281565b6b033b2e3c9fd0803ce800000081565b60035481565b600080600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490508083111561116d576000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611201565b6111808382610b3990919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b8373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a3600191505092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561139157600080fd5b60028081111561139d57fe5b600560149054906101000a900460ff1660028111156113b857fe5b141515156113c557600080fd5b6001600560146101000a81548160ff021916908360028111156113e457fe5b0217905550565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561146d57600080fd5b60028081111561147957fe5b600560149054906101000a900460ff16600281111561149457fe5b141515156114a157600080fd5b6114a9611b01565b565b6040805190810160405280600381526020017f414c54000000000000000000000000000000000000000000000000000000000081525081565b60008073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415151561152157600080fd5b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054821115151561156e57600080fd5b6115bf826000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b3990919063ffffffff16565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611652826000808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b1d90919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b60045481565b68056bc75e2d6310000081565b6b019d971e4fe8401e7400000081565b60006117b782600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b1d90919063ffffffff16565b600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515611a0557600080fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611a4157600080fd5b8073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6002600560146101000a81548160ff02191690836002811115611b2057fe5b021790555060006004541115611c0a57611ba5600454600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610b1d90919063ffffffff16565b600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f19350505050158015611c89573d6000803e3d6000fd5b505600a165627a7a723058205bbef016cc7699572f944871cb6f05e69915ada3a92a1d9f03a3fb434aac0c2b0029


Mais detalhes sobre contratos inteligentes podem ser encontrados no artigo: O que são contratos inteligentes no Ethereum .

Conclusão


Listamos as tecnologias nas quais as cadeias de blocos modernas são construídas e como elas se relacionam. Agora vamos formular quais tarefas podem ser resolvidas usando o blockchain e quais soluções serão, na melhor das hipóteses, ineficientes. Portanto, não é necessário usar uma blockchain se:

  • As transações são realizadas em um ambiente confiável;
  • A presença de uma comissão de intermediários não piora a vida dos participantes;
  • Os participantes não possuem propriedades que possam ser representadas como ativos digitais;
  • Não há distribuição nos ativos digitais, ou seja, apenas um membro possui ou entrega o valor.

Qual é o futuro da blockchain? Agora só podemos especular sobre possíveis maneiras de desenvolver tecnologias blockchain:

  • O Blockchain se tornará a mesma tecnologia convencional de banco de dados que, por exemplo, SQL ou NoSQL para resolver seu intervalo específico de tarefas;
  • Blockchain se tornará um protocolo generalizado como HTTP para a Internet;
  • O Blockchain se tornará a base para o novo sistema financeiro e político do planeta!

Na próxima parte, veremos quais blockchains existem atualmente e por que eles são usados ​​em vários setores.

É só o começo!

Todos os três artigos:


O que devemos construir uma blockchain?
Blockchain: o que devemos construir um caso?
Blockchain: o que devemos construir PoC?

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


All Articles