python区块链简单模拟【05】

这篇具有很好参考价值的文章主要介绍了python区块链简单模拟【05】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

新增内容:构建去中心化网络

import socket      #套接字,利用三元组【ip地址,协议,端口】可以进行网络间通信
import threading   #线程
import pickle

# 定义一个全局列表保存所有节点
NODE_LIST = []


class Node(threading.Thread):  #继承与线程
    def __init__(self, name, port, host="localhost"):
        threading.Thread.__init__(self, name=name)
        self.host = host           #  服务器地址,本地电脑都设为localhost
        self.port = port           # 每个节点对应一个唯一的端口号
        self.name = name           # 唯一的节点名称
        self.wallet = Wallet()
        self.blockchain = None    # 用来存储一个区块链副本  账本
        
    def run(self):
        """
            节点运行
        """
        self.init_blockchain()    # 初始化区块链
        
        # 在指定端口进行监听
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)      #获取TCP/ip  套接字sock
        sock.bind((self.host, self.port))                             #绑定主机,端口号到套接字sock
        NODE_LIST.append({
            "name": self.name,
            "host": self.host,
            "port": self.port
        })
        
        sock.listen(10)                                            #开始TCP监听
        print(self.name, "运行中...")
        
        while True:       # 不断处理其他节点发送的请求
            connection,address = sock.accept()                    #被动接受TCP客户的连接,(阻塞式)等待连接的到来
            try:
                print(self.name, "处理请求内容...")
                self.handle_request(connection)
            except socket.timeout:  
                print('超时!')
            except Exception as e:
                print(e, )
            connection.close()
            
            
            
            
    
    def handle_request(self, connection):
        data = []
        
        while True:    # 不断读取请求数据直至读取完成
            buf = connection.recv(1024)  
            if not buf: # 若读取不到新的数据则退出
                break
            data.append(buf)
            if len(buf) < 1024:   # 若读取到的数据长度小于规定长度,说明数据读取完成,退出
                break
        t = pickle.loads(b''.join(data)) #从pickle格式的文件中读取数据并转换为Python的类型。
        print("数据接受完成,判断数据的  类 :交易,区块,初始化" )
        
        if isinstance(t, Transaction):  # 如果t是新交易类  消息
            print("处理交易请求...")
            if verify_sign(t.pubkey, str(t), t.signature):   #验证交易,公钥验证签名
                # 验证交易签名没问题,生成一个新的区块
                print(self.name, "验证交易成功")
            
                new_block = Block(transactions=[t], prev_hash="")
                print(self.name, "生成新的区块...")
                
                w = ProofOfWork(new_block, self.wallet)
                block = w.mine()                              #挖矿,挖到正确的区块哈希值,此处block就是新的区块,主要是找到了符合要求的nonce值
                print(self.name, "将新区块添加到区块链中")
                self.blockchain.add_block(block)
                
                
                print(self.name, "将新区块广播到网络中...")
                self.broadcast_new_block(block)
                
                
            else:
                print(self.name, "交易验证失败!")   #签名不对
                
        elif isinstance(t, Block):   #如果t是新区块类  消息
            print("处理新区块请求...")
            if self.verify_block(t):  
                print(self.name, "区块验证成功")  
                self.blockchain.add_block(t)
                print(self.name, "添加新区块成功")
            else:
                print(self.name, "区块验证失败!")
                
                
        else:  # 如果不是新区块消息,默认为初始化消息类型,返回本地区块链内容
            print("是我是我,我是初始化,我要返回我的区块链信息")
            connection.send(pickle.dumps(self.blockchain))
            
    def verify_block(self, block):
        """
            验证区块有效性   是否是符合难度的区块哈希值,找到了正确的nonce值
        """
        message = hashlib.sha256()
        message.update(str(block.prev_hash).encode('utf-8'))
        # 更新区块中的交易数据
        # message.update(str(self.block.data).encode('utf-8'))
        message.update(str(block.transactions).encode('utf-8'))
        message.update(str(block.timestamp).encode('utf-8'))
        message.update(str(block.nonce).encode('utf-8'))
        digest = message.hexdigest()

        prefix = '0' * DIFFICULTY
        return digest.startswith(prefix)
            
    def broadcast_new_block(self, block):
        """
            将新生成的区块广播到网络中其他节点
        """
        for node in NODE_LIST:     #遍历节点中的每一个节点,把新的区块广播给除了自己的所有节点
            host =node['host']
            port = node['port']
            
            if host == self.host and port == self.port:
                print(self.name, "忽略自身节点")
            else:
                print(self.name, "广播新区块至 %s" % (node['name']))
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect((host, port))    # 连接到网络中的节点
                sock.send(pickle.dumps(block))   # 发送新区块
                sock.close()          # 发送完成后关闭连接
                
    def init_blockchain(self):
        """
            初始化当前节点的区块链
        """
        #PER_BYTE = 1024
        if NODE_LIST:                # 若当前网络中已存在其他节点,则从第一个节点从获取区块链信息
            host = NODE_LIST[0]['host']
            port = NODE_LIST[0]['port']
            name = NODE_LIST[0]["name"]
            print(self.name, "发送初始化请求 %s" % (name))
            print("开始让节点1发送请求")
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #获取TCP/ip套接字
            sock.connect((host, port))    # 连接到网络中的第一个节点
            sock.send(pickle.dumps('INIT'))   # 发送初始化请求   pickle.dumps将Python数据转换为pickle格式的bytes字串
            print("请求成功")
            
            data = []
            print("开始接受节点1的connect返回的信息")
            while True:          # 读取区块链信息,直至完全获取后退出
                buf = sock.recv(1024)
                print("接收中")
                if not buf:
                    print("接收完毕,接空")
                    break
                
                data.append(buf)
                if len(buf) < 1024:
                    print("太短了,完毕")
                    break
            sock.close()   # 获取完成后关闭连接
            
            # 将获取的区块链信息赋值到当前节点
            self.blockchain = pickle.loads(b''.join(data))
            print(self.name, "初始化完成.")
            
        else:
            # 如果是网络中的第一个节点,初始化一个创世区块
            block = Block(transactions=[], prev_hash="")
            w = ProofOfWork(block, self.wallet)
            genesis_block = w.mine()
            self.blockchain = BlockChain()
            self.blockchain.add_block(genesis_block)
            print("生成创世区块")
    
    def submit_transaction(self, transaction):   #遍历节点中的每一个节点,把新的交易广播给除了自己的所有节点
         for node in NODE_LIST:
            host =node['host']
            port = node['port']
            
            if host == self.host and port == self.port:
                print(self.name, "忽略自身节点")
            else:
                print(self.name, "广播新区块至 %s:%s" % (self.host, self.port))
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
                sock.connect((node["host"], node["port"]))  
                sock.send(pickle.dumps(transaction)) 
                sock.close()

        
    def get_balance(self):
        balance = 0
        for block in self.blockchain.blocks:
            for t in block.transactions:
                if t.sender == self.wallet.address.decode():
                    balance -= t.amount
                elif t.recipient == self.wallet.address.decode():
                    balance += t.amount
        print("当前拥有%.1f个加密货币" % (balance))
    
    def print_blockchain(self):
        print("区块链包含区块个数: %d\n" % len(self.blockchain.blocks))
        for block in self.blockchain.blocks:
            print("上个区块哈希:%s" % block.prev_hash)
            print("区块内容:%s" % block.transactions)
            print("区块哈希:%s" % block.hash)
            print("\n") 
