Una parte importande de una blockchain a la Ethereum, es la ejecución de transacciones de transferencias. Cada cuenta tiene una dirección pública y un estado de cuenta conteniendo su balanca. Los estados de cuenta se almacenan en tries inmutables. Esta semana estuve trabajando en mi proyecto personal de blockchain, escrito en JavaScript/NodeJS:
https://github.com/ajlopez/SimpleBlockchain
para ejecutar una transferencia entre cuentas. Como es habitual, lo codifiqué siguiendo el flujo de trabajo de TDD (Test-Driven Development). Mi primer test:
exports['execute transfer'] = function (test) { var from = utils.hash(); var to = utils.hash(); var value = 1000; var states = tries.states().put(from, { balance: 3000 }); var tx = transactions.transfer(from, to, value); test.ok(tx); test.equal(tx.from, from); test.equal(tx.to, to); test.equal(tx.value, value); var newstates = transactions.execute(tx, states); test.ok(newstates); var oldfromstate = states.get(tx.from); test.ok(oldfromstate); test.equal(oldfromstate.balance, 3000); var oldtostate = states.get(tx.to); test.ok(oldtostate); test.equal(oldtostate.balance, 0); var newtostate = newstates.get(tx.to); test.ok(newtostate); test.equal(newtostate.balance, 1000); var newfromstate = newstates.get(tx.from); test.ok(newfromstate); test.equal(newfromstate.balance, 2000); }
Luego de la ejecución de una transacción, un nuevo trie de estados de cuenta se arma y se devuelve. Pero también hay que rechazar las transferencias que no tienen fondos:
exports['execute transfer without funds'] = function (test) { var from = utils.hash(); var to = utils.hash(); var value = 1000; var states = tries.states(); var tx = transactions.transfer(from, to, value); test.ok(tx); test.equal(tx.from, from); test.equal(tx.to, to); test.equal(tx.value, value); var newstates = transactions.execute(tx, states); test.equal(newstates, null); var oldfromstate = states.get(tx.from); test.ok(oldfromstate); test.equal(oldfromstate.balance, 0); var oldtostate = states.get(tx.to); test.ok(oldtostate); test.equal(oldtostate.balance, 0); }
Para cumplir con esos tests, mi implementación actual, simple, es:
function execute(tx, states) { var fromstate = states.get(tx.from); var tostate = states.get(tx.to); fromstate.balance -= tx.value; if (fromstate.balance < 0) return null; tostate.balance += tx.value; return states.put(tx.from, fromstate).put(tx.to, tostate); }
Próximos posts: ejecutando bloques con transacciones, almacenando permanentemente los tries de estados, smart contracts, etc…
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez