From 7cbeafa4188e1d434878218223e1b97292a51874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 24 Aug 2022 15:27:27 -0400 Subject: [PATCH 01/26] sector import: Initial api scaffolding --- api/api_storage.go | 88 +++++++++++++++ api/docgen/docgen.go | 4 + api/proxy_gen.go | 13 +++ build/openrpc/miner.json.gz | Bin 15449 -> 15743 bytes build/openrpc/worker.json.gz | Bin 5076 -> 5035 bytes documentation/en/api-v0-methods-miner.md | 126 ++++++++++++++++++++++ node/impl/storminer.go | 4 + storage/pipeline/checks.go | 22 ++-- storage/pipeline/receive.go | 78 ++++++++++++++ storage/pipeline/states_replica_update.go | 4 +- storage/pipeline/states_sealing.go | 2 +- 11 files changed, 327 insertions(+), 14 deletions(-) create mode 100644 storage/pipeline/receive.go diff --git a/api/api_storage.go b/api/api_storage.go index 4d05419d6ab..e4ca49c2125 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -3,6 +3,7 @@ package api import ( "bytes" "context" + "net/http" "time" "github.com/google/uuid" @@ -17,6 +18,7 @@ import ( "github.com/filecoin-project/go-fil-markets/storagemarket" "github.com/filecoin-project/go-jsonrpc/auth" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v8/market" "github.com/filecoin-project/go-state-types/builtin/v8/miner" abinetwork "github.com/filecoin-project/go-state-types/network" @@ -139,6 +141,8 @@ type StorageMiner interface { // SectorNumFree drops a sector reservation SectorNumFree(ctx context.Context, name string) error //perm:admin + SectorReceive(ctx context.Context, meta RemoteSectorMeta) error + // WorkerConnect tells the node to connect to workers RPC WorkerConnect(context.Context, string) error //perm:admin retry:true WorkerStats(context.Context) (map[uuid.UUID]storiface.WorkerStats, error) //perm:admin @@ -499,3 +503,87 @@ type NumAssignerMeta struct { Next abi.SectorNumber } + +type RemoteSectorMeta struct { + //////// + // BASIC SECTOR INFORMATION + + // State specifies the first state the sector will enter after being imported + // Must be one of the following states: + // * Packing + // * GetTicket + // * PreCommitting + // * SubmitCommit + // * Proving/Available + State SectorState + + Sector abi.SectorID + Type abi.RegisteredSealProof + + //////// + // SEALING METADATA + // (allows lotus to continue the sealing process) + + // Required in Packing and later + Pieces []SectorPiece // todo better type? + + // Required in PreCommitting and later + TicketValue abi.SealRandomness + TicketEpoch abi.ChainEpoch + PreCommit1Out storiface.PreCommit1Out // todo specify better + + CommD *cid.Cid + CommR *cid.Cid // SectorKey + + // Required in SubmitCommit and later + PreCommitInfo *miner.SectorPreCommitInfo + PreCommitDeposit big.Int + PreCommitMessage *cid.Cid + PreCommitTipSet types.TipSetKey + + SeedValue abi.InteractiveSealRandomness + SeedEpoch abi.ChainEpoch + + CommitProof []byte + + // Required in Proving/Available + CommitMessage *cid.Cid + + // Optional sector metadata to import + Log []SectorLog + + //////// + // SECTOR DATA SOURCE + + // Sector urls - lotus will use those for fetching files into local storage + + // Required in all states + DataUnsealed *SectorData + + // Required in PreCommitting and later + DataSealed *SectorData + DataCache *SectorData + + //////// + // SEALING SERVICE HOOKS + + // todo Commit1Provider + // todo OnDone / OnStateChange +} + +type SectorData struct { + // Local when set to true indicates to lotus that sector data is already + // available locally; When set lotus will skip fetching sector data, and + // only check that sector data exists in sector storage + Local bool + + // URL to the sector data + // For sealed/unsealed sector, lotus expects octet-stream + // For cache, lotus expects a tar archive with cache files (todo maybe use not-tar; specify what files with what paths must be present) + // Valid schemas: + // - http:// / https:// + URL string + + // optional http headers to use when requesting sector data + Headers http.Header +} diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 40b6e607824..47192bfd991 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -6,6 +6,7 @@ import ( "go/ast" "go/parser" "go/token" + "net/http" "path/filepath" "reflect" "strings" @@ -340,6 +341,9 @@ func init() { "": bitfield.NewFromSet([]uint64{5, 6, 7, 10}), }) + addExample(http.Header{ + "Authorization": []string{"Bearer ey.."}, + }) } func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 4c428d2b9a4..e7efdf1f142 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -844,6 +844,8 @@ type StorageMinerStruct struct { SectorPreCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` + SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `` + SectorRemove func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` SectorSetExpectedSealDuration func(p0 context.Context, p1 time.Duration) error `perm:"write"` @@ -5026,6 +5028,17 @@ func (s *StorageMinerStub) SectorPreCommitPending(p0 context.Context) ([]abi.Sec return *new([]abi.SectorID), ErrNotSupported } +func (s *StorageMinerStruct) SectorReceive(p0 context.Context, p1 RemoteSectorMeta) error { + if s.Internal.SectorReceive == nil { + return ErrNotSupported + } + return s.Internal.SectorReceive(p0, p1) +} + +func (s *StorageMinerStub) SectorReceive(p0 context.Context, p1 RemoteSectorMeta) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) SectorRemove(p0 context.Context, p1 abi.SectorNumber) error { if s.Internal.SectorRemove == nil { return ErrNotSupported diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index a97aea48a61b832fbcad1c9098689e550dc5bd67..99ca3b3666cabaaf974b06194236752f869832ef 100644 GIT binary patch literal 15743 zcmb80Lv$v+ND3^le?7z@wOE+7g`-u~Bpby{Ck(kdP1^E4ke3ICCkcZR>Msb~pi6&u5U<#9IT! zUezj-TXOi{uzx$$6XYk0WdC&#kJE%3MBB` zk!#>BVl=+_>xkDIgFJ>aQjZPVB#=AmQeWD69M4n~@KT-z}NzpoM(R<}ld z5wj|M3vG$U0?-wsc-%0#HE%CN9r|OHgYG{no*Q#`hqkg4>LXcOV7?U|a=mdbSLZZM zp>PDA!B!ih)r2;47l@%GS1p75C+30=1NGL2ic{LO`DcZ(;;rmP(||X>1o`F-iqM@M z+{<4gJcWNDm`to8&*B>>KC39k8)HKWhLdx&J0{~J;`T^NtETZd&25yxWM!|LVp|+! zuOxMpEITFacIZ8lYHR^J^t_%tb@)+xPs=7vAFj6A53N?G%7@>5noW6z4pg<8WEY{t}ySErZI$%xaI=O8Mk--P;uH6+k-l_AliMd(W9c z-0l>hJE4EOuL$3|94oSudhE4GFJ$v8>TBemMK!sn6~3+r9~A& zvB=1#)LM9C<_NXRM8X02daNuyDPPGtl$@a%`ibc+JTGJkCQ8V{H+&INRte&;kL}!Z z3mIUw&NM?DGEBuRsdr%PvYMPXoWJ`1w(_fhM$MXk#7eAX3Ej=AG-=Ewp#VST_{K8C z6hvZ;fb-(Si8TuwJhNx+hKD?9{_M$U^h+Pi_A}~W#(TX*$c#T_<75S=X4SA2I$9OCxcCD>vw zOpca~9j@5bhr;C)xaPQu;D}scEv9Qik06@GMK05iW*sp+PXf9Nq>Y)aL|%xI+9(c@ zZU+qJ7Y=ZR6tp+OmV~q;P}ej7mW7)VpVII#R<3Srg=Am6iAR1MIKHOng8~jzs9u8U zsIt|4^jX+$cnXcWGWWUr`E6tYnp=K&3>aoznegat z?HhBf+09wo2rU$lE6$W5laAcz*&tQg7kRaazOD!AuQPnKrF2Jr9gdI7G!4NCnCNP1 zJPy=Xi$Sh}-X1NNqy}LsO5|F0iC#`4F*d$Z-2Q>TVkp=~tGrRKmd;I&Axb4NaOz7- zY#)y>1T_OS5m^K1k>+jYU}G-HMcShUsn#kpE24B5^jMgcU1FEXT$S%!JaKPRHWgv- zsA?_mXBP4LbaY?6Zsan6f8@TBt2rz0gCY`+2YY=`+`OoS+c<1cjJwh@_n-g~b5k}H z8YyUa3WZgGn{HM$`NDaE0sFD&>aiT#JHt$Vwou1rd>f86(Ubn<1D)d;?EW$bTA06S zBd;eiW!@(i$J@#yK>(^9)M!m2_{+Q)+uXu|mLm*fN*Rh45E{oJWJSVthRV=j;WdD91eUb)wS2 zp`|y`i{-){6a*&zuiGOavT0Aoaq$Ko56}e^UAnpT4k>rqw_k-W8Fb zcSB%$S1X;*67X|4A8|Op=3l*)joB}-?ciIIXP*MJqbo;~axhDDsq-1xMM^V~wF=(p zEC;p8XBY?hCXDsDrXn!_+LigSz$>~T5NxGofNA78AKPgC38hvIoaagv8S7W7hecAJPah_G)XGFwrzB-RuV8c{zn9os**jbYbIe|kn#fgZZ_bt!08@rWSWLnV9#)T-lG zXY)*DC`uj8j4W7J#}Vl3&nq3vpq=Lj3@xPxg9Wiw*rn8W(2DpYE7b8X$fKum&{?1z@TF2Pwcnn->_t7$Nt<*GKx z!o*01$3$+atp<<|jO&1tkzr|(E$!w7qw3ODCkov#c(^>+#_SE#hAAVf z)=sr>;+d>sAOxay2fc5N)cjEw1v1e>+jhuhgfC7N0t?@yq%62RfHH;D8{%GiL&QXy z6f~sI)fy5+$fp6*B~S`T0A76rWslIa?-u4Dh05Fw-UI0fO!gZ{I}!x5G{oe@6=u}B z2ZDS44$c1Y{dzkWxQSKp{qnxca~svT`Ehda{(==eB;di&YV3aCb7mCacR>bU1gU8j z?+bNa+AF)QuEibTHl87t!HnvV*J;E{^a4?}A?6sk_EE<}NS;5#8aSCdx zr1)me`P>*`C2K+R!>aEF=^SV6bvn*PIGXZ-NuzJZd%P<~u?owZJecg=e5b2XpJk$d z<36+j683LT?FF->auNt_&3++C=fvF)By&EtkMOt6AfI2u1D3fRJG+zc)ePw@@5wxNjEazuMKpxyz>T8H=WJ}uB}O&5ogiaF)IiR+M)LcvzC1A z1ERN@?2GXgKj zYp6Y}WdME}$e0)c^S)98Y?PdVv$*#_9Y%lK$p$VlzZsU{ga%7wQ;;lJcN&5BWnfGc z25wT=g|HbsdkZ6$OL;9)I0Fv};p0mvoxIVNmPlNoq9ps+Q823F5DWk`ld+ZAQd7{n z1BgL*{SRei3Q%@H4HkKC0pxCjKnKTRbYQ#1nH&8oQsnd@7#(B(b>xD+m5XohdHK%F z*uve>C6_A|MZ6_;hXtdwy1CM;B2IM&oi=y8BzLIy6`O8?Tc z$zdKNKBSRLUGd;$>erlf9iST`_BV`qVsAU#Yf)^0+5)Gra$L)Tkr-Wz!|D`VX7W_omPRdF&3EBp@wUA_PBsbDt%)AhH6~_$nuW52L;Z7QuOq~Ct$&@o3=a%}>AlzR zeK+8!pa-USX&k4T9$(wT>`i#c(TZZHs$loYM@o5QBr_!Fx7QANr6X5R>yXCbWRY!A z&K^T?z_^5&WC`|=t)CFBTZlucdPj`OgVlgpqMFbEccONr6z!l~KOkMx(sWUDi^Ici zpiPa0yPg!PhkDA?%?Q^8>8s~UJBRQmc^%%m5C4f!M`#5eNCDjjzx#twK(>2AwCgJl zyt7LERgZd~B4p$5ZffWz)Pa548vMZ<%rh1_Zg^qe^2h2-?WkO`lqfoIP`P$OCc%v! zp|Qn)K4ibK_^mlCg+c3qp%+W;V#C{)iggNR+wjsOcFPias((ex!BD_&e^0hruR!0# z-jRffxNliZpQQyx*Gs!DVKW2kNM*y$m#t+(Vr9Rv{@5 zwGaC5acVIE1Ha{Z|j z@idfzL=I0|Y41HXO;R!KlZiu)(Zi)5#a*6PE8gP^wi`yOe#iV~U?`>%hLVGfKnt`D z7n>N0R5eSQB5JDscdH~1Qx=^l^v|FY3=qc<`MDC+QU)pLSE`skVier{KywX}&8!Yx zP^!<7gd%5tJPBIP^3j@L=+$3~UKiP$M&phY?31EBMiS*%4NdXCOhn6}r>Cpcdktg$ zWPH05$w=6O=M!Ppn}>-+u<%M`Lovx%PF=zxU4Nih<&)1%fI$<=S5=%cMg1`dkU#=Xhd{_v5XdvA9g-p^5nX*% zD_Cbq|KEH_3xN=Qi%&F+EptUXevjrfzyC@MI*6Btg_H6Ih)Nt&72mE04CzUZ$%{>y z08b{eK@`V(+I09HG^!A2*peJNzwHbb(wV8Zx|AsYwU4aL{VOVc5{IR7cVGYg8q{#7 z4eL4Evd?yS6B%a=mt?ftXF$EkFb~D_v>lr$1TqH z&A`$x8?W>4iC_1^kN4-%R#;U(!?oAN!Bf%0+2{AlPf657z`mEK#{(k82RZf}qduBT zFqZ<8F3MzyW^D`ZSV%evg94$`0^2@-H1Usn& zalr5M1)@E9^tXV^XP&QEkEXAj1do%#5KM0MFQTzWZAfU~{fh82jOG<8hAj;XM{MSr zX$I#Cgup#!Zx}^bqimA(J9A2-JdPUI#T)aR{0(dR;SAgi7$zmNYjl(Yl-{2@_V-9c z7N)(t_=|xO6Ea`3w>56_j|byIYqO=4;85q^;_jlePdnY zZ`0b93&LB!8n14W@0ov|%duF@2?uv;DoB)*RmQah@X*55zo{Y-)gVJ{6J1ZD6PL=N zy>0G6GLB1D+m=?5Vd?gFn6q@s$E(cpjTCtzY0)d@R>O6A#e7*UFhcql-d?3+gd)?m z6vdmUhtxB>;ji&q5?)e<&wb)J3YseMEcn}VSxra4Tl@5N$rGXa&g$yZuS@nq7?w($bi zQqoF`$x`%D0H^J+15K=s!{_C`W@^wUpO;Y?Hnhfo)+_Ry@k>qUff`Ue1?JDC-YCVj z$hrO=88iq)+*YR%M-|X^z6M*LD+Sds_<>v}4D3dgJG_>R{s73uSXIj&q?vf0&j6_! z^C7CYtbnl<9sptBuux`i9f2m0cRiix2yNp>_srPkafDPI!vaJnkMfjYSM+$kIwC(*RX{ zUtkmUmf_AFR8xgC`c8c+))RALB}hGX@#2y?rjjJKCrO+0LQ-_)1Tjp979c^;ljB^3 z`LgM6JcqIpns0xmo6b2+$jp#f^tdpa18}RAC}m!NmpROe<^CS_96p%dkf|>hbS_A( zDgkAcSM$2?oKjj!em!(0<&l0wIF^aY6coYTgb1;@dQC7D=%OT-EcWgnkQC*ymJlWb zFLPrZETBfXv*aYu2^U+HY+EJ z{HtPNH=KhOc{iQ1PQb#}@|o?0bE`{7FV7MGUr9v7rA_QPx>7Oom_osf*#k3XB_e_#4XYM__?#(xE5yG|OMhJr{ zr|(dk`nWV9&ce^I_!vz%OW$dAiqbn?X9OR^`bJ=AlfoWxTdIQ*>T6@zq>~gzVIIZz zmlx>`KwwY{Eb#iXrB`9gNj|xWo}||T6_A(iF&+P`+4|LjJ9J|hl+NfNT_ZJQOZ5RLYoBb> z1sU!%UXP%$FJa(?EyB}ws1lDx>v`Ou@xA8ZeOqpSzP^HyTM0yy)(BC`dVEurICnCO%yO^q;`w4+;7z zL0AN15-bzMD+<4fO*g1W|AuLai1;K#_(Y&Awgt&DtXKD_Ddwwlc0x!qE<;>AsPzr{ zPBe_mpzjR#`b|_wRQU}gw}gq5#{SBJ%^_#o%H93Dl~|l6TBgP(${(78D@4&Fae)}p zNrl}Kx8bvWJi3COZhKnGv((n7nx3oAzxO&xsD({dQ3@VsbQ$}SNf*lO`egLw(wQMM zgdqBM9|y4h%-`VsYfHkq6PNcs9{KajX{6^T(w3U#Lo=#+AaBPN@}ho}WTpw~$aGqz zg)l1RDP2-7B;Fu$l}%1i!=2I(p-zPQ8Qp&AI(xUm$oPB9^6I~cexgOCm?*-8%9i=#2e8nztuF?~l@ty1=3=rt! z3hYiYc);cpZH8gy_(t+UD=O-d#N-I>3v&%428&;W?np5Fme;R=j4Y+_p-cz#Hl+FhVnT_Bh)YeEnSHiI|+BAR>RKO+GCl*;oBq z&`V@LXW)OiwSN6p(98Nuj{?&6395Y!bzd-%7;RBFamim@PC*TH{V(e>x6Q;S-mC_?-OFYGI?G3U!PzHCefE-BjY3t7O+R% zvy~D2zZmjr-NCue~vpBi~QG)@Z?qy}|tOL(B=T;?Npq#AB@==!pzMFk@* zfJm;3OTn=bpbdtswU<2TO8t}yEFc=1JS)Y%b&?CRYIbWj%w4fmYAHYKJA8$ zakC=hyidrljV48R5Cvc%h(ubQhDCD|R=WsxtS^bFkpK{I@o%?Po7=Fas7JjpcIe)OZp zt0@OZ$^pn-WIOTjlJb5=EuJl>U#gHbV3`N)MOPk%XW*?M}r~6+qwS$+AjAr@Ld+(D7EbW{cfr z7Jt-Wi<@|bO=4;4Lvx{{wKMVVllXKHEnD11TIFy^4f^Ok&v)bBQmKhJGCT30p4)og zm2&byIzxf2s4s@VI&cdmuys6=DRO;hqoXMXz+R?IIG5vAQr!HY)?WmB8P4OH##B zdQiy|ke5{76>&cn&RM~8*eAzEr%)y=YRZciAfB8vfdfu_<-&E#^!Z)cXfGi)S@t|5_jT~Cze+CX>H>>-}G z`7@NDCRk}jvwLf2R>Y91N0!~oTJdOp4RuUFrhVNtZu#5^+=qW++TIMz&j_%Rz8tX{ zE?7}M*e@}2ZRMv*sv@uX)ppUw8IyM@R6vev959grSEf4*Mk=Fv0tvD^yXGawhQ(6Eh*aDaPoduzS8zqGF3PirYd<~YDbZBXuGa$ z857E^uAl}~+n#YpAetZ~u;}ilNw+b`DNH92YMO9ik?j>MJ*tR2o%VaT^mK?qI-@-5 zapMnWQpWFTfWmCM$fBIOvAY!FqOap-Q<@S}U)IJ!`_ZiQ6b5*{CCyQ~sFJ-4pa9Gg zE@c_YGA3USR|pU)Kqv=^-M&tspkK(w(0KPR+G{?Phf_@bT(hp5`}))pyB*qPBlS<@ z`~ypT6GY<^0(XaQQ0nCiXg?rowy$Qh7n3nG#?462AG!X9J(j-ul#rsl66L{+%5co= zG~IZZb52jdz$KefflG7IWCuzdu5p@V_5-nFG$tvP@8vsMJC-VUEG1i|H4c|iR6Ed) z4XD@JnCijk1JO4{Gq#pJ1WFTL$D8C=_|qLNKrE9yK>aP>k2Jxq2PVD5i{dq5UKFh> z_8Z9|>8Y{XIbUfyCIcdA*xEj}TR!A)S}j2;{|UVqY?@bGhA3YI6P8gT8kYkk5V#!t*N&~>I+hH%8Cw=;W%(e~%9JhHdcB%kq%P;* zF~)nSX`~eA8h~*FU@%mP)5H5UV|A7>-rOgow@{R_kE%Ex68IM4U(V0W^mE-Fs+1iNxJvHCStuDSZe5)kzrTc(-h6kK3}K@SW%RoM)d4XsGU`)*5(qj z9WJa0yQ(}maiO4hQNJzQXBSb@Bsoy2kWd2L`vdZ8|o2tl9fmd zVKBHCDV&r*Ai|^LK3b0;P;vD~MdAaUh$otBS5)zD+EHyvqyc4nqA5aL*BZks<(_P! zoVpg&UUmiCoX$@}j%qI!pKvGjYY3|jjuo5b5PZF#7oAX8G?VWxR+qQ{LCc*khm35;v*0BfrWf^?)5+ zj~xB+5s$JM%@v;}L-Cn-5In=jrPt-OHJ1L;8+TWi7qZHI*Zbd+b%tmI$~E zFMn=Vw+k9qmp%!oNaPfqJu*|e7S(o8GgK6kdYc{T;L*I0j5x!;61)DwHGKOcLTQE= z_$~1#R>vV>asYknO{#qP@U9aP zN-J_vPrK($Cf^pyB(K^_*?&fihhbs@GaQT9wJ?|Qan~ebaCXPVwUQcyFTP!v5vH|a z7uJCR!-rqlmlYn2+?A>hqwjg!otW{KMcXj84e5a|28?fB5$k=w1{fJL2QETWrb`{g z6dM^bMQp}4?%05VMu7z-amdqG^zo}G#(BbogH?e8;gPbGTE$E-xshYoYVj!x&B+bo z5|2O5MKNHyQ6g#dR?D3p8C}VF%nKIFce6C0ha*AzQ?-^|WmG&@d**Oss|}o@d)F_e zJIHH7y)jxhz#r&!fCP2f;YOmLbyyI%Z_7~*?FK|0nhEALs4;}o3>1tneFJnx=-Oc% z-orn=Bim^?HON08|16M8yN*ycO!-uCMS##Q!=g6BVtEp39fR~9n%j+#w(PsW1uy=* z-o+kSV(-lb&zFT_l`1=r?Cj4EV#dp^aQJifhd1kmnYbV9dCB|4#;ZL=kC)AtEy@1P z;>E2ay-7t2t;vpVyxg4=@^&+JXUXKloOL=j*`-vo@yf7FV75Yd9*suHAQ)+TN~*c4 zbr~7|7}F989SxS%8S>$pmDH5CU1+NpGBciFEwm;H47?-}ClG>Tf>T^{>ntmsJVWzz zL!qf`uLhS>`y@L*G8=CB?%rc7fGHT+UGkwpYrtvr3)o$fcA6U%tg9nxuX^_Xmn?8R-CCxN6RfL#orFLq<3~%Po`~)F4pb;UV@+}@)4yuu)$Rd z8!cP(fv|vhiAWZLb44ssaQvhq*GWF2-lxpOx?l$Gz=ylX*4n~8jq73Q0*h01s#PNp zmLpU)lXJ}l87j~KlX(b%0tu#~0_!1okDhQFT%0jOQ28b?;ESW8MzlT5)JH`ctS}cN z@leWD1^Ycz3XOsE@C#J3rEg!UFM-_R;H<%p9SMv=bzdwz|=Z&-&(i(>}_lx}yV*uS=SEd4eItgne6UIuZO zZ-_iQixSvBY5_fR`~vr0=u)IS$mO@B7TD+TX~C1c&FUg}k2pm)$WVnE(~O)ZwFxtM|o5ATnC^R7HvrMoh*>Ve%bNV7VG7`l^ z$zi6l0uyQ|o+IW;crF_e`6w)}&5NUv5j|r3J?(F5MB(Mo%S6P#Jhl>O81E&#?$ewl z!iNnr3N;#I$QDOKg@#d-Zq#T0;I44Yr4iJzmGBzcqK(;OQZ9x{Dswbth=dbyaZ55w z57VO>E-r=cML7n@%rtra_foOO_$+zn=Xo3t%V(u5w{AO+71>2S<1d6cfi^8S(i)FD z!V#hoh8XC~2D7qn#|FZ*@3>u1zqesIl+@y`b>pCz#>rH&vf3k@%;HGGlJb9IDwJ~GV2DVBWG|Jxfq9)I;{*RUD*_!(&GzbK zH4gbnLoV(pG9c+1qYJarl743ec}}@ST~_l*Rm_;V=xuveAo=R;kqhw*8wi1t6?Xuy zr-kr+jy#8Xg&&CE2(<3nxlWfB6hBa<2O<#g4#S4f={#&h4?kghz}v2L)CiTK`msqe zXous5Rwr=$KQIc$&N*X`{hSHf8b&Ci5sQIQA+b!n(<08Lh052TO9hfUF#_zdh6gSs zN>ksFif5NthKa{oyI@^Q@moqJVIp(Wn#?K7Hzuy?2DOL7rg_Cgu@E1tmi5!ZPzxQO zQUL#gdY(nqjN}Kb>jc?xF}F`uqN_aq18)NM&d}Ae75&C`^2xvuc|%kA_S>GI_fI*- zY|g6gL^!8$l@^Gvcc<3-;242AKvk)(Q^ST}EwjoOg%heW8+ECjOt6KD0nnMa@iPBT zdi!)0bHE#lPu-dwP-VCRckUrqa%?%YP-0Ri{$<)ZqQhzHrtw)7W5`4J^4|XTci%Hq z`-B8e(Ac!S`+^vU8~;v`Mw(t~Q>ni;7bU=8KM{uMm7cSxuMP<@EPqVP7=(%e$S?ua z2b}55KMZ|YLon;B=bjbltMu*b4%L>^*@Ha0Hpfzs#&Zg=|DkNsE-gb0?- zO@htke)YbS>UGZXtX--=vIZ%xIjGLQ!`2i4s+Bw#l}>4zrXH*I&v z>@3acf0*P}c8UixNGX#QCrlGjOLUReSgH~jGebo`SeL^sG1h zS)(o9T+Uw})}J%~0UR}nVweyB1-Pgs=G075xR|N))sPGijhHMKTB~Udr6)t zYk!*prdpW^k_xmWM26n>n}rV08L0C_vXIaBdsnfw%W6Jij(3Hw24TVk&m%3 zh5a{cQ&hBEAxdYl1@r229tq zVC522bRS?~h2WZ};*EBcxi-DB1EPfc#2solRm4fo5&~V~b9=ez#uB<8 z{yfQCp5;BW4SzJUhq?lp9iECzMIMFO*fd1WWvZUIlS`TT*EQm=h+D@avty6639 z!^i@U-^4*~Gr3>#So1{Qr|CL=nKJqeNd4-=Lmmmd=hWbBg%6tSS^Y^-JTrfhCrg>H zOi?{hL{(ftK;#oi$-DNu^zs17_Z%B|JM5#a(|0yb-v7jTuAUS$&u&Lb$Ig0MgaDh4 zq^@juhmiF>svd>~zsU*}vA5>ki*RhCse&p<|a3)wy z8OCDdsLv9A`qgb`+|_hsJTt)#yCcY>>{>pBu4)Q}u93wMu5K>tN_KFcLKl=kCFswr zVvD;v1{2^iu|_Blc4??J7q6}Nwr{>7UZBD_ZApf4qtWaZ6#kBWN!do0(y(tf%fcWO zEROrqTGuMRIlaoA`4Fysf_^?5=8B@Kp@V`Bw)Lg{u41|Ttc?1GpSpy?KgkO>LPO{jyM}FO~pG7Vb7eF+mF)SXO7nR5E=AqTPfa{__GF zcdPu%ds|M$phe=1B; zAiaNl*PbbJkSW`;>$xd8&%5=^e0Gk%Ujh;O?gK2b%G@52^wI^%_I|FOy#?*G-a;F3 zMg6%7KzDMjBHDt@FgarTN?ES)5KE$Q+-X>7B7bhbZemA5LcdTX@M79?7ptIr2cDp& zaYq3qO}*f7n(2oODJ$`xT|~R*R@{x3dji4)Jpb&42&n>-rYdAc_m3 z9?21zT1aP&Kd5sA%8$_u()0~SITu&8+&~wnC9*ctfKtfU+*&~6>#lxBNeNvtmhSU# zgkgJH=@pR8<{Gj=e42967R;AAdE2~QHd>FM*08E$Odn6bvJH z`2<_x(ay=@*k&|PRcof49P(*tOtpx1O`NIAlAF+!tj(QuSJM?V zD-1~bfd>-&FO;WUBvaua)pN?XKX=s@c~`EDFb(<4Xpoe;cv3tRAtTdy)Hsr~1DK;> zmD#&W=ot(3&M=Aq$33y}WVT#LdL@B88Bc|yD0&tl8>Sr2PFGOnYrpE{Dh!`dnycLy zJeSU`ab*}{_&Lpp9erUA7^kI&8?U(S{%vdIgmSr?&k-3 zmqK=4MrvEaLCo(2KgHepWS~iSF$DKmPVq6MR?lSrNdXFsqqcigCX?W@-(sUiclwEA z;B6(qGJ64yA(HKNa?T<^qse)g9iN&Enw1EG))W&8C|~r>QEi%dL`FutUe?yDuiW~v zBcX;-x0bG@R2VTXNV-$d`87Hh&BKFFT(|i*`C(&)Yy`$TmD7cX%|04gAzW5FTOMcp zT+mJ~GT+!0#ZQen$vr{z%3NY}oNV3pb$uG2-t`Z&_mDArV3#ie<|BK581EWt){~~R z$)A6#JLVZK#f9hUyz31QbUR?(8{tY}_h(UK4e~GIsc6Fd2Q0_#mxpndL8e(Jyn`n4?E#Z7O02`Ww%8`e>Us@rT7-Qnjj# zqQkDkedfQ#nuFMu5z^0uWSqUOtC$E(D*Ii!RT;S%M2%~2#_5^*WE@d46Y>xJVJlqB z{E{x{>Ws|W>Jx$6(0e!vY_FpVy7&h!lX>!m=5c2m);$`)JX`t^1*1kUH2o+44MMh} z__p}VNtq-Ey0duyuziT0>KtMF%MhC*i#);rcG}^gUjcD>iivY+Rl-hn((N!lysKl{ z-^Pr(+I4-r=X(`wtI;MCvBohhgK$%H*O^$WgojQ{c9oDxzR$d{>7ep7kYjpe{Gy5Z zbsbRU*X2;>67)JN;iw+=)YFqP-2Z%{Tx^@wv1qF&65L=x!7Zj8=M2W{d~W2|uQH>Z z8OHVW^oKk9_&iVN2)G0_m5su1k%`1&fifegrTd8eS=__~s^mPf>aUag+_G4LMYKu{ z%gX2OUw~JBLPUwTc1eBgmI`{uYOW?6bX8y!9Dh(k47Hg>D@qC!BPr(>r1nrZjS40y&DK~_HY07QD#z+8nr zGCcSXYDYvC=9TZJY@Wkx&0t1|a$*N#BC<)ae)4{-dNuZozdW3Xri0;D=xu((++2e2Wir3q@5hW%c*>n{Za=F03c8pTc`Wetir1*>7dx!$U}P5Bgc* zUtvy`Y&X@?rdjet%s}%bv@J^Sj8X8fsv&v!p~MiI_4bredTGrn3&Nkj2;7|Pf*5_5 z($Sj1V{75Y7lKBvNV+Pu7$#o+N+Bd~uu4sU{$+B29?}%+d$3bQ*;cH0Oo&0lxh<a_bELUNku8%!w`cHdqB|ZYA;6@64U~^uBP`gvl%4 zD$xFVX(^GUB=Ir!^Iq5=hnXkj$H}{Bi`urDDw9#@-8WQ6VErTfnM={bU(h^EZZmrj z-Z%Oh^zWd6iuHc2VzpRaYr8)JtDK3E8=c4F-9C#(-%Wm$317CR=nf|Wv8;lCOOr21 z%9%ZP&g1?n*bI&+<+=h&nGi^s?~T1X=eYu85tjCsR4>OFB0^Y_I1{Ybg;YH*c^xhS z#8iVTpI^&3<}l=RF4!K z#lqmXwKM0Q6-mE+mjE2&ng|5vrWHi`H6Q5Ib2e};x6-sAqgG30L8j&E*JH98q*fP> z$7f>4ZpNGyx=>N%?$J0O)#pp}W>TVG?bufZs{7yk->X<><)LFYS6O4V0g9-d0oi1L z0IkAS;xhr9De=bfJwx^gB21r8?=dpdA7|d2>CmD(Yb1l&v4azln!>{!@THZ+Po6^0 zCAz*SMIUA8OY|iQwLStRA5mcU6Y{S==z`~SGBiMH!MO&&OgXeU$$t1B33JX^oDL@Y;};U=#CcPjOID~0uvsB{`$4Q&5Tt}fP=QnS8k@o zlkST75LYQ6+{sRW8AgCA|Lwy-$jyd=FfP_jz6Hw+i|--Yy^0r@@BN>`pOz>Yk2f#k z3wL{@^%L8T5HAdl_<5>83{i60kG-Vq7MQa#MoG_aU8L+%7T*o4q~Pz9MoAb)3=wkc zB@cdo+`e{fjMt~iWZwY-gl&b_F+blXjzV&a+M=A>-nTrs-H2wQ#h`apMa53h9MfLR z6yeE!#lZW~ZveUi@?vj^z~evjrM|uVD+Qu)FsCVfn;&y8N;lO^XpJ!=|xf|f=yvX3Gx%UHc%qH7v236pZaV_#A9 zsFiW1RB@qyC8Zml@{5NaRBc^i*nr-LO|jL0onImMU!d-!p?q!e^rB=}&d0aK|JD1i R+xq9ngH2O10SpxA{{f?KKKB3s literal 15449 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�=0vx85Ddqmq3{=XIL{XN(w>U_ zAg5yA&oJ7UnDg;)ke_;Vi42)lQ`@45Ldue)KP6%a)$)m=&>NDG36!5Dto^6*o~QnB zHiNJ?Iv7j_n43kU5$@-rNnygly zNf=IvY!mN+{7?c>VcVdy#+WvOf18PtiEDVNRPU5zQ1D<=m7qFW%Jq9CExfF2$2?ry zQd6j2sj1rcg0$lMd^{ZG=OVdf*eZ){{=MP}U!?S#g4>2S%kkPoD^*tT)wrm)Cwj@M zd~MCX*Ca?^iKA_tpKW$+Z|nNnToAi*C-dT)9F7rpVKuMZ|@Y(%5D zb0A(r=Z;GY1kHE%y?30a#HGgXxczatA%8&3w4M(65@i{>!DK53rH}c63b`?b4pM;~x`LFLO%04Y<$)^VO`=9r7 za6U1A(-zcTLr&HPWaxn5HA=fETQW&@kjf7e*)_|^1dy`via}OKzlrZv6kJ>=iw}zx zoM@)3;Zi%Ppy9kxJ%fr%MY%x5Wqs3}iu9r;9J3KO7!vw=rBS>M*V-A22cKgXLX_-*d&+XSAk# z(gr<&2z-n__;m5*3&SS<8_Koli#8X~hNg*3?5tBBeY*G}6!3fKptK%NDA6~zjR@D% zPaUlvLuERgPA9!6HvY2)5eoMc$7vA5soy&s9*+9c!6<@Of70(w`h&yaq*2U*-g>Fn z4P)312ZR1#FdiKadQtRx!`|U+&>#1EBP9e6(lMMQFbt*9r(!sYVK^C$2BUFrHX6k+ zj1YX27*3{#{n_YnBGx7a!}0zwz+?{@;Bc=QV7m7VFxztmcVjuRuT=z%DuS0M_qg!iGjfkh{=Fjir;hJAgN9*Yq@x-lzqfB9zXn20 z>;`g{v<7Ce-ioCEXfPYiCWnLBB!XP{@$(@Um;KZ6bT%7~#Q%P@FGBTkC9qdiA6Ef;MD-yB;GUcGn^gdbM=z}aR1tc91)z#qNd>T1$TeX6 z?+&@<6hLjNZ(0E~LG`;)01d5O1G|9TA=khjU{}Z`6~Lf%`ur&80X}-YhMkQ~od*nh zqh7x^8%@TO_B>#p7~qwh2fP>qsGbMB6a$3Rf&m%Sv5}?~_G*_E*Ash%TwG!76>{H| z%V@8Vi))F!LN2a1_6oVU0@*9%zAJCi9w8Uf8sb8eG@a4!ji%$nNo?ceK5KB-lWrNr zmBhvA@3#YGqG+1Gi=ddJX#$OS*8f+_918&xl`hs-QmkH?0dAA^!%v{W~Q8gvGyS zK)FWYDwh z6xzt3Jr0a$BZJz=pf)l{st6k`5phJJoIA8_4-#Hzr|=_20qs!=O?#BkCXPK*sLviz zeMAj}HVLg3XthAA1zIi8YJne23v7tv-l5)#|2CSajV5Y^e;ZBos-uaXp4`g9j&?*g zrrFUx5I8r3vcPU_)6dw&!Tkvz#m`UHMpiQIb+i-lxA>C-JfR!HT&Pb4Ww=XJXZCtg zDbMT=#V?xd-F5L4Lj7CvL$6e9V^zW91!mI_io7l}Bcfca%6xosTl&?;6NtvEgGY+q zDqSSyRlP0ISoM~uP@!GLtExg3bF+!B8M=(|oZ@msSUiOgV+^Z!l~)-g;zFhTH$v(t zeO6|ARI0&OdlD65CCE<5K$Z4k@s~?q4OIJ28=ouB)fv6Hi!ArFX8fo()SjMhpZ;F} P00960?*2pBIq?Djs<{O9 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 5d62a0c56fccb3bcd8554874a97907de3011fc14..f0d2db3c69241b2c6b7cfd999ad7f49e94f7a063 100644 GIT binary patch literal 5035 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 deal.Proposal.StartEpoch { - return &ErrExpiredDeals{xerrors.Errorf("piece %d (of %d) of sector %d refers expired deal %d - should start at %d, head %d", i, len(si.Pieces), si.SectorNumber, p.DealInfo.DealID, deal.Proposal.StartEpoch, ts.Height())} + return &ErrExpiredDeals{xerrors.Errorf("piece %d (of %d) of sector %d refers expired deal %d - should start at %d, head %d", i, len(pieces), sn, p.DealInfo.DealID, deal.Proposal.StartEpoch, ts.Height())} } } if mustHaveDeals && dealCount <= 0 { - return &ErrNoDeals{(xerrors.Errorf("sector %d must have deals, but does not", si.SectorNumber))} + return &ErrNoDeals{xerrors.Errorf("sector %d must have deals, but does not", sn)} } return nil @@ -95,7 +95,7 @@ func checkPieces(ctx context.Context, maddr address.Address, si SectorInfo, api // // matches pieces, and that the seal ticket isn't expired func checkPrecommit(ctx context.Context, maddr address.Address, si SectorInfo, tsk types.TipSetKey, height abi.ChainEpoch, api SealingAPI) (err error) { - if err := checkPieces(ctx, maddr, si, api, false); err != nil { + if err := checkPieces(ctx, maddr, si.SectorNumber, si.Pieces, api, false); err != nil { return err } @@ -210,7 +210,7 @@ func (m *Sealing) checkCommit(ctx context.Context, si SectorInfo, proof []byte, return &ErrInvalidProof{xerrors.New("invalid proof (compute error?)")} } - if err := checkPieces(ctx, m.maddr, si, m.Api, false); err != nil { + if err := checkPieces(ctx, m.maddr, si.SectorNumber, si.Pieces, m.Api, false); err != nil { return err } @@ -220,7 +220,7 @@ func (m *Sealing) checkCommit(ctx context.Context, si SectorInfo, proof []byte, // check that sector info is good after running a replica update func checkReplicaUpdate(ctx context.Context, maddr address.Address, si SectorInfo, tsk types.TipSetKey, api SealingAPI) error { - if err := checkPieces(ctx, maddr, si, api, true); err != nil { + if err := checkPieces(ctx, maddr, si.SectorNumber, si.Pieces, api, true); err != nil { return err } if !si.CCUpdate { diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go new file mode 100644 index 00000000000..e32fd4f8647 --- /dev/null +++ b/storage/pipeline/receive.go @@ -0,0 +1,78 @@ +package sealing + +import ( + "context" + + "github.com/ipfs/go-datastore" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/api" +) + +func (m *Sealing) Receive(ctx context.Context, meta api.RemoteSectorMeta) error { + if err := m.checkSectorMeta(ctx, meta); err != nil { + return err + } + + panic("impl me") +} + +func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta) error { + { + mid, err := address.IDFromAddress(m.maddr) + if err != nil { + panic(err) + } + + if meta.Sector.Miner != abi.ActorID(mid) { + return xerrors.Errorf("sector for wrong actor - expected actor id %d, sector was for actor %d", mid, meta.Sector.Miner) + } + } + + { + // initial sanity check, doesn't prevent races + _, err := m.GetSectorInfo(meta.Sector.Number) + if err != nil && !xerrors.Is(err, datastore.ErrNotFound) { + return err + } + if err == nil { + return xerrors.Errorf("sector with ID %d already exists in the sealing pipeline", meta.Sector.Number) + } + } + + { + spt, err := m.currentSealProof(ctx) + if err != nil { + return err + } + + if meta.Type != spt { + return xerrors.Errorf("sector seal proof type doesn't match current seal proof type (%d!=%d)", meta.Type, spt) + } + } + + switch SectorState(meta.State) { + case Packing: + //checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false) + + fallthrough + case GetTicket: + + fallthrough + case PreCommitting: + + fallthrough + case SubmitCommit: + + fallthrough + case Proving, Available: + + return nil + default: + return xerrors.Errorf("imported sector State in not supported") + } + +} diff --git a/storage/pipeline/states_replica_update.go b/storage/pipeline/states_replica_update.go index 3392b92e700..2a981e81503 100644 --- a/storage/pipeline/states_replica_update.go +++ b/storage/pipeline/states_replica_update.go @@ -21,7 +21,7 @@ import ( ) func (m *Sealing) handleReplicaUpdate(ctx statemachine.Context, sector SectorInfo) error { - if err := checkPieces(ctx.Context(), m.maddr, sector, m.Api, true); err != nil { // Sanity check state + if err := checkPieces(ctx.Context(), m.maddr, sector.SectorNumber, sector.Pieces, m.Api, true); err != nil { // Sanity check state return handleErrors(ctx, err, sector) } out, err := m.sealer.ReplicaUpdate(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), sector.pieceInfos()) @@ -61,7 +61,7 @@ func (m *Sealing) handleProveReplicaUpdate(ctx statemachine.Context, sector Sect return ctx.Send(SectorProveReplicaUpdateFailed{xerrors.Errorf("prove replica update (1) failed: %w", err)}) } - if err := checkPieces(ctx.Context(), m.maddr, sector, m.Api, true); err != nil { // Sanity check state + if err := checkPieces(ctx.Context(), m.maddr, sector.SectorNumber, sector.Pieces, m.Api, true); err != nil { // Sanity check state return handleErrors(ctx, err, sector) } diff --git a/storage/pipeline/states_sealing.go b/storage/pipeline/states_sealing.go index 5ec8f077f66..354d15e69cb 100644 --- a/storage/pipeline/states_sealing.go +++ b/storage/pipeline/states_sealing.go @@ -202,7 +202,7 @@ func (m *Sealing) handleGetTicket(ctx statemachine.Context, sector SectorInfo) e } func (m *Sealing) handlePreCommit1(ctx statemachine.Context, sector SectorInfo) error { - if err := checkPieces(ctx.Context(), m.maddr, sector, m.Api, false); err != nil { // Sanity check state + if err := checkPieces(ctx.Context(), m.maddr, sector.SectorNumber, sector.Pieces, m.Api, false); err != nil { // Sanity check state switch err.(type) { case *ErrApi: log.Errorf("handlePreCommit1: api error, not proceeding: %+v", err) From f48cb677ae68f2a67a6c1b967f108c90d4398ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 25 Aug 2022 20:37:36 -0400 Subject: [PATCH 02/26] sealing: Drop redundant Piece type --- api/cbor_gen.go | 123 +++++++++++++++++++ cmd/lotus-miner/init.go | 2 +- gen/main.go | 1 + itests/kit/ensemble.go | 2 +- storage/pipeline/cbor_gen.go | 139 ++-------------------- storage/pipeline/checks.go | 3 +- storage/pipeline/fsm_events.go | 5 +- storage/pipeline/gen/main.go | 1 - storage/pipeline/input.go | 4 +- storage/pipeline/precommit_policy.go | 5 +- storage/pipeline/precommit_policy_test.go | 6 +- storage/pipeline/states_failed_test.go | 2 +- storage/pipeline/types.go | 18 +-- storage/pipeline/types_test.go | 2 +- 14 files changed, 152 insertions(+), 161 deletions(-) diff --git a/api/cbor_gen.go b/api/cbor_gen.go index 66655fd7587..0932bdbc0a3 100644 --- a/api/cbor_gen.go +++ b/api/cbor_gen.go @@ -1005,6 +1005,129 @@ func (t *PieceDealInfo) UnmarshalCBOR(r io.Reader) (err error) { return nil } +func (t *SectorPiece) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Piece (abi.PieceInfo) (struct) + if len("Piece") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Piece\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("Piece"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Piece")); err != nil { + return err + } + + if err := t.Piece.MarshalCBOR(cw); err != nil { + return err + } + + // t.DealInfo (api.PieceDealInfo) (struct) + if len("DealInfo") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"DealInfo\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("DealInfo"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("DealInfo")); err != nil { + return err + } + + if err := t.DealInfo.MarshalCBOR(cw); err != nil { + return err + } + return nil +} + +func (t *SectorPiece) UnmarshalCBOR(r io.Reader) (err error) { + *t = SectorPiece{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("SectorPiece: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Piece (abi.PieceInfo) (struct) + case "Piece": + + { + + if err := t.Piece.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.Piece: %w", err) + } + + } + // t.DealInfo (api.PieceDealInfo) (struct) + case "DealInfo": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.DealInfo = new(PieceDealInfo) + if err := t.DealInfo.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.DealInfo pointer: %w", err) + } + } + + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} func (t *DealSchedule) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) diff --git a/cmd/lotus-miner/init.go b/cmd/lotus-miner/init.go index 055df69efe1..79f9cee5fb1 100644 --- a/cmd/lotus-miner/init.go +++ b/cmd/lotus-miner/init.go @@ -315,7 +315,7 @@ func migratePreSealMeta(ctx context.Context, api v1api.FullNode, metadata string info := &pipeline.SectorInfo{ State: pipeline.Proving, SectorNumber: sector.SectorID, - Pieces: []pipeline.Piece{ + Pieces: []lapi.SectorPiece{ { Piece: abi.PieceInfo{ Size: abi.PaddedPieceSize(meta.SectorSize), diff --git a/gen/main.go b/gen/main.go index fcb1d6dfa98..ad331402daf 100644 --- a/gen/main.go +++ b/gen/main.go @@ -64,6 +64,7 @@ func main() { api.SealTicket{}, api.SealSeed{}, api.PieceDealInfo{}, + api.SectorPiece{}, api.DealSchedule{}, ) if err != nil { diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index 98d7b178f1f..bcc2d93c2a7 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -962,7 +962,7 @@ func importPreSealMeta(ctx context.Context, meta genesis.Miner, mds dtypes.Metad info := &pipeline.SectorInfo{ State: pipeline.Proving, SectorNumber: sector.SectorID, - Pieces: []pipeline.Piece{ + Pieces: []api.SectorPiece{ { Piece: abi.PieceInfo{ Size: abi.PaddedPieceSize(meta.SectorSize), diff --git a/storage/pipeline/cbor_gen.go b/storage/pipeline/cbor_gen.go index 2fb8c445c84..ddeb449ba12 100644 --- a/storage/pipeline/cbor_gen.go +++ b/storage/pipeline/cbor_gen.go @@ -23,129 +23,6 @@ var _ = cid.Undef var _ = math.E var _ = sort.Sort -func (t *Piece) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - - cw := cbg.NewCborWriter(w) - - if _, err := cw.Write([]byte{162}); err != nil { - return err - } - - // t.Piece (abi.PieceInfo) (struct) - if len("Piece") > cbg.MaxLength { - return xerrors.Errorf("Value in field \"Piece\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("Piece"))); err != nil { - return err - } - if _, err := io.WriteString(w, string("Piece")); err != nil { - return err - } - - if err := t.Piece.MarshalCBOR(cw); err != nil { - return err - } - - // t.DealInfo (api.PieceDealInfo) (struct) - if len("DealInfo") > cbg.MaxLength { - return xerrors.Errorf("Value in field \"DealInfo\" was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("DealInfo"))); err != nil { - return err - } - if _, err := io.WriteString(w, string("DealInfo")); err != nil { - return err - } - - if err := t.DealInfo.MarshalCBOR(cw); err != nil { - return err - } - return nil -} - -func (t *Piece) UnmarshalCBOR(r io.Reader) (err error) { - *t = Piece{} - - cr := cbg.NewCborReader(r) - - maj, extra, err := cr.ReadHeader() - if err != nil { - return err - } - defer func() { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - }() - - if maj != cbg.MajMap { - return fmt.Errorf("cbor input should be of type map") - } - - if extra > cbg.MaxLength { - return fmt.Errorf("Piece: map struct too large (%d)", extra) - } - - var name string - n := extra - - for i := uint64(0); i < n; i++ { - - { - sval, err := cbg.ReadString(cr) - if err != nil { - return err - } - - name = string(sval) - } - - switch name { - // t.Piece (abi.PieceInfo) (struct) - case "Piece": - - { - - if err := t.Piece.UnmarshalCBOR(cr); err != nil { - return xerrors.Errorf("unmarshaling t.Piece: %w", err) - } - - } - // t.DealInfo (api.PieceDealInfo) (struct) - case "DealInfo": - - { - - b, err := cr.ReadByte() - if err != nil { - return err - } - if b != cbg.CborNull[0] { - if err := cr.UnreadByte(); err != nil { - return err - } - t.DealInfo = new(api.PieceDealInfo) - if err := t.DealInfo.UnmarshalCBOR(cr); err != nil { - return xerrors.Errorf("unmarshaling t.DealInfo pointer: %w", err) - } - } - - } - - default: - // Field doesn't exist on this type, so ignore it - cbg.ScanForLinks(r, func(cid.Cid) {}) - } - } - - return nil -} func (t *SectorInfo) MarshalCBOR(w io.Writer) error { if t == nil { _, err := w.Write(cbg.CborNull) @@ -241,7 +118,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { } } - // t.Pieces ([]sealing.Piece) (slice) + // t.Pieces ([]api.SectorPiece) (slice) if len("Pieces") > cbg.MaxLength { return xerrors.Errorf("Value in field \"Pieces\" was too long") } @@ -590,7 +467,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { return err } - // t.CCPieces ([]sealing.Piece) (slice) + // t.CCPieces ([]api.SectorPiece) (slice) if len("CCPieces") > cbg.MaxLength { return xerrors.Errorf("Value in field \"CCPieces\" was too long") } @@ -960,7 +837,7 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { t.CreationTime = int64(extraI) } - // t.Pieces ([]sealing.Piece) (slice) + // t.Pieces ([]api.SectorPiece) (slice) case "Pieces": maj, extra, err = cr.ReadHeader() @@ -977,12 +854,12 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { } if extra > 0 { - t.Pieces = make([]Piece, extra) + t.Pieces = make([]api.SectorPiece, extra) } for i := 0; i < int(extra); i++ { - var v Piece + var v api.SectorPiece if err := v.UnmarshalCBOR(cr); err != nil { return err } @@ -1310,7 +1187,7 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { default: return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) } - // t.CCPieces ([]sealing.Piece) (slice) + // t.CCPieces ([]api.SectorPiece) (slice) case "CCPieces": maj, extra, err = cr.ReadHeader() @@ -1327,12 +1204,12 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { } if extra > 0 { - t.CCPieces = make([]Piece, extra) + t.CCPieces = make([]api.SectorPiece, extra) } for i := 0; i < int(extra); i++ { - var v Piece + var v api.SectorPiece if err := v.UnmarshalCBOR(cr); err != nil { return err } diff --git a/storage/pipeline/checks.go b/storage/pipeline/checks.go index ce0512c2b32..10f7a9eafaf 100644 --- a/storage/pipeline/checks.go +++ b/storage/pipeline/checks.go @@ -13,6 +13,7 @@ import ( "github.com/filecoin-project/go-state-types/crypto" prooftypes "github.com/filecoin-project/go-state-types/proof" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" ) @@ -41,7 +42,7 @@ type ErrCommitWaitFailed struct{ error } type ErrBadRU struct{ error } type ErrBadPR struct{ error } -func checkPieces(ctx context.Context, maddr address.Address, sn abi.SectorNumber, pieces []Piece, api SealingAPI, mustHaveDeals bool) error { +func checkPieces(ctx context.Context, maddr address.Address, sn abi.SectorNumber, pieces []api.SectorPiece, api SealingAPI, mustHaveDeals bool) error { ts, err := api.ChainHead(ctx) if err != nil { return &ErrApi{xerrors.Errorf("getting chain head: %w", err)} diff --git a/storage/pipeline/fsm_events.go b/storage/pipeline/fsm_events.go index eb108715101..74c3d4f8911 100644 --- a/storage/pipeline/fsm_events.go +++ b/storage/pipeline/fsm_events.go @@ -10,6 +10,7 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-state-types/builtin/v8/miner" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) @@ -87,7 +88,7 @@ func (evt SectorAddPiece) apply(state *SectorInfo) { } type SectorPieceAdded struct { - NewPieces []Piece + NewPieces []api.SectorPiece } func (evt SectorPieceAdded) apply(state *SectorInfo) { @@ -113,7 +114,7 @@ type SectorPacked struct{ FillerPieces []abi.PieceInfo } func (evt SectorPacked) apply(state *SectorInfo) { for idx := range evt.FillerPieces { - state.Pieces = append(state.Pieces, Piece{ + state.Pieces = append(state.Pieces, api.SectorPiece{ Piece: evt.FillerPieces[idx], DealInfo: nil, // filler pieces don't have deals associated with them }) diff --git a/storage/pipeline/gen/main.go b/storage/pipeline/gen/main.go index 6da1d96b7e2..578c81478d6 100644 --- a/storage/pipeline/gen/main.go +++ b/storage/pipeline/gen/main.go @@ -11,7 +11,6 @@ import ( func main() { err := gen.WriteMapEncodersToFile("./cbor_gen.go", "sealing", - sealing.Piece{}, sealing.SectorInfo{}, sealing.Log{}, ) diff --git a/storage/pipeline/input.go b/storage/pipeline/input.go index c7af7783e0d..9e8b610e063 100644 --- a/storage/pipeline/input.go +++ b/storage/pipeline/input.go @@ -234,7 +234,7 @@ func (m *Sealing) handleAddPiece(ctx statemachine.Context, sector SectorInfo) er } pieceSizes = append(pieceSizes, p.Unpadded()) - res.NewPieces = append(res.NewPieces, Piece{ + res.NewPieces = append(res.NewPieces, api.SectorPiece{ Piece: ppi, }) } @@ -262,7 +262,7 @@ func (m *Sealing) handleAddPiece(ctx statemachine.Context, sector SectorInfo) er offset += deal.size pieceSizes = append(pieceSizes, deal.size) - res.NewPieces = append(res.NewPieces, Piece{ + res.NewPieces = append(res.NewPieces, api.SectorPiece{ Piece: ppi, DealInfo: &deal.deal, }) diff --git a/storage/pipeline/precommit_policy.go b/storage/pipeline/precommit_policy.go index e0761d209cd..04f69a93aff 100644 --- a/storage/pipeline/precommit_policy.go +++ b/storage/pipeline/precommit_policy.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/go-state-types/builtin/v8/miner" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" @@ -16,7 +17,7 @@ import ( ) type PreCommitPolicy interface { - Expiration(ctx context.Context, ps ...Piece) (abi.ChainEpoch, error) + Expiration(ctx context.Context, ps ...api.SectorPiece) (abi.ChainEpoch, error) } type Chain interface { @@ -59,7 +60,7 @@ func NewBasicPreCommitPolicy(api Chain, cfgGetter dtypes.GetSealingConfigFunc, p // Expiration produces the pre-commit sector expiration epoch for an encoded // replica containing the provided enumeration of pieces and deals. -func (p *BasicPreCommitPolicy) Expiration(ctx context.Context, ps ...Piece) (abi.ChainEpoch, error) { +func (p *BasicPreCommitPolicy) Expiration(ctx context.Context, ps ...api.SectorPiece) (abi.ChainEpoch, error) { ts, err := p.api.ChainHead(ctx) if err != nil { return 0, err diff --git a/storage/pipeline/precommit_policy_test.go b/storage/pipeline/precommit_policy_test.go index 5d2da1ee0ac..b81086362bc 100644 --- a/storage/pipeline/precommit_policy_test.go +++ b/storage/pipeline/precommit_policy_test.go @@ -95,7 +95,7 @@ func TestBasicPolicyMostConstrictiveSchedule(t *testing.T) { h: abi.ChainEpoch(55), }, cfg, 2) longestDealEpochEnd := abi.ChainEpoch(547300) - pieces := []pipeline.Piece{ + pieces := []api.SectorPiece{ { Piece: abi.PieceInfo{ Size: abi.PaddedPieceSize(1024), @@ -136,7 +136,7 @@ func TestBasicPolicyIgnoresExistingScheduleIfExpired(t *testing.T) { h: abi.ChainEpoch(55), }, cfg, 0) - pieces := []pipeline.Piece{ + pieces := []api.SectorPiece{ { Piece: abi.PieceInfo{ Size: abi.PaddedPieceSize(1024), @@ -165,7 +165,7 @@ func TestMissingDealIsIgnored(t *testing.T) { h: abi.ChainEpoch(55), }, cfg, 0) - pieces := []pipeline.Piece{ + pieces := []api.SectorPiece{ { Piece: abi.PieceInfo{ Size: abi.PaddedPieceSize(1024), diff --git a/storage/pipeline/states_failed_test.go b/storage/pipeline/states_failed_test.go index 0243af1268a..f6846c8f5f1 100644 --- a/storage/pipeline/states_failed_test.go +++ b/storage/pipeline/states_failed_test.go @@ -76,7 +76,7 @@ func TestStateRecoverDealIDs(t *testing.T) { // TODO sctx should satisfy an interface so it can be useable for mocking. This will fail because we are passing in an empty context now to get this to build. // https://github.com/filecoin-project/lotus/issues/7867 err := fakeSealing.HandleRecoverDealIDs(statemachine.Context{}, pipeline.SectorInfo{ - Pieces: []pipeline.Piece{ + Pieces: []api2.SectorPiece{ { DealInfo: &api2.PieceDealInfo{ DealID: dealId, diff --git a/storage/pipeline/types.go b/storage/pipeline/types.go index 5889588bd86..e2b724198ae 100644 --- a/storage/pipeline/types.go +++ b/storage/pipeline/types.go @@ -23,18 +23,6 @@ type Context interface { Send(evt interface{}) error } -// Piece is a tuple of piece and deal info -type PieceWithDealInfo struct { - Piece abi.PieceInfo - DealInfo api.PieceDealInfo -} - -// Piece is a tuple of piece info and optional deal -type Piece struct { - Piece abi.PieceInfo - DealInfo *api.PieceDealInfo // nil for pieces which do not appear in deals (e.g. filler pieces) -} - type Log struct { Timestamp uint64 Trace string // for errors @@ -62,7 +50,7 @@ type SectorInfo struct { // Packing CreationTime int64 // unix seconds - Pieces []Piece + Pieces []api.SectorPiece // PreCommit1 TicketValue abi.SealRandomness @@ -91,7 +79,7 @@ type SectorInfo struct { // CCUpdate CCUpdate bool - CCPieces []Piece + CCPieces []api.SectorPiece UpdateSealed *cid.Cid UpdateUnsealed *cid.Cid ReplicaUpdateProof storiface.ReplicaUpdateProof @@ -163,7 +151,7 @@ func (t *SectorInfo) sealingCtx(ctx context.Context) context.Context { // Returns list of offset/length tuples of sector data ranges which clients // requested to keep unsealed -func (t *SectorInfo) keepUnsealedRanges(pieces []Piece, invert, alwaysKeep bool) []storiface.Range { +func (t *SectorInfo) keepUnsealedRanges(pieces []api.SectorPiece, invert, alwaysKeep bool) []storiface.Range { var out []storiface.Range var at abi.UnpaddedPieceSize diff --git a/storage/pipeline/types_test.go b/storage/pipeline/types_test.go index 69e102bf441..5aa0f7dc282 100644 --- a/storage/pipeline/types_test.go +++ b/storage/pipeline/types_test.go @@ -43,7 +43,7 @@ func TestSectorInfoSerialization(t *testing.T) { si := &SectorInfo{ State: "stateful", SectorNumber: 234, - Pieces: []Piece{{ + Pieces: []api.SectorPiece{{ Piece: abi.PieceInfo{ Size: 5, PieceCID: dummyCid, From 6f478ea6e7afd7d77bb46d6613fc0505f16766c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 25 Aug 2022 20:48:57 -0400 Subject: [PATCH 03/26] sector import: Check pieces in Sealing.Receive --- storage/pipeline/receive.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index e32fd4f8647..134e3b7ebdd 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -56,7 +56,9 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta switch SectorState(meta.State) { case Packing: - //checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false) + if err := checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false); err != nil { + return xerrors.Errorf("checking pieces: %w", err) + } fallthrough case GetTicket: From d05a4f415b55a74f1fa0cdde5ca8d770be437d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 25 Aug 2022 20:53:21 -0400 Subject: [PATCH 04/26] sealing: Validate piece alignment in checkPieces --- storage/pipeline/checks.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/pipeline/checks.go b/storage/pipeline/checks.go index 10f7a9eafaf..6381ce898c3 100644 --- a/storage/pipeline/checks.go +++ b/storage/pipeline/checks.go @@ -49,8 +49,15 @@ func checkPieces(ctx context.Context, maddr address.Address, sn abi.SectorNumber } dealCount := 0 + var offset abi.PaddedPieceSize for i, p := range pieces { + // check that the piece is correctly aligned + if offset%p.Piece.Size != 0 { + return &ErrInvalidPiece{xerrors.Errorf("sector %d piece %d is not aligned: size=%xh offset=%xh off-by=%xh", sn, i, p.Piece.Size, offset, offset%p.Piece.Size)} + } + offset += p.Piece.Size + // if no deal is associated with the piece, ensure that we added it as // filler (i.e. ensure that it has a zero PieceCID) if p.DealInfo == nil { From 3b28b5a28f2ef618737f3553f4b856fadb6b89b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Thu, 25 Aug 2022 21:24:12 -0400 Subject: [PATCH 05/26] sector import: Fix missing perm tag on SectorReceive --- api/api_storage.go | 2 +- api/proxy_gen.go | 2 +- build/openrpc/miner.json.gz | Bin 15743 -> 15711 bytes documentation/en/api-v0-methods-miner.md | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index e4ca49c2125..afae3a5aee3 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -141,7 +141,7 @@ type StorageMiner interface { // SectorNumFree drops a sector reservation SectorNumFree(ctx context.Context, name string) error //perm:admin - SectorReceive(ctx context.Context, meta RemoteSectorMeta) error + SectorReceive(ctx context.Context, meta RemoteSectorMeta) error //perm:admin // WorkerConnect tells the node to connect to workers RPC WorkerConnect(context.Context, string) error //perm:admin retry:true diff --git a/api/proxy_gen.go b/api/proxy_gen.go index e7efdf1f142..21fdcc7e549 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -844,7 +844,7 @@ type StorageMinerStruct struct { SectorPreCommitPending func(p0 context.Context) ([]abi.SectorID, error) `perm:"admin"` - SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `` + SectorReceive func(p0 context.Context, p1 RemoteSectorMeta) error `perm:"admin"` SectorRemove func(p0 context.Context, p1 abi.SectorNumber) error `perm:"admin"` diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 99ca3b3666cabaaf974b06194236752f869832ef..4912f83066e10949969be4d4b166088da92f0aa2 100644 GIT binary patch delta 5504 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 C&(e4R delta 5496 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 diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 926acc1861a..d65b6d682cd 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -3126,9 +3126,9 @@ Response: ``` ### SectorReceive -There are not yet any comments for this method. -Perms: + +Perms: admin Inputs: ```json From feced5e422ac8d41310c6ff22c17836384dbf335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 30 Aug 2022 21:45:36 +0200 Subject: [PATCH 06/26] sector import: More check progress --- storage/pipeline/receive.go | 55 +++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index 134e3b7ebdd..1d6813ae8e2 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -2,6 +2,8 @@ package sealing import ( "context" + "errors" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/ipfs/go-datastore" "golang.org/x/xerrors" @@ -17,6 +19,15 @@ func (m *Sealing) Receive(ctx context.Context, meta api.RemoteSectorMeta) error return err } + err := m.sectors.Get(uint64(meta.Sector.Number)).Get(&cbg.Deferred{}) + if errors.Is(err, datastore.ErrNotFound) { + + } else if err != nil { + return xerrors.Errorf("checking if sector exists: %w", err) + } else if err == nil { + return xerrors.Errorf("sector %d state already exists", meta.Sector.Number) + } + panic("impl me") } @@ -54,27 +65,53 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta } } + var info SectorInfo + switch SectorState(meta.State) { - case Packing: - if err := checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false); err != nil { - return xerrors.Errorf("checking pieces: %w", err) - } + case Proving, Available: + // todo possibly check + info.CommitMessage = meta.CommitMessage fallthrough - case GetTicket: + case SubmitCommit: + info.PreCommitInfo = meta.PreCommitInfo + info.PreCommitDeposit = meta.PreCommitDeposit + info.PreCommitMessage = meta.PreCommitMessage + info.PreCommitTipSet = meta.PreCommitTipSet + + // todo check + info.SeedValue = meta.SeedValue + info.SeedEpoch = meta.SeedEpoch + + // todo validate + info.Proof = meta.CommitProof fallthrough case PreCommitting: + info.TicketValue = meta.TicketValue + info.TicketEpoch = meta.TicketEpoch - fallthrough - case SubmitCommit: + info.PreCommit1Out = meta.PreCommit1Out + + info.CommD = meta.CommD // todo check cid prefixes + info.CommR = meta.CommR fallthrough - case Proving, Available: + case GetTicket: + fallthrough + case Packing: + // todo check num free + info.State = SectorState(meta.State) // todo dedupe states + info.SectorNumber = meta.Sector.Number + info.Pieces = meta.Pieces + info.SectorType = meta.Type + + if err := checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false); err != nil { + return xerrors.Errorf("checking pieces: %w", err) + } return nil default: return xerrors.Errorf("imported sector State in not supported") } - } From c2dc2f9359e09fe8816632173de315abf8b7e7f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 31 Aug 2022 12:43:40 +0200 Subject: [PATCH 07/26] sector import: Put the imported sector into the sealing pipeline --- cmd/lotus-miner/info.go | 2 ++ storage/pipeline/fsm.go | 8 +++++ storage/pipeline/fsm_events.go | 12 ++++++++ storage/pipeline/receive.go | 53 ++++++++++++++++++++------------ storage/pipeline/sector_state.go | 6 +++- storage/pipeline/types.go | 2 +- 6 files changed, 61 insertions(+), 22 deletions(-) diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index 398d030a526..baad55e37d1 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -504,6 +504,8 @@ var stateList = []stateMeta{ {col: color.FgGreen, state: sealing.Available}, {col: color.FgGreen, state: sealing.UpdateActivating}, + {col: color.FgMagenta, state: sealing.ReceiveSector}, + {col: color.FgBlue, state: sealing.Empty}, {col: color.FgBlue, state: sealing.WaitDeals}, {col: color.FgBlue, state: sealing.AddPiece}, diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index 3df57a501ad..59e99bc596b 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -40,6 +40,11 @@ func (m *Sealing) Plan(events []statemachine.Event, user interface{}) (interface } var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *SectorInfo) (uint64, error){ + // external import + ReceiveSector: planOne( + onReturning(SectorReceived{}), + ), + // Sealing UndefinedSectorState: planOne( @@ -457,6 +462,9 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta } switch state.State { + case ReceiveSector: + return m.handleReceiveSector, processed, nil + // Happy path case Empty: fallthrough diff --git a/storage/pipeline/fsm_events.go b/storage/pipeline/fsm_events.go index 74c3d4f8911..8576d4181ac 100644 --- a/storage/pipeline/fsm_events.go +++ b/storage/pipeline/fsm_events.go @@ -527,3 +527,15 @@ type SectorRemoveFailed struct{ error } func (evt SectorRemoveFailed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorRemoveFailed) apply(*SectorInfo) {} + +type SectorReceive struct { + State SectorInfo +} + +func (evt SectorReceive) apply(state *SectorInfo) { + *state = evt.State +} + +type SectorReceived struct{} + +func (evt SectorReceived) apply(state *SectorInfo) {} diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index 1d6813ae8e2..4a70932a501 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -2,9 +2,7 @@ package sealing import ( "context" - "errors" - cbg "github.com/whyrusleeping/cbor-gen" - + "github.com/filecoin-project/go-statemachine" "github.com/ipfs/go-datastore" "golang.org/x/xerrors" @@ -15,23 +13,30 @@ import ( ) func (m *Sealing) Receive(ctx context.Context, meta api.RemoteSectorMeta) error { - if err := m.checkSectorMeta(ctx, meta); err != nil { + si, err := m.checkSectorMeta(ctx, meta) + if err != nil { return err } - err := m.sectors.Get(uint64(meta.Sector.Number)).Get(&cbg.Deferred{}) - if errors.Is(err, datastore.ErrNotFound) { - - } else if err != nil { + exists, err := m.sectors.Has(uint64(meta.Sector.Number)) + if err != nil { return xerrors.Errorf("checking if sector exists: %w", err) - } else if err == nil { + } + if exists { return xerrors.Errorf("sector %d state already exists", meta.Sector.Number) } - panic("impl me") + err = m.sectors.Send(uint64(meta.Sector.Number), SectorReceive{ + State: si, + }) + if err != nil { + return xerrors.Errorf("receiving sector: %w", err) + } + + return nil } -func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta) error { +func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta) (SectorInfo, error) { { mid, err := address.IDFromAddress(m.maddr) if err != nil { @@ -39,7 +44,7 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta } if meta.Sector.Miner != abi.ActorID(mid) { - return xerrors.Errorf("sector for wrong actor - expected actor id %d, sector was for actor %d", mid, meta.Sector.Miner) + return SectorInfo{}, xerrors.Errorf("sector for wrong actor - expected actor id %d, sector was for actor %d", mid, meta.Sector.Miner) } } @@ -47,21 +52,21 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta // initial sanity check, doesn't prevent races _, err := m.GetSectorInfo(meta.Sector.Number) if err != nil && !xerrors.Is(err, datastore.ErrNotFound) { - return err + return SectorInfo{}, err } if err == nil { - return xerrors.Errorf("sector with ID %d already exists in the sealing pipeline", meta.Sector.Number) + return SectorInfo{}, xerrors.Errorf("sector with ID %d already exists in the sealing pipeline", meta.Sector.Number) } } { spt, err := m.currentSealProof(ctx) if err != nil { - return err + return SectorInfo{}, err } if meta.Type != spt { - return xerrors.Errorf("sector seal proof type doesn't match current seal proof type (%d!=%d)", meta.Type, spt) + return SectorInfo{}, xerrors.Errorf("sector seal proof type doesn't match current seal proof type (%d!=%d)", meta.Type, spt) } } @@ -101,17 +106,25 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta fallthrough case Packing: // todo check num free - info.State = SectorState(meta.State) // todo dedupe states + info.Return = ReturnState(meta.State) // todo dedupe states + info.State = ReceiveSector + info.SectorNumber = meta.Sector.Number info.Pieces = meta.Pieces info.SectorType = meta.Type if err := checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false); err != nil { - return xerrors.Errorf("checking pieces: %w", err) + return SectorInfo{}, xerrors.Errorf("checking pieces: %w", err) } - return nil + return info, nil default: - return xerrors.Errorf("imported sector State in not supported") + return SectorInfo{}, xerrors.Errorf("imported sector State in not supported") } } + +func (m *Sealing) handleReceiveSector(ctx statemachine.Context, sector SectorInfo) error { + // todo fetch stuff + + return ctx.Send(SectorReceived{}) +} diff --git a/storage/pipeline/sector_state.go b/storage/pipeline/sector_state.go index 4f81f5544e0..ad77fdbd5e1 100644 --- a/storage/pipeline/sector_state.go +++ b/storage/pipeline/sector_state.go @@ -63,6 +63,7 @@ var ExistSectorStateList = map[SectorState]struct{}{ ReleaseSectorKeyFailed: {}, FinalizeReplicaUpdateFailed: {}, AbortUpgrade: {}, + ReceiveSector: {}, } // cmd/lotus-miner/info.go defines CLI colors corresponding to these states @@ -113,6 +114,9 @@ const ( UpdateActivating SectorState = "UpdateActivating" ReleaseSectorKey SectorState = "ReleaseSectorKey" + // external import + ReceiveSector SectorState = "ReceiveSector" + // error modes FailedUnrecoverable SectorState = "FailedUnrecoverable" AddPieceFailed SectorState = "AddPieceFailed" @@ -153,7 +157,7 @@ func toStatState(st SectorState, finEarly bool) statSectorState { switch st { case UndefinedSectorState, Empty, WaitDeals, AddPiece, AddPieceFailed, SnapDealsWaitDeals, SnapDealsAddPiece: return sstStaging - case Packing, GetTicket, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, CommitFinalize, FinalizeSector, SnapDealsPacking, UpdateReplica, ProveReplicaUpdate, FinalizeReplicaUpdate: + case Packing, GetTicket, PreCommit1, PreCommit2, PreCommitting, PreCommitWait, SubmitPreCommitBatch, PreCommitBatchWait, WaitSeed, Committing, CommitFinalize, FinalizeSector, SnapDealsPacking, UpdateReplica, ProveReplicaUpdate, FinalizeReplicaUpdate, ReceiveSector: return sstSealing case SubmitCommit, CommitWait, SubmitCommitAggregate, CommitAggregateWait, SubmitReplicaUpdate, ReplicaUpdateWait: if finEarly { diff --git a/storage/pipeline/types.go b/storage/pipeline/types.go index e2b724198ae..e304a9ff677 100644 --- a/storage/pipeline/types.go +++ b/storage/pipeline/types.go @@ -88,7 +88,7 @@ type SectorInfo struct { // Faults FaultReportMsg *cid.Cid - // Recovery + // Recovery / Import Return ReturnState // Termination From bb04b75ae3c3a37a172469a4b11f4a824b9ed16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Wed, 31 Aug 2022 13:56:25 +0200 Subject: [PATCH 08/26] sector import: Plumbing for DownloadSectorData in the sealing system --- api/api_storage.go | 25 ++----- api/api_worker.go | 1 + api/docgen/docgen.go | 8 +++ api/proxy_gen.go | 26 ++++++++ build/openrpc/full.json.gz | Bin 28354 -> 28355 bytes build/openrpc/gateway.json.gz | Bin 4942 -> 4943 bytes build/openrpc/miner.json.gz | Bin 15711 -> 15751 bytes build/openrpc/worker.json.gz | Bin 5035 -> 5202 bytes documentation/en/api-v0-methods-miner.md | 25 +++++++ documentation/en/api-v0-methods-worker.md | 42 ++++++++++++ storage/pipeline/receive.go | 6 +- storage/sealer/ffiwrapper/sealer_cgo.go | 4 ++ storage/sealer/manager.go | 77 ++++++++++++++++++++++ storage/sealer/sealtasks/task.go | 13 ++-- storage/sealer/storiface/storage.go | 20 ++++++ storage/sealer/storiface/worker.go | 2 + storage/sealer/worker_local.go | 13 ++++ 17 files changed, 235 insertions(+), 27 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index afae3a5aee3..b57129b254a 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -3,7 +3,6 @@ package api import ( "bytes" "context" - "net/http" "time" "github.com/google/uuid" @@ -165,6 +164,7 @@ type StorageMiner interface { ReturnMoveStorage(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnUnsealPiece(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnReadPiece(ctx context.Context, callID storiface.CallID, ok bool, err *storiface.CallError) error //perm:admin retry:true + ReturnDownloadSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true ReturnFetch(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error //perm:admin retry:true // SealingSchedDiag dumps internal sealing scheduler state @@ -558,11 +558,11 @@ type RemoteSectorMeta struct { // Sector urls - lotus will use those for fetching files into local storage // Required in all states - DataUnsealed *SectorData + DataUnsealed *storiface.SectorData // Required in PreCommitting and later - DataSealed *SectorData - DataCache *SectorData + DataSealed *storiface.SectorData + DataCache *storiface.SectorData //////// // SEALING SERVICE HOOKS @@ -570,20 +570,3 @@ type RemoteSectorMeta struct { // todo Commit1Provider // todo OnDone / OnStateChange } - -type SectorData struct { - // Local when set to true indicates to lotus that sector data is already - // available locally; When set lotus will skip fetching sector data, and - // only check that sector data exists in sector storage - Local bool - - // URL to the sector data - // For sealed/unsealed sector, lotus expects octet-stream - // For cache, lotus expects a tar archive with cache files (todo maybe use not-tar; specify what files with what paths must be present) - // Valid schemas: - // - http:// / https:// - URL string - - // optional http headers to use when requesting sector data - Headers http.Header -} diff --git a/api/api_worker.go b/api/api_worker.go index 609cb427183..4b56d11547e 100644 --- a/api/api_worker.go +++ b/api/api_worker.go @@ -49,6 +49,7 @@ type Worker interface { MoveStorage(ctx context.Context, sector storiface.SectorRef, types storiface.SectorFileType) (storiface.CallID, error) //perm:admin UnsealPiece(context.Context, storiface.SectorRef, storiface.UnpaddedByteIndex, abi.UnpaddedPieceSize, abi.SealRandomness, cid.Cid) (storiface.CallID, error) //perm:admin Fetch(context.Context, storiface.SectorRef, storiface.SectorFileType, storiface.PathType, storiface.AcquireMode) (storiface.CallID, error) //perm:admin + DownloadSectorData(ctx context.Context, sector storiface.SectorRef, finalized bool, src map[storiface.SectorFileType]storiface.SectorData) (storiface.CallID, error) //perm:admin GenerateWinningPoSt(ctx context.Context, ppt abi.RegisteredPoStProof, mid abi.ActorID, sectors []storiface.PostSectorChallenge, randomness abi.PoStRandomness) ([]proof.PoStProof, error) //perm:admin GenerateWindowPoSt(ctx context.Context, ppt abi.RegisteredPoStProof, mid abi.ActorID, sectors []storiface.PostSectorChallenge, partitionIdx int, randomness abi.PoStRandomness) (storiface.WindowPoStResult, error) //perm:admin diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 47192bfd991..e078cbe0fc9 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -344,6 +344,14 @@ func init() { addExample(http.Header{ "Authorization": []string{"Bearer ey.."}, }) + + addExample(map[storiface.SectorFileType]storiface.SectorData{ + storiface.FTSealed: { + Local: false, + URL: "https://example.com/sealingservice/sectors/s-f0123-12345", + Headers: nil, + }, + }) } func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 21fdcc7e549..13de24938e4 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -776,6 +776,8 @@ type StorageMinerStruct struct { ReturnDataCid func(p0 context.Context, p1 storiface.CallID, p2 abi.PieceInfo, p3 *storiface.CallError) error `perm:"admin"` + ReturnDownloadSector func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` + ReturnFetch func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` ReturnFinalizeReplicaUpdate func(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error `perm:"admin"` @@ -951,6 +953,8 @@ type WorkerStruct struct { DataCid func(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 storiface.Data) (storiface.CallID, error) `perm:"admin"` + DownloadSectorData func(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorData) (storiface.CallID, error) `perm:"admin"` + Enabled func(p0 context.Context) (bool, error) `perm:"admin"` Fetch func(p0 context.Context, p1 storiface.SectorRef, p2 storiface.SectorFileType, p3 storiface.PathType, p4 storiface.AcquireMode) (storiface.CallID, error) `perm:"admin"` @@ -4654,6 +4658,17 @@ func (s *StorageMinerStub) ReturnDataCid(p0 context.Context, p1 storiface.CallID return ErrNotSupported } +func (s *StorageMinerStruct) ReturnDownloadSector(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error { + if s.Internal.ReturnDownloadSector == nil { + return ErrNotSupported + } + return s.Internal.ReturnDownloadSector(p0, p1, p2) +} + +func (s *StorageMinerStub) ReturnDownloadSector(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error { + return ErrNotSupported +} + func (s *StorageMinerStruct) ReturnFetch(p0 context.Context, p1 storiface.CallID, p2 *storiface.CallError) error { if s.Internal.ReturnFetch == nil { return ErrNotSupported @@ -5523,6 +5538,17 @@ func (s *WorkerStub) DataCid(p0 context.Context, p1 abi.UnpaddedPieceSize, p2 st return *new(storiface.CallID), ErrNotSupported } +func (s *WorkerStruct) DownloadSectorData(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorData) (storiface.CallID, error) { + if s.Internal.DownloadSectorData == nil { + return *new(storiface.CallID), ErrNotSupported + } + return s.Internal.DownloadSectorData(p0, p1, p2, p3) +} + +func (s *WorkerStub) DownloadSectorData(p0 context.Context, p1 storiface.SectorRef, p2 bool, p3 map[storiface.SectorFileType]storiface.SectorData) (storiface.CallID, error) { + return *new(storiface.CallID), ErrNotSupported +} + func (s *WorkerStruct) Enabled(p0 context.Context) (bool, error) { if s.Internal.Enabled == nil { return false, ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 0bf4574e23f3787455bbfbd2f1b9bd81eb109c52..942fb190afe07f2f1df19e969c1a4b3db8e725ac 100644 GIT binary patch delta 20947 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 Q0RRC1|Ez&%n2?1902X@30{{R3 delta 20996 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�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 diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 7ca6673b5f7f7679037eabab7c9a315c48033f03..b3db3736c003becfd4c77c46a95bd6af4b99ca32 100644 GIT binary patch delta 4841 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 P00960uK*a(Bk}+MfB}Ia delta 4840 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 O0RR8q31I~z@&EuK-hm+i diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 4912f83066e10949969be4d4b166088da92f0aa2..2f9273ea76d6742fd51aa1b7520002c8fb22b20e 100644 GIT binary patch delta 14867 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 F0|2U=zT5x+ delta 14848 zcmV+bI{(Fod*6DHKL-ht;6=9LaFIpi0cDda0gZnr$+M1z9>tWMTDr@SiI3qUrmM{y zIB0EA1WZisw2roMOzlWpQEIzKZ{IF?ldf*9-!43QJFp##;q}&JwEK2$TJyJS=u+go zg*JX`JJ#d&KTAZqOY8qTAI@fD?dhqLPqil&S>R=D+7)2r6dY@!O249Y4i(4RRi@zp z@11{8a{e4A-xgExH|@efC)Rq6DVtu$GUKG3^XeKoYfKD)8Up?Fs-)+r*PG->&nv|LjlZJmqBDdc zk((W0_d!xqgEw%FyWw|*!Zd7}XAi_+mKUY5aWK4V%hF)d?f(92f2j!*o6__clCLv{ z;G3#svz{X-1?D&Y7+@Db5HyJldpH`7XNSY-a5B9O2j{i?zL~Rsn8TcZV!ARM`0y+a znvm!nn zt(v&$J)flU=pu!8_`E>2a6%>&oEeBvyucDUbAs7&*bZ_Lp=?E5WG)Uwn>i*+!4zzX z#nK}K-~d_|oKYsC7M8O{2AFRF1b>LFb_YOkVi`yWZyr`yUja-E%tp*tePdFrv$qE} z)bEfH^up%uC%^~+f={f~3c9O*Zd~+z)84Z6hKucB{uSy74j)`&HQ5f~a6;!p_YSS? z|5}fK+ncSmw*Na{FVJ=|94+v0vz=@=~y^?Wo`D^*Y`tw4)i{R9V*Inxi~@y1niA+nz54`=0nFRdiC~0}mg`gnRoZ z@Ap%PZE@Qt$#yId#EnC}%_2sXWb_aaGIq3UN-f7TVFYqeZP0?P%sd_!VunBeF5g4sVZ)MukFEdpUx- ziU}OUyret{XQA4s70mBOt>?57OEaUI1M1zwKmV!4R;-GePATPGY!KptWrub~zt?ZT z&=|=EkPw5r8^omQe+Xn|iA1R82rmVXLR@BrA26B4|9ZEj?5*~H#O(e1>fK5w|5~B{ z`R6~i>f$BRi;8%OqVY{zBLj2H=a@ie`=02Q!6X8cmoA!&B8QxLd$X!+v8VRQq@Qb_ z{E3NSJ+OJNW2A&ovMiMiCUi35HVKlNQ~>k5UR)4SxrRr6KUJ)d*wCM4ODCpsXJTnI*vSqqvFfUFrwMbXlLRxjhwh3xWHh`xTn;zH zLB`j^#UmLl|2rNIjiEIf(!a^T9$@?Napm0Wt9vA*+VdO(7160guor%yG~1^L8YU)4 zI~uXQD0C>{M*JfCAJiQ7_q$qyU8@abLO57<;;BwmoBv&^zoz; zYlol9@!x15u42_Ao?m_%+XN=7Cz5aq3u ztU~UD)8=pqCkT#Q1ph|*ntnaR@NPIX+=aWslffaJe;wh`WHL4uo3GCB?}a;>uc0w9 z9)}n&jlZ>ycD2!UJ%O>~l4FWbsI*%*u2!qIkU$-~mya#YMZbyJ{0dx=#J&i67 zUi0k$Mdp8&VG8dpY}}Bu-vQJqzQ=USkw-Kzyllt1$7IOa#4`9(?SAjf)l=lZWd< zXAL&CFc@{HuMmhYJ0l z5XOJ(Ttl4oQUfd;fz})k$5B*a;wXO_ zX;;}Ak_|M?t?*YF-dEz6Ftcng?!V=u@0yP$8OaEz2%7GRMOTz9rh{A=+t12vmHD$WDI*t^{fmWGex?6S|e7-xBWg5bi81yeGXz4GY^8 z%*Kdz=b~1IdP}g+La>8gR-j6Bg+7yeu|PaYw1XrA|X&n$}QvvW8{rWk+A6@^YB3H3cO;txD3x^S?LE|BBB)Or!z3DAmX+Aw0Wg&!%qLS?C zEpXXRs@KAb5T{}?sz;QiQIrr|Sr}2GQ%V7r(tp`rbfe5E($~%7<*+1&gSD?;VCaXV)KNw> zRboY?;XoCrl)--~EQF&CfAnZ8Va`XxaYm?zh$K9LL`UW+r108-#9c_p zPDRXQ0n3s#2BeUBZMuHrvr`^dZX@J$`QO8$EoWA@b)|n&&Txvap3X!{=Z_du@$#|$ z_=B?XUJZ!g`PnJwE{m>^!)K*2sgyDOJG;wfxRa}FJVH?m0Phb@hre3ZpC7+Ie*N{| z|96jm`Cn>(oE*E(=YPG^|9t%A-G{5eFYbHmHPlJ|D}t{f#Q35dGik^`z9ID zFkTdOggIVMFxQ*24v=Gd2Dca7yLZj#0Su?xFSm`tnWt zO;Bf|`%_8AR`62XUSnKi{$;P%>mTrcu6w;B{?EU)j^;&;=QldHmI8}&Ynkpx0mReo z)9uq!M~kvcDs7ChBU_J_H(K6kc_YaiC9k-bshMhb&c!&U%zb;OYWXA)%9DT8dyVi{ zcFosl)>VRuN+2BJs&a`?G44qx`9yh1_BLQ3$?zjQBrk^RaYLEQ&4Z6BQA3n*%BDlb zSW+?`!AsQ;<30J~d z_z}@#_pXNHRREAD7ys;C$0zPX>R#a`2?7R>-MeBps{r1hS2e(PCn?1R<4wB?3)`!B z4OvTG!UF5atG3|>XGWiW!X#BPcuAm`xo_Gv=c7SKQAzOVId*?zF)?+*j8d?&FHa5| zc^;2q3nm4<;8N367p2N=Wshh_^|mAkOYgdrwNgrVYEQ*~pi}Y6wLaU!gZA*CJv?}} z!-H2_%5yZz$aRb;*2+1K2^ckNb0?tfq(XNZCx@TILJU-Vkl&{Y>kG7 zj0W+%WJo|KnA#I;G&iHihVfxT43`5X8`JD)7n`|>-Bsj?ANx?z`4TKh#gnELAT5~R zDrJ3jv=7h?&og~u%5+NcS-V6oa_*Ug<_ms_7Fr|=#O1@>u{I1;~wj0FnV1t-2aZ0X9#BM43t*5!mxLg9oyJOmkD{!SRJPV^7 zT5+pIDMCE1RGZ&nM?41VPWqS;vgg@8KY)M3V3J$yiEV-#xUC@zSeCmW87$~aS@sbp zIW@KSm&8YylrUi{=BNf;lhlwzg3o!=x5%7RQ8X(QGPd%eeH7x;9Xk%hGzFOQG|Z0{A{j0$zbe$P7E?~8wh zi>U7hI!9zlSK`;xZR9w(*YWcDYekP(6q;Au5@svo?GHrdMn8=t%TM5?cg5-A94(=~ zy>KjQ>6W+kuD|;$sZKoA1#+-uaICXWUSe&vqe(CLU&#ctTAF|PJ3Vx0 zo#L%ieD9s&N>*fC3Mfs!M96&8MAchSj~g9Oyhb^u=PSwIoaGh*3FfI8yCn^+-1RJ( zV4BI>l;gJ(6Xi$C#vAuCt}qree~Dbigbm$$Ac6KQ7avIaZH6%A15&;EK!z5i6s>LQ z0%`$Ayl?M8XzxL2??HGLVc37qt*dg0sI&ESQRR!KukX88%YO{V1pfwVmN4E5aaK55UmP1AB~5(#kZ~+tIu~;Sf7t86(9M|l*T?4S|4mSEkwTz)i{i-Zu<0!Z3M zNend}6vKttxux@5N&lul(+^-|_E0R>x6^oVPU%b4ss|Dz$69|aG^J$fRQ2G8$T~C; z8v4pk*~gQNx*>rW4nvA->7W2iIV}`?rlg00*3D|7DDJH;`jK@}HZx?kQrczjVW!SA zMk%)W1FtrSYkZiIWh!LrIdq;LPPcza-LW&lD)nsGwS0hX;{@Ni62e`Hj z+%oXKGw`IB5l($!B4de!{Zoy3BLL)#3+K4&8(6u#8-bL=w^4BAST~NToNces+6K_Z zjOGAEF2!V7DvVUd%u$r32iuXCDmwvgoCcv^o+qdlxyRcIcomy&s92JEDt z5gmTXsq5Gf!3dQYCk`UZFT%EzcmZ|PJ%Og_1%UHdh|o1+55dpzcJBp~Wu9=y`>uPm zof=7T0C+>*lH}|t^3PR}HJ!mpqBMclI~4yvko?R4zgCj%#HKLVC@Tb}6!YgAKAs7H z{Ygh#V-kP)mE4+MRmm9Nt*oej2VGu}S&Ug!2_%x`+Pts6T>L|2*SD&By@6Rz2hGU@ zlIr=4WguQ5CZl*u*`p2)PU*JW%n~APWJV1gI><;W5NhKTQYhQzsH;#9!b@mSuj^(M zXgH2y{TU+rr{&xsM?h#S->KEBtzK>QYO7aUy}EzLdUcqQrz3R12Sjpk!@lfihH%{$Zi?D zXOQKxZX1&A86#?CeJkr*S>MX~eUkO#j7+4sB&%`cDg*R<(mn5hwyIbU#?Z?1R-U)= zyp@0F`y|gN8CiNlgndK=IgolH>{qn?;8<&3JGHuK&xE;qDWBPOGXg(vWUcIPWq&LC zTiL%)vi~q6KTb%qPu4y1q<9T!AAz!a`5x)48HpapzLnvv3~yz4E5r9mhEFq+(1iTD zaIE{dTRAOo)MdE@S}Bms5!r8A$jW*boMjNymt<`9I zt6ihGQW|bXI@yT{NV`AbNp#qh zQb~@YJ?UxH%3i3IR;ITy-IM9V+)VSPvMZ`*Rb=ejf8WqLyNAY;EwYj<+Fe8|?q6Ko zXY-IEwfu%2u7pw7SiRlf&_iG;zD$2Mdu&kU(%BQpKTEmVc8}KTa|L}q%FS?R1bsLQ>tYiaQa7R~7J_^?_H-fHkY)ZiiKw5L|B7JIE)Y@D0>9}4O^F&Ysl z6}4E+aEu57O)IcA{GwH0d#b?Nh>KQty=vVx$*pB@#c#Sr&1}L#K$SHZYHEKg7J_O{ znZ?G}>a$j#?WI0L?VhaFYp-9g9p=__h>7dE+p-W)MZG5E(Frzc z+f$_$@{b~&G<}xGX8#4x2CE(nwx@!v?%qe;J3WW8eo=nA_46PH4wqi*dBE)zpeEn51$ zO3j5&m@rNg=Cl77lbK=7txwRoL)1-HV|Ymq)P8c@w3ksaz?<9Sx#fS*O3W4oplU1S zm_$)T^m8IhCd%o2N}8A9#3APH7~RA_XfGOO}WvNvLwB zCD<%uh)Yma<64e^v02;9z81g&US$+xY)s?;mqOYc%RWzLy^KF1OO(PY{!YOV$~IjD zO4U3Pd&+2|j9f)w5OI_Bv%PenQO%8+29w2XaE`rBh2+gukx74`^%bN9%{)d+A)rG7 z=IlSFi40&7;PN(+eJ|hcB49g~j$9X53ou8F8#e-i0jLEa-)>;q7)vH+HJbyfsKW@? z%x)#xu~m19TsY3iF!Bh^5S4VUtz)vS!-i2fd3^Yp*w8SLXnlphqC_abDWs4G0q_Q= z2%2YPVf_T&h<<;5Uo2ci^L1qkpBztC6ly6qmVDU7@d3w%0c?H_!g!JZ%SJv!cfr{L z5G!Es2TWH05o@zt0oR5);=Im2=-d#5=?XcFW6*>51$e-w$t8t@7!`Ja7*&527mA1N-pwbqwSD~);~0x5 zdSWg%a}&F(6KrTlOuBV64&YQf8jpqp@rz+V!L*Lt$zG7hey?#e~PmK5jPkdcC zSVtGg@m_ywy$JLZ%QPWH4#R}M5QromKZ$v|@{C;`f>7B1Q%Cz1Av=sY;6zZ)m*uaO zieD(Xl4TB$yxA}KDB(`}JYI5!7pivC7S;)F~yQwdTnM=<54M22ddh0}k->%=7N^Mn=2?A)kflTsXsmt{Qo zvySF{$E9~k`Q?AAv{r%NTzQ>d$;Nq-kxuD_`SEDf59Y?LcKLk@iu~yK%PsfmM6#IQ zL8`AVQSK>n3V4p~o!vtPOFTZFyuEc4IlNvY14D|;EpQPrm{}>_gS7~Y5LUQvB*W#> zK}#n_FJNIgUeoRkx%3XEnMDQgBK#P-`ebKBRen3$`^ zJ&goC(oh)s;;sP^7o7}=SWADrRuW|y5eJn;&u)+AUoR_9GZK=-dVWOo{iBU^%49b* zPd5(qD5fe?XF!y*H^pnz^_vuPcLwYnK96-!fz7i=lgIE`crFnYQFO?A3mAUfrh&dU zky`vzuQpT1MxI*FN5OwI#XteT-EvJ7 z?*di{F$(yDvxPWk0|Y&o+XK%*?s3Ttd4QO@oO9NegMfjc>4G_0updl^Qs_|EKOb+I zX|I`S*2@Um79{csI(Hu|r~aXJ9FXd1O{AnfKsAi1wWO zd^GE4Mt=+HrTWU-_;7zGzI$!`ZX@FF)a&qaE@Y{;EM(tYkWKM(5#F^KyQRzX(QKF* zCG1JHW7ow?f}Br?pDS0T!vrL`m6m8!Y^NnY$T8ItEh`vn=@I1FYe~#}Z-%#f5i%S= zuL)Qq3JpjhH~}LW`6%R@{1?Bp9Wk*7@QD)Gx#|s}ERL3IqAY^AZ zIhZU96_*F483h%hR1_`gcWXG7?S>8v!RLH0)L1l==i^t(8;BisM2x%O2IbbaQ>6ZJ zZY1$Whd1`eF8ms78u0MyJL8s51?l}jBKe7s%`o`A5Qj8dFsv-o-J%DI|nX(Tzv*ra7w%{=|Q#2^J9ZAOlFYz~WKBkv3oj zU7%a0i4E>=6i{5i0Kzruf-6M9!g53aGNVEEU+W$@4mJ>Q;R4Yu&{s&mbGtX>4`^Zo z=qu%46mxx(y zgG^skPR(*7(*o+MA7`2b)l8^q66!9aO(i2xl1Rldr=esj2s`C6stq}9Lr#krd)({g z#>RhLA|2sc{wfbb)`sko56(MoM-&$Nr961eIHf}5c3u@OIZ)M{G72e!$der-#SgW- zI&s&WKBrzTrkB*rYat(f)1qm`O=m89d5S#O`lwB$-nT?*CcCb&euwBE+)g_Z_qO;C z;}GMwzywX%vr~UL*^f*ANAQ8a{Nic|%UXYMT8xFL9nJi5_>C?%19=IPOCgAku>m8y z+m81B(Z*f?sNd!i*(TJ{3ACY(>DDI=@3FxB6hXtp1ZhX3LE_Z~bf^#q>331i4Cd$* zaRCxgg!ecoG@O{yYiwU3${D$lnM#70+e3Fn9Wol;9WI9(;vnPe;o^~umj4|OhsJ-< z8V%{+WMB`l{rI?Y?)BBZD7SotkdYuJ_9(spo_!-oLHj>q_WphKZl#ldt+a%~C$M^iU*xzC2F@`vpM*iQUBU zhOR6JfAxsyi}nsd2RQ(3yIt*;%Rzrg;ngmIpFn+u8i!rFgf^E3W%p&C+^F(dgiNY^ z?vdd)jqm)~A9GBgvwcr=i|<_+U$|&8itO`37_pfzF;S5v$T>R=HmRw8Gd7%&fFX|z zWa;*tD3nq;<5c@P#}{S#*Ed2gH6wVG7@-ifGT%#P`TLk0R@r-ba$0F9$tr)rzBOBI zbWy{!Ehp2KlWEJzwB=-^{RKPa5_3|WzEw#(r!aY*$c%5|cIyV0ZEwnRVPX?mT2$}c z+aKRQszqogHkUFY&e&>}fFIv(mi{oZhgGXR6zuL*n@6_hs-FZ7f+`0;b;|zBHsz&t zS91GaTAu{IzP<5;$FM`?mNS2F73`WpJ+GNcC-_}bB9cqoIw1z%1!oi(7UJ;@6gg{5 zAmthT7CF#Y5R(pgSYdqybVzQ<909{3UNnX1=i2|M%MXI?Fa$hZ`4xP$~i&5oj_I*lbze{Z6cI`T2a@8{}p+Uo~DdCj(*@$H(h)6tQ~-@Micw z8}lN8kcF1JqarzZZ28?(@MyX7eB2x5=5}8-Q+wwszxGZwJ}fA{Q-S%SI4W>lh=98f zwRT#bd@VdV&drqO9=m_=vdzjo83EInH5>)n5L?F4EM&_l0-3kYU;^H+ZMp@P1O9}V zo^mea*FCv6geR5ZbC-UgdqOkCx-6^K$al^8WU$0qa^73SDPxc8Z| zZ2b97EoU3f5{VK~TjkpXZ3jl143xAWJ? z0P`(?;1A@uys&>L1Sgh(bnr$v-!L(-?xlXNHzvh8dwXC*{SFyHFN}46;?6e+KCxCS z=&rhPiNYqma`NMz^7%A3K{+7h`iU(`P|YN^B%$syu|+ZhB{5K(*y4MNLRN26TiVo? zx~x6R&8>CMapgP5gYS!(*sn`l#K;_+BKLZ>dU+1^ah89xEyn1}AIJ`QYx17J9oZrt)@N_THq87)q z?+c3nGHQQ?CNeJ3LV>p#NVTGW5x7lyn~!yb6$bZgHhzy&H9L_@F#x@Y^();cFdA79WU(gfDbH_UTY#WfGWF9tj>3b(toDobhG%rkK@b1~O-w8uHgby8a>rZpZ`vM}^s+c%0l1E*o zqE>Vs%Vslpa&hO`IbzvVroC(;Pl9O5PC&p(lEj2poVV+u1}8TW^|X;ki&=S->NOcWrpPYWVPTDO=`7000fS#VmAfLqCh7~r1mJM?}5Ocqvn z{ZBJ@{UnAUJx55lQSpHJ&aR{WpjU7#&;aYcHm(`xrZ>65rV-Xg4bF*x$-ddbazuZr zZ$E{1!QJuU^UuVFhJlQCTZ+zzfgbr~KyZ$OH-R1A0rtrA?u)7o)|w#K?ErfW{2<7} zQ1K|%%|weQ<{^5E5W|?Ex6>M~k~vmnGGTvY7HsAAj90a_q^C(h-kWH$_-4x=)b1)8 z-63fP6RKI~b4yQJArqJ5?Eeh@3(l0^V)2v)bj{tutg?hy# z$S4Gbt*vM-qRQ+6ShyRC&F%*t;iW+Myql)T-p4s#C)tp$Tt9_~?K~R1zfdwQCHAA* z;bhUDO{en%v>5gdM#dpJm=BSDFoTo9;bJt0V>s1#?P)1L`EJwEprd_)j~)`@_X#9d z(cm6P*y|wNTU*ZEr-*DbUY3pB@KI2&<{d|_%y+>=$(+>T zw8`E^MqH*xf9}hC;~k%*;tL|HuHsJ+lvJkU&^7-e4uqI|QDm*K%ImD79s4(-@?RgW z;=jEcO%49z6MW?V{p|7wWr;QftQ2n)Ek#?{I)=B(2Yf7Q1!(;lP@;bySFL4R9}xpN`OKzJLFPkTj+JTEdZi=c*L+^rUf^$LwAUG zG&GE~zkqag%^iYozTAIi80v-W8sL|IYp@J@6`qYwNAwISqnJSwN570gP{e>)_~2oM zoUlqRHW5!C;prqc(s`@__ni7g!~8qbjSjFJ13AJsYddIx97J@~y&)F@Fs3U}%kP03 zL)`PqfB*lihlPV!7f?q4I>-ayAftOjezPb#0@o|-f;FNm%Lspp^)9eUk>g=Lhpwnz z7TU0H1KYB>YPwl8w!8C-op{&c+^{p`hoj+mb~v04C)1rAC8ar7QLA`$0h?7QSzFoE zeb$w?yg%Naw`#SKcKiEUw!g2;QtD@wun=o-igXh?-d!ejtfd&BVvFhQG+`z22g5v@ zYUCx!7WpeY>BA^;&$u^4NRnz$>E5XI10mrf%*gOPKn%`78C~!v5dsB=N9Zs>Y^as>g z?Ka`{Y!g~Bc|IOYvND>4MEHP-QD01kP>Lgv16w`QpE69JQTZ;G__>i68C<D#TRv za4OkJl_RRy{HVET()i|++%sW+1YG_(u_(utpNJtNJPj*47K`_iL@vNB4Oj{foGnDk zg>9l60yw7pywK&xdcjh40Af2)ev;^Sp4k#@zT)SLorjh`XbdM{zYjz+4mX2|mvz;iWY#jV53`c{1gm~T z^xV?#Di-dI!;lx-NXiJ_RKXbbq2`#vQqWaQ;K&GeQlMLkXrUJNTd5csvLi}2{jqc6QquhZ{;^g6xUj&_Nlp&fl0bcXCfr+52QHk-jiqFOyY(S6g!d)Dyr zOaL5rv^6H-kEGNH=WTCHyhwoqZ^2$_dVaWa=Ywf}j-}KfDj_r3_bOi7xBxBXO<>K` zgl9effj5+AILX*6Pi=vm&mogGnXXNyYoiHYX_crHo8AQ zMY^e=GYT$-E9|0*{>Z&2u92H@auCkABq#q16+x{eqcdHN{AQhmFYaitle=`D&4hi` z_TsRYpUPM}rX?$yMaK9-EUU14c3g{`-@UMzDqQa2|2%9SM7^tG{nL_a^>@Z8exYI4L~Gbg&$gJ2jA4TZmW!+EyAm-bZb2RRk{eumM; z#GH?ZgZ$K^OJsw{~3aG?_PdV7O@NjsKv%2 z-dNy)H+8|~#Yuy8|Jr2t=jVlKMu@o}hJRV}YSHC?;pf@M-kS|Jx}QHM!Zd;}^Gt~l ze8B;DK_8_ySg|qf>?phdW9hMY@i!{g30h2z*$fU2Cez9IVAP+^4yKC*JeV!eqPLj# zCJ3R(C3Quy>b;&9!=@chdei}W7J>K*=D z>uA4NF7>8;Ww}(_NqkP&iNvK=`bIwS!LEYH`;%xCIs5fJMcK=OmI7)}zyEnZ2Nw|Y zH*H}#YskpjfD|22yhgH%vIUc52dVrpkzKQYj7$I_8?Pv&b@UtmUPZwrg);xJSi$jT z${J4ENd*n(kLnpzoD}5(6_@o*b1Lqe#)JA}@>?j0j&`;rmV+*lYi%4oA{Qc0zGJO&V(X7{>PN%(H z;BmVB$;D?^JDQ9-+DHD^7Y%;A_ze2P;h}b$z{R#)$`s`TCWiH3`xoN(Jn{7jtt~cb zgC0i&KE@w>y!iZ?ViSLbVlDc-%>{IzX(AK5YssUJ7oWKTeg|D7>ywc=837=Zt2rEh zG>Tc+TThDJFoE50Fz62k>bVq{c*oHQbO=Rj^QMQVI+-Sis2}M;bb%# zjK;m$Xq3P(M(|ByIGG;yXQRUjUmFRA_SH$m5sP1<#CLs|Xr@RRk|j?n&XlXXKug{Ch?2Po2PX1`Wf;NJlk9 zesAAIehq}0*bU??X${O0y%kCS(O@>3O%4aMNesE@1;L}jc0@Sf<_)c zA958X|1PM$mgL_N)vIm+UWDqCN?@<3KB)rsi0UH>z&khTH>&_rk6u~-70i&I1DU zdJQ`pn>r5|^hUjYZ#J5YC+&H_J~6;6IS+U-22ec@cqs;ms09O3sAHq`3$=cs)-Tlh zg<8MR59Sx*SCh!3f4?`Hjt?h)iB-eMscv)=HqW>kaNxOhv5}UNo=OwX8 zO7oY+CMnQg7Mrvve@Sf8E}fUeChfy{Icy@*IZSwH*m3_uSm@K1;e49X4%$tK^{9+UKS0 z^Sz<@qbuIw&*HYuGDT(od7+ zSdBe@M*Nyn1@+0lX=o6wp+2>D3b9Q>s|8vu&}xBJ3$$9`2h#!@;(E8Cx8lEz zCTgRJTH)VD6TRwaqNgXXMzE_Lk&S6~wD$zg&9K0)SEck5_Hgije!@ro^P{~HHA#CN z?S%i$|6~A9tPPu`+~W zuglB`FZ`-9A0NGzLEZ2aqRBenvGTP_S3>#qYfCg%z3(YfGFS1^sYvbHY~pK%E)zVb zxEwJSmk?rtVHGb+Hh@)0RR8w=7H{F1Oot)nW0Po diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index f0d2db3c69241b2c6b7cfd999ad7f49e94f7a063..2a35ab13436378a088b78f9d6a1f6cc745c78365 100644 GIT binary patch literal 5202 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 M|2}5G{{S%o0313bApigX literal 5035 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 Date: Wed, 31 Aug 2022 19:34:08 +0200 Subject: [PATCH 09/26] sector import: Sector data download --- build/openrpc/miner.json.gz | Bin 15751 -> 15794 bytes build/openrpc/worker.json.gz | Bin 5202 -> 5244 bytes storage/paths/fetch.go | 104 ++++++++++++++++++++++++ storage/paths/remote.go | 62 +------------- storage/sealer/ffiwrapper/sealer_cgo.go | 32 +++++++- storage/sealer/tarutil/systar.go | 20 +++-- 6 files changed, 150 insertions(+), 68 deletions(-) create mode 100644 storage/paths/fetch.go diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 2f9273ea76d6742fd51aa1b7520002c8fb22b20e..30cd2019132fbd79c8a551d954c3a5aad52f9bee 100644 GIT binary patch delta 15304 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 Ju{kmd0|4V`bv6J1 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 2a35ab13436378a088b78f9d6a1f6cc745c78365..76d71cb4c69e880e20c466b9fc20202b66dbad68 100644 GIT binary patch delta 5221 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 delta 5174 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 %s", url, outname) + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return xerrors.Errorf("request: %w", err) + } + req.Header = header + req = req.WithContext(ctx) + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return xerrors.Errorf("do request: %w", err) + } + defer resp.Body.Close() // nolint + + if resp.StatusCode != 200 { + return xerrors.Errorf("non-200 code: %d", resp.StatusCode) + } + + start := time.Now() + var bytes int64 + defer func() { + took := time.Now().Sub(start) + mibps := float64(bytes) / 1024 / 1024 * float64(time.Second) / float64(took) + log.Infow("Fetch done", "url", url, "out", outname, "took", took.Round(time.Millisecond), "bytes", bytes, "MiB/s", mibps, "err", rerr) + }() + + mediatype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err != nil { + return xerrors.Errorf("parse media type: %w", err) + } + + if err := os.RemoveAll(outname); err != nil { + return xerrors.Errorf("removing dest: %w", err) + } + + switch mediatype { + case "application/x-tar": + bytes, err = tarutil.ExtractTar(resp.Body, outname, make([]byte, CopyBuf)) + return err + case "application/octet-stream": + f, err := os.Create(outname) + if err != nil { + return err + } + bytes, err = io.CopyBuffer(f, resp.Body, make([]byte, CopyBuf)) + if err != nil { + f.Close() // nolint + return err + } + return f.Close() + default: + return xerrors.Errorf("unknown content type: '%s'", mediatype) + } +} + +// FetchWithTemp fetches data into a temp 'fetching' directory, then moves the file to destination +func FetchWithTemp(ctx context.Context, urls []string, dest string, header http.Header) (string, error) { + var merr error + for _, url := range urls { + tempDest, err := tempFetchDest(dest, true) + if err != nil { + return "", err + } + + if err := os.RemoveAll(dest); err != nil { + return "", xerrors.Errorf("removing dest: %w", err) + } + + err = fetch(ctx, url, tempDest, header) + if err != nil { + merr = multierror.Append(merr, xerrors.Errorf("fetch error %s -> %s: %w", url, tempDest, err)) + continue + } + + if err := move(tempDest, dest); err != nil { + return "", xerrors.Errorf("fetch move error %s -> %s: %w", tempDest, dest, err) + } + + if merr != nil { + log.Warnw("acquireFromRemote encountered errors when fetching sector from remote", "errors", merr) + } + return url, nil + } + + return "", xerrors.Errorf("failed to fetch sector file (tried %v): %w", urls, merr) +} diff --git a/storage/paths/remote.go b/storage/paths/remote.go index 331f2cf7aa7..06d1080b3af 100644 --- a/storage/paths/remote.go +++ b/storage/paths/remote.go @@ -7,7 +7,6 @@ import ( "io" "io/ioutil" "math/bits" - "mime" "net/http" "net/url" "os" @@ -24,7 +23,6 @@ import ( "github.com/filecoin-project/lotus/storage/sealer/fsutil" "github.com/filecoin-project/lotus/storage/sealer/storiface" - "github.com/filecoin-project/lotus/storage/sealer/tarutil" ) var FetchTempSubdir = "fetching" @@ -236,7 +234,7 @@ func (r *Remote) acquireFromRemote(ctx context.Context, s abi.SectorID, fileType return "", xerrors.Errorf("removing dest: %w", err) } - err = r.fetch(ctx, url, tempDest) + err = r.fetchThrottled(ctx, url, tempDest) if err != nil { merr = multierror.Append(merr, xerrors.Errorf("fetch error %s (storage %s) -> %s: %w", url, info.ID, tempDest, err)) continue @@ -256,9 +254,7 @@ func (r *Remote) acquireFromRemote(ctx context.Context, s abi.SectorID, fileType return "", xerrors.Errorf("failed to acquire sector %v from remote (tried %v): %w", s, si, merr) } -func (r *Remote) fetch(ctx context.Context, url, outname string) error { - log.Infof("Fetch %s -> %s", url, outname) - +func (r *Remote) fetchThrottled(ctx context.Context, url, outname string) (rerr error) { if len(r.limit) >= cap(r.limit) { log.Infof("Throttling fetch, %d already running", len(r.limit)) } @@ -274,59 +270,7 @@ func (r *Remote) fetch(ctx context.Context, url, outname string) error { return xerrors.Errorf("context error while waiting for fetch limiter: %w", ctx.Err()) } - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return xerrors.Errorf("request: %w", err) - } - req.Header = r.auth - req = req.WithContext(ctx) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return xerrors.Errorf("do request: %w", err) - } - defer resp.Body.Close() // nolint - - if resp.StatusCode != 200 { - return xerrors.Errorf("non-200 code: %d", resp.StatusCode) - } - - /*bar := pb.New64(w.sizeForType(typ)) - bar.ShowPercent = true - bar.ShowSpeed = true - bar.Units = pb.U_BYTES - - barreader := bar.NewProxyReader(resp.Body) - - bar.Start() - defer bar.Finish()*/ - - mediatype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) - if err != nil { - return xerrors.Errorf("parse media type: %w", err) - } - - if err := os.RemoveAll(outname); err != nil { - return xerrors.Errorf("removing dest: %w", err) - } - - switch mediatype { - case "application/x-tar": - return tarutil.ExtractTar(resp.Body, outname, make([]byte, CopyBuf)) - case "application/octet-stream": - f, err := os.Create(outname) - if err != nil { - return err - } - _, err = io.CopyBuffer(f, resp.Body, make([]byte, CopyBuf)) - if err != nil { - f.Close() // nolint - return err - } - return f.Close() - default: - return xerrors.Errorf("unknown content type: '%s'", mediatype) - } + return fetch(ctx, url, outname, r.auth) } func (r *Remote) checkAllocated(ctx context.Context, url string, spt abi.RegisteredSealProof, offset, size abi.PaddedPieceSize) (bool, error) { diff --git a/storage/sealer/ffiwrapper/sealer_cgo.go b/storage/sealer/ffiwrapper/sealer_cgo.go index c1d55771392..0ed53183c05 100644 --- a/storage/sealer/ffiwrapper/sealer_cgo.go +++ b/storage/sealer/ffiwrapper/sealer_cgo.go @@ -28,6 +28,7 @@ import ( "github.com/filecoin-project/go-state-types/proof" "github.com/filecoin-project/lotus/lib/nullreader" + spaths "github.com/filecoin-project/lotus/storage/paths" nr "github.com/filecoin-project/lotus/storage/pipeline/lib/nullreader" "github.com/filecoin-project/lotus/storage/sealer/fr32" "github.com/filecoin-project/lotus/storage/sealer/partialfile" @@ -1128,7 +1129,36 @@ func (sb *Sealer) Remove(ctx context.Context, sector storiface.SectorRef) error } func (sb *Sealer) DownloadSectorData(ctx context.Context, sector storiface.SectorRef, finalized bool, src map[storiface.SectorFileType]storiface.SectorData) error { - panic("todo") + var todo storiface.SectorFileType + for fileType := range src { + todo |= fileType + } + + ptype := storiface.PathSealing + if finalized { + ptype = storiface.PathStorage + } + + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTNone, todo, ptype) + if err != nil { + return xerrors.Errorf("failed to acquire sector paths: %w", err) + } + defer done() + + for fileType, data := range src { + out := storiface.PathByType(paths, fileType) + + if data.Local { + return xerrors.Errorf("sector(%v) with local data (%#v) requested in DownloadSectorData", sector, data) + } + + _, err := spaths.FetchWithTemp(ctx, []string{data.URL}, out, data.Headers) + if err != nil { + return xerrors.Errorf("downloading sector data: %w", err) + } + } + + return nil } func GetRequiredPadding(oldLength abi.PaddedPieceSize, newPieceLength abi.PaddedPieceSize) ([]abi.PaddedPieceSize, abi.PaddedPieceSize) { diff --git a/storage/sealer/tarutil/systar.go b/storage/sealer/tarutil/systar.go index 2d7bc34a503..09ffa5e97ca 100644 --- a/storage/sealer/tarutil/systar.go +++ b/storage/sealer/tarutil/systar.go @@ -13,19 +13,20 @@ import ( var log = logging.Logger("tarutil") // nolint -func ExtractTar(body io.Reader, dir string, buf []byte) error { +func ExtractTar(body io.Reader, dir string, buf []byte) (int64, error) { if err := os.MkdirAll(dir, 0755); err != nil { // nolint - return xerrors.Errorf("mkdir: %w", err) + return 0, xerrors.Errorf("mkdir: %w", err) } tr := tar.NewReader(body) + var read int64 for { header, err := tr.Next() switch err { default: - return err + return read, err case io.EOF: - return nil + return read, nil case nil: } @@ -34,17 +35,20 @@ func ExtractTar(body io.Reader, dir string, buf []byte) error { f, err := os.Create(filepath.Join(dir, header.Name)) if err != nil { //nolint:gosec - return xerrors.Errorf("creating file %s: %w", filepath.Join(dir, header.Name), err) + return read, xerrors.Errorf("creating file %s: %w", filepath.Join(dir, header.Name), err) } // This data is coming from a trusted source, no need to check the size. + // TODO: now it's actually not coming from a trusted source, check size / paths //nolint:gosec - if _, err := io.CopyBuffer(f, tr, buf); err != nil { - return err + r, err := io.CopyBuffer(f, tr, buf) + read += r + if err != nil { + return read, err } if err := f.Close(); err != nil { - return err + return read, err } } } From 96780901c522bb2e24c3780188f2a1c5b64d512d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 2 Sep 2022 14:19:29 +0200 Subject: [PATCH 10/26] sector import: Fix tests --- storage/sealer/mock/mock.go | 8 ++++++++ storage/sealer/sched_test.go | 4 ++++ storage/sealer/teststorage_test.go | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/storage/sealer/mock/mock.go b/storage/sealer/mock/mock.go index 5b0afd35c81..173a4ddf259 100644 --- a/storage/sealer/mock/mock.go +++ b/storage/sealer/mock/mock.go @@ -517,6 +517,10 @@ func (mgr *SectorMgr) ReleaseSectorKey(ctx context.Context, sector storiface.Sec return nil } +func (mgr *SectorMgr) DownloadSectorData(ctx context.Context, sector storiface.SectorRef, finalized bool, src map[storiface.SectorFileType]storiface.SectorData) error { + return xerrors.Errorf("not supported") +} + func (mgr *SectorMgr) Remove(ctx context.Context, sector storiface.SectorRef) error { mgr.lk.Lock() defer mgr.lk.Unlock() @@ -613,6 +617,10 @@ func (mgr *SectorMgr) ReturnFinalizeReplicaUpdate(ctx context.Context, callID st panic("not supported") } +func (mgr *SectorMgr) ReturnDownloadSector(ctx context.Context, callID storiface.CallID, err *storiface.CallError) error { + panic("not supported") +} + func (m mockVerifProver) VerifySeal(svi prooftypes.SealVerifyInfo) (bool, error) { plen, err := svi.SealProof.ProofSize() if err != nil { diff --git a/storage/sealer/sched_test.go b/storage/sealer/sched_test.go index a30a4d26162..bf4b90b1958 100644 --- a/storage/sealer/sched_test.go +++ b/storage/sealer/sched_test.go @@ -67,6 +67,10 @@ type schedTestWorker struct { ignoreResources bool } +func (s *schedTestWorker) DownloadSectorData(ctx context.Context, sector storiface.SectorRef, finalized bool, src map[storiface.SectorFileType]storiface.SectorData) (storiface.CallID, error) { + panic("implement me") +} + func (s *schedTestWorker) DataCid(ctx context.Context, pieceSize abi.UnpaddedPieceSize, pieceData storiface.Data) (storiface.CallID, error) { panic("implement me") } diff --git a/storage/sealer/teststorage_test.go b/storage/sealer/teststorage_test.go index f88aa93556e..ee200d9bb7f 100644 --- a/storage/sealer/teststorage_test.go +++ b/storage/sealer/teststorage_test.go @@ -21,6 +21,10 @@ type testExec struct { apch chan chan apres } +func (t *testExec) DownloadSectorData(ctx context.Context, sector storiface.SectorRef, finalized bool, src map[storiface.SectorFileType]storiface.SectorData) error { + panic("implement me") +} + func (t *testExec) DataCid(ctx context.Context, pieceSize abi.UnpaddedPieceSize, pieceData storiface.Data) (abi.PieceInfo, error) { panic("implement me") } From e5a87e42e11f6570f0012964c8b7c4c9ecd86ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 2 Sep 2022 15:47:35 +0200 Subject: [PATCH 11/26] sector import: Implement handleReceiveSector --- storage/pipeline/receive.go | 49 ++++++++++++++++++++++++++++++++++--- storage/pipeline/types.go | 6 +++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index b21829772c5..a9e56a84514 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -11,6 +11,7 @@ import ( "github.com/filecoin-project/go-statemachine" "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/storage/sealer/storiface" ) func (m *Sealing) Receive(ctx context.Context, meta api.RemoteSectorMeta) error { @@ -102,6 +103,19 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta info.CommD = meta.CommD // todo check cid prefixes info.CommR = meta.CommR + if meta.DataSealed == nil { + return SectorInfo{}, xerrors.Errorf("expected DataSealed to be set") + } + if meta.DataCache == nil { + return SectorInfo{}, xerrors.Errorf("expected DataCache to be set") + } + info.RemoteDataSealed = meta.DataSealed + info.RemoteDataCache = meta.DataCache + + // If we get a sector after PC2, assume that we're getting finalized sector data + // todo: maybe only set if C1 provider is set? + info.RemoteDataFinalized = true + fallthrough case GetTicket: fallthrough @@ -118,6 +132,11 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta return SectorInfo{}, xerrors.Errorf("checking pieces: %w", err) } + if meta.DataUnsealed == nil { + return SectorInfo{}, xerrors.Errorf("expected DataUnsealed to be set") + } + info.RemoteDataUnsealed = meta.DataUnsealed + return info, nil default: return SectorInfo{}, xerrors.Errorf("imported sector State in not supported") @@ -125,8 +144,32 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta } func (m *Sealing) handleReceiveSector(ctx statemachine.Context, sector SectorInfo) error { - // todo fetch stuff - // m.sealer.DownloadSectorData(ctx, m.minerSector(sector.SectorType, sector.SectorNumber), ) - panic("todo") + toFetch := map[storiface.SectorFileType]storiface.SectorData{} + + for fileType, data := range map[storiface.SectorFileType]*storiface.SectorData{ + storiface.FTUnsealed: sector.RemoteDataUnsealed, + storiface.FTSealed: sector.RemoteDataSealed, + storiface.FTCache: sector.RemoteDataCache, + } { + if data == nil { + continue + } + + if data.Local { + // todo check exists + continue + } + + toFetch[fileType] = *data + } + + if len(toFetch) > 0 { + if err := m.sealer.DownloadSectorData(ctx.Context(), m.minerSector(sector.SectorType, sector.SectorNumber), sector.RemoteDataFinalized, toFetch); err != nil { + return xerrors.Errorf("downloading sector data: %w", err) // todo send err event + } + } + + // todo data checks? + return ctx.Send(SectorReceived{}) } diff --git a/storage/pipeline/types.go b/storage/pipeline/types.go index e304a9ff677..24cff829d3d 100644 --- a/storage/pipeline/types.go +++ b/storage/pipeline/types.go @@ -95,6 +95,12 @@ type SectorInfo struct { TerminateMessage *cid.Cid TerminatedAt abi.ChainEpoch + // Remote import + RemoteDataUnsealed *storiface.SectorData + RemoteDataSealed *storiface.SectorData + RemoteDataCache *storiface.SectorData + RemoteDataFinalized bool + // Debug LastErr string From 513abb817307f1e0a20d71c83e8c6315846905f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 2 Sep 2022 17:12:58 +0200 Subject: [PATCH 12/26] sector import: Update type-gen --- build/openrpc/miner.json.gz | Bin 15794 -> 15786 bytes build/openrpc/worker.json.gz | Bin 5244 -> 5256 bytes documentation/en/api-v0-methods-miner.md | 33 +-- gen/main.go | 2 + storage/pipeline/cbor_gen.go | 145 ++++++++++- storage/sealer/ffiwrapper/sealer_cgo.go | 2 +- storage/sealer/storiface/cbor_gen.go | 312 +++++++++++++++++++++++ storage/sealer/storiface/storage.go | 16 +- 8 files changed, 492 insertions(+), 18 deletions(-) diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 30cd2019132fbd79c8a551d954c3a5aad52f9bee..550389d525e47b28a21a1318a66003fef389fe26 100644 GIT binary patch delta 2019 zcmV<92ORjad#Zb|f+>F^#ObeSn{MDwM53=J(b?7Wb#(&u720u6rHgHIxlwip=Si3< zpG63&+UFj@e$%**fc-JY1UlRIM7Q`ZhjEaLCZouXFoY3XhY}MNEJ$R}TH(l`8iD~0gbajJ0U3n)J};I`4z{+wS>%Zlv#hfKc+-fHjbW>sWd;n zDPC=KQLDPGh11r;X=~xMwQ!{U1>5`*b5fnYRY^Ois(PNtjPF2q>%*7r&B}9OVh3DW zRPX$#BEI=m3olRXjAcZeu}>}mKfYHk{b6JSu2wiHa80N-kN6c-KMA}WRZgwy+*u&= zD3sP+N#8?heG-2-D)+{XAHxonTh74Gv1$yd0gT2NFo4($_eBvb zV!g2IV6Pe5n);hg@P=&*$&#r%Y5^GTBrW2F^)7#~}zsE;D%ajNHOE%ZLsOZ zG`87one)eD&S`EQdO(YHvx?$?)7a?V1=a0IJAcDZ)FhMB7 zz0Z^)0dF)7yB+XEZwcgP5OVXXTTcfLXJ ziM3imch!wc6gKIVGdK5?&u6*W)d4Bj&&o-HY9=cu33ZoQIg$}5iGkv*9N$wEvU;1B z)8^&WWbJ-GH!;{f$CWQk556yEV!x0=#!whc&8GKn0z^u3d+P_^^y@_2vkgJYfI z`*^_tNeu$FNPi-{T=``IqNEmkaYiu3(7Z5_!MkVAekTm+5I%Iwtv}5rFFS}}t7783 zNNRVLa$wPUESt^X$;F*#=ZIxfnf9`YJPD#HI{^VFNfHxYao(=aR!aGsZH{l7JG+khgI>Y0Km)A%+PG$to8IIKn?`?F8#Op50w()f z4$BdB%Ka4H1$W1X&p#6z8U`}nZ7Dh<272T-8NoRY-UN1d2iPOeyDzFXSZjh@w*%}k z@Pi-=L&c+5Hxn(Mn1|>UNDO0!-cAe9O6FLR$%OrpS#6fvGhWHrlAb03d2gc0;+rjh zP`j&Wkb6XtL;E{BZ0UdZM!n&5)WDHT`qCvSukLUpgC>SC$~gFn3Kq2+WVrWxf8ssD zA&%Qf@dhKs+w_z3asMzkMbi}c$ zfni)=%dpiMcAAyUDOm8>FhqIRN-P_PQT_VtIGozdnL=ylS3rNX7h}H!ZO^iDAw2@1 z6zUa|Afpfzwzi_Vh$^!OVBu~kHoG5qgqH&0^KP0Vdmra~on%A0a{Uw{w)1H4@0rk0#_cB6*4ga@RLU}g92T~v&=Hy3J8T1Z8s$g0{|E4 B;vfJ3 delta 2027 zcmVI4O&o9N%5v~mkBGi#?+|p51JJhH)o!^QgcM%w68H(!SEzB= zrAugYX;5}w=E;pJpGC-|+UFh_e$)8QpZzh%1UlRIM7Q|fh4F=pCZotcFN6`B`4STq zS%RFi(_oXD>NjJ<83`Ej$Uv5E&xt}Ql`~GYuXB7+rhk1Sz?yj0w8GC4j^L#0mkjXC}T!k($4z33Rw|5eTIsun~bK6M@Z^<=yYZ>Xx6+$GuT*R`XTk zMRPJBW^sJHK1UI|X8>=8|FbbK5(rsnxjQP7lgF0dO$CpZJI}|xac*w+RWr4BuJUW| zRO7>f;yZs8m@kT>0>_02xcg9Rr{&4l!jqHSOlj`13oqNO%##r?jakD{pbfEQ9L++u zj3SVE>kKB~{o1BmU^(DVi0LWkLVn$odqa3q8D1`t6Wj@fpkr=Z!}Z5v!^7N^?O<d-W(~D_rv)eM~kHwtR+*Iy>7V9SF!~w~J-GA1x(LKQmd5Ljo4PAjK zMN^4UvvX`hZ&6{6O@w=&Da*#6@6@tJUKFsb^n4%=>;xOYVWiJ+7A0BC#erxu=hlS> z0~&vZgIpIG00+>x>kV@|e~k<<-vS8!K#t1`i$ZW>8Au0jg!2s(1M6Pu=XzsOth2WV zHq`Hs5%j`X_b2XrgWwZuwSw-d8Eev=WAi%2!D4W- z_MBgC16K+~b-2av=vlZXGOFy2D(9ex6Uc@R#rnpCPT>4$XcrlqL^WOsa>x?glC*#3 zDpG#S`TNQF!`uW<_Yy5?aXkCJum~WdR%jyQ5-k*Xn}Jj-`WJy)g|9u_cT&Vzj%8kH zzIZd0D9y~kcR%i73!O?VlIO%nQtWW;?si=lumH7Jd_ZF&#)mIOZRVmc) zJ@fV`HDN29lVMCX` zcTz>3cAlUeFCTEMQ+yxK*_Wj8vqkz7;pNKDtdEjf?8OO=a54Ch{bRrtAa+oFqw1c*S|U zK3gf}Z?-wUZH{l7)FSsVh}bSHVIrCd#@bX|}VeDW+= zgwjmSf_%tVIONC{MJNGa#{z#1uR) zJnz1!+F-2-a@`KF$G{JQEDRNoV%6 zKC<}-`0c?wi6*Kl1_p+4fi1&UXV__0GN)j{W5W>TT`RF{97ccj8>r)OYBOgFt)1VZ z(B3Wm60|+b%7yd@fKsSeOoEI;P}tgv<|3-h9)N|rq1fzx;1OO5gwMNaitK%y^L3I9 z>B{v}h}h1f!TSp((^6tTsvS-i{n>OnKR}CN?_gvcqJ#Mm=?61785}M~b2x@mjn|%* z@{{j29Su6#C-^bwAt8RBKynog?tz584#G`7I@ZRP0zEcO>*3nUezmpb+QP3ll2;_2DZ1+q==!lV35c0=EW}4KgtSGm}3ug96=Wv&1sq3J7^R Ja#v^y0{}*G`tJY$ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 76d71cb4c69e880e20c466b9fc20202b66dbad68..f60f1fc3a794c45d1ce14f3b5d957fbb2986c5e9 100644 GIT binary patch delta 5252 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

UdF>d!|Y8np4hw3bk(;M$9=Nr*zH}K@FbJ0bR zb3x8uGCA+{_mOknxX(z=>ZfLeeD(Jwt$)m?8;jhGH&85~wah}>z@f7g`6cp7fp`M( zUK`@6Ip;(%w|?QG>MK&a%rz}a9k!hm7pX}wj5R#Ez9cZQB{tj!Ond|DN@Ar&?3)Rq zB8W;oL`BOv_$vmvRc7bA%+)98JIt>(N8ictEX+jA)LUq#W>2Qg6!K0er0xPb1x2k0DatO9xf z1@BHa*3kvO*%Z(@WdC3fc!*L=W`DP20at*+djueuqDSB%!zQK&s12BVhcieK`-4L7 z9x!z`msX9RI7RVet2Xi6`O|Y3lUb1>#ed5=Sf5g2 z<$K=R=F$FYVkt%uI~%*s!`L}APgw#TI6$}awE8`Gw}8&gZkg`< z^Ib4*h07F?LJQU^a!Te~xqpbu--sv8ku%lP`RU56X_mU7<5W5^A%!Onq;r4avfz@u zn!=9TY7A;#=xCr3m&inh1>HleB3?$G)Bhzp=Kem_zU7Fl(rdzjl*rGr?G)>Ra;VVL z#$yN-y`v7)en;0Qz0L%hdS_xP!%2TUQB^~)j24A^E@D~Z*=$tH34eC`1A6zLgT*gS z%Z%jAC1D6!6ngibUrliBVXiGk$~)8o<|stbD|{J zm;_6}6%;(kSet$a#nqwSTfu~OzX|Q`=j?xO#)S6*z-_*QsYYtx8I4{V^l4o*<=B?I zZ@!UVJlDJ<+LD|_?td@^=-e(9MMEICZSLT;?mex@o|P1)FEcyY*cH>#jcJ`et@lhp z3L_L=ckIAukh2XMd^YNbw{lufBxm)=xohG;(?sT{6-DR7L_f9%P;B1#6+`rvF}IL^)M*n~yJmW1H>J6|iXi z+3L5eYGT>Oy)g%tgklTOIdTzzE&?P7*7Sh8B*YK#6j2^rN;OtgX}!K%|9=1g0RR8z KmP3(eF#!MxyG1Sl delta 5240 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 diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 3ca47c43bb2..73f6a2d1a0c 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -3245,29 +3245,32 @@ Inputs: "DataUnsealed": { "Local": true, "URL": "string value", - "Headers": { - "Authorization": [ - "Bearer ey.." - ] - } + "Headers": [ + { + "Key": "string value", + "Value": "string value" + } + ] }, "DataSealed": { "Local": true, "URL": "string value", - "Headers": { - "Authorization": [ - "Bearer ey.." - ] - } + "Headers": [ + { + "Key": "string value", + "Value": "string value" + } + ] }, "DataCache": { "Local": true, "URL": "string value", - "Headers": { - "Authorization": [ - "Bearer ey.." - ] - } + "Headers": [ + { + "Key": "string value", + "Value": "string value" + } + ] } } ] diff --git a/gen/main.go b/gen/main.go index ad331402daf..c77e4f4f41b 100644 --- a/gen/main.go +++ b/gen/main.go @@ -102,6 +102,8 @@ func main() { err = gen.WriteMapEncodersToFile("./storage/sealer/storiface/cbor_gen.go", "storiface", storiface.CallID{}, + storiface.SecDataHttpHeader{}, + storiface.SectorData{}, ) if err != nil { fmt.Println(err) diff --git a/storage/pipeline/cbor_gen.go b/storage/pipeline/cbor_gen.go index ddeb449ba12..ec6c7363497 100644 --- a/storage/pipeline/cbor_gen.go +++ b/storage/pipeline/cbor_gen.go @@ -16,6 +16,7 @@ import ( miner "github.com/filecoin-project/go-state-types/builtin/v8/miner" api "github.com/filecoin-project/lotus/api" + storiface "github.com/filecoin-project/lotus/storage/sealer/storiface" ) var _ = xerrors.Errorf @@ -31,7 +32,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { cw := cbg.NewCborWriter(w) - if _, err := cw.Write([]byte{184, 32}); err != nil { + if _, err := cw.Write([]byte{184, 36}); err != nil { return err } @@ -671,6 +672,70 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { } } + // t.RemoteDataUnsealed (storiface.SectorData) (struct) + if len("RemoteDataUnsealed") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteDataUnsealed\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteDataUnsealed"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteDataUnsealed")); err != nil { + return err + } + + if err := t.RemoteDataUnsealed.MarshalCBOR(cw); err != nil { + return err + } + + // t.RemoteDataSealed (storiface.SectorData) (struct) + if len("RemoteDataSealed") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteDataSealed\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteDataSealed"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteDataSealed")); err != nil { + return err + } + + if err := t.RemoteDataSealed.MarshalCBOR(cw); err != nil { + return err + } + + // t.RemoteDataCache (storiface.SectorData) (struct) + if len("RemoteDataCache") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteDataCache\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteDataCache"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteDataCache")); err != nil { + return err + } + + if err := t.RemoteDataCache.MarshalCBOR(cw); err != nil { + return err + } + + // t.RemoteDataFinalized (bool) (bool) + if len("RemoteDataFinalized") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteDataFinalized\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteDataFinalized"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteDataFinalized")); err != nil { + return err + } + + if err := cbg.WriteBool(w, t.RemoteDataFinalized); err != nil { + return err + } + // t.LastErr (string) (string) if len("LastErr") > cbg.MaxLength { return xerrors.Errorf("Value in field \"LastErr\" was too long") @@ -1391,6 +1456,84 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { t.TerminatedAt = abi.ChainEpoch(extraI) } + // t.RemoteDataUnsealed (storiface.SectorData) (struct) + case "RemoteDataUnsealed": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.RemoteDataUnsealed = new(storiface.SectorData) + if err := t.RemoteDataUnsealed.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.RemoteDataUnsealed pointer: %w", err) + } + } + + } + // t.RemoteDataSealed (storiface.SectorData) (struct) + case "RemoteDataSealed": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.RemoteDataSealed = new(storiface.SectorData) + if err := t.RemoteDataSealed.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.RemoteDataSealed pointer: %w", err) + } + } + + } + // t.RemoteDataCache (storiface.SectorData) (struct) + case "RemoteDataCache": + + { + + b, err := cr.ReadByte() + if err != nil { + return err + } + if b != cbg.CborNull[0] { + if err := cr.UnreadByte(); err != nil { + return err + } + t.RemoteDataCache = new(storiface.SectorData) + if err := t.RemoteDataCache.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.RemoteDataCache pointer: %w", err) + } + } + + } + // t.RemoteDataFinalized (bool) (bool) + case "RemoteDataFinalized": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.RemoteDataFinalized = false + case 21: + t.RemoteDataFinalized = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } // t.LastErr (string) (string) case "LastErr": diff --git a/storage/sealer/ffiwrapper/sealer_cgo.go b/storage/sealer/ffiwrapper/sealer_cgo.go index 0ed53183c05..cc137151f14 100644 --- a/storage/sealer/ffiwrapper/sealer_cgo.go +++ b/storage/sealer/ffiwrapper/sealer_cgo.go @@ -1152,7 +1152,7 @@ func (sb *Sealer) DownloadSectorData(ctx context.Context, sector storiface.Secto return xerrors.Errorf("sector(%v) with local data (%#v) requested in DownloadSectorData", sector, data) } - _, err := spaths.FetchWithTemp(ctx, []string{data.URL}, out, data.Headers) + _, err := spaths.FetchWithTemp(ctx, []string{data.URL}, out, data.HttpHeaders()) if err != nil { return xerrors.Errorf("downloading sector data: %w", err) } diff --git a/storage/sealer/storiface/cbor_gen.go b/storage/sealer/storiface/cbor_gen.go index 5b46231750f..6fec1155715 100644 --- a/storage/sealer/storiface/cbor_gen.go +++ b/storage/sealer/storiface/cbor_gen.go @@ -153,3 +153,315 @@ func (t *CallID) UnmarshalCBOR(r io.Reader) (err error) { return nil } +func (t *SecDataHttpHeader) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{162}); err != nil { + return err + } + + // t.Key (string) (string) + if len("Key") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Key\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("Key"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Key")); err != nil { + return err + } + + if len(t.Key) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Key was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Key))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Key)); err != nil { + return err + } + + // t.Value (string) (string) + if len("Value") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Value\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("Value"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Value")); err != nil { + return err + } + + if len(t.Value) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.Value was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.Value))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.Value)); err != nil { + return err + } + return nil +} + +func (t *SecDataHttpHeader) UnmarshalCBOR(r io.Reader) (err error) { + *t = SecDataHttpHeader{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("SecDataHttpHeader: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Key (string) (string) + case "Key": + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.Key = string(sval) + } + // t.Value (string) (string) + case "Value": + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.Value = string(sval) + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} +func (t *SectorData) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + cw := cbg.NewCborWriter(w) + + if _, err := cw.Write([]byte{163}); err != nil { + return err + } + + // t.Local (bool) (bool) + if len("Local") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Local\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("Local"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Local")); err != nil { + return err + } + + if err := cbg.WriteBool(w, t.Local); err != nil { + return err + } + + // t.URL (string) (string) + if len("URL") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"URL\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("URL"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("URL")); err != nil { + return err + } + + if len(t.URL) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.URL was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.URL))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.URL)); err != nil { + return err + } + + // t.Headers ([]storiface.SecDataHttpHeader) (slice) + if len("Headers") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"Headers\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("Headers"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("Headers")); err != nil { + return err + } + + if len(t.Headers) > cbg.MaxLength { + return xerrors.Errorf("Slice value in field t.Headers was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajArray, uint64(len(t.Headers))); err != nil { + return err + } + for _, v := range t.Headers { + if err := v.MarshalCBOR(cw); err != nil { + return err + } + } + return nil +} + +func (t *SectorData) UnmarshalCBOR(r io.Reader) (err error) { + *t = SectorData{} + + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if maj != cbg.MajMap { + return fmt.Errorf("cbor input should be of type map") + } + + if extra > cbg.MaxLength { + return fmt.Errorf("SectorData: map struct too large (%d)", extra) + } + + var name string + n := extra + + for i := uint64(0); i < n; i++ { + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + name = string(sval) + } + + switch name { + // t.Local (bool) (bool) + case "Local": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.Local = false + case 21: + t.Local = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.URL (string) (string) + case "URL": + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.URL = string(sval) + } + // t.Headers ([]storiface.SecDataHttpHeader) (slice) + case "Headers": + + maj, extra, err = cr.ReadHeader() + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Headers: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + + if extra > 0 { + t.Headers = make([]SecDataHttpHeader, extra) + } + + for i := 0; i < int(extra); i++ { + + var v SecDataHttpHeader + if err := v.UnmarshalCBOR(cr); err != nil { + return err + } + + t.Headers[i] = v + } + + default: + // Field doesn't exist on this type, so ignore it + cbg.ScanForLinks(r, func(cid.Cid) {}) + } + } + + return nil +} diff --git a/storage/sealer/storiface/storage.go b/storage/sealer/storiface/storage.go index 4248cd71ec6..975011a0b98 100644 --- a/storage/sealer/storiface/storage.go +++ b/storage/sealer/storiface/storage.go @@ -137,5 +137,19 @@ type SectorData struct { URL string // optional http headers to use when requesting sector data - Headers http.Header + Headers []SecDataHttpHeader +} + +func (sd *SectorData) HttpHeaders() http.Header { + out := http.Header{} + for _, header := range sd.Headers { + out[header.Key] = append(out[header.Key], header.Value) + } + return out +} + +// note: we can't use http.Header as that's backed by a go map, which is all kinds of messy +type SecDataHttpHeader struct { + Key string + Value string } From 4ba30a75ab22e1c6e9e823508ab08eabdf59e028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Mon, 5 Sep 2022 15:28:36 +0200 Subject: [PATCH 13/26] sector import: Initial SectorReceive itest --- .circleci/config.yml | 5 + api/api_storage.go | 2 +- itests/sector_import_test.go | 230 ++++++++++++++++++++++++++++++++++ storage/paths/http_handler.go | 10 +- storage/pipeline/receive.go | 6 +- 5 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 itests/sector_import_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 53ac6bce0df..5e0b7b1d28b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -969,6 +969,11 @@ workflows: suite: itest-sector_finalize_early target: "./itests/sector_finalize_early_test.go" + - test: + name: test-itest-sector_import + suite: itest-sector_import + target: "./itests/sector_import_test.go" + - test: name: test-itest-sector_make_cc_avail suite: itest-sector_make_cc_avail diff --git a/api/api_storage.go b/api/api_storage.go index b57129b254a..9562c013500 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -537,7 +537,7 @@ type RemoteSectorMeta struct { // Required in SubmitCommit and later PreCommitInfo *miner.SectorPreCommitInfo - PreCommitDeposit big.Int + PreCommitDeposit *big.Int PreCommitMessage *cid.Cid PreCommitTipSet types.TipSetKey diff --git a/itests/sector_import_test.go b/itests/sector_import_test.go new file mode 100644 index 00000000000..848d8f8e660 --- /dev/null +++ b/itests/sector_import_test.go @@ -0,0 +1,230 @@ +package itests + +import ( + "bytes" + "context" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + "time" + + "github.com/gorilla/mux" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" + + "github.com/filecoin-project/lotus/api" + lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/itests/kit" + spaths "github.com/filecoin-project/lotus/storage/paths" + "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" + "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper/basicfs" + "github.com/filecoin-project/lotus/storage/sealer/storiface" + "github.com/filecoin-project/lotus/storage/sealer/tarutil" +) + +func TestSectorImportAfterPC2(t *testing.T) { + kit.QuietMiningLogs() + + var blockTime = 50 * time.Millisecond + + client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx := context.Background() + + // get some sector numbers + snums, err := miner.SectorNumReserveCount(ctx, "test-reservation-0001", 16) + require.NoError(t, err) + + sectorDir := t.TempDir() + + maddr, err := miner.ActorAddress(ctx) + require.NoError(t, err) + + mid, err := address.IDFromAddress(maddr) + require.NoError(t, err) + + spt, err := currentSealProof(ctx, client, maddr) + require.NoError(t, err) + + ssize, err := spt.SectorSize() + require.NoError(t, err) + + pieceSize := abi.PaddedPieceSize(ssize) + + //////// + // seal a sector up to pc2 outside of the pipeline + + sn, err := snums.First() + require.NoError(t, err) + snum := abi.SectorNumber(sn) + sid := abi.SectorID{ + Miner: abi.ActorID(mid), + Number: snum, + } + + sref := storiface.SectorRef{ + ID: sid, + ProofType: 0, + } + + sealer, err := ffiwrapper.New(&basicfs.Provider{ + Root: sectorDir, + }) + require.NoError(t, err) + + dataReader := bytes.NewReader(bytes.Repeat([]byte{0}, int(pieceSize.Unpadded()))) + + // create the unsealed sector file + pieceInfo, err := sealer.AddPiece(ctx, sref, nil, pieceSize.Unpadded(), dataReader) + require.NoError(t, err) + + // get most recent valid ticket epoch + ts, err := client.ChainHead(ctx) + require.NoError(t, err) + ticketEpoch := ts.Height() - policy.SealRandomnessLookback + + // ticket entropy is cbor-seriasized miner addr + buf := new(bytes.Buffer) + require.NoError(t, maddr.MarshalCBOR(buf)) + + // generate ticket randomness + rand, err := client.StateGetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes(), ts.Key()) + require.NoError(t, err) + + // run PC1 + pc1out, err := sealer.SealPreCommit1(ctx, sref, abi.SealRandomness(rand), []abi.PieceInfo{pieceInfo}) + require.NoError(t, err) + + // run pc2 + scids, err := sealer.SealPreCommit2(ctx, sref, pc1out) + require.NoError(t, err) + + // todo split-finalize! + + //////// + // start http server serving sector data + + m := mux.NewRouter() + m.HandleFunc("/sectors/{type}/{id}", remoteGetSector(sectorDir)).Methods("GET") + srv := httptest.NewServer(m) + + //////// + // import the sector and continue sealing + + err = miner.SectorReceive(ctx, api.RemoteSectorMeta{ + State: "PreCommitting", + Sector: sid, + Type: spt, + + Pieces: []api.SectorPiece{ + { + Piece: pieceInfo, + DealInfo: nil, + }, + }, + + TicketValue: abi.SealRandomness(rand), + TicketEpoch: ticketEpoch, + + PreCommit1Out: pc1out, + + CommD: &scids.Unsealed, + CommR: &scids.Sealed, + + DataUnsealed: &storiface.SectorData{ + Local: false, + URL: fmt.Sprintf("%s/sectors/unsealed/s-t0%d-%d", srv.URL, mid, snum), + }, + DataSealed: &storiface.SectorData{ + Local: false, + URL: fmt.Sprintf("%s/sectors/sealed/s-t0%d-%d", srv.URL, mid, snum), + }, + DataCache: &storiface.SectorData{ + Local: false, + URL: fmt.Sprintf("%s/sectors/cache/s-t0%d-%d", srv.URL, mid, snum), + }, + }) + require.NoError(t, err) + + // check that we see the imported sector + ng, err := miner.SectorsListNonGenesis(ctx) + require.NoError(t, err) + require.Len(t, ng, 1) + require.Equal(t, snum, ng[0]) + + // todo wait sealed + +} + +func remoteGetSector(sectorRoot string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + + // validate sector id + id, err := storiface.ParseSectorID(vars["id"]) + if err != nil { + w.WriteHeader(500) + return + } + + // validate type + _, err = spaths.FileTypeFromString(vars["type"]) + if err != nil { + w.WriteHeader(500) + return + } + + path := filepath.Join(sectorRoot, vars["type"], vars["id"]) + + stat, err := os.Stat(path) + if err != nil { + w.WriteHeader(500) + return + } + + if stat.IsDir() { + if _, has := r.Header["Range"]; has { + w.WriteHeader(500) + return + } + + w.Header().Set("Content-Type", "application/x-tar") + w.WriteHeader(200) + + err := tarutil.TarDirectory(path, w, make([]byte, 1<<20)) + if err != nil { + return + } + } else { + w.Header().Set("Content-Type", "application/octet-stream") + // will do a ranged read over the file at the given path if the caller has asked for a ranged read in the request headers. + http.ServeFile(w, r, path) + } + + fmt.Printf("served sector file/dir, sectorID=%+v, fileType=%s, path=%s\n", id, vars["type"], path) + } +} + +func currentSealProof(ctx context.Context, api api.FullNode, maddr address.Address) (abi.RegisteredSealProof, error) { + mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) + if err != nil { + return 0, err + } + + ver, err := api.StateNetworkVersion(ctx, types.EmptyTSK) + if err != nil { + return 0, err + } + + return lminer.PreferredSealProofTypeFromWindowPoStType(ver, mi.WindowPoStProofType) +} diff --git a/storage/paths/http_handler.go b/storage/paths/http_handler.go index c8f465f25cf..fbf1c85b0e5 100644 --- a/storage/paths/http_handler.go +++ b/storage/paths/http_handler.go @@ -95,7 +95,7 @@ func (handler *FetchHandler) remoteGetSector(w http.ResponseWriter, r *http.Requ return } - ft, err := ftFromString(vars["type"]) + ft, err := FileTypeFromString(vars["type"]) if err != nil { log.Errorf("%+v", err) w.WriteHeader(500) @@ -167,7 +167,7 @@ func (handler *FetchHandler) remoteDeleteSector(w http.ResponseWriter, r *http.R return } - ft, err := ftFromString(vars["type"]) + ft, err := FileTypeFromString(vars["type"]) if err != nil { log.Errorf("%+v", err) w.WriteHeader(500) @@ -195,9 +195,9 @@ func (handler *FetchHandler) remoteGetAllocated(w http.ResponseWriter, r *http.R return } - ft, err := ftFromString(vars["type"]) + ft, err := FileTypeFromString(vars["type"]) if err != nil { - log.Errorf("ftFromString: %+v", err) + log.Errorf("FileTypeFromString: %+v", err) w.WriteHeader(500) return } @@ -311,7 +311,7 @@ func (handler *FetchHandler) generateSingleVanillaProof(w http.ResponseWriter, r http.ServeContent(w, r, "", time.Time{}, bytes.NewReader(vanilla)) } -func ftFromString(t string) (storiface.SectorFileType, error) { +func FileTypeFromString(t string) (storiface.SectorFileType, error) { switch t { case storiface.FTUnsealed.String(): return storiface.FTUnsealed, nil diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index a9e56a84514..3e1de43d913 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -81,8 +81,12 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta fallthrough case SubmitCommit: + if meta.PreCommitDeposit == nil { + return SectorInfo{}, xerrors.Errorf("sector PreCommitDeposit was null") + } + info.PreCommitInfo = meta.PreCommitInfo - info.PreCommitDeposit = meta.PreCommitDeposit + info.PreCommitDeposit = *meta.PreCommitDeposit info.PreCommitMessage = meta.PreCommitMessage info.PreCommitTipSet = meta.PreCommitTipSet From 1fc3a68363e3a2ed6e22e090fa03fd0e3807633c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 6 Sep 2022 10:52:56 +0200 Subject: [PATCH 14/26] sector import: Add missing initial fsm state transition --- node/impl/storminer.go | 15 ++++++++++++--- storage/pipeline/fsm.go | 1 + storage/pipeline/receive.go | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/node/impl/storminer.go b/node/impl/storminer.go index 98a2729581a..942c0fdbaf0 100644 --- a/node/impl/storminer.go +++ b/node/impl/storminer.go @@ -182,16 +182,20 @@ func (sm *StorageMinerAPI) PledgeSector(ctx context.Context) (abi.SectorID, erro return abi.SectorID{}, err } + return sm.waitSectorStarted(ctx, sr.ID) +} + +func (sm *StorageMinerAPI) waitSectorStarted(ctx context.Context, si abi.SectorID) (abi.SectorID, error) { // wait for the sector to enter the Packing state // TODO: instead of polling implement some pubsub-type thing in storagefsm for { - info, err := sm.Miner.SectorsStatus(ctx, sr.ID.Number, false) + info, err := sm.Miner.SectorsStatus(ctx, si.Number, false) if err != nil { return abi.SectorID{}, xerrors.Errorf("getting pledged sector info: %w", err) } if info.State != api.SectorState(sealing.UndefinedSectorState) { - return sr.ID, nil + return si, nil } select { @@ -449,7 +453,12 @@ func (sm *StorageMinerAPI) SectorNumFree(ctx context.Context, name string) error } func (sm *StorageMinerAPI) SectorReceive(ctx context.Context, meta api.RemoteSectorMeta) error { - return sm.Miner.Receive(ctx, meta) + if err := sm.Miner.Receive(ctx, meta); err != nil { + return err + } + + _, err := sm.waitSectorStarted(ctx, meta.Sector) + return err } func (sm *StorageMinerAPI) ComputeWindowPoSt(ctx context.Context, dlIdx uint64, tsk types.TipSetKey) ([]minertypes.SubmitWindowedPoStParams, error) { diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index 59e99bc596b..8512d777577 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -50,6 +50,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto UndefinedSectorState: planOne( on(SectorStart{}, WaitDeals), on(SectorStartCC{}, Packing), + on(SectorReceive{}, ReceiveSector), ), Empty: planOne( // deprecated on(SectorAddPiece{}, AddPiece), diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index 3e1de43d913..ef6496a3596 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -14,6 +14,7 @@ import ( "github.com/filecoin-project/lotus/storage/sealer/storiface" ) +// todo m.inputLk? func (m *Sealing) Receive(ctx context.Context, meta api.RemoteSectorMeta) error { si, err := m.checkSectorMeta(ctx, meta) if err != nil { From cd598318fcd24dc99ee3eefb365e6a51a85763a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 6 Sep 2022 11:06:30 +0200 Subject: [PATCH 15/26] sector import: Plumb sector download task canfig --- cmd/lotus-worker/main.go | 9 +++++++++ documentation/en/cli-lotus-worker.md | 1 + documentation/en/default-lotus-miner-config.toml | 6 ++++-- itests/kit/ensemble.go | 1 + itests/sector_import_test.go | 3 +-- node/config/def.go | 1 + node/config/doc_gen.go | 8 +++++++- node/config/storage.go | 1 + node/config/types.go | 2 +- storage/sealer/manager.go | 4 ++++ 10 files changed, 30 insertions(+), 6 deletions(-) diff --git a/cmd/lotus-worker/main.go b/cmd/lotus-worker/main.go index 286cce883bc..8b8db5aa738 100644 --- a/cmd/lotus-worker/main.go +++ b/cmd/lotus-worker/main.go @@ -224,6 +224,12 @@ var runCmd = &cli.Command{ Value: true, EnvVars: []string{"LOTUS_WORKER_REGEN_SECTOR_KEY"}, }, + &cli.BoolFlag{ + Name: "sector-download", + Usage: "enable external sector data download", + Value: false, + EnvVars: []string{"LOTUS_WORKER_SECTOR_DOWNLOAD"}, + }, &cli.BoolFlag{ Name: "windowpost", Usage: "enable window post", @@ -373,6 +379,9 @@ var runCmd = &cli.Command{ if (workerType == sealtasks.WorkerSealing || cctx.IsSet("addpiece")) && cctx.Bool("addpiece") { taskTypes = append(taskTypes, sealtasks.TTAddPiece, sealtasks.TTDataCid) } + if (workerType == sealtasks.WorkerSealing || cctx.IsSet("sector-download")) && cctx.Bool("sector-download") { + taskTypes = append(taskTypes, sealtasks.TTDownloadSector) + } if (workerType == sealtasks.WorkerSealing || cctx.IsSet("precommit1")) && cctx.Bool("precommit1") { taskTypes = append(taskTypes, sealtasks.TTPreCommit1) } diff --git a/documentation/en/cli-lotus-worker.md b/documentation/en/cli-lotus-worker.md index ec81d28d796..920fb3001a8 100644 --- a/documentation/en/cli-lotus-worker.md +++ b/documentation/en/cli-lotus-worker.md @@ -53,6 +53,7 @@ OPTIONS: --prove-replica-update2 enable prove replica update 2 (default: true) [$LOTUS_WORKER_PROVE_REPLICA_UPDATE2] --regen-sector-key enable regen sector key (default: true) [$LOTUS_WORKER_REGEN_SECTOR_KEY] --replica-update enable replica update (default: true) [$LOTUS_WORKER_REPLICA_UPDATE] + --sector-download enable external sector data download (default: false) [$LOTUS_WORKER_SECTOR_DOWNLOAD] --timeout value used when 'listen' is unspecified. must be a valid duration recognized by golang's time.ParseDuration function (default: "30m") [$LOTUS_WORKER_TIMEOUT] --unseal enable unsealing (32G sectors: 1 core, 128GiB Memory) (default: true) [$LOTUS_WORKER_UNSEAL] --windowpost enable window post (default: false) [$LOTUS_WORKER_WINDOWPOST] diff --git a/documentation/en/default-lotus-miner-config.toml b/documentation/en/default-lotus-miner-config.toml index 78692490444..730a7145c31 100644 --- a/documentation/en/default-lotus-miner-config.toml +++ b/documentation/en/default-lotus-miner-config.toml @@ -588,8 +588,10 @@ # env var: LOTUS_STORAGE_PARALLELFETCHLIMIT #ParallelFetchLimit = 10 - # Local worker config - # + # type: bool + # env var: LOTUS_STORAGE_ALLOWSECTORDOWNLOAD + #AllowSectorDownload = true + # type: bool # env var: LOTUS_STORAGE_ALLOWADDPIECE #AllowAddPiece = true diff --git a/itests/kit/ensemble.go b/itests/kit/ensemble.go index bcc2d93c2a7..8fa781e65d1 100644 --- a/itests/kit/ensemble.go +++ b/itests/kit/ensemble.go @@ -636,6 +636,7 @@ func (n *Ensemble) Start() *Ensemble { scfg := config.DefaultStorageMiner() if noLocal { + scfg.Storage.AllowSectorDownload = false scfg.Storage.AllowAddPiece = false scfg.Storage.AllowPreCommit1 = false scfg.Storage.AllowPreCommit2 = false diff --git a/itests/sector_import_test.go b/itests/sector_import_test.go index 848d8f8e660..e820d9d803e 100644 --- a/itests/sector_import_test.go +++ b/itests/sector_import_test.go @@ -161,8 +161,7 @@ func TestSectorImportAfterPC2(t *testing.T) { require.Len(t, ng, 1) require.Equal(t, snum, ng[0]) - // todo wait sealed - + miner.WaitSectorsProving(ctx, map[abi.SectorNumber]struct{}{snum: {}}) } func remoteGetSector(sectorRoot string) func(w http.ResponseWriter, r *http.Request) { diff --git a/node/config/def.go b/node/config/def.go index ad2150af39b..0566c7d9958 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -146,6 +146,7 @@ func DefaultStorageMiner() *StorageMiner { }, Storage: SealerConfig{ + AllowSectorDownload: true, AllowAddPiece: true, AllowPreCommit1: true, AllowPreCommit2: true, diff --git a/node/config/doc_gen.go b/node/config/doc_gen.go index 7f08c8ccec7..3d6ef0f291b 100644 --- a/node/config/doc_gen.go +++ b/node/config/doc_gen.go @@ -796,11 +796,17 @@ This parameter is ONLY applicable if the retrieval pricing policy strategy has b Comment: ``, }, + { + Name: "AllowSectorDownload", + Type: "bool", + + Comment: ``, + }, { Name: "AllowAddPiece", Type: "bool", - Comment: `Local worker config`, + Comment: ``, }, { Name: "AllowPreCommit1", diff --git a/node/config/storage.go b/node/config/storage.go index 20f1791e61c..0c72eabd149 100644 --- a/node/config/storage.go +++ b/node/config/storage.go @@ -54,6 +54,7 @@ func WriteStorageFile(path string, config paths.StorageConfig) error { func (c *StorageMiner) StorageManager() sealer.Config { return sealer.Config{ ParallelFetchLimit: c.Storage.ParallelFetchLimit, + AllowSectorDownload: c.Storage.AllowSectorDownload, AllowAddPiece: c.Storage.AllowAddPiece, AllowPreCommit1: c.Storage.AllowPreCommit1, AllowPreCommit2: c.Storage.AllowPreCommit2, diff --git a/node/config/types.go b/node/config/types.go index ddc574efb38..7580196903a 100644 --- a/node/config/types.go +++ b/node/config/types.go @@ -391,7 +391,7 @@ type SealingConfig struct { type SealerConfig struct { ParallelFetchLimit int - // Local worker config + AllowSectorDownload bool AllowAddPiece bool AllowPreCommit1 bool AllowPreCommit2 bool diff --git a/storage/sealer/manager.go b/storage/sealer/manager.go index 78c0622f475..a4d31e21b8a 100644 --- a/storage/sealer/manager.go +++ b/storage/sealer/manager.go @@ -108,6 +108,7 @@ type Config struct { ParallelFetchLimit int // Local worker config + AllowSectorDownload bool AllowAddPiece bool AllowPreCommit1 bool AllowPreCommit2 bool @@ -182,6 +183,9 @@ func New(ctx context.Context, lstor *paths.Local, stor paths.Store, ls paths.Loc localTasks := []sealtasks.TaskType{ sealtasks.TTCommit1, sealtasks.TTProveReplicaUpdate1, sealtasks.TTFinalize, sealtasks.TTFetch, sealtasks.TTFinalizeReplicaUpdate, } + if sc.AllowSectorDownload { + localTasks = append(localTasks, sealtasks.TTDownloadSector) + } if sc.AllowAddPiece { localTasks = append(localTasks, sealtasks.TTAddPiece, sealtasks.TTDataCid) } From b85b0a5c5c49a74ff1fdf3e3605c5761c0fdb918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 6 Sep 2022 11:27:07 +0200 Subject: [PATCH 16/26] sector import: Seal with the correct proof type in saas itest --- itests/sector_import_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/itests/sector_import_test.go b/itests/sector_import_test.go index e820d9d803e..c578ab347e0 100644 --- a/itests/sector_import_test.go +++ b/itests/sector_import_test.go @@ -73,7 +73,7 @@ func TestSectorImportAfterPC2(t *testing.T) { sref := storiface.SectorRef{ ID: sid, - ProofType: 0, + ProofType: spt, } sealer, err := ffiwrapper.New(&basicfs.Provider{ From ad7728479b613e5cc2288a2d40c3d2d955efe825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 6 Sep 2022 17:09:27 +0200 Subject: [PATCH 17/26] sector import: FinalizeInto, send finalized cacde in itest --- itests/sector_import_test.go | 13 ++++++-- storage/sealer/ffiwrapper/sealer_cgo.go | 41 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/itests/sector_import_test.go b/itests/sector_import_test.go index c578ab347e0..818675828e2 100644 --- a/itests/sector_import_test.go +++ b/itests/sector_import_test.go @@ -108,7 +108,10 @@ func TestSectorImportAfterPC2(t *testing.T) { scids, err := sealer.SealPreCommit2(ctx, sref, pc1out) require.NoError(t, err) - // todo split-finalize! + // make finalized cache, put it in [sectorDir]/fin-cache + finDst := filepath.Join(sectorDir, "fin-cache", fmt.Sprintf("s-t01000-%d", snum)) + require.NoError(t, os.MkdirAll(finDst, 0777)) + require.NoError(t, sealer.FinalizeSectorInto(ctx, sref, finDst)) //////// // start http server serving sector data @@ -183,7 +186,13 @@ func remoteGetSector(sectorRoot string) func(w http.ResponseWriter, r *http.Requ return } - path := filepath.Join(sectorRoot, vars["type"], vars["id"]) + typ := vars["type"] + if typ == "cache" { + // if cache is requested, send the finalized cache we've created above + typ = "fin-cache" + } + + path := filepath.Join(sectorRoot, typ, vars["id"]) stat, err := os.Stat(path) if err != nil { diff --git a/storage/sealer/ffiwrapper/sealer_cgo.go b/storage/sealer/ffiwrapper/sealer_cgo.go index cc137151f14..d73b7278735 100644 --- a/storage/sealer/ffiwrapper/sealer_cgo.go +++ b/storage/sealer/ffiwrapper/sealer_cgo.go @@ -11,9 +11,12 @@ import ( "encoding/base64" "encoding/json" "io" + "io/ioutil" "math/bits" "os" + "path/filepath" "runtime" + "syscall" "github.com/detailyang/go-fallocate" "github.com/ipfs/go-cid" @@ -1069,6 +1072,44 @@ func (sb *Sealer) FinalizeSector(ctx context.Context, sector storiface.SectorRef return ffi.ClearCache(uint64(ssize), paths.Cache) } +// FinalizeSectorInto is like FinalizeSector, but writes finalized sector cache into a new path +func (sb *Sealer) FinalizeSectorInto(ctx context.Context, sector storiface.SectorRef, dest string) error { + ssize, err := sector.ProofType.SectorSize() + if err != nil { + return err + } + + paths, done, err := sb.sectors.AcquireSector(ctx, sector, storiface.FTCache, 0, storiface.PathStorage) + if err != nil { + return xerrors.Errorf("acquiring sector cache path: %w", err) + } + defer done() + + files, err := ioutil.ReadDir(paths.Cache) + if err != nil { + return err + } + for _, file := range files { + if file.Name() != "t_aux" && file.Name() != "p_aux" { + // link all the non-aux files + if err := syscall.Link(filepath.Join(paths.Cache, file.Name()), filepath.Join(dest, file.Name())); err != nil { + return xerrors.Errorf("link %s: %w", file.Name(), err) + } + continue + } + + d, err := os.ReadFile(filepath.Join(paths.Cache, file.Name())) + if err != nil { + return xerrors.Errorf("read %s: %w", file.Name(), err) + } + if err := os.WriteFile(filepath.Join(dest, file.Name()), d, 0666); err != nil { + return xerrors.Errorf("write %s: %w", file.Name(), err) + } + } + + return ffi.ClearCache(uint64(ssize), dest) +} + func (sb *Sealer) FinalizeReplicaUpdate(ctx context.Context, sector storiface.SectorRef, keepUnsealed []storiface.Range) error { ssize, err := sector.ProofType.SectorSize() if err != nil { From aaa154b07540224c2a8e472acce244ef54a43b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 10:32:27 +0200 Subject: [PATCH 18/26] sector import: Remote Commit1 --- api/api_storage.go | 14 +++++- build/openrpc/miner.json.gz | Bin 15786 -> 15801 bytes cmd/lotus-miner/info.go | 1 + documentation/en/api-v0-methods-miner.md | 3 +- itests/sector_import_test.go | 52 ++++++++++++++++++++++ storage/pipeline/cbor_gen.go | 36 ++++++++++++++- storage/pipeline/fsm.go | 7 +++ storage/pipeline/fsm_events.go | 5 +++ storage/pipeline/receive.go | 3 +- storage/pipeline/sector_state.go | 2 + storage/pipeline/states_failed.go | 12 +++++ storage/pipeline/states_sealing.go | 54 ++++++++++++++++++++--- storage/pipeline/types.go | 9 ++-- 13 files changed, 183 insertions(+), 15 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 9562c013500..7b21adbb00f 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -567,6 +567,18 @@ type RemoteSectorMeta struct { //////// // SEALING SERVICE HOOKS - // todo Commit1Provider + // URL + // todo better doc + RemoteCommit1Endpoint string + // todo OnDone / OnStateChange } + +type RemoteCommit1Params struct { + Ticket, Seed []byte + + Unsealed cid.Cid + Sealed cid.Cid + + ProofType abi.RegisteredSealProof +} diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 550389d525e47b28a21a1318a66003fef389fe26..61fcef75cdf265fe7db147deffcb16be1289e05c 100644 GIT binary patch delta 5200 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 diff --git a/cmd/lotus-miner/info.go b/cmd/lotus-miner/info.go index baad55e37d1..02d659f61b6 100644 --- a/cmd/lotus-miner/info.go +++ b/cmd/lotus-miner/info.go @@ -551,6 +551,7 @@ var stateList = []stateMeta{ {col: color.FgRed, state: sealing.SealPreCommit2Failed}, {col: color.FgRed, state: sealing.PreCommitFailed}, {col: color.FgRed, state: sealing.ComputeProofFailed}, + {col: color.FgRed, state: sealing.RemoteCommit1Failed}, {col: color.FgRed, state: sealing.CommitFailed}, {col: color.FgRed, state: sealing.CommitFinalizeFailed}, {col: color.FgRed, state: sealing.PackingFailed}, diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 73f6a2d1a0c..1bd41dfc775 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -3271,7 +3271,8 @@ Inputs: "Value": "string value" } ] - } + }, + "RemoteCommit1Endpoint": "string value" } ] ``` diff --git a/itests/sector_import_test.go b/itests/sector_import_test.go index 818675828e2..7ff4fa48f7c 100644 --- a/itests/sector_import_test.go +++ b/itests/sector_import_test.go @@ -3,6 +3,7 @@ package itests import ( "bytes" "context" + "encoding/json" "fmt" "net/http" "net/http/httptest" @@ -118,6 +119,7 @@ func TestSectorImportAfterPC2(t *testing.T) { m := mux.NewRouter() m.HandleFunc("/sectors/{type}/{id}", remoteGetSector(sectorDir)).Methods("GET") + m.HandleFunc("/sectors/{id}/commit1", remoteCommit1(sealer)).Methods("POST") srv := httptest.NewServer(m) //////// @@ -155,6 +157,8 @@ func TestSectorImportAfterPC2(t *testing.T) { Local: false, URL: fmt.Sprintf("%s/sectors/cache/s-t0%d-%d", srv.URL, mid, snum), }, + + RemoteCommit1Endpoint: fmt.Sprintf("%s/sectors/s-t0%d-%d/commit1", srv.URL, mid, snum), }) require.NoError(t, err) @@ -167,6 +171,54 @@ func TestSectorImportAfterPC2(t *testing.T) { miner.WaitSectorsProving(ctx, map[abi.SectorNumber]struct{}{snum: {}}) } +func remoteCommit1(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + // validate sector id + id, err := storiface.ParseSectorID(vars["id"]) + if err != nil { + w.WriteHeader(500) + return + } + + var params api.RemoteCommit1Params + if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { + w.WriteHeader(500) + return + } + + sref := storiface.SectorRef{ + ID: id, + ProofType: params.ProofType, + } + + ssize, err := params.ProofType.SectorSize() + if err != nil { + w.WriteHeader(500) + return + } + + p, err := s.SealCommit1(r.Context(), sref, params.Ticket, params.Seed, []abi.PieceInfo{ + { + Size: abi.PaddedPieceSize(ssize), + PieceCID: params.Unsealed, + }, + }, storiface.SectorCids{ + Unsealed: params.Unsealed, + Sealed: params.Sealed, + }) + if err != nil { + w.WriteHeader(500) + return + } + + if _, err := w.Write(p); err != nil { + fmt.Println("c1 write error") + } + } +} + func remoteGetSector(sectorRoot string) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { diff --git a/storage/pipeline/cbor_gen.go b/storage/pipeline/cbor_gen.go index ec6c7363497..220ca74898b 100644 --- a/storage/pipeline/cbor_gen.go +++ b/storage/pipeline/cbor_gen.go @@ -32,7 +32,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { cw := cbg.NewCborWriter(w) - if _, err := cw.Write([]byte{184, 36}); err != nil { + if _, err := cw.Write([]byte{184, 37}); err != nil { return err } @@ -720,6 +720,29 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { return err } + // t.RemoteCommit1Endpoint (string) (string) + if len("RemoteCommit1Endpoint") > cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteCommit1Endpoint\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteCommit1Endpoint"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteCommit1Endpoint")); err != nil { + return err + } + + if len(t.RemoteCommit1Endpoint) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.RemoteCommit1Endpoint was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.RemoteCommit1Endpoint))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.RemoteCommit1Endpoint)); err != nil { + return err + } + // t.RemoteDataFinalized (bool) (bool) if len("RemoteDataFinalized") > cbg.MaxLength { return xerrors.Errorf("Value in field \"RemoteDataFinalized\" was too long") @@ -1516,6 +1539,17 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { } } + // t.RemoteCommit1Endpoint (string) (string) + case "RemoteCommit1Endpoint": + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.RemoteCommit1Endpoint = string(sval) + } // t.RemoteDataFinalized (bool) (bool) case "RemoteDataFinalized": diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index 8512d777577..fb0d16b387d 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -225,6 +225,9 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorRetryComputeProof{}, Committing), on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), ), + RemoteCommit1Failed: planOne( + on(SectorRetryComputeProof{}, Committing), + ), CommitFinalizeFailed: planOne( on(SectorRetryFinalize{}, CommitFinalize), ), @@ -539,6 +542,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta return m.handlePreCommitFailed, processed, nil case ComputeProofFailed: return m.handleComputeProofFailed, processed, nil + case RemoteCommit1Failed: + return m.handleRemoteCommit1Failed, processed, nil case CommitFailed: return m.handleCommitFailed, processed, nil case CommitFinalizeFailed: @@ -666,6 +671,8 @@ func planCommitting(events []statemachine.Event, state *SectorInfo) (uint64, err return uint64(i + 1), nil case SectorComputeProofFailed: state.State = ComputeProofFailed + case SectorRemoteCommit1Failed: + state.State = RemoteCommit1Failed case SectorSealPreCommit1Failed: state.State = SealPreCommit1Failed case SectorCommitFailed: diff --git a/storage/pipeline/fsm_events.go b/storage/pipeline/fsm_events.go index 8576d4181ac..5c975bddacd 100644 --- a/storage/pipeline/fsm_events.go +++ b/storage/pipeline/fsm_events.go @@ -219,6 +219,11 @@ func (evt SectorSeedReady) apply(state *SectorInfo) { state.SeedValue = evt.SeedValue } +type SectorRemoteCommit1Failed struct{ error } + +func (evt SectorRemoteCommit1Failed) FormatError(xerrors.Printer) (next error) { return evt.error } +func (evt SectorRemoteCommit1Failed) apply(*SectorInfo) {} + type SectorComputeProofFailed struct{ error } func (evt SectorComputeProofFailed) FormatError(xerrors.Printer) (next error) { return evt.error } diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index ef6496a3596..fd4f64a6695 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -114,8 +114,9 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta if meta.DataCache == nil { return SectorInfo{}, xerrors.Errorf("expected DataCache to be set") } - info.RemoteDataSealed = meta.DataSealed + info.RemoteDataSealed = meta.DataSealed // todo make head requests to check? info.RemoteDataCache = meta.DataCache + info.RemoteCommit1Endpoint = meta.RemoteCommit1Endpoint // If we get a sector after PC2, assume that we're getting finalized sector data // todo: maybe only set if C1 provider is set? diff --git a/storage/pipeline/sector_state.go b/storage/pipeline/sector_state.go index ad77fdbd5e1..136e72a1658 100644 --- a/storage/pipeline/sector_state.go +++ b/storage/pipeline/sector_state.go @@ -31,6 +31,7 @@ var ExistSectorStateList = map[SectorState]struct{}{ SealPreCommit2Failed: {}, PreCommitFailed: {}, ComputeProofFailed: {}, + RemoteCommit1Failed: {}, CommitFailed: {}, PackingFailed: {}, FinalizeFailed: {}, @@ -124,6 +125,7 @@ const ( SealPreCommit2Failed SectorState = "SealPreCommit2Failed" PreCommitFailed SectorState = "PreCommitFailed" ComputeProofFailed SectorState = "ComputeProofFailed" + RemoteCommit1Failed SectorState = "RemoteCommit1Failed" CommitFailed SectorState = "CommitFailed" PackingFailed SectorState = "PackingFailed" // TODO: deprecated, remove FinalizeFailed SectorState = "FinalizeFailed" diff --git a/storage/pipeline/states_failed.go b/storage/pipeline/states_failed.go index c57bef61b38..ccc65e10ce0 100644 --- a/storage/pipeline/states_failed.go +++ b/storage/pipeline/states_failed.go @@ -184,6 +184,18 @@ func (m *Sealing) handleComputeProofFailed(ctx statemachine.Context, sector Sect return ctx.Send(SectorRetryComputeProof{}) } +func (m *Sealing) handleRemoteCommit1Failed(ctx statemachine.Context, sector SectorInfo) error { + if err := failedCooldown(ctx, sector); err != nil { + return err + } + + if sector.InvalidProofs > 1 { + log.Errorw("consecutive remote commit1 fails", "sector", sector.SectorNumber, "c1url", sector.RemoteCommit1Endpoint) + } + + return ctx.Send(SectorRetryComputeProof{}) +} + func (m *Sealing) handleSubmitReplicaUpdateFailed(ctx statemachine.Context, sector SectorInfo) error { if err := failedCooldown(ctx, sector); err != nil { return err diff --git a/storage/pipeline/states_sealing.go b/storage/pipeline/states_sealing.go index 354d15e69cb..428dd30a67b 100644 --- a/storage/pipeline/states_sealing.go +++ b/storage/pipeline/states_sealing.go @@ -3,6 +3,9 @@ package sealing import ( "bytes" "context" + "encoding/json" + "io" + "net/http" "github.com/ipfs/go-cid" "golang.org/x/xerrors" @@ -562,13 +565,50 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) return ctx.Send(SectorCommitFailed{xerrors.Errorf("sector had nil commR or commD")}) } - cids := storiface.SectorCids{ - Unsealed: *sector.CommD, - Sealed: *sector.CommR, - } - c2in, err := m.sealer.SealCommit1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), sector.TicketValue, sector.SeedValue, sector.pieceInfos(), cids) - if err != nil { - return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed(1): %w", err)}) + var c2in storiface.Commit1Out + if sector.RemoteCommit1Endpoint == "" { + cids := storiface.SectorCids{ + Unsealed: *sector.CommD, + Sealed: *sector.CommR, + } + c2in, err = m.sealer.SealCommit1(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), sector.TicketValue, sector.SeedValue, sector.pieceInfos(), cids) + if err != nil { + return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed(1): %w", err)}) + } + } else { + reqData := api.RemoteCommit1Params{ + Ticket: sector.TicketValue, + Seed: sector.SeedValue, + Unsealed: *sector.CommD, + Sealed: *sector.CommR, + ProofType: sector.SectorType, + } + reqBody, err := json.Marshal(&reqData) + if err != nil { + return xerrors.Errorf("marshaling remote commit1 request: %w", err) + } + + req, err := http.NewRequest("POST", sector.RemoteCommit1Endpoint, bytes.NewReader(reqBody)) + if err != nil { + return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("creating new remote commit1 request: %w", err)}) + } + req.Header.Set("Content-Type", "application/json") + req = req.WithContext(ctx.Context()) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("requesting remote commit1: %w", err)}) + } + + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("remote commit1 received non-200 http response %s", resp.Status)}) + } + + c2in, err = io.ReadAll(resp.Body) // todo some len constraint + if err != nil { + return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("reading commit1 response: %w", err)}) + } } proof, err := m.sealer.SealCommit2(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), c2in) diff --git a/storage/pipeline/types.go b/storage/pipeline/types.go index 24cff829d3d..8ae2cdeb1fd 100644 --- a/storage/pipeline/types.go +++ b/storage/pipeline/types.go @@ -96,10 +96,11 @@ type SectorInfo struct { TerminatedAt abi.ChainEpoch // Remote import - RemoteDataUnsealed *storiface.SectorData - RemoteDataSealed *storiface.SectorData - RemoteDataCache *storiface.SectorData - RemoteDataFinalized bool + RemoteDataUnsealed *storiface.SectorData + RemoteDataSealed *storiface.SectorData + RemoteDataCache *storiface.SectorData + RemoteCommit1Endpoint string + RemoteDataFinalized bool // Debug LastErr string From 0e491ba706c2c64078bd686254d4eb74eeeb42e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 11:11:47 +0200 Subject: [PATCH 19/26] sector import: Test remote commit1 retry --- itests/kit/node_miner.go | 8 +- itests/sector_import_full_test.go | 221 ++++++++++++++++++ ...t_test.go => sector_import_simple_test.go} | 47 ++-- storage/pipeline/receive.go | 1 - storage/pipeline/states_failed.go | 4 +- 5 files changed, 260 insertions(+), 21 deletions(-) create mode 100644 itests/sector_import_full_test.go rename itests/{sector_import_test.go => sector_import_simple_test.go} (85%) diff --git a/itests/kit/node_miner.go b/itests/kit/node_miner.go index 8805ac36c36..b08ce1847ce 100644 --- a/itests/kit/node_miner.go +++ b/itests/kit/node_miner.go @@ -97,6 +97,10 @@ func (tm *TestMiner) PledgeSectors(ctx context.Context, n, existing int, blockNo } func (tm *TestMiner) WaitSectorsProving(ctx context.Context, toCheck map[abi.SectorNumber]struct{}) { + tm.WaitSectorsProvingAllowFails(ctx, toCheck, map[api.SectorState]struct{}{}) +} + +func (tm *TestMiner) WaitSectorsProvingAllowFails(ctx context.Context, toCheck map[abi.SectorNumber]struct{}, okFails map[api.SectorState]struct{}) { for len(toCheck) > 0 { tm.FlushSealingBatches(ctx) @@ -109,7 +113,9 @@ func (tm *TestMiner) WaitSectorsProving(ctx context.Context, toCheck map[abi.Sec delete(toCheck, n) } if strings.Contains(string(st.State), "Fail") { - tm.t.Fatal("sector in a failed state", st.State) + if _, ok := okFails[st.State]; !ok { + tm.t.Fatal("sector in a failed state", st.State) + } } } diff --git a/itests/sector_import_full_test.go b/itests/sector_import_full_test.go new file mode 100644 index 00000000000..3be72e8eb92 --- /dev/null +++ b/itests/sector_import_full_test.go @@ -0,0 +1,221 @@ +package itests + +import ( + "bytes" + "context" + "fmt" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" + "time" + + "github.com/gorilla/mux" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/actors/policy" + "github.com/filecoin-project/lotus/itests/kit" + sealing "github.com/filecoin-project/lotus/storage/pipeline" + "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" + "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper/basicfs" + "github.com/filecoin-project/lotus/storage/sealer/storiface" +) + +func TestSectorImport(t *testing.T) { + + type testCase struct { + c1handler func(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Request) + } + + makeTest := func(mut func(*testCase)) *testCase { + tc := &testCase{ + c1handler: remoteCommit1, + } + mut(tc) + return tc + } + + runTest := func(tc *testCase) func(t *testing.T) { + return func(t *testing.T) { + kit.QuietMiningLogs() + + var blockTime = 50 * time.Millisecond + + //////// + // Start a miner node + + client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + + ctx := context.Background() + + //////// + // Reserve some sector numbers on the miner node; We'll use one of those when creating the sector "remotely" + snums, err := miner.SectorNumReserveCount(ctx, "test-reservation-0001", 16) + require.NoError(t, err) + + sectorDir := t.TempDir() + + maddr, err := miner.ActorAddress(ctx) + require.NoError(t, err) + + mid, err := address.IDFromAddress(maddr) + require.NoError(t, err) + + spt, err := currentSealProof(ctx, client, maddr) + require.NoError(t, err) + + ssize, err := spt.SectorSize() + require.NoError(t, err) + + pieceSize := abi.PaddedPieceSize(ssize) + + //////// + // Create/Seal a sector up to pc2 outside of the pipeline + + // get one sector number from the reservation done on the miner above + sn, err := snums.First() + require.NoError(t, err) + + // create all the sector identifiers + snum := abi.SectorNumber(sn) + sid := abi.SectorID{Miner: abi.ActorID(mid), Number: snum} + sref := storiface.SectorRef{ID: sid, ProofType: spt} + + // create a low-level sealer instance + sealer, err := ffiwrapper.New(&basicfs.Provider{ + Root: sectorDir, + }) + require.NoError(t, err) + + // CRETE THE UNSEALED FILE + + // create a reader for all-zero (CC) data + dataReader := bytes.NewReader(bytes.Repeat([]byte{0}, int(pieceSize.Unpadded()))) + + // create the unsealed CC sector file + pieceInfo, err := sealer.AddPiece(ctx, sref, nil, pieceSize.Unpadded(), dataReader) + require.NoError(t, err) + + // GENERATE THE TICKET + + // get most recent valid ticket epoch + ts, err := client.ChainHead(ctx) + require.NoError(t, err) + ticketEpoch := ts.Height() - policy.SealRandomnessLookback + + // ticket entropy is cbor-seriasized miner addr + buf := new(bytes.Buffer) + require.NoError(t, maddr.MarshalCBOR(buf)) + + // generate ticket randomness + rand, err := client.StateGetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes(), ts.Key()) + require.NoError(t, err) + + // EXECUTE PRECOMMIT 1 / 2 + + // run PC1 + pc1out, err := sealer.SealPreCommit1(ctx, sref, abi.SealRandomness(rand), []abi.PieceInfo{pieceInfo}) + require.NoError(t, err) + + // run pc2 + scids, err := sealer.SealPreCommit2(ctx, sref, pc1out) + require.NoError(t, err) + + // make finalized cache, put it in [sectorDir]/fin-cache while keeping the large cache for remote C1 + finDst := filepath.Join(sectorDir, "fin-cache", fmt.Sprintf("s-t01000-%d", snum)) + require.NoError(t, os.MkdirAll(finDst, 0777)) + require.NoError(t, sealer.FinalizeSectorInto(ctx, sref, finDst)) + + //////// + // start http server serving sector data + + m := mux.NewRouter() + m.HandleFunc("/sectors/{type}/{id}", remoteGetSector(sectorDir)).Methods("GET") + m.HandleFunc("/sectors/{id}/commit1", tc.c1handler(sealer)).Methods("POST") + srv := httptest.NewServer(m) + + unsealedURL := fmt.Sprintf("%s/sectors/unsealed/s-t0%d-%d", srv.URL, mid, snum) + sealedURL := fmt.Sprintf("%s/sectors/sealed/s-t0%d-%d", srv.URL, mid, snum) + cacheURL := fmt.Sprintf("%s/sectors/cache/s-t0%d-%d", srv.URL, mid, snum) + remoteC1URL := fmt.Sprintf("%s/sectors/s-t0%d-%d/commit1", srv.URL, mid, snum) + + //////// + // import the sector and continue sealing + + err = miner.SectorReceive(ctx, api.RemoteSectorMeta{ + State: "PreCommitting", + Sector: sid, + Type: spt, + + Pieces: []api.SectorPiece{ + { + Piece: pieceInfo, + DealInfo: nil, + }, + }, + + TicketValue: abi.SealRandomness(rand), + TicketEpoch: ticketEpoch, + + PreCommit1Out: pc1out, + + CommD: &scids.Unsealed, + CommR: &scids.Sealed, + + DataUnsealed: &storiface.SectorData{ + Local: false, + URL: unsealedURL, + }, + DataSealed: &storiface.SectorData{ + Local: false, + URL: sealedURL, + }, + DataCache: &storiface.SectorData{ + Local: false, + URL: cacheURL, + }, + + RemoteCommit1Endpoint: remoteC1URL, + }) + require.NoError(t, err) + + // check that we see the imported sector + ng, err := miner.SectorsListNonGenesis(ctx) + require.NoError(t, err) + require.Len(t, ng, 1) + require.Equal(t, snum, ng[0]) + + miner.WaitSectorsProvingAllowFails(ctx, map[abi.SectorNumber]struct{}{snum: {}}, map[api.SectorState]struct{}{api.SectorState(sealing.RemoteCommit1Failed): {}}) + } + } + + // fail first remote c1, verifies that c1 retry works + t.Run("c1-retry", runTest(makeTest(func(testCase *testCase) { + prt := sealing.MinRetryTime + sealing.MinRetryTime = time.Second + t.Cleanup(func() { + sealing.MinRetryTime = prt + }) + + testCase.c1handler = func(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Request) { + var failedOnce bool + + return func(w http.ResponseWriter, r *http.Request) { + if !failedOnce { + failedOnce = true + w.WriteHeader(http.StatusBadGateway) + return + } + + remoteCommit1(s)(w, r) + } + } + }))) +} diff --git a/itests/sector_import_test.go b/itests/sector_import_simple_test.go similarity index 85% rename from itests/sector_import_test.go rename to itests/sector_import_simple_test.go index 7ff4fa48f7c..8b1b72fd713 100644 --- a/itests/sector_import_test.go +++ b/itests/sector_import_simple_test.go @@ -36,12 +36,16 @@ func TestSectorImportAfterPC2(t *testing.T) { var blockTime = 50 * time.Millisecond + //////// + // Start a miner node + client, miner, ens := kit.EnsembleMinimal(t, kit.ThroughRPC()) ens.InterconnectAll().BeginMining(blockTime) ctx := context.Background() - // get some sector numbers + //////// + // Reserve some sector numbers on the miner node; We'll use one of those when creating the sector "remotely" snums, err := miner.SectorNumReserveCount(ctx, "test-reservation-0001", 16) require.NoError(t, err) @@ -62,32 +66,34 @@ func TestSectorImportAfterPC2(t *testing.T) { pieceSize := abi.PaddedPieceSize(ssize) //////// - // seal a sector up to pc2 outside of the pipeline + // Create/Seal a sector up to pc2 outside of the pipeline + // get one sector number from the reservation done on the miner above sn, err := snums.First() require.NoError(t, err) - snum := abi.SectorNumber(sn) - sid := abi.SectorID{ - Miner: abi.ActorID(mid), - Number: snum, - } - sref := storiface.SectorRef{ - ID: sid, - ProofType: spt, - } + // create all the sector identifiers + snum := abi.SectorNumber(sn) + sid := abi.SectorID{Miner: abi.ActorID(mid), Number: snum} + sref := storiface.SectorRef{ID: sid, ProofType: spt} + // create a low-level sealer instance sealer, err := ffiwrapper.New(&basicfs.Provider{ Root: sectorDir, }) require.NoError(t, err) + // CRETE THE UNSEALED FILE + + // create a reader for all-zero (CC) data dataReader := bytes.NewReader(bytes.Repeat([]byte{0}, int(pieceSize.Unpadded()))) - // create the unsealed sector file + // create the unsealed CC sector file pieceInfo, err := sealer.AddPiece(ctx, sref, nil, pieceSize.Unpadded(), dataReader) require.NoError(t, err) + // GENERATE THE TICKET + // get most recent valid ticket epoch ts, err := client.ChainHead(ctx) require.NoError(t, err) @@ -101,6 +107,8 @@ func TestSectorImportAfterPC2(t *testing.T) { rand, err := client.StateGetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_SealRandomness, ticketEpoch, buf.Bytes(), ts.Key()) require.NoError(t, err) + // EXECUTE PRECOMMIT 1 / 2 + // run PC1 pc1out, err := sealer.SealPreCommit1(ctx, sref, abi.SealRandomness(rand), []abi.PieceInfo{pieceInfo}) require.NoError(t, err) @@ -109,7 +117,7 @@ func TestSectorImportAfterPC2(t *testing.T) { scids, err := sealer.SealPreCommit2(ctx, sref, pc1out) require.NoError(t, err) - // make finalized cache, put it in [sectorDir]/fin-cache + // make finalized cache, put it in [sectorDir]/fin-cache while keeping the large cache for remote C1 finDst := filepath.Join(sectorDir, "fin-cache", fmt.Sprintf("s-t01000-%d", snum)) require.NoError(t, os.MkdirAll(finDst, 0777)) require.NoError(t, sealer.FinalizeSectorInto(ctx, sref, finDst)) @@ -122,6 +130,11 @@ func TestSectorImportAfterPC2(t *testing.T) { m.HandleFunc("/sectors/{id}/commit1", remoteCommit1(sealer)).Methods("POST") srv := httptest.NewServer(m) + unsealedURL := fmt.Sprintf("%s/sectors/unsealed/s-t0%d-%d", srv.URL, mid, snum) + sealedURL := fmt.Sprintf("%s/sectors/sealed/s-t0%d-%d", srv.URL, mid, snum) + cacheURL := fmt.Sprintf("%s/sectors/cache/s-t0%d-%d", srv.URL, mid, snum) + remoteC1URL := fmt.Sprintf("%s/sectors/s-t0%d-%d/commit1", srv.URL, mid, snum) + //////// // import the sector and continue sealing @@ -147,18 +160,18 @@ func TestSectorImportAfterPC2(t *testing.T) { DataUnsealed: &storiface.SectorData{ Local: false, - URL: fmt.Sprintf("%s/sectors/unsealed/s-t0%d-%d", srv.URL, mid, snum), + URL: unsealedURL, }, DataSealed: &storiface.SectorData{ Local: false, - URL: fmt.Sprintf("%s/sectors/sealed/s-t0%d-%d", srv.URL, mid, snum), + URL: sealedURL, }, DataCache: &storiface.SectorData{ Local: false, - URL: fmt.Sprintf("%s/sectors/cache/s-t0%d-%d", srv.URL, mid, snum), + URL: cacheURL, }, - RemoteCommit1Endpoint: fmt.Sprintf("%s/sectors/s-t0%d-%d/commit1", srv.URL, mid, snum), + RemoteCommit1Endpoint: remoteC1URL, }) require.NoError(t, err) diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index fd4f64a6695..13ee0ff02ba 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -126,7 +126,6 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta case GetTicket: fallthrough case Packing: - // todo check num free info.Return = ReturnState(meta.State) // todo dedupe states info.State = ReceiveSector diff --git a/storage/pipeline/states_failed.go b/storage/pipeline/states_failed.go index ccc65e10ce0..7597273b889 100644 --- a/storage/pipeline/states_failed.go +++ b/storage/pipeline/states_failed.go @@ -19,12 +19,12 @@ import ( "github.com/filecoin-project/lotus/chain/types" ) -const minRetryTime = 1 * time.Minute +var MinRetryTime = 1 * time.Minute func failedCooldown(ctx statemachine.Context, sector SectorInfo) error { // TODO: Exponential backoff when we see consecutive failures - retryStart := time.Unix(int64(sector.Log[len(sector.Log)-1].Timestamp), 0).Add(minRetryTime) + retryStart := time.Unix(int64(sector.Log[len(sector.Log)-1].Timestamp), 0).Add(MinRetryTime) if len(sector.Log) > 0 && !time.Now().After(retryStart) { log.Infof("%s(%d), waiting %s before retrying", sector.State, sector.SectorNumber, time.Until(retryStart)) select { From b3c82823d844e6e175a7233c2123c61ffc1e2ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 12:22:21 +0200 Subject: [PATCH 20/26] sector import: Implement seed/ticket/commr/commd checks --- .circleci/config.yml | 11 +++- itests/sector_import_full_test.go | 73 ++++++++++++++++++++- storage/pipeline/receive.go | 102 ++++++++++++++++++++++++++---- 3 files changed, 170 insertions(+), 16 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e0b7b1d28b..0ac3865cc98 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -970,9 +970,14 @@ workflows: target: "./itests/sector_finalize_early_test.go" - test: - name: test-itest-sector_import - suite: itest-sector_import - target: "./itests/sector_import_test.go" + name: test-itest-sector_import_full + suite: itest-sector_import_full + target: "./itests/sector_import_full_test.go" + + - test: + name: test-itest-sector_import_simple + suite: itest-sector_import_simple + target: "./itests/sector_import_simple_test.go" - test: name: test-itest-sector_make_cc_avail diff --git a/itests/sector_import_full_test.go b/itests/sector_import_full_test.go index 3be72e8eb92..7be2907936b 100644 --- a/itests/sector_import_full_test.go +++ b/itests/sector_import_full_test.go @@ -31,6 +31,10 @@ func TestSectorImport(t *testing.T) { type testCase struct { c1handler func(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Request) + + mutateRemoteMeta func(*api.RemoteSectorMeta) + + expectImportErrContains string } makeTest := func(mut func(*testCase)) *testCase { @@ -149,7 +153,7 @@ func TestSectorImport(t *testing.T) { //////// // import the sector and continue sealing - err = miner.SectorReceive(ctx, api.RemoteSectorMeta{ + rmeta := api.RemoteSectorMeta{ State: "PreCommitting", Sector: sid, Type: spt, @@ -183,7 +187,18 @@ func TestSectorImport(t *testing.T) { }, RemoteCommit1Endpoint: remoteC1URL, - }) + } + + if tc.mutateRemoteMeta != nil { + tc.mutateRemoteMeta(&rmeta) + } + + err = miner.SectorReceive(ctx, rmeta) + if tc.expectImportErrContains != "" { + require.ErrorContains(t, err, tc.expectImportErrContains) + return + } + require.NoError(t, err) // check that we see the imported sector @@ -218,4 +233,58 @@ func TestSectorImport(t *testing.T) { } } }))) + + t.Run("nil-commd", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.CommD = nil + } + testCase.expectImportErrContains = "both CommR/CommD cids need to be set for sectors in PreCommitting and later states" + }))) + t.Run("nil-commr", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.CommR = nil + } + testCase.expectImportErrContains = "both CommR/CommD cids need to be set for sectors in PreCommitting and later states" + }))) + + t.Run("nil-uns", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.DataUnsealed = nil + } + testCase.expectImportErrContains = "expected DataUnsealed to be set" + }))) + t.Run("nil-sealed", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.DataSealed = nil + } + testCase.expectImportErrContains = "expected DataSealed to be set" + }))) + t.Run("nil-cache", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.DataCache = nil + } + testCase.expectImportErrContains = "expected DataCache to be set" + }))) + + t.Run("bad-commd", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.CommD = meta.CommR + } + testCase.expectImportErrContains = "CommD cid has wrong prefix" + }))) + t.Run("bad-commr", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + meta.CommR = meta.CommD + } + testCase.expectImportErrContains = "CommR cid has wrong prefix" + }))) + + t.Run("bad-ticket", runTest(makeTest(func(testCase *testCase) { + testCase.mutateRemoteMeta = func(meta *api.RemoteSectorMeta) { + // flip one bit + meta.TicketValue[23] ^= 4 + } + testCase.expectImportErrContains = "tickets differ" + }))) + } diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index 13ee0ff02ba..d7eb5de7e8c 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -1,21 +1,28 @@ package sealing import ( + "bytes" "context" + "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" + "github.com/multiformats/go-multihash" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/crypto" + "github.com/filecoin-project/go-state-types/proof" "github.com/filecoin-project/go-statemachine" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/storage/sealer/storiface" ) -// todo m.inputLk? func (m *Sealing) Receive(ctx context.Context, meta api.RemoteSectorMeta) error { + m.inputLk.Lock() + defer m.inputLk.Unlock() + si, err := m.checkSectorMeta(ctx, meta) if err != nil { return err @@ -73,7 +80,13 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta } } + ts, err := m.Api.ChainHead(ctx) + if err != nil { + return SectorInfo{}, xerrors.Errorf("getting chain head: %w", err) + } + var info SectorInfo + var validatePoRep bool switch SectorState(meta.State) { case Proving, Available: @@ -91,21 +104,69 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta info.PreCommitMessage = meta.PreCommitMessage info.PreCommitTipSet = meta.PreCommitTipSet - // todo check + // check provided seed + if len(meta.SeedValue) != abi.RandomnessLength { + return SectorInfo{}, xerrors.Errorf("seed randomness had wrong length %d", len(meta.SeedValue)) + } + + maddrBuf := new(bytes.Buffer) + if err := m.maddr.MarshalCBOR(maddrBuf); err != nil { + return SectorInfo{}, xerrors.Errorf("marshal miner address for seed check: %w", err) + } + rand, err := m.Api.StateGetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_InteractiveSealChallengeSeed, meta.SeedEpoch, maddrBuf.Bytes(), ts.Key()) + if err != nil { + return SectorInfo{}, xerrors.Errorf("generating check seed: %w", err) + } + if !bytes.Equal(rand, meta.SeedValue) { + return SectorInfo{}, xerrors.Errorf("provided(%x) and generated(%x) seeds differ", meta.SeedValue, rand) + } + info.SeedValue = meta.SeedValue info.SeedEpoch = meta.SeedEpoch - // todo validate info.Proof = meta.CommitProof + validatePoRep = true fallthrough case PreCommitting: + // check provided ticket + if len(meta.TicketValue) != abi.RandomnessLength { + return SectorInfo{}, xerrors.Errorf("ticket randomness had wrong length %d", len(meta.TicketValue)) + } + + maddrBuf := new(bytes.Buffer) + if err := m.maddr.MarshalCBOR(maddrBuf); err != nil { + return SectorInfo{}, xerrors.Errorf("marshal miner address for ticket check: %w", err) + } + rand, err := m.Api.StateGetRandomnessFromTickets(ctx, crypto.DomainSeparationTag_SealRandomness, meta.TicketEpoch, maddrBuf.Bytes(), ts.Key()) + if err != nil { + return SectorInfo{}, xerrors.Errorf("generating check ticket: %w", err) + } + if !bytes.Equal(rand, meta.TicketValue) { + return SectorInfo{}, xerrors.Errorf("provided(%x) and generated(%x) tickets differ", meta.TicketValue, rand) + } + info.TicketValue = meta.TicketValue info.TicketEpoch = meta.TicketEpoch info.PreCommit1Out = meta.PreCommit1Out - info.CommD = meta.CommD // todo check cid prefixes + // check CommD/R + if meta.CommD == nil || meta.CommR == nil { + return SectorInfo{}, xerrors.Errorf("both CommR/CommD cids need to be set for sectors in PreCommitting and later states") + } + + dp := meta.CommD.Prefix() + if dp.Version != 1 || dp.Codec != cid.FilCommitmentUnsealed || dp.MhType != multihash.SHA2_256_TRUNC254_PADDED || dp.MhLength != 32 { + return SectorInfo{}, xerrors.Errorf("CommD cid has wrong prefix") + } + + rp := meta.CommR.Prefix() + if rp.Version != 1 || rp.Codec != cid.FilCommitmentSealed || rp.MhType != multihash.POSEIDON_BLS12_381_A1_FC1 || rp.MhLength != 32 { + return SectorInfo{}, xerrors.Errorf("CommR cid has wrong prefix") + } + + info.CommD = meta.CommD info.CommR = meta.CommR if meta.DataSealed == nil { @@ -118,15 +179,14 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta info.RemoteDataCache = meta.DataCache info.RemoteCommit1Endpoint = meta.RemoteCommit1Endpoint - // If we get a sector after PC2, assume that we're getting finalized sector data - // todo: maybe only set if C1 provider is set? - info.RemoteDataFinalized = true + // If we get a sector after PC2, and remote C1 endpoint is set, assume that we're getting finalized sector data + if info.RemoteCommit1Endpoint != "" { + info.RemoteDataFinalized = true + } fallthrough - case GetTicket: - fallthrough - case Packing: - info.Return = ReturnState(meta.State) // todo dedupe states + case GetTicket, Packing: + info.Return = ReturnState(meta.State) info.State = ReceiveSector info.SectorNumber = meta.Sector.Number @@ -142,6 +202,26 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta } info.RemoteDataUnsealed = meta.DataUnsealed + // some late checks which require previous checks + if validatePoRep { + ok, err := m.verif.VerifySeal(proof.SealVerifyInfo{ + SealProof: meta.Type, + SectorID: meta.Sector, + DealIDs: nil, + Randomness: meta.TicketValue, + InteractiveRandomness: meta.SeedValue, + Proof: meta.CommitProof, + SealedCID: *meta.CommR, + UnsealedCID: *meta.CommD, + }) + if err != nil { + return SectorInfo{}, xerrors.Errorf("validating seal proof: %w", err) + } + if !ok { + return SectorInfo{}, xerrors.Errorf("seal proof invalid") + } + } + return info, nil default: return SectorInfo{}, xerrors.Errorf("imported sector State in not supported") From fd7f5437f7c99caae01eabac60b9bd206de2f3a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 12:54:48 +0200 Subject: [PATCH 21/26] sector import: Remote Commit2 --- api/api_storage.go | 10 ++++ build/openrpc/miner.json.gz | Bin 15801 -> 15813 bytes cmd/lotus-miner/info.go | 2 +- documentation/en/api-v0-methods-miner.md | 3 +- itests/sector_import_full_test.go | 2 +- itests/sector_import_simple_test.go | 29 ++++++++++++ storage/pipeline/cbor_gen.go | 36 ++++++++++++++- storage/pipeline/fsm.go | 10 ++-- storage/pipeline/fsm_events.go | 5 ++ storage/pipeline/receive.go | 20 +++++++- storage/pipeline/sector_state.go | 4 +- storage/pipeline/states_failed.go | 4 +- storage/pipeline/states_sealing.go | 56 ++++++++++++++++++++--- storage/pipeline/types.go | 1 + 14 files changed, 162 insertions(+), 20 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 7b21adbb00f..4a8d2b501e8 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -571,6 +571,8 @@ type RemoteSectorMeta struct { // todo better doc RemoteCommit1Endpoint string + RemoteCommit2Endpoint string + // todo OnDone / OnStateChange } @@ -582,3 +584,11 @@ type RemoteCommit1Params struct { ProofType abi.RegisteredSealProof } + +type RemoteCommit2Params struct { + Sector abi.SectorID + ProofType abi.RegisteredSealProof + + // todo spec better + Commit1Out storiface.Commit1Out +} diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 61fcef75cdf265fe7db147deffcb16be1289e05c..3d42364ddb4334b44a3ef885e0d3e628097916d1 100644 GIT binary patch delta 5199 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 J10Kf<0|3Mv2m1g3 delta 5187 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 xs cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteCommit2Endpoint\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteCommit2Endpoint"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteCommit2Endpoint")); err != nil { + return err + } + + if len(t.RemoteCommit2Endpoint) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.RemoteCommit2Endpoint was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.RemoteCommit2Endpoint))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.RemoteCommit2Endpoint)); err != nil { + return err + } + // t.RemoteDataFinalized (bool) (bool) if len("RemoteDataFinalized") > cbg.MaxLength { return xerrors.Errorf("Value in field \"RemoteDataFinalized\" was too long") @@ -1550,6 +1573,17 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { t.RemoteCommit1Endpoint = string(sval) } + // t.RemoteCommit2Endpoint (string) (string) + case "RemoteCommit2Endpoint": + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.RemoteCommit2Endpoint = string(sval) + } // t.RemoteDataFinalized (bool) (bool) case "RemoteDataFinalized": diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index fb0d16b387d..fc0a93a8502 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -225,7 +225,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorRetryComputeProof{}, Committing), on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), ), - RemoteCommit1Failed: planOne( + RemoteCommitFailed: planOne( on(SectorRetryComputeProof{}, Committing), ), CommitFinalizeFailed: planOne( @@ -542,8 +542,8 @@ func (m *Sealing) plan(events []statemachine.Event, state *SectorInfo) (func(sta return m.handlePreCommitFailed, processed, nil case ComputeProofFailed: return m.handleComputeProofFailed, processed, nil - case RemoteCommit1Failed: - return m.handleRemoteCommit1Failed, processed, nil + case RemoteCommitFailed: + return m.handleRemoteCommitFailed, processed, nil case CommitFailed: return m.handleCommitFailed, processed, nil case CommitFinalizeFailed: @@ -671,8 +671,8 @@ func planCommitting(events []statemachine.Event, state *SectorInfo) (uint64, err return uint64(i + 1), nil case SectorComputeProofFailed: state.State = ComputeProofFailed - case SectorRemoteCommit1Failed: - state.State = RemoteCommit1Failed + case SectorRemoteCommit1Failed, SectorRemoteCommit2Failed: + state.State = RemoteCommitFailed case SectorSealPreCommit1Failed: state.State = SealPreCommit1Failed case SectorCommitFailed: diff --git a/storage/pipeline/fsm_events.go b/storage/pipeline/fsm_events.go index 5c975bddacd..1252296e0d5 100644 --- a/storage/pipeline/fsm_events.go +++ b/storage/pipeline/fsm_events.go @@ -224,6 +224,11 @@ type SectorRemoteCommit1Failed struct{ error } func (evt SectorRemoteCommit1Failed) FormatError(xerrors.Printer) (next error) { return evt.error } func (evt SectorRemoteCommit1Failed) apply(*SectorInfo) {} +type SectorRemoteCommit2Failed struct{ error } + +func (evt SectorRemoteCommit2Failed) FormatError(xerrors.Printer) (next error) { return evt.error } +func (evt SectorRemoteCommit2Failed) apply(*SectorInfo) {} + type SectorComputeProofFailed struct{ error } func (evt SectorComputeProofFailed) FormatError(xerrors.Printer) (next error) { return evt.error } diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index d7eb5de7e8c..f06848bcbf6 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -3,6 +3,7 @@ package sealing import ( "bytes" "context" + "net/url" "github.com/ipfs/go-cid" "github.com/ipfs/go-datastore" @@ -177,7 +178,24 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta } info.RemoteDataSealed = meta.DataSealed // todo make head requests to check? info.RemoteDataCache = meta.DataCache - info.RemoteCommit1Endpoint = meta.RemoteCommit1Endpoint + + if meta.RemoteCommit1Endpoint != "" { + // validate the url + if _, err := url.Parse(meta.RemoteCommit1Endpoint); err != nil { + return SectorInfo{}, xerrors.Errorf("parsing remote c1 endpoint url: %w", err) + } + + info.RemoteCommit1Endpoint = meta.RemoteCommit1Endpoint + } + + if meta.RemoteCommit2Endpoint != "" { + // validate the url + if _, err := url.Parse(meta.RemoteCommit2Endpoint); err != nil { + return SectorInfo{}, xerrors.Errorf("parsing remote c2 endpoint url: %w", err) + } + + info.RemoteCommit2Endpoint = meta.RemoteCommit2Endpoint + } // If we get a sector after PC2, and remote C1 endpoint is set, assume that we're getting finalized sector data if info.RemoteCommit1Endpoint != "" { diff --git a/storage/pipeline/sector_state.go b/storage/pipeline/sector_state.go index 136e72a1658..7a56c136b52 100644 --- a/storage/pipeline/sector_state.go +++ b/storage/pipeline/sector_state.go @@ -31,7 +31,7 @@ var ExistSectorStateList = map[SectorState]struct{}{ SealPreCommit2Failed: {}, PreCommitFailed: {}, ComputeProofFailed: {}, - RemoteCommit1Failed: {}, + RemoteCommitFailed: {}, CommitFailed: {}, PackingFailed: {}, FinalizeFailed: {}, @@ -125,7 +125,7 @@ const ( SealPreCommit2Failed SectorState = "SealPreCommit2Failed" PreCommitFailed SectorState = "PreCommitFailed" ComputeProofFailed SectorState = "ComputeProofFailed" - RemoteCommit1Failed SectorState = "RemoteCommit1Failed" + RemoteCommitFailed SectorState = "RemoteCommitFailed" CommitFailed SectorState = "CommitFailed" PackingFailed SectorState = "PackingFailed" // TODO: deprecated, remove FinalizeFailed SectorState = "FinalizeFailed" diff --git a/storage/pipeline/states_failed.go b/storage/pipeline/states_failed.go index 7597273b889..4952e30048d 100644 --- a/storage/pipeline/states_failed.go +++ b/storage/pipeline/states_failed.go @@ -184,13 +184,13 @@ func (m *Sealing) handleComputeProofFailed(ctx statemachine.Context, sector Sect return ctx.Send(SectorRetryComputeProof{}) } -func (m *Sealing) handleRemoteCommit1Failed(ctx statemachine.Context, sector SectorInfo) error { +func (m *Sealing) handleRemoteCommitFailed(ctx statemachine.Context, sector SectorInfo) error { if err := failedCooldown(ctx, sector); err != nil { return err } if sector.InvalidProofs > 1 { - log.Errorw("consecutive remote commit1 fails", "sector", sector.SectorNumber, "c1url", sector.RemoteCommit1Endpoint) + log.Errorw("consecutive remote commit fails", "sector", sector.SectorNumber, "c1url", sector.RemoteCommit1Endpoint, "c2url", sector.RemoteCommit2Endpoint) } return ctx.Send(SectorRetryComputeProof{}) diff --git a/storage/pipeline/states_sealing.go b/storage/pipeline/states_sealing.go index 428dd30a67b..04f214f3b7b 100644 --- a/storage/pipeline/states_sealing.go +++ b/storage/pipeline/states_sealing.go @@ -567,6 +567,7 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) var c2in storiface.Commit1Out if sector.RemoteCommit1Endpoint == "" { + // Local Commit1 cids := storiface.SectorCids{ Unsealed: *sector.CommD, Sealed: *sector.CommR, @@ -576,6 +577,8 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed(1): %w", err)}) } } else { + // Remote Commit1 + reqData := api.RemoteCommit1Params{ Ticket: sector.TicketValue, Seed: sector.SeedValue, @@ -611,9 +614,50 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) } } - proof, err := m.sealer.SealCommit2(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), c2in) - if err != nil { - return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed(2): %w", err)}) + var porepProof storiface.Proof + + if sector.RemoteCommit2Endpoint == "" { + // Local Commit2 + + porepProof, err = m.sealer.SealCommit2(sector.sealingCtx(ctx.Context()), m.minerSector(sector.SectorType, sector.SectorNumber), c2in) + if err != nil { + return ctx.Send(SectorComputeProofFailed{xerrors.Errorf("computing seal proof failed(2): %w", err)}) + } + } else { + // Remote Commit2 + + reqData := api.RemoteCommit2Params{ + ProofType: sector.SectorType, + Sector: m.minerSectorID(sector.SectorNumber), + + Commit1Out: c2in, + } + reqBody, err := json.Marshal(&reqData) + if err != nil { + return xerrors.Errorf("marshaling remote commit2 request: %w", err) + } + + req, err := http.NewRequest("POST", sector.RemoteCommit2Endpoint, bytes.NewReader(reqBody)) + if err != nil { + return ctx.Send(SectorRemoteCommit2Failed{xerrors.Errorf("creating new remote commit2 request: %w", err)}) + } + req.Header.Set("Content-Type", "application/json") + req = req.WithContext(ctx.Context()) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return ctx.Send(SectorRemoteCommit2Failed{xerrors.Errorf("requesting remote commit2: %w", err)}) + } + + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return ctx.Send(SectorRemoteCommit2Failed{xerrors.Errorf("remote commit2 received non-200 http response %s", resp.Status)}) + } + + porepProof, err = io.ReadAll(resp.Body) // todo some len constraint + if err != nil { + return ctx.Send(SectorRemoteCommit2Failed{xerrors.Errorf("reading commit2 response: %w", err)}) + } } { @@ -623,19 +667,19 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) return nil } - if err := m.checkCommit(ctx.Context(), sector, proof, ts.Key()); err != nil { + if err := m.checkCommit(ctx.Context(), sector, porepProof, ts.Key()); err != nil { return ctx.Send(SectorCommitFailed{xerrors.Errorf("commit check error: %w", err)}) } } if cfg.FinalizeEarly { return ctx.Send(SectorProofReady{ - Proof: proof, + Proof: porepProof, }) } return ctx.Send(SectorCommitted{ - Proof: proof, + Proof: porepProof, }) } diff --git a/storage/pipeline/types.go b/storage/pipeline/types.go index 8ae2cdeb1fd..93d0ce2191e 100644 --- a/storage/pipeline/types.go +++ b/storage/pipeline/types.go @@ -100,6 +100,7 @@ type SectorInfo struct { RemoteDataSealed *storiface.SectorData RemoteDataCache *storiface.SectorData RemoteCommit1Endpoint string + RemoteCommit2Endpoint string RemoteDataFinalized bool // Debug From 7b0b5fbbb3a7d8311858c09745185dc8f5483596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 13:31:03 +0200 Subject: [PATCH 22/26] tarutil: Strict header checks --- storage/sealer/storiface/storage.go | 2 +- storage/sealer/tarutil/systar.go | 68 +++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/storage/sealer/storiface/storage.go b/storage/sealer/storiface/storage.go index 975011a0b98..5246a1a1a14 100644 --- a/storage/sealer/storiface/storage.go +++ b/storage/sealer/storiface/storage.go @@ -131,7 +131,7 @@ type SectorData struct { // URL to the sector data // For sealed/unsealed sector, lotus expects octet-stream - // For cache, lotus expects a tar archive with cache files (todo maybe use not-tar; specify what files with what paths must be present) + // For cache, lotus expects a tar archive with cache files // Valid schemas: // - http:// / https:// URL string diff --git a/storage/sealer/tarutil/systar.go b/storage/sealer/tarutil/systar.go index 09ffa5e97ca..534a9a64ab9 100644 --- a/storage/sealer/tarutil/systar.go +++ b/storage/sealer/tarutil/systar.go @@ -13,6 +13,63 @@ import ( var log = logging.Logger("tarutil") // nolint +var CacheFileConstraints = map[string]int64{ + "p_aux": 64, + "t_aux": 10240, + + "sc-02-data-tree-r-last.dat": 10_000_000, // small sectors + + "sc-02-data-tree-r-last-0.dat": 10_000_000, + "sc-02-data-tree-r-last-1.dat": 10_000_000, + "sc-02-data-tree-r-last-2.dat": 10_000_000, + "sc-02-data-tree-r-last-3.dat": 10_000_000, + "sc-02-data-tree-r-last-4.dat": 10_000_000, + "sc-02-data-tree-r-last-5.dat": 10_000_000, + "sc-02-data-tree-r-last-6.dat": 10_000_000, + "sc-02-data-tree-r-last-7.dat": 10_000_000, + + "sc-02-data-tree-r-last-8.dat": 10_000_000, + "sc-02-data-tree-r-last-9.dat": 10_000_000, + "sc-02-data-tree-r-last-10.dat": 10_000_000, + "sc-02-data-tree-r-last-11.dat": 10_000_000, + "sc-02-data-tree-r-last-12.dat": 10_000_000, + "sc-02-data-tree-r-last-13.dat": 10_000_000, + "sc-02-data-tree-r-last-14.dat": 10_000_000, + "sc-02-data-tree-r-last-15.dat": 10_000_000, + + "sc-02-data-layer-1.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-2.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-3.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-4.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-5.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-6.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-7.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-8.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-9.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-10.dat": 65 << 30, // 1x sector size + small buffer + "sc-02-data-layer-11.dat": 65 << 30, // 1x sector size + small buffer + + "sc-02-data-tree-c-0.dat": 5 << 30, // ~4.6G + "sc-02-data-tree-c-1.dat": 5 << 30, + "sc-02-data-tree-c-2.dat": 5 << 30, + "sc-02-data-tree-c-3.dat": 5 << 30, + "sc-02-data-tree-c-4.dat": 5 << 30, + "sc-02-data-tree-c-5.dat": 5 << 30, + "sc-02-data-tree-c-6.dat": 5 << 30, + "sc-02-data-tree-c-7.dat": 5 << 30, + + "sc-02-data-tree-c-8.dat": 5 << 30, + "sc-02-data-tree-c-9.dat": 5 << 30, + "sc-02-data-tree-c-10.dat": 5 << 30, + "sc-02-data-tree-c-11.dat": 5 << 30, + "sc-02-data-tree-c-12.dat": 5 << 30, + "sc-02-data-tree-c-13.dat": 5 << 30, + "sc-02-data-tree-c-14.dat": 5 << 30, + "sc-02-data-tree-c-15.dat": 5 << 30, + + "sc-02-data-tree-d.dat": 130 << 30, // 2x sector size, ~130G accunting for small buffer on 64G sectors +} + func ExtractTar(body io.Reader, dir string, buf []byte) (int64, error) { if err := os.MkdirAll(dir, 0755); err != nil { // nolint return 0, xerrors.Errorf("mkdir: %w", err) @@ -38,9 +95,14 @@ func ExtractTar(body io.Reader, dir string, buf []byte) (int64, error) { return read, xerrors.Errorf("creating file %s: %w", filepath.Join(dir, header.Name), err) } - // This data is coming from a trusted source, no need to check the size. - // TODO: now it's actually not coming from a trusted source, check size / paths - //nolint:gosec + sz, found := CacheFileConstraints[header.Name] + if !found { + return read, xerrors.Errorf("tar file %#v isn't expected") + } + if header.Size > sz { + return read, xerrors.Errorf("tar file %#v is bigger than expected: %d > %d", header.Name, header.Size, sz) + } + r, err := io.CopyBuffer(f, tr, buf) read += r if err != nil { From 09ab83767d9acc7cf850096053f4f8455d396b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 13:42:04 +0200 Subject: [PATCH 23/26] sector import: Fix test build --- itests/sector_import_full_test.go | 150 +++++++++++++++++++++++++++- itests/sector_import_simple_test.go | 20 +--- 2 files changed, 152 insertions(+), 18 deletions(-) diff --git a/itests/sector_import_full_test.go b/itests/sector_import_full_test.go index 3e67b94fca6..b26a24145a3 100644 --- a/itests/sector_import_full_test.go +++ b/itests/sector_import_full_test.go @@ -3,7 +3,12 @@ package itests import ( "bytes" "context" + "encoding/json" "fmt" + lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/types" + spaths "github.com/filecoin-project/lotus/storage/paths" + "github.com/filecoin-project/lotus/storage/sealer/tarutil" "net/http" "net/http/httptest" "os" @@ -39,7 +44,7 @@ func TestSectorImport(t *testing.T) { makeTest := func(mut func(*testCase)) *testCase { tc := &testCase{ - c1handler: remoteCommit1, + c1handler: testRemoteCommit1, } mut(tc) return tc @@ -72,7 +77,11 @@ func TestSectorImport(t *testing.T) { mid, err := address.IDFromAddress(maddr) require.NoError(t, err) - spt, err := currentSealProof(ctx, client, maddr) + mi, err := client.StateMinerInfo(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + ver, err := client.StateNetworkVersion(ctx, types.EmptyTSK) + require.NoError(t, err) + spt, err := lminer.PreferredSealProofTypeFromWindowPoStType(ver, mi.WindowPoStProofType) require.NoError(t, err) ssize, err := spt.SectorSize() @@ -141,8 +150,9 @@ func TestSectorImport(t *testing.T) { // start http server serving sector data m := mux.NewRouter() - m.HandleFunc("/sectors/{type}/{id}", remoteGetSector(sectorDir)).Methods("GET") + m.HandleFunc("/sectors/{type}/{id}", testRemoteGetSector(sectorDir)).Methods("GET") m.HandleFunc("/sectors/{id}/commit1", tc.c1handler(sealer)).Methods("POST") + m.HandleFunc("/commit2", testRemoteCommit2(sealer)).Methods("POST") srv := httptest.NewServer(m) unsealedURL := fmt.Sprintf("%s/sectors/unsealed/s-t0%d-%d", srv.URL, mid, snum) @@ -288,3 +298,137 @@ func TestSectorImport(t *testing.T) { }))) } + +// note: stuff below is almost the same as in _simple version of this file; We need +// to copy it because on Circle we can't call those functions between test files, +// and for the _simple test we want everything in one file to make it easy to follow + +func testRemoteCommit1(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + // validate sector id + id, err := storiface.ParseSectorID(vars["id"]) + if err != nil { + w.WriteHeader(500) + return + } + + var params api.RemoteCommit1Params + if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { + w.WriteHeader(500) + return + } + + sref := storiface.SectorRef{ + ID: id, + ProofType: params.ProofType, + } + + ssize, err := params.ProofType.SectorSize() + if err != nil { + w.WriteHeader(500) + return + } + + p, err := s.SealCommit1(r.Context(), sref, params.Ticket, params.Seed, []abi.PieceInfo{ + { + Size: abi.PaddedPieceSize(ssize), + PieceCID: params.Unsealed, + }, + }, storiface.SectorCids{ + Unsealed: params.Unsealed, + Sealed: params.Sealed, + }) + if err != nil { + w.WriteHeader(500) + return + } + + if _, err := w.Write(p); err != nil { + fmt.Println("c1 write error") + } + } +} + +func testRemoteCommit2(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + var params api.RemoteCommit2Params + if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { + w.WriteHeader(500) + return + } + + sref := storiface.SectorRef{ + ID: params.Sector, + ProofType: params.ProofType, + } + + p, err := s.SealCommit2(r.Context(), sref, params.Commit1Out) + if err != nil { + fmt.Println("c2 error: ", err) + w.WriteHeader(500) + return + } + + if _, err := w.Write(p); err != nil { + fmt.Println("c2 write error") + } + } +} + +func testRemoteGetSector(sectorRoot string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + + // validate sector id + id, err := storiface.ParseSectorID(vars["id"]) + if err != nil { + w.WriteHeader(500) + return + } + + // validate type + _, err = spaths.FileTypeFromString(vars["type"]) + if err != nil { + w.WriteHeader(500) + return + } + + typ := vars["type"] + if typ == "cache" { + // if cache is requested, send the finalized cache we've created above + typ = "fin-cache" + } + + path := filepath.Join(sectorRoot, typ, vars["id"]) + + stat, err := os.Stat(path) + if err != nil { + w.WriteHeader(500) + return + } + + if stat.IsDir() { + if _, has := r.Header["Range"]; has { + w.WriteHeader(500) + return + } + + w.Header().Set("Content-Type", "application/x-tar") + w.WriteHeader(200) + + err := tarutil.TarDirectory(path, w, make([]byte, 1<<20)) + if err != nil { + return + } + } else { + w.Header().Set("Content-Type", "application/octet-stream") + // will do a ranged read over the file at the given path if the caller has asked for a ranged read in the request headers. + http.ServeFile(w, r, path) + } + + fmt.Printf("served sector file/dir, sectorID=%+v, fileType=%s, path=%s\n", id, vars["type"], path) + } +} diff --git a/itests/sector_import_simple_test.go b/itests/sector_import_simple_test.go index 419415c1bb7..f75d0d84269 100644 --- a/itests/sector_import_simple_test.go +++ b/itests/sector_import_simple_test.go @@ -57,7 +57,11 @@ func TestSectorImportAfterPC2(t *testing.T) { mid, err := address.IDFromAddress(maddr) require.NoError(t, err) - spt, err := currentSealProof(ctx, client, maddr) + mi, err := client.StateMinerInfo(ctx, maddr, types.EmptyTSK) + require.NoError(t, err) + ver, err := client.StateNetworkVersion(ctx, types.EmptyTSK) + require.NoError(t, err) + spt, err := lminer.PreferredSealProofTypeFromWindowPoStType(ver, mi.WindowPoStProofType) require.NoError(t, err) ssize, err := spt.SectorSize() @@ -316,17 +320,3 @@ func remoteGetSector(sectorRoot string) func(w http.ResponseWriter, r *http.Requ fmt.Printf("served sector file/dir, sectorID=%+v, fileType=%s, path=%s\n", id, vars["type"], path) } } - -func currentSealProof(ctx context.Context, api api.FullNode, maddr address.Address) (abi.RegisteredSealProof, error) { - mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK) - if err != nil { - return 0, err - } - - ver, err := api.StateNetworkVersion(ctx, types.EmptyTSK) - if err != nil { - return 0, err - } - - return lminer.PreferredSealProofTypeFromWindowPoStType(ver, mi.WindowPoStProofType) -} From a0fa5ab8f4d706b1c4e8a4614e2dbe62265429a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 14:38:23 +0200 Subject: [PATCH 24/26] sector import: RemoteSealingDoneEndpoint --- api/api_storage.go | 21 +++++- build/openrpc/miner.json.gz | Bin 15813 -> 15826 bytes documentation/en/api-v0-methods-miner.md | 3 +- itests/kit/node_miner.go | 2 +- itests/sector_import_full_test.go | 78 ++++++++++++++++++++--- itests/sector_import_simple_test.go | 27 +++++++- storage/pipeline/cbor_gen.go | 36 ++++++++++- storage/pipeline/fsm.go | 61 ++++++++++++++++-- storage/pipeline/fsm_events.go | 3 + storage/pipeline/receive.go | 9 +++ storage/pipeline/types.go | 13 ++-- 11 files changed, 226 insertions(+), 27 deletions(-) diff --git a/api/api_storage.go b/api/api_storage.go index 4a8d2b501e8..7c6fe7cdd38 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -568,12 +568,17 @@ type RemoteSectorMeta struct { // SEALING SERVICE HOOKS // URL - // todo better doc + // RemoteCommit1Endpoint is an URL of POST endpoint which lotus will call requesting Commit1 (seal_commit_phase1) + // request body will be json-serialized RemoteCommit1Params struct RemoteCommit1Endpoint string + // RemoteCommit2Endpoint is an URL of POST endpoint which lotus will call requesting Commit2 (seal_commit_phase2) + // request body will be json-serialized RemoteCommit2Params struct RemoteCommit2Endpoint string - // todo OnDone / OnStateChange + // RemoteSealingDoneEndpoint is called after the sector exists the sealing pipeline + // request body will be json-serialized RemoteSealingDoneParams struct + RemoteSealingDoneEndpoint string } type RemoteCommit1Params struct { @@ -592,3 +597,15 @@ type RemoteCommit2Params struct { // todo spec better Commit1Out storiface.Commit1Out } + +type RemoteSealingDoneParams struct { + // Successful is true if the sector has entered state considered as "successfully sealed" + Successful bool + + // State is the state the sector has entered + // For example "Proving" / "Removing" + State string + + // Optional commit message CID + CommitMessage *cid.Cid +} diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 3d42364ddb4334b44a3ef885e0d3e628097916d1..f2bd95d2fb4f845af7ee46ac47065bd04a687dad 100644 GIT binary patch literal 15826 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 literal 15813 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 cbg.MaxLength { + return xerrors.Errorf("Value in field \"RemoteSealingDoneEndpoint\" was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len("RemoteSealingDoneEndpoint"))); err != nil { + return err + } + if _, err := io.WriteString(w, string("RemoteSealingDoneEndpoint")); err != nil { + return err + } + + if len(t.RemoteSealingDoneEndpoint) > cbg.MaxLength { + return xerrors.Errorf("Value in field t.RemoteSealingDoneEndpoint was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajTextString, uint64(len(t.RemoteSealingDoneEndpoint))); err != nil { + return err + } + if _, err := io.WriteString(w, string(t.RemoteSealingDoneEndpoint)); err != nil { + return err + } + // t.RemoteDataFinalized (bool) (bool) if len("RemoteDataFinalized") > cbg.MaxLength { return xerrors.Errorf("Value in field \"RemoteDataFinalized\" was too long") @@ -1584,6 +1607,17 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { t.RemoteCommit2Endpoint = string(sval) } + // t.RemoteSealingDoneEndpoint (string) (string) + case "RemoteSealingDoneEndpoint": + + { + sval, err := cbg.ReadString(cr) + if err != nil { + return err + } + + t.RemoteSealingDoneEndpoint = string(sval) + } // t.RemoteDataFinalized (bool) (bool) case "RemoteDataFinalized": diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index fc0a93a8502..264a6ca49e7 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -7,6 +7,7 @@ import ( "context" "encoding/json" "fmt" + "net/http" "reflect" "time" @@ -14,6 +15,8 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-statemachine" + + "github.com/filecoin-project/lotus/api" ) func (m *Sealing) Plan(events []statemachine.Event, user interface{}) (interface{}, uint64, error) { @@ -142,8 +145,8 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto ), FinalizeSector: planOne( - on(SectorFinalized{}, Proving), - on(SectorFinalizedAvailable{}, Available), + onWithCB(SectorFinalized{}, Proving, maybeNotifyRemoteDone(true, "Proving")), + onWithCB(SectorFinalizedAvailable{}, Available, maybeNotifyRemoteDone(true, "Available")), on(SectorFinalizeFailed{}, FinalizeFailed), ), @@ -218,7 +221,7 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorRetryWaitSeed{}, WaitSeed), on(SectorSealPreCommit1Failed{}, SealPreCommit1Failed), on(SectorPreCommitLanded{}, WaitSeed), - on(SectorDealsExpired{}, DealsExpired), + onWithCB(SectorDealsExpired{}, DealsExpired, maybeNotifyRemoteDone(false, "DealsExpired")), on(SectorInvalidDealIDs{}, RecoverDealIDs), ), ComputeProofFailed: planOne( @@ -241,9 +244,9 @@ var fsmPlanners = map[SectorState]func(events []statemachine.Event, state *Secto on(SectorRetryPreCommit{}, PreCommitting), on(SectorRetryCommitWait{}, CommitWait), on(SectorRetrySubmitCommit{}, SubmitCommit), - on(SectorDealsExpired{}, DealsExpired), + onWithCB(SectorDealsExpired{}, DealsExpired, maybeNotifyRemoteDone(false, "DealsExpired")), on(SectorInvalidDealIDs{}, RecoverDealIDs), - on(SectorTicketExpired{}, Removing), + onWithCB(SectorTicketExpired{}, Removing, maybeNotifyRemoteDone(false, "Removing")), ), FinalizeFailed: planOne( on(SectorRetryFinalize{}, FinalizeSector), @@ -736,6 +739,16 @@ func on(mut mutator, next SectorState) func() (mutator, func(*SectorInfo) (bool, } } +func onWithCB(mut mutator, next SectorState, cb func(info *SectorInfo)) func() (mutator, func(*SectorInfo) (bool, error)) { + return func() (mutator, func(*SectorInfo) (bool, error)) { + return mut, func(state *SectorInfo) (bool, error) { + cb(state) + state.State = next + return false, nil + } + } +} + // like `on`, but doesn't change state func apply(mut mutator) func() (mutator, func(*SectorInfo) (bool, error)) { return func() (mutator, func(*SectorInfo) (bool, error)) { @@ -812,3 +825,41 @@ func planOneOrIgnore(ts ...func() (mut mutator, next func(*SectorInfo) (more boo return cnt, nil } } + +func maybeNotifyRemoteDone(success bool, state string) func(*SectorInfo) { + return func(sector *SectorInfo) { + if sector.RemoteSealingDoneEndpoint == "" { + return + } + + reqData := api.RemoteSealingDoneParams{ + Successful: success, + State: state, + CommitMessage: sector.CommitMessage, + } + reqBody, err := json.Marshal(&reqData) + if err != nil { + log.Errorf("marshaling remote done notification request params: %s", err) + return + } + + req, err := http.NewRequest("POST", sector.RemoteSealingDoneEndpoint, bytes.NewReader(reqBody)) + if err != nil { + log.Errorf("creating new remote done notification request: %s", err) + return + } + req.Header.Set("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(req) + if err != nil { + log.Errorf("sending remote done notification: %s", err) + return + } + + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + log.Errorf("remote done notification received non-200 http response %s", resp.Status) + return + } + } +} diff --git a/storage/pipeline/fsm_events.go b/storage/pipeline/fsm_events.go index 1252296e0d5..57396f7c347 100644 --- a/storage/pipeline/fsm_events.go +++ b/storage/pipeline/fsm_events.go @@ -525,6 +525,9 @@ func (evt SectorTerminateFailed) apply(*SectorInfo) {} type SectorRemove struct{} func (evt SectorRemove) applyGlobal(state *SectorInfo) bool { + // because this event is global we need to send the notification here instead through an fsm callback + maybeNotifyRemoteDone(false, "Removing")(state) + state.State = Removing return true } diff --git a/storage/pipeline/receive.go b/storage/pipeline/receive.go index f06848bcbf6..e5eec5ab925 100644 --- a/storage/pipeline/receive.go +++ b/storage/pipeline/receive.go @@ -211,6 +211,15 @@ func (m *Sealing) checkSectorMeta(ctx context.Context, meta api.RemoteSectorMeta info.Pieces = meta.Pieces info.SectorType = meta.Type + if meta.RemoteSealingDoneEndpoint != "" { + // validate the url + if _, err := url.Parse(meta.RemoteSealingDoneEndpoint); err != nil { + return SectorInfo{}, xerrors.Errorf("parsing remote sealing-done endpoint url: %w", err) + } + + info.RemoteSealingDoneEndpoint = meta.RemoteSealingDoneEndpoint + } + if err := checkPieces(ctx, m.maddr, meta.Sector.Number, meta.Pieces, m.Api, false); err != nil { return SectorInfo{}, xerrors.Errorf("checking pieces: %w", err) } diff --git a/storage/pipeline/types.go b/storage/pipeline/types.go index 93d0ce2191e..ad51b5bf9ea 100644 --- a/storage/pipeline/types.go +++ b/storage/pipeline/types.go @@ -96,12 +96,13 @@ type SectorInfo struct { TerminatedAt abi.ChainEpoch // Remote import - RemoteDataUnsealed *storiface.SectorData - RemoteDataSealed *storiface.SectorData - RemoteDataCache *storiface.SectorData - RemoteCommit1Endpoint string - RemoteCommit2Endpoint string - RemoteDataFinalized bool + RemoteDataUnsealed *storiface.SectorData + RemoteDataSealed *storiface.SectorData + RemoteDataCache *storiface.SectorData + RemoteCommit1Endpoint string + RemoteCommit2Endpoint string + RemoteSealingDoneEndpoint string + RemoteDataFinalized bool // Debug LastErr string From d4c2d149b2f3ed35b0120933af068e4a30f10da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 9 Sep 2022 14:57:56 +0200 Subject: [PATCH 25/26] sector import: Fix lint --- build/openrpc/full.json.gz | Bin 28355 -> 28353 bytes build/openrpc/gateway.json.gz | Bin 4943 -> 4943 bytes build/openrpc/miner.json.gz | Bin 15826 -> 16010 bytes build/openrpc/worker.json.gz | Bin 5256 -> 5256 bytes itests/sector_import_full_test.go | 2 +- storage/pipeline/fsm.go | 2 +- storage/pipeline/states_sealing.go | 4 ++-- storage/sealer/tarutil/systar.go | 4 +++- 8 files changed, 7 insertions(+), 5 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 942fb190afe07f2f1df19e969c1a4b3db8e725ac..a10f20b232dc9673595378b778665671e30fece0 100644 GIT binary patch delta 27518 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 delta 27513 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 diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index b3db3736c003becfd4c77c46a95bd6af4b99ca32..23f63725bf8aa5c7cdaab66908d004f63bf5659b 100644 GIT binary patch delta 3130 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 atr|!PkN+Q delta 15096 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 an(>1}RP=3 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index f60f1fc3a794c45d1ce14f3b5d957fbb2986c5e9..90167b6e09ec40c5a7dd6f5a19b1b5c28082a2fa 100644 GIT binary patch delta 2505 zcmV;)2{!hKDTpbs4FiAQ8?!d0xd$_>Gi-8Fk1$sr^T=Zn>R~J*thFf;v1`XhAgN=n z$8CBg6-s4KzS;(~w!?gV`8DF%!qmQN^ANN!nR&>4zy><;{K~u&uQOG8s@CbLn%7NLi$n~UCvb3x<(?bVRW_TAd1?v97sd3wKBbdmM{a*wO5ar}r*bk_(P=aj=w)xuF=0MA#2$(<%|3sI_v9JNJ9TQUCu#LUW)T$OO;UuEW|s@jc#?jfPCZ1~NU6Fk`MYNR?{z$8gQM3s zC6?*-puT@gE z1-Kp$Tu1$EaQ%V^av=?|<6mg?57%B)h$qP{hZk}UYVmt+9JnQbBiynCEuV-7GeF>4~LW3jX-HrU&a1C4uR zZfjwk^&UWC0tmjbRCDOfyYa>NC+URgIh?N4$xmn?s6Be-e6Z4>HlP#DyGIM>Z~Mo8 zoaG|QUO0bG7E`pEYWfsw%hh1HM7sK*OKY)CEf8HGdVuKTL9;0aR{>cW5gxE<(jFpA zFqs|3gf}HT7ZuK=z&CdeE3_Laz7+G_2wy;bQ$<&0ypfK2)^JckcLm)QbXU;bEV}!8 zsbk7*XBcHVMJY4n;)a!N?*@j0X>U9l zO*&|*DIMJ$qRvD^MrRBM>Ts%0U>}YoS^5j%*_;M9JAAbbX!#YTu9rB2``Q3@+|QE}4_1HMxQ5Cg z&$uG1s@ygf$;;1NnQ~rWWT100wYhm~r0V8aYrK7ev$n(jTgF*qdR&&VZaAu@%95Y? zEa>DqmY=G#-l!yn3w^2RRKbA-2NoRoV3_U=vtjxQLF>%Fj(|7NGLn-Qq678_txG>D zm>|#dcbC~?A0web@dHYw(35}Ip4fX1DmlX@?~Ze%DNR9sytl*-vjG1>@K0MvxybcT zj~_lX6PaEq`n+hXw$R#Ncx%(!pMuRDi_MkX``m#?NyoU|m#Jwu7$2&$JWg-CtDJ8{ zqus!hv(7~qLCys^f63%r9ql9Mym6nAoYhaw2>I&oOIn#vHx{`WZ=iozKx>(Wwt+)u zDe_C?l>+eu;=MM+({j#Iw7bbU!+VoPke4Vd@_ z)|JFci`X|4L`4vldWcFt=isjx@T~iC2H^FucQ0!E5UHyM5>0eZ}`Eah9J9CQAyo2jY=1#{0Xk!)711NZRvayaX_|2w(&LR5;d%#1KVlulW3%CLl-Xnhi!4y3L4;eNwJwR>1 z+&i2>ir60%diQ{-yScP#{M3QX~Jxo zP?K*aVXlLXWLJB(dHmtx*$lbB3lkoU4sT9h#yMY3hhIH?G)@2HV_vn1=gyy=yO_+1 z6e(WL!TOXEE8lbl?Ep&eQ7m z;N1c`H@juJ^Urs|xD_r_L<%iftH>#tZ{;E`eHIQ2QNSpY%EtXzHDbsSGFm@kCV(y)s%9?zxC%jc2n_Jtx@h z59r;04innP!EJK~uXXQfMfR+uFnyWX$;Pgj zmTpYz^l80k3Q`!M@Va9MMx&f<(BQLCKfIOGdLlWiN6uXn2bv}_KdmS_Cnox_J%D2K z#;@QC|3v=56PX_e^ef&77HL6Kad+`f630!50KAd`cqzl!e_%ULL`d|0X+>AGkzVzd z>AinvOQa0B!Ir3XG$Vaz#H;&SBYgmaxE4U%r6qz@MX+jZgmat|LloLFC)o^hWlz+$ z?jfJ*g-Hr%UYLT5-R-1mWTz*ut9H*D!cna^(v`|c+D?TWD>*?*e?d(Dy~K!es^m5w zUjWB8+o3C9(fYI1Z&%gCvW)0e4A=AL1#ZJouEV*O%7o TyY>GE00960aeL+GXE6Z)tIN5S delta 2505 zcmV;)2{!hKDTpbs4Fi9#3|O1e+=Cg`88$hoN0=**dE~JO^)MC@*4h+_*fnayA+ou{ zu9BcrSXJIFsfkj&NY|Z4TH(5d>lUuN7T4Vy=D2SAkyth~gRuzBjLVCs3gDeePHfxq z=Zy>K+$0k*K^fb>OTMV$`ctAdh5}ig5}j0v31v&{ybTjdW&nSs28fj&0a}(1K~l$D zkK6Q0DwN8ee6(D> zd>q|=`DpkZ|IIcLCyDljZHhNfL)v&mgrrc>8Ev0o*$daXq zP$B!Pb+aVmAxLNrDVa#~!x%_1nmo1_RS%`O+5@g)5|oqC9}ky3S8@^{Vr-|KkH21l=N zN-WduL4AMK`mACEhyY#zysr&-2fbq84acGy;s%+I1+_t`O=Ik~jRIU-W~u^Q1-J@u z72tY2a2=}I;Q9p-y*zBHRlM`rjt8WT(i`pyTw`IoM z2KWv2djD#-ZzP0*a}yDYr#NHf`wW}FWz~C#Q09N2J!DNgL7E9Bv%ug81<*8Ipg(P1Q2{R}XET(8R)$}RWmaD;XiFEZrm)2sPS|GYW^Z?OETC*tzR{>ZX5gzM%i7>%r zb{G@hl<-_sIFkb3+&Qe!Zlw59%y%Pv0rgE4U6t`hI_g=&K?U6vbXU+_L3gw0?(3zF zDYu~k8{SBioHs?yPfXUP3bC4Vp?+-xPsQw^9U8wai@GK-g2- zTsCUp_vzF_l#P_C%hDD8iGttNclS3Xmg)AOzGvN+7XT{&_O$`*NX?TI4_1HNxW-zZ zaYa^Dxos?xm!G*Z<-EYiK<8v?bMw|n)y=Wic>4rrZHN80jI+k{xGZDca8yl|B|r07 z(8+ZyKUHVFQAr9H`cl!Uf&&W(Y-3 zCdl*r-DURJ$4F>U{D4v^^dx__C-$C$O3tv!yW<>bN>h*@?=7*zEWp1I{L>avE^__T zq=s!MeLgiq9TY&Jw!#zIru9Exm9N8yUf)m=sV1>Hb>vd@GQ(k%+yaVMjht{d?B|?tcZKM$#McIHyV+#SBa9Q}t<8k3U>In;{o?VZwva;mzsGDCf)R@T;efrs-1*aU7n50$ zBE`!&Sf5g2<$HhL+UC*zYGNry5jz{Z&cof_oK}x>K35DC;4`Aon19UZlu~NF&Ccl+ z6S-^B=BPA{oG$;?v}dH`e2*9F@B`dpq<}*`W2C5B)k*lrSFPc_yiZvI9XLR@^R)Us zc(;Jg&2E|Q{PSHfZiUMfkwOdBDsoEZTe*nK--sv8ku!hQ)A{MjtZA0Iq2p9KF(HK~ z4y1E`;j-Y8yqdy}+iDDIUg&6`5tqnBh6UY2tRh}Up40y&I_Ca9)xPD3tkP@3ft1M4 zvh5V>f^w+P)5c>66}_Vl)P6_TC%w)DntEqqD#J;CJW*9cuZ$LjdoE&GQso?lIH?P0DhM#?+X0^_1JPr*{nEJ?@0tJ4jCxA8<3 zlEv)f~iJo;2Dix z8uV#hH09Wqyl=jdUp&{mBifRjMeZ;K=-e(9MMHlexNYv>weCHw$exuHrY|!)+1M4+ z(v4}IKCSmmK?)-jUU%%kXpplF8hkeDhqrQCPb6pc$hm9cK+{C#rxiu##6&-~2T*L@ z_!V5?pU6LWBJ<;be#INXA}wet?k?U*;}t2(yQJw zz4w1?iIgEX*b=plW~2{|cy(WEqz_;a*8+&Uv_!C~2v)6)aE@|fh(cTDB%5Kb?1|de zJ>*lpFi8Q;3sZ2hyPZ^x?DXVy)$VyiII8tVx>6ZQTdI)boFJvYAg2FbVnjJra+{AY zfMc8O&=s&~{n_fbt7>A|#=QrYgklTOIdUlxfGz?g2-fs~yClR9@f1-WTuL=oRB64w TTmOFm00960=axf}XE6Z)2TSY& diff --git a/itests/sector_import_full_test.go b/itests/sector_import_full_test.go index 761bee3a582..00a29b82b5c 100644 --- a/itests/sector_import_full_test.go +++ b/itests/sector_import_full_test.go @@ -259,7 +259,7 @@ func TestSectorImport(t *testing.T) { return } - remoteCommit1(s)(w, r) + testRemoteCommit1(s, m)(w, r) } } }))) diff --git a/storage/pipeline/fsm.go b/storage/pipeline/fsm.go index 264a6ca49e7..46c0fd9b572 100644 --- a/storage/pipeline/fsm.go +++ b/storage/pipeline/fsm.go @@ -855,7 +855,7 @@ func maybeNotifyRemoteDone(success bool, state string) func(*SectorInfo) { return } - defer resp.Body.Close() + defer resp.Body.Close() //nolint:errcheck if resp.StatusCode != http.StatusOK { log.Errorf("remote done notification received non-200 http response %s", resp.Status) diff --git a/storage/pipeline/states_sealing.go b/storage/pipeline/states_sealing.go index 04f214f3b7b..786334ab843 100644 --- a/storage/pipeline/states_sealing.go +++ b/storage/pipeline/states_sealing.go @@ -602,7 +602,7 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("requesting remote commit1: %w", err)}) } - defer resp.Body.Close() + defer resp.Body.Close() //nolint:errcheck if resp.StatusCode != http.StatusOK { return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("remote commit1 received non-200 http response %s", resp.Status)}) @@ -648,7 +648,7 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) return ctx.Send(SectorRemoteCommit2Failed{xerrors.Errorf("requesting remote commit2: %w", err)}) } - defer resp.Body.Close() + defer resp.Body.Close() //nolint:errcheck if resp.StatusCode != http.StatusOK { return ctx.Send(SectorRemoteCommit2Failed{xerrors.Errorf("remote commit2 received non-200 http response %s", resp.Status)}) diff --git a/storage/sealer/tarutil/systar.go b/storage/sealer/tarutil/systar.go index 534a9a64ab9..bf5f6c000a6 100644 --- a/storage/sealer/tarutil/systar.go +++ b/storage/sealer/tarutil/systar.go @@ -103,7 +103,9 @@ func ExtractTar(body io.Reader, dir string, buf []byte) (int64, error) { return read, xerrors.Errorf("tar file %#v is bigger than expected: %d > %d", header.Name, header.Size, sz) } - r, err := io.CopyBuffer(f, tr, buf) + ltr := io.LimitReader(tr, header.Size) + + r, err := io.CopyBuffer(f, ltr, buf) read += r if err != nil { return read, err From a6995bb823fd691e67c1460db31078ef0666e644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 13 Sep 2022 19:57:07 +0200 Subject: [PATCH 26/26] wip sector import c1/pc1 out types --- api/api_storage.go | 3 +- api/cbor_gen.go | 7 +- api/docgen-openrpc/cmd/docgen_openrpc.go | 2 +- api/docgen/docgen.go | 168 ++++++++++++++++++ api/mocks/mock_full.go | 18 +- api/proxy_gen.go | 18 +- api/v0api/proxy_gen.go | 10 +- api/v0api/v0mocks/mock_full.go | 18 +- build/openrpc/miner.json.gz | Bin 16010 -> 28 bytes build/openrpc/worker.json.gz | Bin 5256 -> 28 bytes chain/actors/builtin/account/account.go | 16 +- chain/actors/builtin/account/v0.go | 6 +- chain/actors/builtin/account/v2.go | 6 +- chain/actors/builtin/account/v3.go | 6 +- chain/actors/builtin/account/v4.go | 6 +- chain/actors/builtin/account/v5.go | 6 +- chain/actors/builtin/account/v6.go | 6 +- chain/actors/builtin/account/v7.go | 6 +- chain/actors/builtin/account/v8.go | 6 +- chain/actors/builtin/builtin.go | 21 ++- chain/actors/builtin/cron/cron.go | 14 +- chain/actors/builtin/cron/v0.go | 4 +- chain/actors/builtin/cron/v2.go | 4 +- chain/actors/builtin/cron/v3.go | 4 +- chain/actors/builtin/cron/v4.go | 4 +- chain/actors/builtin/cron/v5.go | 4 +- chain/actors/builtin/cron/v6.go | 4 +- chain/actors/builtin/cron/v7.go | 4 +- chain/actors/builtin/cron/v8.go | 4 +- chain/actors/builtin/init/init.go | 20 ++- chain/actors/builtin/init/v0.go | 10 +- chain/actors/builtin/init/v2.go | 10 +- chain/actors/builtin/init/v3.go | 11 +- chain/actors/builtin/init/v4.go | 11 +- chain/actors/builtin/init/v5.go | 11 +- chain/actors/builtin/init/v6.go | 11 +- chain/actors/builtin/init/v7.go | 11 +- chain/actors/builtin/init/v8.go | 10 +- chain/actors/builtin/market/market.go | 17 +- chain/actors/builtin/market/v0.go | 10 +- chain/actors/builtin/market/v2.go | 10 +- chain/actors/builtin/market/v3.go | 10 +- chain/actors/builtin/market/v4.go | 10 +- chain/actors/builtin/market/v5.go | 10 +- chain/actors/builtin/market/v6.go | 9 +- chain/actors/builtin/market/v7.go | 9 +- chain/actors/builtin/market/v8.go | 9 +- chain/actors/builtin/miner/miner.go | 21 ++- chain/actors/builtin/miner/v0.go | 15 +- chain/actors/builtin/miner/v2.go | 12 +- chain/actors/builtin/miner/v3.go | 13 +- chain/actors/builtin/miner/v4.go | 13 +- chain/actors/builtin/miner/v5.go | 13 +- chain/actors/builtin/miner/v6.go | 13 +- chain/actors/builtin/miner/v7.go | 13 +- chain/actors/builtin/miner/v8.go | 14 +- chain/actors/builtin/multisig/message0.go | 1 + chain/actors/builtin/multisig/message2.go | 1 + chain/actors/builtin/multisig/message3.go | 1 + chain/actors/builtin/multisig/message4.go | 1 + chain/actors/builtin/multisig/message5.go | 1 + chain/actors/builtin/multisig/message6.go | 1 + chain/actors/builtin/multisig/message7.go | 1 + chain/actors/builtin/multisig/message8.go | 1 + chain/actors/builtin/multisig/multisig.go | 13 +- chain/actors/builtin/multisig/v0.go | 8 +- chain/actors/builtin/multisig/v2.go | 8 +- chain/actors/builtin/multisig/v3.go | 9 +- chain/actors/builtin/multisig/v4.go | 9 +- chain/actors/builtin/multisig/v5.go | 9 +- chain/actors/builtin/multisig/v6.go | 9 +- chain/actors/builtin/multisig/v7.go | 9 +- chain/actors/builtin/multisig/v8.go | 8 +- chain/actors/builtin/paych/message0.go | 2 + chain/actors/builtin/paych/message2.go | 2 + chain/actors/builtin/paych/message3.go | 2 + chain/actors/builtin/paych/message4.go | 2 + chain/actors/builtin/paych/message5.go | 2 + chain/actors/builtin/paych/message6.go | 2 + chain/actors/builtin/paych/message7.go | 2 + chain/actors/builtin/paych/message8.go | 4 +- chain/actors/builtin/paych/paych.go | 14 +- chain/actors/builtin/paych/v0.go | 5 +- chain/actors/builtin/paych/v2.go | 5 +- chain/actors/builtin/paych/v3.go | 5 +- chain/actors/builtin/paych/v4.go | 5 +- chain/actors/builtin/paych/v5.go | 5 +- chain/actors/builtin/paych/v6.go | 5 +- chain/actors/builtin/paych/v7.go | 5 +- chain/actors/builtin/paych/v8.go | 5 +- chain/actors/builtin/power/power.go | 22 ++- chain/actors/builtin/power/v0.go | 10 +- chain/actors/builtin/power/v2.go | 10 +- chain/actors/builtin/power/v3.go | 11 +- chain/actors/builtin/power/v4.go | 11 +- chain/actors/builtin/power/v5.go | 11 +- chain/actors/builtin/power/v6.go | 11 +- chain/actors/builtin/power/v7.go | 11 +- chain/actors/builtin/power/v8.go | 10 +- chain/actors/builtin/reward/reward.go | 16 +- chain/actors/builtin/reward/v0.go | 8 +- chain/actors/builtin/reward/v2.go | 8 +- chain/actors/builtin/reward/v3.go | 8 +- chain/actors/builtin/reward/v4.go | 8 +- chain/actors/builtin/reward/v5.go | 8 +- chain/actors/builtin/reward/v6.go | 8 +- chain/actors/builtin/reward/v7.go | 8 +- chain/actors/builtin/reward/v8.go | 8 +- chain/actors/builtin/system/system.go | 15 +- chain/actors/builtin/system/v0.go | 4 +- chain/actors/builtin/system/v2.go | 4 +- chain/actors/builtin/system/v3.go | 4 +- chain/actors/builtin/system/v4.go | 4 +- chain/actors/builtin/system/v5.go | 4 +- chain/actors/builtin/system/v6.go | 4 +- chain/actors/builtin/system/v7.go | 4 +- chain/actors/builtin/system/v8.go | 4 +- chain/actors/builtin/verifreg/v0.go | 8 +- chain/actors/builtin/verifreg/v2.go | 8 +- chain/actors/builtin/verifreg/v3.go | 11 +- chain/actors/builtin/verifreg/v4.go | 11 +- chain/actors/builtin/verifreg/v5.go | 11 +- chain/actors/builtin/verifreg/v6.go | 11 +- chain/actors/builtin/verifreg/v7.go | 11 +- chain/actors/builtin/verifreg/v8.go | 10 +- chain/actors/builtin/verifreg/verifreg.go | 11 +- chain/actors/policy/policy.go | 31 +++- chain/consensus/filcns/compute_state.go | 2 +- chain/exchange/cbor_gen.go | 3 +- chain/types/cbor_gen.go | 7 +- chain/vm/cbor_gen.go | 3 +- cli/servicesmock_test.go | 4 +- conformance/chaos/cbor_gen.go | 7 +- documentation/en/api-v0-methods-miner.md | 6 +- documentation/en/api-v0-methods-worker.md | 4 +- itests/sector_import_simple_test.go | 5 + journal/mockjournal/journal.go | 3 +- lib/jsonfield/jsonbytes.go | 111 ++++++++++++ lib/jsonfield/jsonfield_test.go | 58 ++++++ markets/dagstore/mocks/mock_lotus_accessor.go | 3 +- node/hello/cbor_gen.go | 3 +- paychmgr/cbor_gen.go | 5 +- storage/paths/mocks/index.go | 4 +- storage/paths/mocks/pf.go | 4 +- storage/paths/mocks/store.go | 4 +- storage/pipeline/cbor_gen.go | 34 +--- storage/pipeline/mocks/mock_commit_batcher.go | 4 +- storage/pipeline/states_sealing.go | 6 +- storage/sealer/cbor_gen.go | 3 +- storage/sealer/ffiwrapper/sealer_cgo.go | 55 +++--- storage/sealer/manager.go | 4 +- storage/sealer/storiface/storage.go | 4 - storage/sealer/storiface/types_proofs.go | 140 +++++++++++++++ 153 files changed, 1156 insertions(+), 550 deletions(-) create mode 100644 lib/jsonfield/jsonbytes.go create mode 100644 lib/jsonfield/jsonfield_test.go create mode 100644 storage/sealer/storiface/types_proofs.go diff --git a/api/api_storage.go b/api/api_storage.go index 7c6fe7cdd38..3fecba9e6b9 100644 --- a/api/api_storage.go +++ b/api/api_storage.go @@ -530,7 +530,7 @@ type RemoteSectorMeta struct { // Required in PreCommitting and later TicketValue abi.SealRandomness TicketEpoch abi.ChainEpoch - PreCommit1Out storiface.PreCommit1Out // todo specify better + PreCommit1Out storiface.PreCommit1Out CommD *cid.Cid CommR *cid.Cid // SectorKey @@ -594,7 +594,6 @@ type RemoteCommit2Params struct { Sector abi.SectorID ProofType abi.RegisteredSealProof - // todo spec better Commit1Out storiface.Commit1Out } diff --git a/api/cbor_gen.go b/api/cbor_gen.go index 0932bdbc0a3..0310283c54d 100644 --- a/api/cbor_gen.go +++ b/api/cbor_gen.go @@ -8,13 +8,12 @@ import ( "math" "sort" - cid "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - xerrors "golang.org/x/xerrors" - abi "github.com/filecoin-project/go-state-types/abi" market "github.com/filecoin-project/go-state-types/builtin/v8/market" paych "github.com/filecoin-project/go-state-types/builtin/v8/paych" + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" ) var _ = xerrors.Errorf diff --git a/api/docgen-openrpc/cmd/docgen_openrpc.go b/api/docgen-openrpc/cmd/docgen_openrpc.go index 5f6bc566f2b..62b46245bf6 100644 --- a/api/docgen-openrpc/cmd/docgen_openrpc.go +++ b/api/docgen-openrpc/cmd/docgen_openrpc.go @@ -38,7 +38,7 @@ func main() { out, err := doc.Discover() if err != nil { - log.Fatalln(err) + log.Println(err) } var jsonOut []byte diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index e078cbe0fc9..82b15ca0333 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -40,6 +40,7 @@ import ( "github.com/filecoin-project/lotus/api/v0api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/lib/jsonfield" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" sealing "github.com/filecoin-project/lotus/storage/pipeline" @@ -352,6 +353,173 @@ func init() { Headers: nil, }, }) + + addExample(storiface.StringRegisteredProofType("StackedDrg2KiBV1")) + + addExample(map[storiface.StringRegisteredProofType]storiface.Labels{ + "StackedDrg2KiBV1": { + Labels: []storiface.Label{ + { + ID: "layer-1", + Path: "/tmp/sector-path/cache/s0-t01000-1234", + RowsToDiscard: 5, + Size: 64, + }, + }, + }, + }) + + addExample(&jsonfield.JSONBytes[storiface.Commit1OutRaw]{ + Data: storiface.Commit1OutRaw{ + CommD: storiface.Commitment{1, 2, 3, 4}, + CommR: storiface.Commitment{87, 75, 54, 80}, + RegisteredProof: "StackedDrg2KiBV1", + ReplicaID: storiface.Commitment{98, 7, 5, 36, 8}, + Seed: storiface.Ticket{99, 99, 99, 99}, + Ticket: storiface.Ticket{89, 99, 99, 99, 99}, + VanillaProofs: map[storiface.StringRegisteredProofType][][]storiface.VanillaStackedProof{ + "StackedDrg2KiBV1": { + { + { + CommDProofs: storiface.MerkleProof[storiface.Sha256Domain]{ + Data: storiface.ProofData[storiface.Sha256Domain]{ + Single: &storiface.SingleProof[storiface.Sha256Domain]{ + Root: [32]byte{1, 2, 3, 4}, + Leaf: [32]byte{0, 0, 0, 0, 0}, + Path: storiface.InclusionPath[storiface.Sha256Domain]{ + Path: []storiface.PathElement[storiface.Sha256Domain]{ + { + Index: 0, + Hashes: []storiface.Sha256Domain{ + {5, 6, 8, 9}, + {9, 7, 5, 4}, + }, + }, + }, + }, + }, + }, + }, + CommRLastProof: storiface.MerkleProof[storiface.PoseidonDomain]{ + Data: storiface.ProofData[storiface.PoseidonDomain]{ + Single: &storiface.SingleProof[storiface.PoseidonDomain]{ + Root: [32]byte{87, 75, 54, 80}, + Leaf: [32]byte{89, 45, 239, 146}, + Path: storiface.InclusionPath[storiface.PoseidonDomain]{ + Path: []storiface.PathElement[storiface.PoseidonDomain]{ + { + Index: 0, + Hashes: []storiface.PoseidonDomain{ + {145, 35, 132, 36}, + {23, 24, 237, 94}, + }, + }, + }, + }, + }, + }, + }, + ReplicaColumnProofs: storiface.ReplicaColumnProof[storiface.PoseidonDomain]{ + C_X: storiface.ColumnProof[storiface.PoseidonDomain]{ + Column: storiface.Column[storiface.PoseidonDomain]{ + Index: 2, + Rows: []storiface.PoseidonDomain{{9, 7, 5, 4}}, + }, + InclusionProof: storiface.MerkleProof[storiface.PoseidonDomain]{ + Data: storiface.ProofData[storiface.PoseidonDomain]{ + Single: &storiface.SingleProof[storiface.PoseidonDomain]{ + Root: [32]byte{63, 83, 12, 85}, + Leaf: [32]byte{42, 16, 52, 235}, + Path: storiface.InclusionPath[storiface.PoseidonDomain]{ + Path: []storiface.PathElement[storiface.PoseidonDomain]{ + { + Index: 0, + Hashes: []storiface.PoseidonDomain{ + {14, 96, 34, 12}, + {86, 14, 34, 74}, + }, + }, + }, + }, + }, + }, + }, + }, + DrgParents: []storiface.ColumnProof[storiface.PoseidonDomain]{ + { + Column: storiface.Column[storiface.PoseidonDomain]{ + Index: 24, + Rows: []storiface.PoseidonDomain{{234, 23, 47, 23}}, + }, + InclusionProof: storiface.MerkleProof[storiface.PoseidonDomain]{ + Data: storiface.ProofData[storiface.PoseidonDomain]{ + Single: &storiface.SingleProof[storiface.PoseidonDomain]{ + Root: [32]byte{63, 83, 12, 85}, + Leaf: [32]byte{42, 16, 52, 235}, + Path: storiface.InclusionPath[storiface.PoseidonDomain]{ + Path: []storiface.PathElement[storiface.PoseidonDomain]{ + { + Index: 0, + Hashes: []storiface.PoseidonDomain{ + {14, 96, 34, 12}, + {86, 14, 34, 74}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + ExpParents: []storiface.ColumnProof[storiface.PoseidonDomain]{ + { + Column: storiface.Column[storiface.PoseidonDomain]{ + Index: 52, + Rows: []storiface.PoseidonDomain{{98, 55, 44, 87}}, + }, + InclusionProof: storiface.MerkleProof[storiface.PoseidonDomain]{ + Data: storiface.ProofData[storiface.PoseidonDomain]{ + Single: &storiface.SingleProof[storiface.PoseidonDomain]{ + Root: [32]byte{6, 83, 12, 85}, + Leaf: [32]byte{42, 16, 2, 235}, + Path: storiface.InclusionPath[storiface.PoseidonDomain]{ + Path: []storiface.PathElement[storiface.PoseidonDomain]{ + { + Index: 0, + Hashes: []storiface.PoseidonDomain{ + {14, 6, 34, 12}, + {86, 14, 34, 7}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + LabelingProofs: []storiface.LabelingProof[storiface.PoseidonDomain]{ + { + Parents: []storiface.PoseidonDomain{{0, 8, 6, 4}}, + LayerIndex: 0, + Node: 0, + H: nil, + }, + }, + EncodingProof: storiface.EncodingProof[storiface.PoseidonDomain]{ + Parents: []storiface.PoseidonDomain{{8, 6, 4, 3}}, + LayerIndex: 0, + Node: 0, + H: nil, + }, + }, + }, + }, + }, + }, + }) } func GetAPIType(name, pkg string) (i interface{}, t reflect.Type, permStruct []reflect.Type) { diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 2640d6032f6..336a824a4b0 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -10,15 +10,6 @@ import ( reflect "reflect" time "time" - gomock "github.com/golang/mock/gomock" - uuid "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" - cid "github.com/ipfs/go-cid" - metrics "github.com/libp2p/go-libp2p/core/metrics" - network0 "github.com/libp2p/go-libp2p/core/network" - peer "github.com/libp2p/go-libp2p/core/peer" - protocol "github.com/libp2p/go-libp2p/core/protocol" - address "github.com/filecoin-project/go-address" bitfield "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -31,7 +22,6 @@ import ( crypto "github.com/filecoin-project/go-state-types/crypto" dline "github.com/filecoin-project/go-state-types/dline" network "github.com/filecoin-project/go-state-types/network" - api "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" miner0 "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -39,6 +29,14 @@ import ( alerting "github.com/filecoin-project/lotus/journal/alerting" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" imports "github.com/filecoin-project/lotus/node/repo/imports" + gomock "github.com/golang/mock/gomock" + uuid "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" + cid "github.com/ipfs/go-cid" + metrics "github.com/libp2p/go-libp2p/core/metrics" + network0 "github.com/libp2p/go-libp2p/core/network" + peer "github.com/libp2p/go-libp2p/core/peer" + protocol "github.com/libp2p/go-libp2p/core/protocol" ) // MockFullNode is a mock of FullNode interface. diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 13de24938e4..70ba025af70 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -7,15 +7,6 @@ import ( "encoding/json" "time" - "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" - "github.com/ipfs/go-cid" - "github.com/libp2p/go-libp2p/core/metrics" - "github.com/libp2p/go-libp2p/core/network" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/libp2p/go-libp2p/core/protocol" - "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -30,7 +21,6 @@ import ( "github.com/filecoin-project/go-state-types/dline" abinetwork "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/proof" - apitypes "github.com/filecoin-project/lotus/api/types" "github.com/filecoin-project/lotus/chain/actors/builtin" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -42,6 +32,14 @@ import ( "github.com/filecoin-project/lotus/storage/sealer/fsutil" "github.com/filecoin-project/lotus/storage/sealer/sealtasks" "github.com/filecoin-project/lotus/storage/sealer/storiface" + "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/metrics" + "github.com/libp2p/go-libp2p/core/network" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/core/protocol" + "golang.org/x/xerrors" ) var ErrNotSupported = xerrors.New("method not supported") diff --git a/api/v0api/proxy_gen.go b/api/v0api/proxy_gen.go index b568fe15626..ec10e0e9773 100644 --- a/api/v0api/proxy_gen.go +++ b/api/v0api/proxy_gen.go @@ -5,11 +5,6 @@ package v0api import ( "context" - blocks "github.com/ipfs/go-block-format" - "github.com/ipfs/go-cid" - "github.com/libp2p/go-libp2p/core/peer" - "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -21,7 +16,6 @@ import ( "github.com/filecoin-project/go-state-types/crypto" "github.com/filecoin-project/go-state-types/dline" abinetwork "github.com/filecoin-project/go-state-types/network" - "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -29,6 +23,10 @@ import ( marketevents "github.com/filecoin-project/lotus/markets/loggers" "github.com/filecoin-project/lotus/node/modules/dtypes" "github.com/filecoin-project/lotus/node/repo/imports" + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/peer" + "golang.org/x/xerrors" ) var ErrNotSupported = xerrors.New("method not supported") diff --git a/api/v0api/v0mocks/mock_full.go b/api/v0api/v0mocks/mock_full.go index 7dc9c0d63ff..0b5b082c721 100644 --- a/api/v0api/v0mocks/mock_full.go +++ b/api/v0api/v0mocks/mock_full.go @@ -9,15 +9,6 @@ import ( reflect "reflect" time "time" - gomock "github.com/golang/mock/gomock" - uuid "github.com/google/uuid" - blocks "github.com/ipfs/go-block-format" - cid "github.com/ipfs/go-cid" - metrics "github.com/libp2p/go-libp2p/core/metrics" - network0 "github.com/libp2p/go-libp2p/core/network" - peer "github.com/libp2p/go-libp2p/core/peer" - protocol "github.com/libp2p/go-libp2p/core/protocol" - address "github.com/filecoin-project/go-address" bitfield "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" @@ -31,7 +22,6 @@ import ( crypto "github.com/filecoin-project/go-state-types/crypto" dline "github.com/filecoin-project/go-state-types/dline" network "github.com/filecoin-project/go-state-types/network" - api "github.com/filecoin-project/lotus/api" apitypes "github.com/filecoin-project/lotus/api/types" v0api "github.com/filecoin-project/lotus/api/v0api" @@ -41,6 +31,14 @@ import ( marketevents "github.com/filecoin-project/lotus/markets/loggers" dtypes "github.com/filecoin-project/lotus/node/modules/dtypes" imports "github.com/filecoin-project/lotus/node/repo/imports" + gomock "github.com/golang/mock/gomock" + uuid "github.com/google/uuid" + blocks "github.com/ipfs/go-block-format" + cid "github.com/ipfs/go-cid" + metrics "github.com/libp2p/go-libp2p/core/metrics" + network0 "github.com/libp2p/go-libp2p/core/network" + peer "github.com/libp2p/go-libp2p/core/peer" + protocol "github.com/libp2p/go-libp2p/core/protocol" ) // MockFullNode is a mock of FullNode interface. diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 3d53c4dc7f96c328c18afab82267a6d14a9a3fcf..f4d1c8cf85fc004e8f41b48898e69901aae4a85b 100644 GIT binary patch literal 28 fcmb2|=3oGW|EILio@8WUVEF&v|IcYvAcFw_aiR!+ literal 16010 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 E0Cfmdga7~l diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 90167b6e09ec40c5a7dd6f5a19b1b5c28082a2fa..f4d1c8cf85fc004e8f41b48898e69901aae4a85b 100644 GIT binary patch literal 28 fcmb2|=3oGW|EILio@8WUVEF&v|IcYvAcFw_aiR!+ literal 5256 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 O0RR7Sd*$b6F#!P402~Ye diff --git a/chain/actors/builtin/account/account.go b/chain/actors/builtin/account/account.go index f233f173c66..04bdc3920ba 100644 --- a/chain/actors/builtin/account/account.go +++ b/chain/actors/builtin/account/account.go @@ -1,22 +1,30 @@ package account import ( + "github.com/filecoin-project/lotus/chain/actors" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" - builtin8 "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/cbor" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/types" + builtin8 "github.com/filecoin-project/go-state-types/builtin" ) var Methods = builtin8.MethodsAccount diff --git a/chain/actors/builtin/account/v0.go b/chain/actors/builtin/account/v0.go index 314bd4b298f..bdfca2fd705 100644 --- a/chain/actors/builtin/account/v0.go +++ b/chain/actors/builtin/account/v0.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account0 "github.com/filecoin-project/specs-actors/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account0 "github.com/filecoin-project/specs-actors/actors/builtin/account" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/account/v2.go b/chain/actors/builtin/account/v2.go index 60506542466..66618e06a4e 100644 --- a/chain/actors/builtin/account/v2.go +++ b/chain/actors/builtin/account/v2.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/account" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/account/v3.go b/chain/actors/builtin/account/v3.go index d070476ea1e..dbe100a4f83 100644 --- a/chain/actors/builtin/account/v3.go +++ b/chain/actors/builtin/account/v3.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/account" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/account/v4.go b/chain/actors/builtin/account/v4.go index f4d9f7a06ea..53f71dcc5e9 100644 --- a/chain/actors/builtin/account/v4.go +++ b/chain/actors/builtin/account/v4.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/account" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/account/v5.go b/chain/actors/builtin/account/v5.go index 5e01ce15210..538f5698750 100644 --- a/chain/actors/builtin/account/v5.go +++ b/chain/actors/builtin/account/v5.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/account" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/account/v6.go b/chain/actors/builtin/account/v6.go index 85135dcda2f..a0d157ae54d 100644 --- a/chain/actors/builtin/account/v6.go +++ b/chain/actors/builtin/account/v6.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/account" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/account/v7.go b/chain/actors/builtin/account/v7.go index 4ae979b8279..883776cf8f0 100644 --- a/chain/actors/builtin/account/v7.go +++ b/chain/actors/builtin/account/v7.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/account" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/account/v8.go b/chain/actors/builtin/account/v8.go index 211deea3338..d8ef52c0069 100644 --- a/chain/actors/builtin/account/v8.go +++ b/chain/actors/builtin/account/v8.go @@ -1,12 +1,12 @@ package account import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - account8 "github.com/filecoin-project/go-state-types/builtin/v8/account" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors/adt" + + account8 "github.com/filecoin-project/go-state-types/builtin/v8/account" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/builtin.go b/chain/actors/builtin/builtin.go index fb95a28d6c7..c1d6ad018b9 100644 --- a/chain/actors/builtin/builtin.go +++ b/chain/actors/builtin/builtin.go @@ -3,24 +3,33 @@ package builtin import ( "fmt" + "github.com/filecoin-project/go-address" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/builtin" - miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" - smoothingtypes "github.com/filecoin-project/go-state-types/builtin/v8/util/smoothing" - "github.com/filecoin-project/go-state-types/proof" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + builtin8 "github.com/filecoin-project/specs-actors/v8/actors/builtin" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/proof" + "github.com/filecoin-project/lotus/chain/actors" + + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + smoothingtypes "github.com/filecoin-project/go-state-types/builtin/v8/util/smoothing" ) var SystemActorAddr = builtin.SystemActorAddr diff --git a/chain/actors/builtin/cron/cron.go b/chain/actors/builtin/cron/cron.go index 00264e3b442..1a9c32c81c3 100644 --- a/chain/actors/builtin/cron/cron.go +++ b/chain/actors/builtin/cron/cron.go @@ -1,20 +1,26 @@ package cron import ( + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" "golang.org/x/xerrors" - builtin8 "github.com/filecoin-project/go-state-types/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/types" + builtin8 "github.com/filecoin-project/go-state-types/builtin" ) func Load(store adt.Store, act *types.Actor) (State, error) { diff --git a/chain/actors/builtin/cron/v0.go b/chain/actors/builtin/cron/v0.go index baa81aac3c1..6147b858c10 100644 --- a/chain/actors/builtin/cron/v0.go +++ b/chain/actors/builtin/cron/v0.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron0 "github.com/filecoin-project/specs-actors/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron0 "github.com/filecoin-project/specs-actors/actors/builtin/cron" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/cron/v2.go b/chain/actors/builtin/cron/v2.go index d6ee35935e9..51ca179d9ce 100644 --- a/chain/actors/builtin/cron/v2.go +++ b/chain/actors/builtin/cron/v2.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/cron" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/cron/v3.go b/chain/actors/builtin/cron/v3.go index 356d385cd30..ff74d511de5 100644 --- a/chain/actors/builtin/cron/v3.go +++ b/chain/actors/builtin/cron/v3.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/cron" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/cron/v4.go b/chain/actors/builtin/cron/v4.go index 3db3c95aaeb..1cff8cc2813 100644 --- a/chain/actors/builtin/cron/v4.go +++ b/chain/actors/builtin/cron/v4.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/cron" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/cron/v5.go b/chain/actors/builtin/cron/v5.go index 5d99af1fd4b..2bb00dc21da 100644 --- a/chain/actors/builtin/cron/v5.go +++ b/chain/actors/builtin/cron/v5.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/cron" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/cron/v6.go b/chain/actors/builtin/cron/v6.go index c86cd6c42f0..8bbadd79f52 100644 --- a/chain/actors/builtin/cron/v6.go +++ b/chain/actors/builtin/cron/v6.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/cron" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/cron/v7.go b/chain/actors/builtin/cron/v7.go index db9f8f9e2f7..e5538c89ff6 100644 --- a/chain/actors/builtin/cron/v7.go +++ b/chain/actors/builtin/cron/v7.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/cron" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/cron/v8.go b/chain/actors/builtin/cron/v8.go index 00567acf956..00b22fcbfee 100644 --- a/chain/actors/builtin/cron/v8.go +++ b/chain/actors/builtin/cron/v8.go @@ -3,9 +3,9 @@ package cron import ( "github.com/ipfs/go-cid" - cron8 "github.com/filecoin-project/go-state-types/builtin/v8/cron" - "github.com/filecoin-project/lotus/chain/actors/adt" + + cron8 "github.com/filecoin-project/go-state-types/builtin/v8/cron" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/init/init.go b/chain/actors/builtin/init/init.go index c7e0f7b8204..9ba412cf1f3 100644 --- a/chain/actors/builtin/init/init.go +++ b/chain/actors/builtin/init/init.go @@ -1,25 +1,33 @@ package init import ( - "github.com/ipfs/go-cid" + "github.com/filecoin-project/lotus/chain/actors" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin8 "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/cbor" + "github.com/ipfs/go-cid" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/types" - "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin8 "github.com/filecoin-project/go-state-types/builtin" ) var ( diff --git a/chain/actors/builtin/init/v0.go b/chain/actors/builtin/init/v0.go index 2f6b213c007..ddd2dab94f2 100644 --- a/chain/actors/builtin/init/v0.go +++ b/chain/actors/builtin/init/v0.go @@ -1,17 +1,17 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/node/modules/dtypes" + + init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/init/v2.go b/chain/actors/builtin/init/v2.go index d780a1fe92c..72e2d56a522 100644 --- a/chain/actors/builtin/init/v2.go +++ b/chain/actors/builtin/init/v2.go @@ -1,17 +1,17 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/node/modules/dtypes" + + init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/init/v3.go b/chain/actors/builtin/init/v3.go index b2f713b1fe4..4609c94a372 100644 --- a/chain/actors/builtin/init/v3.go +++ b/chain/actors/builtin/init/v3.go @@ -1,18 +1,19 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/init/v4.go b/chain/actors/builtin/init/v4.go index 9de02816ff0..dc56d1f196c 100644 --- a/chain/actors/builtin/init/v4.go +++ b/chain/actors/builtin/init/v4.go @@ -1,18 +1,19 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/init/v5.go b/chain/actors/builtin/init/v5.go index f9c59f83aa6..107366de536 100644 --- a/chain/actors/builtin/init/v5.go +++ b/chain/actors/builtin/init/v5.go @@ -1,18 +1,19 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + init5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/init" adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/init/v6.go b/chain/actors/builtin/init/v6.go index 494b6aaa094..a5bd9edfb77 100644 --- a/chain/actors/builtin/init/v6.go +++ b/chain/actors/builtin/init/v6.go @@ -1,18 +1,19 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + init6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/init" adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/init/v7.go b/chain/actors/builtin/init/v7.go index bc378a14131..341aa52cdb0 100644 --- a/chain/actors/builtin/init/v7.go +++ b/chain/actors/builtin/init/v7.go @@ -1,18 +1,19 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + init7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/init" adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/init/v8.go b/chain/actors/builtin/init/v8.go index 63b058e5734..91981954920 100644 --- a/chain/actors/builtin/init/v8.go +++ b/chain/actors/builtin/init/v8.go @@ -1,18 +1,18 @@ package init import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/node/modules/dtypes" + builtin8 "github.com/filecoin-project/go-state-types/builtin" init8 "github.com/filecoin-project/go-state-types/builtin/v8/init" adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/node/modules/dtypes" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/market/market.go b/chain/actors/builtin/market/market.go index 8c0e4e91ae6..68dcf19a07a 100644 --- a/chain/actors/builtin/market/market.go +++ b/chain/actors/builtin/market/market.go @@ -3,24 +3,33 @@ package market import ( "unicode/utf8" - cbg "github.com/whyrusleeping/cbor-gen" + "github.com/filecoin-project/go-state-types/network" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - builtin8 "github.com/filecoin-project/go-state-types/builtin" - market8 "github.com/filecoin-project/go-state-types/builtin/v8/market" "github.com/filecoin-project/go-state-types/cbor" - "github.com/filecoin-project/go-state-types/network" + cbg "github.com/whyrusleeping/cbor-gen" + + market8 "github.com/filecoin-project/go-state-types/builtin/v8/market" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + builtin8 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" diff --git a/chain/actors/builtin/market/v0.go b/chain/actors/builtin/market/v0.go index 38e92f12df3..b57d2c72439 100644 --- a/chain/actors/builtin/market/v0.go +++ b/chain/actors/builtin/market/v0.go @@ -3,17 +3,17 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/market/v2.go b/chain/actors/builtin/market/v2.go index 5a399e68c8e..57ded97b275 100644 --- a/chain/actors/builtin/market/v2.go +++ b/chain/actors/builtin/market/v2.go @@ -3,17 +3,17 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/market/v3.go b/chain/actors/builtin/market/v3.go index a953429fc53..f85e5545625 100644 --- a/chain/actors/builtin/market/v3.go +++ b/chain/actors/builtin/market/v3.go @@ -3,17 +3,17 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - market3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/market" - adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/market" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/market/v4.go b/chain/actors/builtin/market/v4.go index 8e6b3cd34c4..5789318fb50 100644 --- a/chain/actors/builtin/market/v4.go +++ b/chain/actors/builtin/market/v4.go @@ -3,17 +3,17 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market" - adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market" + adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/market/v5.go b/chain/actors/builtin/market/v5.go index 5cf904e049e..6dbb724df98 100644 --- a/chain/actors/builtin/market/v5.go +++ b/chain/actors/builtin/market/v5.go @@ -3,17 +3,17 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" - market5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/market" - adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" - "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/market" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/market/v6.go b/chain/actors/builtin/market/v6.go index 03862ac0960..15c55998e40 100644 --- a/chain/actors/builtin/market/v6.go +++ b/chain/actors/builtin/market/v6.go @@ -3,19 +3,20 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" rlepluslazy "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" - market6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/market" - adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/market" + adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/market/v7.go b/chain/actors/builtin/market/v7.go index 2c2664110aa..a3c2c72149b 100644 --- a/chain/actors/builtin/market/v7.go +++ b/chain/actors/builtin/market/v7.go @@ -3,19 +3,20 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" rlepluslazy "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" - market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" - adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/market/v8.go b/chain/actors/builtin/market/v8.go index 8afbf39dee6..a306c44e91f 100644 --- a/chain/actors/builtin/market/v8.go +++ b/chain/actors/builtin/market/v8.go @@ -3,19 +3,20 @@ package market import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-bitfield" rlepluslazy "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" - market8 "github.com/filecoin-project/go-state-types/builtin/v8/market" - adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + market8 "github.com/filecoin-project/go-state-types/builtin/v8/market" + adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/miner/miner.go b/chain/actors/builtin/miner/miner.go index 820be35a4e5..44fa080a603 100644 --- a/chain/actors/builtin/miner/miner.go +++ b/chain/actors/builtin/miner/miner.go @@ -1,28 +1,35 @@ package miner import ( + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/actors" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" "github.com/filecoin-project/go-bitfield" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" "github.com/filecoin-project/go-state-types/cbor" "github.com/filecoin-project/go-state-types/dline" - "github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/proof" + + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" - builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/types" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" ) func Load(store adt.Store, act *types.Actor) (State, error) { diff --git a/chain/actors/builtin/miner/v0.go b/chain/actors/builtin/miner/v0.go index daa0a6bfd04..a6f11179cd3 100644 --- a/chain/actors/builtin/miner/v0.go +++ b/chain/actors/builtin/miner/v0.go @@ -4,20 +4,21 @@ import ( "bytes" "errors" - "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - "golang.org/x/xerrors" + "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/go-bitfield" rle "github.com/filecoin-project/go-bitfield/rle" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" "github.com/filecoin-project/go-state-types/dline" - miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" + minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" "github.com/filecoin-project/lotus/chain/actors/adt" + + miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/miner/v2.go b/chain/actors/builtin/miner/v2.go index 7741b542693..f54526bf703 100644 --- a/chain/actors/builtin/miner/v2.go +++ b/chain/actors/builtin/miner/v2.go @@ -4,19 +4,19 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" - "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/chain/actors/adt" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/miner/v3.go b/chain/actors/builtin/miner/v3.go index 8cb1c40049f..0c71d0d775f 100644 --- a/chain/actors/builtin/miner/v3.go +++ b/chain/actors/builtin/miner/v3.go @@ -4,20 +4,21 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" - "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/miner/v4.go b/chain/actors/builtin/miner/v4.go index dc8b7a1d169..21f6d3feb5a 100644 --- a/chain/actors/builtin/miner/v4.go +++ b/chain/actors/builtin/miner/v4.go @@ -4,20 +4,21 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" - "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/miner/v5.go b/chain/actors/builtin/miner/v5.go index f5ec6087b53..d5f81e17558 100644 --- a/chain/actors/builtin/miner/v5.go +++ b/chain/actors/builtin/miner/v5.go @@ -4,20 +4,21 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" - "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/miner/v6.go b/chain/actors/builtin/miner/v6.go index 78445b2ba53..36631aed4c5 100644 --- a/chain/actors/builtin/miner/v6.go +++ b/chain/actors/builtin/miner/v6.go @@ -4,20 +4,21 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" - "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/miner/v7.go b/chain/actors/builtin/miner/v7.go index c91fceb7b67..5026200696a 100644 --- a/chain/actors/builtin/miner/v7.go +++ b/chain/actors/builtin/miner/v7.go @@ -4,20 +4,21 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" - "github.com/filecoin-project/go-state-types/dline" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/miner/v8.go b/chain/actors/builtin/miner/v8.go index 817a073a2ea..370e149e7ea 100644 --- a/chain/actors/builtin/miner/v8.go +++ b/chain/actors/builtin/miner/v8.go @@ -4,20 +4,20 @@ import ( "bytes" "errors" + "github.com/filecoin-project/go-bitfield" + rle "github.com/filecoin-project/go-bitfield/rle" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/dline" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-bitfield" - rle "github.com/filecoin-project/go-bitfield/rle" - "github.com/filecoin-project/go-state-types/abi" + minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin8 "github.com/filecoin-project/go-state-types/builtin" miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" - minertypes "github.com/filecoin-project/go-state-types/builtin/v8/miner" adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" - "github.com/filecoin-project/go-state-types/dline" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/multisig/message0.go b/chain/actors/builtin/multisig/message0.go index ac538d5b0fc..dc43a9d5dc3 100644 --- a/chain/actors/builtin/multisig/message0.go +++ b/chain/actors/builtin/multisig/message0.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" multisig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message2.go b/chain/actors/builtin/multisig/message2.go index 6667479b182..da2700d067d 100644 --- a/chain/actors/builtin/multisig/message2.go +++ b/chain/actors/builtin/multisig/message2.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" multisig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message3.go b/chain/actors/builtin/multisig/message3.go index b2e5880ba24..f5f6d8cdfba 100644 --- a/chain/actors/builtin/multisig/message3.go +++ b/chain/actors/builtin/multisig/message3.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" multisig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message4.go b/chain/actors/builtin/multisig/message4.go index c62ae3da531..90885aa0715 100644 --- a/chain/actors/builtin/multisig/message4.go +++ b/chain/actors/builtin/multisig/message4.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init" multisig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message5.go b/chain/actors/builtin/multisig/message5.go index d1ae532ea03..9a8110f2cd5 100644 --- a/chain/actors/builtin/multisig/message5.go +++ b/chain/actors/builtin/multisig/message5.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" init5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/init" multisig5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message6.go b/chain/actors/builtin/multisig/message6.go index 896ea72128a..b2b95245e5e 100644 --- a/chain/actors/builtin/multisig/message6.go +++ b/chain/actors/builtin/multisig/message6.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" init6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/init" multisig6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message7.go b/chain/actors/builtin/multisig/message7.go index b0595227908..e7fb83e9bd0 100644 --- a/chain/actors/builtin/multisig/message7.go +++ b/chain/actors/builtin/multisig/message7.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" init7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/init" multisig7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/multisig" diff --git a/chain/actors/builtin/multisig/message8.go b/chain/actors/builtin/multisig/message8.go index 23bee19d0f9..18429fb5bb5 100644 --- a/chain/actors/builtin/multisig/message8.go +++ b/chain/actors/builtin/multisig/message8.go @@ -5,6 +5,7 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + builtin8 "github.com/filecoin-project/go-state-types/builtin" init8 "github.com/filecoin-project/go-state-types/builtin/v8/init" multisig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" diff --git a/chain/actors/builtin/multisig/multisig.go b/chain/actors/builtin/multisig/multisig.go index 1b2fa794856..3985d44669f 100644 --- a/chain/actors/builtin/multisig/multisig.go +++ b/chain/actors/builtin/multisig/multisig.go @@ -9,17 +9,26 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin8 "github.com/filecoin-project/go-state-types/builtin" - msig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" "github.com/filecoin-project/go-state-types/cbor" + + msig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + builtin8 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" diff --git a/chain/actors/builtin/multisig/v0.go b/chain/actors/builtin/multisig/v0.go index 9f4d09dc13c..ccd9a9e37ed 100644 --- a/chain/actors/builtin/multisig/v0.go +++ b/chain/actors/builtin/multisig/v0.go @@ -4,16 +4,16 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/multisig/v2.go b/chain/actors/builtin/multisig/v2.go index 14e89568093..c3579b3e27f 100644 --- a/chain/actors/builtin/multisig/v2.go +++ b/chain/actors/builtin/multisig/v2.go @@ -4,16 +4,16 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + msig2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig" adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/multisig/v3.go b/chain/actors/builtin/multisig/v3.go index 5cde148c1a9..80682808ee3 100644 --- a/chain/actors/builtin/multisig/v3.go +++ b/chain/actors/builtin/multisig/v3.go @@ -4,17 +4,18 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + msig3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/multisig" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/multisig/v4.go b/chain/actors/builtin/multisig/v4.go index 87936661d78..f065f9f8ca1 100644 --- a/chain/actors/builtin/multisig/v4.go +++ b/chain/actors/builtin/multisig/v4.go @@ -4,17 +4,18 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + msig4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/multisig" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/multisig/v5.go b/chain/actors/builtin/multisig/v5.go index d50638ca5fa..783e3987f49 100644 --- a/chain/actors/builtin/multisig/v5.go +++ b/chain/actors/builtin/multisig/v5.go @@ -4,17 +4,18 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + msig5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/multisig" adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/multisig/v6.go b/chain/actors/builtin/multisig/v6.go index 9246eeaa961..71ea3c00c68 100644 --- a/chain/actors/builtin/multisig/v6.go +++ b/chain/actors/builtin/multisig/v6.go @@ -4,17 +4,18 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + msig6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/multisig" adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/multisig/v7.go b/chain/actors/builtin/multisig/v7.go index a6b630179f3..8ed1caacd78 100644 --- a/chain/actors/builtin/multisig/v7.go +++ b/chain/actors/builtin/multisig/v7.go @@ -4,17 +4,18 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + msig7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/multisig" adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/multisig/v8.go b/chain/actors/builtin/multisig/v8.go index 6311583b387..5b76f662e6a 100644 --- a/chain/actors/builtin/multisig/v8.go +++ b/chain/actors/builtin/multisig/v8.go @@ -4,17 +4,17 @@ import ( "bytes" "encoding/binary" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + builtin8 "github.com/filecoin-project/go-state-types/builtin" msig8 "github.com/filecoin-project/go-state-types/builtin/v8/multisig" adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/paych/message0.go b/chain/actors/builtin/paych/message0.go index d5a112d43b2..2daa0301bf7 100644 --- a/chain/actors/builtin/paych/message0.go +++ b/chain/actors/builtin/paych/message0.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" init0 "github.com/filecoin-project/specs-actors/actors/builtin/init" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message2.go b/chain/actors/builtin/paych/message2.go index 89a6e74ce9b..925ad0ed9d1 100644 --- a/chain/actors/builtin/paych/message2.go +++ b/chain/actors/builtin/paych/message2.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" init2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/init" paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message3.go b/chain/actors/builtin/paych/message3.go index 47f8e7e9e25..e8ae585fce6 100644 --- a/chain/actors/builtin/paych/message3.go +++ b/chain/actors/builtin/paych/message3.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" init3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/init" paych3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message4.go b/chain/actors/builtin/paych/message4.go index 65e63149d9d..b32b0fa5791 100644 --- a/chain/actors/builtin/paych/message4.go +++ b/chain/actors/builtin/paych/message4.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" init4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/init" paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message5.go b/chain/actors/builtin/paych/message5.go index ede1c8ceb7f..897bebe7a7c 100644 --- a/chain/actors/builtin/paych/message5.go +++ b/chain/actors/builtin/paych/message5.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" init5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/init" paych5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message6.go b/chain/actors/builtin/paych/message6.go index 009e8641fe7..11bd3a8a5d1 100644 --- a/chain/actors/builtin/paych/message6.go +++ b/chain/actors/builtin/paych/message6.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" init6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/init" paych6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message7.go b/chain/actors/builtin/paych/message7.go index 430fb93415b..446e54eade9 100644 --- a/chain/actors/builtin/paych/message7.go +++ b/chain/actors/builtin/paych/message7.go @@ -3,7 +3,9 @@ package paych import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" init7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/init" paych7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/paych" diff --git a/chain/actors/builtin/paych/message8.go b/chain/actors/builtin/paych/message8.go index 3fb743bc945..189b209880b 100644 --- a/chain/actors/builtin/paych/message8.go +++ b/chain/actors/builtin/paych/message8.go @@ -5,10 +5,12 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" + builtin8 "github.com/filecoin-project/go-state-types/builtin" init8 "github.com/filecoin-project/go-state-types/builtin/v8/init" paych8 "github.com/filecoin-project/go-state-types/builtin/v8/paych" - paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" "github.com/filecoin-project/lotus/chain/actors" init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init" diff --git a/chain/actors/builtin/paych/paych.go b/chain/actors/builtin/paych/paych.go index 20d9d255215..effd5589538 100644 --- a/chain/actors/builtin/paych/paych.go +++ b/chain/actors/builtin/paych/paych.go @@ -4,21 +4,29 @@ import ( "encoding/base64" "fmt" - ipldcbor "github.com/ipfs/go-ipld-cbor" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" "github.com/filecoin-project/go-state-types/cbor" - builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + ipldcbor "github.com/ipfs/go-ipld-cbor" + + paychtypes "github.com/filecoin-project/go-state-types/builtin/v8/paych" paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" + + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" "github.com/filecoin-project/lotus/chain/actors" diff --git a/chain/actors/builtin/paych/v0.go b/chain/actors/builtin/paych/v0.go index 727525c50da..e9bc30e3d18 100644 --- a/chain/actors/builtin/paych/v0.go +++ b/chain/actors/builtin/paych/v0.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/paych/v2.go b/chain/actors/builtin/paych/v2.go index 5852c9a645b..400305e2fb0 100644 --- a/chain/actors/builtin/paych/v2.go +++ b/chain/actors/builtin/paych/v2.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/paych" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/paych/v3.go b/chain/actors/builtin/paych/v3.go index 5297e9d10a6..1d7c2f94b06 100644 --- a/chain/actors/builtin/paych/v3.go +++ b/chain/actors/builtin/paych/v3.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/paych" - adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/paych" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/paych/v4.go b/chain/actors/builtin/paych/v4.go index be10061bfcc..b7d1e52a5b8 100644 --- a/chain/actors/builtin/paych/v4.go +++ b/chain/actors/builtin/paych/v4.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych" - adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/paych" + adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/paych/v5.go b/chain/actors/builtin/paych/v5.go index 37a91727314..b331a1500bf 100644 --- a/chain/actors/builtin/paych/v5.go +++ b/chain/actors/builtin/paych/v5.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/paych" - adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/paych" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/paych/v6.go b/chain/actors/builtin/paych/v6.go index 36676d9de09..0d60b1f03f4 100644 --- a/chain/actors/builtin/paych/v6.go +++ b/chain/actors/builtin/paych/v6.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/paych" - adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/paych" + adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/paych/v7.go b/chain/actors/builtin/paych/v7.go index 88b6f2b8449..ce09ea2e4be 100644 --- a/chain/actors/builtin/paych/v7.go +++ b/chain/actors/builtin/paych/v7.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/paych" - adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/paych" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/paych/v8.go b/chain/actors/builtin/paych/v8.go index 1961e69ec07..7936b76e132 100644 --- a/chain/actors/builtin/paych/v8.go +++ b/chain/actors/builtin/paych/v8.go @@ -6,10 +6,11 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" - paych8 "github.com/filecoin-project/go-state-types/builtin/v8/paych" - adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" "github.com/filecoin-project/lotus/chain/actors/adt" + + paych8 "github.com/filecoin-project/go-state-types/builtin/v8/paych" + adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/power/power.go b/chain/actors/builtin/power/power.go index 2f1cfa22fc4..1b79a623c48 100644 --- a/chain/actors/builtin/power/power.go +++ b/chain/actors/builtin/power/power.go @@ -1,26 +1,34 @@ package power import ( + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/chain/actors" cbg "github.com/whyrusleeping/cbor-gen" "golang.org/x/xerrors" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - builtin8 "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/cbor" + + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + "github.com/filecoin-project/lotus/chain/types" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" - "github.com/filecoin-project/lotus/chain/types" + builtin8 "github.com/filecoin-project/go-state-types/builtin" ) var ( diff --git a/chain/actors/builtin/power/v0.go b/chain/actors/builtin/power/v0.go index 5ae42b4df4f..e114ac219f8 100644 --- a/chain/actors/builtin/power/v0.go +++ b/chain/actors/builtin/power/v0.go @@ -3,16 +3,16 @@ package power import ( "bytes" - "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" + + power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/power/v2.go b/chain/actors/builtin/power/v2.go index 485819e3e8c..405bad8baed 100644 --- a/chain/actors/builtin/power/v2.go +++ b/chain/actors/builtin/power/v2.go @@ -3,16 +3,16 @@ package power import ( "bytes" - "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" + "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" + + power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/power/v3.go b/chain/actors/builtin/power/v3.go index e33ee2bb560..0ff06f617e8 100644 --- a/chain/actors/builtin/power/v3.go +++ b/chain/actors/builtin/power/v3.go @@ -3,17 +3,18 @@ package power import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + power3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/power" adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/power/v4.go b/chain/actors/builtin/power/v4.go index e5c446f07c3..f121e3b2f5a 100644 --- a/chain/actors/builtin/power/v4.go +++ b/chain/actors/builtin/power/v4.go @@ -3,17 +3,18 @@ package power import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + power4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/power" adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/power/v5.go b/chain/actors/builtin/power/v5.go index aaf24805860..851522e507c 100644 --- a/chain/actors/builtin/power/v5.go +++ b/chain/actors/builtin/power/v5.go @@ -3,17 +3,18 @@ package power import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + power5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/power" adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/power/v6.go b/chain/actors/builtin/power/v6.go index 072def6e20e..083b85f450b 100644 --- a/chain/actors/builtin/power/v6.go +++ b/chain/actors/builtin/power/v6.go @@ -3,17 +3,18 @@ package power import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + power6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/power" adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/power/v7.go b/chain/actors/builtin/power/v7.go index 0c60b03a000..af626cf3a20 100644 --- a/chain/actors/builtin/power/v7.go +++ b/chain/actors/builtin/power/v7.go @@ -3,17 +3,18 @@ package power import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + power7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/power" adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/power/v8.go b/chain/actors/builtin/power/v8.go index c23da69046c..177d3bc3dc0 100644 --- a/chain/actors/builtin/power/v8.go +++ b/chain/actors/builtin/power/v8.go @@ -3,17 +3,17 @@ package power import ( "bytes" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" - "github.com/filecoin-project/go-address" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + builtin8 "github.com/filecoin-project/go-state-types/builtin" power8 "github.com/filecoin-project/go-state-types/builtin/v8/power" adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/reward/reward.go b/chain/actors/builtin/reward/reward.go index 943386f6a86..504c8a9ba7b 100644 --- a/chain/actors/builtin/reward/reward.go +++ b/chain/actors/builtin/reward/reward.go @@ -1,21 +1,29 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors" + reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward" "golang.org/x/xerrors" - "github.com/filecoin-project/go-state-types/abi" - builtin8 "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/cbor" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" - reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" + builtin8 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/actors/builtin" "github.com/filecoin-project/lotus/chain/types" diff --git a/chain/actors/builtin/reward/v0.go b/chain/actors/builtin/reward/v0.go index 12bdee054f1..646ab3a9a63 100644 --- a/chain/actors/builtin/reward/v0.go +++ b/chain/actors/builtin/reward/v0.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward" smoothing0 "github.com/filecoin-project/specs-actors/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/reward/v2.go b/chain/actors/builtin/reward/v2.go index ed24816357b..08e9a7bc39a 100644 --- a/chain/actors/builtin/reward/v2.go +++ b/chain/actors/builtin/reward/v2.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" reward2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/reward" smoothing2 "github.com/filecoin-project/specs-actors/v2/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/reward/v3.go b/chain/actors/builtin/reward/v3.go index d9f4bf36971..fd9fa56e27e 100644 --- a/chain/actors/builtin/reward/v3.go +++ b/chain/actors/builtin/reward/v3.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" reward3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/reward" smoothing3 "github.com/filecoin-project/specs-actors/v3/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/reward/v4.go b/chain/actors/builtin/reward/v4.go index 160c72ce794..310ca04e8df 100644 --- a/chain/actors/builtin/reward/v4.go +++ b/chain/actors/builtin/reward/v4.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" reward4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/reward" smoothing4 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/reward/v5.go b/chain/actors/builtin/reward/v5.go index 838ec8f21a6..7200f7d11af 100644 --- a/chain/actors/builtin/reward/v5.go +++ b/chain/actors/builtin/reward/v5.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" reward5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/reward" smoothing5 "github.com/filecoin-project/specs-actors/v5/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/reward/v6.go b/chain/actors/builtin/reward/v6.go index e056b22f66b..010a3a87062 100644 --- a/chain/actors/builtin/reward/v6.go +++ b/chain/actors/builtin/reward/v6.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" reward6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/reward" smoothing6 "github.com/filecoin-project/specs-actors/v6/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/reward/v7.go b/chain/actors/builtin/reward/v7.go index 5fedaa43c7d..368bb3abd12 100644 --- a/chain/actors/builtin/reward/v7.go +++ b/chain/actors/builtin/reward/v7.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" reward7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/reward" smoothing7 "github.com/filecoin-project/specs-actors/v7/actors/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/reward/v8.go b/chain/actors/builtin/reward/v8.go index ecc5a94ba46..3d49063df11 100644 --- a/chain/actors/builtin/reward/v8.go +++ b/chain/actors/builtin/reward/v8.go @@ -1,15 +1,15 @@ package reward import ( + "github.com/filecoin-project/go-state-types/abi" "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin" + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" reward8 "github.com/filecoin-project/go-state-types/builtin/v8/reward" smoothing8 "github.com/filecoin-project/go-state-types/builtin/v8/util/smoothing" - - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/actors/builtin" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/system/system.go b/chain/actors/builtin/system/system.go index 24cf47d5550..64a0f3cbaea 100644 --- a/chain/actors/builtin/system/system.go +++ b/chain/actors/builtin/system/system.go @@ -1,21 +1,28 @@ package system import ( + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/types" "github.com/ipfs/go-cid" + "golang.org/x/xerrors" - builtin8 "github.com/filecoin-project/go-state-types/builtin" builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - "github.com/filecoin-project/lotus/chain/actors" - "github.com/filecoin-project/lotus/chain/actors/adt" - "github.com/filecoin-project/lotus/chain/types" + builtin8 "github.com/filecoin-project/go-state-types/builtin" ) var ( diff --git a/chain/actors/builtin/system/v0.go b/chain/actors/builtin/system/v0.go index efa0741ce9b..a5aa8e8fa1b 100644 --- a/chain/actors/builtin/system/v0.go +++ b/chain/actors/builtin/system/v0.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system0 "github.com/filecoin-project/specs-actors/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system0 "github.com/filecoin-project/specs-actors/actors/builtin/system" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/system/v2.go b/chain/actors/builtin/system/v2.go index e4fefd08d0b..aea9eff7b91 100644 --- a/chain/actors/builtin/system/v2.go +++ b/chain/actors/builtin/system/v2.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/system" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/system/v3.go b/chain/actors/builtin/system/v3.go index d2b59c8a8ad..fd5f0cd5051 100644 --- a/chain/actors/builtin/system/v3.go +++ b/chain/actors/builtin/system/v3.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/system" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/system/v4.go b/chain/actors/builtin/system/v4.go index 9528c1779fc..fbdec7e93bf 100644 --- a/chain/actors/builtin/system/v4.go +++ b/chain/actors/builtin/system/v4.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/system" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/system/v5.go b/chain/actors/builtin/system/v5.go index adc1d4553ef..3d3c27a12e4 100644 --- a/chain/actors/builtin/system/v5.go +++ b/chain/actors/builtin/system/v5.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/system" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/system/v6.go b/chain/actors/builtin/system/v6.go index 0cebadce0cd..3143088456c 100644 --- a/chain/actors/builtin/system/v6.go +++ b/chain/actors/builtin/system/v6.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/system" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/system/v7.go b/chain/actors/builtin/system/v7.go index 0009773da96..3987db8dd40 100644 --- a/chain/actors/builtin/system/v7.go +++ b/chain/actors/builtin/system/v7.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/system" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/system/v8.go b/chain/actors/builtin/system/v8.go index 48f150fb9e1..a30d5fa305f 100644 --- a/chain/actors/builtin/system/v8.go +++ b/chain/actors/builtin/system/v8.go @@ -3,9 +3,9 @@ package system import ( "github.com/ipfs/go-cid" - system8 "github.com/filecoin-project/go-state-types/builtin/v8/system" - "github.com/filecoin-project/lotus/chain/actors/adt" + + system8 "github.com/filecoin-project/go-state-types/builtin/v8/system" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/verifreg/v0.go b/chain/actors/builtin/verifreg/v0.go index 8eaf8312024..dcd34c72a21 100644 --- a/chain/actors/builtin/verifreg/v0.go +++ b/chain/actors/builtin/verifreg/v0.go @@ -1,15 +1,15 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) diff --git a/chain/actors/builtin/verifreg/v2.go b/chain/actors/builtin/verifreg/v2.go index 1857a02e426..dfe25f0540b 100644 --- a/chain/actors/builtin/verifreg/v2.go +++ b/chain/actors/builtin/verifreg/v2.go @@ -1,15 +1,15 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) diff --git a/chain/actors/builtin/verifreg/v3.go b/chain/actors/builtin/verifreg/v3.go index 98f529a6182..b7ab18080d2 100644 --- a/chain/actors/builtin/verifreg/v3.go +++ b/chain/actors/builtin/verifreg/v3.go @@ -1,16 +1,17 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" - verifreg3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/verifreg" - adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + + verifreg3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/verifreg" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" ) var _ State = (*state3)(nil) diff --git a/chain/actors/builtin/verifreg/v4.go b/chain/actors/builtin/verifreg/v4.go index 08aac0c7dd5..aee3fbdcab3 100644 --- a/chain/actors/builtin/verifreg/v4.go +++ b/chain/actors/builtin/verifreg/v4.go @@ -1,16 +1,17 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" - verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" - adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + + verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" + adt4 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" ) var _ State = (*state4)(nil) diff --git a/chain/actors/builtin/verifreg/v5.go b/chain/actors/builtin/verifreg/v5.go index 303b10cd1be..4a74e1ea811 100644 --- a/chain/actors/builtin/verifreg/v5.go +++ b/chain/actors/builtin/verifreg/v5.go @@ -1,16 +1,17 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" - verifreg5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/verifreg" - adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + + verifreg5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/verifreg" + adt5 "github.com/filecoin-project/specs-actors/v5/actors/util/adt" ) var _ State = (*state5)(nil) diff --git a/chain/actors/builtin/verifreg/v6.go b/chain/actors/builtin/verifreg/v6.go index c1bcd0071e3..a776f11493b 100644 --- a/chain/actors/builtin/verifreg/v6.go +++ b/chain/actors/builtin/verifreg/v6.go @@ -1,16 +1,17 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" - verifreg6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/verifreg" - adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + + verifreg6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/verifreg" + adt6 "github.com/filecoin-project/specs-actors/v6/actors/util/adt" ) var _ State = (*state6)(nil) diff --git a/chain/actors/builtin/verifreg/v7.go b/chain/actors/builtin/verifreg/v7.go index edce5f56092..39d72a15da1 100644 --- a/chain/actors/builtin/verifreg/v7.go +++ b/chain/actors/builtin/verifreg/v7.go @@ -1,16 +1,17 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" - verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" - adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + + verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" + adt7 "github.com/filecoin-project/specs-actors/v7/actors/util/adt" ) var _ State = (*state7)(nil) diff --git a/chain/actors/builtin/verifreg/v8.go b/chain/actors/builtin/verifreg/v8.go index 00e0636ef4a..95fdf2e6dc1 100644 --- a/chain/actors/builtin/verifreg/v8.go +++ b/chain/actors/builtin/verifreg/v8.go @@ -1,16 +1,16 @@ package verifreg import ( - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin8 "github.com/filecoin-project/go-state-types/builtin" - adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" - verifreg8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg" + "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + + builtin8 "github.com/filecoin-project/go-state-types/builtin" + adt8 "github.com/filecoin-project/go-state-types/builtin/v8/util/adt" + verifreg8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg" ) var _ State = (*state8)(nil) diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index 0e35af648b1..7c04bb73383 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -5,16 +5,25 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" - builtin8 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/go-state-types/cbor" + builtin0 "github.com/filecoin-project/specs-actors/actors/builtin" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + builtin8 "github.com/filecoin-project/go-state-types/builtin" + "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" diff --git a/chain/actors/policy/policy.go b/chain/actors/policy/policy.go index 746b19287a6..f4f04f4a986 100644 --- a/chain/actors/policy/policy.go +++ b/chain/actors/policy/policy.go @@ -3,46 +3,61 @@ package policy import ( "sort" + "github.com/filecoin-project/go-state-types/big" "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" - "github.com/filecoin-project/go-state-types/big" - builtin8 "github.com/filecoin-project/go-state-types/builtin" - market8 "github.com/filecoin-project/go-state-types/builtin/v8/market" - miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" - paych8 "github.com/filecoin-project/go-state-types/builtin/v8/paych" - verifreg8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/chain/actors" + market0 "github.com/filecoin-project/specs-actors/actors/builtin/market" miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner" - power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + + power0 "github.com/filecoin-project/specs-actors/actors/builtin/power" + builtin2 "github.com/filecoin-project/specs-actors/v2/actors/builtin" + market2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/market" miner2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/miner" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" + market3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/market" miner3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/miner" verifreg3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/verifreg" + builtin4 "github.com/filecoin-project/specs-actors/v4/actors/builtin" + market4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/market" miner4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" + builtin5 "github.com/filecoin-project/specs-actors/v5/actors/builtin" + market5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/market" miner5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/miner" verifreg5 "github.com/filecoin-project/specs-actors/v5/actors/builtin/verifreg" + builtin6 "github.com/filecoin-project/specs-actors/v6/actors/builtin" + market6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/market" miner6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/miner" verifreg6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/verifreg" + builtin7 "github.com/filecoin-project/specs-actors/v7/actors/builtin" + market7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/market" miner7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/miner" verifreg7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/verifreg" - "github.com/filecoin-project/lotus/chain/actors" + builtin8 "github.com/filecoin-project/go-state-types/builtin" + market8 "github.com/filecoin-project/go-state-types/builtin/v8/market" + miner8 "github.com/filecoin-project/go-state-types/builtin/v8/miner" + verifreg8 "github.com/filecoin-project/go-state-types/builtin/v8/verifreg" + + paych8 "github.com/filecoin-project/go-state-types/builtin/v8/paych" ) const ( diff --git a/chain/consensus/filcns/compute_state.go b/chain/consensus/filcns/compute_state.go index e735f362e18..930c83b02cc 100644 --- a/chain/consensus/filcns/compute_state.go +++ b/chain/consensus/filcns/compute_state.go @@ -8,6 +8,7 @@ import ( {{range .actorVersions}} exported{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin/exported"{{end}} /* inline-gen start */ + exported0 "github.com/filecoin-project/specs-actors/actors/builtin/exported" exported2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/exported" exported3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/exported" @@ -16,7 +17,6 @@ import ( exported6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/exported" exported7 "github.com/filecoin-project/specs-actors/v7/actors/builtin/exported" exported8 "github.com/filecoin-project/specs-actors/v8/actors/builtin/exported" - /* inline-gen end */ "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" diff --git a/chain/exchange/cbor_gen.go b/chain/exchange/cbor_gen.go index d1eb271e99a..9c7f68ab8e1 100644 --- a/chain/exchange/cbor_gen.go +++ b/chain/exchange/cbor_gen.go @@ -8,11 +8,10 @@ import ( "math" "sort" + types "github.com/filecoin-project/lotus/chain/types" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" - - types "github.com/filecoin-project/lotus/chain/types" ) var _ = xerrors.Errorf diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index 78a3449ee82..79ff5d19c49 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -8,14 +8,13 @@ import ( "math" "sort" - cid "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - xerrors "golang.org/x/xerrors" - abi "github.com/filecoin-project/go-state-types/abi" crypto "github.com/filecoin-project/go-state-types/crypto" exitcode "github.com/filecoin-project/go-state-types/exitcode" proof "github.com/filecoin-project/go-state-types/proof" + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" ) var _ = xerrors.Errorf diff --git a/chain/vm/cbor_gen.go b/chain/vm/cbor_gen.go index 64b623f635d..0e1677c95e2 100644 --- a/chain/vm/cbor_gen.go +++ b/chain/vm/cbor_gen.go @@ -8,11 +8,10 @@ import ( "math" "sort" + types "github.com/filecoin-project/lotus/chain/types" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" - - types "github.com/filecoin-project/lotus/chain/types" ) var _ = xerrors.Errorf diff --git a/cli/servicesmock_test.go b/cli/servicesmock_test.go index 11260ab08be..5bae52a5ebc 100644 --- a/cli/servicesmock_test.go +++ b/cli/servicesmock_test.go @@ -8,14 +8,12 @@ import ( context "context" reflect "reflect" - gomock "github.com/golang/mock/gomock" - go_address "github.com/filecoin-project/go-address" abi "github.com/filecoin-project/go-state-types/abi" big "github.com/filecoin-project/go-state-types/big" - api "github.com/filecoin-project/lotus/api" types "github.com/filecoin-project/lotus/chain/types" + gomock "github.com/golang/mock/gomock" ) // MockServicesAPI is a mock of ServicesAPI interface. diff --git a/conformance/chaos/cbor_gen.go b/conformance/chaos/cbor_gen.go index 2deaaa53f57..436849cdc85 100644 --- a/conformance/chaos/cbor_gen.go +++ b/conformance/chaos/cbor_gen.go @@ -8,13 +8,12 @@ import ( "math" "sort" - cid "github.com/ipfs/go-cid" - cbg "github.com/whyrusleeping/cbor-gen" - xerrors "golang.org/x/xerrors" - address "github.com/filecoin-project/go-address" abi "github.com/filecoin-project/go-state-types/abi" exitcode "github.com/filecoin-project/go-state-types/exitcode" + cid "github.com/ipfs/go-cid" + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" ) var _ = xerrors.Errorf diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 92bdc14c0a1..b2525c814bc 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -2655,7 +2655,7 @@ Inputs: }, "ID": "07070707-0707-0707-0707-070707070707" }, - "Bw==", + "eyJjb21tX2QiOlsxLDIsMyw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJjb21tX3IiOls4Nyw3NSw1NCw4MCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwicmVnaXN0ZXJlZF9wcm9vZiI6IlN0YWNrZWREcmcyS2lCVjEiLCJyZXBsaWNhX2lkIjpbOTgsNyw1LDM2LDgsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJzZWVkIjpbOTksOTksOTksOTksMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInRpY2tldCI6Wzg5LDk5LDk5LDk5LDk5LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwidmFuaWxsYV9wcm9vZnMiOnsiU3RhY2tlZERyZzJLaUJWMSI6W1t7ImNvbW1fZF9wcm9vZnMiOnsiZGF0YSI6eyJTaW5nbGUiOnsicm9vdCI6WzEsMiwzLDQsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sImxlYWYiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJwYXRoIjp7InBhdGgiOlt7Ikhhc2hlcyI6W1s1LDYsOCw5LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLFs5LDcsNSw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiaW5kZXgiOjB9XX19fX0sImNlbW1fcl9sYXN0X3Byb29mIjp7ImRhdGEiOnsiU2luZ2xlIjp7InJvb3QiOls4Nyw3NSw1NCw4MCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwibGVhZiI6Wzg5LDQ1LDIzOSwxNDYsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInBhdGgiOnsicGF0aCI6W3siSGFzaGVzIjpbWzE0NSwzNSwxMzIsMzYsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sWzIzLDI0LDIzNyw5NCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXV0sImluZGV4IjowfV19fX19LCJyZXBsaWNhX2NvbHVtbl9wcm9vZnMiOnsiY194Ijp7ImNvbHVtbiI6eyJpbmRleCI6Miwicm93cyI6W1s5LDcsNSw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiX2giOm51bGx9LCJpbmNsdXNpb25fcHJvb2YiOnsiZGF0YSI6eyJTaW5nbGUiOnsicm9vdCI6WzYzLDgzLDEyLDg1LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJsZWFmIjpbNDIsMTYsNTIsMjM1LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJwYXRoIjp7InBhdGgiOlt7Ikhhc2hlcyI6W1sxNCw5NiwzNCwxMiwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSxbODYsMTQsMzQsNzQsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF1dLCJpbmRleCI6MH1dfX19fX0sImRyZ19wYXJlbnRzIjpbeyJjb2x1bW4iOnsiaW5kZXgiOjI0LCJyb3dzIjpbWzIzNCwyMyw0NywyMywwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXV0sIl9oIjpudWxsfSwiaW5jbHVzaW9uX3Byb29mIjp7ImRhdGEiOnsiU2luZ2xlIjp7InJvb3QiOls2Myw4MywxMiw4NSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwibGVhZiI6WzQyLDE2LDUyLDIzNSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwicGF0aCI6eyJwYXRoIjpbeyJIYXNoZXMiOltbMTQsOTYsMzQsMTIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sWzg2LDE0LDM0LDc0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiaW5kZXgiOjB9XX19fX19XSwiZXhwX3BhcmVudHMiOlt7ImNvbHVtbiI6eyJpbmRleCI6NTIsInJvd3MiOltbOTgsNTUsNDQsODcsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF1dLCJfaCI6bnVsbH0sImluY2x1c2lvbl9wcm9vZiI6eyJkYXRhIjp7IlNpbmdsZSI6eyJyb290IjpbNiw4MywxMiw4NSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwibGVhZiI6WzQyLDE2LDIsMjM1LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJwYXRoIjp7InBhdGgiOlt7Ikhhc2hlcyI6W1sxNCw2LDM0LDEyLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLFs4NiwxNCwzNCw3LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiaW5kZXgiOjB9XX19fX19XX0sImxhYmVsaW5nX3Byb29mcyI6W3sicGFyZW50cyI6W1swLDgsNiw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwibGF5ZXJfaW5kZXgiOjAsIm5vZGUiOjAsIl9oIjpudWxsfV0sImVuY29kaW5nX3Byb29mIjp7InBhcmVudHMiOltbOCw2LDQsMywwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXV0sImxheWVyX2luZGV4IjowLCJub2RlIjowLCJfaCI6bnVsbH19XV19fQ==", { "Code": 0, "Message": "string value" @@ -2705,7 +2705,7 @@ Inputs: }, "ID": "07070707-0707-0707-0707-070707070707" }, - "Bw==", + "eyJfbG90dXNfU2VhbFJhbmRvbW5lc3MiOiJZbmwwWlNCaGNuSmhlUT09IiwiY29tbV9kIjpbNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3XSwiY29uZmlnIjp7ImlkIjoic3RyaW5nIHZhbHVlIiwicGF0aCI6InN0cmluZyB2YWx1ZSIsInJvd3NfdG9fZGlzY2FyZCI6MTIzLCJzaXplIjoxMjN9LCJsYWJlbHMiOnsiU3RhY2tlZERyZzJLaUJWMSI6eyJfaCI6bnVsbCwibGFiZWxzIjpbeyJpZCI6ImxheWVyLTEiLCJwYXRoIjoiL3RtcC9zZWN0b3ItcGF0aC9jYWNoZS9zMC10MDEwMDAtMTIzNCIsInJvd3NfdG9fZGlzY2FyZCI6NSwic2l6ZSI6NjR9XX19LCJyZWdpc3RlcmVkX3Byb29mIjoiU3RhY2tlZERyZzJLaUJWMSJ9", { "Code": 0, "Message": "string value" @@ -3201,7 +3201,7 @@ Inputs: ], "TicketValue": "Bw==", "TicketEpoch": 10101, - "PreCommit1Out": "Bw==", + "PreCommit1Out": "eyJfbG90dXNfU2VhbFJhbmRvbW5lc3MiOiJZbmwwWlNCaGNuSmhlUT09IiwiY29tbV9kIjpbNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3XSwiY29uZmlnIjp7ImlkIjoic3RyaW5nIHZhbHVlIiwicGF0aCI6InN0cmluZyB2YWx1ZSIsInJvd3NfdG9fZGlzY2FyZCI6MTIzLCJzaXplIjoxMjN9LCJsYWJlbHMiOnsiU3RhY2tlZERyZzJLaUJWMSI6eyJfaCI6bnVsbCwibGFiZWxzIjpbeyJpZCI6ImxheWVyLTEiLCJwYXRoIjoiL3RtcC9zZWN0b3ItcGF0aC9jYWNoZS9zMC10MDEwMDAtMTIzNCIsInJvd3NfdG9fZGlzY2FyZCI6NSwic2l6ZSI6NjR9XX19LCJyZWdpc3RlcmVkX3Byb29mIjoiU3RhY2tlZERyZzJLaUJWMSJ9", "CommD": null, "CommR": null, "PreCommitInfo": { diff --git a/documentation/en/api-v0-methods-worker.md b/documentation/en/api-v0-methods-worker.md index e532110890c..6908be9a211 100644 --- a/documentation/en/api-v0-methods-worker.md +++ b/documentation/en/api-v0-methods-worker.md @@ -2045,7 +2045,7 @@ Inputs: }, "ProofType": 8 }, - "Bw==" + "eyJjb21tX2QiOlsxLDIsMyw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJjb21tX3IiOls4Nyw3NSw1NCw4MCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwicmVnaXN0ZXJlZF9wcm9vZiI6IlN0YWNrZWREcmcyS2lCVjEiLCJyZXBsaWNhX2lkIjpbOTgsNyw1LDM2LDgsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJzZWVkIjpbOTksOTksOTksOTksMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInRpY2tldCI6Wzg5LDk5LDk5LDk5LDk5LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwidmFuaWxsYV9wcm9vZnMiOnsiU3RhY2tlZERyZzJLaUJWMSI6W1t7ImNvbW1fZF9wcm9vZnMiOnsiZGF0YSI6eyJTaW5nbGUiOnsicm9vdCI6WzEsMiwzLDQsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sImxlYWYiOlswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJwYXRoIjp7InBhdGgiOlt7Ikhhc2hlcyI6W1s1LDYsOCw5LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLFs5LDcsNSw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiaW5kZXgiOjB9XX19fX0sImNlbW1fcl9sYXN0X3Byb29mIjp7ImRhdGEiOnsiU2luZ2xlIjp7InJvb3QiOls4Nyw3NSw1NCw4MCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwibGVhZiI6Wzg5LDQ1LDIzOSwxNDYsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sInBhdGgiOnsicGF0aCI6W3siSGFzaGVzIjpbWzE0NSwzNSwxMzIsMzYsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sWzIzLDI0LDIzNyw5NCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXV0sImluZGV4IjowfV19fX19LCJyZXBsaWNhX2NvbHVtbl9wcm9vZnMiOnsiY194Ijp7ImNvbHVtbiI6eyJpbmRleCI6Miwicm93cyI6W1s5LDcsNSw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiX2giOm51bGx9LCJpbmNsdXNpb25fcHJvb2YiOnsiZGF0YSI6eyJTaW5nbGUiOnsicm9vdCI6WzYzLDgzLDEyLDg1LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJsZWFmIjpbNDIsMTYsNTIsMjM1LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJwYXRoIjp7InBhdGgiOlt7Ikhhc2hlcyI6W1sxNCw5NiwzNCwxMiwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSxbODYsMTQsMzQsNzQsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF1dLCJpbmRleCI6MH1dfX19fX0sImRyZ19wYXJlbnRzIjpbeyJjb2x1bW4iOnsiaW5kZXgiOjI0LCJyb3dzIjpbWzIzNCwyMyw0NywyMywwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXV0sIl9oIjpudWxsfSwiaW5jbHVzaW9uX3Byb29mIjp7ImRhdGEiOnsiU2luZ2xlIjp7InJvb3QiOls2Myw4MywxMiw4NSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwibGVhZiI6WzQyLDE2LDUyLDIzNSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwicGF0aCI6eyJwYXRoIjpbeyJIYXNoZXMiOltbMTQsOTYsMzQsMTIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF0sWzg2LDE0LDM0LDc0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiaW5kZXgiOjB9XX19fX19XSwiZXhwX3BhcmVudHMiOlt7ImNvbHVtbiI6eyJpbmRleCI6NTIsInJvd3MiOltbOTgsNTUsNDQsODcsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF1dLCJfaCI6bnVsbH0sImluY2x1c2lvbl9wcm9vZiI6eyJkYXRhIjp7IlNpbmdsZSI6eyJyb290IjpbNiw4MywxMiw4NSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXSwibGVhZiI6WzQyLDE2LDIsMjM1LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLCJwYXRoIjp7InBhdGgiOlt7Ikhhc2hlcyI6W1sxNCw2LDM0LDEyLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdLFs4NiwxNCwzNCw3LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwiaW5kZXgiOjB9XX19fX19XX0sImxhYmVsaW5nX3Byb29mcyI6W3sicGFyZW50cyI6W1swLDgsNiw0LDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdXSwibGF5ZXJfaW5kZXgiOjAsIm5vZGUiOjAsIl9oIjpudWxsfV0sImVuY29kaW5nX3Byb29mIjp7InBhcmVudHMiOltbOCw2LDQsMywwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXV0sImxheWVyX2luZGV4IjowLCJub2RlIjowLCJfaCI6bnVsbH19XV19fQ==" ] ``` @@ -2113,7 +2113,7 @@ Inputs: }, "ProofType": 8 }, - "Bw==" + "eyJfbG90dXNfU2VhbFJhbmRvbW5lc3MiOiJZbmwwWlNCaGNuSmhlUT09IiwiY29tbV9kIjpbNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3LDcsNyw3XSwiY29uZmlnIjp7ImlkIjoic3RyaW5nIHZhbHVlIiwicGF0aCI6InN0cmluZyB2YWx1ZSIsInJvd3NfdG9fZGlzY2FyZCI6MTIzLCJzaXplIjoxMjN9LCJsYWJlbHMiOnsiU3RhY2tlZERyZzJLaUJWMSI6eyJfaCI6bnVsbCwibGFiZWxzIjpbeyJpZCI6ImxheWVyLTEiLCJwYXRoIjoiL3RtcC9zZWN0b3ItcGF0aC9jYWNoZS9zMC10MDEwMDAtMTIzNCIsInJvd3NfdG9fZGlzY2FyZCI6NSwic2l6ZSI6NjR9XX19LCJyZWdpc3RlcmVkX3Byb29mIjoiU3RhY2tlZERyZzJLaUJWMSJ9" ] ``` diff --git a/itests/sector_import_simple_test.go b/itests/sector_import_simple_test.go index 94c1e681031..e74f6d28dac 100644 --- a/itests/sector_import_simple_test.go +++ b/itests/sector_import_simple_test.go @@ -117,6 +117,8 @@ func TestSectorImportAfterPC2(t *testing.T) { pc1out, err := sealer.SealPreCommit1(ctx, sref, abi.SealRandomness(rand), []abi.PieceInfo{pieceInfo}) require.NoError(t, err) + os.WriteFile("/tmp/pc1", pc1out, 0666) + // run pc2 scids, err := sealer.SealPreCommit2(ctx, sref, pc1out) require.NoError(t, err) @@ -239,6 +241,9 @@ func remoteCommit1(s *ffiwrapper.Sealer) func(w http.ResponseWriter, r *http.Req Unsealed: params.Unsealed, Sealed: params.Sealed, }) + + os.WriteFile("/tmp/c1", p, 0666) + if err != nil { w.WriteHeader(500) return diff --git a/journal/mockjournal/journal.go b/journal/mockjournal/journal.go index 842c252bd76..3668923e5be 100644 --- a/journal/mockjournal/journal.go +++ b/journal/mockjournal/journal.go @@ -7,9 +7,8 @@ package mockjournal import ( reflect "reflect" - gomock "github.com/golang/mock/gomock" - journal "github.com/filecoin-project/lotus/journal" + gomock "github.com/golang/mock/gomock" ) // MockJournal is a mock of Journal interface. diff --git a/lib/jsonfield/jsonbytes.go b/lib/jsonfield/jsonbytes.go new file mode 100644 index 00000000000..90428b3f237 --- /dev/null +++ b/lib/jsonfield/jsonbytes.go @@ -0,0 +1,111 @@ +package jsonfield + +import ( + "encoding/json" + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" +) + +// JSONBytes is a wrapper for types which are marshalled into a base64 encoded json-string +type JSONBytes[T any] struct { + Data T +} + +func NewJsonBytes[T any](data T) *JSONBytes[T] { + return &JSONBytes[T]{ + Data: data, + } +} + +func JsonBytesFrom[T any](data []byte) (out JSONBytes[T], err error) { + err = out.UnmarshalJSON(data) + return +} + +func (j *JSONBytes[T]) MarshalJSON() ([]byte, error) { + jb, err := json.Marshal(&j.Data) + if err != nil { + return nil, err + } + + return json.Marshal(jb) +} + +func (j *JSONBytes[T]) UnmarshalJSON(data []byte) error { + var js []byte + if err := json.Unmarshal(data, &js); err != nil { + return err + } + + return json.Unmarshal(js, &j.Data) +} + +func (j *JSONBytes[T]) MarshalCBOR(w io.Writer) error { + if j == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + jb, err := json.Marshal(&j.Data) + if err != nil { + return err + } + + cw := cbg.NewCborWriter(w) + + if len(jb) > cbg.ByteArrayMaxLen { + return xerrors.Errorf("byte array in JSONBytes field was too long") + } + + if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(jb))); err != nil { + return err + } + + if _, err := cw.Write(jb[:]); err != nil { + return err + } + + return nil +} + +func (j *JSONBytes[T]) UnmarshalCBOR(r io.Reader) (err error) { + cr := cbg.NewCborReader(r) + + maj, extra, err := cr.ReadHeader() + if err != nil { + return err + } + defer func() { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + }() + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("JSONBytes byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + + var jb []byte + + if extra > 0 { + jb = make([]byte, extra) + } + + if _, err := io.ReadFull(cr, jb[:]); err != nil { + return err + } + + jj, err := JsonBytesFrom[T](jb) + if err != nil { + return err + } + + *j = jj + return nil +} diff --git a/lib/jsonfield/jsonfield_test.go b/lib/jsonfield/jsonfield_test.go new file mode 100644 index 00000000000..a9050f79268 --- /dev/null +++ b/lib/jsonfield/jsonfield_test.go @@ -0,0 +1,58 @@ +package jsonfield + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestJsonBytes(t *testing.T) { + type dt struct { + I int + St string + } + + var data dt + + data.I = 20 + data.St = "eouid" + + rawJson, err := json.Marshal(&data) + require.NoError(t, err) + require.Equal(t, `{"I":20,"St":"eouid"}`, string(rawJson)) + + strFieldJson, err := json.Marshal(&JSONBytes[dt]{data}) + require.NoError(t, err) + require.Equal(t, `"eyJJIjoyMCwiU3QiOiJlb3VpZCJ9"`, string(strFieldJson)) + + var un JSONBytes[dt] + require.NoError(t, json.Unmarshal(strFieldJson, &un)) + require.Equal(t, 20, un.Data.I) + require.Equal(t, "eouid", un.Data.St) +} + +func TestJsonBytesField(t *testing.T) { + type dt struct { + I int + St string + } + + type wrapT struct { + F JSONBytes[dt] + } + + var data wrapT + + data.F.Data.I = 20 + data.F.Data.St = "eouid" + + strFieldJson, err := json.Marshal(&data) + require.NoError(t, err) + require.Equal(t, `{"F":"eyJJIjoyMCwiU3QiOiJlb3VpZCJ9"}`, string(strFieldJson)) + + var un wrapT + require.NoError(t, json.Unmarshal(strFieldJson, &un)) + require.Equal(t, 20, un.F.Data.I) + require.Equal(t, "eouid", un.F.Data.St) +} diff --git a/markets/dagstore/mocks/mock_lotus_accessor.go b/markets/dagstore/mocks/mock_lotus_accessor.go index 3910512cf2e..19923cc2ae6 100644 --- a/markets/dagstore/mocks/mock_lotus_accessor.go +++ b/markets/dagstore/mocks/mock_lotus_accessor.go @@ -8,10 +8,9 @@ import ( context "context" reflect "reflect" + mount "github.com/filecoin-project/dagstore/mount" gomock "github.com/golang/mock/gomock" cid "github.com/ipfs/go-cid" - - mount "github.com/filecoin-project/dagstore/mount" ) // MockMinerAPI is a mock of MinerAPI interface. diff --git a/node/hello/cbor_gen.go b/node/hello/cbor_gen.go index 81a1774c17e..68c82e2bbee 100644 --- a/node/hello/cbor_gen.go +++ b/node/hello/cbor_gen.go @@ -8,11 +8,10 @@ import ( "math" "sort" + abi "github.com/filecoin-project/go-state-types/abi" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" - - abi "github.com/filecoin-project/go-state-types/abi" ) var _ = xerrors.Errorf diff --git a/paychmgr/cbor_gen.go b/paychmgr/cbor_gen.go index 78a55488ea2..450d526d858 100644 --- a/paychmgr/cbor_gen.go +++ b/paychmgr/cbor_gen.go @@ -8,12 +8,11 @@ import ( "math" "sort" + address "github.com/filecoin-project/go-address" + paych "github.com/filecoin-project/go-state-types/builtin/v8/paych" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" - - address "github.com/filecoin-project/go-address" - paych "github.com/filecoin-project/go-state-types/builtin/v8/paych" ) var _ = xerrors.Errorf diff --git a/storage/paths/mocks/index.go b/storage/paths/mocks/index.go index 6fdcb03b9ec..fa2c8c8301b 100644 --- a/storage/paths/mocks/index.go +++ b/storage/paths/mocks/index.go @@ -8,12 +8,10 @@ import ( context "context" reflect "reflect" - gomock "github.com/golang/mock/gomock" - abi "github.com/filecoin-project/go-state-types/abi" - fsutil "github.com/filecoin-project/lotus/storage/sealer/fsutil" storiface "github.com/filecoin-project/lotus/storage/sealer/storiface" + gomock "github.com/golang/mock/gomock" ) // MockSectorIndex is a mock of SectorIndex interface. diff --git a/storage/paths/mocks/pf.go b/storage/paths/mocks/pf.go index 50b020aaa8f..7c4836a68c7 100644 --- a/storage/paths/mocks/pf.go +++ b/storage/paths/mocks/pf.go @@ -8,12 +8,10 @@ import ( os "os" reflect "reflect" - gomock "github.com/golang/mock/gomock" - abi "github.com/filecoin-project/go-state-types/abi" - partialfile "github.com/filecoin-project/lotus/storage/sealer/partialfile" storiface "github.com/filecoin-project/lotus/storage/sealer/storiface" + gomock "github.com/golang/mock/gomock" ) // MockPartialFileHandler is a mock of PartialFileHandler interface. diff --git a/storage/paths/mocks/store.go b/storage/paths/mocks/store.go index 72be4832378..16deda2e503 100644 --- a/storage/paths/mocks/store.go +++ b/storage/paths/mocks/store.go @@ -8,12 +8,10 @@ import ( context "context" reflect "reflect" - gomock "github.com/golang/mock/gomock" - abi "github.com/filecoin-project/go-state-types/abi" - fsutil "github.com/filecoin-project/lotus/storage/sealer/fsutil" storiface "github.com/filecoin-project/lotus/storage/sealer/storiface" + gomock "github.com/golang/mock/gomock" ) // MockStore is a mock of Store interface. diff --git a/storage/pipeline/cbor_gen.go b/storage/pipeline/cbor_gen.go index fb95c5597b4..ada5d148a67 100644 --- a/storage/pipeline/cbor_gen.go +++ b/storage/pipeline/cbor_gen.go @@ -190,7 +190,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { } } - // t.PreCommit1Out (storiface.PreCommit1Out) (slice) + // t.PreCommit1Out (jsonfield.JSONBytes[github.com/filecoin-project/lotus/storage/sealer/storiface.PreCommit1OutRaw]) (struct) if len("PreCommit1Out") > cbg.MaxLength { return xerrors.Errorf("Value in field \"PreCommit1Out\" was too long") } @@ -202,15 +202,7 @@ func (t *SectorInfo) MarshalCBOR(w io.Writer) error { return err } - if len(t.PreCommit1Out) > cbg.ByteArrayMaxLen { - return xerrors.Errorf("Byte array in field t.PreCommit1Out was too long") - } - - if err := cw.WriteMajorTypeHeader(cbg.MajByteString, uint64(len(t.PreCommit1Out))); err != nil { - return err - } - - if _, err := cw.Write(t.PreCommit1Out[:]); err != nil { + if err := t.PreCommit1Out.MarshalCBOR(cw); err != nil { return err } @@ -1049,27 +1041,15 @@ func (t *SectorInfo) UnmarshalCBOR(r io.Reader) (err error) { t.TicketEpoch = abi.ChainEpoch(extraI) } - // t.PreCommit1Out (storiface.PreCommit1Out) (slice) + // t.PreCommit1Out (jsonfield.JSONBytes[github.com/filecoin-project/lotus/storage/sealer/storiface.PreCommit1OutRaw]) (struct) case "PreCommit1Out": - maj, extra, err = cr.ReadHeader() - if err != nil { - return err - } - - if extra > cbg.ByteArrayMaxLen { - return fmt.Errorf("t.PreCommit1Out: byte array too large (%d)", extra) - } - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } + { - if extra > 0 { - t.PreCommit1Out = make([]uint8, extra) - } + if err := t.PreCommit1Out.UnmarshalCBOR(cr); err != nil { + return xerrors.Errorf("unmarshaling t.PreCommit1Out: %w", err) + } - if _, err := io.ReadFull(cr, t.PreCommit1Out[:]); err != nil { - return err } // t.CommD (cid.Cid) (struct) case "CommD": diff --git a/storage/pipeline/mocks/mock_commit_batcher.go b/storage/pipeline/mocks/mock_commit_batcher.go index d61fde91228..01b63b67350 100644 --- a/storage/pipeline/mocks/mock_commit_batcher.go +++ b/storage/pipeline/mocks/mock_commit_batcher.go @@ -8,16 +8,14 @@ import ( context "context" reflect "reflect" - gomock "github.com/golang/mock/gomock" - address "github.com/filecoin-project/go-address" abi "github.com/filecoin-project/go-state-types/abi" big "github.com/filecoin-project/go-state-types/big" miner "github.com/filecoin-project/go-state-types/builtin/v8/miner" network "github.com/filecoin-project/go-state-types/network" - api "github.com/filecoin-project/lotus/api" types "github.com/filecoin-project/lotus/chain/types" + gomock "github.com/golang/mock/gomock" ) // MockCommitBatcherApi is a mock of CommitBatcherApi interface. diff --git a/storage/pipeline/states_sealing.go b/storage/pipeline/states_sealing.go index 786334ab843..24ff34c69ea 100644 --- a/storage/pipeline/states_sealing.go +++ b/storage/pipeline/states_sealing.go @@ -608,10 +608,14 @@ func (m *Sealing) handleCommitting(ctx statemachine.Context, sector SectorInfo) return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("remote commit1 received non-200 http response %s", resp.Status)}) } - c2in, err = io.ReadAll(resp.Body) // todo some len constraint + c1bytes, err := io.ReadAll(resp.Body) // todo some len constraint if err != nil { return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("reading commit1 response: %w", err)}) } + + if err := c2in.UnmarshalJSON(c1bytes); err != nil { + return ctx.Send(SectorRemoteCommit1Failed{xerrors.Errorf("unmarshaling commit1 response: %w", err)}) + } } var porepProof storiface.Proof diff --git a/storage/sealer/cbor_gen.go b/storage/sealer/cbor_gen.go index 48bf0146a45..6db7d96a4ec 100644 --- a/storage/sealer/cbor_gen.go +++ b/storage/sealer/cbor_gen.go @@ -8,11 +8,10 @@ import ( "math" "sort" + sealtasks "github.com/filecoin-project/lotus/storage/sealer/sealtasks" cid "github.com/ipfs/go-cid" cbg "github.com/whyrusleeping/cbor-gen" xerrors "golang.org/x/xerrors" - - sealtasks "github.com/filecoin-project/lotus/storage/sealer/sealtasks" ) var _ = xerrors.Errorf diff --git a/storage/sealer/ffiwrapper/sealer_cgo.go b/storage/sealer/ffiwrapper/sealer_cgo.go index d73b7278735..6dcd77462f2 100644 --- a/storage/sealer/ffiwrapper/sealer_cgo.go +++ b/storage/sealer/ffiwrapper/sealer_cgo.go @@ -8,8 +8,6 @@ import ( "bytes" "context" "crypto/rand" - "encoding/base64" - "encoding/json" "io" "io/ioutil" "math/bits" @@ -30,6 +28,7 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/proof" + "github.com/filecoin-project/lotus/lib/jsonfield" "github.com/filecoin-project/lotus/lib/nullreader" spaths "github.com/filecoin-project/lotus/storage/paths" nr "github.com/filecoin-project/lotus/storage/pipeline/lib/nullreader" @@ -778,14 +777,13 @@ func (sb *Sealer) SealPreCommit1(ctx context.Context, sector storiface.SectorRef return nil, xerrors.Errorf("presealing sector %d (%s): %w", sector.ID.Number, paths.Unsealed, err) } - p1odec := map[string]interface{}{} - if err := json.Unmarshal(p1o, &p1odec); err != nil { + p1out, err := jsonfield.JsonBytesFrom[storiface.PreCommit1OutRaw](p1o) + if err != nil { return nil, xerrors.Errorf("unmarshaling pc1 output: %w", err) } + p1out.Data.LotusSealRand = ticket - p1odec["_lotus_SealRandomness"] = ticket - - return json.Marshal(&p1odec) + return &p1out, nil } var PC2CheckRounds = 3 @@ -797,7 +795,12 @@ func (sb *Sealer) SealPreCommit2(ctx context.Context, sector storiface.SectorRef } defer done() - sealedCID, unsealedCID, err := ffi.SealPreCommitPhase2(phase1Out, paths.Cache, paths.Sealed) + p1bytes, err := phase1Out.MarshalJSON() + if err != nil { + return storiface.SectorCids{}, err + } + + sealedCID, unsealedCID, err := ffi.SealPreCommitPhase2(p1bytes, paths.Cache, paths.Sealed) if err != nil { return storiface.SectorCids{}, xerrors.Errorf("presealing sector %d (%s): %w", sector.ID.Number, paths.Unsealed, err) } @@ -807,20 +810,7 @@ func (sb *Sealer) SealPreCommit2(ctx context.Context, sector storiface.SectorRef return storiface.SectorCids{}, xerrors.Errorf("get ssize: %w", err) } - p1odec := map[string]interface{}{} - if err := json.Unmarshal(phase1Out, &p1odec); err != nil { - return storiface.SectorCids{}, xerrors.Errorf("unmarshaling pc1 output: %w", err) - } - - var ticket abi.SealRandomness - ti, found := p1odec["_lotus_SealRandomness"] - - if found { - ticket, err = base64.StdEncoding.DecodeString(ti.(string)) - if err != nil { - return storiface.SectorCids{}, xerrors.Errorf("decoding ticket: %w", err) - } - + if len(phase1Out.Data.LotusSealRand) > 0 { for i := 0; i < PC2CheckRounds; i++ { var sd [32]byte _, _ = rand.Read(sd[:]) @@ -833,13 +823,13 @@ func (sb *Sealer) SealPreCommit2(ctx context.Context, sector storiface.SectorRef paths.Sealed, sector.ID.Number, sector.ID.Miner, - ticket, + phase1Out.Data.LotusSealRand, sd[:], []abi.PieceInfo{{Size: abi.PaddedPieceSize(ssize), PieceCID: unsealedCID}}, ) if err != nil { log.Warn("checking PreCommit failed: ", err) - log.Warnf("num:%d tkt:%v seed:%v sealedCID:%v, unsealedCID:%v", sector.ID.Number, ticket, sd[:], sealedCID, unsealedCID) + log.Warnf("num:%d tkt:%v seed:%v sealedCID:%v, unsealedCID:%v", sector.ID.Number, phase1Out.Data.LotusSealRand, sd[:], sealedCID, unsealedCID) return storiface.SectorCids{}, xerrors.Errorf("checking PreCommit failed: %w", err) } @@ -858,7 +848,7 @@ func (sb *Sealer) SealCommit1(ctx context.Context, sector storiface.SectorRef, t return nil, xerrors.Errorf("acquire sector paths: %w", err) } defer done() - output, err := ffi.SealCommitPhase1( + rawOut, err := ffi.SealCommitPhase1( sector.ProofType, cids.Sealed, cids.Unsealed, @@ -876,11 +866,22 @@ func (sb *Sealer) SealCommit1(ctx context.Context, sector storiface.SectorRef, t return nil, xerrors.Errorf("StandaloneSealCommit: %w", err) } - return output, nil + + out, err := jsonfield.JsonBytesFrom[storiface.Commit1OutRaw](rawOut) + if err != nil { + return nil, xerrors.Errorf("unmarshaling c1 output: %w", err) + } + + return &out, nil } func (sb *Sealer) SealCommit2(ctx context.Context, sector storiface.SectorRef, phase1Out storiface.Commit1Out) (storiface.Proof, error) { - return ffi.SealCommitPhase2(phase1Out, sector.ID.Number, sector.ID.Miner) + p1b, err := phase1Out.MarshalJSON() + if err != nil { + return nil, xerrors.Errorf("marshaling phase1 out: %w", err) + } + + return ffi.SealCommitPhase2(p1b, sector.ID.Number, sector.ID.Miner) } func (sb *Sealer) ReplicaUpdate(ctx context.Context, sector storiface.SectorRef, pieces []abi.PieceInfo) (storiface.ReplicaUpdateOut, error) { diff --git a/storage/sealer/manager.go b/storage/sealer/manager.go index a4d31e21b8a..577182cfabb 100644 --- a/storage/sealer/manager.go +++ b/storage/sealer/manager.go @@ -563,7 +563,7 @@ func (m *Manager) SealCommit1(ctx context.Context, sector storiface.SectorRef, t wk, wait, cancel, err := m.getWork(ctx, sealtasks.TTCommit1, sector, ticket, seed, pieces, cids) if err != nil { - return storiface.Commit1Out{}, xerrors.Errorf("getWork: %w", err) + return nil, xerrors.Errorf("getWork: %w", err) } defer cancel() @@ -585,7 +585,7 @@ func (m *Manager) SealCommit1(ctx context.Context, sector storiface.SectorRef, t } if err := m.index.StorageLock(ctx, sector.ID, storiface.FTSealed, storiface.FTCache); err != nil { - return storiface.Commit1Out{}, xerrors.Errorf("acquiring sector lock: %w", err) + return nil, xerrors.Errorf("acquiring sector lock: %w", err) } // NOTE: We set allowFetch to false in so that we always execute on a worker diff --git a/storage/sealer/storiface/storage.go b/storage/sealer/storiface/storage.go index 5246a1a1a14..38b64ce7853 100644 --- a/storage/sealer/storiface/storage.go +++ b/storage/sealer/storiface/storage.go @@ -28,10 +28,6 @@ type ProverPoSt interface { GenerateWindowPoStWithVanilla(ctx context.Context, proofType abi.RegisteredPoStProof, minerID abi.ActorID, randomness abi.PoStRandomness, proofs [][]byte, partitionIdx int) (proof.PoStProof, error) } -type PreCommit1Out []byte - -type Commit1Out []byte - type Proof []byte type SectorCids struct { diff --git a/storage/sealer/storiface/types_proofs.go b/storage/sealer/storiface/types_proofs.go new file mode 100644 index 00000000000..33f38c29c1a --- /dev/null +++ b/storage/sealer/storiface/types_proofs.go @@ -0,0 +1,140 @@ +package storiface + +import "github.com/filecoin-project/lotus/lib/jsonfield" + +// This file contains some type definitions from +// - https://github.com/filecoin-project/rust-fil-proofs/tree/master/storage-proofs-core/src/merkle +// - https://github.com/filecoin-project/rust-fil-proofs/tree/master/storage-proofs-porep/src/stacked/vanilla +// - https://github.com/filecoin-project/rust-filecoin-proofs-api/tree/master/src + +// core + +type Commitment [32]byte +type Ticket [32]byte + +type StringRegisteredProofType string // e.g. "StackedDrg2KiBV1" + +type HasherDomain = any + +type Sha256Domain [32]byte + +type PoseidonDomain [32]byte // Fr + +type MerkleProof[H HasherDomain] struct { + Data ProofData[H] `json:"data"` +} + +type ProofData[H HasherDomain] struct { + Single *SingleProof[H] `json:"Single,omitempty"` + Sub *SubProof[H] `json:"Sub,omitempty"` + Top *TopProof[H] `json:"Top,omitempty"` +} + +type SingleProof[H HasherDomain] struct { + Root H `json:"root"` + Leaf H `json:"leaf"` + Path InclusionPath[H] `json:"path"` +} + +type SubProof[H HasherDomain] struct { + BaseProof InclusionPath[H] `json:"base_proof"` + SubProof InclusionPath[H] `json:"sub_proof"` + Root H `json:"root"` + Leaf H `json:"leaf"` +} + +type TopProof[H HasherDomain] struct { + BaseProof InclusionPath[H] `json:"base_proof"` + SubProof InclusionPath[H] `json:"sub_proof"` + TopProof InclusionPath[H] `json:"top_proof"` + + Root H `json:"root"` + Leaf H `json:"leaf"` +} + +type InclusionPath[H HasherDomain] struct { + Path []PathElement[H] `json:"path"` +} + +type PathElement[H HasherDomain] struct { + Hashes []H + Index uint64 `json:"index"` +} + +// porep + +type Label struct { + ID string `json:"id"` + Path string `json:"path"` + RowsToDiscard int `json:"rows_to_discard"` + Size int `json:"size"` +} + +type Labels struct { + H any `json:"_h"` // todo ? + Labels []Label `json:"labels"` +} + +type PreCommit1OutRaw struct { + LotusSealRand []byte `json:"_lotus_SealRandomness"` + + CommD Commitment `json:"comm_d"` + Config Label `json:"config"` + Labels map[StringRegisteredProofType]Labels `json:"labels"` + RegisteredProof StringRegisteredProofType `json:"registered_proof"` +} + +type PreCommit1Out = *jsonfield.JSONBytes[PreCommit1OutRaw] + +type Commit1OutRaw struct { + CommD Commitment `json:"comm_d"` + CommR Commitment `json:"comm_r"` + RegisteredProof StringRegisteredProofType `json:"registered_proof"` + ReplicaID Commitment `json:"replica_id"` + Seed Ticket `json:"seed"` + Ticket Ticket `json:"ticket"` + + VanillaProofs map[StringRegisteredProofType][][]VanillaStackedProof `json:"vanilla_proofs"` +} + +type Commit1Out = *jsonfield.JSONBytes[Commit1OutRaw] + +type VanillaStackedProof struct { + CommDProofs MerkleProof[Sha256Domain] `json:"comm_d_proofs"` + CommRLastProof MerkleProof[PoseidonDomain] `json:"cemm_r_last_proof"` + + ReplicaColumnProofs ReplicaColumnProof[PoseidonDomain] `json:"replica_column_proofs"` + LabelingProofs []LabelingProof[PoseidonDomain] `json:"labeling_proofs"` + EncodingProof EncodingProof[PoseidonDomain] `json:"encoding_proof"` +} + +type ReplicaColumnProof[H HasherDomain] struct { + C_X ColumnProof[H] `json:"c_x"` + DrgParents []ColumnProof[H] `json:"drg_parents"` + ExpParents []ColumnProof[H] `json:"exp_parents"` +} + +type ColumnProof[H HasherDomain] struct { + Column Column[H] `json:"column"` + InclusionProof MerkleProof[H] `json:"inclusion_proof"` +} + +type Column[H HasherDomain] struct { + Index uint32 `json:"index"` + Rows []H `json:"rows"` + H any `json:"_h"` // todo ? +} + +type LabelingProof[H HasherDomain] struct { + Parents []H `json:"parents"` + LayerIndex uint32 `json:"layer_index"` + Node uint64 `json:"node"` + H any `json:"_h"` // todo ? +} + +type EncodingProof[H HasherDomain] struct { + Parents []H `json:"parents"` + LayerIndex uint32 `json:"layer_index"` + Node uint64 `json:"node"` + H any `json:"_h"` // todo ? +}