# 初始化节点1

node1 = Node("节点1", 8000)
node1.start()   #启动线程  调用 start() 方法是用来启动线程的,轮到该线程执行时,会自动调用 run();直接调用 run() 方法
node1.print_blockchain()  #输出区块信息

python区块链简单模拟【05】,区块链模拟,python,区块链,php

node2 = Node("节点2", 8001)
node2.start() 
node2.print_blockchain()

python区块链简单模拟【05】,区块链模拟,python,区块链,php

node1.get_balance()
node2.get_balance()

python区块链简单模拟【05】,区块链模拟,python,区块链,php

#创建交易
new_transaction = Transaction(
    sender=node1.wallet.address,
    recipient=node2.wallet.address,
    amount=0.3
)
sig = node1.wallet.sign(str(new_transaction))  #私钥签名
new_transaction.set_sign(sig, node1.wallet.pubkey)#发送公钥,和签名,给验证者验证
node1.submit_transaction(new_transaction)    #广播交易

python区块链简单模拟【05】,区块链模拟,python,区块链,phpnode1.print_blockchain()

node2.print_blockchain()

python区块链简单模拟【05】,区块链模拟,python,区块链,php

node1.get_balance()
node2.get_balance()

python区块链简单模拟【05】,区块链模拟,python,区块链,php文章来源地址https://www.toymoban.com/news/detail-768088.html

