设计和构建区块链社交媒体平台

这篇具有很好参考价值的文章主要介绍了设计和构建区块链社交媒体平台。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

集中式社交媒体,例如 Facebook 和 Twitter,并不适合所有用例。 例如,集中式社交媒体平台与中央权威机构(提供商)相关联。 该提供商有能力删除或隐藏用户帖子。

此外,由于集中式社交媒体是一个可变记录,它可能会被更改。 这有各种各样的后果。 例如,用户可能很难证明他们何时发布了某些内容。 这可能会对几个商业案例产生影响,例如专利诉讼或基于专家预测的专家评估。

可变性还带来了恶意行为的风险,其中用户的帖子可能会被修改,或者内容可能会发布在另一个用户的个人资料下。

这就是区块链可以改变游戏规则的地方。 区块链是一种实际上不可变的账本。 它提供了无法伪造或删除的永久记录,使其成为某些社交网络用例的理想选择。

在本文中,我们将设计和构建一个名为 Chirper 的区块链社交媒体平台,它将在以太坊之上运行。

内容

  • 设计社交媒体平台

    • 信息存储

    • 索引

  • 指定数据和控制流

    • 发布消息

    • 查找消息

  • 构建社交媒体平台应用程序

    • 编写 Solidity 合约

    • 创建 JavaScript API

    • 测试与 Waffle 和 Chai 的合同

设计社交媒体平台

要设计一个去中心化的区块链社交媒体平台,我们需要考虑如何存储信息以及如何访问它。

信息存储

向区块链提供信息的唯一方法是将其作为交易的一部分。 一旦交易被添加到一个区块中,它就会成为区块链永久记录的一部分。 这并不意味着存储的信息易于搜索。

一旦数据进入区块链,我们就可以对它采取额外的行动,但我们在区块链上所做的一切都需要花钱。 出于这个原因,最好将自己限制在启用功能绝对必要的操作上。

索引

在撰写本文时,以太坊区块链中有 超过 1500 万个区块 。 下载所有这些以查找消息是不可行的。 因此,我们将保留一个索引,该索引由地址和数组之间的映射组成。

对于每个地址,该数组将包含发布该地址的块的序列号。 用户应用程序收到此列表后,可以查询以太坊端点以检索块,并在其中搜索消息。


超过 20 万开发人员使用 LogRocket 来创造更好的数字体验 了解更多 →


指定数据和控制流

接下来,我们需要确定用户将如何发布消息以及他们将如何查找消息。

发布消息

发布消息需要两个操作:

  • 将消息写入事务的一部分

  • 将消息的块添加到索引中

这是我们将用于实现消息发布的流程:

  1. 用户应用程序将交易与消息一起发送到链上合约; 消息自动写入以太坊永久记录

  2. 合约验证它是由交易直接调用的,而不是由另一个智能合约调用的。 这一步是必要的,因为我们用来查找消息的算法只有在直接调用时才有效(因为它查看事务)

  3. 合约识别发送者和当前区块号

  4. 合约将块号附加到发送者的消息块数组中。 如果发送方还没有消息块数组,则无关紧要,因为它被视为零长度数组

查找消息

这是我们将用来使用户能够查找、阅读和解释消息的流程:

  1. 用户应用程序使用与请求消息相关联的地址调用链上合约。 因为这是一个 view函数 (只读函数),它只在单个节点上执行,不消耗任何气体

  2. 用户应用程序读取列表中的块,包括它们的交易,并过滤它们以找到满足这些条件的相关交易:

    • 有我们正在寻找的发件人作为来源

    • 有 Chirper合同作为目的地

    • (可选)具有正确的函数签名。 仅当我们在 Chirper 中有多个接受交易的功能时才需要这样做; 如果我们只有一个帖子的函数,那么我们不需要检查函数签名

  3. 用户应用程序将事务调用数据转换为字符串以取回用户发布的帖子

  4. 用户应用程序将块号转换为时间戳

  5. 用户应用程序向用户显示帖子(或其中的一个子集)

构建社交媒体平台应用程序

本文中使用的应用程序源代码可在 GitHub 上 获得。 它包含两个文件, 一个 Solidity 合约 和 JavaScript 代码 ,其中包括 API(如何使用合约)和测试(如何验证合约正常工作)。

编写 Solidity 合约

我们将使用最小合约在区块链上实现社交网络。

