Filecoin:扇区到期续期/删除流程详情

BitRainforest
28 min readApr 20, 2022

背景

⾸批540天扇区⼤量到期、其他时间段的扇区陆续到期,其中包含可续期的扇区、不可续期的扇区。在这⾥给⼤家介绍扇区续期命令的详细⽤法、最佳实践以帮助⼤家消除疑惑、正确续期。如果你不想看下边的源码介绍,可以直接跳转到”到期扇区删除”、”未到期的如何查询”、”扇区续期实践”。

specs-actors 是filecoin的共识算法,相关源码在 https://github.com/filecoin-project/specs-actors,以下解释都为当前正在使⽤的逻辑。

specs-actors actor/builtin/miner/policy.go 中扇区生命周期的定义

// The maximum number of epochs past the current epoch that sector lifetime may be extended.
// A sector may be extended multiple times, however, the total maximum lifetime is also bounded by
// the associated seal proof's maximum lifetime.
const MaxSectorExpirationExtension = 540 * builtin.EpochsInDay // PARAM_SPEC

specs-actors actors/builtin/sector.go 中对于扇区的最⼤生命周期定义

// For V1 Stacked DRG sectors, the max is 540 days since Network Version 11
// according to https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0014.md
const EpochsIn540Days = stabi.ChainEpoch(540 * EpochsInDay)
// For V1_1 Stacked DRG sectors, the max is 5 years
const EpochsInFiveYears = stabi.ChainEpoch(5 * EpochsInYear)
// 540-day maximum life time setting for V1 since network version 11
var SealProofPoliciesV11 = map[stabi.RegisteredSealProof]*SealProofPolicy{
stabi.RegisteredSealProof_StackedDrg2KiBV1: {
SectorMaxLifetime: EpochsIn540Days,
},
stabi.RegisteredSealProof_StackedDrg8MiBV1: {
SectorMaxLifetime: EpochsIn540Days,
},
stabi.RegisteredSealProof_StackedDrg512MiBV1: {
SectorMaxLifetime: EpochsIn540Days,
},
stabi.RegisteredSealProof_StackedDrg32GiBV1: {
SectorMaxLifetime: EpochsIn540Days,
},
stabi.RegisteredSealProof_StackedDrg64GiBV1: {
SectorMaxLifetime: EpochsIn540Days,
},
stabi.RegisteredSealProof_StackedDrg2KiBV1_1: {
SectorMaxLifetime: EpochsInFiveYears,
},
stabi.RegisteredSealProof_StackedDrg8MiBV1_1: {
SectorMaxLifetime: EpochsInFiveYears,
},
stabi.RegisteredSealProof_StackedDrg512MiBV1_1: {
SectorMaxLifetime: EpochsInFiveYears,
},
stabi.RegisteredSealProof_StackedDrg32GiBV1_1: {
SectorMaxLifetime: EpochsInFiveYears,
},
stabi.RegisteredSealProof_StackedDrg64GiBV1_1: {
SectorMaxLifetime: EpochsInFiveYears,
},
}

specs-actors actors/builtin/sector.go 中对于交易的⽣命周期定义

// Minimum deal duration.
var DealMinDuration = abi.ChainEpoch(180 * builtin.EpochsInDay) // PARAM_SPEC
// Maximum deal duration
var DealMaxDuration = abi.ChainEpoch(540 * builtin.EpochsInDay) // PARAM_SPEC

SealProof 对应表

const (
RegisteredSealProof_StackedDrg2KiBV1 = RegisteredSealProof(0)
RegisteredSealProof_StackedDrg8MiBV1 = RegisteredSealProof(1)
RegisteredSealProof_StackedDrg512MiBV1 = RegisteredSealProof(2)
RegisteredSealProof_StackedDrg32GiBV1 = RegisteredSealProof(3)
RegisteredSealProof_StackedDrg64GiBV1 = RegisteredSealProof(4)
RegisteredSealProof_StackedDrg2KiBV1_1 = RegisteredSealProof(5)
RegisteredSealProof_StackedDrg8MiBV1_1 = RegisteredSealProof(6)
RegisteredSealProof_StackedDrg512MiBV1_1 = RegisteredSealProof(7)
RegisteredSealProof_StackedDrg32GiBV1_1 = RegisteredSealProof(8)
RegisteredSealProof_StackedDrg64GiBV1_1 = RegisteredSealProof(9)
)

以上⼏段代码,⽤通俗易懂的说法就是:扇区的⽣命周期范围为180–540天,默认情况会⾃动设置540天左右,V1版本的扇区最⼤的寿命是540天,V1_1版本的扇区最⼤的寿命是5年,续期时会根据扇区类型选择可以续期的策略。

