Skip to content

Commit a99b878

Browse files
committed
Complete Section: Transactions on the Network
1 parent 8c4a976 commit a99b878

5 files changed

Lines changed: 88 additions & 16 deletions

File tree

backend/app/__init__.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
from backend.blockchain.blockchain import Blockchain
88
from backend.wallet.wallet import Wallet
99
from backend.wallet.transaction import Transaction
10+
from backend.wallet.transaction_pool import TransactionPool
1011
from backend.pubsub import PubSub
1112

1213
app = Flask(__name__)
1314
blockchain = Blockchain()
1415
wallet = Wallet()
15-
pubsub = PubSub(blockchain)
16+
transaction_pool = TransactionPool()
17+
pubsub = PubSub(blockchain, transaction_pool)
1618

1719
@app.route('/')
1820
def route_default():
@@ -36,13 +38,22 @@ def route_blockchain_mine():
3638
@app.route('/wallet/transact', methods=['POST'])
3739
def route_wallet_transact():
3840
transaction_data = request.get_json()
39-
transaction = Transaction(
40-
wallet,
41-
transaction_data['recipient'],
42-
transaction_data['amount']
43-
)
44-
45-
print(f'transaction.to_json(): {transaction.to_json()}')
41+
transaction = transaction_pool.existing_transaction(wallet.address)
42+
43+
if transaction:
44+
transaction.update(
45+
wallet,
46+
transaction_data['recipient'],
47+
transaction_data['amount']
48+
)
49+
else:
50+
transaction = Transaction(
51+
wallet,
52+
transaction_data['recipient'],
53+
transaction_data['amount']
54+
)
55+
56+
pubsub.broadcast_transaction(transaction)
4657

4758
return jsonify(transaction.to_json())
4859

backend/pubsub.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,22 @@
55
from pubnub.callbacks import SubscribeCallback
66

77
from backend.blockchain.block import Block
8+
from backend.wallet.transaction import Transaction
89

910
pnconfig = PNConfiguration()
1011
pnconfig.subscribe_key = 'sub-c-666638f6-ec63-11e9-b715-9abbdb5d0da2'
1112
pnconfig.publish_key = 'pub-c-82bf7695-ce5e-4bc5-9cd9-a8f8147dc2a8'
1213

1314
CHANNELS = {
1415
'TEST': 'TEST',
15-
'BLOCK': 'BLOCK'
16+
'BLOCK': 'BLOCK',
17+
'TRANSACTION': 'TRANSACTION'
1618
}
1719

1820
class Listener(SubscribeCallback):
19-
def __init__(self, blockchain):
21+
def __init__(self, blockchain, transaction_pool):
2022
self.blockchain = blockchain
23+
self.transaction_pool = transaction_pool
2124

2225
def message(self, pubnub, message_object):
2326
print(f'\n-- Channel: {message_object.channel} | Message: {message_object.message}')
@@ -32,16 +35,20 @@ def message(self, pubnub, message_object):
3235
print('\n -- Successfully replaced the local chain')
3336
except Exception as e:
3437
print(f'\n -- Did not replace chain: {e}')
38+
elif message_object.channel == CHANNELS['TRANSACTION']:
39+
transaction = Transaction.from_json(message_object.message)
40+
self.transaction_pool.set_transaction(transaction)
41+
print('\n -- Set the new transaction in the transaction pool')
3542

3643
class PubSub():
3744
"""
3845
Handles the publish/subscribe layer of the application.
3946
Provides communication between the nodes of the blockchain network.
4047
"""
41-
def __init__(self, blockchain):
48+
def __init__(self, blockchain, transaction_pool):
4249
self.pubnub = PubNub(pnconfig)
4350
self.pubnub.subscribe().channels(CHANNELS.values()).execute()
44-
self.pubnub.add_listener(Listener(blockchain))
51+
self.pubnub.add_listener(Listener(blockchain, transaction_pool))
4552

4653
def publish(self, channel, message):
4754
"""
@@ -55,6 +62,12 @@ def broadcast_block(self, block):
5562
"""
5663
self.publish(CHANNELS['BLOCK'], block.to_json())
5764

65+
def broadcast_transaction(self, transaction):
66+
"""
67+
Broadcast a transaction to all nodes.
68+
"""
69+
self.publish(CHANNELS['TRANSACTION'], transaction.to_json())
70+
5871
def main():
5972
pubsub = PubSub()
6073

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from backend.wallet.transaction_pool import TransactionPool
2+
from backend.wallet.transaction import Transaction
3+
from backend.wallet.wallet import Wallet
4+
5+
def test_set_transaction():
6+
transaction_pool = TransactionPool()
7+
transaction = Transaction(Wallet(), 'recipient', 1)
8+
transaction_pool.set_transaction(transaction)
9+
10+
assert transaction_pool.transaction_map[transaction.id] == transaction

backend/wallet/transaction.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,22 @@ class Transaction:
88
Document of an exchange in currency from a sender to one
99
or more recipients.
1010
"""
11-
def __init__(self, sender_wallet, recipient, amount):
12-
self.id = str(uuid.uuid4())[0:8]
13-
self.output = self.create_output(
11+
def __init__(
12+
self,
13+
sender_wallet=None,
14+
recipient=None,
15+
amount=None,
16+
id=None,
17+
output=None,
18+
input=None
19+
):
20+
self.id = id or str(uuid.uuid4())[0:8]
21+
self.output = output or self.create_output(
1422
sender_wallet,
1523
recipient,
1624
amount
1725
)
18-
self.input = self.create_input(sender_wallet, self.output)
26+
self.input = input or self.create_input(sender_wallet, self.output)
1927

2028
def create_output(self, sender_wallet, recipient, amount):
2129
"""
@@ -66,6 +74,14 @@ def to_json(self):
6674
"""
6775
return self.__dict__
6876

77+
@staticmethod
78+
def from_json(transaction_json):
79+
"""
80+
Deserialize a transaction's json representation back into a
81+
Transaction instance
82+
"""
83+
return Transaction(**transaction_json)
84+
6985
@staticmethod
7086
def is_valid_transaction(transaction):
7187
"""
@@ -88,5 +104,9 @@ def main():
88104
transaction = Transaction(Wallet(), 'recipient', 15)
89105
print(f'transaction.__dict__: {transaction.__dict__}')
90106

107+
transaction_json = transaction.to_json()
108+
restored_transaction = Transaction.from_json(transaction_json)
109+
print(f'restored_transaction.__dict__: {restored_transaction.__dict__}')
110+
91111
if __name__ == '__main__':
92112
main()

backend/wallet/transaction_pool.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class TransactionPool:
2+
def __init__(self):
3+
self.transaction_map = {}
4+
5+
def set_transaction(self, transaction):
6+
"""
7+
Set a transaction in the transaction pool.
8+
"""
9+
self.transaction_map[transaction.id] = transaction
10+
11+
12+
def existing_transaction(self, address):
13+
"""
14+
Find a transaction generated by the address in the transaction pool
15+
"""
16+
for transaction in self.transaction_map.values():
17+
if transaction.input['address'] == address:
18+
return transaction

0 commit comments

Comments
 (0)