最初的代码行指定了 的Solidity 编程语言 用于编译合约 的许可和版本。 Solidity 仍在快速发展,其他版本,无论是更早的(v0.7.x)还是更高的(v0.9.x)都可能无法正确编译合约。

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

接下来,我们定义合约:


来自 LogRocket 的更多精彩文章:

  • 不要错过 The Replay 来自 LogRocket 的精选时事通讯

  • 了解 LogRocket 的 Galileo 如何消除噪音以主动解决应用程序中的问题

  • 使用 React 的 useEffect 优化应用程序的性能

  • 之间切换 在多个 Node 版本

  • 了解如何 使用 AnimXYZ 为您的 React 应用程序制作动画

  • 探索 Tauri ,一个用于构建二进制文件的新框架

  • 比较 NestJS 与 Express.js


contract Chirper {

然后,我们包含包含发布到此合约的每个地址的块列表的数据结构。

    // The blocks in which an address posted a message
    mapping (address => uint[]) MessageBlocks;

这是链下应用程序调用以发布信息的函数。

    function post(string calldata _message) external {
        // We don't need to do anything with the message, we just need it here
        // so it becomes part of the transaction.

我们真的不需要 _message,它只是一个参数,以便链下代码将其放入交易中。 但是,如果我们不对它做任何事情,编译器会抱怨。 所以我们将包括它以避免这种行为!

        (_message);

现在,如果消息在事务本身中,则只能在事务中查看消息。 如果 Chirper合同被另一个合同在内部调用,这不会发生; 因此,我们不支持这一行动。

        require(msg.sender == tx.origin, "Only works when called directly");

注意 ,这是教育代码,为简单而优化; 在生产系统中,我们可能会以更高的 gas 成本支持内部调用,而是将这些特定的帖子存储起来

来自同一用户的多个帖子可以添加到同一块中。 发生这种情况时,我们不想浪费资源多次写入块号。

        // Only add the block number if we don't already have a post
        // in this block
        uint length = MessageBlocks[msg.sender].length;

如果列表为空,那么当前块当然不在其中。

        if (length == 0) {
            MessageBlocks[msg.sender].push(block.number);

如果列表不为空,则最后一个条目位于索引处 length-1. 如果列表中的任何条目是当前块,则它将是最后一个条目。 因为块序号只会增加,所以检查最后一个条目是否小于当前块号就足够了。

        } else if (MessageBlocks\[msg.sender\][length-1] < block.number) {

我们使用 push函数 将值添加到数组的末尾。

            MessageBlocks[msg.sender].push(block.number);
        }
    }   // function post

此函数返回特定发件人的阻止列表。

    function getSenderMessages(address sender) public view 
        returns (uint[] memory) {
        return MessageBlocks[sender];
    }   // function getSenderMessages

}   // contract Chirper

创建 JavaScript API

现在我们将创建 JavaScript API 以使用户能够与智能合约进行交互。

将 JavaScript API 放在一个单独的模块中会使事情变得不必要地复杂化。 的测试文件顶部看到代码 相反,您可以在 GitHub 存储库中 。

消息数据以十六进制数字的格式发送,表示消息字符的 ASCII 码,用零填充,长度为 64 个字符的整数倍。 例如,如果消息是 Hello, 我们得到的数据是 "48656c6c6f0000…0000".

我们使用以下函数将从 ethers.js 库 中获取的数据转换为普通字符串:

const data2Str = str => {

首先,我们将这个单个字符串拆分为一个数组,使用 String.match和一个正则表达式。

[0-9a-f]匹配单个十六进制数字; 这 {2}告诉程序匹配其中两个。 周围的斜线 [0-9a-f]{2} 告诉系统这是一个正则表达式。 这 g指定我们想要一个全局匹配,以匹配与正则表达式匹配的所有子字符串,而不仅仅是第一个。

在这个调用之后,我们有一个数组, ["48", "65", "6c", "6c", "6f", "00", "00" … "00"]

  bytes = str.match(/[0-9a-f]{2}/g)

现在,我们需要删除所有这些填充零。 一种策略是使用 filter功能。 filter接收一个函数作为输入,并仅返回该函数返回的数组成员 true. 在这种情况下,只有那些不等于的数组成员 "00".

  usefulBytes = bytes.filter(x => x != "00")

下一步是添加 0x到每个十六进制数,以便正确解释它。 为此,我们使用 map功能。 Map 还接受一个函数作为输入,它在数组的每个成员上运行该函数,并将结果作为数组返回。 在这个电话之后,我们有 ["0x48", "0x65", "0x6c", "0x6c", "0x6f"]

  hexBytes = usefulBytes.map(x => '0x' + x)

现在,我们需要将 ASCII 码数组转换为实际的字符串。 我们使用 String.fromCharCode. 但是,该函数需要为每个字符使用单独的参数,而不是数组。 语法 ..["0x48", "0x65", "0x63" etc.]将数组成员转换为单独的参数。

  decodedStr = String.fromCharCode(...hexBytes)

最后,前六个字符并不是真正的字符串,而是元数据(例如,字符串长度)。 我们不需要这些字符。

  result = decodedStr.slice(6)
  return result
}  // data2Str

