14个版本 (9个重大突破)

13.1.0 2024年7月15日
12.1.0 2024年6月25日
11.1.0 2024年6月13日
10.1.0 2024年5月21日
1.1.0 2023年10月27日

#1 in #encointer

Download history 90/week @ 2024-05-05 311/week @ 2024-05-12 548/week @ 2024-05-19 402/week @ 2024-05-26 547/week @ 2024-06-02 584/week @ 2024-06-09 247/week @ 2024-06-16 720/week @ 2024-06-23 443/week @ 2024-06-30 304/week @ 2024-07-07 793/week @ 2024-07-14 423/week @ 2024-07-21 561/week @ 2024-07-28 291/week @ 2024-08-04 372/week @ 2024-08-11 529/week @ 2024-08-18

1,814 每月下载量

GPL-3.0-or-later

210KB
4.5K SLoC

crates.io

pallet-encointer-bazaar

这个crate是Encointer区块链逻辑的一部分,基于substrate / polkadot-sdk

有关高级技术以及用例文档,请参阅我们的书籍

设计

这是一个设计文档WIP,并不总是反映当前的实现

class diagram

范围

Encointer bazaar应当

  • 尽可能遵循电子商务的GoodRelations词汇表
  • 与schema.org json兼容
    • LocalBusiness 许多商店可能已经为谷歌地图准备了这些
    • Product 任何提供的商品或服务。例如:一双鞋;音乐会门票;租用汽车;理发;或在线流式传输的电视剧集。
    • Offer / Demand 带有价格和交付方式

自定义rpc方法

为了良好的API性能和开发体验,encointer节点应提供对bazaar的方便查询。通常,查询仅涉及一个社区

bazaar_getMyLocalBusinesses(:AccountId)

返回:JsonArray<local_business: AccountId>

获取由who控制的全部业务。需要遍历所有代理账户,以查看哪些账户委托给who

bazaar_getLocalBusinesses(cid:CommunityIdentifier)

返回:JsonArray<(local_business: AccountId, json: url)>

获取特定社区的所有业务账户及其元数据URL

bazaar_getOfferings(cid:CommunityIdentifier,local_business?:AccountId,since?:区块编号)

返回: JsonArray<(offering: url)>

可选

  • local_business: 仅查询该业务提供的商品
  • since: 允许通过更新的区块高度进行过滤,以查询最新的条目

用例

  1. 业务管理
    • 创建业务
    • 编辑业务
    • 删除业务
  2. 商品管理
    • 创建商品
    • 编辑商品
    • 删除商品
  3. 查看(RPC)
    • 每个社区的业务
    • 每个社区的商品
    • 每个业务的商品

建议的存储模型

BusinessRegistry: double_map(CommunityId, BusinessAccountId) -> (business_url, last_oid)
OfferingRegistry: double_map((CommunityId, BusinessAccountId), OfferingId) -> (offering_url)

BusinessAccountId是匿名代理(即业务)的公钥。所描述的元组/三元组被封装在值类型对象中。

分派伪代码

createBusiness(CommunityId, business_url) {
  var BusinessAccountId = new AnonymousProxy(sender);
  BusinessRegistry.insert(CommunityId, 
                       BusinessAccountId, 
                       (business_url, 1, currrent_block_number));
}
  
updateBusiness(CommunityId, BusinessAccountId, new_business_url) {
  verify(BusinessAccountId, sender);
  BusinessRegistry.mutate(CommunityId, BusinessAccountId, (new_business_url, counter, current_block_number));
} 

deleteBusiness(CommunityId, BusinessAccountId) {
  verify(BusinessAccountId, sender);
  BusinessRegistry.remove(CommunityId, BusinessAccountId);
  OfferingRegistry.remove_prefix((CommunityId, BusinessId));
}

createOffering(CommunityId, BusinessAccountId, offering_url) {
  verify(BusinessAccountId, sender);
  var OfferingId = BusinessRegistry.get(CommunityId, BusinessAccountId).counter++
  OfferingRegistry.insert((CommunityId, BusinessAccountId), OfferingId, (offering_url, block_number));
  return OfferingId;
}
  
updateOffering(BusinessAccountId, OfferingId, new_offering_url) {
  verify(BusinessAccountId, sender);
  OfferingRegistry.mutate((CommunityId, BusinessAccountId), OfferingId, (BusinessAccountId, new_offering_url));
} 

deleteOffering(BusinessAccountId, OfferingId) {
  verify(BusinessAccountId, sender);
  OfferingRegistry.remove((CommunityId, BusinessAccountId), OfferingId);
}

RPCs

viewBusinesses(cid) {
  return BusinessRegistry.get(cid);
}
  
viewOfferings(cid) {
  return BusinessRegistry.get(cid).flatMap(bid -> OfferingRegistry.get(bid));
}

viewOfferings(bid) {
  return OfferingRegistry.get(bid);
}

性能考虑

对于特定业务提出的viewOfferings实现具有O(n)的复杂度。它应仅通过链外RPC进行评估。

复杂度 Vecmap 对于集合

操作 vec map
成员检查 数据库读取:O(1) 解码:O(n) 搜索:O(log n) 数据库读取:O(1)
更新 数据库写入:O(1) 编码:O(n) 数据库读取:O(1) 编码:O(1) 数据库写入:O(1)
迭代 数据库读取:O(1) 解码:O(n) 处理:O(n) 数据库读取:O(n) 解码:O(n) 处理:O(n)

迭代复杂度(其中vec会更好)是不相关的,因为bazaar pallet不进行迭代

显然,map 在大型n(无n较小调用数量的缺点)的情况下,在可调度weight方面具有更好的扩展性。此外,weight 是常数,与n 无关

移动应用或Web界面通常会获取给定cid的整个集合,因此Vec 更易于使用。然而,如果我们添加自定义RPC API来获取这些集合,我们可以提供一个方便的API,同时只对API节点产生轻微的额外负载

依赖项

~20–36MB
~603K SLoC