区块链技术原理考试内容

一.简答题

第一题 .

请简单说明区块头与区块体分别保存哪些内容?

区块头:

  • 1.引用父区块哈希值的数据:这组元数据用于该区块与区块链中前一区块相连接
  • 2. 默克尔(Merkle)根哈希:是一个哈希值,由多个交易的哈希值按照一定的算法计算出来,用于验证区块体中包含的所有交易的有效性
  • 3. 区块难度:与挖矿过程有关,用于确保区块的创建速度,目标值越小,矿工创建区块的难度越
  • 4. 随机数:也称为 nonce 值,用于挖矿过程中的计算,如果符合难度目标,则表示这个区块被创建成功
  • 5. 时间戳:表示区块被创建的时间,通常采用 Unix 时间戳格式
  • 6. 版本号:表示区块链协议的版本

区块体:

在一定时间内所生成的详细数据,包括当前区块经过验证的、区块创建过程中生成的交易记录,交易数量和其他相关信息。相较于区块头,区块体主要用于原始数据的存放,占据了区块的大部分信息。

第二题.

请用图文结合的方式描述,单节点区块链系统的各模块组成及功能

构建区块链系统包括账户功能,账本功能,点对点(P2p)通信功能以及共识算法功能

  • 开发包括具体模型,具体包括区块链中的交易模型(Transaction)、区块链中的区块模型(Block)、区块链网络模型(Network)、区块链账本模型(Blockchain)、数据通信的消息模型(message)、区块链中的节点模型(Peer).
  • 预定义功能开发涉及的加密算法以及实体。其中加密算法包括账户创建以及数据签名与验证等功能、哈希加密算法功能、默克尔根计算等,创建实体包括预定义的节点、网络以及区块链账本。
  • 开发具体包括账户、账本、P2p通信以及共识算法等功能
  • 开发系统入口模块,功能包括启动节点通信、共识算法等定时器以及可供HTTP访问接口。

思维导图:

第三题

请以图文的方式描述,单节点区块链系统项目开发中相关Python文件的作用(models.py,crypto_utils.py,utils.py)

在单节点区块链系统项目开发中,通常使用Python来实现各种功能