相当于扇区可以续期多次,但是扇区有最⼤的⽣命时长。举例:

你租房东的房⼦,每次签订⼏个⽉到⼏年不等的租期,但房东的房⼦有使⽤年限,会有不能续租的⼀天。续期时扇区可以续⾄180–540天,假设你有⼀个扇区现在还剩下30天且是V1_1的扇区,那么你可以为此扇区增加150–510天;假设你的扇区还剩下90天且是V1_1扇区,那么你可以为此扇区增加90–450天。以此类推,注意不是增加180–540!!!

V1的扇区总的寿命只有540天,所以如果你在最开始改动代码设置封存180天的扇区,那么你可以续期360天。

可能有朋友会有疑问,我改了配置⽂件封存180天的扇区,为什么查询却是210天左右?答:确实是的,它会⾃⼰增加30天左右,此处是因为之前的版本升级让ProveCommit消息可以在PreCommit消息之后30天左右发送,当时的⽬的是为了节省gas费⽤。

上边也有deal相关的参数,deal本身的⽣命周期也是180–540天,但是它没有最⼤的寿命⼀说。扇区的⽣命周期会以其中的deal最久的设定扇区的周期。

那怎么看扇区是V1还是V1_1版本的呢?

从时间线来看2020.11.25⽇前封装的都是V1版本的扇区,在这之后都是V1_1版本的扇区使⽤lotus state sector miner sectorid命令得出的结果其中的字段SealProof对照上边的SealProof对应表就可以得出结果。如SealProof:5那说明就是V1_1版本的2K环境的扇区;如SealProof:8就是当前主⽹32G的扇区,SealProof有辨别⽹络版本和扇区⼤⼩的属性。

环境

官⽅原版⽆改动,本地localnet作为演示环境。搭建⽅法

lotusversion1.15.1+2k+git.731da455d

lotus-minerversion1.15.1+2k+git.731da455d

扇区种类详情

扇区链上状态种类

type Partition interface {
// AllSectors returns all sector numbers in this partition, including faulty, unproven, and terminated sectors
// List all sector BitFields of a partition(简单理解就是扇区编号)
AllSectors() (bitfield.BitField, error)
// Subset of sectors detected/declared faulty and not yet recovered (excl. from PoSt).
// Faults ∩ Terminated = ∅
// 列出 partition faulty 的扇区,扇区在没有正常做 wdpost 或者扇区因为某些原因没有正常提交证明,此状态中会增加扇区
FaultySectors() (bitfield.BitField, error)
// Subset of faulty sectors expected to recover on next PoSt
// Recoveries ∩ Terminated = ∅
// 列出 partition Recovering 的扇区,扇区在 faulty 后,下次证明前1⼩时会触发恢复检查逻辑,发送 Recovering 消息。(恢复前必须发送 Recovering 消息,不然是⽆法做证明的)注意还有恢复截⽌时间 FaultCutoff
RecoveringSectors() (bitfield.BitField, error)
// Live sectors are those that are not terminated (but may be faulty).
// 列出 partition Live 的扇区,此类是正常需要提交证明扇区的集合。到期的扇区会在⼀定时间后从这⾥移除。
LiveSectors() (bitfield.BitField, error)
// Active sectors are those that are neither terminated nor faulty nor unproven, i.e. actively contributing power.
// 列出 partition Active 的扇区,此类是证明成功过的扇区的集合。
ActiveSectors() (bitfield.BitField, error)
// Unproven sectors in this partition. This bitfield will be cleared on
// a successful window post (or at the end of the partition's next
// deadline). At that time, any still unproven sectors will be added to
// the faulty sector bitfield.
// 列出 partition Unproven 的扇区,此类是封存后扇区第⼀次上链时会存在这个地⽅,证明成功过后,会从当中移除。
UnprovenSectors() (bitfield.BitField, error)
}

已经到期的扇区如何删除

这个地⽅的筛选逻辑是查看本地的SectorsList然后跟链上AllocatedSectors取交集,然后去掉LiveSectors、UnprovenSectors,再去掉处于PreCommit后ProveCommit前的扇区,再去查询扇区状态不是Removed的扇区,最后将这部分扇区Remove(这个操作等同于⽤命令⾏lotus-miner sectors remove — really-do-it sectorNum)

部分朋友的 lotus-miner 仓库丢失过数据或者从链上恢复过 miner,此命令就不能完美删除过期的扇区,需要注释掉相应的逻辑以强制执⾏下去。

