《区块链公链数据分析简易速速上手小册》第3章:区块链数据结构(2024 最新版)

news2024/11/28 22:36:25

在这里插入图片描述

文章目录

  • 3.1 区块和交易的结构
    • 3.1.1 基础知识
    • 3.1.2 重点案例:构建简单的区块链
    • 3.1.3 拓展案例 1:验证交易签名
        • 生成密钥对
        • 签名交易
        • 验证签名
        • 完整的交易签名与验证演示
    • 3.1.4 拓展案例 2:监听和解析区块链事件
        • 代币合约示例(Solidity)
        • Python 脚本监听和解析事件
        • 结论
  • 3.2 智能合约数据解析
    • 3.2.1 基础知识
    • 3.2.2 重点案例:读取以太坊智能合约状态
        • 步骤1:准备智能合约
        • 步骤2:安装Web3.py
        • 步骤3:编写Python脚本读取合约状态
        • 结论
    • 3.2.3 拓展案例 1:监听智能合约事件
        • 智能合约示例(Solidity)
        • 步骤1:安装 Web3.py
        • 步骤2:编写 Python 脚本以监听事件
        • 注意事项
    • 3.2.4 拓展案例 2:向智能合约发送交易
        • 智能合约示例(Solidity)
        • 步骤1:准备环境
        • 步骤2:编写Python脚本发送交易
        • 注意事项
  • 3.3 链上与链下数据
    • 3.3.1 基础知识
    • 3.3.2 重点案例:链上验证链下数据
        • 步骤1: 智能合约编写
        • 步骤2: 部署智能合约
        • 步骤3: 使用Python存储和验证数据哈希
        • 结论
    • 3.3.3 拓展案例 1:使用 IPFS 存储链下数据
        • 步骤1: 安装IPFS和Python客户端
        • 步骤2: 启动IPFS守护进程
        • 步骤3: 使用Python脚本存储数据到IPFS
        • 步骤4: 将IPFS哈希值存储到以太坊智能合约
        • 结论
    • 3.3.4 拓展案例 2:链下数据的链上验证
        • 步骤1: 智能合约编写
        • 步骤2: 部署智能合约
        • 步骤3: 使用Python存储和验证数据哈希
        • 结论

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_IDYOUR_CONTRACT_ABI_HEREYOUR_CONTRACT_ADDRESS_HERE为你自己的Infura项目ID、智能合约的ABI和合约地址。

结论

通过这个案例,我们演示了如何使用Python和Web3.py库来读取以太坊智能合约中的状态变量。这种方法可以用来访问智能合约的任何公开状态或执行其任何公开函数,为开发去中心化应用(DApps)提供了强大的基础。了解如何与智能合约交互并解析其数据对于构建复杂的区块链应用至关重要。

3.2.3 拓展案例 1:监听智能合约事件

在许多去中心化应用(DApps)中,实时监听智能合约事件并对其做出响应是一个常见且关键的需求。这可以用于追踪代币转移、用户投票、状态更新等重要活动。以下案例演示了如何使用Python和Web3.py监听以太坊智能合约的事件。

假设我们有一个智能合约,它定义了一个ValueChanged事件,每当合约中的某个值被更新时就会触发这个事件。

智能合约示例(Solidity)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract SimpleStorage {
    uint public storedData;

    event ValueChanged(uint oldValue, uint newValue);

    function set(uint x) public {
        emit ValueChanged(storedData, x);
        storedData = x;
    }
}
步骤1:安装 Web3.py

确保你的环境中已安装Web3.py:

pip install web3
步骤2:编写 Python 脚本以监听事件

接下来,我们将编写一个Python脚本,该脚本通过Infura连接到以太坊网络,并监听ValueChanged事件。

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('[YOUR_CONTRACT_ABI]')

contract = w3.eth.contract(address=contract_address, abi=contract_abi)

