Last active
          March 9, 2024 12:27 
        
      - 
      
- 
        Save johnnieskywalker/c56c89de45d378b44d2b77e21c764c0b to your computer and use it in GitHub Desktop. 
Revisions
- 
        johnnieskywalker revised this gist Mar 9, 2024 . 2 changed files with 40 additions and 3 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,37 @@ const { assert } = require('chai'); const Transaction = require('../Transaction'); const TXO = require('../TXO'); describe('Transaction', function () { const fromAddress = "1DBS97W3jWw6FnAqdduK1NW6kFo3Aid1N6"; const toAddress = "12ruWjb4naCME5QhjrQSJuS5disgME22fe"; describe('with no remainder', () => { const txo1 = new TXO(fromAddress, 5); const txo2 = new TXO(fromAddress, 5); const outputTXO1 = new TXO(toAddress, 7); const outputTXO2 = new TXO(fromAddress, 3); const tx = new Transaction([txo1, txo2], [outputTXO1, outputTXO2]); tx.execute(); it('should have zero fee', () => { assert.equal(tx.fee, 0); }); }); describe('with some remainder', () => { const txo1 = new TXO(fromAddress, 15); const outputTXO1 = new TXO(toAddress, 7); const outputTXO2 = new TXO(fromAddress, 6); const tx = new Transaction([txo1], [outputTXO1, outputTXO2]); tx.execute(); it('should have the remainder as the fee', () => { assert.equal(tx.fee, 2); }); }); }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,15 +5,15 @@ class Transaction { } execute() { const sumInputUTXOs = this.inputUTXOs.reduce((acc, curr) => acc + curr.amount, 0); const sumOutputUTXOs = this.outputUTXOs.reduce((acc, curr) => acc + curr.amount, 0); try { const hasSpentInput = this.inputUTXOs.some(input => input.spent); if (hasSpentInput) { throw new Error('One or more input UTXOs have already been spent.'); } const sufficientInput = sumInputUTXOs >= sumOutputUTXOs; if (!sufficientInput) { @@ -27,7 +27,7 @@ class Transaction { throw error; } this.inputUTXOs.forEach(input => input.spent = true); this.fee = sumInputUTXOs - sumOutputUTXOs; } } 
- 
        johnnieskywalker revised this gist Mar 7, 2024 . 2 changed files with 72 additions and 10 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,50 @@ const { assert } = require('chai'); const Transaction = require('../Transaction'); const TXO = require('../TXO'); describe('Transaction', function () { const fromAddress = "1DBS97W3jWw6FnAqdduK1NW6kFo3Aid1N6"; const toAddress = "12ruWjb4naCME5QhjrQSJuS5disgME22fe"; const txo1 = new TXO(fromAddress, 5); const txo2 = new TXO(fromAddress, 5); const txo3 = new TXO(fromAddress, 3); const txo4 = new TXO(fromAddress, 4); const outputTXO1 = new TXO(toAddress, 7); const outputTXO2 = new TXO(fromAddress, 3); it('should mark both inputs as spent', () => { const tx = new Transaction([txo1, txo2], [outputTXO1, outputTXO2]); tx.execute(); assert(txo1.spent); assert(txo2.spent); }); it('should leave both inputs unspent if funds unavailable', () => { const tx = new Transaction([txo3, txo4], [outputTXO1, outputTXO2]); let ex; try { tx.execute(); } catch (_ex) { ex = _ex; } assert(ex, "Expected an exception to be thrown!"); assert(!txo3.spent, "The transaction should be marked as unspent"); assert(!txo4.spent, "The transaction should be marked as unspent"); }); it('should leave valid inputs unspent if a double spend occurs', () => { const tx = new Transaction([txo1, txo4], [outputTXO1, outputTXO2]); let ex; try { tx.execute(); } catch (_ex) { ex = _ex; } assert(ex, "Expected an exception to be thrown!"); assert(!txo4.spent, "The transaction should be marked as unspent"); }); }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -3,20 +3,32 @@ class Transaction { this.inputUTXOs = inputUTXOs; this.outputUTXOs = outputUTXOs; } execute() { try { const hasSpentInput = this.inputUTXOs.some(input => input.spent); if (hasSpentInput) { throw new Error('One or more input UTXOs have already been spent.'); } const sumInputUTXOs = this.inputUTXOs.reduce((acc, curr) => acc + curr.amount, 0); const sumOutputUTXOs = this.outputUTXOs.reduce((acc, curr) => acc + curr.amount, 0); const sufficientInput = sumInputUTXOs >= sumOutputUTXOs; if (!sufficientInput) { throw new Error('Insufficient input UTXOs'); } } catch (error) { if (error.message === 'Insufficient input UTXOs') { this.inputUTXOs.forEach(input => input.spent = false); } throw error; } this.inputUTXOs.forEach(input => input.spent = true); } } module.exports = Transaction; 
- 
        johnnieskywalker revised this gist Mar 7, 2024 . 2 changed files with 52 additions and 0 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,45 @@ const { assert } = require('chai'); const Transaction = require('../Transaction'); const TXO = require('../TXO'); describe('Transaction', function () { const fromAddress = "1DBS97W3jWw6FnAqdduK1NW6kFo3Aid1N6"; const toAddress = "12ruWjb4naCME5QhjrQSJuS5disgME22fe"; describe('with sufficient UTXOs', () => { const txo1 = new TXO(fromAddress, 5); const txo2 = new TXO(fromAddress, 5); const outputTXO1 = new TXO(toAddress, 10); const tx = new Transaction([txo1, txo2], [outputTXO1]); it('should execute without error', () => { try { tx.execute(); } catch (ex) { assert.fail(ex.message); console.log(ex); } }); }); describe('with insufficient UTXOs', () => { const txo1 = new TXO(fromAddress, 3); const txo2 = new TXO(fromAddress, 3); const txo3 = new TXO(fromAddress, 3); const outputTXO1 = new TXO(toAddress, 10); const tx = new Transaction([txo1, txo2, txo3], [outputTXO1]); it('should throw an error on execute', () => { let ex; try { tx.execute(); } catch (_ex) { ex = _ex; } assert(ex, "Did not throw an exception for a lack of UTXO funds!"); }); }); }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -9,6 +9,13 @@ class Transaction { if (hasSpentInput) { throw new Error('One or more input UTXOs have already been spent.'); } const sumInputUTXOs = this.inputUTXOs.reduce((acc, curr) => acc + curr.amount, 0); const sumOutputUTXOs = this.outputUTXOs.reduce((acc, curr) => acc + curr.amount, 0); const sufficientInput = sumInputUTXOs >= sumOutputUTXOs; if (!sufficientInput) { throw new Error('insufficient input utxos') } } } 
- 
        johnnieskywalker revised this gist Mar 6, 2024 . 2 changed files with 62 additions and 0 deletions.There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,47 @@ const { assert } = require('chai'); const Transaction = require('../Transaction'); const TXO = require('../TXO'); describe('Transaction', function () { const fromAddress = "1DBS97W3jWw6FnAqdduK1NW6kFo3Aid1N6"; const toAddress = "12ruWjb4naCME5QhjrQSJuS5disgME22fe"; describe('with unspent input TXOs', () => { const inputTXO1 = new TXO(fromAddress, 5); const inputTXO2 = new TXO(fromAddress, 5); const outputTXO1 = new TXO(toAddress, 10); const tx = new Transaction([inputTXO1, inputTXO2], [outputTXO1]); it('should execute without error', () => { try { tx.execute(); } catch(ex) { assert.fail(ex.message); console.log(ex); } }); }); describe('with a spent input TXO', () => { const txo1 = new TXO(fromAddress, 5); const txo2 = new TXO(fromAddress, 5); const txo3 = new TXO(fromAddress, 5); const outputTXO1 = new TXO(toAddress, 15); txo2.spend(); const tx = new Transaction([txo1, txo2, txo3], [outputTXO1]); it('should throw an error on execute', () => { let ex; try { tx.execute(); } catch (_ex) { ex = _ex; } assert(ex, "Did not throw an exception with a spent input TXO!"); }); }); }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,15 @@ class Transaction { constructor(inputUTXOs, outputUTXOs) { this.inputUTXOs = inputUTXOs; this.outputUTXOs = outputUTXOs; } execute() { const hasSpentInput = this.inputUTXOs.some(input => input.spent); if (hasSpentInput) { throw new Error('One or more input UTXOs have already been spent.'); } } } module.exports = Transaction; 
- 
        johnnieskywalker created this gist Mar 5, 2024 .There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,12 @@ class TXO { constructor(owner, amount) { this.owner = owner; this.amount = amount; this.spent = false; } spend() { this.spent = true; } } module.exports = TXO; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,27 @@ const { assert } = require('chai'); const TXO = require('../TXO'); describe('TXO', function () { const address = "1DBS97W3jWw6FnAqdduK1NW6kFo3Aid1N6"; const amount = 10; const txo = new TXO(address, amount); describe('constructor', () => { it('should set the owner', () => { assert.equal(txo.owner, address); }); it('should set the amount', () => { assert.equal(txo.amount, amount); }); it('should set spent to false', () => { assert.equal(txo.spent, false); }); }); describe('spend', () => { it('should set spent to true', () => { txo.spend(); assert.equal(txo.spent, true); }); }); });