From 67d4f905e6b880f044bd45dfadaf48d0fb072e70 Mon Sep 17 00:00:00 2001 From: LexLuthr <88259624+LexLuthr@users.noreply.github.com> Date: Tue, 6 Sep 2022 21:17:30 +0530 Subject: [PATCH] feat: proving: Introduce manual sector fault recovery (#9144) * rebase * fix lint error * fix errors * add itest * make gen after rebase * apply suggestion from review * make gen after latest rebase * gen after rebase * fix waitgroup * change as per review * refactor Recovery Batches * fix CLI * gen after rebase * close the channel --- api/api_storage.go | 5 + api/proxy_gen.go | 13 ++ build/openrpc/full.json.gz | Bin 28350 -> 28354 bytes build/openrpc/gateway.json.gz | Bin 4943 -> 4942 bytes build/openrpc/miner.json.gz | Bin 15263 -> 15449 bytes build/openrpc/worker.json.gz | Bin 5077 -> 5076 bytes cmd/lotus-miner/proving.go | 83 +++++++++++ documentation/en/api-v0-methods-miner.md | 32 +++++ documentation/en/cli-lotus-miner.md | 30 ++-- extern/filecoin-ffi | 2 +- itests/wdpost_config_test.go | 167 +++++++++++++++++++++++ node/impl/storminer.go | 21 +++ storage/wdpost/wdpost_run.go | 4 + storage/wdpost/wdpost_run_faults.go | 109 +++++++++++++++ storage/wdpost/wdpost_sched.go | 2 + 15 files changed, 459 insertions(+), 9 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 93bb1f869..4d05419d6 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -314,6 +314,11 @@ type StorageMiner interface { CheckProvable(ctx context.Context, pp abi.RegisteredPoStProof, sectors []storiface.SectorRef, expensive bool) (map[abi.SectorNumber]string, error) //perm:admin ComputeProof(ctx context.Context, ssi []builtin.ExtendedSectorInfo, rand abi.PoStRandomness, poStEpoch abi.ChainEpoch, nv abinetwork.Version) ([]builtin.PoStProof, error) //perm:read + + // RecoverFault can be used to declare recoveries manually. It sends messages + // to the miner actor with details of recovered sectors and returns the CID of messages. It honors the + // maxPartitionsPerRecoveryMessage from the config + RecoverFault(ctx context.Context, sectors []abi.SectorNumber) ([]cid.Cid, error) //perm:admin } var _ storiface.WorkerReturn = *new(StorageMiner) diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 274b9ee12..4c428d2b9 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -770,6 +770,8 @@ type StorageMinerStruct struct { PledgeSector func(p0 context.Context) (abi.SectorID, error) `perm:"write"` + RecoverFault func(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) `perm:"admin"` + ReturnAddPiece func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` ReturnDataCid func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` @@ -4617,6 +4619,17 @@ func (s *StorageMinerStub) PledgeSector(p0 context.Context) (abi.SectorID, error return *new(abi.SectorID), ErrNotSupported } +func (s *StorageMinerStruct) RecoverFault(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) { + if s.Internal.RecoverFault == nil { + return *new([]cid.Cid), ErrNotSupported + } + return s.Internal.RecoverFault(p0, p1) +} + +func (s *StorageMinerStub) RecoverFault(p0 context.Context, p1 []abi.SectorNumber) ([]cid.Cid, error) { + return *new([]cid.Cid), ErrNotSupported +} + func (s *StorageMinerStruct) ReturnAddPiece(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error { if s.Internal.ReturnAddPiece == nil { return ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 6beb0d65af84db6fa5835a7d37a4677615412cb0..0bf4574e23f3787455bbfbd2f1b9bd81eb109c52 100644 GIT binary patch delta 25681 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

6d-x?07OWQ6O8l~k(h8iLjVgp#?V6o_d^Bj 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 delta 25636 zcmV)vK$XA3-2uMc0kBsBfA++fYIfMs6nWR#Qt7tE3XN3mF}am$cT%B+>aEmrvy`c7 z*eyi@LKKP3!2l%S31oBPO(RNZ%$|ZNf&rfbPt*XE$W7ykHhyIs^85x8Lrv%fqq!^_ z6CXvv9FqyaVja&A;c^phEWP1A#z9c}g!*B&f0ETr#EbjAwqL$%e^}ecC_o&28vWI6 zRj1V}*7FdATfoEq#u4@xt?jg(URJe9m7tt~ib`!AVIM?d^)W;^0}wD2jGwDABe9D- z-3Iji2r-6yfYa7Cf4~U`m;tew)qo-RL&1?DfZ&Mw$OBJqr`VeUOnfX>xaeaR2ON9i z?eh?N*T_$M5xeIpfW!w7d=RCkkWDuR!@OAfRm>Y4&$mbaKo7y4Tjo#q<~wj_kB@fP zHJXKg(YwFHcur^GU!&O=&Br^tW4sg3_u?4sZr|(1#1EU)ssyKPXXlt;012c7ACXb}NIFiRt3h(wNybIH7B@KEKdBYOl4tLm; zM`U;B`sHLNCK2-gc{#o#yOY0O?CkhEba#jUO}4{r9NyhcqZ@B}g9hKft^`AWSIO0M zfs|&^d}B3#0x$LL3HV6t`|^Wp3)`1gmJL1WEuEM;+2xk(s>wcLEMx;TDjUiDmOU?a zn`Ms>Bc0`qcvdH4)F%*%;Yk?ypXBt~2p7?2uPUJ?vR-iX#P#)>vtd@cEVz+8qE|H~ zo9wcVl6z-qZRwArej5EHcVRn!m7vq6S6w~g%eUKmFPgV~-f5&W1IRbC*hth0X674T z8OSV+VKKxkP}bm)6+#1G0y8ercRraxj3^c}PD+5zH6B!sK55_dg1Y(6GydqV9-pb%|in2De zOLKr(V#N_ch5<^@b55UAf|N(E6sohlI8LOF2ZI1`S_4_q`pUal5^;omCy^hpM6TR6 z74o^RoRzeGbBDQ@)4~4caBwbHWVM`o2ifmTko>y4l*&4@JjPHx+7wPmU+(tH!xccU znj*nScEhJjh#fw)wBZkbLAYIM*MIgNLH}q9iLKJbr_DkqYp|zyLwWN4{Y86U5~){S^^1BD;423FT814S~AgAvf&4 z?EZ=X^*>J2Kf(WA5qa1T06#bokN-D$%nuJ_;e*2~0{-{;^XJcEo{>{^<@QR(u$d?b&eKP1Uv;OroGnXZ7+YX(NpyOyvyy~mwg%T8Gp z67#chMRFI-2~F;RSC=0eSGEZy&&3pE9Y7F3jv`g`iX?Zn6BAE=Y%u?k7n^HRjky@w zP&@`$Xe((EW5<8X_*e!8&}AHCb$t9`@$u~iVL;UE9?pAV;z=_$YcT+D_<|r|}gLN=M9u_)*$MfO-3TP)#B9ZQygXZt03(ax^{LZvvya#0jYv(QUGc4DS4N&ZEHaUX{-KI03(3KYe z3VE=Xfs0S0zeK%-=t4K%fG%`P?cqg6x5WWoLPwf1nL~~l#~w4%Bu^q3P79#p7drau z7j=C1%Lp>`i#*c`7|o!F^s-PU>hyYyXg`0Aeh-0<$Kxw9Li`r#lKhrx6~G~rhk;BQ zPbJ-#Su@P2*-mM4v*$KetPA{)zO#FZ$u$#ywlrPodN$XERA-Ma#MkatliQ+#OP`nU zbTM17_l8za4)NrKES7?17Y(A&Y_q*QER16T{zz%tli9yW7k&vUh%x*O#*~o^I{FsBuGmJcRBtKx6&1g2U*r`BB=%bTk zfeaVxF=o>ZW)Gvyc23a% zZ&BTjaoclkQE~ytUV>d~iWjl!ln{ecM<_u@DVKH(`5`mpT5jAQEB+yj^RcqO*L9At za*MyY6Kta+^HY`USf6@(j>ghTCi*=`_b8OFp2;?3O$^KeCF5XceO= zUv05Tc%6*ShEe6`se-C5#|WJnT9YkPZ)a=%&!^?@e!}E1lSO~h;_K;}RdakgD4Ks7k5RN3QYW1>Ub4s<>;S8c zVc1BUl%N!JGI?ae0G~n*rtk&<2s{*Vh>4Uf!`!Wkj8+DoP=Y|H&s?55XT}Es#~Zot zvq%1E1W)bv{z`wgpDJ##9UQlEvPmvGK5Rzc(KrIyWy+A|jx>!o8(MWS8N$W|3K| z^&O0%xed^ECRgjoQ`oRBB69(WZq;4Fk)Y}wB1f>RGmxrWheEZ!BT;DLQMka8p&IPR zl93W;gDrK(6GTv?#qH6-xw2=J9gD@|{xIWX(F+^l*;=?zJ~}ORyY7~P-W2jU z&^Rmouxs~>`NoRXM>M1i2E8VF)FFkWMv~+Ttg>&v&nM>WJ!@iHe* zU%t5uk;jpL9ILE6SDsg_Ni-+p!5j%g%ST9#UU=V^PTWYMaGOCN({TtlzJ3!i=d<6L!KbkQ$fz z{RfS`DXK82)b9CDe46OjU8g3Q0?9JPQs|3^tQ&`DowGc*3BC;!GEh$X=s6cpD->XZ z)@vh%!J&V+H(N}fv02-ZncI|A+ElhhtKJ$Zf=f*s zTeISAw#ixyGpp3)BsjMp+ggKiJH28&YKwLwOz!H6Hgg-hqlKv9yjroeAKh ztCii0+uiQ-Vq9wU|H)?o>$?A5G~R#de-D{-eC)XOlIlHVW68DGS3;H|k&E_P+J9zT zzMUd@u|D$(J32WQi(5J+2XpPJ?2Pdb))?<{vXq$0tKBB1axz=ua)YY8z#rf#c=AjY zJV$IXTTw-OJmpJ?T*Odx&v>S8H%MQASRloMH$VvaRE5M(Z#g*UfL=1arOSV$e3WLs z`ti3tRPXYXV{y)#!jz^}S7kDNXj;hY#>=Rum~qqI+f@@OwNss7>dRNNkXBt6bFotE zjb8N?U374-uNqMkzZ2y%`b?Jwt+3EBfI*N({@`g@I+izEm(E#LIr0kU;_6aXUdHa2 z?hzf+b@qC8r$9g38tx3;kLZ6C=)pQ)?`<~TB$pBz!C)!OBI?&-6>E>mw5eubqTB0= zMl`L9P>3QVK_F#MN`XmyS!M=(l%!cwH_biS%JTU$v%yvYkT#Bd&Xdo1@;OgF=gH?( zg!SVPOXvvBsn0p}Id#sdb55OePJPa)&pGuur@qJI)c3%wR9lU~s!o3~(`Vt!*r{|2 zb(Sji+Rjd;n`*RFsWKhyR2i*{EL9090cMR3uz!rlU&HQLBraxHh{F**7du^EG|daHPp z6{<6f_rQK~W3S*s#rJmhaTT7pU)$R8VE;ui5>{m_uX4bzMC00QFtZt^<&IW1K>|BR z9>O63ZWq{y>B3gB zGB-GT;{CO&IFrfav?prbVr3z)q`1)}l*1(*PF|KWCv}UqXc~m7_<;SV&yYu38t$hR z$i?wZ*8Qf)fLXZ!#ae#3|XN7y& z68H88clDgw!Q4&~VkLQR)()jt-t^ACWEmdj-dWxCmU_Qp#3o`$ygbZjLV6aH9Djg! zFb3BW%}m@`uii*e*7}ucSJe$XiyQhrfm|xd~1dkw8XlL zMo4379vpwi-D`}NbB<>81}zod!fc|B^Xh038z;vLlU-aCxLC>Kni^A;+#RJW6S$YBy9Vs2FnT^OIv~ zYoIdfm6)X7ws6hYSlNEw>AIa8!O*?HaAgbGj|o`i7~$#G-m9In9~)Bw0Xvg(9lC#V zx8^SPJILNJj%Sdgw+J1<_S?JELai1erju>x=n2v*Q>LDkKAGy>B@QnT{|(Kbf+y<9 zA)cI&#wdTK{u^##n{Bqbhg~(u#V(s=(vbeizyvZdMhJK?>`(W|&9J5Bp(SPFI%FdG zw-KG0zdusqX`i4!oV`-6Xz zVDmp0hf|OI*A)Htzy38C4l08@jgzJaEq`r2hSaFrVmV{n9jfa2v%#z8gtm4*(sOUq zkN((pt~}~HejCh?kL3~@VFIK18{$!4aBA@p8QR-5ZkQPA2kiiz)%xpzxS6G9(Alq~ z$(?w$xwc>T-~wItB`&aL+X#KV*eFU2AlzY79+BOh>z9+Am_*3`=jHg0>`wlAv46AU z@6g>H{x{hUw{duPH;rz*>5Yye`eU3GOaW6fk?Bhd{Ij{Duor6zQub%G<31TB}s?X$Yir45HW_)d?~hyk~|QJnbMmD;-9HuOZ6cQ9m+SZ$O#8y zhyw=jI4z_ea0<{J@?zd&tQd!79DkN^SZ1BEjKc-?xFErO_X7>CDLi;tb6qm)Io$ev0Rj*Wk_pA@^-f$yGBOOiftRYft&UXF%}zek&v0ei`yyW5@UoB_7GrG z8V5cYA%!`{Gy?F7ByfULFoib=Oz~t20(^}EJf+kJbPO=@f>`i7fC>1MjDO@wk9hbe zKq2*}tUu@xuXbPVZm;B~>e@MTH!79u%K9>z%k0_-Jf{f%7)kf4Cb)vZY_($a4z|DV zQ`t%jW%!x?ae;_`5hAa~fM2X>CF(MQdT}+X8)_@ty+Ko6ZIViQ`7~-i~ERFjZ z1wG!?ar&^+hn+sW&iZhXEq_|>(GT$MElOSG*yQ(EWo~(?{_lCkf0F+jv|Rm3SFM*; zLX{CX%mR=tUR*PHccL2H+8YjLm>9o!E)ZD{U(B6sEaeAQls`^9Iq~Gg(|U=gHC1O` z*Mvy=An(c^`2Habp!no%HJM@qZPGtf+3j*RH1NdYjzp1y1_ND^Vt=BI{!%f(#i~n* zCg}T2g$@9mszW|m1VE3|{vy7uvjytD+soF*WKx9<>RiMhxrg{q&Y-cL!r;|rO?(^0 zwca6qju?t=Pv%QRhccxuR&gLxHI8~G^)g8l#8n(UIHNJ)fQ}R9KZRTd znDOE$LWBo%5G9q8B!579ZXT{saMtR+cl1_Gz#6qO&ryINL)}7Cm78b-@$zu4_HIeJ zlVxw1RFd87q*Xygq<$pOE#0c4c{(rh$=in=6w1O0Weql`yJd2^^=i8&uugfocIE_G z6F*DYGig|fx>p#at-_b1OEZgvcSt`Ac_IFh@`-h()@gfA+kbng+TKo01Qf-xK4U)h zBY4|U8YIfkAjmlATjZkgMtbvRZ;EhaG)I|^mJ-(iTy|63Naj9;0b|h$$lHCU{g)g)w?G~ zKAxD7k5SC!XDq|7oY4!eKm3<(1LM~#8S{yb59b_J&VSbTwpkhTYsm1e>JYxHllOyO zvn?DF41b2ae^xrVc7ec>E!SeC*@o;m+H8Aw8*sLDyL~ESw>y_0=MvP>CCI3rW2Zlg zXQVL#TN7-Gzv&74?svAqnHDIx`4EfjF(EIW8ZE#sl zV11p>s(L)>;da>bGbYQRoBq*$+T>@1CsVGW z>3jV{!!%VwM*r>XPP6H0b$?tSFTC!*;kG#499-=ci2GunY8M)~ zD4;X$*Jc6>3wQmoN{P$fckRsF`1fJ@OA_)vX^I7|X#=eip=TAb+F(ZQcJos3I%WCY zs#gfwmci4@K%h$lpVOJ{tYbWC32=W^riZL9nP!1JXnNGk^?}`_diA0vjI(6y?~vrt zCx2v2yPcgG4YYEp7~zehDa1sYfa{_`e82>gNz(qpGd6>k{?6F)16=G@aXCd1k{852vlQb001aq2camo|2LH3xqM7N?nb~!2u&U=M2q6js8MyR!^iY1atmV zKhl5d>o8%}U!32I^LufAFKzu^41dXMD6&elcUQ?$AyL6x7y94#uhQn(!~^v2FZtqk z{FdtqtX|bbSUuo*$6L z^|~h8M;`nCPIweE-X$(#bvr-8xSe*kVk@^fC|h%PMw_kOTZPYv(|U}?k%xNBJmmzs z6X;H$JAv*5x-*A6bND)dv)7w-xeEj!IGQ3abG7b-%W_RLKr&tAETWvMkMZQo*Dqi7 zW7*0DhdgEr!C9`yMqF0ae1Ch8Rvh61e3mCKM3Gp;3wB05xu-X*%-$ zg5Xw6xI!^ckde7G%Wj@42O?GMvx3vq6tiG9U%m;LP~OX3 zFPIBlFxcN54nF;sjP*?vr5|7AyBrJ$@3FcY2}j;we`|Y3XhXS8-+yWQ>!Gysu~Z~m z1s#eaV-;jAB!dYd7gFmiN7Kf$`bDcIs1Ds4%TUZ_=jHdn;M7)K_K#HbpCKZ6P!Fi8 z(2{*NkY#{Xq0=9QugYV!fmuaj>(G`AA07lCROM5=r3_*aOz;gNk27_MWAl#9J2qcr z^V@YPVN%v}j=}(XsDB4GUuenJnQTcuU+DEm@%i##ZTNhV*aoe-#Nux;pMpp=Fhhhp zhcf3-=9J-kq6|CL)?prpd43G$*{Mr@CB<-nVEK^84&;ccb*M(nc~fe;w1K5l+L@#* z!W^GL~MlYF(N)>y^G+mw(hpe9(7@A5k*K<#?-B zt39n=vEs8-4QiRmatq;l+G0O(WQs&K?1QXl)eZwsAn<572Xy>YZULQ$Rc!?^+%cZC z+7S(LZ;d&s3w@g}V&e;b7GWA;K0omNs9fVzR0>by*(tr%kF+jwIDd=K zIpmm%=Nmi2!Ae;a6Ldsr;L}?&*x%bs|ChncPd6w+jN=(p0}(Y_x|r8B^{oOM<_BvV zs-Pq#^N!-Bk=ls(idm~5xbO+ALL=n9P&a6KpLyAflfWr?fA7`B%ahAYA=7S~TUV~z z+q@J2uj3_E-OmrWo0^Si0TW0_Nvzpssws*r8#60VK7tAi$ne6>XMmXy%Wu1`y(di+bWOb6&N!HGi z)g=#i$-`HUe|KItMJHQ2FquV6GP{Um-Ap};LXmYjs%jl<%%nnDW?>M_0b~L!Nz0*N z-$RL=*ibIw6i;a&bwzSWY9@pFh#f>pFbA>NUAI$2Kq}dO%|s6vV-)xdzzC6FcxF$& zB3Il%$7m-V|aYKDOez z{W&mq@Nat*P_G@p1!5_7 z0!yl{f29|rw04gJ3i;k{caKKZUF{ahu284_Aw0tdMos0#gX^HRlK>m<4Kzk!;>^dq79oNJsM>jGCKS0bwJj-Xq0G7{yV-%b&qB6W{h?R-H> zvhj2k2H2Fwfe%IqVB$pxGUTgv9_|(8e@2~qovGcqM^~sbs>>I@*LjX#+$(DL)+lgL zRgQsb|Fm{l2p*rAsGNkroohOK&Cj#fw9hdOM(^0VD#(5|McPq>>6w1{^bv2H?%hLTK-RDf3P^&TazSqW@i zAL5Bw&9&~uHD;|7V7i?GnmSwyg+PgTU=FSoT?1cOJ zc2}tMRcJtaP0k6=Gh1Q;-4dhXe`pSP1POzlm~C)!+zSRw`zy393ne&FLC{?NM~d0* zgDvkKU^fSx9B^{L$pNQ_2%KKm1u@QK|K%Nd54%J&E;Z2)jH*3JRzBv3cydCxbQ3KX zdYQHR3ViuGnsc-SD$~R28=PgcRp(DCMk0o=5Vs{1wuEm(Gx%T31WX%Ie?Be1E`6PN zDmqBaae_-Ajv}UF4Jt$66;VCGU;|tliD>9p69(nMIT#^Ti&KCIiz5W)G**!d^#HC2 zx`Q4M=CU`F98r=_F}aq1!3b^ii#SWC<-o?@H9{T^v2o2i|5~QL6vLGx8K|@ zJ6BIDr@(_jkXT`hLnzQMe{Z3BaseakrnaO_b&ZzcbW*32I-S(%qz_Oh-P)`RG|%v435VwP-pu`)@_Y7H zu5?wdR|p&Ylk4?BXS8>!#ywRv96)ja$pIt>kRBpH+NulVoXYuSe{A--7J4+<7tHh3 zksZ=DUM^vt&yApGz-4Egzjrunr3UM|t7y(%?Lg#xnd7p(dL1pm_dOuQeOR|;yS1|b zI|aunI8MQF3QkW7&URhQbpfCw1bH`aZdJ8TrAbwfZSdu5<$b;p-Z+{%&s1c+PeDd}aq?Ealn917Zoa&(b53w4r& zLV=hB)Vl_L9Lb=X3FKEVF~JZdO^n|vkzIvPs z(l6DJn51HoW_23Lg917>;QlWxLDhgyAy1t5Z!w?x5xgaUMu3Hg@JDKX=PrSiHJB+N ztu=*V>&ilRe;XqFzeD^?rBLh2Id%2r80MF+&qQ;V*{P!i+tfWbr>ZM7+l6OlBeY_b z30Vn;Oj6VtN2)4KonW04e1nJ)1WDOQHozyrH!Ewx2!U}NWcQu?p=fCiZgCI*LP0>u z1VvW_h9QCxm?C-4$?;gnV;AMeE9{l3+<4_8Rx>ITf3nv_717iKEj2rRWzjcRRrfq_ zS!=ze(NUV`Vr`|35_DfQn}?rPZ0p5dqbU6Yb<2xy)?Px8$`gpCwGlGXmxm$_F##cpF!lSn^~*SnI6xuwrui3$_~v6L zdY$OCe?4Y!ljd~7A0x>28gfEthKtGM!kZ#L4mw-a3e7C1BZ@Y4gO*av=(<6i8SQqJ zX8AE%X^BPpOxbp$-T@zRhy$kVYI#l3X>^W5F5-~J!Y<8Y{+-RS--&XSNbKxNZMzU4 zNS%rA%fsv8;CJb7aje}f^y8LiX2rhRsxKy4e>NIck>=H<99>s=@UkIT`ZAHydkT|Y z@S&=X?UXua?JaRHr0)po_2JVOyHb^7sITVM$4V}Al%uY@8yznG`dVW2hZAw=J~#`O z9jV;i2J7dZ25X-JDMw8T zf8YgV6`%eF2Fj|VgW8NEI?JU)QfCy<^H9iH?u`J!GkA^EWrQgt69gz3nrJw~;+$R) z0nb$nIy|Z9OqI`yfsrN*`9mGERqu`~f{BkkC@oS+Vk8;?Lb+^1j6gamOe4gmH1LhI zNCCY?5%R%k4k$ra1O`+zg84Mpy`GWBe`?cOXKL^J1#Fi#$ze%{B^{P@Sh6FQ+}>=6 z{(o@`!(~z@8TD73LB8tFZ4dDpjREuqIrEd!-fC>pR2kDhGn$H`3Zkws{bp?_`o&r1 zn*--dtXYx0vzXP>!OFFx*5#D{8P?%-ruH7hrFSUbp?rt(9m;=*D1WOVp1MGZe@nzv z&#M1ejNcW{_Z)*gH~cCz-;CrNVu4oS_+I@&+C}PI4CftScYxgi_WKOj9Rzj|*g;?i zfgd6S-foDPF96muZqP>kRk%#_gnaw=i}G# z@pG?i#M#B1c)G&=w}HOAD#X+wnquOMzXf+eD9TESU+j{e#iIbT=?6Ape}nz4?VVxa z#bH3bYxU~;a3JGYXKkpLXDGVFAw&EWGQPFBDGG1w46EM0#RLYJ&sCA{EyYlw_ZBtl z2>n*(!Hrax%2zSB{5-dyvU=vN1V_ck?8ce%OR3Ei>!oHxuJ!fmGKCLKHtg2Ks6B&o zZ+Z{}R8V{hNqgHtsRc{xf5B7mBsnar7Z|0+tL4UK8$nS;aJ{^Es48)ltVqvG?#nUC znr^liHPKAf%1go&zm19C9+6eFVZY&?9Zex2D9G1eya98?d$GM$55sLkX^*J}gd^_>&#J3aQ_d|TYtcj>9 z<*B6*F-(+ZyaHNq4d=aHyjt}mRg+^6liv8r=VL;WQq9f`2zb-B^$`M zb%cEo32K-;ZGnKHVEkN_8DTO}t0#-{hkSt3);7Qi2Uwobf6P?G4hZxC;SfM@M1ACe zC%04VO@R&wk_9C6#M|c~^sbSg_9Eu)sg5P`L6n+8Hr>dZr}~M^+BF2&y0Vg2HNiOL z&Jswb8y^uh`wYZs!2T05rVH7P=)XT`uSc^uhd|c%1aSsvWaK6e;e006s;7nlMu^`c zL{j&!5aMX#e~MgA5nv(m#7^;()B`f#&PYbFK{A|W5|BqU#HSIBCsRPlb8iYUk;#kY z0q8gutPaG?xrD7BwQC%uvPl~f+pks!(l6U-KB+=egr$A(>mQ|#ECZ<@8a#bn6B15x z$9JeBG<}C`VX1v+=cM6JA!ltx%sW(rX1hojH8?xBf916IZZhVIfJPY;X$@COkeHzj za3UR(mA4J~g#$#Sydji4&kD!HXIBIO022*$s2&!DmzGwLWCBay;@h|);5qm_MFh~0 zvyD&Vv2@`OSW)f)<q~Yr==2IGTDRl+%h3Tb4NYoliWcv3<`i@{CWdV|fbXbe@u!gt+; z^O~}o?V6}6a+{rE)=}#cH7nSQ%%k0wsfe~3GiWc(PBgVkvykef#f#QzRSAofVd-+U zf6pykTDcD^_wCM3&HZTkkw2o_Go|NtThdwmW$g)HzUsrtix7EF!INjYT`T)RMn->T zgxt^;o2#9=w`SCq)xF#jv*Rb<1_#ojqa8Ia@eG|(@A?BKY2v)}8N5rMeZb@bafyEP zlQ(xflC2+joJOXOVq8i+h8$L1N&UV=f39>*ep~G$rMFFAYG`e{Qlsv8@6!G@Xw{7y z<2%{hoymRbRuypP?1UYqQKiCdu+*}`oqxGT3U}(ZlIvBloSZ+G<<`7FUWE92$fnho zzn9yn!-2dnBrgCOSJrb(Bwcjx5uQwW#xzhg(KB1oi1?xxctW6(E#C&0a#d_Me{zi< zWvj?O(6@w5{SYpdTMLfGRk1j=lx&z)vi`b#Li>KKFXdMaM?X-k@O#B(>NzZc$u2s6 zzuc~EF{4W@8pR#D&G8Qta}D3sSwAxkZnq|efmBm8e(9vWsk;3;D5`c>;h&gN?A#Nb zd*Yg!X4jRCylA@a-Z2)6QMbj7e_Ny0VqVe^8l{U_$08icW8xssn!bMFrIk)d36E$= zJ3Gb^@>Hu^ZIu$U#n!+(>$jWweV;e{UelF(t+E~X9lesX`fV(~&q7gmLk2zfbrahB zJDPJO9mxv5%6Uh#1>7Q|ssVlEI%v&6as#*XGJB{DrO`HA^{Lw#mYj*lf5ODmikCV& zi?g#hJIkZ9v-Eq2CIq#e>?!f9&MH-tf8^SDaaQ5$0�f`MM(5mrb!XG^RM3BJcVl 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 diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 583f188390e8d332771655a1083519bf234fe090..7ca6673b5f7f7679037eabab7c9a315c48033f03 100644 GIT binary patch delta 4355 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

uYP<3bFuA^(3)Wol9@8ZX_h<60j*Wln zS&ZIWH#O z7dH?`$qm`1MxrfJf=1JuMr)0!J*d@7*@yR8n`B!R!B;tdr@W=cg9&2iWJIeefKl%? zjq(W0YTYktS!9eyZ7LYz%6hg^@2idQN2=-N??d&Cj+XcFhQzh0FO*%ypL{?!>4#$5 zGU|k+l_VY6Uf!r5S9|&hv2$VHH(Mv|ca(lP`!)OZ?(hFzqqqOz?pgQHW1s(ZWPO>v zJ$f@}z4cB@>Di|lyLf;7?mv74Oc2yB5`>+5Wy2RtY5oV zy?3zRe%0>2igkdD2VYON^<;4Wm=X^W&-dOy-{Gf|Fb+Qr>E&!3QlO5HI!axI@o&W28_Ir$BBl%5zl^$tuhkkw-8C`^Ke4zf3Tl24v2RStn3S{z@i zW$jIHI&(3LKN8)(lb8_{9dza*izE94&M(moWOm|tblyqrbBSCBTF90tI#iR%5nKVM zlO_@?0^OsNQxZRa%n8xiM1`O_+EPbb>S#+HZK}QR`@{7}wD85inIqy=J@ls?#vRQE(L~ za^M{FI<2y9Q3asRepd(6bSf=?=WPB*vhfabsx^Iqj#IfligK*8rc>y-@r)~1h8Jzk x82Ew>s=_O^MU(U2wi6Ot=kBR*hu`qN+;1F!+uQHA{|f*B|Nq_zVFe@d005V(ghc=V delta 4356 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 bS~Gsu)1IDgpZ;F}00960a;gQbrt1O#br#6s diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 020bc9d1b70debe22a19c0b2034b8ecf3b8fd3a8..5d62a0c56fccb3bcd8554874a97907de3011fc14 100644 GIT binary patch delta 3512 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%0DZE+yWIXt`cC`!_D4$U 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 P0RR6}1qRdRVkiLs4J*Bi diff --git a/cmd/lotus-miner/proving.go b/cmd/lotus-miner/proving.go index 5ff49c25f..85bc48e78 100644 --- a/cmd/lotus-miner/proving.go +++ b/cmd/lotus-miner/proving.go @@ -7,10 +7,12 @@ import ( "os" "strconv" "strings" + "sync" "text/tabwriter" "time" "github.com/fatih/color" + "github.com/ipfs/go-cid" "github.com/urfave/cli/v2" "golang.org/x/xerrors" @@ -19,6 +21,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lotus/blockstore" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" @@ -37,6 +40,7 @@ var provingCmd = &cli.Command{ provingCheckProvableCmd, workersCmd(false), provingComputeCmd, + provingRecoverFaultsCmd, }, } @@ -644,3 +648,82 @@ It will not send any messages to the chain.`, return nil }, } + +var provingRecoverFaultsCmd = &cli.Command{ + Name: "recover-faults", + Usage: "Manually recovers faulty sectors on chain", + ArgsUsage: "", + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "confidence", + Usage: "number of block confirmations to wait for", + Value: int(build.MessageConfidence), + }, + }, + Action: func(cctx *cli.Context) error { + if cctx.Args().Len() < 1 { + return xerrors.Errorf("must pass at least 1 sector number") + } + + arglist := cctx.Args().Slice() + var sectors []abi.SectorNumber + for _, v := range arglist { + s, err := strconv.ParseUint(v, 10, 64) + if err != nil { + return xerrors.Errorf("failed to convert sectors, please check the arguments: %w", err) + } + sectors = append(sectors, abi.SectorNumber(s)) + } + + nodeApi, closer, err := lcli.GetStorageMinerAPI(cctx) + if err != nil { + return err + } + defer closer() + + api, acloser, err := lcli.GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer acloser() + + ctx := lcli.ReqContext(cctx) + + msgs, err := nodeApi.RecoverFault(ctx, sectors) + if err != nil { + return err + } + + // wait for msgs to get mined into a block + var wg sync.WaitGroup + wg.Add(len(msgs)) + results := make(chan error, len(msgs)) + for _, msg := range msgs { + go func(m cid.Cid) { + defer wg.Done() + wait, err := api.StateWaitMsg(ctx, m, uint64(cctx.Int("confidence"))) + if err != nil { + results <- xerrors.Errorf("Timeout waiting for message to land on chain %s", wait.Message) + return + } + + if wait.Receipt.ExitCode != 0 { + results <- xerrors.Errorf("Failed to execute message %s: %w", wait.Message, wait.Receipt.ExitCode.Error()) + return + } + results <- nil + return + }(msg) + } + + wg.Wait() + close(results) + + for v := range results { + if v != nil { + fmt.Println("Failed to execute the message %w", v) + } + } + return nil + }, +} diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 6eb1e5121..e5147340d 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -106,6 +106,8 @@ * [PiecesListPieces](#PiecesListPieces) * [Pledge](#Pledge) * [PledgeSector](#PledgeSector) +* [Recover](#Recover) + * [RecoverFault](#RecoverFault) * [Return](#Return) * [ReturnAddPiece](#ReturnAddPiece) * [ReturnDataCid](#ReturnDataCid) @@ -2265,6 +2267,36 @@ Response: } ``` +## Recover + + +### RecoverFault +RecoverFault can be used to declare recoveries manually. It sends messages +to the miner actor with details of recovered sectors and returns the CID of messages. It honors the +maxPartitionsPerRecoveryMessage from the config + + +Perms: admin + +Inputs: +```json +[ + [ + 123, + 124 + ] +] +``` + +Response: +```json +[ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + } +] +``` + ## Return diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 88c4d4141..ec266311b 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -2093,14 +2093,15 @@ USAGE: lotus-miner proving command [command options] [arguments...] COMMANDS: - info View current state information - deadlines View the current proving period deadlines information - deadline View the current proving period deadline information by its index - faults View the currently known proving faulty sectors information - check Check sectors provable - workers list workers - compute Compute simulated proving tasks - help, h Shows a list of commands or help for one command + info View current state information + deadlines View the current proving period deadlines information + deadline View the current proving period deadline information by its index + faults View the currently known proving faulty sectors information + check Check sectors provable + workers list workers + compute Compute simulated proving tasks + recover-faults Manually recovers faulty sectors on chain + help, h Shows a list of commands or help for one command OPTIONS: --help, -h show help (default: false) @@ -2210,6 +2211,19 @@ OPTIONS: ``` ``` +### lotus-miner proving recover-faults +``` +NAME: + lotus-miner proving recover-faults - Manually recovers faulty sectors on chain + +USAGE: + lotus-miner proving recover-faults [command options] + +OPTIONS: + --confidence value number of block confirmations to wait for (default: 5) + +``` + ## lotus-miner storage ``` NAME: diff --git a/extern/filecoin-ffi b/extern/filecoin-ffi index f997fe6c7..32afd6e1f 160000 --- a/extern/filecoin-ffi +++ b/extern/filecoin-ffi @@ -1 +1 @@ -Subproject commit f997fe6c77632c0bc58d0b1fdf53ee7a93f6027c +Subproject commit 32afd6e1f1419b6bb7d0f4b3944287fde593ca64 diff --git a/itests/wdpost_config_test.go b/itests/wdpost_config_test.go index 61b64387d..984650ae6 100644 --- a/itests/wdpost_config_test.go +++ b/itests/wdpost_config_test.go @@ -300,3 +300,170 @@ func TestWindowPostMaxSectorsRecoveryConfig(t *testing.T) { sectors = p.MinerPower.RawBytePower.Uint64() / uint64(ssz) require.Equal(t, nSectors+kit.DefaultPresealsPerBootstrapMiner-1, int(sectors)) // -1 not recovered sector } + +func TestWindowPostManualSectorsRecovery(t *testing.T) { + oldVal := wdpost.RecoveringSectorLimit + defer func() { + wdpost.RecoveringSectorLimit = oldVal + }() + wdpost.RecoveringSectorLimit = 1 + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + client, miner, ens := kit.EnsembleMinimal(t, + kit.LatestActorsAt(-1), + kit.MockProofs()) + ens.InterconnectAll().BeginMining(2 * time.Millisecond) + + nSectors := 10 + + miner.PledgeSectors(ctx, nSectors, 0, nil) + + maddr, err := miner.ActorAddress(ctx) + require.NoError(t, err) + di, err := client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + + mid, err := address.IDFromAddress(maddr) + require.NoError(t, err) + + t.Log("Running one proving period") + waitUntil := di.Open + di.WPoStProvingPeriod + t.Logf("End for head.Height > %d", waitUntil) + + ts := client.WaitTillChain(ctx, kit.HeightAtLeast(waitUntil)) + t.Logf("Now head.Height = %d", ts.Height()) + + p, err := client.StateMinerPower(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + + ssz, err := miner.ActorSectorSize(ctx, maddr) + require.NoError(t, err) + + require.Equal(t, p.MinerPower, p.TotalPower) + require.Equal(t, p.MinerPower.RawBytePower, types.NewInt(uint64(ssz)*uint64(nSectors+kit.DefaultPresealsPerBootstrapMiner))) + + failed, err := client.StateMinerFaults(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + failedCount, err := failed.Count() + require.NoError(t, err) + + require.Equal(t, failedCount, uint64(0)) + + t.Log("Drop some sectors") + + // Drop 2 sectors from deadline 2 partition 0 (full partition / deadline) + parts, err := client.StateMinerPartitions(ctx, maddr, 2, types.EmptyTSK) + require.NoError(t, err) + require.Greater(t, len(parts), 0) + + secs := parts[0].AllSectors + n, err := secs.Count() + require.NoError(t, err) + require.Equal(t, uint64(2), n) + + var failedSectors []abi.SectorNumber + + // Drop the partition + err = secs.ForEach(func(sid uint64) error { + failedSectors = append(failedSectors, abi.SectorNumber(sid)) + return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkFailed(storiface.SectorRef{ + ID: abi.SectorID{ + Miner: abi.ActorID(mid), + Number: abi.SectorNumber(sid), + }, + }, true) + }) + require.NoError(t, err) + + di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + + t.Log("Go through another PP, wait for sectors to become faulty") + waitUntil = di.Open + di.WPoStProvingPeriod + t.Logf("End for head.Height > %d", waitUntil) + + ts = client.WaitTillChain(ctx, kit.HeightAtLeast(waitUntil)) + t.Logf("Now head.Height = %d", ts.Height()) + + failed, err = client.StateMinerFaults(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + failedCount, err = failed.Count() + require.NoError(t, err) + + require.Equal(t, failedCount, uint64(2)) + + recovered, err := client.StateMinerRecoveries(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + recoveredCount, err := recovered.Count() + require.NoError(t, err) + + require.Equal(t, recoveredCount, uint64(0)) + + p, err = client.StateMinerPower(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + + require.Equal(t, p.MinerPower, p.TotalPower) + + t.Log("Make the sectors recoverable") + + err = secs.ForEach(func(sid uint64) error { + return miner.StorageMiner.(*impl.StorageMinerAPI).IStorageMgr.(*mock.SectorMgr).MarkFailed(storiface.SectorRef{ + ID: abi.SectorID{ + Miner: abi.ActorID(mid), + Number: abi.SectorNumber(sid), + }, + }, false) + }) + require.NoError(t, err) + + // Try to manually recover the sector + t.Log("Send recovery message") + _, err = miner.RecoverFault(ctx, failedSectors) + require.NoError(t, err) + + currentHeight, err := client.ChainHead(ctx) + require.NoError(t, err) + + ts = client.WaitTillChain(ctx, kit.HeightAtLeast(currentHeight.Height()+abi.ChainEpoch(10))) + t.Logf("Now head.Height = %d", ts.Height()) + + failed, err = client.StateMinerFaults(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + failedCount, err = failed.Count() + require.NoError(t, err) + + require.Equal(t, failedCount, uint64(2)) + + recovered, err = client.StateMinerRecoveries(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + recoveredCount, err = recovered.Count() + require.NoError(t, err) + + require.Equal(t, recoveredCount, uint64(2)) + + di, err = client.StateMinerProvingDeadline(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + + t.Log("Go through another PP, wait for sectors to become faulty") + waitUntil = di.Open + di.WPoStProvingPeriod + t.Logf("End for head.Height > %d", waitUntil) + + ts = client.WaitTillChain(ctx, kit.HeightAtLeast(waitUntil)) + t.Logf("Now head.Height = %d", ts.Height()) + + failed, err = client.StateMinerFaults(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + failedCount, err = failed.Count() + require.NoError(t, err) + + require.Equal(t, failedCount, uint64(0)) + + recovered, err = client.StateMinerRecoveries(ctx, maddr, types.TipSetKey{}) + require.NoError(t, err) + recoveredCount, err = recovered.Count() + require.NoError(t, err) + + require.Equal(t, recoveredCount, uint64(0)) +} diff --git a/node/impl/storminer.go b/node/impl/storminer.go index bab72d631..f054f627e 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -1323,6 +1323,27 @@ func (sm *StorageMinerAPI) ComputeProof(ctx context.Context, ssi []builtin.Exten return sm.Epp.ComputeProof(ctx, ssi, rand, poStEpoch, nv) } +func (sm *StorageMinerAPI) RecoverFault(ctx context.Context, sectors []abi.SectorNumber) ([]cid.Cid, error) { + allsectors, err := sm.Miner.ListSectors() + if err != nil { + return nil, xerrors.Errorf("could not get a list of all sectors from the miner: %w", err) + } + var found bool + for _, v := range sectors { + found = false + for _, s := range allsectors { + if v == s.SectorNumber { + found = true + break + } + } + if !found { + return nil, xerrors.Errorf("sectors %d not found in the sector list for miner", v) + } + } + return sm.WdPoSt.ManualFaultRecovery(ctx, sm.Miner.Address(), sectors) +} + func (sm *StorageMinerAPI) RuntimeSubsystems(context.Context) (res api.MinerSubsystems, err error) { return sm.EnabledSubsystems, nil } diff --git a/storage/wdpost/wdpost_run.go b/storage/wdpost/wdpost_run.go index 0e715f101..0501923b0 100644 --- a/storage/wdpost/wdpost_run.go +++ b/storage/wdpost/wdpost_run.go @@ -717,3 +717,7 @@ func (s *WindowPoStScheduler) ComputePoSt(ctx context.Context, dlIdx uint64, ts return s.runPoStCycle(ctx, true, *dl, ts) } + +func (s *WindowPoStScheduler) ManualFaultRecovery(ctx context.Context, maddr address.Address, sectors []abi.SectorNumber) ([]cid.Cid, error) { + return s.declareManualRecoveries(ctx, maddr, sectors, types.TipSetKey{}) +} diff --git a/storage/wdpost/wdpost_run_faults.go b/storage/wdpost/wdpost_run_faults.go index 0b7a33238..9e9854a7c 100644 --- a/storage/wdpost/wdpost_run_faults.go +++ b/storage/wdpost/wdpost_run_faults.go @@ -10,6 +10,7 @@ import ( "go.opencensus.io/trace" "golang.org/x/xerrors" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/builtin" @@ -345,3 +346,111 @@ func (s *WindowPoStScheduler) asyncFaultRecover(di dline.Info, ts *types.TipSet) } }() } + +// declareRecoveries identifies sectors that were previously marked as faulty +// for our miner, but are now recovered (i.e. are now provable again) and +// still not reported as such. +// +// It then reports the recovery on chain via a `DeclareFaultsRecovered` +// message to our miner actor. +// +// This is always invoked ahead of time, before the deadline for the evaluated +// sectors arrives. That way, recoveries are declared in preparation for those +// sectors to be proven. +// +// If a declaration is made, it awaits for build.MessageConfidence confirmations +// on chain before returning. +func (s *WindowPoStScheduler) declareManualRecoveries(ctx context.Context, maddr address.Address, sectors []abi.SectorNumber, tsk types.TipSetKey) ([]cid.Cid, error) { + + var RecoveryDecls []miner.RecoveryDeclaration + var RecoveryBatches [][]miner.RecoveryDeclaration + + type ptx struct { + deadline uint64 + partition uint64 + } + + smap := make(map[ptx][]uint64) + + var mcids []cid.Cid + + for _, sector := range sectors { + ptxID, err := s.api.StateSectorPartition(ctx, maddr, sector, types.TipSetKey{}) + if err != nil { + return nil, xerrors.Errorf("failed to fetch partition and deadline details for sector %d: %w", sector, err) + } + ptxinfo := ptx{ + deadline: ptxID.Deadline, + partition: ptxID.Partition, + } + + slist := smap[ptxinfo] + sn := uint64(sector) + slist = append(slist, sn) + smap[ptxinfo] = slist + } + + for i, v := range smap { + sectorinbit := bitfield.NewFromSet(v) + RecoveryDecls = append(RecoveryDecls, miner.RecoveryDeclaration{ + Deadline: i.deadline, + Partition: i.partition, + Sectors: sectorinbit, + }) + } + + // Batch if maxPartitionsPerRecoveryMessage is set + if s.maxPartitionsPerRecoveryMessage > 0 { + + // Create batched + for len(RecoveryDecls) > s.maxPartitionsPerPostMessage { + Batch := RecoveryDecls[len(RecoveryDecls)-s.maxPartitionsPerRecoveryMessage:] + RecoveryDecls = RecoveryDecls[:len(RecoveryDecls)-s.maxPartitionsPerPostMessage] + RecoveryBatches = append(RecoveryBatches, Batch) + } + + // Add remaining as new batch + RecoveryBatches = append(RecoveryBatches, RecoveryDecls) + } else { + RecoveryBatches = append(RecoveryBatches, RecoveryDecls) + } + + for _, Batch := range RecoveryBatches { + msg, err := s.manualRecoveryMsg(ctx, Batch) + if err != nil { + return nil, err + } + + mcids = append(mcids, msg) + } + + return mcids, nil +} + +func (s *WindowPoStScheduler) manualRecoveryMsg(ctx context.Context, Recovery []miner.RecoveryDeclaration) (cid.Cid, error) { + params := &miner.DeclareFaultsRecoveredParams{ + Recoveries: Recovery, + } + + enc, aerr := actors.SerializeParams(params) + if aerr != nil { + return cid.Undef, xerrors.Errorf("could not serialize declare recoveries parameters: %w", aerr) + } + + msg := &types.Message{ + To: s.actor, + Method: builtin.MethodsMiner.DeclareFaultsRecovered, + Params: enc, + Value: types.NewInt(0), + } + spec := &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)} + if err := s.prepareMessage(ctx, msg, spec); err != nil { + return cid.Undef, err + } + sm, err := s.api.MpoolPushMessage(ctx, msg, &api.MessageSendSpec{MaxFee: abi.TokenAmount(s.feeCfg.MaxWindowPoStGasFee)}) + if err != nil { + return cid.Undef, xerrors.Errorf("pushing message to mpool: %w", err) + } + + return sm.Cid(), nil +} diff --git a/storage/wdpost/wdpost_sched.go b/storage/wdpost/wdpost_sched.go index 2739bc386..66722e283 100644 --- a/storage/wdpost/wdpost_sched.go +++ b/storage/wdpost/wdpost_sched.go @@ -19,6 +19,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" + lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" @@ -44,6 +45,7 @@ type NodeAPI interface { StateMinerPartitions(context.Context, address.Address, uint64, types.TipSetKey) ([]api.Partition, error) StateLookupID(context.Context, address.Address, types.TipSetKey) (address.Address, error) StateAccountKey(context.Context, address.Address, types.TipSetKey) (address.Address, error) + StateSectorPartition(ctx context.Context, maddr address.Address, sectorNumber abi.SectorNumber, tok types.TipSetKey) (*lminer.SectorLocation, error) MpoolPushMessage(context.Context, *types.Message, *api.MessageSendSpec) (*types.SignedMessage, error)