这是从特定发件人获取所有消息的函数 Chirper合同:

const getMsgs = async (chirper, sender) => {

首先,我们调用 Chirper 来获取包含相关消息的块列表。 这 getSenderMessages方法返回一个整数数组,但因为以太坊整数的范围可达 2^256-1,所以我们收到一个 BigInt 值数组。 这 .map(x => x.toNumber())把它们变成我们可以用来检索块的普通数字。

  blockList = (await chirper.getSenderMessages(sender)).map(x => x.toNumber())

接下来,我们检索块。 这个操作有点复杂,我们一步一步来。

要检索区块,包括区块头和交易,我们使用 ethers.js 函数 provider.getBlockWithTransactions().

JavaScript 是单线程的,所以这个函数会立即返回一个 Promise 对象。 我们可以告诉它等待通过使用 async x => await ethers…,但那将是低效的。

相反,我们使用 map创建一系列的承诺。 然后我们使用 Promise.all等到所有的承诺都得到解决。 数组 这给了我们一个Block 对象 。

  blocks = await Promise.all(
    blockList.map(x => ethers.provider.getBlockWithTransactions(x))
  )

timestamp是块的函数,而不是交易。 在这里,我们创建了一个从块号到时间戳的映射,以便我们稍后可以将时间戳添加到消息中。 块号包含在每个 Transaction 对象 中。

  // Get the timestamps
  timestamps = {}
  blocks.map(block => timestamps[block.number] = block.timestamp)

每个 Block 对象都包含一个交易列表; 然而, map给了我们一个交易数组。 在单个数组中处理事务更容易,所以我们使用 Array.flat()把它弄平。

  // Get the texts
  allTxs = blocks.map(x => x.transactions).flat()

现在我们拥有了包含我们需要的交易的区块中的所有交易。 然而,这些交易中的大部分都是无关紧要的。 我们只想要来自我们想要的发件人的交易,其目的地是 Chirper 本身。

如果 Chirper 有多个方法,我们将需要过滤控制调用什么方法的数据的前四个字节。 但是由于 Chirper 只有一种方法,所以这一步是不必要的。

  ourTxs = allTxs.filter(x => x.from == sender && x.to == chirper.address)

最后,我们需要将交易转换为有用的消息,使用 data2Str我们之前定义的函数。

  msgs = ourTxs.map(x => {return {
    text: data2Str(x.data),
    time: timestamps[x.blockNumber]
  }})
​
  return msgs
}   // getMsgs

此函数发布一条消息。 相比之下 getMsgs,这是对区块链的一个微不足道的调用。 它一直等到事务实际添加到块中,以便保留消息的顺序。

const post = async (chirper, msg) => {
  await (await chirper.post(msg)).wait()
}    // post

电视家TV,超清影视秒播不卡顿,老牌直播盒子无广告!

测试与 Waffle 和 Chai 的合同

我们将使用 Waffle 编写合约测试,Waffle 是一个与 ethers.js 一起使用的智能合约测试库。 请参阅本教程以 了解有关使用 Waffle 测试以太坊合约 的更多信息。

我们将使用 Chai 库 进行测试。

const { expect } = require("chai")

Chai 的工作方式是你 describe各种实体(在这种情况下, Chirper合同)与 async()成功或失败的函数。

