Skip to content

Commit e2b843f

Browse files
committed
Update backend
1 parent ba22165 commit e2b843f

1,663 files changed

Lines changed: 104 additions & 692830 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
*__pycache__*
33
*node_modules*
44
blockchain-env/lib/python3.7
5+
*.DS_Store*
6+

backend/app/__init__.py

Lines changed: 5 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import random
44

55
from flask import Flask, jsonify, request
6-
from flask_cors import CORS
76

87
from backend.blockchain.blockchain import Blockchain
98
from backend.wallet.wallet import Wallet
@@ -12,9 +11,8 @@
1211
from backend.pubsub import PubSub
1312

1413
app = Flask(__name__)
15-
CORS(app, resources={ r'/*': { 'origins': 'http://localhost:3000' } })
1614
blockchain = Blockchain()
17-
wallet = Wallet(blockchain)
15+
wallet = Wallet()
1816
transaction_pool = TransactionPool()
1917
pubsub = PubSub(blockchain, transaction_pool)
2018

@@ -26,23 +24,9 @@ def route_default():
2624
def route_blockchain():
2725
return jsonify(blockchain.to_json())
2826

29-
@app.route('/blockchain/range')
30-
def route_blockchain_range():
31-
# http://localhost:5000/blockchain/range?start=2&end=5
32-
start = int(request.args.get('start'))
33-
end = int(request.args.get('end'))
34-
35-
return jsonify(blockchain.to_json()[::-1][start:end])
36-
37-
@app.route('/blockchain/length')
38-
def route_blockchain_length():
39-
return jsonify(len(blockchain.chain))
40-
4127
@app.route('/blockchain/mine')
4228
def route_blockchain_mine():
43-
transaction_data = transaction_pool.transaction_data()
44-
transaction_data.append(Transaction.reward_transaction(wallet).to_json())
45-
blockchain.add_block(transaction_data)
29+
blockchain.add_block(transaction_pool.transaction_data())
4630
block = blockchain.chain[-1]
4731
pubsub.broadcast_block(block)
4832
transaction_pool.clear_blockchain_transactions(blockchain)
@@ -68,33 +52,14 @@ def route_wallet_transact():
6852
)
6953

7054
pubsub.broadcast_transaction(transaction)
71-
transaction_pool.set_transaction(transaction)
7255

7356
return jsonify(transaction.to_json())
7457

75-
@app.route('/wallet/info')
76-
def route_wallet_info():
77-
return jsonify({ 'address': wallet.address, 'balance': wallet.balance })
78-
79-
@app.route('/known-addresses')
80-
def route_known_addresses():
81-
known_addresses = set()
82-
83-
for block in blockchain.chain:
84-
for transaction in block.data:
85-
known_addresses.update(transaction['output'].keys())
86-
87-
return jsonify(list(known_addresses))
88-
89-
@app.route('/transactions')
90-
def route_transactions():
91-
return jsonify(transaction_pool.transaction_data())
92-
93-
ROOT_PORT = 5000
58+
ROOT_PORT = 5050
9459
PORT = ROOT_PORT
9560

9661
if os.environ.get('PEER') == 'True':
97-
PORT = random.randint(5001, 6000)
62+
PORT = random.randint(5051, 6000)
9863

9964
result = requests.get(f'http://localhost:{ROOT_PORT}/blockchain')
10065
result_blockchain = Blockchain.from_json(result.json())
@@ -105,16 +70,5 @@ def route_transactions():
10570
except Exception as e:
10671
print(f'\n -- Error synchronizing: {e}')
10772

108-
if os.environ.get('SEED_DATA') == 'True':
109-
for i in range(10):
110-
blockchain.add_block([
111-
Transaction(Wallet(), Wallet().address, random.randint(2, 50)).to_json(),
112-
Transaction(Wallet(), Wallet().address, random.randint(2, 50)).to_json()
113-
])
114-
115-
for i in range(3):
116-
transaction_pool.set_transaction(
117-
Transaction(Wallet(), Wallet().address, random.randint(2, 50))
118-
)
73+
app.run(port=5050)
11974

120-
app.run(port=PORT)

backend/blockchain/blockchain.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
from backend.blockchain.block import Block
2-
from backend.wallet.transaction import Transaction
3-
from backend.wallet.wallet import Wallet
4-
from backend.config import MINING_REWARD_INPUT
52

