Relation ONE IM 介绍
Last updated
Last updated
Relation ONE IM是一个去中心化的隐私聊天协议。
实现了Relation Protocol,通过Relation Name Service来管理身份,通过Relationship来管理好友和群组。
使用Lit Protocol来进行消息加密和解密。
使用Arweave来做去中心化存储。
Relation ONE IM真正实现了去中心化和隐私性。
它主要有四部分组成(见图 1-1)
Client: 是一个前端应用程序,帮助用户加密/解密消息、发送消息至Proxy。并且需要调用Relation Protocol的标准接口来进行好友和群组管理。
Proxy: 是一个简单的后端程序,仅用于接收Client发来的消息,存储消息至Arweave并且推送至消息接收者。
Decentralized Storage(Arweave): 用于永久化存储加密的消息。
合约:一系列符合Relation Protocol的合约(Relation Name Service、Follow、DAO),用于存储用户信息、Follow信息、DAO信息。
流程见图 1-1
发消息的用户使用钱包连接至Client
在Client端使用Lit Protocol对消息进行加密
Client将加密消息发生至Proxy
Proxy将消息保存至永久化存储
Proxy通过websocket将消息推送至需要接收消息的Client
收消息用户在Client端使用Lit Protocol对消息进行解密
每一个以太坊的公私钥对就是一个身份。可以使用MetaMask等钱包来连接Client。
以太坊地址相当于用户的id,聊天的时候在消息体中指定接收人的地址,Proxy会将消息推送至目标地址登录的Client。
私钥用于对消息体进行签名,保证了消息是由该地址发出去的,并且不能被任何人修改。
该身份也用于登录Lit Protocol,用来在Client中加密或解密消息。
该身份需要在Relation Name Service注册一个SBT Token作为隐私聊天的准入条件。
Relation Name Service是由Relation部署的一个符合Relation Protocol的Name Service标准的合约。
Relation Name Service作为隐私聊天的准入条件,使用隐私聊天之前需要在Relation Name Service
合约注册,用户将会获得一个SBT Token。
在聊天时,从Relation Name Service
合约中获取对方的Name和头像等信息,可以更方便的我们找到和认出好友。
Relation Name Service合约主要提供以下接口:
注册:register(address owner, string calldata name, bool reverseRecord) external returns (uint)
设置头像:setProfileURI(string memory profileURI) external
获取用户名: nameOf(address addr) external view returns (string memory)
获取头像:profileURI(address addr) external view returns (string memory)
Client是一个前端应用程序,可以是web应用、Chrome插件、桌面应用程序,移动应用程序等,在Relation ONE中是一个Chrome 插件。
用户在登录到Client后,Client会通过WebSocket连接至Proxy。当有人给自己发消息时,Proxy主动会推送消息到Client,Client使用Lit对消息解密后就可以看到明文了。
用户在发消息前,Client按照消息结构组装消息体,使用Lit对消息体进行加密后再发送至Proxy。
由于消息是在Client进行加密和解密的,保证了数据的隐私性。
Relation ONE Proxy是一个后端应用程序,提供了一套REST Api接口(用于接收Client发送的消息、修改状态等)和一个WebSocket端口(用于推送消息至Client)。
Proxy会将Client发过来的消息存储至Arweave,由于所有消息都记录在去中心化存储中,因此Client并不是强依赖于某一个Proxy。即使Proxy宕机,Client在更换Proxy后,消息数据依然不会丢失。
Client通过REST Api接口将(加密)消息发送至Proxy,Proxy会根据永久化存储策略将消息存储至Arweave,同时通过WebSocket将消息推送至接收者登录的Client上。
未读消息数、屏蔽群消息、置顶消息等状态信息,由Proxy记录在自己的数据库中,用户连接到不同的Proxy时未读消息数不共享。
Proxy会将消息打包上传至Arweave,每个消息包里包含1条或多条消息。每个包上传至Arweave时,都会打一个tag,指向前一个交易的Hash。
永久化存储消息有三个策略:
每12小时将消息打包上传到Arweave上。
如果12小时内没有消息,将不会打包,然后重新计时12小时。
如果没有到定时任务触发的时候,消息的大小超过了100MB,立即将消息打包上传到Arweave。
Proxy需提供以下接口
发送消息
POST
/message/send
查询聊天内容
GET
/message/list?limit=${limit}&offset=${offset}
标记为已读
POST
/message/read?messageId=${messageId}
未读消息数
GET
/message/unreadCount
Long
聊天列表
GET
/chats/list?limit=${limit}&offset=${offset}
使用符合Relation Protocol的Follow合约来管理好友。
每个身份都会通过FollowRegister
创建一个Follow合约(见图 1-4),当Alicefollow
Bob的时候,只用调用Bob的Follow合约
的follow()
方法即可。
好友列表:通过FollowRegister
遍历出所有的Follow合约,再遍历出每个用户的follow信息。
关注:调用对方合约的follow()
方法。
取关:调用对方合约的unfollow()
方法。
使用符合Relation Protocol的DAO合约来管理群聊,该合约中所有持有Semantic SBT的地址即为群成员。
Client通过调用标准的DAO接口来进行成员管理。
例如:发起人通过DaoRegister
创建一个DAO合约。通过isFreeJoin()
方法设置群聊是否可以自由加入。通过调用join()
方法来加入群聊,通过调用remove(address addr)
方法离开群聊。(见图1-5)
创建群聊:在Client端调用DaoRegister
合约的deployDaoContract(address owner,string memory name) external returns (uint256)
方法创建一个新的群聊(见图 1-5)。
加入群聊:如果isFreeJoin()
设置为True
。可以通过join()
方法自由加入;如果为False
需要管理员通过addMember(address[] memory addr) external
来添加成员。
离开群聊:自己调用remove(address addr)
方法离开群聊。或者管理员调用remove(address addr)
方法移除某个成员。
设置群公告:群公告由群主向群里发送一条特殊的消息,发送时将kind
设置为3
。
群名称:通过name()
方法获取群名称。
群头像:通过daoURI()
方法获取群头像。
群成员:合约里所有持有SBT Token的地址即为群成员。
可以与好友进行聊天,也可以给非好友的以太坊地址发送消息。具体步骤:
Client(A)使用Lit对消息的payload
进行加密(accessCondition为接收方的以太坊地址),receiver
设置为对方的以太坊地址,按照消息结构组装成消息体后发送至Proxy。Proxy会将消息推送至接收方地址登录的Client(B)。
发送群消息时,用户A登录到Client(A)设置Lit对消息的payload
进行加密(accessCondition为群成员可见),receiver
设置为群聊的合约地址,按照消息结构组装成消息体后发送至Proxy。Proxy会将消息推送至每个群成员所在的Client(C)、Client(D)、Client(E)……
Client会集成Lit Protocol SDK,每条消息都在发送者的CLient加密,在接收者的Client解密。
如图 1-6,Alice
要给Bob
发送一条加密消息:Hi
。
Alice的Client会使用Lit SDK在本地对Hi
进行加密,得到消息密文encryptedString
和秘钥symmetricKey
:
Alice的Client设置accessControlConditions
为Bob的地址可见,并将accessControlConditions
和秘钥symmetricKey
上传到Lit的节点
Alice的Client组装Message
,并发送至Proxy。
Proxy将消息转发至Bob的Client。
Bob接收到Proxy推送的Message
后,去Lit节点校验通过后拿到加密秘钥_symmetricKey
:
Bob在本地对消息解密:
messageId
生成方法: 组装下面格式的json字符串,计算其Keccak256
kind
0: p2p message。
1: group message。
2: dao message。
3: announcement。
4: hide message。
Session Key:
在客户端生成一个公私钥对作为Session Key,把Session Key的公钥组装成delegationMessage
,使用用户的私钥对delegationMessage
进行签名,得到delegationSig
。
用户发消息时,使用Session Key的私钥对消息进行签名,并且带上delegationMessage
和delegationSig
,通过这个delegationChain,就能验证消息是由用户本人签名的。
sig
生成方法:
通过Session Key的私钥对messageId
进行签名即得到sig
。
1条或多条Message组成的数组称为一个消息包(Messages),它是以下格式:
文本消息
卡片消息
NFT
本地图片
表情包
群转账
公告
使用永久存储Arweave来存储加密消息,保证了数据的可靠性和去中心化。
Message由Proxy打包成Messages,上传至rweave上。每个Transaction都被打上一个tag,指向前一个Transaction的Hash。可以方便的根据最新Hash找到所有历史消息。
Relation Name Service
0x04C23dDfE813d8D208bc8120b73F8EF30f423850
0xe4AA1f1E5be0A4E7F80CAC26C2Db1611C3E70c41
-
FollowRegister
0xA0cECa90d7A2033f5162dc73391cdB72272456E7
-
0x734dE4f1b3a1c0619ECB80e3a676a6cFabe72Adc
DaoRegister
0x153C3eF051C7665c9A9c1a718bF12bC8EE6b5115
-
0x7229Dc0117E8484D61137B7304b02b163beC912c
[]
[]