# Simple Summary (概述)
droplet 批量发单是指基于 go-graphsplit (opens new window) 工具实现一个能够批量发离线订单的工具,并且 DC 订单符合 DC 发单要求。
# Abstract (功能简介)
droplet-client 需要实现以下功能:
- 增加批量发布订单命令和接口
- 离线订单持久化存储,订单状态追踪
- 增加获取离线订单、订单分布情况接口
- 命令行可以输出离线订单信息和
DC订单分布信息 - 批量导入订单及聚合抵押
- 支持 f+ 对 LDN 发单要求,简称:
DC 发单要求
关联:
- [x] 提案的issue (opens new window)
# Motivation (来源/背景)
目前 droplet-client 一次只能发布一个订单,当有大量订单需要发布时,需要一个一个发,发单的效率并不高。批量发单可以一次对多个 SP 发布多个订单,可以提高效率。
# Specification (feature Spec)
# 名词解释
- 批量发单:指批量发布离线订单
- 订单:分普通订单和
DC订单,DC订单是被分配了datacap的订单 - SP:存储提供者
- 发单地址:发单时使用的地址,可以是具有
datacap的地址 - go-graphsplit:一种用于将数据集切分成固定大小的 car 文件的工具
- datacap 发单要求:
- Storage provider should not exceed 25% of total datacap(
client给一个SP发的DC订单不能超过SP总DC订单的 25%) - Storage provider should not be storing duplicate data for more than 20%(
SP不能超过 20% 的重复数据) - Storage provider should have published its public IP address(
SP需要公开公告 IP 地址) - All storage providers should be located in different regions(
SP需要位于不同地区)
- Storage provider should not exceed 25% of total datacap(
# 订单持久化
把离线订单存储到 badger 数据库,以 proposal cid 作为 key,把订单 JSON marshal 后的结果作为 value。
# 接口
droplet-client 新增接口
# 批量导入订单
ClientBatchDeal(ctx context.Context, params *client.DealsParams) (*client.DealResults, error)
# 获取 DC 订单分布情况
ClientGetVerifiedDealDistribution(ctx context.Context, providers []address.Address, client address.Address) (*client.DealDistribution, error)
# 查询所有离线订单
ClientListOfflineDeals(ctx context.Context) ([]client.DealInfo, error)
droplet 新增接口
# 批量导入离线订单数据
DealsBatchImportData(ctx context.Context, refs market.ImportDataRefs) ([]*market.ImportDataResult, error)
# 新增命令
- droplet-client 批量发单:支持对多
SP发布多个离线订单, - droplet-client 查询离线订单:能够查询单个订单和列出所有离线订单
- droplet-client 查询订单分布情况:可以按
SP和 发单地址查询 - droplet-client 导出离线订单:当订单状态为 StorageDealWaitingForData 时,导出订单 proposalcid 和 piececid
- droplet 批量导入订单:支持输入多个 proposalcid 和 car 文件组合,也支持根据文件导入
# Design Rationale (设计思路)
存储离线订单使用 JSON marshal 是为了方便以后加字段
根据用户使用 go-graphsplit 生成的 manifest.csv 文件内容来批量生成离线订单。
# Backwards Compatibility(兼容性)
需要兼容已有的发单逻辑
# Test Cases (测试用例)
# Security Considerations (安全考量)
# Implementation(实施)
# 查询离线订单
- 按 proposal cid 查询单个离线订单信息
- 列出所有离线订单信息
# 持久化订单数据
离线订单数据结构如下:
ClientDealProposal (opens new window)
types.ClientDealProposal
ProposalCID cid.Cid
DataRef *storagemarket.DataRef
Message string
State uint64
DealID uint64
AddFundsCid *cid.Cid
PublishMessage *cid.Cid
FastRetrieval bool
SlashEpoch abi.ChainEpoch
CreatedAt time.Time
UpdatedAt time.Time
接口:
type ClientOfflineDealRepo interface {
SaveDeal(ctx context.Context, deal *ClientOfflineDeal) error
GetDeal(ctx context.Context, proposalCid cid.Cid) (*ClientOfflineDeal, error)
ListDeal(ctx context.Context) ([]*ClientOfflineDeal, error)
ListDeal(ctx context.Context) ([]*types2.ClientOfflineDeal, error)
}
# 离线订单状态追踪
粗略的把订单分成 active 订单和 inactive 订单,循序检查订单状态,如果订单状态是 StorageDealActive 则为 active 订单,反之是 inactive 订单。
- active 订单:间隔一段较长时间去链上查询订单是否 slash
- inactive 订单:间隔较短时间使用 libp2p 去获取订单状态
# 批量发布订单接口
DealsParams (opens new window)
ClientBatchDeal(ctx context.Context, params *client.DealsParams) (*client.DealResults, error)
type DealResults struct {
Results []*DealResult
}
type DealResult struct {
ProposalCID cid.Cid
// Create deal failed
Message string
}
type DealsParams struct {
Params []*DealParams
}
# 统计 DC 订单分布情况
- 统计
SPDC订单数据重复率,重复率 = 不重复DC订单 /SP所有DC订单。
假如有两个 piece1,三个 piece3,则重复率 = 1 - (piece1+piece3) / (2 * piece1 + 3 * piece3)
- 统计发单地址分配给
SP的DC订单占比
# 获取 DC 订单分布情况
ClientGetVerifiedDealDistribution(ctx context.Context) (*PieceDistribution, error)
type ProviderDistribution struct {
Provider address.Address
// Total deal
Total uint64
// Uniq deal
Uniq uint64
// May be too large
UniqPieces map[string]uint64
// (Total-Uniq) / Total
DuplicationPercentage float64
}
type ReplicaDistribution struct {
// Datacap address
Client address.Address
// Total deal
Total uint64
// Uniq deal
Uniq uint64
// (Total-Uniq) / Uniq
DuplicationPercentage float64
// ProviderTotalDeal / Total
ReplicasPercentage map[string]float64
ReplicasDistribution []*ProviderDistribution
}
type DealDistribution struct {
ProvidersDistribution []*ProviderDistribution
ReplicasDistribution []*ReplicaDistribution
}