加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
myblockchian_anchor.py 11.86 KB
一键复制 编辑 原始数据 按行查看 历史
卢昊骋 提交于 2023-10-29 19:49 . supports multiple peers
import hashlib
import time
import json
import requests
import signal
import threading
import socket
import random
import multiprocessing
from urllib.parse import urlparse
listenflag = True
# a block contains the index, timestamp, tx, prev hash, hash and nonce
# now the block doesn't support the minning function, it will just continuously output the block
class Block:
def __init__(self, index, timestamp, tx, PrevHash, nonce, hash):
self.index = index
self.timestamp = timestamp
self.tx = tx
self.PrevHash = PrevHash
if(nonce!=-1):
self.nonce = nonce
else:
self.nonce = random.randint(0,65535)
if(hash!=0):
self.hash = hash
else:
self.hash = self.CalculateHash()
# this func helps to generate the previous block's hash
def CalculateHash(self):
data = str(self.index) + str(self.timestamp) + str(self.PrevHash) + str(self.tx) + str(self.nonce)
return hashlib.sha256(data.encode()).hexdigest()
# this func will help convert the block to the json type
def to_dict(self):
return {
'index': self.index,
'timestamp' : self.timestamp,
'tx' : self.tx,
'previous_hash' : self.PrevHash,
'nonce' : self.nonce,
'hash' : self.hash
}
# the blockchain helps remain the whole chain where all the block exists
# every next block will have the previous block's hash which called the PrevHash
# now it will contains the whole blockchain and a set of nodes
class Blockchain:
def __init__(self):
self.chain = [self.CreateGenesisBlock()]
# func CreateGenesisBlock will create the genesis block whose index is 0 and the tx is "The Genesis Block"
def CreateGenesisBlock(self):
block = Block(0, time.time(), "The Genesis Block", 0, -1, 0)
return block
# func Check will check whether this block is valid
def CheckTheNewestBlock(self, Block):
LastIndex = self.GetLatestBlock().index
if Block.index > LastIndex:
if(Block.index - LastIndex == 1):
if self.chain[LastIndex].hash == Block.PrevHash:
return 1
else:
return 0
elif Block.index - LastIndex == 0:
self.chain[LastIndex] = Block
return 2
else:
return 4
else:
return 3
def CheckTheBlock(self, Block):
if Block.index == 0:
self.chain.append(Block)
return 1
LastIndex = self.GetLatestBlock().index
if Block.index <= LastIndex:
if(Block.PrevHash == self.chain[Block.index-1].hash):
self.chain[Block.index] = Block
return 1
else:
return 0
elif Block.index == LastIndex + 1:
if Block.PrevHash == self.chain[LastIndex].hash:
self.chain.append(Block)
return 1
else:
return 0
else:
return 0
# func AddBlock will first check if this new block is valid
# and then insert this new block to the end of the chain
def AddBlock(self, Block):
self.chain.append(Block)
# func GetLatestBlock will return the latest block
def GetLatestBlock(self):
return self.chain[-1]
# this func is just for test, it will print the latest block
def PrintLatestBlock(self):
block = self.GetLatestBlock()
print("Block:{}\n\ttimestamp:{}\n\ttx:{}\n\tPrevHash:{}\n\tHash:{}\n\tNonce:{}\n\t".format(block.index, block.timestamp, block.tx, block.PrevHash, block.hash, block.nonce))
# here is the struct Peer
# Peer acts as a node which maintains the network and send the messages
# As the anchor peer, it should
class Peer:
def __init__(self, host, port):
self.host = host
self.port = port
self.status = 0
self.MaxIndex = -1
self.blockchain = Blockchain()
ip = {
'host' : self.host,
'port' : self.port
}
self.peers = [ip]
self.transaction = []
def start_listening(self):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((self.host, self.port))
server_socket.listen(5)
while listenflag:
client_socket, address = server_socket.accept()
print(f"Accepted connection from {address[0]}:{address[1]}")
client_thread = threading.Thread(target=self.handle_connection, args=(client_socket,))
client_thread.start()
def handle_connection(self, client_socket):
while listenflag:
data = client_socket.recv(1024).decode()
if data:
print(f"Received message: {data}")
message = json.loads(data)
self.process_message(message)
else:
break
client_socket.close()
def send_message(self, host, port, message):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
again = True
while again:
again = False
try:
client_socket.connect((host, port))
except OSError as e:
again = True
finally:
continue
MessageToSend = json.dumps(message)
client_socket.send(MessageToSend.encode())
client_socket.close()
def process_message(self, message):
command = message.get('command')
# handle the command: add block
if command == 'add_block' and self.status==1:
block_data = message.get('block')
block = Block(block_data['index'], block_data['timestamp'],
block_data['tx'], block_data['previous_hash'], block_data['nonce'], block_data['hash'])
ip = message.get('ip')
host = ip['host']
port = ip['port']
x = self.blockchain.CheckTheNewestBlock(block)
if x==1:
self.MaxIndex = block.index
self.blockchain.AddBlock(block)
self.broadcast_block(block)
self.blockchain.PrintLatestBlock()
elif x==2:
self.broadcast_block(block)
elif x==3:
print("the chain is outdated, please check it!")
elif x==4:
self.status = 2
self.MaxIndex = block.index
message = {
'command' : 'AskForSynchronization',
'index' : 0,
'ip' : {
'host' : self.host,
'port' : self.port
}
}
self.send_message(host, port, message)
# handle the command: add transaction
elif command == 'add_transaction':
transaction = message.get('transaction')
self.transaction.append(transaction)
print("Added transaction to pending list:", transaction)
# handle the command: initialize
elif command == 'initialize':
ip = message.get('ip')
self.initalize(ip)
# handle the command: Get the max index
elif command == "AskForMaxIndex":
ip = message.get('ip')
host = ip['host']
port = ip['port']
MaxIndex = self.blockchain.GetLatestBlock().index
message = {
'command' : 'TheMaxIndex',
'index' : MaxIndex
}
self.send_message(host, port, message)
# synchronization command gives the index which wants to get the corresponding block
elif command == "AskForSynchronization":
index = message.get('index')
ip = message.get('ip')
host = ip['host']
port = ip['port']
block = self.blockchain.chain[index]
message = {
'command' : 'SynchronizationBlock',
'block' : block.to_dict(),
'ip' : {
'host' : self.host,
'port' : self.port
}
}
self.send_message(host, port, message)
elif command == "SynchronizationIP":
IPs = message.get('peers')
self.peers = IPs
# get the block
elif command == "SynchronizationBlock":
block_data = message.get('block')
block = Block(block_data['index'], block_data['timestamp'],block_data['tx'], block_data['previous_hash'], block_data['nonce'], block_data['hash'])
ip = message.get('ip')
host = ip['host']
port = ip['port']
x = self.blockchain.CheckTheBlock(block)
if x==0:
# restart to ask for synchronization
self.MaxIndex = 0
self.status = 0
return
else:
if self.blockchain.GetLatestBlock().index == self.MaxIndex:
self.status = 1
return
else:
message = {
'command' : 'AskForSynchronization',
'ip' : {
'host' : self.host,
'port' : self.port
},
'index' : block.index+1
}
self.send_message(host, port, message)
def initalize(self, ip):
host = ip['host']
port = ip['port']
# first give the ip to all other peers
message = {
'command' : 'addIP',
'ip' : {
'host' : host,
'port' : port
}
}
for peer in self.peers:
PeerHost = peer['host']
PeerPort = peer['port']
if PeerPort==12500:
continue
self.send_message(PeerHost, PeerPort, message)
# then give the IP all the peers
message = {
'command' : 'SynchronizationIP',
'peers' : self.peers
}
self.send_message(host, port, message)
self.peers.append({'host' : host, 'port' : port})
def broadcast_block(self, block):
message = {
'command': 'add_block',
'block': block.to_dict(),
'ip' : {
'host' : self.host,
'port' : self.port
}
}
for peer in self.peers:
if peer['port'] == 12500:
continue
self.send_message(peer['host'], peer['port'], message)
def GenerateBlock(self):
if len(self.transaction) != 0:
block = Block(self.blockchain.GetLatestBlock().index +1, time.time(), self.transaction.pop(0), self.blockchain.GetLatestBlock().hash, -1, 0)
self.blockchain.AddBlock(block)
self.blockchain.PrintLatestBlock()
self.broadcast_block(block)
def send_transaction(self, transaction):
message = {
'command': 'add_transaction',
'transaction': transaction
}
for peer in self.peers:
if peer['port'] == 12500:
continue
self.send_message(peer['host'], peer['port'], message)
def CreateTx(self):
a = 0
while a < 10:
data = "Tx" + str(a)
a+=1
self.transaction.append(data)
def start(self):
listener_thread = threading.Thread(target=self.start_listening)
listener_thread.start()
time.sleep(10)
if(self.port==12500):
CreateThread = threading.Thread(target=self.CreateTx)
CreateThread.start()
while listenflag:
self.GenerateBlock()
time.sleep(3)
def SignalHandler(sig, frame):
global listenflag
listenflag = False
signal.signal(signal.SIGINT, SignalHandler)
peer = Peer('127.0.0.1', 12500)
peer.start()
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化