Como escrevi uma criptomoeda centralizada em PHP. (Parte 1 - Resumos básicos + Início rápido)

Prefácio


Sim, você apenas pensa sobre isso, uma criptomoeda centralizada em PHP, isso não está certo. Porém, minhas limitações quanto às idéias fizeram o seu caminho; portanto, como você deve ter adivinhado, decidi escrever sobre isso. Na primeira parte, mostraremos o que é criptomoeda, discutiremos as notas iniciais e criaremos um sistema de carteira. Agora, vamos começar.

Criptomoeda, como é?


informações retiradas da Wikipedia

A criptomoeda é um tipo de moeda digital, cuja contabilidade das unidades de liquidação interna é garantida por um sistema de pagamentos descentralizado (não há administrador interno ou externo ou qualquer análogo), funcionando de modo totalmente automático.

A criptomoeda em si não possui nenhum material especial ou formato eletrônico - é apenas um número que indica a quantidade de dados das unidades de liquidação, que é gravada na posição correspondente do pacote de informações do protocolo de transferência de dados e muitas vezes nem é criptografada, como todas as outras informações sobre transações entre endereços do sistema.

Em resumo, a criptomoeda funciona assim:

  1. Um usuário da rede, com saldo, envia uma transação para outro usuário anônimo.
  2. A transação entra na rede.
  3. Mineiros (ou usuários que criam blocos) resolvem um problema gerado por um algoritmo especial com condições (por exemplo, para a presença dos 10 a 30 zeros anteriores no hash ou vice-versa).
  4. Quando uma condição (ou condições) é atendida em um hash, graças a ela, o minerador envia uma mensagem à rede informando sobre a criação de um novo bloco e a transação.
  5. O destinatário recebe os fundos e o mineiro recebe o valor da remuneração, na forma de uma comissão calculada durante a preparação da tarefa.

Faz sentido escrever uma criptomoeda centralizada e também em PHP?


Eu acho que não muito. Mas tente novamente como deveria.

Consideramos notas antes do desenvolvimento


Usaremos um sistema de verificação dupla de hash usando Prova de trabalho. Faz sentido verificar os hashes no nível do software e do aplicativo de rede. Isso ocorre devido ao processo de otimização da carga no servidor. Porque quando formos ao servidor verificar o hash várias vezes, essa carga aparecerá. Portanto, proponho fazer o seguinte método:

  1. Em um minerador de software, verifique localmente o hash para satisfazer as condições.
  2. Quando as condições no minerador de software coincidem com as condições necessárias, fazemos uma verificação no nível da rede do aplicativo (no nível do servidor).

Essa, na minha opinião, é a melhor maneira de distribuir a carga. É mais fácil verificar várias vezes localmente no computador do que solicitações de spam para o servidor várias vezes.

O nome - criei um nome simples e talvez memorável - FlyCoin com um código de moeda FLC de três dígitos.

Banco de Dados - Usarei uma opção simples e conveniente, DOP.

Carteiras criptográficas - serão geradas usando o GUID e o mt_rand, e o tempo POSIX será usado como semente.

Você está com preguiça de ter uma função de verificação de hash? - Sim, então eu decidi pegar o código de um antigo minerador (de código aberto) dessa criptomoeda (já falecida) Entropy, minha amiga Nikita.

Não acredito que ele criou apenas uma criptomoeda. Existe algo mais?
Em geral, todas as suas criações (que às vezes eu até uso), você pode encontrar em seu grupo VKontakte . Espero que eles também sejam úteis.

Vamos lá!


Vamos começar criando a estrutura do nosso futuro sistema. Vamos começar com o desenvolvimento da API do aplicativo para nossa criptomoeda. E o quadro parece tão vazio até agora.

