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