Skip to content

Commit b13bfd4

Browse files
committed
Merge branch 'issue-54'
2 parents 2b9e788 + 95b7fe8 commit b13bfd4

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

src/blockchain.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,30 @@ class Blockchain {
192192
}
193193

194194
// Making sure that the amount sent is not greater than existing balance
195-
if (this.getBalanceOfAddress(transaction.fromAddress) < transaction.amount) {
195+
const walletBalance = this.getBalanceOfAddress(transaction.fromAddress);
196+
if (walletBalance < transaction.amount) {
196197
throw new Error('Not enough balance');
197198
}
198199

200+
// Get all other pending transactions for the "from" wallet
201+
const pendingTxForWallet = this.pendingTransactions
202+
.filter(tx => tx.fromAddress === transaction.fromAddress);
203+
204+
// If the wallet has more pending transactions, calculate the total amount
205+
// of spend coins so far. If this exceeds the balance, we refuse to add this
206+
// transaction.
207+
if (pendingTxForWallet.length > 0) {
208+
const totalPendingAmount = pendingTxForWallet
209+
.map(tx => tx.amount)
210+
.reduce((prev, curr) => prev + curr);
211+
212+
const totalAmount = totalPendingAmount + transaction.amount;
213+
if (totalAmount > walletBalance) {
214+
throw new Error('Pending transactions for this wallet is higher than its balance.');
215+
}
216+
}
217+
218+
199219
this.pendingTransactions.push(transaction);
200220
debug('transaction added: %s', transaction);
201221
}

tests/blockchain.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,36 @@ describe('Blockchain class', function() {
8282
});
8383
});
8484

85+
describe('minePendingTransactions', function() {
86+
// It should not be possible for a user to create multiple pending
87+
// transactions for a total amount higher than his balance.
88+
// In this test we start with this situation:
89+
// - Wallet "walletAddr" -> 80 coins (100 mining reward - 2 test tx)
90+
// - Wallet "wallet2" -> 0 coins
91+
it('should not allow pending transactions to go below zero', function() {
92+
const blockchain = createBlockchainWithTx();
93+
const walletAddr = signingKey.getPublic('hex');
94+
95+
// Verify that the wallets have the correct balance
96+
assert.strict.equal(blockchain.getBalanceOfAddress('wallet2'), 0);
97+
assert.strict.equal(blockchain.getBalanceOfAddress(walletAddr), 80);
98+
99+
// Create a transaction for 80 coins (from walletAddr -> "wallet2")
100+
blockchain.addTransaction(createSignedTx(80));
101+
102+
// Try tro create another transaction for which we don't have the balance.
103+
// Blockchain should refuse this!
104+
assert.throws(() => { blockchain.addTransaction(createSignedTx(80)); }, Error);
105+
106+
// Mine transactions, send rewards to another address
107+
blockchain.minePendingTransactions(1);
108+
109+
// Verify that the first transaction did go through.
110+
assert.strict.equal(blockchain.getBalanceOfAddress(walletAddr), 0);
111+
assert.strict.equal(blockchain.getBalanceOfAddress('wallet2'), 80);
112+
});
113+
});
114+
85115
describe('helper functions', function() {
86116
it('should correctly set first block to genesis block', function() {
87117
assert.strict.deepEqual(blockchain.chain[0], blockchain.createGenesisBlock());

0 commit comments

Comments
 (0)