<?php /* * The API for FlyCoin */ function checkHash ($hash, $exp) //  $hash -     ,  $exp - .    Entropy Miner,   . { $sum = 0; //    . $len = strlen ($hash); // C  . for ($i = 0; $i < $len; ++$i) $sum += 2 * base_convert ($hash[$i], 16, 10); //        return $sum % 10 == 0 && substr ($hash, -$exp) === str_repeat ('0', $exp); //  false       true,         . } class Block { public $id; // ID  public $prev_hash; //    public $from; //   public $to; //  public $ammount; //  public $difficult; //   } class API { protected $db; public function __construct () { $dsn = "mysql:host=localhost;dbname=flc"; // DSN   $this->db = new PDO ($dsn, $username, $password); //     try { return true; //  . } catch (PDOException $exception) { return false; //  . } } } 

Aqui está, a moldura do nosso milagre. Primeiro, implementamos o registro e a geração de GUIDs para nossas carteiras. Criei imediatamente uma definição de função de API vazia e também encontrei uma função de geração de GUID no Google. Não se esqueça das sementes. Acabei de encontrar uma função para obter sementes, para obter um GUID exclusivo.

  function make_seed () //      PHP { list ($usec, $sec) = explode (' ', microtime ()); return $sec + $usec * 1000000; } mt_srand (make_seed ()); 

Ótimo. E a função para gerar o GUID para a carteira fica assim (assim como o próprio stub):

  public function register () //    { } protected function genGUID4 () //  Google { return sprintf ('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand (0, 0xffff), mt_rand (0, 0xffff), mt_rand (0, 0xffff), mt_rand (0, 0x0fff) | 0x4000, mt_rand (0, 0x3fff) | 0x8000, mt_rand (0, 0xffff), mt_rand (0, 0xffff), mt_rand (0, 0xffff)); //     ,   . } 

Como fazemos tudo anonimamente, não armazenaremos IP ou email. Sem confirmação. Seremos o suficiente. Em ~ 25 minutos, escrevi uma função de registro. Somente uma senha é exigida de nós. A função API retornará a carteira para nós.

  public function register ($password) //  $password -    { if ($this->db) //    { $walletId = 'FLC@' . $this->genGUID4 (); //      $hash = crc32 ($walletId) . $walletId . hash_hmac ('sha512', str_rot13 ($password), 'FLC'); //     . $hash = hash_hmac ('sha512', $hash, 'FLC2'); //     . $newUser = $this->db->prepare (" INSERT INTO `wallets` (walletId, loginHash, balance) VALUES (:walletId, :hash, :startBalance) "); //    . $newUser->bindParam (':walletId', $walletId, PDO::PARAM_STR); //     $newUser->bindParam (':hash', $hash, PDO::PARAM_STR); //     $newUser->bindParam (':startBalance', 0, PDO::PARAM_INT); //    (   ,   0!)   $newUser->execute (); //  . return ['walletId' => $walletId]; //     ( ) } else return false; //      . } 

Aqui descrevi brevemente o que essa ou aquela linha faz.

Mensagem justa para pessoas e programadores justos.
Se você deixou seus contatos no site (no qual, talvez, essa criptomoeda estará localizada), e eles escrevem algo assim para você:

"Olá, você pode ajudar?" Eu mantive a mani no seu blockchain e, de repente, perdi minha senha, ajude e você será bom ”- fique à vontade para rejeitar esta oferta. A essência da criptomoeda é o armazenamento de números digitados em segurança. Ninguém pode provar que possui uma conta. Assim, qualquer atacante pode até roubar os fundos de outras pessoas, mesmo sem a participação da vítima! Não importa, embora essa pessoa seja realmente o proprietário da conta, é melhor recusar. Se você perdeu dinheiro, significa que não armazenou corretamente os dados da conta. Para aumentar a segurança, não implementaremos mais a recuperação de senha.

A função hash apresentada aqui pode ser representada da seguinte maneira:
hash(w,pw)=crc32(w).w.hmac(pw)

A função funciona assim:

Uma senha é inserida, verificamos se o banco de dados está conectado:

Sim, conectado. (Vamos criar uma senha 12345)
Geramos o endereço da carteira e escrevemos em $ walletId - obtemos algo parecido com isto: FLC @ c1cbe61d-a19d-4c82-ba17-3a577df0aeb5 (esse GUID foi gerado por outro site, depois adicionei o prefixo FLC @).