推荐使⽤命令lotus-miner sectors expired删除过期扇区。

命令解释

root@ESXI-4-6:~# lotus-miner  sectors expired -h
NAME:
lotus-miner sectors expired - Get or cleanup expired sectors
USAGE:
lotus-miner sectors expired [command options] [arguments...]
OPTIONS:
--show-removed show removed sectors (default: false) # 默认不会打印已经 removed 的扇区,如果有需要可以开启
--remove-expired remove expired sectors (default: false) # 如果想执⾏删除操作,需要加这个参数
--expired-epoch value epoch at which to check sector expirations (default: WinningPoSt lookback epoch) # 这个参数相当于筛选多少⾼度以前过期且符合删除逻辑的扇区,默认为 900 ⾼度
--help, -h show help (default: false)

删除操作

# 使⽤`lotus-miner sectors expired`命令,不加参数它会直接输出到屏幕`Sector State
root@ESXI-4-6:~# lotus-miner sectors expired
Expiration`信息
# 执⾏`lotus-miner sectors expired --remove-expired`,它会帮你筛选所有满⾜条件的扇区并警告你操作不可逆,并返回要继续执⾏应操作什么命令。
root@ESXI-4-6:~# lotus-miner sectors expired --remove-expired
Removing sectors:
Sector State Expiration
All 0 sectors listed above will be removedTo confirm removal of the above sectors, including
all related sealed and unsealed data, run:
lotus-miner sectors expired --remove-expired --confirm-remove-count=0 --expired-epoch=3766WARNING: This operation is irreversible# 跟上它返回的隐藏参数,你就能真正将扇区删除。
root@ESXI-4-6:~# lotus-miner sectors expired --remove-expired --confirm-remove-count=0 --expired-epoch=3766
Removing sectors:
Sector State Expiration
# 因为这⾥我没有到期的扇区,所以没有结果。

未到期的如何查询

推荐使⽤命令lotus-miner sectors check-expire来查询,⽬前原⽣没有其他⽐这更⽅便的批量查询⽅式,注意此命令只能查询 ActiveSectors(也就是过期的查不了)。

root@ESXI-4-6:~# lotus-miner sectors check-expire -h
NAME:
lotus-miner sectors check-expire - Inspect expiring sectors
USAGE:
lotus-miner sectors check-expire [command options] [arguments...]
OPTIONS:
--cutoff value skip sectors whose current expiration is more than <cutoff> epochs from now, defaults to 60 days (default: 172800) #查询当前过期时间⼩于多少天的扇区,默认是 60 天,注意单位是⾼度。
--help, -h show help (default: false)
# 如果你想查询所有的扇区信息,直接设定⼀个很⼤的值,就可以查询
root@ESXI-4-6:~# lotus-miner sectors check-expire --cutoff 5184000
ID SealProof InitialPledge Activation Expiration MaxExpiration MaxExtendNow
2 5 59.605 nFIL 122 (4 hours 51 minutes ago) 607922 (in 3 weeks 6 days) 5256122 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
4 5 59.605 nFIL 119 (4 hours 52 minutes ago) 607923 (in 3 weeks 6 days) 5256119 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
5 5 59.605 nFIL 121 (4 hours 51 minutes ago) 607924 (in 3 weeks 6 days) 5256121 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
6 5 59.605 nFIL 266 (4 hours 42 minutes ago) 608067 (in 3 weeks 6 days) 5256266 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
7 5 59.605 nFIL 264 (4 hours 42 minutes ago) 608067 (in 3 weeks 6 days) 5256264 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
8 5 59.605 nFIL 263 (4 hours 42 minutes ago) 608067 (in 3 weeks 6 days) 5256263 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
9 5 59.605 nFIL 265 (4 hours 42 minutes ago) 608067 (in 3 weeks 6 days) 5256265 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
10 5 59.605 nFIL 262 (4 hours 42 minutes ago) 608067 (in 3 weeks 6 days) 5256262 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)
11 5 59.605 nFIL 270 (4 hours 41 minutes ago) 608067 (in 3 weeks 6 days) 5256270 (in 34 weeks 5 days) 1559699 (in 10 weeks 2 days)

字段介绍

ID:扇区编号
SealProof:扇区的一个参数,具有辨别网络版本和扇区大小的属性
InitialPledge:初始质押,注意这里不包含交易的部分
Activation:扇区激活的高度,这里是 ProveCommit 消息上链无误的高度
Expiration:扇区过期的高度,这个地方是默认或者设定后在 PreCommit 消息上链无误后确认下来的
MaxExpiration:最大的可以续期到多少高度,上边因为是 localnet 环境,出块时间不是 30s ,只看高度是精准的。
MaxExtendNow:目前可以续期到多少高度

以上查出来的信息可以作为决策的依据还有后边续期方式的入参。

续期命令介绍

续期主要有以下两种命令:

1. lotus-miner sectors extend

2. lotus-miner sectors renew

直接先说结论,如果你想续期V1版本扇区你⽤第⼀个命令,如果你想续期V1版本之后的扇区 使⽤第⼆个命令(参数更多、更丰富)。

命令详解

root@ESXI-4-6:~# lotus-miner sectors extend -h
NAME:
lotus-miner sectors extend - Extend sector expiration
USAGE:
lotus-miner sectors extend [command options] <sectorNumbers...>
OPTIONS:
--new-expiration value new expiration epoch (default: 0) # 准备续期到的⾼度
--v1-sectors renews all v1 sectors up to the maximum
--v1-sectors renews all v1 sectors up to the maximum possible lifetime (default: false) # ⾃动判断 V1 版本扇区,并全部续期到最长的期限
--tolerance value when extending v1 sectors, don't try to extend sectors by fewer than this number of epochs (default: 20160) # extend sectors by fewer than this number of epochs (default: 20160) # 如果扇区过期到的⾼度跟要求它扩展到的⾼度的时间⼩于 7 天,那就不续期,因为可续期的天数太少没有意义,默认 7 天
--expiration-ignore value when extending v1 sectors, skip sectors whose current expiration is less than <ignore> epochs from now (default: 120) # 当扩展V1扇区时,跳过过期时间⼩于 xx 的扇区,默认 120 ,可以起到筛选扇区的作⽤
--expiration-cutoff value when extending v1 sectors, skip sectors whose current expiration is more than <cutoff> epochs from now (infinity if unspecified) (default: 0) # 当扩展V1扇区时,跳过过期时间⼤于 xx 的扇区,默认0,可以起到筛选扇区的作⽤ --help, -h show help (default: false)
root@ESXI-4-6:~# lotus-miner sectors renew -h
NAME:
lotus-miner sectors renew - Renew expiring sectors while not exceeding each sector's max life
USAGE:
lotus-miner sectors renew [command options] [arguments...]
OPTIONS:
--from value only consider sectors whose current expiration epoch is in the range of [from, to], <from> defaults to: now + 120 (1 hour) (default: 0) # 筛选从当前 +X ⼩时⾼度开始过期的扇区,默认 120 个⾼度
--to value only consider sectors whose current expiration epoch is in the range of [from, to], <to> defaults to: now + 92160 (32 days) (default: 0) # 筛选从当前 +X ⼩时⾼度开始过期的扇区,默认 92160 个⾼度
--sector-file value provide a file containing one sector number in each line, ignoring above selecting criteria # 以⽂件列表,每⾏⼀个扇区 ID 作为输⼊,进⾏定制化续期,这个参数加上后会忽略上边两个参数
--exclude value optionally provide a file containing excluding sectors # 以⽂件列表,每⾏⼀个扇区 ID 作为输⼊,去排除扇区,此参数可以跟上边三个参数共⽤
--extension value try to extend selected sectors by this number of epochs, defaults to 540 days (default: 1555200) #默认将扇区扩展 540 天
--new-expiration value try to extend selected sectors to this epoch, ignoring extension (default: 0) # 将扇区续期⾄某个⾼度
--tolerance value don't try to extend sectors by fewer than this number of epochs, defaults to 7 days (default: 20160) # 如果扇区过期到的⾼度跟要求它扩展到的⾼度的时间⼩于 7 天,那就不续期,因为可续期的天数太少没有意义,默认 7 天
--max-fee value use up to this amount of FIL for one message. pass this flag to avoid message congestion. (default: "0") # ⼀条消息最多可以使⽤多少 FIL
--really-do-it pass this flag to really renew sectors, otherwise will only print out json representation of parameters (default: false) # 真的做,需要敲这个,如果不敲,将返回筛选出的扇区信息
--help, -h show help (default: false)

实操续期/最佳实践

V1版本的扇区续期

直接使⽤默认的参数就可以达到最优的效果:lotus-miner sectors extend — v1-sectors 此命令是将V1版本的扇区全部续期⾄最长的期限,如有特殊需求可使⽤上边介绍的参数。

V1版本之后的扇区续期

actor v7版本每条消息最多能包含 25000 个扇区,所以⼀次性续期超过 25000 会⾃动拆分消息。 注意:确认续期请跟上参数 — really-do-it ,会返回续期消息 ID ,否则只是打印出构造好的序列化后的续期参数。

第⼀种续期⽅式extension使⽤ from + to或者lotus-miner sectors check-expire 筛选出想续期的扇区,使⽤ — extension 指定要将这部分扇区过期时间增加多久,⽐如想将原本还有30天的扇区,续期成还有 180 天,这个地⽅就写 150 天对应的⾼度个数。

如果要增加的⾼度⼤于它允许的最⼤过期⾼度,那就会续期⾄最⼤。

# 使⽤ from + to 筛选过期时间满⾜我们设定条件的扇区,对它们进⾏调整到 540 天的周期,它会去⾃动设定这些扇区的分别的到期时间
root@ESXI-4-6:~# lotus-miner sectors renew --from 607922 --to 607924 --extension 1555200
Renewing 3 sectors:
{
"Extensions": [
{
"Deadline": 1,
"Partition": 0,
"Sectors": "4",
"NewExpiration": 1561026
},
{
"Deadline": 2,
"Partition": 0,
"Sectors": "2,5",
"NewExpiration": 1561026
}
]
}
3 sectors renewed
# 将想续期的扇区放到⽂件中
root@ESXI-4-6:~# cat sectors.list
2
4
5
root@ESXI-4-6:~# lotus-miner sectors renew --sector-file sectors.list --extension 1555200
Renewing 3 sectors:
{
"Extensions": [
{
"Deadline": 2,
"Partition": 0,
"Sectors": "2,5",
"NewExpiration": 1561142
},
{
"Deadline": 1,
"Partition": 0,
"Sectors": "4",
"NewExpiration": 1561142
}
]
}
3 sectors renewed
# 只续期1个⾼度,需要指定 tolerance 为 0,因为默认忽略续期 7 天以内的扇区
root@ESXI-4-6:~# lotus-miner sectors renew --from 607922 --to 607924 --extension 1 --tolerance 0
Renewing 3 sectors:
{
"Extensions": [
{
"Deadline": 2,
"Partition": 0,
"Sectors": "2",
"NewExpiration": 607923
},
{
"Deadline": 2,
"Partition": 0,
"Sectors": "5",
"NewExpiration": 607925
},
{
"Deadline": 1,
"Partition": 0,
"Sectors": "4",
"NewExpiration": 607924
}
]
}
3 sectors renewed

第二种续期方式new-expiration使⽤ from + to 或者 lotus-miner sectors check-expire 筛选出想续期的扇区,使⽤ — new-expiration 指定要将这部分扇区过期时间扩展至哪个⾼度,⽐如想将原本还有 30天的扇区,续期成还有 180 天,那你就要计算出它当前的过期时间 + 150 天的⾼度。如果筛选跟你后边的要求符合(180<=⽣命周期<=540/最⼤寿命),那就会将所有的扇区续期⾄同一⾼度,它们会基本在同⼀时间段到期;

# 上⽂有这⼏个扇区的过期时间,我们假设需要给它只扩展⼏⼗个⾼度,指定 608000,相当于扩展了77左右的⾼度,注意看结果其实是空,接着往下⾛,解释在下边
root@ESXI-4-6:~# lotus-miner sectors renew --sector-file sectors.list --new-expiration 608000
nothing to extend
# 因为其中⼀个默认参数 --tolerance 是 7 天,所以我们把它设置为 0,也就是即使有⼀个⾼度可以续期,我也续期(夸张说法)
root@ESXI-4-6:~# lotus-miner sectors renew --sector-file sectors.list --new-expiration 608000 --tolerance 0
Renewing 3 sectors:
{
"Extensions": [
{
"Deadline": 2,
"Partition": 0,
"Sectors": "2,5",
"NewExpiration": 608000
},
{
"Deadline": 1,
"Partition": 0,
"Sectors": "4",
"NewExpiration": 608000
}
]
}
3 sectors renewed
# 将想续期的扇区放到⽂件中
root@ESXI-4-6:~# cat sectors.list
2
4
5
root@ESXI-4-6:~# lotus-miner sectors renew --sector-file sectors.list --new-expiration 608000 --tolerance 0
Renewing 3 sectors:
{
"Extensions": [
{
"Deadline": 2,
"Partition": 0,
"Sectors": "2,5",
"NewExpiration": 608000
},
{
"Deadline": 1,
"Partition": 0,
"Sectors": "4",
"NewExpiration": 608000
}
]
}
3 sectors renewed

⾄此,扇区续期、删除的解释完毕,如有问题可以Email(brf_alpha@greaterheat.com)交流。

本⽂为原创,转载请注明出处。

--

--