DPOS 共识算法实现

This commit is contained in:
myh 2024-05-29 18:34:06 +08:00
parent 00fcf3962c
commit 8379de4870

163
DPOS/blockChain.py Normal file
View 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