2024年如何在Stellar网络上高效存储数据?新手指南!

2025-03-05 12:13:39 学术 阅读 68

Stellar 存储教程

Stellar,作为一个快速、低成本的支付网络,吸引了越来越多的用户和开发者。理解如何在 Stellar 网络上存储数据至关重要,无论是存储简单的账户信息,还是构建复杂的去中心化应用。本教程将详细介绍 Stellar 上的存储机制及其使用方法。

账户和数据条目

在Stellar网络中,账户是进行任何交易和存储数据的基本单元。每个账户都由一对非对称密钥控制:一个公钥和一个私钥。公钥如同银行账户的账号,作为账户在网络中的唯一地址,用于接收资金和识别账户。私钥则相当于银行账户的密码,必须妥善保管,因为它允许账户持有者授权交易,包括发送资金、更改账户设置以及更新数据条目。私钥的泄露意味着账户控制权的丧失。

账户除了控制密钥外,还可以存储一些关键信息。最重要的是余额,表示账户持有的各种资产(例如XLM、法币锚定代币等)的数量。账户还可以维护一个签名者列表,允许账户通过多重签名机制进行控制,提高安全性。例如,可以设置需要多个授权签名才能执行特定操作,防止单点故障。

Stellar账户还可以存储数据条目。数据条目是一种键值对存储机制,允许开发者在链上附加任意数据到账户。键是字符串,值可以是任何字节序列。这为开发者提供了在Stellar网络上构建各种应用程序的可能性,例如身份验证、投票系统或简单的元数据存储。数据条目存储在Stellar分布式账本中,这意味着它们是公开可见且不可篡改的。

数据条目是 Stellar 中存储键值对的关键机制。每个账户可以拥有多个数据条目,每个条目都由一个键和一个值组成。键和值都是base64编码的字符串,最大长度为64字节。

如何添加和修改数据条目

在 Stellar 网络中, ManageData 操作是管理账户数据存储的关键手段。它允许账户持有者在区块链上存储少量与账户相关的自定义数据,用于各种用途,如身份验证、投票、或其他去中心化应用(DApp)的特定需求。添加或修改数据条目都需要构建并提交一个包含 ManageData 操作的交易到 Stellar 网络。此操作赋予用户创建新数据条目、更新现有数据条目以及删除不再需要的数据条目的能力。每个数据条目都由一个唯一的名称(字符串)和一个与之关联的值(字节字符串)组成。

ManageData 操作的运作机制如下: 当你想创建一个新的数据条目时,你需要指定一个尚未被该账户使用过的名称,以及你想存储在该名称下的数据值。 如果你想修改现有的数据条目,你需要提供该数据条目的名称,以及你想更新的新值。 如果你想删除一个数据条目,你需要提供该数据条目的名称,并将数据值设置为空。 这些操作都需要经过签名并提交到 Stellar 网络,最终由验证节点处理并记录在区块链上,从而实现数据的持久化存储和状态变更。

1. 构建交易:

构建包含 ManageData 操作的交易是与 Stellar 网络交互的关键步骤。 这需要使用 Stellar SDK (软件开发工具包),它提供了必要的工具和函数来创建、签名和提交交易。针对不同的编程语言,Stellar 社区提供了多种 SDK,例如 JavaScript、Python、Go 和 Java 等,开发者可以根据自己的技术栈选择合适的 SDK。

以 JavaScript 为例,可以使用 stellar-sdk 来构建交易,以下是一个示例:

javascript const StellarSdk = require('stellar-sdk');

// 服务器实例。指定连接的 Horizon 服务器 URL。测试网络和生产网络使用不同的 Horizon 实例。 const server = new StellarSdk.Server('https://horizon-testnet.stellar.org'); // 测试网络,生产环境使用正式网络 (例如:'https://horizon.stellar.org')

// 发送方私钥 (切勿在生产环境硬编码私钥!这只是一个示例,生产环境中需要安全地管理和存储私钥。可以使用硬件钱包或密钥管理系统。) const sourceSecretKey = 'SC****************************************'; const sourceKeypair = StellarSdk.Keypair.fromSecret(sourceSecretKey);

// 账户地址,从密钥对中获取公钥,即账户地址。 const sourcePublicKey = sourceKeypair.publicKey();

