DPOS 共识算法实现
This commit is contained in:
parent
00fcf3962c
commit
8379de4870
163
DPOS/blockChain.py
Normal file
163
DPOS/blockChain.py
Normal file
@ -0,0 +1,163 @@
|
||||
# Implementation of a simple decentralized blockchain class with multiple nodes and DPoS consensus in the network
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlparse
|
||||
import requests
|
||||
from random import randint
|
||||
|
||||
|
||||
# Blockchain class
|
||||
class Blockchain(object):
|
||||
|
||||
# Constructor which creates lists to store the blockchain and the transactions
|
||||
def __init__(self):
|
||||
|
||||
# List to store the blockchain
|
||||
self.chain = []
|
||||
|
||||
# List to store the unverified transactions
|
||||
self.unverified_transactions = []
|
||||
|
||||
# List to store verified transactions
|
||||
self.verified_transactions = []
|
||||
|
||||
# Genesis block
|
||||
self.new_block(previous_hash=1)
|
||||
|
||||
# Set containing the nodes in the network. Used set here to prevent the same node getting added again.
|
||||
self.nodes = set()
|
||||
|
||||
# List containing all the nodes along with their stake in the network
|
||||
self.all_nodes = []
|
||||
|
||||
# List of all the voting nodes in the network
|
||||
self.voteNodespool = []
|
||||
|
||||
# List which stores all the nodes in descending order of votes received
|
||||
self.starNodespool = []
|
||||
|
||||
# List to store the top 3 nodes with the highest (stake * votes_received)
|
||||
self.superNodespool = []
|
||||
|
||||
# List to store the address of the delegate nodes selected for mining process
|
||||
self.delegates = []
|
||||
|
||||
# Method to create a new block in the Blockchain
|
||||
def new_block(self, previous_hash=None):
|
||||
block = {
|
||||
'index': len(self.chain) + 1,
|
||||
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'transactions': self.unverified_transactions,
|
||||
'previous_hash': previous_hash or self.hash(self.chain[-1])
|
||||
}
|
||||
self.verified_transactions += self.unverified_transactions
|
||||
print(self.verified_transactions)
|
||||
self.unverified_transactions = []
|
||||
|
||||
# appending the block at the end of the blockchain
|
||||
self.chain.append(block)
|
||||
return block
|
||||
|
||||
# Method to add a new transaction in the next block
|
||||
def new_transaction(self, sender, item_name, bill_amount):
|
||||
self.unverified_transactions.append({
|
||||
'Customer name': sender,
|
||||
'Recipient': "Dexter's Coffee Shop",
|
||||
'Item name': item_name,
|
||||
'Total billing amount': bill_amount,
|
||||
'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
})
|
||||
return self.last_block['index'] + 1
|
||||
|
||||
@property
|
||||
def last_block(self):
|
||||
return self.chain[-1]
|
||||
|
||||
# Static method to create an SHA-256 Hash of a given block
|
||||
@staticmethod
|
||||
def hash(block):
|
||||
block_string = json.dumps(block, sort_keys=True).encode()
|
||||
hash_val = hashlib.sha256(block_string).hexdigest()
|
||||
return hash_val
|
||||
|
||||
# Method to add node using its IP address to our Blockchain network.
|
||||
def add_node(self, address, stake):
|
||||
parsed_url = urlparse(address)
|
||||
authority = stake
|
||||
self.nodes.add((parsed_url.netloc, authority))
|
||||
|
||||
# Method to simulate the voting process
|
||||
def add_vote(self):
|
||||
self.all_nodes = list(self.nodes)
|
||||
|
||||
for x in self.all_nodes:
|
||||
y = list(x)
|
||||
y.append(x[1] * randint(0, 100))
|
||||
self.voteNodespool.append(y)
|
||||
|
||||
print(self.voteNodespool)
|
||||
|
||||
# Method to select top three nodes based on voting results
|
||||
def selection(self):
|
||||
self.starNodespool = sorted(self.voteNodespool, key=lambda vote: vote[2], reverse=True)
|
||||
print(self.starNodespool)
|
||||
|
||||
for x in range(3):
|
||||
self.superNodespool.append(self.starNodespool[x])
|
||||
print(self.superNodespool)
|
||||
|
||||
for y in self.superNodespool:
|
||||
self.delegates.append(y[0])
|
||||
print(self.delegates)
|
||||
|
||||
# Method to sync the list
|
||||
def sync(self):
|
||||
r = requests.get('http://localhost:5000/delegates/show')
|
||||
print(r)
|
||||
|
||||
if r.status_code == 200:
|
||||
delegates = r.json()['node_delegates']
|
||||
self.delegates = delegates[0:3]
|
||||
print(self.delegates)
|
||||
|
||||
# Method to check if the chain is validated.
|
||||
def valid_chain(self, chain):
|
||||
last_block = chain[0]
|
||||
current_index = 1
|
||||
|
||||
while current_index < len(chain):
|
||||
block = chain[current_index]
|
||||
|
||||
# If the hash value of the current block isn't correct then return false
|
||||
if block['previous_hash'] != self.hash(last_block):
|
||||
return False
|
||||
|
||||
last_block = block
|
||||
current_index += 1
|
||||
|
||||
return True
|
||||
|
||||
# Method to replace the blockchain with the longest validated chain in the network.
|
||||
def resolve_chain(self):
|
||||
neighbours = self.nodes
|
||||
new_chain = None
|
||||
max_length = len(self.chain)
|
||||
|
||||
for node in neighbours:
|
||||
response = requests.get(f'http://{node}/chain')
|
||||
|
||||
if response.status_code == 200:
|
||||
length = response.json()['length']
|
||||
chain = response.json()['chain']
|
||||
|
||||
if length > max_length and self.valid_chain(chain):
|
||||
max_length = length
|
||||
new_chain = chain
|
||||
|
||||
if new_chain:
|
||||
self.chain = new_chain
|
||||
return True
|
||||
|
||||
return False
|
Loading…
Reference in New Issue
Block a user