Skip to content

Commit

Permalink
マイニング報酬
Browse files Browse the repository at this point in the history
  • Loading branch information
mizumotok committed Apr 25, 2018
1 parent 77a595a commit 71ddeb2
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 20 deletions.
32 changes: 25 additions & 7 deletions src/__tests__/blockchain/transaction.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,60 @@

import SHA256 from 'crypto-js/sha256';
import Blockchain, { Transaction } from '../../blockchain';
import Wallet, { INITIAL_BALANCE } from '../../wallet';
import Wallet from '../../wallet';
import Miner from '../../miner';
import { MINING_REWARD } from '../../config';

describe('Transaction', () => {
let wallet: Wallet;
let tx: Transaction;
let miner: Miner;
beforeEach(() => {
const blockchain = new Blockchain();
wallet = new Wallet(blockchain);
tx = Transaction.createTransaction(wallet, 'recipient-address', 100);
miner = new Miner(blockchain, wallet.publicKey);
});

it('createOutputs test', () => {
miner.mine(); // まず報酬をもらう
const tx = Transaction.createTransaction(wallet, 'recipient-address', 10);

// おつりあり
expect(tx.outputs).toEqual([
{ amount: 100, address: 'recipient-address' },
{ amount: INITIAL_BALANCE - 100, address: wallet.publicKey },
{ amount: 10, address: 'recipient-address' },
{ amount: MINING_REWARD - 10, address: wallet.publicKey },
]);

// おつりなし
const tx2 = Transaction.createTransaction(wallet, 'recipient-address', INITIAL_BALANCE);
const tx2 = Transaction.createTransaction(wallet, 'recipient-address', MINING_REWARD);
expect(tx2.outputs).toEqual([
{ amount: INITIAL_BALANCE, address: 'recipient-address' },
{ amount: MINING_REWARD, address: 'recipient-address' },
]);
});

it('signTransaction test', () => {
miner.mine();
const tx = Transaction.createTransaction(wallet, 'recipient-address', 10);

const hash = SHA256(JSON.stringify(tx.outputs)).toString();
expect(tx.input.address).toBe(wallet.publicKey);
expect(tx.input.signature).toEqual(wallet.sign(hash));
});

it('verifyTransaction test', () => {
miner.mine();
const tx = Transaction.createTransaction(wallet, 'recipient-address', 10);

expect(tx.verifyTransaction()).toBe(true);

// 改ざん
tx.outputs[0].address = 'kaizansareta-address';
expect(tx.verifyTransaction()).toBe(false);
});

it('rewardTransaction', () => {
const tx = Transaction.rewardTransaction('reward-address');
expect(tx.outputs[0].address).toBe('reward-address');
expect(tx.outputs[0].amount).toBe(MINING_REWARD);
expect(tx.coinbase.length).toBeGreaterThan(1);
});
});
2 changes: 1 addition & 1 deletion src/__tests__/miner/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('Miner', () => {
beforeEach(() => {
blockchain = new Blockchain();
wallet = new Wallet(blockchain);
miner = new Miner(blockchain);
miner = new Miner(blockchain, wallet.publicKey);
});

it('mine test', () => {
Expand Down
15 changes: 9 additions & 6 deletions src/__tests__/wallet/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import { ec as EC } from 'elliptic';
import Blockchain, { Transaction } from '../../blockchain';
import Miner from '../../miner';
import Wallet, { INITIAL_BALANCE } from '../../wallet';
import Wallet from '../../wallet';
import { MINING_REWARD } from '../../config';

const ec = new EC('secp256k1');

Expand All @@ -14,18 +15,20 @@ describe('Miner', () => {

beforeEach(() => {
blockchain = new Blockchain();
miner = new Miner(blockchain);
wallet = new Wallet(blockchain);
miner = new Miner(blockchain, wallet.publicKey);
});

it('balance test', () => {
expect(wallet.balance()).toBe(INITIAL_BALANCE);
expect(wallet.balance()).toBe(0);

const tx = Transaction.createTransaction(wallet, 'recipient-address', 100);
miner.mine();
expect(wallet.balance()).toBe(MINING_REWARD);

const tx = Transaction.createTransaction(wallet, 'recipient-address', 10);
miner.pushTransaction(tx);
miner.mine();
expect(wallet.balance()).toBe(INITIAL_BALANCE - 100);
console.log(`残高: ${INITIAL_BALANCE - 100}`);
expect(wallet.balance()).toBe((MINING_REWARD * 2) - 10);
});

it('sign test', () => {
Expand Down
16 changes: 16 additions & 0 deletions src/blockchain/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import uuidv1 from 'uuid/v1';
import SHA256 from 'crypto-js/sha256';
import { ec as EC } from 'elliptic';
import Wallet from '../wallet';
import { MINING_REWARD } from '../config';

const ec = new EC('secp256k1');

Expand All @@ -23,6 +24,7 @@ class Transaction {
id: string;
outputs: Array<Output>;
input: Input;
coinbase: ?string;

createOutputs(senderWallet: Wallet, recipient: string, amount: number) {
const balance = senderWallet.balance();
Expand Down Expand Up @@ -62,6 +64,20 @@ class Transaction {
tx.signTransaction(senderWallet);
return tx;
}

createCoinbase(recipient: string) {
this.outputs = [
{ amount: MINING_REWARD, address: recipient },
];
this.coinbase = `This is coinbase created at ${new Date().toString()}`;
}

static rewardTransaction(rewardAddress: string) {
const tx = new Transaction();
tx.id = uuidv1();
tx.createCoinbase(rewardAddress);
return tx;
}
}

export default Transaction;
2 changes: 2 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const DIFFICULTY_TARGET = 240;
const MINING_DURATION = 5000;
const MINING_REWARD = 50;

module.exports = {
DIFFICULTY_TARGET,
MINING_DURATION,
MINING_REWARD,
};
10 changes: 8 additions & 2 deletions src/miner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@ import Blockchain, { Block, Transaction } from '../blockchain';
class Miner {
transactionPool: Array<Transaction>;
blockchain: Blockchain;
rewardAddress: string;

constructor(blockchain: Blockchain) {
constructor(blockchain: Blockchain, rewardAddress: string) {
this.transactionPool = [];
this.blockchain = blockchain;
this.rewardAddress = rewardAddress;
}

mine() {
const miningStartTimestamp = new Date().getTime();
const prevHash = this.blockchain.lastHash();
const target = this.blockchain.nextDifficultyTarget();
const rewardTx = Transaction.rewardTransaction(this.rewardAddress);
this.transactionPool.push(rewardTx);

let nonce = 0;
let block;
Expand All @@ -34,14 +38,16 @@ class Miner {
} while (!block.isValid());

this.blockchain.addBlock(block);
this.clearTransactions();
}

pushTransaction(tx: Transaction) {
if (!tx.verifyTransaction()) {
console.log('署名の検証に失敗しました。');
return;
}
this.transactionPool = this.transactionPool.filter(t => t.input.address !== tx.input.address);
this.transactionPool =
this.transactionPool.filter(t => t.input && t.input.address !== tx.input.address);
this.transactionPool.push(tx);
console.log('トランザクションを追加しました。');
}
Expand Down
5 changes: 1 addition & 4 deletions src/wallet/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import Blockchain, { Transaction } from '../blockchain';

const ec = new EC('secp256k1');

const INITIAL_BALANCE = 1000;

class Wallet {
blockchain: Blockchain;
keyPair: any;
Expand Down Expand Up @@ -38,7 +36,7 @@ class Wallet {
o.address === this.publicKey ? a2 + o.amount : a2
), 0)
), 0);
return (outputs - inputs) + INITIAL_BALANCE;
return outputs - inputs;
}

sign(data: string) :string {
Expand All @@ -47,4 +45,3 @@ class Wallet {
}

export default Wallet;
export { INITIAL_BALANCE };

0 comments on commit 71ddeb2

Please sign in to comment.