1.models.py

  • 作用:在区块链系统中,模型文件负责定义区块、交易和其他数据结构。models.py 文件定义了不同实体的数据结构,并提供了对它们进行操作的方法。
  • import hashlib
    from datetime import datetime
    from crypto_utils import data_sign,sha256d
    import binascii
    INITIAL_BITS=0x1e777777  #此配置为模块真实区块的数据设置(预留)
    #预设一个私钥,用于创建创世区块使用
    d_pk="""-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIClncSpsc2Fua3ljeiR2aCNydSFkbXQoQHAleGZl
    YiZqoAcGBSuBBAAK\noUQDQgAEyTx/sAlhdNUOwcfnCjOVp9fxMF6DUwSLKFqj2E6sDFuPVrKF9wVWH8J3\nntxWh+kR3GFKcB48v3eTfElUs5L7Zw==\n
    -----END EC PRTVATE KEY -----\n
    """
    class Transaction (object):
        def __init__(self,sender,recipient,data,timestamp,private_key,):
         """
         交易初始化
         :param sender:发送者的地址
         :param recipient:接收者的地址
         :param data:交易的内容
         :param timestamp:交易的时间戳
         :param private_key:发送者的私钥
         """
         self.sender = sender
         self.recipient=recipient
         self.data = data
         self.timestamp = timestamp
         #生成交易的哈希值
         self.id=sha256d(self.to_string())
         #生成签名
         self.sig = data_sign(self.id,private_key)
    
        def to_string(self):
           """
           将交易元素拼接为一个字符串
           :return:
           """
           return f"{self.sender}{self.recipient}{self.data}"  f"{self.timestamp.strftime('%Y/%m/%d %H:%M:%S')}"
    
        def to_json(self):
           """
           将交易转换变为一个DICT对象
           :return:
           """
           return {
              "id":self.id,
              "sender":self.sender,
              "recipient":self.recipient,
              "data":self.data,
              "timestamp":self.timestamp.strftime('%Y/%m/%d %H:%M:%S'),
              "sig":binascii.hexlify(self.sig).decode(),         
           }
    
    #区块对象
    class Block(object):
        def __init__(self, index, prev_hash, data, timestamp, bits):
            """
            区块的初始化方法,在创建一个区块需传入包括索引号等相关信息
            :param index: 区块索引号
            :param prev_hash: 前一区块的哈希值
            :param data: 区块中需保存的记录
            :param timestamp: 区块生成的时间戳
            :param bits: 区块需传入的比特值(预留)
            """
            self.index = index
            self.prev_hash = prev_hash
            self.data = data
            self.timestamp = timestamp
            self.bits = bits
            self.nonce = 0
            #计算新区块的默克尔根
            self.merkle_root=self.calc_merkle_root()
            #计算区块哈希值
            self.block_hash=self.calc_block_hash()
        def to_json(self):
            """
            将区块内容以JSON的形式输出
            :return:
            """
            tx_list = [tx.to_json() for tx in self.data]
            # tx_json = json.dumps(tx_list, indent=3)
            return {
                "index": self.index,
                "prev_hash": self.prev_hash,
                "merkle_root": self.merkle_root,
                "data": tx_list,
                "timestamp": self.timestamp.strftime('%Y/%m/%d %H:%M:%S'),
                'bits': hex(self.bits)[2:].rjust(8, "0"),
                'nonce': hex(self.nonce)[2:].rjust(8, "0"),
                'block_hash': self.block_hash
            }
    
        def calc_merkle_root(self):
            """
            计算默克树的根(Merkle Root)
            :return:
            """
            calc_txs = [tx.id for tx in self.data]
            if len(calc_txs) == 1:
                return calc_txs[0]
            while len(calc_txs) > 1:
                if len(calc_txs) % 2 == 1:
                    calc_txs.append(calc_txs[-1])
                sub_hash_roots = []
                for i in range(0, len(calc_txs), 2):
                    join_str = "".join(calc_txs[i:i+2])
                    sub_hash_roots.append(hashlib.sha256(join_str.encode()).hexdigest())
                calc_txs = sub_hash_roots
            return calc_txs[0]
        def calc_block_hash(self):
            """
            生成区块对应的哈希值
            :return:
            """
            blockheader = str(self.index) + str(self.prev_hash) \
                          + str(self.data) + str(self.timestamp) + \
                          hex(self.bits)[2:] + str(self.nonce)
            h = hashlib.sha256(blockheader.encode()).hexdigest()
            self.block_hash = h
            return h
    # 区块链对象,包括一个以chain为对象的数组
    class Blockchain(object):
        def __init__(self):
            """
            初始化区块链对象,操作包括:
            1、定义一个以chain命名的区块链数组
            2、在链中加入创世区块(genesis block)
            """
            self.chain = []
            self.create_genesis_block()
    
        def add_block(self, block):
            self.chain.append(block)
    
        def query_block_info(self, index=0):
            """
            通过索引值查询区块链chain中的区块信息
            """
            block_json = self.chain[index].to_json()
            return block_json
    
        def create_genesis_block(self):
            """
            创建创世区块
            """
            tx = Transaction("0" * 32, "0" * 32, "第一笔交易", datetime.now(), d_pk)
            genesis_block = Block(0,
                                  "0" * 64,
                                  [tx],
                                  datetime.now(),
                                  INITIAL_BITS)
            self.add_block(genesis_block)
    
        def add_new_block(self, data):
            last_block = self.chain[-1]
            block = Block(last_block.index + 1,
                          last_block.block_hash,
                          data,
                          datetime.now(),
                          last_block.bits)
            self.chain.append(block)
            return last_block.index + 1
    
    
    # 模拟的节点
    class Peer:
        def __init__(self):
            self.tx_pool = []
    
        def add_tx(self, tx):
            self.tx_pool.append(tx)
    
        def clear_pool(self):
            self.tx_pool = []
       

    crypto_utils.py 文件

  • 作用:在区块链系统中,加密工具文件负责实现各种加密相关功能,例如生成密钥对、签名和验签等。crypto_utils.py 文件定义了加密所需的函数与方法。
  • #账户公钥和私钥的生成方式
    import ecdsa
    import random
    import hashlib
    import base58
    from hashlib import sha256
    def create_seed():
        """
        创建绝对随机的种子
        :return: string绝对随机数
        :return:随机数
        """
        return ''.join(random.sample('abcdefghijklmnopqrstuvwxyz!@#$%^&*()',32)).encode()
        
    def create_private_key(seed):
        """
        使用种子创建密钥
        :param seed:创建私钥需要的随机数
        :return :以pem形式保存的私钥
        """
        return ecdsa.SigningKey.from_string(seed,curve=ecdsa.SECP256k1).to_pem()
    
    def create_public_key(private_key):
        """
        使用私钥生成公钥
        :param private_key:生成公钥需要的私钥
        :return:以pem形式保存的公钥
        """
        return ecdsa.SigningKey.from_pem(private_key).verifying_key.to_pem()
    
    def sha256d(string):
        """
        双重 SHA-256 哈希计算
        将字符串转为哈希值
        :param string: 需要计算的字符串(bytes 或 str 类型)
        :return: 计算结果的 16 进制字符串形式
    
        """
        if not isinstance(string, bytes):
            string = string.encode()
    
        return sha256 (sha256(string).digest()).hexdigest()
    #地址生成的具体过程如下:
    # 1.利用SHA-256将公开的密钥进行哈希处理生成哈希值
    # 2.将第一步中的哈希值通过RT\IPEMD-160进行哈希处理后生成哈希值
    # 3.将第二步中的哈希值记性Base58编码
    def create_account():
        """
        创建区块链用户地址
        1.如果代码存在飘红内容,将鼠标移动到飘红点,查看问题,一般性为变量命名错误,或者是包未引入,修改
        2.如果存在base58这个包无法解析,解决方法为:pip install base58
        """ 
        new_seed = create_seed()
        private_key_pem =create_private_key(new_seed)
        public_key_pem = create_public_key(private_key_pem)
        in_public_key = ecdsa.VerifyingKey.from_pem(public_key_pem).to_string()
        intermediate =hashlib.sha256(in_public_key).digest()  #中间哈希值
        #作二次hash生成double_hash
        ripemd160=hashlib.new('ripemd160')
        ripemd160.update(intermediate)
        hash160 = ripemd160.digest()
        double_hash = hashlib.sha256(hashlib.sha256(hash160).digest()).digest()
        #取前四位,作为校验值
        checksum = double_hash[:4]
        #将中间哈希与校验值拼接
        pre_address = hash160 +checksum
        #通过base58编码生成地址
        address = base58.b58encode(pre_address)
        print(f"生成地址是:{address.decode()}")
        #将区块链账户三要素返回:adress、private_key、public_key
        return{
            "address":address.decode(),
            'private_key':private_key_pem.decode(),
            'public_key':public_key_pem.decode()
        }
    def data_sign(data, private_key):
        """
        签名
        :param data: 签名时使用的数据
        :param private_key: 签名时使用的私钥
        :return:
        """
        if not isinstance(data,bytes):
            data = data.encode()
        sk = ecdsa.SigningKey.from_pem(private_key)
        sig = sk.sign(data)
        return sig
        
    
    def data_verify(data, sig, public_key):
        """
        验证签名
        :param data: 验证时使用的数据
        :param sig: 要验证的签名
        :param public_key: 验证时使用的公钥
        :return: 验证结果,返回0表示成功,返回1表示失败,返回2表示出现问题
        """
        if not isinstance(data,bytes):
            data = data.encode()
    
        vk = ecdsa.VerifyingKey.from_pem(public_key)
        try:
            if vk.verify(sig, data):
                return 0 # 如果验证成功则返回0
            else:
                return 1 # 如果验证失败则返回1
        except Exception as e:
            return 2 # 如果验证出现问题则返回2

    utils.py 文件

  • 作用:在区块链系统的开发过程中,通用工具文件负责提供一些常用的功能和辅助方法。utils.py 文件定义了各种实用工具函数和方法。
  • from hashlib import sha256
    
    def calc_merkle_root(data):
        """
        计算默克树的根(Merkle Root)
        :return:
        """
        calc_txs = [tx.id for tx in data]
        if len(calc_txs) == 1:
            return calc_txs[0]
        while len(calc_txs) > 1:
            if len(calc_txs) % 2 == 1:
                calc_txs.append(calc_txs[-1])
            sub_hash_roots = []
            for i in range(0, len(calc_txs), 2):
                join_str = "".join(calc_txs[i:i + 2])
                sub_hash_roots.append(sha256(join_str.encode()).hexdigest())
            calc_txs = sub_hash_roots
        return calc_txs[0]