Calculamos o hash de texto sem formatação. Na primeira série, obtemos a seguinte: 0087196442FLC @ c1cbe61d-a19d-4c82 -ba17-3a577df0aeb59ee77779db5a44ef3f60044fcb0e1170218e642cb9adc0789ddd08871ad95c7e1d3b1391c6c79774d319b5141bd3b13b717c3d389206ede659cb280949feac66 ( muitas cartas, não ser surpreendido).
No segundo turno, o hash se tornará cem por cento HMAC: 5e43cbb404c81efeb35162e5bba0766f20b340fbabcc66fd5f7a6a1993a8ccd43fc6384ac53f939acca4378681e2bb17912eacf4c65aa novamente.

Escrevemos tudo no banco de dados.

Em resposta, escrevemos o número da carteira através do qual você pode fazer login.

Não, não está conectado.
Nesse caso, você não precisa esperar nada que valha a pena, retorne FALSE.

É assim que um sistema sofisticado de registro se parece. De fato, parece muito simples. E em termos de código - muito mais complicado.

Vamos gastar mais tempo e fazer a autorização. Com autorização, a situação é mais simples. Estamos procurando uma conta e tentando fazer login, conhecendo os algoritmos familiares de geração de hash de senha. Em seguida, verificamos e, se os dados estiverem corretos, fornecemos ao cliente uma linha importante na qual os dados são armazenados para comunicação entre o servidor e o minerador.

De mim mesmo.
Parece que não estamos fazendo criptomoeda, mas um sistema de autorização entre o PHP no servidor e o PHP usando php.exe. Na segunda parte, adicionaremos um segundo bolo ao nosso "bolo", no qual veremos algo relacionado à mineração, blockchain e transações.

Após mais 15 a 25 minutos, a função de autorização estava pronta. Veja este código abaixo:

  public function login ($walletId, $password) //  { if ($this->db) //    { $hash = crc32 ($walletId) . $walletId . hash_hmac ('sha512', str_rot13 ($password), 'FLC'); //     . $hash = hash_hmac ('sha512', $hash, 'FLC2'); //     . $newUser = $this->db->prepare (" SELECT * FROM `wallets` WHERE walletId = :walletId AND loginHash = :hash LIMIT 0, 1 "); //    . $newUser->bindParam (':walletId', $walletId, PDO::PARAM_STR); //     $newUser->bindParam (':hash', $hash, PDO::PARAM_STR); //     $newUser->execute (); //  . $object = $newUser->fetch_object (); //   ,     if ($object AND hash_equals ($object->hash, $hash)) //   ,   . { $loginString = new stdClass; //    stdClass $loginString->hash = $hash; //       . $loginString->wallet = $walletId; return ['token' => serialize ($loginString)]; //      ,   . } else return false; //   / . } else return false; //    } 

Este código é quase registro, mas opera no algoritmo reverso. O trabalho com usuários chegou ao fim.

Pós-condição


Durante esse tempo interessante, lendo o artigo, fizemos o seguinte:

  • Nós nos familiarizamos brevemente com a criptomoeda e como ela deve ser criada corretamente.
  • Eles responderam brevemente à pergunta "Faz sentido criar uma criptomoeda centralizada e também em PHP?"
  • Notas discutidas antes de executar esta tarefa
  • Implementou um sistema de contas criptográficas.

E agora, você pode ler o que estava por trás dos blinds:

Debaixo da cortina
Este artigo foi escrito cerca de 4-5 horas (durante o pôr do sol e a noite). Durante esse período, como escrevi, desenvolvi, mas quando se trata de escrever um artigo sobre Habrahabr, meu desejo de realizar meu sonho não desaparece. De fato, devido ao conceito simples de OOP, era mais fácil para mim usá-lo do que o MySQLi, ou pior, funções comuns com o prefixo mysql_, que são consideradas obsoletas e não são mais adequadas para o desenvolvimento em PHP.

O que faremos da próxima vez:

  • Vamos fazer a mineração.
  • Vamos considerar como as transações e os blocos são organizados.
  • Faremos transações e daremos sentido à classe Block não utilizada.

Obrigado pela leitura! Vejo você de novo! Este é o meu primeiro artigo - estou aguardando críticas.

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


All Articles