3.1 区块和交易的结构
3.1.1 基础知识
在区块链的世界里,一切都始于区块和交易。这两个概念是构成任何区块链网络基础的核心元素。
- 区块:区块是区块链数据结构的主体,它包含了一系列的交易。每个区块都有一个唯一的区块头,其中包含了重要的元数据,如前一个区块的哈希值(确保区块之间的连接)、时间戳(记录区块创建的时间)、难度目标(用于工作量证明算法)和一个称为nonce的值(使区块的哈希值满足网络难度要求)。
- 交易:交易是区块链网络中传输资产或数据的基本单位。每笔交易都包含了一系列的输入和输出,输入指的是资产的来源,输出指的是资产的去向。交易一旦被网络验证并加入到一个区块中,就会被永久记录在区块链上。
3.1.2 重点案例:构建简单的区块链
让我们使用Python来模拟构建一个包含基本区块和交易结构的简单区块链。这个示例将帮助我们理解区块链是如何一步步构建并将交易记录在区块中的。
import hashlib import json from time import time class Blockchain: def __init__(self): self.chain = [] self.current_transactions = [] self.new_block(previous_hash='1', proof=100) # 创世区块 def new_block(self, proof, previous_hash=None): block = { 'index': len(self.chain) + 1, 'timestamp': time(), 'transactions': self.current_transactions, 'proof': proof, 'previous_hash': previous_hash or self.hash(self.chain[-1]), } self.current_transactions = [] self.chain.append(block) return block def new_transaction(self, sender, recipient, amount): self.current_transactions.append({ 'sender': sender, 'recipient': recipient, 'amount': amount, }) return self.last_block['index'] + 1 @staticmethod def hash(block): block_string = json.dumps(block, sort_keys=True).encode() return hashlib.sha256(block_string).hexdigest() @property def last_block(self): return self.chain[-1] # 实例化Blockchain blockchain = Blockchain() # 创建一个新交易 blockchain.new_transaction(sender="Alice", recipient="Bob", amount=100) # 挖掘一个新区块 blockchain.new_block(proof=12345) print(blockchain.chain)
3.1.3 拓展案例 1:验证交易签名
在区块链系统中,交易签名是确保交易安全性和完整性的关键。签名机制允许网络验证交易是否真的由交易发起者发起,而没有被第三方篡改。在这个扩展案例中,我们将使用Python演示如何生成密钥对、签名交易以及验证交易签名。
首先,确保安装了必要的Python库:
pip install ecdsa
生成密钥对
我们将使用椭圆曲线数字签名算法(ECDSA),这是比特币和许多其他加密货币使用的签名算法。
from ecdsa import SigningKey, SECP256k1 # 生成ECDSA密钥对 sk = SigningKey.generate(curve=SECP256k1) # 私钥 vk = sk.verifying_key # 公钥 private_key = sk.to_string().hex() public_key = vk.to_string().hex() print(f"Private Key: {private_key}") print(f"Public Key: {public_key}")
签名交易
使用生成的私钥对一条交易信息进行签名。
message = "Alice pays Bob 1 BTC" signature = sk.sign(message.encode()).hex() print(f"Message: {message}") print(f"Signature: {signature}")
验证签名
最后,我们将展示如何使用公钥和签名来验证消息。
from ecdsa import VerifyingKey # 将公钥和签名转换回相应格式 vk = VerifyingKey.from_string(bytes.fromhex(public_key), curve=SECP256k1) signature_bytes = bytes.fromhex(signature) # 验证签名 try: is_valid = vk.verify(signature_bytes, message.encode()) print("Signature is valid." if is_valid else "Signature is invalid.") except Exception as e: print(f"Signature verification failed: {str(e)}")
完整的交易签名与验证演示
将上述片段组合起来,我们就得到了一个完整的交易签名与验证的演示。这个过程从生成密钥对开始,接着用私钥签名一条简单的消息(模拟交易),最后使用公钥验证签名的有效性。
通过这个案例,我们可以深入理解数字签名在区块链交易安全中的关键作用。数字签名不仅确保了交易的非抵赖性,还验证了交易的完整性和发起人的身份,是区块链技术核心安全机制的重要组成部分。
3.1.4 拓展案例 2:监听和解析区块链事件
监听和解析区块链事件,尤其是在以太坊这样的支持智能合约的平台上,对于开发去中心化应用(DApps)非常关键。它允许应用实时响应合约中发生的特定活动,如代币转移、投票结果或其他自定义事件。以下案例将展示如何使用 Python 和 Web3.py 监听以太坊智能合约事件,并对事件数据进行解析。
首先,确保你已经安装了 Web3.py 库:
pip install web3
假设我们有一个简单的 ERC-20 代币合约,其中包含一个Transfer
事件,每当代币被转移时都会触发该事件。
代币合约示例(Solidity)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleToken { event Transfer(address indexed from, address indexed to, uint256 value); // 假设的代币转移函数 function transfer(address _to, uint256 _value) external { // ...执行转移逻辑 emit Transfer(msg.sender, _to, _value); } }
Python 脚本监听和解析事件
以下Python脚本示例展示了如何连接到以太坊网络,订阅Transfer
事件,并打印事件详情。
from web3 import Web3 # 使用Infura的WebSocket服务连接到以太坊主网络 w3 = Web3(Web3.WebsocketProvider('wss://mainnet.infura.io/ws/v3/YOUR_INFURA_PROJECT_ID')) # 假设合约地址和ABI contract_address = '0xYourContractAddress' contract_abi = json.loads('''[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]''') # 创建合约对象 contract = w3.eth.contract(address=contract_address, abi=contract_abi) # 创建事件过滤器 transfer_event_filter = contract.events.Transfer.createFilter(fromBlock='latest') print("Listening for Transfer events...") while True: # 检查新的事件 for event in transfer_event_filter.get_new_entries(): handle_event(event) time.sleep(10) def handle_event(event): print(f"New Transfer event:\n From: {event['args']['from']}\n To: {event['args']['to']}\n Value: {event['args']['value']} tokens")
在上述代码中,YOUR_INFURA_PROJECT_ID
需要替换为你的Infura项目ID,0xYourContractAddress
需要替换为你的代币合约地址。contract_abi
是合约的ABI,其中应包含你想要监听的事件定义。
这个脚本使用了Web3.py的事件过滤器功能来监听特定的Transfer
事件,并在新事件到达时通过handle_event
函数进行处理。这个处理函数简单地打印了事件的详细信息,包括转账的发送方、接收方和转移的代币数量。
结论
通过这个案例,我们展示了如何在以太坊区块链上监听和解析智能合约事件。这种能力对于开发实时响应链上活动的DApps至关重要。无论是追踪代币交易,还是其他基于事件的合约逻辑,使用Web3.py监听事件提供了一个强大且灵活的方法来增强应用的功能和用户体验。
通过这些案例,我们探索了区块链的基础数据结构,从构建和记录交易到验证交易的完整性和监听链上事件。这些操作是构建任何区块链应用的基石,理解它们对于任何 aspiring 区块链开发者来说都是必不可少的。
3.2 智能合约数据解析
智能合约是区块链技术的一项革命性创新,它允许在没有中介的情况下自动执行合约条款。这一切都是通过在区块链上编写和部署代码实现的。了解如何解析智能合约数据对于开发去中心化应用(DApp)、执行自动化测试或进行区块链数据分析至关重要。
3.2.1 基础知识
- 智能合约:是存储在区块链上的一段程序,它能够在满足预设条件时自动执行预定义的操作。
- 事件(Events):智能合约可以定义和触发事件,这些事件会被记录在区块链上,应用程序可以监听和响应这些事件。
- 函数调用:智能合约包含可被外部或合约内部调用的函数,这些函数可以读取或修改合约的状态。
3.2.2 重点案例:读取以太坊智能合约状态
假设我们有一个部署在以太坊上的智能合约,该合约包含一个可以公开访问的状态变量storedData
,以及一个函数getStoredData
用于返回这个变量的值。我们的目标是使用Python和Web3.py库来读取这个智能合约状态变量的当前值。
步骤1:准备智能合约
首先,假设智能合约代码如下(Solidity语言):
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleStorage { uint storedData; constructor(uint initialValue) { storedData = initialValue; } function setStoredData(uint x) public { storedData = x; } function getStoredData() public view returns (uint) { return storedData; } }
智能合约部署在以太坊网络上后,我们可以通过它的ABI和地址与之交互。
步骤2:安装Web3.py
确保你已经安装了Web3.py库:
pip install web3
步骤3:编写Python脚本读取合约状态
以下是使用Web3.py读取智能合约状态的Python脚本示例。在这个示例中,我们将连接到以太坊网络(通过Infura),使用合约的ABI和地址来创建一个合约对象,然后调用getStoredData
函数来获取storedData
变量的值。
from web3 import Web3 import json # 连接到以太坊节点 infura_url = 'https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID' w3 = Web3(Web3.HTTPProvider(infura_url)) # 确认连接成功 if w3.isConnected(): print("Connected to Ethereum network") # 智能合约ABI和地址 contract_abi = json.loads('[YOUR_CONTRACT_ABI_HERE]') contract_address = 'YOUR_CONTRACT_ADDRESS_HERE' # 创建智能合约对象 contract = w3.eth.contract(address=contract_address, abi=contract_abi) # 调用合约的getStoredData函数 stored_data = contract.functions.getStoredData().call() print(f"The stored data is: {stored_data}")
在上面的代码中,你需要替换YOUR_INFURA_PROJECT_ID
、YOUR_CONTRACT_ABI_HERE
和YOUR_CONTRACT_ADDRESS_HERE
为你自己的Infura项目ID、智能合约的ABI和合约地址。
结论
通过这个案例,我们演示了如何使用Python和Web3.py库来读取以太坊智能合约中的状态变量。这种方法可以用来访问智能合约的任何公开状态或执行其任何公开函数,为开发去中心化应用(DApps)提供了强大的基础。了解如何与智能合约交互并解析其数据对于构建复杂的区块链应用至关重要。
3.2.3 拓展案例 1:监听智能合约事件
在许多去中心化应用(DApps)中,实时监听智能合约事件并对其做出响应是一个常见且关键的需求。这可以用于追踪代币转移、用户投票、状态更新等重要活动。以下案例演示了如何使用Python和Web3.py监听以太坊智能合约的事件。
假设我们有一个智能合约,它定义了一个ValueChanged
事件,每当合约中的某个值被更新时就会触发这个事件。
《区块链公链数据分析简易速速上手小册》第3章:区块链数据结构(2024 最新版)(下)+https://developer.aliyun.com/article/1486954