# 创建事件过滤器
value_changed_filter = contract.events.ValueChanged.createFilter(fromBlock='latest')

print("Listening for ValueChanged events...")

# 轮询以检查新事件
while True:
    for event in value_changed_filter.get_new_entries():
        print(f"Old Value: {event['args']['oldValue']}, New Value: {event['args']['newValue']}")
    time.sleep(10)

在这段代码中,将YOUR_INFURA_PROJECT_ID替换为你的Infura项目ID,0xYourContractAddress替换为智能合约的地址,[YOUR_CONTRACT_ABI]替换为合约的ABI。这段脚本首先创建了一个事件过滤器,然后进入一个循环,不断检查并打印新的ValueChanged事件。

注意事项
  • 使用WebSocket提供者(WebsocketProvider)对于监听事件是必需的,因为它支持订阅和实时更新,而HTTP提供者不支持这些功能。
  • 在生产环境中,你可能需要考虑错误处理和重新连接逻辑,以确保应用能够持续稳定地监听事件。

通过这个案例,我们展示了如何监听并处理以太坊智能合约中的事件,这对于构建响应式和交互式的DApps至关重要。监听智能合约事件是区块链开发中的一个强大工具,它可以帮助开发者实时捕捉到链上发生的关键活动,并据此执行相应的逻辑。

3.2.4 拓展案例 2:向智能合约发送交易

在以太坊上,向智能合约发送交易是一种常见的操作,用于执行合约的函数。这种操作可以改变合约的状态或触发链上的某些活动。以下案例演示了如何使用Python和Web3.py向以太坊智能合约发送交易。

假设我们有一个简单的智能合约,它允许存储和更新一个数值。

智能合约示例(Solidity)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract SimpleStorage {
    uint public storedData;

    function set(uint x) public {
        storedData = x;
    }
}

此合约包含一个名为set的函数,允许更新storedData变量的值。

步骤1:准备环境

确保你已安装Web3.py库:

pip install web3
步骤2:编写Python脚本发送交易

接下来,我们将编写一个Python脚本,通过Infura连接到以太坊网络,并发送一个交易来调用set函数。

from web3 import Web3
from web3.middleware import geth_poa_middleware

# 使用Infura的HTTP服务连接到以太坊网络
w3 = Web3(Web3.HTTPProvider('https://rinkeby.infura.io/v3/YOUR_INFURA_PROJECT_ID'))
w3.middleware_onion.inject(geth_poa_middleware, layer=0)

# 智能合约地址和ABI
contract_address = '0xYourContractAddress'
contract_abi = json.loads('[YOUR_CONTRACT_ABI]')

contract = w3.eth.contract(address=contract_address, abi=contract_abi)

# 发送交易需要的账户和私钥
account = '0xYourAccountAddress'
private_key = 'YourPrivateKey'

# 构建交易
nonce = w3.eth.getTransactionCount(account)
tx = contract.functions.set(123).buildTransaction({
    'chainId': 4,  # Rinkeby测试网络的chain ID
    'gas': 2000000,
    'gasPrice': w3.toWei('50', 'gwei'),
    'nonce': nonce,
})

# 签名交易
signed_tx = w3.eth.account.sign_transaction(tx, private_key)

# 发送交易
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)

# 获取交易哈希值
print(f"Transaction hash: {tx_hash.hex()}")

在这个脚本中,替换YOUR_INFURA_PROJECT_ID0xYourContractAddress[YOUR_CONTRACT_ABI]0xYourAccountAddressYourPrivateKey为你自己的值。

注意事项
  • 安全性:处理私钥时要非常小心,确保不要在公共代码库或不安全的地方暴露私钥。
  • Gas费用:发送交易需要支付Gas费用,因此确保你的账户有足够的以太币来支付。
  • 测试网络:在实际将交易发送到主网之前,强烈推荐在测试网络(如Rinkeby)上进行测试。

通过这个案例,我们演示了如何向以太坊智能合约发送交易以执行其函数,这是开发去中心化应用(DApps)的一个重要环节。理解如何与智能合约交互、发送交易和管理Gas费用对于区块链开发者来说是基本技能。

通过这些案例,我们展示了如何与以太坊智能合约进行交互,包括读取合约状态、监听事件以及发送交易以调用合约函数。这些技能是开发去中心化应用和进行区块链数据分析的基础,为开发者提供了强大的工具来构建复杂和高效的区块链应用。

3.3 链上与链下数据

在区块链应用开发中,理解链上和链下数据的区别及其应用是至关重要的。这不仅关乎数据的存储和处理方式,也影响到应用的设计和性能。

3.3.1 基础知识

  • 链上数据:直接存储在区块链上的数据。它的特点是不可篡改、透明且永久保存,适合存储交易记录、智能合约状态等关键信息。但由于存储成本较高,通常不适合存储大量数据。
  • 链下数据:存储在区块链外部的数据。链下数据可以存储在传统数据库、文件系统或任何其他形式的数据存储系统中。它适合存储大量数据,如应用日志、复杂的文档等,但不享有区块链数据的安全性和不可篡改性。

3.3.2 重点案例:链上验证链下数据

在区块链应用开发中,经常面临一个问题:如何有效地存储和验证大量数据。由于直接在链上存储数据成本较高,一种常见的解决方案是将数据存储在链下(如在服务器或分布式文件系统中),同时在链上存储数据的指纹(通常是数据的哈希值)以保证数据的不可篡改性和可验证性。

以下案例演示了如何使用Python和Web3.py以及以太坊智能合约来实现链上验证链下数据的完整性。

步骤1: 智能合约编写

首先,编写一个简单的智能合约,该合约允许用户存储和检索数据哈希值。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract DataHashStorage {
    mapping(bytes32 => bool) public hashExists;

    event HashStored(bytes32 dataHash);

    function storeDataHash(bytes32 dataHash) public {
        require(!hashExists[dataHash], "Data hash already stored.");
        hashExists[dataHash] = true;
        emit HashStored(dataHash);
    }

    function verifyDataHash(bytes32 dataHash) public view returns (bool) {
        return hashExists[dataHash];
    }
}

该合约包含一个storeDataHash函数用于存储数据哈希值,和一个verifyDataHash函数用于验证给定的哈希值是否已经被存储。

步骤2: 部署智能合约

使用Remix或Truffle等工具部署智能合约到以太坊网络,并记录合约地址。

步骤3: 使用Python存储和验证数据哈希

首先,安装Web3.py库。

pip install web3

接下来,编写Python脚本来计算链下数据的哈希值,存储这个哈希值到智能合约,并验证它。

from web3 import Web3
import hashlib

# 连接到以太坊节点
w3 = Web3(Web3.HTTPProvider('https://rinkeby.infura.io/v3/YOUR_INFURA_PROJECT_ID'))

# 智能合约地址和ABI
contract_address = '0xYourContractAddress'
contract_abi = json.loads('[YOUR_CONTRACT_ABI]')

contract = w3.eth.contract(address=contract_address, abi=contract_abi)

# 链下数据
data = "This is an example of off-chain data."
data_hash = hashlib.sha256(data.encode()).hexdigest()

# 发送交易存储数据哈希到智能合约
# 注意: 这里需要账户和私钥进行交易签名
account = w3.eth.account.privateKeyToAccount('YourPrivateKey')
nonce = w3.eth.getTransactionCount(account.address)
tx = contract.functions.storeDataHash(data_hash).buildTransaction({
    'chainId': 4,  # Rinkeby测试网络的chain ID
    'gas': 200000,
    'gasPrice': w3.toWei('50', 'gwei'),
    'nonce': nonce,
})
signed_tx = w3.eth.account.sign_transaction(tx, 'YourPrivateKey')
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)

# 等待交易被挖矿
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)

# 验证数据哈希
verified = contract.functions.verifyDataHash(data_hash).call()
print(f"Data hash verified: {verified}")

在这个脚本中,替换YOUR_INFURA_PROJECT_ID0xYourContractAddress[YOUR_CONTRACT_ABI]YourPrivateKey为你自己的值。

结论

通过这个案例,我们展示了如何将链下数据的哈希值存储到以太坊智能合约中,并实现了一个机制来验证链下数据的完整性和真实性。这种方法结合了区块链的不可篡改性和链下数据存储的灵活性与成本效益,为开发复杂的区块链应用提供了一种有效的数据管理策略。

3.3.3 拓展案例 1:使用 IPFS 存储链下数据

IPFS(InterPlanetary File System)是一个分布式文件系统,它允许存储和访问大量的数据,同时提供了一个唯一的哈希值用于数据的访问和验证。IPFS是链下数据存储的理想选择,因为它提供了去中心化和持久性,同时能够通过链上存储的哈希值来验证数据的完整性。以下案例演示了如何使用Python将数据存储到IPFS,并将对应的哈希值记录在以太坊智能合约中。

步骤1: 安装IPFS和Python客户端

首先,确保你的系统中安装了IPFS。你可以从IPFS官网下载并安装IPFS。

然后,安装Python的IPFS客户端库:

pip install ipfshttpclient
步骤2: 启动IPFS守护进程

在终端运行以下命令来启动IPFS守护进程:

ipfs daemon
步骤3: 使用Python脚本存储数据到IPFS

接下来,我们将使用Python脚本来存储数据到IPFS,并获取数据的唯一哈希值。

import ipfshttpclient

# 连接到本地IPFS节点
client = ipfshttpclient.connect('/ip4/127.0.0.1/tcp/5001/http')

# 要存储到IPFS的数据
data = "Hello, IPFS and Ethereum!"

# 添加数据到IPFS
res = client.add_str(data)
ipfs_hash = res

print(f"Data stored on IPFS with hash: {ipfs_hash}")
步骤4: 将IPFS哈希值存储到以太坊智能合约

现在,我们有了存储在IPFS上的数据哈希值,下一步是将这个哈希值存储到以太坊智能合约中,以便链上验证。

假设我们已经有一个智能合约,它有一个函数可以存储和验证IPFS哈希值。我们将使用Web3.py来与以太坊交互。

from web3 import Web3

# 连接到以太坊
w3 = Web3(Web3.HTTPProvider('https://rinkeby.infura.io/v3/YOUR_INFURA_PROJECT_ID'))

# 智能合约地址和ABI
contract_address = '0xYourContractAddress'
contract_abi = '[YOUR_CONTRACT_ABI]'

contract = w3.eth.contract(address=contract_address, abi=contract_abi)

# 账户和私钥
account = '0xYourAccountAddress'
private_key = 'YourPrivateKey'

# 构建交易
nonce = w3.eth.getTransactionCount(account)
tx = contract.functions.storeIPFSHash(ipfs_hash).buildTransaction({
    'chainId': 4,  # Rinkeby测试网络的chain ID
    'gas': 200000,
    'gasPrice': w3.toWei('50', 'gwei'),
    'nonce': nonce,
})

# 签名交易
signed_tx = w3.eth.account.sign_transaction(tx, private_key)

# 发送交易
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)

# 获取交易哈希值
print(f"Transaction hash: {tx_hash.hex()}")

在这个脚本中,替换YOUR_INFURA_PROJECT_ID0xYourContractAddress[YOUR_CONTRACT_ABI]0xYourAccountAddressYourPrivateKey为你自己的值。

结论

通过这个案例,我们演示了如何结合使用IPFS和以太坊来存储和验证大量的链下数据。这种方法利用了IPFS的分布式存储能力和以太坊智能合约的不可篡改性,为构建去中心化应用提供了一个高效、安全的数据存储和验证解决方案。

