Armando una Blockchain (9)

Published on Author lopezLeave a comment

Anterior Post
Siguiente Post

Ya estuve publicando detalles de mi proyecto personal de blockchain escrito en C#:

https://github.com/ajlopez/BlockchainSharp

Esta semana comencé otra implementación, esta vez usando JavaScript/NodeJS:

https://github.com/ajlopez/SimpleBlockchain

Es interesante comparar las dos implementaciones, una en un lenguaje tipado y otra en un lenguaje dinámico.

Al igual que en C#, los conceptos bases a implementar son: bloques, transacciones, una blockchain, etc…. Estoy escribiendo el código usando el flujo de trabajo de TDD (Test-Driven Development), como es habitual, para practicar esa disciplina cada dia. La idea es implementar esas entidades de base, y entonces, escribir código de un servidor que pueda comunicarse con otros servidores en una red. Quiero usar mensajes JSON en este proyecto (en C# pienso usar corrientes de bytes sobre sockets). Igual el formato es una decisión que puede cambiar, y sin mayor costo o esfuerzo. Por ahora, necesito implementar la conducta de base, cubierta por los correspondientes tests.

Estos son, por ejemplo, algunos tests de creación de bloques:

exports['create genesis block'] = function (test) {
    var block = blocks.block();
    
    test.ok(block);
    test.equal(typeof block, 'object');
    test.equal(block.number, 0);
    test.ok(isHash(block.hash));
    test.ok(isHash(block.parentHash));
    test.equal(block.parentHash, '0x000....000000');
}

exports['create child block'] = function (test) {
    var genesis = blocks.block();
    var block = blocks.block(genesis);
    
    test.ok(block);
    test.equal(typeof block, 'object');
    test.equal(block.number, 1);
    test.ok(isHash(block.hash));
    test.ok(isHash(block.parentHash));
    test.equal(block.parentHash, genesis.hash);
}

exports['create child block with initial data'] = function (test) {
    var genesis = blocks.block();
    var block = blocks.block({ extra: 'hello' }, genesis);
    
    test.ok(block);
    test.equal(typeof block, 'object');
    test.equal(block.number, 1);
    test.ok(isHash(block.hash));
    test.ok(isHash(block.parentHash));
    test.equal(block.parentHash, genesis.hash);
    test.equal(block.extra, 'hello');
}

Escribo esos tests, uno por uno, y luego de cada test, escribo el código de producción más simple que hace que el test pase. De esa manera, voy avanzando siempre sobre una solución simple a la conducta esperada. Y si luego se me ocurre una mejor implementación, puedo refactorizar y hasta rediseñar, sabiendo que la conducta no cambia ejecutando los tests. Tanto la simplicidad obtenida como la facilidad para el cambio me parecen grandes aportes de seguir este flujo de trabajo.

Despues de las entidades de base, necesito algunas entidades auxiliares, especialmente para permitir el proceso eficiente de bloques y transacciones. Una de esas entidades ayudantes es un almacén de bloques: un lugar donde guardar y recuperar bloques, por hash, hash padre, número. Siguiendo el principio de simplicidad, por ahora tengo una implementación en memoria, vean algunos tests:

exports['create store'] = function (test) {
    var store = stores.blockstore();
    
    test.ok(store);
    test.equal(typeof store, 'object');
};

exports['retrieve unknown block by hash'] = function (test) {
    var store = stores.blockstore();
    
    var block = store.getByHash(utils.hash());
    
    test.equal(block, null);
};

exports['save block and retrieve it by hash'] = function (test) {
    var store = stores.blockstore();
    var hash = utils.hash();
    var block = { hash: hash };
    
    store.save(block);
    
    var result = store.getByHash(hash);
    
    test.ok(result);
    test.equal(result.hash, hash);
};

Voy a seguir trabajando en ambos proyectos: el de C# necesita mejorar el proceso de bloques, y algo de implementación de servidor de red. Con el de JavaScript posiblemente llegue primero a implementar nodos corriendo en red, sin transacciones, bloques vacios intercambiándose entre pares, formando una blockchain por consenso. Algo lindo de la implementación de JavaScript es que no tengo que preocuparme por la concurrencia de varios threads. Puedo, por ejemplo, cambiar la estructura de la blockchain sin preocuparme que otros threads esten ingresando al mismo tiempo a consultarla o actualizarla.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *