From 2194eacc0f39252a911f5665d784192e54bf67fb Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Thu, 22 Feb 2024 19:16:06 +1100 Subject: [PATCH] Adjust actor event API after review --- api/api_full.go | 2 +- api/api_gateway.go | 2 +- api/docgen/docgen.go | 26 +-- api/mocks/mock_full.go | 2 +- api/proxy_gen.go | 12 +- build/openrpc/full.json.gz | Bin 35811 -> 35803 bytes build/openrpc/gateway.json.gz | Bin 12146 -> 12141 bytes chain/types/actor_event.go | 32 ++-- chain/types/actor_event_test.go | 28 +-- documentation/en/api-v1-unstable-methods.md | 53 +++--- documentation/en/default-lotus-config.toml | 18 +- gateway/node.go | 2 +- gateway/proxy_fil.go | 2 +- itests/direct_data_onboard_test.go | 75 ++++---- itests/kit/node_opts.go | 2 +- node/builder_chain.go | 6 +- node/config/def.go | 4 +- node/config/doc_gen.go | 24 ++- node/config/types.go | 14 +- node/impl/full/actor_event_test.go | 112 ++++++++++++ node/impl/full/actor_events.go | 188 ++++++++++++-------- node/impl/full/dummy.go | 2 +- node/impl/full/eth.go | 5 + node/modules/actorevent.go | 6 +- 24 files changed, 398 insertions(+), 219 deletions(-) create mode 100644 node/impl/full/actor_event_test.go diff --git a/api/api_full.go b/api/api_full.go index 6a10d05a5..c07688ac0 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -919,7 +919,7 @@ type FullNode interface { // This API also allows clients to read all historical events matching the given filter before // any real-time events are written to the response stream. // NOTE: THIS API IS ONLY SUPPORTED OVER WEBSOCKETS FOR NOW - SubscribeActorEvents(ctx context.Context, filter *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) //perm:read + SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) //perm:read } // reverse interface to the client, called after EthSubscribe diff --git a/api/api_gateway.go b/api/api_gateway.go index 49fe7d7f1..e71a8b712 100644 --- a/api/api_gateway.go +++ b/api/api_gateway.go @@ -131,5 +131,5 @@ type Gateway interface { EthTraceReplayBlockTransactions(ctx context.Context, blkNum string, traceTypes []string) ([]*ethtypes.EthTraceReplayBlockTransaction, error) GetActorEvents(ctx context.Context, filter *types.ActorEventFilter) ([]*types.ActorEvent, error) - SubscribeActorEvents(ctx context.Context, filter *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) + SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) } diff --git a/api/docgen/docgen.go b/api/docgen/docgen.go index 4d485c442..bf76444e6 100644 --- a/api/docgen/docgen.go +++ b/api/docgen/docgen.go @@ -430,25 +430,8 @@ func init() { }, }, }, - FromEpoch: "earliest", - ToEpoch: "latest", - }) - - addExample(&types.SubActorEventFilter{ - Filter: types.ActorEventFilter{ - Addresses: []address.Address{addr}, - Fields: map[string][]types.ActorEventBlock{ - "abc": { - { - Codec: 0x51, - Value: []byte("ddata"), - }, - }, - }, - FromEpoch: "earliest", - ToEpoch: "latest", - }, - Prefill: true, + FromHeight: epochPtr(1010), + ToHeight: epochPtr(1020), }) } @@ -555,6 +538,11 @@ func exampleStruct(method string, t, parent reflect.Type) interface{} { return ns.Interface() } +func epochPtr(ei int64) *abi.ChainEpoch { + ep := abi.ChainEpoch(ei) + return &ep +} + type Visitor struct { Root string Methods map[string]ast.Node diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index cc0359afc..01e0cec45 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -3984,7 +3984,7 @@ func (mr *MockFullNodeMockRecorder) StateWaitMsg(arg0, arg1, arg2, arg3, arg4 in } // SubscribeActorEvents mocks base method. -func (m *MockFullNode) SubscribeActorEvents(arg0 context.Context, arg1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) { +func (m *MockFullNode) SubscribeActorEvents(arg0 context.Context, arg1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "SubscribeActorEvents", arg0, arg1) ret0, _ := ret[0].(<-chan *types.ActorEvent) diff --git a/api/proxy_gen.go b/api/proxy_gen.go index b2e9cf97f..5bbd32aa9 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -591,7 +591,7 @@ type FullNodeMethods struct { StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `perm:"read"` - SubscribeActorEvents func(p0 context.Context, p1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) `perm:"read"` + SubscribeActorEvents func(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) `perm:"read"` SyncCheckBad func(p0 context.Context, p1 cid.Cid) (string, error) `perm:"read"` @@ -835,7 +835,7 @@ type GatewayMethods struct { StateWaitMsg func(p0 context.Context, p1 cid.Cid, p2 uint64, p3 abi.ChainEpoch, p4 bool) (*MsgLookup, error) `` - SubscribeActorEvents func(p0 context.Context, p1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) `` + SubscribeActorEvents func(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) `` Version func(p0 context.Context) (APIVersion, error) `` @@ -4000,14 +4000,14 @@ func (s *FullNodeStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p return nil, ErrNotSupported } -func (s *FullNodeStruct) SubscribeActorEvents(p0 context.Context, p1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) { +func (s *FullNodeStruct) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { if s.Internal.SubscribeActorEvents == nil { return nil, ErrNotSupported } return s.Internal.SubscribeActorEvents(p0, p1) } -func (s *FullNodeStub) SubscribeActorEvents(p0 context.Context, p1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) { +func (s *FullNodeStub) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { return nil, ErrNotSupported } @@ -5276,14 +5276,14 @@ func (s *GatewayStub) StateWaitMsg(p0 context.Context, p1 cid.Cid, p2 uint64, p3 return nil, ErrNotSupported } -func (s *GatewayStruct) SubscribeActorEvents(p0 context.Context, p1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) { +func (s *GatewayStruct) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { if s.Internal.SubscribeActorEvents == nil { return nil, ErrNotSupported } return s.Internal.SubscribeActorEvents(p0, p1) } -func (s *GatewayStub) SubscribeActorEvents(p0 context.Context, p1 *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) { +func (s *GatewayStub) SubscribeActorEvents(p0 context.Context, p1 *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { return nil, ErrNotSupported } diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index badaa1984b3f77122f3cb118186818b3d5d3a68d..10e58d209420255dba30bfe7b6cb498b7e45ca4d 100644 GIT binary patch delta 21758 zcmV)LK)Ju;mjc_D0u@8O``r3|RSEshI=z>-k~kc)+K zn(1=mRom!2Jvk=K_B!HxEqLwXK)13I=?`NR(}x45uw3&Ar{*1XdBs8rwEh%FJ zRuSPL)*I%X52viRx7+W@8Olf89;%g)##jY(B!+-ySggP_JPXk^e+qdrbT74;HZz}P z&G2)-H)GR7rQ38tSNlNVcvhP(-1rN(+y95=`(LjglcIVH768|uD`g?c!ZV>U`SMX& zi5mz9CoUo!PjI?kIy^aA?4@_Iwq-%jAb$33MLxbyFuX#1-*pe54+Zvb3I+2G7>3PM z9{pyHVZjRryBmktf2~7@c?xRqp>C}aCM+4?V(WK-Cg{2hOyR`GS+;QU;uD>kzvj6x1-4OAj#QPhP7sV*zIz-A07MU4Y}( zHoyrNip_+EGvzD^fmY1>00Jos!HXLYJ08Hq#g05Bf?ziHe>s*&`E>xDE9Az#h`DGRsyfdxO42$!EVH9G zE7GH=m3fAIe*_tNCsts~EuC(n3B=37Ik~H=H+8y`@?G6@2j|GH_wz3yB2+&j=oW9) z@m)MG@`)_{bT_PlAM+Y)&N8<0dF~hUD(HtP5ET2m`Tis41jCAiDaGa5niC{VJe0DR zreP)OUT%=43SWjU%`76`AzgKWi=h8Z`NTR?YqdSAf9*Y0ZEsYOM@O-&ub6vo2ya?S zgQ)sLNrI^Vl}Lfq;7lbzOwWz}gMm5msa(oh4uo`O4S?%UtrZDYBs^7-uw9YO=o2O= zJd}5yw7Z}w-$12nkjj3IW`PemN`f8a<46|F9(gn2+5OgS!$J%Q2 zXLL?nIjnM`(4Mk-IP;>be6N1U~l%8|_;lKUtrGCBX_vBydf0pXf&)d*nEW3uPE|zMX>acoBXQXHzhRvkaZ$fCC)kI z=!{a{mB((>lQ}y$A(5|wG@oTOn~qk;IdX!l?i+53)6;{ijD>wH_Niu0&v}!QJ0gFo zNwia%88zF@OTp`y<+rO|B50ctUjhW$H1IW^>DD^Nvz7plS7mz2>QdS)kOfW8dbvKa zkoujSiX_{TvA;)>N1u=hZFhE-YM_xz#TaiKdJq$70j~SRrOXkM&bfd_8{gq{fl-2-yMZ!a; z1Iq5=k~CWR_r}M{r}Rcz(+0hM?=#{zG`vbbI!6wtp(=llO1)9*N7~QS109On zjp;@7h}_cS$hHCF{oYp^ULi$iVnbBKpX0w#Z*R0U+J3t`dNbOQ<~ekoD5ZaLY$kTU zCG3UAKAz&SkKWNxeb!bP%AS}aT{0=9xzkchx~Zm-UHy&ql;S#h6ce3Z_$KH&W(e(8 zREmd~^_F4)%@ApZ9kr<%v9@j&aEj|JpQzw5W9i+BjP#!ZO8o=K9q)9`yyi$cQ@sjD z$EjV;@suD}t7|elm5KXtrjLKxoK&qGkn=;Ri9XFzGM1^Of;sb~w#Ve)Kq^E049!H1 z?s7?$Poyb`vmRLY>4DWYM~?NJv7R&5bEcCNLFK8)s{HrUZ|+Sg{$6@l@DqvKrHZ{K;n`f1P@9-GuTWdP+v?p`Bw3MU_3kI6 ztG%tbqamv`{6Tm)XS_{L#`1RV!z>|WG*JV|bdl4La;iSYi*Mh* zeb(MGCkJfva;rzgS7kz7vQrjc>xN=B4)s+Q|v$=IN~(}lmMu48=XW@ zt-A!gB@=E@SUC#&6Z+WI9VIRTbA&(iz5ml>DjhOSgYxUv=mcC9eP0D{F%pp5;#J^dE&M5Cc(XQ<$ z6IJ#j6;K2-Aiq4=|M)SDLVO>Lkt&GXvRY~-0AKztR18AOk;9SOmzpf)9tz8v?Fih6 z?_$L1#8^`sA=*Rs!aL)Aw^en$kyu{u5kI74f{U4FjrLw#y=4C-msY4nFUu`d9^w|e z$*7YjvSxo*COxZm7m$T98hZElDcr{SESLrQ&@ z-jLqj&LI9L0liSuomQq2z5H044;W@p{j3nMiF93``6 zl)xeTO&V2^pR677eay^lr|O~}y`z<;)0Vf%+U9ogIVOB(%Y?uhM7^@O+nUe?5IJ>hL=TMFR3 zsmt%yKDAq2R=0}aHPg_w176A+55gZ(@It=S*>JkEm`fo z>h@msmE)bab!pd@&bVffY|SjyT02wEq8w{&&aN6~QA<;yEVIz}?*L>1EJ@3uVBdX- zomgKk;uue9AazMHNNOhY5{Vr|iGK&?Vt3tmh=5qK{g#LxFu}-o8Gs=o|KN!|`I3KJ zlCPpt(i%ftK(;}@Xf>9{&eJ(!48TBe%n(D4zyzU7A{e3zD2Y$w91mh5KDOez-T7Cy zaKC#NP_G%*vZ%?TrezKuZK}6to$AfV8g8|8tEF3cW95z2($`q|do!rZ2!r z9hkpOlC~{n2XBzAElbZDq-e9E*ouE*D~hcswxZY?%&ozEY0R`)mtO50`C=)y0!yl{ zq5q?_lTUmK`Oa2*Ur5#EJ-9-~V>7UqYoa1&NCakCqE9)(}VsFV>OQ2qyMw7KU+!(d>l(sIL&jK7BSeJjH?R>d# z+Vh%l+Kl@`5(&B}xc$67p0+WvN(fwFnMyilh_fW1UB}G=P7Cq1Y#szYR(eCz&{~s& zd>cP&<7Xcze%59p_&9tss>*uC@O0mG_k$p$*DZX%GSv;kb)`yMd^Q465O1(m@_M`E z*^W*!@}iIuyH+F45Z#T#Sbl#VBK22{OAJU1KoDHPwX+mK^RR>KD`kNv|`bF;Br0~j2vksVt5*7!xT?ZU%ypR$I&~X zhKsf|DPYE?+2S!Z(Lu+_kuGpaG9|+D?g+Y3M z&V3h*5x~R=5oE|!?L6IR=UOFvov9r?qG;@d>S7G}I?wU;qoQ_ajgk_T-KJ3P>elSO zh398CDqgo>4?3*@=iv-E&F@%v%m{zGD%Y68mWPlysHpQ80(@0_#rS>+EU)P663WLT zE<^IQC|=Xz$p5SZhF5=-w1Myzq+5_~LHY_ox`n+K_FC9$VXuX~ZDH?jRTfGG#!eN+ zX^VSx^<{x?@!8fgXjfC!CEQI0n#a4fST~|XLrEq^DnP4tgAXHLtq8WR5antTQZUz| zSc_uUn%W|IwRq6tL5l}19<+F{EgpPRmA6;`mSwygn!7l}=FWct0BnW(x^`D6^;M`r zdv(qUuM=Bh1l=N|;`k2m5E2F*G27tes1pnr_m^v17K(79f}olD&lIyg23y`Ez-|^e zS>R-WlLbys5jefA%7>iD{)=1k0k%nuTxg;j7*%KRHld3H8_7uW~<7dRE$InVIgjdC~OGd`sqA^b0%Qgm~t-%yL5c9Cpw7Cae_-A zjzXr=7AiyFB~d*=e*;{k?zEv3O&F91=U|LfElvRc~)A7u8p@NZKOl6Dxh7&U%KYOE@$)_h#|9{lh3{h8kZ%QJF#pf)G1hD;19c?i7`a!tO9jsUD+B^IYEr zrq+KpwQ;T1k=fQO`xu*p&B5kMl3!Rwq0wRc3#Nr|%Kp zzlPX{V;>zT1lJ1lm$cL5OoM0d26_ozWFdb&axdw;<~F8`p3oH4mydJ7eM}W3Mt3tw zvpNmsK>?kl;Ql{YgsK7eAdj5)Z!q`V5Z-?fKtsR+MEEl`zjJ$|lrfmeA+0rqVe865 zw`wx{zeoI3-Ko}=bL#5LG0bn@Uy0@}l2bBiY#W}LjL?WxMr1`CGP<)a zb)>59trM(simwq#B|%a)k`3@h@XgYiFhpQ7_mg-hw=Y_{12@?B0inRBWQxK|0)u}5 z!4P;z#yMFYYkBOV3-fY&rR=i2ViBVm6$;tgyo#9C0}VAh9kS@AS5^Cq;gZ%myH`hP zo{P1WCQ8s_(QKanJ!5aT-_(lIKT*4j^3%1K5Tx=1Vrgwek+DJ@Bp#=kS9(HHTIYZ> zIw$f@*mox%m4dbdbLs6moxv2?$V#soPD|FXJ%e00q?XvM&&E(~qs_wW8Pb zn88k()d}xMknPmm385J-Cew4rL+;#fZB@%Pvz(47+SCmiO0iVeHR3GQZd+-V9ix$! zn5Qo-+pg6+;35vO&y-y)t0`KI&T_~_95S`A3-g$LXL9U!qFf~+JG)Zb&INx6QfK0O z^6Pwm|6Add*^Xje~T~~SVrY2eXGMUmlN|T=Rp(@Yq z6gy|_ED;ydbq4k7^y!OTsfsz&R}=NIl7Nn4)^!`vVe_xAB}RWb8HXN&vtZGY%Em@m zrzz_+Wu2z1(^N-j{%uXF`!jzuqt{4XG1&^zryE$O>yOfObq3#agEhYbDML*R;00tA zpZ*&9%BrK2+Dt+^%Up+~&M2Vcpn$W?8v%l6@CvD51P_ua0+jUAXgI;*oL&+E&s7UL zJ*ntSl~0O+u_g?;eVwya?~Y4?iHjX5EmG0NNHhe5a@mF$fpk*vLd1VO>bt3Hk$ifC zLga$+9iRkV66jOW2J>a%Lx`xz#vLQ)y2B#AqstDu}wm>o+S?(J#JbzCLlj z#F{0ycjj;Pw6JpRsI`B0%0Gm4c%7+z1bOK#%C{)rqI`?;pCZcNtjVV?P~s9f)syP? zi}Bmy`Hpk2XNF&f=IfDsO)k(f9N(#5NV80xi{ZQl>=v+F!2Xy4yM@3O0$T`dA@Ea# zz{8r1`2t`q;|86ozY3R$j*xHHzR%fFoBK|rX^CAY*bNK^;>Bc`J{t+{dNShQ|>B=Rz@FjR5=CcmE zrCTV+ZE6Y|Ah#S*0sPMV*p_^|;*Qe}Y*du$zEw64o+yCNB&S~rl-S@UHUSFO@* zwM&0euy)PGrD~EkB!wE~Y{-x*NGo517aj_c%(O=+2X}}ANbZ0`XEQ{2l)Mi!ph8(U zI@0VO&R4nS<7Zx(!1D7u;^+!{KYKa|U%>4HmDK(j5z0^#|HBJ*zr0}U> z+?|T-cBg;v&hhqrp9+dULeks@T4=%03i=Yfhz|X$1xBIqa=9^RA}GoTu9g>1)wEY8 zE8=tC$8sFJrkicIA_JFNc~QFccXQ%4M`R^!m~XgOhaMyZ`Pur5H(;iCCua!d!?4>> z+Eq)xQqj0tRm=p+>AH31)U2`fkdg@wXUN^3aczGp)!DF<2cIc9Lkxx2Wu+o23va$c z%+C?wSklu`La*L`&(SSt)KqD zZR=(}d&@@hD=!&skTzzN_{K!t<-8iPm&uIxd4C1t!;o44zN5CnyEZT5azC>@t0EN?SM~6S|Pyi2l3N2=r(c-@KCaJw==W8m4Y^58&NQtW`%11B?;BL5P3E zPO|~T;l?Go@DN}Da>Pz?qYGQ)EoEbw`wPh=z)>1A(Gd4SI-h!glGlz0F_Blk%j4F` zT(CMYXV#H+{it2z+`e^6l-Pcis*`@%Qej$!;&NZ=$TE=nsln4>MOd`tj_*-RX!;(R z!cy~u_))`O0?wL>nD?jx&9;#+YH)vM!5(q%?PSa)0ktwF)EcgoAajN`z=;g!P`*9n z9~>Yed-SfUocEi8q2hpz909{W^c;PG7?-JTH20F_}rnNi+AEc20y4;#;Y zQpIKxT|a8q7$nq2*`yh(As~Nn|^!gt+;^O~}ot%^`9 zxy?Re)>7*dHOu2*zI|`XR76`f%%sp@b9SPsT}g~gfxMC%dD^VjWVwHu-^gBAxliiG z@X_XWMOc^o$e+>8snT=XE$O8Gvi5{;-}T|-d4Qak;KeK5u95v9A)`ApLS|@-&DB=j zTQh2l>Rx7vnemgKy?trX(T*Ayc!oYw=jszC@pYr|Gk6<6`-I6k;u8JnC&#xul&$YO zoQ7!~B^Anl1UW1V{O#i^xa!mOh8*X|RV_hX#Oq-;3)fntTfN;Xr+$yCzpqUHC??Aiu1 zy40dk+@akZ-u9!sTO?G~ppQ%kjTuO0;AUQCPnDt6+J?(Mbu)j%k~Q%dn0OlTQfp_ib{1=A zd3JV|ZV%Cfpf-~|1%B09rK*YLXo{D!3dLX)+LNd zgDQDF$?|`AR5r6L7JaFsCr!|%?64eZE&(y4Vc5iP7FJqVXl@?Y$dRSR{mC4*M zLMHt%<$$BRBjUy521LWUv{w-XkZCoR14FWjCO{~AavY3+x+35uc=0OJ=9&D2#uhnQ zr#pv~{P1k3Q7K4TA6t2yD!I0oP?Y-qlP2Z% z=Hq`EUJmD|CRXN2XBv>2p=K3vsrlhrCpvrDX-_*Xys_}c!kb3{Z>$sD>YV6omIj-p z!5EltSLB{OgA@J{LAT`FF9PIA)$;7K0Yc%%$x$7OPMWAe&$^vP=s82%N^;F=stU7~ zJU8GEo5Q2g@05Oh|M%_RzyIrhuhED9;lYy(6Ci)Cwx&ySry`TA_=e}ajekd6vwUH` zir))ayl8#Of}Qwfq{&*zn#>NYs3PTGn^{KH*np)Gw>L)hq${HDf1*#-FF;1C;WHR z{JM}_{pQ|?7dSXaqH42?L~{ME=o*pY=<1_2@>Ho7nY`yKn2&wzfGczt-FMDu0c7@|^X4PT1|8 zCmnIjHx=0d^&aOmJftoz;qM0LJ;lyy zm}Rl)HvBR>uxihj64KHfQ$C;*0DWKn9?!AQF#%B2P+T%$pL&|WwVI~xIA!4rtjw8t z*r_vf@lzHEDlKB5T7QZDi~-qWF~mLNgv!IW6^Rj(4f+WZJVA^fmKcuA*hSQBUD-vj_jq3ZKFhSuvIQMy5 zSeI#|hRbcpJ7tdp>Ub6E@VD=;WGjo=UZ&4_*JfF!1=q_D%YQ@>&XN^zJt!~NCa=+L zAl4AjujOUc)N$say!9Fr;8S`vhRzj0Vv=&|GRFZ!yi4wv`XDRgeA2z8E%UQFa(7W=}5fv|p53J<5xzy>qp0#mGlSQP9lX{Pf*9N5hJwG?FnL!jgz|BknG0 zR`K*#Y76SKoqr0R{_2EWQ)h92b=+Gg=XYt^4H&oVH=JvPs`%|p4NHQKh?8T<)x}UG z%cgSs`02Gz2(0=h+&n^QDA$ zsN=olcgkl{A1XdP(ZRT(9xx()s_A;X)A^Y_l|dg#sQ6~7s~w^#6Xi#7JNw1=AZP_r8sJd25zy7wd{ zn2M|}`+w4e(S2f5p?r6C<>eX z>YX(8s3n;!L-FejLH7&s@6?`cw*=I?xQk!?p4hcl$coa^*>J_eUZaIlHjAra1 zs}MBqHr5@Q)-2Odnzj+CDoyL9w3<%#(0wsPYruPw2E6QI(l(%mySNo2&saU0b${4Q z2&CBBiY3OAk4qShDsm;O(;|6%q!4yXcZ^IERVR0`ds#4y{?5ADDnqhtWbvV0x<@lt z+f?(-Ju~tnG&$ePkeK$%;2w(H&u%=*kUD^4`XCRC5x+r5oviU2s*eU`8R@NiNiMz| zec1!&9-aFx;2vgx!>j0A4_u);27fSN96|U0>+B%TI(j{%qgUMljQuhX_+=J2g{PQK zonv^mn90cxA8ZasJ5R}wSnuv`Z8II(W}XPF*{aBytHdu3ow*M=CQ~8h{gzReg=VVY zO-Z2T7;jwAD@0VDtHqcm-&I|_Wwz}WfTmXlG%u*NN?0b9vbe^wmS7galyO7R;d5fec>BfqbaygIWtT7 zN5T++a83Xe4bb`2lQsVQ1a1U()7&r!={0td3p|<3PWo|v^$-CL^nK*^GoKFJVBg=n zB(K3o3f*jdMMEFZP_R+?&Y6eO#nTaA6?h1`08b>NjcSReqP7#~P=Bp%YJbmM4|3!* zh~K8XNG}NhufYpKWovSPm;uI7pj=(YXhK5-u4ihja^|&*sdi39(NXG4)s{M1)jBem z2h$L`NDKm!J2j1hXSj1;$PG22NUdHP3i(0izAst=VC+-piUG0Xkt+mLGF;WwVWgZp zA=Lq5VyL2p#g*R)F@FRdPnC=$S5iWh*_Q$_?LDiT)uma090B~?xWWw#UEN}c)Q>y4 zE+P{2Q%P*~D5BuDXgSCk5?}sglI=M2Wjs9fkf;brv36g6xI6I~M85@yBPqY;q!uQ? z#ghq=L(0Ybv5o4Pxg@f`vI$ZzXuf8&FU5+@PS7Qp6OPsAiiaw8xEO>YRXSfM6BF$q zIr(A{MALUkk`Bjej^_-8lAC-^ZASsBFvrl(?sP}80H|h0`+iR*$l-Bwm!#xlyjB>j z%qjebB=Lv%UVnlQ3Oe+hO1>6?8%Q|QUr8(rC&h&%QT=32n6h<^k!+6BOR{jj<;Xu( z5S5HzHfJ1o@LKar8ivT>fCw#%sWml)?2<^Y69ziweje;feAJ+!3HMSzyuqZU;`6uV1f-yuz?BIT=^)>l{PTpUIG&; zf$3B8@!P4mm@4fPaRfPRoiaDuMw6=*;23Y5p(z%$BljH1RZ1uN+F0@S2tohkNM0UW zbeSojT|1{( z;Wc(qcu0L8auh=UfX<2AGBB~O#X2Y0Q|P+LJ%7c>LFf2ym1cBIsbAs!D!R!xzfi8% z(N-hn%lc|A@)t~uq5o{{5YoW`Gfd=mnZaA�AAZ<}`%U*uyluBn~71Gd4$Z+j4lN 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 diff --git a/build/openrpc/gateway.json.gz b/build/openrpc/gateway.json.gz index 2c85d00401d1fc33a807b81f5824ad269985f2d2..dd9fe19c55ab15181e499d28c79d5a16d5c92d5d 100644 GIT binary patch delta 5701 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 0 { + // Here the client is looking for events between the head and some future height + if maxHeight-heaviest > maxRange { + return 0, 0, fmt.Errorf("invalid epoch range: 'to' height is too far in the future (maximum: %d)", maxRange) + } + } else if minHeight >= 0 && maxHeight == -1 { + // Here the client is looking for events between some time in the past and the current head + if heaviest-minHeight > maxRange { + return 0, 0, fmt.Errorf("invalid epoch range: 'from' height is too far in the past (maximum: %d)", maxRange) + } + } else if minHeight >= 0 && maxHeight >= 0 { + if minHeight > maxHeight { + return 0, 0, fmt.Errorf("invalid epoch range: 'to' height (%d) must be after 'from' height (%d)", minHeight, maxHeight) + } else if maxHeight-minHeight > maxRange { + return 0, 0, fmt.Errorf("invalid epoch range: range between to and 'from' heights is too large (maximum: %d)", maxRange) + } + } + return minHeight, maxHeight, nil +} + +func (a *ActorEventHandler) SubscribeActorEvents(ctx context.Context, evtFilter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { if a.EventFilterManager == nil { return nil, api.ErrNotSupported } - - params, err := a.parseFilter(&f.Filter) + if evtFilter == nil { + evtFilter = &types.ActorEventFilter{} + } + params, err := a.parseFilter(*evtFilter) if err != nil { return nil, err } - fm, err := a.EventFilterManager.Install(ctx, params.MinHeight, params.MaxHeight, params.TipSetCid, f.Filter.Addresses, f.Filter.Fields, false) + tipSetCid, err := params.GetTipSetCid() + if err != nil { + return nil, fmt.Errorf("failed to get tipset cid: %w", err) + } + fm, err := a.EventFilterManager.Install(ctx, params.MinHeight, params.MaxHeight, tipSetCid, evtFilter.Addresses, evtFilter.Fields, false) if err != nil { return nil, err } @@ -128,30 +184,29 @@ func (a *ActorEventHandler) SubscribeActorEvents(ctx context.Context, f *types.S _ = a.EventFilterManager.Remove(ctx, fm.ID()) }() - if f.Prefill { - evs, err := getCollected(ctx, fm) - if err != nil { - log.Errorf("failed to get collected events: %w", err) - return - } + evs, err := getCollected(ctx, fm) + if err != nil { + log.Errorf("failed to get collected events: %w", err) + return + } - for _, ev := range evs { - ev := ev - select { - case out <- ev: - case <-ctx.Done(): - return - default: - log.Errorf("closing event subscription due to slow reader") - return - } + for _, ev := range evs { + ev := ev + select { + case out <- ev: + case <-ctx.Done(): + return + default: + // TODO: need to fix this, buffer of 25 isn't going to work for prefill without a _really_ fast client or a small number of events + log.Errorf("closing event subscription due to slow reader") + return } } in := make(chan interface{}, 256) fm.SetSubChannel(in) - for { + for ctx.Err() == nil { select { case val, ok := <-in: if !ok { @@ -164,24 +219,19 @@ func (a *ActorEventHandler) SubscribeActorEvents(ctx context.Context, f *types.S log.Errorf("got unexpected value from event filter: %T", val) return } - c, err := ce.TipSetKey.Cid() - if err != nil { - log.Errorf("failed to get tipset cid: %w", err) - return - } ev := &types.ActorEvent{ - Entries: ce.Entries, - EmitterAddr: ce.EmitterAddr, - Reverted: ce.Reverted, - Height: ce.Height, - TipSetCid: c, - MsgCid: ce.MsgCid, + Entries: ce.Entries, + Emitter: ce.EmitterAddr, + Reverted: ce.Reverted, + Height: ce.Height, + TipSetKey: ce.TipSetKey, + MsgCid: ce.MsgCid, } select { case out <- ev: - default: + default: // TODO: need to fix this to be more intelligent about the consumption rate vs the accumulation rate log.Errorf("closing event subscription due to slow reader") return } @@ -204,22 +254,14 @@ func getCollected(ctx context.Context, f *filter.EventFilter) ([]*types.ActorEve var out []*types.ActorEvent for _, e := range ces { - e := e - c, err := e.TipSetKey.Cid() - if err != nil { - return nil, fmt.Errorf("failed to get tipset cid: %w", err) - } - - ev := &types.ActorEvent{ - Entries: e.Entries, - EmitterAddr: e.EmitterAddr, - Reverted: e.Reverted, - Height: e.Height, - TipSetCid: c, - MsgCid: e.MsgCid, - } - - out = append(out, ev) + out = append(out, &types.ActorEvent{ + Entries: e.Entries, + Emitter: e.EmitterAddr, + Reverted: e.Reverted, + Height: e.Height, + TipSetKey: e.TipSetKey, + MsgCid: e.MsgCid, + }) } return out, nil diff --git a/node/impl/full/dummy.go b/node/impl/full/dummy.go index 9adb93a27..497c896ac 100644 --- a/node/impl/full/dummy.go +++ b/node/impl/full/dummy.go @@ -198,7 +198,7 @@ func (a *ActorEventDummy) GetActorEvents(ctx context.Context, filter *types.Acto return nil, ErrActorEventModuleDisabled } -func (a *ActorEventDummy) SubscribeActorEvents(ctx context.Context, filter *types.SubActorEventFilter) (<-chan *types.ActorEvent, error) { +func (a *ActorEventDummy) SubscribeActorEvents(ctx context.Context, filter *types.ActorEventFilter) (<-chan *types.ActorEvent, error) { return nil, ErrActorEventModuleDisabled } diff --git a/node/impl/full/eth.go b/node/impl/full/eth.go index 5c6f29d66..c7529c0b6 100644 --- a/node/impl/full/eth.go +++ b/node/impl/full/eth.go @@ -1264,6 +1264,11 @@ func (e *EthEventHandler) EthGetFilterLogs(ctx context.Context, id ethtypes.EthF return nil, xerrors.Errorf("wrong filter type") } +// parseBlockRange is similar to actor event's parseHeightRange but with slightly different semantics +// +// * "block" instead of "height" +// * strings that can have "latest" and "earliest" and nil +// * hex strings for actual heights func parseBlockRange(heaviest abi.ChainEpoch, fromBlock, toBlock *string, maxRange abi.ChainEpoch) (minHeight abi.ChainEpoch, maxHeight abi.ChainEpoch, err error) { if fromBlock == nil || *fromBlock == "latest" || len(*fromBlock) == 0 { minHeight = heaviest diff --git a/node/modules/actorevent.go b/node/modules/actorevent.go index ddab4eda3..1e790179c 100644 --- a/node/modules/actorevent.go +++ b/node/modules/actorevent.go @@ -164,14 +164,14 @@ func EventFilterManager(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.Loc } } -func ActorEventHandler(cfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *filter.EventFilterManager, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.ActorEventHandler, error) { +func ActorEventHandler(enable bool, fevmCfg config.FevmConfig) func(helpers.MetricsCtx, repo.LockedRepo, fx.Lifecycle, *filter.EventFilterManager, *store.ChainStore, *stmgr.StateManager, EventHelperAPI, *messagepool.MessagePool, full.StateAPI, full.ChainAPI) (*full.ActorEventHandler, error) { return func(mctx helpers.MetricsCtx, r repo.LockedRepo, lc fx.Lifecycle, fm *filter.EventFilterManager, cs *store.ChainStore, sm *stmgr.StateManager, evapi EventHelperAPI, mp *messagepool.MessagePool, stateapi full.StateAPI, chainapi full.ChainAPI) (*full.ActorEventHandler, error) { ee := &full.ActorEventHandler{ - MaxFilterHeightRange: abi.ChainEpoch(cfg.Events.MaxFilterHeightRange), + MaxFilterHeightRange: abi.ChainEpoch(fevmCfg.Events.MaxFilterHeightRange), Chain: cs, } - if !cfg.EnableActorEventsAPI || cfg.Events.DisableRealTimeFilterAPI { + if !enable || fevmCfg.Events.DisableRealTimeFilterAPI { // all Actor events functionality is disabled return ee, nil }