63
class Blockchain:
74
"""
@@ -68,53 +65,6 @@ def is_valid_chain(chain):
6865
last_block = chain[i-1]
6966
Block.is_valid_block(last_block, block)
7067

71-
Blockchain.is_valid_transaction_chain(chain)
72-
73-
@staticmethod
74-
def is_valid_transaction_chain(chain):
75-
"""
76-
Enforce the rules of a chain composed of blocks of transactions.
77-
- Each transaction must only appear once in the chain.
78-
- There can only be one mining reward per block.
79-
- Each transaction must be valid.
80-
"""
81-
transaction_ids = set()
82-
83-
for i in range(len(chain)):
84-
block = chain[i]
85-
has_mining_reward = False
86-
87-
for transaction_json in block.data:
88-
transaction = Transaction.from_json(transaction_json)
89-
90-
if transaction.id in transaction_ids:
91-
raise Exception(f'Transaction {transaction.id} is not unique')
92-
93-
transaction_ids.add(transaction.id)
94-
95-
if transaction.input == MINING_REWARD_INPUT:
96-
if has_mining_reward:
97-
raise Exception(
98-
'There can only be one mining reward per block. '\
99-
f'Check block with hash: {block.hash}'
100-
)
101-
102-
has_mining_reward = True
103-
else:
104-
historic_blockchain = Blockchain()
105-
historic_blockchain.chain = chain[0:i]
106-
historic_balance = Wallet.calculate_balance(
107-
historic_blockchain,
108-
transaction.input['address']
109-
)
110-
111-
if historic_balance != transaction.input['amount']:
112-
raise Exception(
113-
f'Transaction {transaction.id} has an invalid '\
114-
'input amount'
115-
)
116-
117-
Transaction.is_valid_transaction(transaction)
11868

11969
def main():
12070
blockchain = Blockchain()

backend/config.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,3 @@
66
MINE_RATE = 4 * SECONDS
77

88
STARTING_BALANCE = 1000
9-
10-
MINING_REWARD = 50
11-
MINING_REWARD_INPUT = { 'address': '*--official-mining-reward--*' }

backend/pubsub.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
from backend.wallet.transaction import Transaction
99

1010
pnconfig = PNConfiguration()
11-
pnconfig.subscribe_key = 'sub-c-666638f6-ec63-11e9-b715-9abbdb5d0da2'
12-
pnconfig.publish_key = 'pub-c-82bf7695-ce5e-4bc5-9cd9-a8f8147dc2a8'
11+
# NOTE: these keys have been retired.
12+
pnconfig.subscribe_key = 'sub-c-448d1fb4-5f47-4e56-a496-e4588e0808a7'
13+
pnconfig.publish_key = 'pub-c-691add7b-2cc0-42c8-96f9-7edf786b5b4b'
14+
pnconfig.user_id = 'test-1'
1315

1416
CHANNELS = {
1517
'TEST': 'TEST',
@@ -32,9 +34,11 @@ def message(self, pubnub, message_object):
3234

3335
try:
3436
self.blockchain.replace_chain(potential_chain)
37+
3538
self.transaction_pool.clear_blockchain_transactions(
3639
self.blockchain
3740
)
41+
3842
print('\n -- Successfully replaced the local chain')
3943
except Exception as e:
4044
print(f'\n -- Did not replace chain: {e}')
@@ -57,9 +61,7 @@ def publish(self, channel, message):
5761
"""
5862
Publish the message object to the channel.
5963
"""
60-
self.pubnub.unsubscribe().channels([channel]).execute()
6164
self.pubnub.publish().channel(channel).message(message).sync()
62-
self.pubnub.subscribe().channels([channel]).execute()
6365

6466
def broadcast_block(self, block):
6567
"""

backend/scripts/average_block_rate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919

2020
print(f'New block difficulty: {blockchain.chain[-1].difficulty}')
2121
print(f'Time to mine new block: {time_to_mine}s')
22-
print(f'Average time to add blocks: {average_time}s\n')
22+
print(f'Average time to add blocks: {average_time}s\n')

backend/scripts/test_app.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,20 @@
33

44
from backend.wallet.wallet import Wallet
55

6-
BASE_URL = 'http://127.0.0.1:5000'
6+
BASE_URL = 'http://localhost:5050'
77

88
def get_blockchain():
99
return requests.get(f'{BASE_URL}/blockchain').json()
1010

1111
def get_blockchain_mine():
1212
return requests.get(f'{BASE_URL}/blockchain/mine').json()
1313

14-
def post_wallet_transact(recipient, amount):
14+
def post_wallet_transact(recipient, amount):
1515
return requests.post(
1616
f'{BASE_URL}/wallet/transact',
1717
json={ 'recipient': recipient, 'amount': amount }
1818
).json()
1919

20-
def get_wallet_info():
21-
return requests.get(f'{BASE_URL}/wallet/info').json()
22-
2320
start_blockchain = get_blockchain()
2421
print(f'start_blockchain: {start_blockchain}')
2522

@@ -34,6 +31,3 @@ def get_wallet_info():
3431
time.sleep(1)
3532
mined_block = get_blockchain_mine()
3633
print(f'\nmined_block: {mined_block}')
37-
38-
wallet_info = get_wallet_info()
39-
print(f'\nwallet_info: {wallet_info}')

