节点) IPFS(使用第三方提供商) Filecoin Storj Arweave 出于我们 dApp 的目的,我们决定尽量减少对 Piñata、Web3.storage 或 Infura 等任何第三方解决方案的依赖。虽然它们在易于部署等方面带来了许多优势,但它们需要 API 密钥,我们将其视为单点故障和控制风险。只要有 API 密钥,就无法保证不可篡改性和可达性。 不可避免地存在权衡。在 Outlier,我们经常采用 IPFS 来托管静态内容。我们甚至讨论了托管我们自己的 IPFS 节点。这将为最终用户提供验证特定部署是否与已部署的代码包的 CID 相匹配的机会,并且我们可以利用 IPNS 和 IPFS 以及 ENS 来允许可变的 IPFS CID 指针更新网站内容并通过 HTTPS 启用域名解析时。 然而,由于 IPFS 本身不是一个激励网络,因此将 dApp 固定到我们自己的节点可能会造成单点故障,这是我们严格试图避免的。 我们研究了 IPFS 固定解决方案,例如https://web3.storage/,它提供了出色的开发人员体验,但最终它是一个中心化解决方案,因为它基于他们持有的密钥,并且允许他们随时撤销服务时间。这是一项有用的服务,但在这种情况下,我们决定它不会为我们提供我们所追求的完全去中心化的体验。 出于同样的原因,另一个解决方案https://filebase.com/被排除。 接下来,我们考虑了 Filecoin,它在 IPFS 之上提供了一个层,并激励提供商通过将内容固定到 IPFS 节点来提供存储空间。以 Filecoin 向提供商支付费用,并且由于 IPFS 和 Filecoin 都是由 Protocol Labs 开发的,因此这是一种流畅且连贯的体验。
如果不是他们的商业模式取决于交易,我们可能会选择 Filecoin 。作为开发人员,我们不需要持续考虑向谁付款以及支付多少钱,因此对于我们的特定用例,我们也排除了 Filecoin。 我们的第三个选择 Arweave 为我们提供了技术权衡,但最终是我们选择的解决方案。虽然每次上传的成本很低——每次大约 0.003 美元,而且该网络已经存在五年了,但工具和资源比 Filecoin 和 IPFS 生态系统中的要少,因此我们必须解决一些有趣的挑战——包括开发我们的自己的库,用于直接从我们的 CI/CD 捆绑和上传。
Arweave 工具 你可以在这里按照我们的步骤熟悉如何将内容上传到 Arweave(又名 Permaweb)。 首先,我们熟悉了基础知识。在我们决定构建一个简单的 React 应用程序后,我们的第一站是https://cookbook.arweave.dev/,在那里我们找到了大量用于将数据上传到 Arweave 的有用资源,包括部署应用程序。 先决条件 你需要安装 Node,以及 npx 和 pnpm。你还需要一个交易所帐户,可以在其中购买一些用于部署的 AR。我们使用 Arweave 的主网而不是测试网,因为它足够便宜,可以进行实验。 第一步是创建一个 Arwave 钱包并用一些 AR 为其提供资金。有趣的是,最简单的方法是通过 CEX。 检查资金是否已到达你的地址:https: //viewblock.io/arweave 创建你的钱包: $ mkdir upload-arweave $ pnpm install arweave $ node -e "require('arweave').init({}).wallets.generate().then(JSON.stringify).then(console.log.bind(console)) > wallet.json 现在你有了一个 wallet.json,其中包含你的私钥和公钥。通过运行查找地址: npx arweave-bundler address 你需要提供少量 AR 资金。有趣的是,最简单的方法是通过 CEX。 检查资金是否已到达你的地址:https: //viewblock.io/arweave 之后,你可以开始编写几行代码来部署某些内容。 Arweave Hello World 首先创建一个简单的网络应用程序。今天最简单的就是`pnpm create vite`并选择最适合你的默认值。 然后查看https://cookbook.arweave.dev/,你可以在其中找到大量用于将数据(包括部署应用程序)上传到 Arweave 的有用资源,或者继续浏览博客文章以获取好的方法。 创建一个名为 ar-deploy.js 的文件并粘贴以下内容: import Arweave from "arweave"; import fs from "fs"; // load the JWK wallet key file from disk const jwk = JSON.parse(fs.readFileSync('./wallet.json').toString()); // initialize arweave const arweave = Arweave.init({ host: "arweave.net", port: 443, protocol: "https", }); const tx = await arweave.createTransaction( { data: "Hello world!", }, jwk ); await arweave.transactions.sign(tx, jwk); arweave.transactions.post(tx).then(console.log).catch(console.log); console.log(`https://arweave.net/${tx.id}`); 使用“node ar-deploy.js”运行它……你刚刚将第一个内容部署到了 Permaweb!
这很好,但还不够有用。 上传一个文件 下一步是上传实际文件而不是字符串。为此,你需要处理标签。网关需要知道它正在提供什么类型的数据(例如图像/png)。 import Arweave from 'arweave'; import fs from "fs"; // load the JWK wallet key file from disk let key = JSON.parse(fs.readFileSync("walletFile.txt").toString()); // initialize an arweave instance const arweave = Arweave.init({}); // load the data from disk const imageData = fs.readFileSync(`iamges/myImage.png`); // create a data transaction let transaction = await arweave.createTransaction({ data: imageData }, key); // add a custom tag that tells the gateway how to serve this data to a browser transaction.addTag('Content-Type', 'image/png'); // you must sign the transaction with your key before posting await arweave.transactions.sign(transaction, key); // create an uploader that will seed your data to the network let uploader = await arweave.transactions.getUploader(transaction); // run the uploader until it completes the upload. while (!uploader.isComplete) { await uploader.uploadChunk(); } 上传多个文件 事情开始变得有趣,但在遍历目录并将所有文件发布到 Permaweb 之前,还有最后一个概念需要掌握:理解清单的概念。 将文件上传到 Arweave 时,每个文件都会分配自己唯一的交易 ID。默认情况下,这些 ID 不以任何特定方式分组或组织。 因此,清单是一个 JSON 文件,其中包含一组文件的所有 ID。它还包含一个索引属性,该属性指向指向任何交易 ID 的别名。 { "manifest": "arweave/paths", "version": "0.1.0", "index": { "path": "index.html" }, "paths": { "index.html": { "id": "cG7Hdi_iTQPoEYgQJFqJ8NMpN4KoZ-vH_j7pG4iP7NI" }, "js/style.css": { "id": "fZ4d7bkCAUiXSfo3zFsPiQvpLVKVtXUKB6kiLNt2XVQ" }, "css/style.css": { "id": "fZ4d7bkCAUiXSfo3zFsPiQvpLVKVtXUKB6kiLNt2XVQ" }, "css/mobile.css": { "id": "fZ4d7bkCAUiXSfo3zFsPiQvpLVKVtXUKB6kiLNt2XVQ" }, "assets/img/logo.png": { "id": "QYWh-QsozsYu2wor0ZygI5Zoa_fRYFc8_X1RkYmw_fU" }, "assets/img/icon.png": { "id": "0543SMRGYuGKTaqLzmpOyK4AxAB96Fra2guHzYxjRGo" } } } Arweave 交易很便宜,但创建如此多的交易远非理想,特别是当网络拥塞时。 虽然此解决方案可行,但它不是最佳方案,因此我们转向下一个解决方案:Arweave bundles ( ANS-104 ) Arweave bundles 交易捆绑是一种特殊类型的 Arweave 交易。它允许将多个其他交易和/或数据项捆绑在其中。由于交易包里含有许多嵌套交易,因此它们是 Arweave 能够扩展到每秒数千个交易的关键。 我们的主要要求是能够将文件和资产捆绑在一起,以便我们可以在构建应用程序后以原子方式上传,从而拥有正确版本的 dApp,而不是零散地上传单个文件。这也具有成本优势,因为这意味着我们只需为上传付费一次。 我们考虑使用 Iris(以前称为 Bundlr),它具有良好的开发人员体验,包括允许使用许多代币进行支付,支持不同的链并允许在 Arweave 和其他我们没有的功能之上增加了一层额外的费用需要。 你可以利用名为arbundles 的开源库并添加一些粘合功能,从而在不使用 Irys 服务的情况下利用捆绑功能。 import { bundleAndSignData, createData } from "arbundles"; const dataItems = [createData("some data"), createData("some other data")]; const signer = new ArweaveSigner(jwk); const bundle = await bundleAndSignData(dataItems, signer); 我们的 Arweave 实用程序:arweave-bundler 我们决定创建自己的 Arweave 实用程序,以便直接在 CI/CD 中利用捆绑功能,并使步骤始终可重复。 在 Arweave Bundler 的公共存储库中,你将找到一个 GitHub Action 和 CLI,用于从目录上传静态资产,这非常适合将单页应用程序 (Single Page App,SPA) 或其他静态内容发布到 Arweave。 如果你想使用GitHub Action,配置如下: uses: outlierventures/arweave-bundler-action@v0.3.1 with: directory: build/ private-key: ${secret.ARWEAVE_PRIVATE_KEY} dry-run: false network: arweave.net 确保将私钥添加到存储库的 GitHub Secrets 中。如果你希望使用 CLI,请按照以下步骤捆绑和部署你的 Web 应用程序: npx arweave-bundler upload build/ --private-key ${PRIVATE_KEY} 始终确保你的私钥存储为环境变量。 结论 Arweave 提供了一种廉价且便捷的方式来永久存储 Web 应用程序前端,证明去中心化存储比中心化存储更便宜。另一方面,虽然中心化存储提供商拥有经过验证的商业模式,但我们需要等待 Arweave 模型是否能够通过时间的考验。主要挑战是激励调整,即费用。在一个没有租金且只收取一次性费用的系统中,如果节点不再获得足够的奖励,它们可能会决定离开。 虽然这个发现过程中最复杂的部分是在无法访问大量文档或示例的情况下找到我们的方法,但我们最终找到了一个有弹性的解决方案,我们希望其他开发人员能够从使用 arweave-bundler 简化其部署过程中受益。 我们的下一个任务是研究去中心化的域名管理。我们的下一篇文章将重点关注实施 ENS 和 ANT(Arweave 名称代币)所涉及的挑战和决 策。 来源:金色财经lg...