describe("Chirper",  async () => {

在 - 的里面 describe你有的功能 it实体应该具有的行为的功能。

  it("Should return messages posted by a user", async () => {
    messages = ["Hello, world", "Shalom Olam", "Salut Mundi"]

我们的第一步是部署 Chirper使用合同 ContractFactory,像这样:

    Chirper = await ethers.getContractFactory("Chirper")
    chirper = await Chirper.deploy()

接下来,我们发布数组中的所有消息。 我们 await让每个帖子在下一个帖子之前发生,这样我们就不会让消息乱序并导致下面的相等比较失败。

    for(var i=0; i<messages.length; i++)
      await post(chirper, messages[i])

这 getSigners函数 获取我们的客户拥有凭据的帐户。 第一个条目是默认值,所以它是 post使用的功能。

    fromAddr = (await ethers.getSigners())[0].address

接下来,我们调用 getMsgs获取消息。

    receivedMessages = await getMsgs(chirper, fromAddr)

这种使用 map让我们检查我们发送的消息列表是否等于我们收到的消息列表。 里面的函数 map可以接受两个参数:列表中的值及其位置。

    messages.map((msg,i) => expect(msg).to.equal(receivedMessages[i].text))
​
  })   // it should return messages posted ...

检索正确的消息是不够的。 为了证明应用程序正常工作,我们还必须证明应该过滤掉的消息实际上被过滤掉了。

  it("Should ignore irrelevant messages", async () => {  
    Chirper = await ethers.getContractFactory("Chirper")
    chirper1 = await Chirper.deploy()

要创建来自不同地址的消息,我们需要获取该地址的钱包。

    otherWallet = (await ethers.getSigners())[1]

然后,我们使用 connect函数 创建一个新的 Chirper与新签名者的合同对象。

    chirper1a = chirper1.connect(otherWallet)    

从我们正在寻找的地址发送的消息,但发送到另一个地址 chirper例如,也无关紧要。

    chirper2 = await Chirper.deploy()
    await post(chirper1, "Hello, world")
    // Different chirper instance
    await post(chirper2, "Not relevant")
    // Same chirper, different source address
    await post(chirper1a, "Hello, world, from somebody else")
    await post(chirper1, "Hello, world, 2nd half")
    await post(chirper2, "Also not relevant (different chirper)")
    await post(chirper1a, "Same chirper, different user, also irrelevant")
​
    receivedMessages = await getMsgs(chirper1, 
        (await ethers.getSigners())[0].address)
    expected = ["Hello, world", "Hello, world, 2nd half"]
    expected.map((msg,i) => expect(msg).to.equal(receivedMessages[i].text))     
  })   // it should ignore irrelevant messages
​
}) //describe Chirper

结论

在本文中,我们演示了如何构建一个在以太坊区块链上运行的去中心化社交媒体平台 Chirper。

与 Facebook 或 Twitter 相比,向我们的区块链平台发布消息会导致用户付费。 这是可以预料的。 去中心化系统的成本高于中心化系统。 因此,我们可能不太可能像在免费社交网络上看到那么多猫图片或政治模因!

另一方面,我们的 Chirper 区块链社交媒体平台提供了一些优势。

首先,它是永久不可更改的记录。 其次,数据在链上公开可用,业务逻辑是开源的,与用户界面解耦。 这意味着用户可以切换 UI,同时保留对相同数据的访问权限,而不是绑定到特定提供商的用户界面。

由于更好的用户界面不需要为了获得认可而与网络效应作斗争,因此会有更多的实验和竞争空间,从而带来更好的用户体验。

我希望你喜欢这篇文章。

加入 Bitso 和 Coinsquare 等使用 LogRocket 主动监控其 Web3 应用程序的 组织

影响用户在您的应用程序中激活和交易的能力的客户端问题可能会严重影响您的底线。 如果您对监控 UX 问题、自动显示 JavaScript 错误以及跟踪缓慢的网络请求和组件加载时间感兴趣,请 尝试 LogRocket 。

LogRocket 就像一个用于 Web 和移动应用程序的 DVR,记录您的 Web 应用程序或网站中发生的一切。 无需猜测问题发生的原因,您可以汇总和报告关键前端性能指标、重放用户会话以及应用程序状态、记录网络请求并自动显示所有错误。文章来源地址https://www.toymoban.com/news/detail-796787.html

