Skip to content

Commit 87d3fec

Browse files
author
mx
committed
add(blockchain): 🎉
1 parent 78722fc commit 87d3fec

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

blockchain.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import hashlib
2+
import json
3+
from time import time
4+
from urllib.parse import urlparse
5+
from uuid import uuid4
6+
from collections import OrderedDict
7+
8+
from block import Block
9+
from transaction import Transaction
10+
from wallet import Wallet
11+
from node import Node
12+
13+
"""
14+
Lq je reçois une transaction je dois la validera avant de l'enregister dans mon block.
15+
Lq je créé une transaction, c'est différent.
16+
"""
17+
18+
"""
19+
Our Blockchain class is responsible for managing the chain. It will store transactions and have some helper methods for adding new blocks to the chain.
20+
"""
21+
22+
MINING_SENDER = "THE BLOCKCHAIN"
23+
24+
25+
class Blockchain():
26+
27+
def __init__(self):
28+
self.current_transactions = []
29+
self.chain = []
30+
self.nodes = set()
31+
32+
# Create the genesis block
33+
self.new_block(100, '1')
34+
35+
def register_node(self, node):
36+
"""
37+
Add a new node to the list of nodes.
38+
"""
39+
if not isinstance(node, Node):
40+
raise ValueError('node parameter should be a Node instance.')
41+
42+
self.nodes.add(node)
43+
44+
@property
45+
def last_block(self):
46+
return self.chain[-1]
47+
48+
def submit_transaction(self, transaction, signature):
49+
"""
50+
Add a transaction to transactions array if the signature verified
51+
Return index of block that the transaction will be.
52+
"""
53+
if not isinstance(transaction, Transaction):
54+
raise ValueError(
55+
'transaction parameter should be a Transaction instance.')
56+
57+
transaction_verification = transaction.verify_signature(signature)
58+
59+
if transaction_verification:
60+
self.current_transactions.append(transaction)
61+
return len(self.chain) + 1
62+
63+
return False
64+
65+
def new_block(self, nonce, previous_hash):
66+
"""
67+
Create a new Block in the Blockchain
68+
:param nonce: The nonce given by the Proof of Work algorithm
69+
:param previous_hash: Hash of previous Block
70+
:return: New Block
71+
"""
72+
73+
# Why we have this OR condition? Seems useless.
74+
block = Block(nonce, self.current_transactions, len(self.chain) +
75+
1, previous_hash or Block.hash(self.chain[-1]))
76+
77+
# Reset the current list of transactions
78+
self.current_transactions = []
79+
80+
self.chain.append(block)
81+
return block
82+
83+
def valid_chain(self, chain):
84+
"""
85+
Determine if a given blockchain is valid
86+
:param chain: A blockchain
87+
:return: True if valid, False if not
88+
"""
89+
90+
last_block = chain[0]
91+
92+
current_index = 1
93+
lenChain = len(chain)
94+
95+
while current_index < lenChain:
96+
current_block = chain[current_index]
97+
98+
# Check with last_block & current_block
99+
100+
print(f'{last_block}')
101+
print(f'{current_block}')
102+
print("\n-----------\n")
103+
104+
# Check that the hash of the block is correct
105+
last_block_hash = Block.hash(last_block)
106+
if current_block['previous_hash'] != last_block_hash:
107+
return False
108+
109+
# Check that the Proof of Work is correct
110+
if not Block.valid_proof(last_block['proof'], current_block['proof'], last_block_hash):
111+
return False
112+
113+
last_block = current_block
114+
current_index += 1
115+
116+
return True
117+
118+
def mine(self):
119+
"""
120+
Take the last Block, mine it and add it to the Blockchain.
121+
"""
122+
# We run the proof of work algorithm to get the next proof...
123+
last_block = self.last_block
124+
125+
nonce = Block.proof_of_work(last_block)
126+
127+
# @TODO
128+
# We must receive a reward for finding the proof.
129+
# The sender is "0" to signify that this node has mined a new coin.
130+
# blockchain.new_transaction(
131+
# sender=MINING_SENDER,
132+
# recipient=node_identifier,
133+
# amount=1,
134+
# )
135+
136+
# Forge the new Block by adding it to the chain
137+
previous_hash = Block.hash(last_block)
138+
block = self.new_block(nonce, previous_hash)
139+
140+
response = {
141+
'message': "New Block Forged",
142+
'index': block.index,
143+
'transactions': block.transactions,
144+
'nonce': block.nonce,
145+
'previous_hash': block.previous_hash,
146+
}
147+
148+
return response

test_blockchain.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from blockchain import Blockchain
2+
from wallet import Wallet
3+
from client import Client
4+
5+
blockchain = Blockchain()
6+
7+
wallet = Wallet()
8+
guy_wallet = Wallet(1024, True)
9+
10+
11+
def test_submit_transaction():
12+
transaction, signature = Client.generate_transaction(
13+
wallet, guy_wallet.address, 10)
14+
15+
# don't forget genesis block
16+
assert len(blockchain.current_transactions) == 0
17+
blockchain.submit_transaction(transaction, signature)
18+
assert len(blockchain.chain) == 1
19+
20+
21+
def test_mine():
22+
for i in range(10):
23+
transaction, signature = Client.generate_transaction(
24+
wallet, guy_wallet.address, 10)
25+
blockchain.submit_transaction(transaction, signature)
26+
27+
print(blockchain.mine())

0 commit comments

Comments
 (0)