async function manageData() { try { // 从 Horizon 服务器加载账户信息,包括余额、序列号等。 const account = await server.loadAccount(sourcePublicKey);

const transaction = new StellarSdk.TransactionBuilder(account, { fee: StellarSdk.BASE_FEE })
   .addOperation(StellarSdk.Operation.manageData({
     name: 'my_data_key', //  数据条目的键,用于标识存储在账户上的数据。
     value: 'my_data_value' // 数据条目的值,需要 base64 编码。如果设为 null 或者 undefined,表示删除该条目。值的长度有限制,具体请参考 Stellar 协议。
  }))
  .setTimeout(30) // 设置交易的有效时间,单位为秒。如果交易在指定时间内未被网络处理,则会失效。
   .build();

transaction.sign(sourceKeypair); // 使用发送方的私钥对交易进行签名,证明交易是由该账户发起的。

const transactionResult = await server.submitTransaction(transaction); // 将签名后的交易提交到 Stellar 网络。
console.log('Success! Results:', transactionResult); // 打印交易结果,包括交易哈希、操作结果等。

} catch (e) { console.error('Error!', e); // 错误处理,捕获并打印交易过程中可能发生的任何错误。 } }

manageData(); // 调用 manageData 函数执行交易。

上述代码首先连接到 Stellar 测试网络 (或者生产网络,取决于 StellarSdk.Server 的配置),然后加载发送方的账户信息。 接着,它创建一个 ManageData 操作,该操作指定了数据条目的键为 my_data_key ,值为 my_data_value 。数据的键 (name) 和值 (value) 都是字符串。 值需要进行 Base64 编码,因为 Stellar 协议将数据存储为二进制格式。 代码使用发送者的私钥对交易进行签名,并将签名后的交易提交到网络。 提交后,网络会对交易进行验证和处理,并将数据存储在发送方的账户上。

2. Base64 编码:

在恒星网络(Stellar Network)的 ManageData 操作中, value 字段的数据必须以 Base64 编码字符串的形式存在。这是因为恒星核心协议在处理数据条目时,期望接收到的是二进制数据的编码表示。如果希望在数据条目中存储非字符串类型的数据,例如数字、布尔值、数组或复杂的 JSON 对象,则需要预先进行序列化操作,将其转换为字符串,然后再进行 Base64 编码。这一过程确保了数据的兼容性和可存储性,同时允许开发者在链上存储各种类型的数据。

例如:

JavaScript代码示例:


// 将 JSON 对象序列化为字符串并进行 Base64 编码
const Data = { message: "Hello, Stellar!" };  // 定义一个 JSON 对象,包含一条消息
const String = JSON.stringify(Data);         // 使用 JSON.stringify() 方法将 JSON 对象转换为字符串
const buffer = Buffer.from(String);           // 将字符串转换为 Buffer 对象,以便进行 Base64 编码
const base64Encoded = buffer.toString('base64'); // 使用 toString('base64') 方法将 Buffer 对象进行 Base64 编码

console.log(base64Encoded);                 // 在控制台输出 Base64 编码后的字符串

详细说明:

  • JSON 序列化: JSON.stringify() 方法将 JavaScript 对象转换为 JSON 格式的字符串。这一步是必要的,因为 Base64 编码处理的是字符串或二进制数据。
  • Buffer 对象: Buffer.from() 方法用于创建一个包含给定字符串的 Buffer 对象。Buffer 对象代表一个固定长度的字节序列,适用于处理二进制数据。在 Node.js 环境中,Buffer 是处理二进制数据的核心类。
  • Base64 编码: buffer.toString('base64') 方法将 Buffer 对象的内容编码为 Base64 字符串。Base64 是一种常用的编码方案,它将二进制数据转换为 ASCII 字符串,以便在文本协议(如 HTTP)中传输。
  • 编码后的结果: base64Encoded 变量将包含一个 Base64 编码的字符串,该字符串可以安全地存储在恒星网络的 ManageData 操作的 value 字段中。

通过以上步骤,开发者可以方便地将各种类型的数据转换为 Base64 编码的字符串,并将其存储在恒星区块链上,从而实现更丰富的数据存储和应用场景。

3. 删除数据条目:

在Stellar网络中,删除数据条目是通过 ManageData 操作实现的。核心机制是将与特定键( name )相关联的 value 明确设置为 null undefined 。这种操作会从账户的数据存储中移除该键值对,有效地删除了该数据条目。

以下JavaScript代码片段展示了如何构建一个交易来删除数据条目。这段代码使用了Stellar JavaScript SDK。


  const transaction = new StellarSdk.TransactionBuilder(account, { fee: StellarSdk.BASE_FEE })
    .addOperation(StellarSdk.Operation.manageData({
      name: 'my_data_key',  // 要删除的数据条目的键,指定需要删除的键名
      value: null         // 设置为 null 删除该条目,表示将该键对应的值置空,从而删除数据
    }))
    .setTimeout(30)
    .build();

代码详解:

  • StellarSdk.TransactionBuilder : 创建一个新的交易构建器,需要账户对象和交易费作为参数。
  • fee: StellarSdk.BASE_FEE : 设置交易费用,使用StellarSdk提供的基础费用常量。
  • StellarSdk.Operation.manageData : 添加一个 ManageData 操作到交易中。该操作用于创建、修改或删除数据条目。
  • name: 'my_data_key' : 指定要删除的数据条目的键名。 确保此键与要删除的现有条目的键完全匹配。
  • value: null : 关键步骤,将 value 设置为 null 意味着我们想要删除与指定 name 关联的数据条目。
  • setTimeout(30) : 设置交易的超时时间,以秒为单位。超出此时间,交易将不再有效。
  • build() : 构建交易对象,准备签名和提交。

重要提示:

  • 确保账户有足够的余额支付交易费用。
  • name 必须与要删除的现有数据条目的键完全匹配,区分大小写。
  • 删除数据条目后,该键将不再存在于账户的数据存储中,直到再次使用 ManageData 操作添加新的值。

读取数据条目

要读取 Stellar 账户的数据条目,可以使用 Stellar SDK 提供的 API。 数据条目存储在账户的分类账本中,允许开发者将键值对与特定的账户相关联。 这些数据条目可以用于各种目的,例如存储账户的元数据、授权信息或应用程序特定的配置。

JavaScript 示例:

async function readData() {
  try {
    const account = await server.loadAccount(sourcePublicKey);

    // account.data 包含了账户的所有数据条目,以键值对的形式存储
    console.log("账户数据条目:", account.data);

    // 或者,可以直接访问特定键的数据条目
    const dataValueBase64 = account.data['my_data_key'];

    if (dataValueBase64) {
      // 数据条目以 Base64 编码存储,需要解码
      const buffer = Buffer.from(dataValueBase64, 'base64');
      const dataValueString = buffer.toString('utf8');
      console.log("键 'my_data_key' 对应的值:", dataValueString);
    } else {
      console.log("未找到键为 'my_data_key' 的数据条目。");
    }
  } catch (e) {
    console.error('读取数据时发生错误!', e);
  }
}

readData();

这段 JavaScript 代码演示了如何使用 Stellar SDK 读取账户的数据条目。 它使用 server.loadAccount() 方法加载指定公钥 sourcePublicKey 的账户信息。 然后,它访问 account.data 属性,该属性包含账户的所有数据条目,以键值对对象的形式呈现。 代码随后尝试读取键为 my_data_key 的特定数据条目。 由于 Stellar 网络上的数据条目以 Base64 编码存储,因此需要使用 Buffer.from(dataValueBase64, 'base64') 将检索到的 Base64 编码的值解码为 Buffer 对象,再使用 buffer.toString('utf8') 将 Buffer 对象转换为 UTF-8 字符串。 如果找到该条目,则将其解码后的 UTF-8 字符串值打印到控制台。 如果未找到该条目,则会显示一条相应的消息。

数据条目的限制

  • 大小限制: 数据条目的键和值的最大长度都被严格限制为 64 字节。此限制旨在优化存储效率和检索速度,确保区块链网络的性能。任何超过此限制的键或值都将无法存储。
  • 存储成本: 在区块链账户中存储数据条目需要支付一定的存储费用。这是为了防止恶意用户通过大量存储无用数据来占用网络资源,从而影响网络的整体性能。存储费用通常根据存储的数据量和存储时间来计算,并且以原生代币支付,确保了网络的经济可持续性。这种机制有效地抑制了垃圾数据的产生,维护了区块链的健康运行。
  • 账户限制: 每个账户可以拥有的数据条目数量存在上限。尽管此限制通常设置得相对较高,旨在满足大多数应用的正常需求,但开发者在设计应用时仍然需要仔细规划数据存储策略。超出此限制将无法继续写入新的数据条目。合理利用数据结构和优化存储方式可以有效地减少数据条目的使用量,从而避免达到账户限制。

应用场景

Stellar 的数据条目(Data Entries)机制提供了强大的链上数据存储能力,这使其适用于各种应用场景,超越了简单的交易和支付。

  • 身份验证(KYC/AML): 数据条目可安全地存储用户的身份信息,例如符合 KYC(Know Your Customer,了解你的客户)和 AML(Anti-Money Laundering,反洗钱)法规所需的数据。 这允许在 Stellar 网络上构建合规的金融应用,例如需要验证用户身份才能进行交易的交易所或汇款服务。通过数据条目存储哈希化的敏感数据,可以增强隐私并确保合规性。
  • 账户属性存储: 除了基本的账户信息外,数据条目还可以用来存储与账户相关的各种属性,例如用户的昵称、头像、个人简介、联系方式等。这些信息可以用于构建更具个性化和社交化的应用,为用户提供更好的体验。这对于社区代币、粉丝代币和社交媒体应用尤其有用。
  • 资产元数据管理: Stellar 资产(Issued Assets)可以通过数据条目存储丰富的元数据信息,例如资产的完整名称、详细描述、官方网站链接、logo 图片的 URL、以及其他相关的业务信息。 这使得用户更容易识别和理解不同的资产,并降低资产欺诈的风险。 例如,稳定币发行者可以存储关于其储备金审计的信息。
  • 构建去中心化应用(DApps): 数据条目是构建更复杂的去中心化应用(DApps)的基础。它们可以用于存储应用的状态、逻辑和数据,例如:
    • 投票系统: 存储投票的选项、投票结果、以及投票者的身份信息。
    • 供应链管理系统: 跟踪商品的来源、运输过程、以及质量信息。
    • 去中心化社交网络: 存储用户的帖子、评论、以及关注关系。
    • 预言机(Oracles): 存储来自链下世界的真实数据,例如价格、天气预报、体育赛事结果等。
    通过结合 Stellar 的智能合约功能(Stellar Contract Protocol,SCP)和数据条目,可以构建功能丰富且具有高度安全性和透明度的 DApp。

注意事项

  • 安全性: 绝对不要将敏感信息,例如私钥、助记词、API 密钥或任何其他类型的身份验证凭据,直接存储在区块链的数据条目中。尽管数据条目会永久记录在 Stellar 区块链上,但它们的设计初衷是公开可读的。任何泄露的敏感信息都可能导致资金损失或其他安全风险。考虑使用加密方法或链下存储来保护您的数据。
  • 成本: 在 Stellar 网络上,添加或修改数据条目会产生交易费用。这些费用用于激励网络验证者并防止垃圾交易。请仔细考虑数据条目的数量和频率,因为它们会对您的运营成本产生直接影响。重要的是,删除不再需要的数据条目也能释放账户使用的存储空间,这反过来会降低账户所需的最低余额要求,从而释放之前锁定的资金。请记住,Stellar 网络上的资源使用是需要付费的,因此有效的资源管理至关重要。
  • 可读性: 为了便于读取和解析存储在区块链上的数据,强烈建议使用标准且广泛支持的数据格式,例如 JSON (JavaScript Object Notation) 或其他结构化格式。这种方法可以确保不同的应用程序和服务能够轻松地访问和解释数据,从而促进互操作性。适当的编码 (例如 UTF-8) 可以保证字符的正确显示,防止出现数据损坏或解析错误。务必确保所有存储的数据都符合预定义的模式和验证规则,以维护数据质量和一致性。
  • 测试网络: 在将任何应用程序或服务部署到 Stellar 主网络之前,强烈建议在 Stellar 测试网络上进行全面的开发和测试。测试网络是一个独立的、与主网络功能类似的区块链环境,允许开发者在不承担真实资产风险的情况下安全地试验和调试其代码。利用测试网络可以帮助您识别和修复潜在的错误、优化性能以及估算交易费用,从而避免在主网络上花费不必要的费用。请确保您的应用程序在测试环境中运行良好后再进行部署,以确保顺利过渡并降低意外问题发生的概率。

Stellar Horizon API

Stellar Horizon API 提供了一整套全面的RESTful接口,旨在简化开发者与Stellar网络之间的交互。通过这些接口,开发者可以执行各种关键操作,例如:

  • 账户信息查询: 获取Stellar网络上特定账户的详细信息,包括账户余额(各种资产)、账户的签名者权重、以及账户的标志位等。这对于构建用户友好的账户管理界面至关重要。
  • 交易提交: 构建并提交交易到Stellar网络。这包括支付交易、资产发行交易、账户设置交易(如更改签名者、设置授权标志)以及其他各种Stellar网络支持的操作。交易的构建需要遵循Stellar Transaction Envelope (XDR)格式。
  • 历史记录查询: 检索Stellar网络上的交易历史、操作历史、以及账本历史。可以根据账户、交易哈希、账本序号等条件进行过滤,以便追踪特定事件或进行数据分析。
  • 资产信息查询: 获取关于Stellar网络上各种资产的详细信息,包括资产代码、发行者账户、资产类型等。
  • 路径查找: 寻找在Stellar网络上进行资产兑换的最佳路径。这对于实现分布式交易所(DEX)功能至关重要。
  • 订阅事件: 通过WebSocket协议实时订阅Stellar网络上的事件,例如新的交易、新的账本、以及账户余额变化等。这使得开发者能够构建响应迅速的实时应用程序。

熟练掌握Stellar Horizon API是开发任何Stellar网络应用程序的基石。开发者应该充分利用Horizon API提供的丰富功能,构建安全、高效、且用户体验良好的Stellar应用。为了更方便的使用,Stellar社区还提供了多种编程语言的SDK,对Horizon API进行了封装,使得开发者可以更方便地调用这些API,无需直接处理HTTP请求和响应。

相关推荐