到了这里,关于python区块链简单模拟【05】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python实现简单的区块链

    运用datetime和hashlib模拟实现区块链 区块函数 包含区块高度标识:blockNo 交易数据:data nonce值 preious_hash:上一个区块哈希 timestamp:当前时间 链函数 分别包括三个方法,添加块的方法、挖矿功能、以及打包交易 添加块的方法: 挖矿功能(采用的是工作量证明共识机制) 打包交

    2024年02月06日
    浏览(29)
  • 用python搭建简单的区块链

    以下是使用Python编写简单的区块链的步骤: 安装需要的库 创建区块链的类 创建创世块和区块的添加方法 创建Flask Web应用程序 运行应用程序并测试 运行应用程序: 使用POST请求创建新的交易: 使用GET请求获取完整的区块链: 使用GET请求挖掘新的区块: 以上就是使用Python编

    2024年04月26日
    浏览(22)
  • 【Python】实现一个简单的区块链系统

    本文章利用 Python 实现一个简单的功能较为完善的区块链系统(包括区块链结构、账户、钱包、转账),采用的共识机制是 POW。 Block.py  BlockChain.py  测试结果  将工作量证明加入到 Block.py 中 测试结果 更新 BlockChain.py  测试结果  实现钱包、账户、交易功能要先安装非对称加

    2024年02月11日
    浏览(33)
  • 区块链实战:用python编写最简单的比特币区块链本地测试框架

    比特币本身并不是特别复杂,中本聪的白皮书只有十页左右。 可从该链接下载(有各种语言版本):Bitcoin: A Peer-to-Peer Electronic Cash System 但是,真正投入使用的比特币系统实际上非常复杂,包含诸多因素,涉及诸多细节,甚至对一个手续费机制研究几天还云里雾里。 如何有效地

    2024年02月05日
    浏览(35)
  • 用Python简单模拟《原神》抽卡系统

    欢迎 这是我第一次发布文章,就爱闲的没事整点活玩,写的不好还请见谅 使用的语言是Python,因为实在是太方便了o(TヘTo) 对了,要是懒得看代码思想直接跳到完整代码就彳亍 想必大家都听说过原神吧,是米哈游开发的大世界探索游戏。大学一放假就太闲了,于是就用pytho

    2024年02月06日
    浏览(34)
  • 使用python搭建简单的区块链,并实现数据上链

    目录 一、引入库文件 二、编写消息类 三、编写区块类 四、编写区块链 五、编写主函数 六、运行 引入所需的库文件,其中hashlib为核心文件。 通过编写消息类,将消息读入并进行哈希运算,与前面的消息进行连接等操作。 通过编写区块类,使用前一区块的哈希值与时间戳等

    2024年02月12日
    浏览(30)
  • IIS perl python cbrother php脚本语言配置及简单测试样例程序

    上篇笔记写了 IIS 配置 CGI, IIS CGI配置和CGI程序FreeBasic, VB6, VC 简单样例_Mongnewer的博客-CSDN博客 这篇在IIS上配置一些脚本语言。为了操作方便,每种语言在站点下分设文件夹。 1. IIS perl配置 Perl CGI方式是曾经流行的做法。先下载一个开源的 Perl.exe 解释器,在免费的 sambar 服务器

    2024年02月09日
    浏览(34)
  • 区块链学习(Fisco搭建)【Day04-05,09】

    搭建进度 搭建区块链网络 一、搭建单群组 FISCO BCOS 联盟链 1.安装依赖 2.创建操作目录, 下载安装脚本 3.搭建单群组4节点联盟链 4.启动FISCO BCOS链 5.检查进程 6.检查日志输出  二、配置及使用控制台 1.安装Java 2.安装maven(可以跳过) 3.下载共享库 native library(可以跳过) 4. 获

    2024年02月05日
    浏览(44)
  • 分布式技术原理与实战45讲--05 第05讲:共识问题:区块链如何确认记账权?

    本课时我们主要讲解“共识问题:区块链如何确认记账权?” 区块链可以说是最近几年最热的技术领域之一,区块链起源于中本聪的比特币,作为比特币的底层技术,本质上是一个去中心化的数据库,其特点是 去中心化、 公开透明,作为分布式账本技术,每个节点都可以参

    2024年02月03日
    浏览(32)
  • 网络协议与攻击模拟-05-ICMP协议

    1、理解 ICMP 协议 2、理解 ICMP 重定向 3、会使用 wireshark 分析 ICMP 重定向流量实验 1、 ICMP 协议 Internet 控制报文协议,用于在 IP 主机、路由器之间传递控制消息,控制消息指网络通不通、主机是否可达、路由是否可用等等. ICMP 是属于网络层的协议,封装在传输层与网络层之间

    2024年02月03日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包