=> Cronograma de Desenvolvimento
O cronograma a seguir mostra como a dupla organizou seus encontros para o desenvolvimento do trabalho, bem como planejamento e tomada de decisões.
- 23/10: Tomada de decisões primárias, como linguagem, estrutura de dados, função hash, padrão de formatação de código e forma com que os programas devem ser executados;
- 30/10: Construção da biblioteca de blockchain;
- 03/11: Consrução do servidor
- 04/11: Construção do cliente
- 05/11: Fluxos de exceção, comentários e prints adicionais para geração de arquivos de log adicionados
- 11/11: Ajustes finais, geração de logs para todos os fluxos previstos pela dupla para o trabalho e desenvolvimento do site para entrega
=> Implementação
O projeto foi dividido em 4 arquivos python: blockchain, servidor, cliente e main. O arquivo blockchain.py contém todas as funções necessárias para o funcionamento do blockchain, como criação de novos blocos, consultas e hash. Os arquivos servidor.py e cliente.py, como dizem os nomes, são responsáveis pela comunicação entre servidor e cliente, usando funções do blockchain para realizar transações e manter a blockchain. Já o arquivo main.py serve apenas para chamar o servidor e o cliente, conforme o argumento dado por linha de comando.
blockchain.py
Este arquivo implementa toda a lógica por trás do blockchain: criação de bloco gênesis, cálculo de hash, função para retornar o último bloco, cálculo do saldo e criação de novo bloco. Cada bloco do blockchain possui Id (altura do bloco), timestamp da data e hora em que foi criado, nome do proprietário, transação feita, com tipo e valor, hash do bloco anterior e hash do bloco atual. A blockchain é mantida como uma array de blocos.
- Id – altura do bloco na cadeia;
- Timestamp – data e hora de criação;
- Proprietário – nome do dono da conta;
- Transação – tipo e valor da operação;
- Hash anterior e hash atual.
As principais funções implementadas são:
cria_bloco_genesis:cria e retorna o bloco gênesis, recebendo o nome do proprietário e o valor inicial.
calcular_hash:concatena os campos Id, timestamp, proprietário, transação e hash anterior, transformando-os em bytes e aplicando
sha256.get_ultimo_bloco:retorna o último bloco da blockchain.
get_saldo_atual:percorre a blockchain desde o bloco gênesis até o último bloco, calculando o saldo atual com base nas transações feitas. Para cada novo bloco, a função verifica se o hash está correto. Caso a verificação falhe em algum bloco, a função imprime uma mensagem de erro e retorna -1. Caso contrário, continua os cálculos e retorna o saldo atual no final.
nova_transacao:recebe a blockchain, o tipo de transação e o valor. Primeiramente, verifica se a transação é do tipo saque e se há saldo o suficiente para tal operação. Se não houver, a função imprime uma mensagem de erro e retorna. Caso contrário, cria um novo dicionário com as informações da transação, além de calcular a hash atual a partir dos novos dados. Por fim, retorna o novo bloco criado.
servidor.py
Este arquivo implementa uma única função, iniciar_servidor, que controla toda a parte de manter o blockchain e comunicar com o cliente. Neste arquivo, estão definidos valores como endereço e porta do host.
A função começa inicializando a blockchain como uma array vazia e, em seguida, configurando o socket de escuta. Assim que uma requisição chega, o servidor aceita a conexão e a comunicação começa.
O servidor recebe um pacote de bytes do cliente. Em seguida, ele decodifica e interpreta qual a ação sendo feita: criação de conta, transação, consulta ou saída. Em caso de criação de conta, ele chama a função cria_bloco_genesis,
envia uma resposta ao cliente e volta à esperar pelo próximo bloco de dados. Em caso de transação, verifica qual o tipo: Depósito ou Saque, tratando cada tipo de forma devida e enviando uma resposta ao cliente. Em casos de consulta,
basta chamar a função que calcula o saldo atual e enviar a resposta ao cliente. Por fim, em caso de saída, o servidor relaiza todas as finalizações necessárias (como fechar o socket) e encerra sua execução.
Existem diversos tratamentos de fluxos de exceção, como o caso em que o cliente termina a execução abruptamente (ctrl+c) ou conexão perdida por motivos externos ao programa.
cliente.py
Este arquivo implementa toda a lógica por trás do cliente. Ela inicia como o servidor, definindo endereço, porta e configurando o socket.
O fluxo principal inicia com o input do usuário, para que os dados do bloco gênesis possam ser enviados para o servidor. Após a criação ser realizada com sucesso, o cliente entra em um loop que apenas acaba quando o cliente encerrar sua execução, seja por interrupção de teclado ou pelo comando 4-Sair. Dentro deste loop, o cliente recebe do usuário o comando desejado, podendo este ser uma transação (saque e depósito) ou consulta ao saldo. Todos os comando de transação devem ser acompanhados pelo valor da transação.
Assim como o servidor, esta função também trata fluxos de exceção, como na situação em que o servidor encerra sua execução, em que o cliente é encerrado por interrupção de teclado ou em que o usuário digita valores não numéricos nas entradas de valores.
main.py
Como explicado anteriormente, este arquivo apenas chama a função desejada de acordo com o argumento passado por linha de comando. Assim, para executar o servidor, por exemplo, basta digitar python3 main.py servidor na linha de comando.
=> Link dos códigos fontes
Códigos do trabalho:
blockchain.py
cliente.py
servidor.py
main.py
=> Logs de execução
Abaixo estão detalhados os cenários de teste executados para gerar os arquivos de log da aplicação.
- Fluxo normal em:
- Cliente
- Servidor
- Fluxo de exceção em:
- Cancela execução no cliente com ctrl + C
- Cancela execução no servidor com ctrl + C
- Cliente caiu conexão
- Servidor caiu a conexão
- Cliente sem servidor
- Input errado em:
- Cliente
- Servidor
- Log exaustivo com 1000 entradas em:
- Cliente
- Servidor
Testa a operação padrão e esperada do sistema.
Testa o que acontece com interrupções e falhas no programa.
Testa como o programa lida com dados errados.
Relatório – Trabalho Prático de Redes II