3.3.4 拓展案例 2:链下数据的链上验证

链下数据的链上验证是确保数据完整性和真实性的关键机制,特别是在去中心化应用(DApp)中处理大量数据时。这个过程通常涉及两个步骤:首先将数据存储在链下,然后将数据的哈希值或数字指纹存储在链上。当需要验证数据时,可以重新计算其哈希值并与链上存储的哈希值进行比对。

在本案例中,我们将使用Python演示如何实现链下数据的链上验证,包括如何通过智能合约存储和验证数据哈希。

步骤1: 智能合约编写

假设我们有一个简单的智能合约,用于存储和验证数据哈希:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract DataVerifier {
    mapping(bytes32 => bool) private hashes;

    // 事件,用于记录数据哈希已存储
    event HashStored(bytes32 dataHash);

    // 存储数据哈希
    function storeHash(bytes32 dataHash) public {
        require(!hashes[dataHash], "Hash already stored.");
        hashes[dataHash] = true;
        emit HashStored(dataHash);
    }

    // 验证数据哈希
    function verifyHash(bytes32 dataHash) public view returns (bool) {
        return hashes[dataHash];
    }
}
步骤2: 部署智能合约

使用你偏好的工具(如Truffle、Hardhat或Remix)将智能合约部署到以太坊网络(主网或测试网)。

步骤3: 使用Python存储和验证数据哈希

首先,确保安装了Web3.py库:

pip install web3

接下来,我们将计算链下数据的哈希值,通过智能合约存储这个哈希值,然后验证它。

from web3 import Web3
import hashlib

# 连接到以太坊
w3 = Web3(Web3.HTTPProvider('https://rinkeby.infura.io/v3/YOUR_INFURA_PROJECT_ID'))

# 智能合约地址和ABI
contract_address = '0xYourContractAddress'
contract_abi = '[YOUR_CONTRACT_ABI]'

contract = w3.eth.contract(address=contract_address, abi=contract_abi)

# 链下数据
data = "This is an example of off-chain data."
data_hash = hashlib.sha256(data.encode()).hexdigest()

# 转换哈希值为bytes32
data_hash_bytes32 = w3.toBytes(hexstr=data_hash)

# 发送交易存储数据哈希到智能合约
account = '0xYourAccountAddress'
private_key = 'YourPrivateKey'
nonce = w3.eth.getTransactionCount(account)
tx = contract.functions.storeHash(data_hash_bytes32).buildTransaction({
    'chainId': 4,  # Rinkeby测试网络的chain ID
    'gas': 2000000,
    'gasPrice': w3.toWei('50', 'gwei'),
    'nonce': nonce,
})

signed_tx = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
print(f"Transaction hash: {tx_hash.hex()}")

# 等待交易被挖掘
tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash)

# 验证数据哈希
verified = contract.functions.verifyHash(data_hash_bytes32).call()
print(f"Data hash verified: {verified}")

在这个脚本中,替换YOUR_INFURA_PROJECT_ID0xYourContractAddress[YOUR_CONTRACT_ABI]0xYourAccountAddressYourPrivateKey为你自己的值。

结论

这个案例展示了如何利用智能合约在链上存储和验证链下数据的哈希值。这种机制增加了数据处理的透明度和安全性,同时依然能够利用链下存储的高效性和低成本。这对于那些需要处理大量数据的去中心化应用尤其有用,例如在供应链管理、版权认证和数据市场等领域。

通过这些案例,我们探讨了链上与链下数据的不同用途和如何将它们结合使用。存储关键验证信息到链上,同时将大量数据存储到链下,是一种既能利用区块链技术的安全性和透明度,又能有效管理成本和性能的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1448147.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HarmonyOS 通过getInspectorByKey获取指定元素高宽等属性