backend/tests/blockchain/test_block.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@ def test_is_valid_block_bad_block_hash(last_block, block):
8585
block.hash = '0000000000000000bbbabc'
8686

8787
with pytest.raises(Exception, match='block hash must be correct'):
88-
Block.is_valid_block(last_block, block)
88+
Block.is_valid_block(last_block, block)
Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import pytest
2-
31
from backend.blockchain.blockchain import Blockchain
42
from backend.blockchain.block import GENESIS_DATA
5-
from backend.wallet.wallet import Wallet
6-
from backend.wallet.transaction import Transaction
73

84
def test_blockchain_instance():
95
blockchain = Blockchain()
@@ -15,76 +11,3 @@ def test_add_block():
1511
blockchain.add_block(data)
1612

1713
assert blockchain.chain[-1].data == data
18-
19-
@pytest.fixture
20-
def blockchain_three_blocks():
21-
blockchain = Blockchain()
22-
for i in range(3):
23-
blockchain.add_block([Transaction(Wallet(), 'recipient', i).to_json()])
24-
return blockchain
25-
26-
def test_is_valid_chain(blockchain_three_blocks):
27-
Blockchain.is_valid_chain(blockchain_three_blocks.chain)
28-
29-
def test_is_valid_chain_bad_genesis(blockchain_three_blocks):
30-
blockchain_three_blocks.chain[0].hash = 'evil_hash'
31-
32-
with pytest.raises(Exception, match='genesis block must be valid'):
33-
Blockchain.is_valid_chain(blockchain_three_blocks.chain)
34-
35-
def test_replace_chain(blockchain_three_blocks):
36-
blockchain = Blockchain()
37-
blockchain.replace_chain(blockchain_three_blocks.chain)
38-
39-
assert blockchain.chain == blockchain_three_blocks.chain
40-
41-
def test_replace_chain_not_longer(blockchain_three_blocks):
42-
blockchain = Blockchain()
43-
44-
with pytest.raises(Exception, match='The incoming chain must be longer'):
45-
blockchain_three_blocks.replace_chain(blockchain.chain)
46-
47-
def test_replace_chain_bad_chain(blockchain_three_blocks):
48-
blockchain = Blockchain()
49-
blockchain_three_blocks.chain[1].hash = 'evil_hash'
50-
51-
with pytest.raises(Exception, match='The incoming chain is invalid'):
52-
blockchain.replace_chain(blockchain_three_blocks.chain)
53-
54-
def test_valid_transaction_chain(blockchain_three_blocks):
55-
Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
56-
57-
def test_is_valid_transaction_chain_duplicate_transactions(blockchain_three_blocks):
58-
transaction = Transaction(Wallet(), 'recipient', 1).to_json()
59-
blockchain_three_blocks.add_block([transaction, transaction])
60-
61-
with pytest.raises(Exception, match='is not unique'):
62-
Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
63-
64-
def test_is_valid_transaction_chain_multiple_rewards(blockchain_three_blocks):
65-
reward_1 = Transaction.reward_transaction(Wallet()).to_json()
66-
reward_2 = Transaction.reward_transaction(Wallet()).to_json()
67-
blockchain_three_blocks.add_block([reward_1, reward_2])
68-
69-
with pytest.raises(Exception, match='one mining reward per block'):
70-
Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
71-
72-
def test_is_valid_transaction_chain_bad_transaction(blockchain_three_blocks):
73-
bad_transaction = Transaction(Wallet(), 'recipient', 1)
74-
bad_transaction.input['signature'] = Wallet().sign(bad_transaction.output)
75-
blockchain_three_blocks.add_block([bad_transaction.to_json()])
76-
77-
with pytest.raises(Exception):
78-
Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
79-
80-
def test_is_valid_transaction_chain_bad_historic_balance(blockchain_three_blocks):
81-
wallet = Wallet()
82-
bad_transaction = Transaction(wallet, 'recipient', 1)
83-
bad_transaction.output[wallet.address] = 9000
84-
bad_transaction.input['amount'] = 9001
85-
bad_transaction.input['signature'] = wallet.sign(bad_transaction.output)
86-
87-
blockchain_three_blocks.add_block([bad_transaction.to_json()])
88-
89-
with pytest.raises(Exception, match='has an invalid input amount'):
90-
Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from backend.util.crypto_hash import crypto_hash
22

33
def test_crypto_hash():
4-
# It should create the same hash with arguments of different data types
5-
# in any order
4+
# It should create the same hash with arguments of different data types in
5+
# any order
66
assert crypto_hash(1, [2], 'three') == crypto_hash('three', 1, [2])
7-
assert crypto_hash('foo') == 'b2213295d564916f89a6a42455567c87c3f480fcd7a1c15e220f17d7169a790b'
7+
assert crypto_hash('foo') == 'b2213295d564916f89a6a42455567c87c3f480fcd7a1c15e220f17d7169a790b'

0 commit comments

Comments
 (0)