到了这里,关于设计和构建区块链社交媒体平台的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【毕业设计】微信小程序之二手车交易商城平台的设计与实现 后台php+mysql(附论文 源码 讲解)

    摘 要 在移动互联网的迅速发展推进下,微信成了人们生活中不可缺少的一款信息交流和沟通平台。而微信小程序的推出,便得现在人们在日常生活中更多的是通过手机微信平台进行安装各种各样的APP小程序来满足个人所需。二手车微信小程序是基于满足当前人们对二手车买

    2024年02月07日
    浏览(59)
  • 微信小程序之二手车交易商城平台的设计与实现 后台php+mysql(附论文 源码 讲解)

    摘 要 在移动互联网的迅速发展推进下,微信成了人们生活中不可缺少的一款信息交流和沟通平台。而微信小程序的推出,便得现在人们在日常生活中更多的是通过手机微信平台进行安装各种各样的APP小程序来满足个人所需。二手车微信小程序是基于满足当前人们对二手车买

    2024年02月06日
    浏览(55)
  • 交易履约之结算平台实践

    京东科技业务在快速发展的同时,产生了众多线上化资金结算的需求。传统的线下资金结算模式有着人力成本高、耗时长、多方沟通协调成本高、结算准确率低等固有缺点,且无法满足“风法财审”对于资金流程的管控要求,在此背景下金道结算平台孕育而生。本文从系统建

    2024年02月08日
    浏览(40)
  • 去中心化社交媒体:分析 Facebook 在区块链平台上的角色

    在当今数字时代,社交媒体已经成为人们日常生活中不可或缺的一部分。然而,随着人们对数据隐私和信息控制的关注不断增加,传统的中心化社交媒体平台也面临着越来越多的质疑和挑战。为了应对这些挑战,越来越多的人开始探索去中心化社交媒体平台,其中包括运用区

    2024年04月16日
    浏览(47)
  • 某省公共资源交易电子公共服务平台学习案例

    声明:本文仅限学习交流使用,禁止用于非法用途、商业活动等。否则后果自负。如有侵权,请告知删除,谢谢!本教程也没有专门针对某个网站而编写,单纯的技术研究 目标案例:aHR0cHM6Ly9nZ3p5ZncuZnVqaWFuLmdvdi5jbi9idXNpbmVzcy9saXN0Lw== 1.对应接口 2.对应难点 参数加密 数据加密 通过

    2024年02月08日
    浏览(42)
  • 数字藏品平台开发 NFT数字藏品交易网站开发

    数字藏品,就是指应用区块链应用,相匹配相应的著作、工艺品转化成的唯一数据凭据,在维护其数据出版权的根基上,完成真实有效的智能化发售、选购、个人收藏和应用。现阶段,小蚂蚁、腾讯官方、百度搜索以内的各种互联网大佬均进行了有关业务流程。以小蚂蚁集团

    2024年02月09日
    浏览(53)
  • 使用 OpenDAX v4 创建自己的加密交易经纪平台

    使用本教程,我们将使用OpenDAX WEB SDK从头创建一个加密交易平台,并通过交易页面、工具栏和图表启动并运行它。 OpenDAX WEB SDK为标准的WEB接口提供可重用的UI组件,可创建交换平台应用程序,包括UI组件和小部件。 所有组件都采用简单、现代的设计,可以原样使用,也可以用

    2024年02月06日
    浏览(36)
  • NFT交易系统平台开发流程解析 探索元宇宙应用场景

    元宇宙是近年来爆火的词语,也是互联网从web2.0时代向web3.0时代跨越的体现。 怎么理解元宇宙? 元宇宙是指虚拟世界,包括虚拟人物、虚拟IP、虚拟场景、虚拟消费......是伴随区块链、人工智能、虚拟现实技术发展下,区别于现实世界的产物。 当下,元宇宙深受品牌营销和

    2023年04月08日
    浏览(51)
  • uniapp - [微信小程序平台] 实现输入支付密码键盘弹框,uniapp小程序端底部弹起密码输入键盘组件效果,类似电商平台支付密码、弹出支付密码输入框、交易密码(详细示例源码,一键复制开箱即用!)

    在uniapp微信小程序端平台,详细实现底部弹出输入支付密码框组件,自定义密码输入框键盘功能(密码自动带星号、黑点保护隐私,自定义数字键盘),类似电商在付款时输入支付密码的组件。 直接复制组件源码,改下样式就能用了。 复制运行即可查看效果。

    2024年02月03日
    浏览(125)
  • 区块链与社交媒体革命:剖析Facebook的探索之路

    在当今数字化时代,社交媒体不仅是人们日常生活的一部分,更是连接世界的桥梁。然而,随着信息时代的发展,隐私泄露、数据滥用等问题愈发凸显,引发了对社交媒体平台的担忧和质疑。正是在这样的背景下,区块链技术作为一种去中心化、不可篡改的技术手段,逐渐被

    2024年04月09日
    浏览(80)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包