例如 这里 我们有这样一个组件 Entry Component struct Dom {build() {Column() {Row() {Circle({ width: 200, height: 200 }).fill(#20101010)}.id(ES)}.width(100%).height(100%)} }这里 我们就写了个很基本的组件结构 然后 我们写了个 Circle 组件 定义了宽高 然后 如果我…

消息中间件面试篇

目录 消息中间件 RabbitMQ 消息不丢失 生产者确认机制 消息持久化 交换机持久化 队列持久化 消息持久化 消费者确认 消息重复消费 出现的场景 解决方案 每条消息设置一个唯一的标识id 幂等方案:【 分布式锁、数据库锁(悲观锁、乐观锁&#…

VMware虚拟机安装openEuler系统(二)(2024)

下面我们进行openEuler系统的一些简单配置。 1. 开启openEuler系统 在VMware Workstation Pro虚拟机软件中找到安装好的openEuler操作系统虚拟机并开启。 等待开启。 2. 安装配置 进入后选择第一个“Install openEuler 20.03-LTS”。 3. 选择系统语言 为虚拟机设置系统语言…

【lesson53】线程控制

文章目录 线程控制 线程控制 线程创建 代码: 运行代码: 强调一点,线程和进程不一样,进程有父进程的概念,但在线程组里面,所有的线程都是对等关系。 错误检查: 传统的一些函数是,成功返回0&…

【Java】零基础蓝桥杯算法学习——二分查找

算法模板一: // 数组arr的区间[0,left-1]满足arr[i]<k,[left,n-1]满足arr[i]>k;Scanner scan new Scanner(System.in);int[] arr {1,2,3,4,5};int left 0,right arr.length-1;int k scan.nextInt();while(left<right) {//leftright时退出循环int mid (leftrigh…

【Linux 02】权限基本概念

文章目录 &#x1f308; Ⅰ 权限概念&#x1f308; Ⅱ 权限管理1. 文件访问者分类 (角色)2. 文件类型和访问权限 (事物属性)3. 文件权限值表示方法 &#x1f308; Ⅲ 权限修改1. chmod 设置文件访问权限2. chown 修改文件拥有者3. chgrp 修改文件或目录的所属组 &#x1f308; …

【ArcGIS Pro二次开发】(79):符号系统_CIMUniqueValueRenderer

CIMUniqueValueRenderer是ArcGIS Pro SDK中的一个类&#xff0c;用于创建唯一值渲染器&#xff08;Unique Value Renderer&#xff09;。 在ArcGIS Pro中长这样&#xff1a; 通过对CIMUniqueValueRenderer的操作&#xff0c;可以对符号系统进行更改&#xff0c;实现很多功能。…

Matplotlib Figure与Axes速成:核心技能一网打尽

Matplotlib Figure与Axes速成&#xff1a;核心技能一网打尽 &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333; 一、Figure&#xff08;图形&#xff09;&#x1f333;&#x1f341;1. 创建Figure&#x1f341;&#x1f341;2. 添加Axes&#…

【教学类-47-01】20240206UIBOT+IDM下载儿童古诗+修改文件名

背景需求&#xff1a; 去年12月&#xff0c;我去了其他幼儿园参观&#xff0c;这是一个传统文化德育教育特色的学校&#xff0c;在“古典集市”展示活动中&#xff0c;小班中班大班孩子共同现场念诵《元日》《静夜思》包含了演唱版本和儿歌念诵版本。 我马上也要当班主任了&a…

MyBatis中的XML实现和动态SQL实现

文章目录 一、XML实现1.1增1.2删1.3查1.4改 二、XML方式实现动态SQL2.1if标签2.2trim标签2.3where标签2.4set标签2.5foreach标签2.6include标签和sql标签 一、XML实现 先在新建的XML文件中写入如下内容&#xff1a; <?xml version"1.0" encoding"UTF-8&qu…

php基础学习之分支结构和循环结构(不细讲,来对比一下和两大常用高级编程语言(C++/Java)的细微区别以便记忆)

分支结构 常见分支结构 编程语言常见分支结构有&#xff1a; if语句if-else语句if-elseif-else语句switch语句 其中&#xff0c;除了if-elseif-else语句外&#xff0c;另外3中分支语句在php中和C/Java是一模一样的&#xff01; 而if-elseif-else的唯一不同点就在&#xff0c;【…

【Python网络编程之DHCP服务器】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python开发技术 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python网络编程之DHCP服务器 代码见资源&#xff0c;效果图如下一、实验要求二、协议原理2.1 D…

奇异递归模板模式应用-对象计数

需求&#xff1a;有时遇到某些类特征相似而又没有共同的父类&#xff0c;希望能够知道这些类的创建数量之和。 思路&#xff1a;将这些类继承自同一个计数类&#xff0c;共享计数变量s_createCount信息&#xff0c;实现如下&#xff1a; class Counter { public:Counter() {s_…

Linux操作系统基础(十五):Shell编程

文章目录 Shell编程 一、什么是Shell 1、简介 2、Shell解释器 二、快速入门 1、编写Shell脚本 2、执行Shell脚本 Shell编程 一、什么是Shell 1、简介 Shell 是一个用 C 语言编写的程序&#xff0c; 通过 Shell 用户可以访问操作系统内核服务。 它类似于 DOS 下的 co…

【实战】一、Jest 前端自动化测试框架基础入门(二) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(二)

文章目录 一、Jest 前端自动化测试框架基础入门5.Jest 中的匹配器toBe 匹配器toEqual匹配器toBeNull匹配器toBeUndefined匹配器和toBeDefined匹配器toBeTruthy匹配器toBeFalsy匹配器数字相关的匹配器字符串相关的匹配器数组相关的匹配器异常情况的匹配器 6.Jest 命令行工具的使…

【python】object() takes no parameters报错原因

__init__ 你以为写对了&#xff0c;其实错了&#xff0c;因为是左右都是2个下划线。是左边两个&#xff01;&#xff01;右边也是两个&#xff01;&#xff01;&#xff01;不是合计2个&#xff01;&#xff01;&#xff01;

30. 异常

异常 1. 概述2. Throwable 方法2.1 概述2.2 代码示例 3. 异常分类4. 异常处理方式4.1 JVM默认处理异常4.2 自己处理&#xff08;捕获异常&#xff09;try...catch4.2.1 概述4.2.2 灵魂四问 4.3 抛出处理(throw和throws) 5. 自定义异常5.1 概述5.2 代码示例 6. 异常注意事项 文章…

GPT-4影响高度创新思维的领域(一)

GPT-4的应用范围不再局限于对现有信息的检索、整理和复述&#xff0c;而是进一步拓展到了诸如文学创作、科学假设生成、教育辅导、商业策略建议等需要高度创新思维的领域。这种独立思考和创新能力赋予了GPT-4作为虚拟助手时更加丰富多元的角色定位&#xff0c;使其成为一种强大…

如何在PDF 文件中删除页面?

查看不同的工具以及解释如何在 Windows、Android、macOS 和 iOS 上从 PDF 删除页面的步骤&#xff1a; PDF 是最难处理的文件格式之一。曾经有一段时间&#xff0c;除了阅读之外&#xff0c;无法用 PDF 做任何事情。但是今天&#xff0c;有许多应用程序和工具可以让您用它们做…

寒假思维训练day21

今天更新一道不错的状态压缩DP题&#xff0c;顺带总结一下状态压缩DP。 摘要&#xff1a; Part1 浅谈状态压缩DP的理解 Part2 浅谈对状态机DP的理解 Part3 关于状态压缩DP的1道例题 Part1 状态压缩DP 1、状态压缩DP&#xff1a; 事物的状态可能包含多个特征&#xff0c;…