第四题.

请以图文结合的方式描述,单节点区块链系统添加区块(/add_block)的过程

第一步:当前的区块链系统只有一个节点,节点上存储着一个创世区块(Genesis Block

第二步:我们向节点发送一个 /add_block 请求,该请求是一个 GET 请求,并包含了一些交易信息。

第三步:节点将会处理这个请求。它会先从自己的交易池(Transaction Pool)中获取交易记录,然后将peer节点的交易缓存数据添加进一个新的区块中。

第四步:新的区块包含了之前缓存的交易记录,以及一些基础信息,例如前一区块的哈希值、时间戳、随机数等。当新的区块创建完毕后,节点会将新区块添加到区块链中。

第五步:节点会将交易池清空,并返回一个 JSON 格式的响应,其中包含了新区块的索引。

第五题:

请以图文结合的方式描述,单节点区块链系统添加交易(/add_transaction)的过程

第一步:当前的区块链系统只有一个节点,节点上存储着一个创世区块(Genesis Block).

第二步:我们向节点发送一个 /add_transaction 请求,该请求是一个 POST 请求,并包含了要添加的交易信息。

第三步:检查请求体是否存在那些信息,如果不存在或缺少,则返回一个空响应,如果存在则创建一个新的交易对象,将新的交易加入到交易池,并返回一个正确的响应

第六题.

请以图文结合的方式描述,单节点区块链系统区块验证(/validate_block的过程

首先,我们假设当前的区块链系统只有一个节点,节点上存储着多个区块:

现在,我们向节点发送一个 /validate_block 请求,该请求是一个 POST 请求,并包含了要验证的区块信息。

节点将会处理这个请求,它会对待验证的区块进行一系列的验证,以确保该区块是合法的。接下来,我们将会描述这些验证步骤:

1. 检查区块的哈希值是否正确

节点会首先验证该区块的哈希值是否为正确的值。这个过程可以防止区块内数据被篡改。

2. 检查区块内每一笔交易的有效性

节点会遍历该区块内的每一笔交易,验证它们的有效性,包括余额是否足够、交易签名是否正确等。如果任何一笔交易无效,整个区块都会被认为是无效的。

3. 检查区块的时间戳是否正确

节点会验证该区块的时间戳是否早于当前时间,以确保该区块是按照正确的时间顺序创建的。

4. 检查该区块是否是链上下一个区块

节点会检查该区块是否是链上下一个区块。如果该区块不是下一个区块,则认为它是无效的,因为它没有按照正确的顺序添加到链上。

5. 检查区块内的随机数是否正确

节点会验证该区块内的随机数是否满足一定的规则,以确保该区块是通过工作量证明机制生成的。

如果该区块通过了所有的验证,节点会返回一个 JSON 格式的响应,其中包含了一个 code 字段表示该区块的验证是否成功。

如果该区块被认为是无效的,则会返回一个失败的响应:

第七题.

请使用Flask框架编写最简的web服务,并实现返回"Hello World"内容的GET接口

第一步:保证在python虚拟环境中有flask框架:pip install flask

第二步:创建app.py文件,在其中加入最小应用代码(最简的web服务)

from flask import Flask

# 创建一个 Flask 应用程序实例
app = Flask(__name__)

# 定义路由和视图函数
@app.route('/')
def hello():
    return 'Hello, world!'



# 运行 Flask 应用程序
if __name__ == '__main__':
    app.run()
  1. 导入 Flask 模块。
  2. 创建 Flask 实例,并指定应用名称。
  3. 编写接口函数 index(),使用 @app.route 装饰器将其与根路径 / 关联起来。
  4. 在接口函数中返回字符串 Hello World
  5. 在 if __name__ == '__main__': 中启动应用。

第三步:在终端中执行命令

 

第四步:打开postman,以GET接口访问 http://127.0.0.1:5000/,返回值为Hello World

 

第八题.

请描述,在开发区块链系统中,区块对象(Block)一般包括哪些属性,并详细说明每个属性的作用

  1. 区块索引号(index):区块的索引号,表示该区块在整个区块链中的位置。

  2. 前一区块的哈希值(prev_hash):前一区块的哈希值,记录了上一个区块的唯一标识符,用于连接区块链中的各个区块。

  3. 区块体数据(data):区块中需要保存的记录或数据。

  4. 区块时间戳(timestamp):区块生成的时间戳,记录了区块的创建时间。

  5. 区块需传入预留的比特值(bits):预留的比特值,用于区块的扩展或其他用途。

  6. 随机数(nonce):用于挖矿过程中尝试的随机数值。

  7. 默克尔根[calc_merkle_root()]:计算区块中交易数据的默克尔根,通过对包含的交易进行哈希计算,生成一个唯一标识区块中交易数据的值。

  8. 区块自身的哈希值

第九题.

请描述,在开发区块链系统中,交易对象(Transaction)一般包括哪些属性,并详细说明每个属性的作用

1.交易发送方地址:指定交易发送者的区块链地址,用于标识交易的发送方。

2.交易接收方地址:指定交易接收者的区块链地址,用于标识交易的接收方。

3.交易发生的时间戳:记录交易创建的时间,用于确保每笔交易的时间顺序和一致性。

4.交易哈希:该属性是通过对交易数据进行哈希计算得到的唯一标识符,用于验证和识别交易的完整性。

5.交易的内容:交易的详细数据内容

6.交易的签名:使用交易发送方的私钥对交易数据进行签名后生成的内容,可以使用交易发送方的公钥验证交易的正确性。

第十题.

请描述,在开发区块链系统中,区块链网络对象(Blockchain)一般包括哪些属性,并详细说明每个属性的作用。

以区块和链概念组成的数据存储方式,并且在区块链创建时需要在其中加入创世区块(Genesis Block)。

  1. __init__:初始化方法,在创建一个区块链对象时会调用。该方法会初始化一个空的区块链数组(chain),并创建创世区块(genesis block)。

  2. add_block:将一个新的区块添加到区块链(chain)的末尾。

  3. query_block_info:通过指定索引值(index)查询区块链(chain)中的某个区块的信息,并将其转换成JSON格式返回。

  4. create_genesis_block:创建创世区块(genesis block),即第一个区块。该方法会生成一个创世区块并将其添加到区块链(chain)中。

  5. add_new_block:向区块链(chain)中添加一个新的区块。该方法首先获取当前链中最后一个区块(last_block),然后使用该区块信息创建一个新的区块(block),并将其添加到链(chain)的末尾。最后返回新区块的索引号

第十一题.

请描述,在开发区块链系统中,默克尔根(Merckle Root)的生成过程以及与区块中交易的关系

 默克尔根(Merckle Root)的生成过程:

默克尔根(Merkle Root)用于验证和确认区块中的交易数据的完整性。它是通过对区块中的交易数据进行哈希运算来生成的。

1.第一步:构建calc_merkle_Root函数,将需要打包的交易数组作为输入参数。

2.第二步:通过循环的方式将交易的哈希值两两组合

3.第三步:通过哈希处理生成新的哈希值并更新数组

4.以此方式周而复始当最终生成的数组长度为1时,将第一个元素作为默克尔根输出。

import hashlib
class MerkleTree(object):
    def __init__(self, tx_list):
        self.tx_list=tx_list
    def calc_merkle_root(self):
        """
        计算Merkle根
        """
        calc_txs=self.tx_list
        if len (calc_txs) ==1:
            #如果交易长度大于1,则直接返回交易值
            return calc_txs[0]
          #如果交易长度大于1
        while len(calc_txs) >1:
            #若列表中的交易个数为奇数个,则在列表最后一个交易信息进行补全。
            if len(calc_txs) %2==1:
                calc_txs.append(calc_txs[-1])
            sub_hash_roots = []
            #每两个交易进行组合,生成新的哈希值
            for i in range (0,len(calc_txs),2):
               # 生成的哈希值进行累加
                sub_hash_roots.append(hashlib.sha256("".join(calc_txs[i:i+2]).encode()).hexdigest())
            # 将累加为新的哈希列表赋值为下一次循环的内容
            calc_txs = sub_hash_roots
        return calc_txs[0]

# 验证
tx_list = ['1','2','3','4',"5"]
m_t = MerkleTree(tx_list)
merckle_root = m_t.calc_merkle_root();
print(merckle_root)
                

与区块中交易的关系:

默克尔根将区块中的所有交易数据形成一个哈希树的结构。树的叶子节点是每笔交易的哈希值,而内部节点是两个子节点的哈希值的组合。最终的默克尔根就是树的根节点的哈希值。

在一个区块中,默克尔根作为区块头的一部分,被包含在区块中。这个区块头还包含了其他的信息,如前一个区块的哈希值、时间戳等。默克尔根的存在使得区块链具备了安全性和可验证性。如果有人试图篡改区块中的任何一笔交易,默克尔根将会发生变化,从而使其他节点能够轻松检测到区块数据的篡改。

因此,默克尔根在区块链系统中被用于验证区块中的交易数据的完整性,确保区块链的安全性和可靠性。

第十二题

请简述采用默克尔根(Merckle Root)进行区块验证的过程.

第一步 : 将生成的默克尔根与区块头中记录的默克尔根进行比较。

第二步 : 如果两者相等,则说明区块中的交易数据没有被篡改,通过了验证,可信任并加入到区块链中。

第三步 : 如果两者不相等,说明区块中的交易数据发生了篡改,区块验证失败,该区块将被丢弃。

通过默克尔根进行区块验证的过程可以保证区块中的交易数据的完整性。如果有人试图篡改区块中的任何一笔交易,默克尔根将会发生变化,从而被其他节点轻松检测到,并拒绝接受这个被篡改的区块。这个验证过程确保了区块链系统中的数据的安全性和可信度。

第十三题.

请简述,在开发的区块链系统中进行区块验证的过程(transaction validate)。

在开发区块链系统中进行区块验证的过程主要包括交易验证和区块验证两个方面。
交易验证(Transaction Validation):


交易验证是验证单个交易的有效性。在验证过程中,通常会执行以下步骤:
验证交易的数字签名:使用发送者的公钥和交易签名,通过公开密钥加密算法(如RSA)来验证签名的有效性。
验证发送者的账户余额:检查发送者账户余额是否足够支付交易的金额。这可以通过查询账户的交易历史来计算账户的当前余额。
验证交易的合法性:检查交易中涉及的地址是否有效,检查交易的金额是否非负,检查交易的内容是否合规等。
区块验证(Block Validation):


区块验证是验证整个区块的有效性。在验证过程中,通常会执行以下步骤:
验证区块的哈希:计算区块的哈希值,并比对区块头中记录的哈希值。确保区块头中的哈希值未被篡改。
验证区块的前一个区块哈希:检查前一个区块的哈希值是否与当前区块头中的前一个区块哈希值一致,确保区块链的连续性。
验证区块中的交易:对区块中的每个交易进行交易验证,确保所有交易都是有效的。这可以包括执行交易验证的步骤,以确保每个交易都经过正确的验证。
验证区块的工作量证明(Proof of Work):根据区块头中的目标难度,验证区块的工作量证明是否有效。这可以涉及计算区块头的哈希,并检查是否满足目标难度条件。
在区块链系统中,交易验证和区块验证是保证数据的合法性和完整性的关键步骤。通过对交易和区块进行验证,可以防止无效的交易和被篡改的区块进入系统,并确保整个区块链的安全性和可靠性

第十四题.

请简述,在区块链系统创建区块链账户的过程(包括公钥、私钥、地址)。

第一步:生成私钥的种子即"绝对"的随机数'"种子"。

第二步:通过"种子"利用特定的非对称加密算法生成对应的私钥

第三步:基于已生成的私钥借助ecdsa库生成公钥。

第四步:创建create_account函数,利用SHA-256将公钥进行哈希处理后得到第一个哈希值作为中间哈希值

第五步:.将中间哈希值(intermediate)通过RIPMD-160及连续两次SHA-256哈希处理得到第二个哈希值(double_hash)

第六步:取double_hash的前4位以及intermediate哈希值组合后进行base58编码得到地址。

# 1.随机生成一个种子
# 2.使用该种子用 ecdsa 库生成私钥,然后生成公钥
# 3.将公钥进行 SHA-256 哈希处理生成哈希值,再用 RIPEMD-160 进行哈希处理生成中间哈希值
# 4.将中间哈希值进行两次 SHA-256 哈希处理,取结果的前四位作为校验值
# 5.将中间哈希值和校验值拼接,经过 Base58 编码生成地址


#账户公钥和私钥的生成方式
import ecdsa
import random
import hashlib
import base58
from hashlib import sha256
def create_seed():
    """
    创建绝对随机的种子
    :return: string绝对随机数
    :return:随机数
    """
    return ''.join(random.sample('abcdefghijklmnopqrstuvwxyz!@#$%^&*()',32)).encode()
    
def create_private_key(seed):
    """
    使用种子创建密钥
    :param seed:创建私钥需要的随机数
    :return :以pem形式保存的私钥
    """
    return ecdsa.SigningKey.from_string(seed,curve=ecdsa.SECP256k1).to_pem()

def create_public_key(private_key):
    """
    使用私钥生成公钥
    :param private_key:生成公钥需要的私钥
    :return:以pem形式保存的公钥
    """
    return ecdsa.SigningKey.from_pem(private_key).verifying_key.to_pem()

#地址生成的具体过程如下:
# 1.利用SHA-256将公开的密钥进行哈希处理生成哈希值
# 2.将第一步中的哈希值通过RT\IPEMD-160进行哈希处理后生成哈希值
# 3.将第二步中的哈希值记性Base58编码
def create_account():
    """
    创建区块链用户地址
    1.如果代码存在飘红内容,将鼠标移动到飘红点,查看问题,一般性为变量命名错误,或者是包未引入,修改
    2.如果存在base58这个包无法解析,解决方法为:pip install base58
    """ 
    seed = create_seed()
    private_key_pem =create_private_key(seed)
    public_key_pem = create_public_key(private_key_pem)
    in_public_key = ecdsa.VerifyingKey.from_pem(public_key_pem).to_string()
    intermediate =hashlib.sha256(in_public_key).digest()  #中间哈希值
    #作二次hash生成double_hash
    ripemd160=hashlib.new('ripemd160')
    ripemd160.update(intermediate)
    hash160 = ripemd160.digest()
    double_hash = hashlib.sha256(hashlib.sha256(hash160).digest()).digest()
    #取前四位,作为校验值
    checksum = double_hash[:4]
    #将中间哈希与校验值拼接
    pre_address = hash160 +checksum
    #通过base58编码生成地址
    address = base58.b58encode(pre_address)
    print(f"生成地址是:{address.decode()}")
    #将区块链账户三要素返回:adress、private_key、public_key
    return{
        "address":address.decode(),
        'private_key':private_key_pem.decode(),
        'public_key':public_key_pem.decode()
    }
def sha256d(string):
    """
    双重 SHA-256 哈希计算
    将字符串转为哈希值
    :param string: 需要计算的字符串(bytes 或 str 类型)
    :return: 计算结果的 16 进制字符串形式

    """
    if not isinstance(string, bytes):
        string = string.encode()

    return sha256 (sha256(string).digest()).hexdigest()


def data_sign(data, private_key):
    """
    签名
    :param data: 签名时使用的数据
    :param private_key: 签名时使用的私钥
    :return:
    """
    if not isinstance(data,bytes):
        data = data.encode()
    sk = ecdsa.SigningKey.from_pem(private_key)
    sig = sk.sign(data)
    return sig
    

def data_verify(data, sig, public_key):
    """
    验证签名
    :param data: 验证时使用的数据
    :param sig: 要验证的签名
    :param public_key: 验证时使用的公钥
    :return: 验证结果,返回0表示成功,返回1表示失败,返回2表示出现问题
    """
    if not isinstance(data,bytes):
        data = data.encode()

    vk = ecdsa.VerifyingKey.from_pem(public_key)
    try:
        if vk.verify(sig, data):
            return 0 # 如果验证成功则返回0
        else:
            return 1 # 如果验证失败则返回1
    except Exception as e:
        return 2 # 如果验证出现问题则返回2
#验证
print(create_account())

第十五题 .

请简单描述单节点区块链系统中具体包含的模块以及每个模块对应的功能

构建区块链系统包括账户功能,账本功能,点对点(P2p)通信功能以及共识算法功能

  • 开发包括具体模型,具体包括区块链中的交易模型(Transaction)、区块链中的区块模型(Block)、区块链网络模型(Network)、区块链账本模型(Blockchain)、数据通信的消息模型(message)、区块链中的节点模型(Peer).
  • 预定义功能开发涉及的加密算法以及实体。其中加密算法包括账户创建以及数据签名与验证等功能、哈希加密算法功能、默克尔根计算等,创建实体包括预定义的节点、网络以及区块链账本。
  • 开发具体包括账户、账本、P2p通信以及共识算法等功能
  • 开发系统入口模块,功能包括启动节点通信、共识算法等定时器以及可供HTTP访问接口。 

二.填空题:

1.区块链的区块分别包括_区块头___和_区块体___。

2.在区块链节点实现中,通过__Flask__框架实现WEB HTTP服务以及进程持久化?

3.在客户端通过HTTP POST的形式向服务端发送请求时,数据一般以_JSON_格式在Body中封装。

4.在使用Python语言开发区块链系统中,开发中使用__hashlib___包实现哈希算法

5.在使用Python语言开发区块链系统中,开发中使用__ecdsa___包实现非对称加密算法

6.在使用Python开发的区块链系统中,采用___Networkx___工具可以绘制区块链网络。

7.在使用Python开发的区块链系统中,采用__Flask-socketio__实现Socket通信的服务端。

 8.在使用Python开发的区块链系统中,采用__python-socketio[client]__实现Socket通信的客户端。

猜你喜欢

转载自blog.csdn.net/2201_76041915/article/details/134753070