From daa7b44fef41de956a97b9731fe94df30d8fc3d4 Mon Sep 17 00:00:00 2001 From: philip-morlier Date: Thu, 23 Sep 2021 16:01:00 -0700 Subject: [PATCH] Updated toctree with further development of scope. --- documentation/_build/doctrees/anatomy.doctree | Bin 32663 -> 3164 bytes documentation/_build/doctrees/api.doctree | Bin 0 -> 32380 bytes documentation/_build/doctrees/build.doctree | Bin 17832 -> 17601 bytes .../_build/doctrees/core_restricted.doctree | Bin 3209 -> 3428 bytes .../_build/doctrees/environment.pickle | Bin 27973 -> 96974 bytes documentation/_build/doctrees/hooks.doctree | Bin 2959 -> 3116 bytes documentation/_build/doctrees/index.doctree | Bin 7164 -> 7150 bytes .../_build/doctrees/plugin_hooks.doctree | Bin 0 -> 3155 bytes .../_build/doctrees/plugin_loader.doctree | Bin 0 -> 3176 bytes documentation/_build/doctrees/project.doctree | Bin 15124 -> 14618 bytes documentation/_build/html/.buildinfo | 2 +- .../_build/html/_sources/anatomy.rst.txt | 123 +-------- .../_build/html/_sources/api.rst.txt | 120 +++++++++ .../_build/html/_sources/build.rst.txt | 5 +- .../html/_sources/core_restricted.rst.txt | 3 +- .../_build/html/_sources/hooks.rst.txt | 3 +- .../_build/html/_sources/index.rst.txt | 13 +- .../_build/html/_sources/plugin_hooks.rst.txt | 7 + .../html/_sources/plugin_loader.rst.txt | 7 + .../_build/html/_sources/project.rst.txt | 4 +- documentation/_build/html/anatomy.html | 142 ++--------- documentation/_build/html/api.html | 238 ++++++++++++++++++ documentation/_build/html/build.html | 32 +-- documentation/_build/html/contact.html | 12 +- .../_build/html/core_restricted.html | 21 +- documentation/_build/html/genindex.html | 8 +- documentation/_build/html/hooks.html | 17 +- documentation/_build/html/index.html | 25 +- documentation/_build/html/objects.inv | Bin 531 -> 595 bytes documentation/_build/html/plugeth.html | 8 +- documentation/_build/html/plugin_hooks.html | 124 +++++++++ documentation/_build/html/plugin_loader.html | 124 +++++++++ documentation/_build/html/plugins.html | 8 +- documentation/_build/html/project.html | 15 +- documentation/_build/html/search.html | 8 +- documentation/_build/html/searchindex.js | 2 +- documentation/_build/html/system_req.html | 19 +- documentation/_build/html/types.html | 8 +- documentation/_build/html/utils.html | 8 +- documentation/anatomy.rst | 123 +-------- documentation/api.rst | 120 +++++++++ documentation/build.rst | 5 +- documentation/conf.py | 8 +- documentation/core_restricted.rst | 3 +- documentation/hooks.rst | 3 +- documentation/index.rst | 13 +- documentation/plugin_hooks.rst | 7 + documentation/plugin_loader.rst | 7 + documentation/project.rst | 4 +- 49 files changed, 952 insertions(+), 447 deletions(-) create mode 100644 documentation/_build/doctrees/api.doctree create mode 100644 documentation/_build/doctrees/plugin_hooks.doctree create mode 100644 documentation/_build/doctrees/plugin_loader.doctree create mode 100644 documentation/_build/html/_sources/api.rst.txt create mode 100644 documentation/_build/html/_sources/plugin_hooks.rst.txt create mode 100644 documentation/_build/html/_sources/plugin_loader.rst.txt create mode 100644 documentation/_build/html/api.html create mode 100644 documentation/_build/html/plugin_hooks.html create mode 100644 documentation/_build/html/plugin_loader.html create mode 100644 documentation/api.rst create mode 100644 documentation/plugin_hooks.rst create mode 100644 documentation/plugin_loader.rst diff --git a/documentation/_build/doctrees/anatomy.doctree b/documentation/_build/doctrees/anatomy.doctree index 2a72aebe4953a355bf259cc52fc1c62096688af0..104446d39eb904f35105a784bd517ac6c814ade8 100644 GIT binary patch delta 640 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 diff --git a/documentation/_build/doctrees/api.doctree b/documentation/_build/doctrees/api.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e629ad5a1619d2ab246d69dac70ee096cc8ebf67 GIT binary patch literal 32380 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¬aNqn7B0}gvKYEKD?CN(UP*S%X(P}Kbk9*R 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 a!k+F@U1oDLNuegDVedR#i!UPPhH z8^h>S*zXJn{R2Tz)`2b)d%2D1IrKr z2zKVP|N0G^1VRV%dw=^Vh`8?R)Pwdd4jkC#cn!`5e0E#_@Zd>j6}lQwbG`tO^mW$= z2R+PPX!BkLSy#Q^jS#>kX$9JG+vvmn{>u>5(O>1@5C-K92Rh*~?3b8<; zOfyh7p$^u_`Dfhd*Bq;S6G&D{Mn4Q8d?arD3P_YT^;Nx#F^RMpLc% zbfHL;8B#2!FOi~_((rC_4=O_;e3?vg4!)V)#AWRm9uDLAq=)@PeOVhW4j=dpNMhW} delta 751 zcmah`O-vI(6z=QptRYZZN+pE~yM+>owSZP=so_vtJcx-QQBO9wm4)fr^4DF$MXWI- z66@(L!2=j$JZOwWovR)=;1v%hoFy?N8jQ*XVoaPZ#&Gj6Gw*%#-Z%4oZ*2jd-3L-4 ziz@@K$qY1;b7n3-V$mZRi&mAz%i64Ap;bPBaTP9ri2Lvzw}oR!ge{2T7iRzkaT_H3 zDlS14yGv#yQcV^529u(KEj2sfVl}Q>Aa1JY7jexK$7OdlW@~?ghh2AH1E|Ayo(XWX zNZk)7)T8WMhokJXZvvnZT>(E98cGmg-x@XnWcJ>F-U&gDThPXy1a?K~IOo0T#3^43 zzVe9tMK5kBm!Jye-~xo%^WZ}#M6fyL#cGTh;8#dwwa4<}6- z%cL!|joT?u;44U5sXQp^^`gTu2)LY(!C-F_^O9t6gf`<)vPkUk9@|K+0th&l^5e@? zyBm1BUIw^@Dhi^%&PwsQ!M%1d_0n<=x$=qO46tJH&q->hvOm_sk?X!*V%qpC#NWT zjcIkfI65(17%phVqB^D(t&FAD@^YLNWc-xscXn4O|MExdM8>hShv*%4)m+*SE?i2V F_yYh>^WOjf diff --git a/documentation/_build/doctrees/core_restricted.doctree b/documentation/_build/doctrees/core_restricted.doctree index 55537f385fd151f5d8cb25f691ef34795c53b3f8..e84586b93b29567181241174ebb6e3e707439bf1 100644 GIT binary patch delta 556 zcmb`EO-lnY5Qf>V+p1M6BBJ#x3Sx!2)r%J?;zb0-s;KCp=yo?{Qre{Khiwm{9u$SW zC4%0?yLj~P_y@d+AehuD1+NB%Op-~Sci!9#zb1`yE|s9nf}--}Dp(g9IGu)?==)SHr77A9c| zCe}N7E|T1V<<_Nt6U*cJh_Ng|+X{J>`@t!6P{7cq%<0dIP$$lUuwX!@3CpQ4N|Xn4 zO-C&ll&uWONXp}w!)$6*uq;&W9VzQvqO21EjKfkJVj48i+b}%TUo`r>){%{9ch6VR z2R%b!3@T6x!Y=iu->71*`C;@LDw_fHD}7@y4J8@JkmY;bZw5TBYaU;X?`T{6KEAJg Ws@{y8?CC>hqkN%fUVG<-o|!LgNW2~Z delta 311 zcmaDN)hWr^z&f>#XCtc*lSu|=4`)GQQDS;gVnN1~$x}2Nr_@f-$YAa9(9$Z&Psz7Z zNX{>)RLIW*(nYBXiFqjsMUx*giiMPxWabp>DU@d#d%8JS@RmeTKW!DlcV#Nf&EnWb6TG88hLCV$|O;VjLN%WwelY(P9-5YH+@ zF+(Xs-kW{0H_JK3=*?2BwoHtznoYDRd5>SS&1kCPR7f*7qQm+*u!zJl9k1+?uskmtkrbh0h4Isn8xYhwTa diff --git a/documentation/_build/doctrees/environment.pickle b/documentation/_build/doctrees/environment.pickle index 3e776e705550dcf3945e34ab2a03db99ecf49feb..707ce2bcbeaadf7a15cf504fd3b6b0cd049f495e 100644 GIT binary patch literal 96974 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�wgT)c6kz3Rw+6lS= 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

Z;a%&p&M#3(p4c>FdVI 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 diff --git a/documentation/_build/doctrees/hooks.doctree b/documentation/_build/doctrees/hooks.doctree index 27dcea649f681872d6667f81a4ce626d2be85c06..40190bb71c132f8af1284b7393e4e211691d0b97 100644 GIT binary patch delta 457 zcmeAdUn9ZVz&cftXCv!7#`+%q;)0CKyb8V4iW0q&{FMADJ)9saJ}*Bdb;{%^nvGLx zr)Xrb_DH2<7AKb$7iZ?@DdeXq6y%hqXXYtnPsw191**}6t7QoR83Yo|(C>k8 zTBkq_%3#Y-$Z#x8O3V-d8a(*~qYS5QhGK?NhP*fXinjreRt7-tVOE^zVz zMumERm@z;R+tQ>|umu@Hu~T}OGgAzwBxZ;Jnf!?XN>LcCU*A(vr|WUy)mV+J#_;Tk=Cg3K(bEJ!T|hh|sdn4;R#`+A-9?pWqqQvx~#Da_|lc#7lPN|)uk-^%dqNP=mpOSB- zkdj%PTv}Y5nV+WsL6v*78Tt9y#adcZGT39M0F7WPE-A{-OGnb5VF#Ad?@_>O ziZIZaDXmkWmS(VJC}cQIKESBJ>HuWffLNSX8HyQ78S>s7lhc`77^648VYX#rY~8HI zwuD(bIzu)iDkHqKhchoRH?^d)Ahj6m{OFF1D8JGSA&^&OGgLFeGgK%4<@`ALGglC! f^<+10AI4W;TdaV#JO{F5CSTz;V0=26l}8-_188TE diff --git a/documentation/_build/doctrees/index.doctree b/documentation/_build/doctrees/index.doctree index 76218cc6ab17b6562d8becede462482f326cde5e..1c460c21317d7e6757fd245ffd7117389a680ab8 100644 GIT binary patch delta 1021 zcmb7DOK1~O6wNe=lSz}>+K`&2(pYReS}Z}4Ac6=&K?Ac86%=ASNuRxm`E@=>7ydAQ z0s}7ItAcK%pooaSSgS=)p)Onsf*UvDO2kM(aMOkNO_Mf@66)fedE9%>n{&ADEyb!a z*G2dA_h+szqF=Jav#OR)=O-9tbjGt^@X~LdU5Ei`58`3zkf2j0r38)smHOHu#jH7z z&g;Vr!~~;vJqMZ#Xt#HyIU}@s0+pl-tc&ZEbb!h8LSO~08SWy zL68+%Z9V2LWAPe2;T-mtR$K8-dfE3xd;kyO5j>`Q{pUBmFrgoAFDv6g6y2g9{kykK z4Oyj|g{Yq;1EAdvHI&6w947)7f!$m8tL)d!JNz9v7fuNk>hiprzHU z&S16-FUv4jhF5V1ye`8$65qh*MgtN2?Sh$9p^L{2At8+GoeEp<(~E0sf^q(ey>Kma zbAPg8dG#sXAh}VEOrlH0@-NS8G+R)|iDs94wGtExXLP%=F;&nAN_0a@rwqdLDV9?$ zrg1}fP#J!}PxuADVUg4mA0elSM)E1b6X({7{HHPU07m}$Katm!Sh2)ZA#bQD1FhOK z$w-33Q6GzVu-06AC>bAe8%;*h~wm^xFwJ-Prcm&At7{5p~+A%3~R%SZJT7=^j zXW*^#WE9((og8Ei{TzBZ^dOj)lvi`am?{#TU;GSbD>hTHS=UVn@j5>MhHN#IY-uJ~ q>Dk;WP&xELn5WgypfE>Ig`;$&yRU1OvxE3fR^Ce7g`w#C@V&a delta 1240 zcmbVMO-NKx6!tZLPK{$Tq%kvPPnjAW&4nUHfu&I)6GNF2{YcF`Z=UxU-^=#{wJ?=1 z8kj|LuTk3yY8N#`n1%gl(V|6*FbafR)h1{Y1T8x6IioMIj28F2d(Y23-~G-x?`!MN zR_BOo;@dsvoJZVUH_C=sEx2-_c>HL4SF$sCU?<;`Jks6Xad02seyB4ZXW;2&;LW); zT~*|MMp-ckGL|Wjt5`9Vjj_V*;HE>qs7r=Qkm#td!BY<$IE*xvy?Z#G-t{)2JYL#@ z@=9qZC({q50&Vlwa4P-0cK_cz!YY3@WAux%)@VyNhKVlHV~%*B4YolHY7>6cSV`%; zug7&2PYmsiW#cB0f=`fYWp_Of;2})H6s_}L2tG4lE8H%aD=_F5o%AbVblrLU@Zf91~tGR+85hURGps zPSkW!?&tdy!5AR2&d0R#IvK!z7>q5>ejwNJAJ;65T+^zGH!X}@x6P*;ng6)_qW8-$ l3N%aa@RW0AM47Ne6#qJkp_*+M!_rBG=l(u?gyti=egW#&t;zrZ diff --git a/documentation/_build/doctrees/plugin_hooks.doctree b/documentation/_build/doctrees/plugin_hooks.doctree new file mode 100644 index 0000000000000000000000000000000000000000..79fcd56e2210dff320ff0cce10497842ba9ec1b2 GIT binary patch literal 3155 zcma)8TWcFf6wbwxEJv0d=h9o$C@uk~)KVMzP*OrDfs$fy(h~Y+rlZ}FX5!tQ?aZt% z4}ta}kifiU3jGEBjipfNclIL5rZhDO@0>Yv&Y5q%bNQw9+mqgf^3QMBT&nD3#N#;A zv9Q6f#yToek-6|T-1{}W3_HGS__5W6iA3-hpb<%x#71P{0GoZ%cPg=?+CbZJGZTyB zvgNOiMnje-#Y|;PYJF%Q1lc(VevLb4)TD55OpY$A*utpqLpJ0agi?; z6CNEJF|Bm)q2l0sm5<%hM<{&9@fn>6a?P(KDidMvqHpIMvAZBI%Zu`|Z#Or4JeE2Y zW8jgfd~8iLHtI;YG1(MO?v|GvH|TJubXM*)cN!V%LNSqD-?1X1?Ky(7CEIl29c;Fo za*0^l^1WvzGQ%f?ObHCsR-TI!!tmVgt57}(41Oku@>9Bjyt6NF?-vs;H-VwtItcPQ zemC)ZAHNR|LLonvJ5aw{smpD7d#_bY=8q3gBd22>e3$+)ddTGf2eU%OV(9en*eIv6 z*|5TSSm9jV>|R9{y!Og-vPDukt{022+lb?v{}b#(d8Z7tQ$pIsqw$&Hxm*fNKB}F( zBfy3CNAUjrySzVbJVW_mF%ffIiJ$iaCwTn^k5ioi4V~?l*zsk=eFr=#nb&Z#;(hrP zUoY7&pJds`jvSDiFM?=Zai=j+!`&=vi(>heKS9VPt!o!8|A9Ek!A6D*5ukk}Vm3Kt zWoR#h%w*5{_x@D{`2>Xl6qdtlf@+-3(?@O-%P#tUR2WJxR;Sgz?=_M#0r&l?6^=-R zT61+?JElfwPGrd8_K!R%knm0QkvsdoI}@2O+-VcAh&k$o<7tk?mC6l+?L#cr>SbXP ztk#{57}W{dg}WBwGN-|BO|^EJc4BE0g<+l2HY-wgGSw!fQqi|4PdSTpN(IrvL%Nvnv<5(h&L=yHc`8COt`4W{;oG4)BxGQX<)bg!ZOo|!Y z^^dv9fE6^1;3*_sXLuy&QsK4lt1K@Z!?WrbTFBqRO?SWAwF=+2&TcYcj5bX2EKY<0 z&J=3oz+_#xvsPNAmEZ^GcFviQzx#e=bP+&v^w!ypb0_^KUBCh*349Vk0cWg*F`R?7%zXU9OGmXxTp)KXPF^e5)siJT;x&SUNTOXtc;70g z@M2Va7)~D+If9{~rR>9XuD=0EbfmH=p1Mi?Eh+~nerNSIMLIzZweA$Yq`;i>#@~n% z%@3JKxk?x&DI?0^<+Z;ovZH|3>{qKYfV=~XR2D1n+OcX-Dkqq$a0FI33>m;Crn%-N z3e_2DHTyseYt#9nP3*_mM8z5%x5usT&}JpuL5Uy8RK6&Dm!$4A2XZtgWUpnqU&t-` z9$++hf!|N)cYb~O5z8>vBZUG*fx%ZLp+sx+stYVjDm`>bJY_o3$($FZ>h*KNxpw!A z#ct!ZJhXMjJ_@FBRH1L2w^i?4@M|aokuE67gTE5#Bmv~O1NuPcaV>vKsQs~b$-W9d zAR#bgAjL3kT9l#6>%1f^i!q+{?WsjpHPS`5swX}9tQm)@$q$pz{U^ZQP%9c%4?o;q z9#^-A$_~+#hV#^kM`1C!(A@O*yC;{S{OiAze5-Cm7ySxR0h#sP{3RE*F bQ$PO`#{88z2qk~lVyek?`J#!kn2i1b$br&e literal 0 HcmV?d00001 diff --git a/documentation/_build/doctrees/plugin_loader.doctree b/documentation/_build/doctrees/plugin_loader.doctree new file mode 100644 index 0000000000000000000000000000000000000000..493c0d3187eb7432ffd668bc8249033bcaf3f701 GIT binary patch literal 3176 zcma)8TWcIQ6pmx>uGjXi9p}OFwpEZE%QV}s_n!n(Hca2w*<+`uhpc;=Z7(g zj}@JiJow;=v%ONueyPM2wqwZDKXGi$uB2R0cd%sJIf3=Yv1PWzmTkNC?duVf865$U zl;rOLn%)ZXL9Wagza1H8e7j&UXF3$VYS0#5-d}$#Ei2#XwF5CC-Bq z=fR{9rMIPr_sYCM;8&h_iJrQ*wH$qd$o)T|0eHinRGGecVKl$^h!y~zC&j@(lbKQP!vK;lW2Sv z1?!$UCfJ6yZ~Z3=N(>A;U|2M;Hmg?J6cpR_Nw;MCaiM&{MOC34+KrkLO7hUIYHAD@ zQ}mxJO+T3^DGU`T>-JA1Ezkq%j>Ps3ZFfoqRm4c;a7YMRh#^^y!+NPEg6v})*Q#To zQk;55#*uFw{ub(5uuGjeyFHQ82x;iTC0a$#*Rd$FXf}~5^Ub5L(XsLl5}k6xqPl@WWA&iwXmDQ9Tq+Z#^n|AF;Ids~ByEl@dxg$8urkCHx@KzGRzkhUQ`HKrL?Ur{y10@E0QaFUPPKlTn zWJ&=yx{#oDkkkv@3=}{sw2%Fqlxtd`LC!LtPg^JyscE$MGNcIV>x64w=I3UV za81UkccikiQ&$7qwHt6oBmculfzV#X7EO3sj=p|Q^Lf2`TQ)ppOrY8)wjD5Ia(#a^ zIz2rd=4XaUF_daLO6bW5oOMH2_cR%_Jh1OS-_<|ZwnX9>3 zt1(hyoG~Fn6$OcaTk4)D%|JZX%ug@V>M+f;C)ds(jx>(t3;% zWbryyj^>D}+tO#kkXgj|l%@C~M^{qm(|bc_1jY1Af!fu0c{QBNBl=-XDg<|8hPe?V zzGY1zV!ruAczs;tFvc%3VK7&<{?hh9;bMYN*Tui>+X0&2dA=>0jnPB3IfE`nvHQHV z*JI4a!|dA7G0#9&4*=4epfFz6~NzR+sE(t$-v$%jFSP-bJ9HhB?PuU#NE z+}(2$yS3KvX#1ReG)!fDhrWJMR&{g9uAvRYvhYRj?0PKI6p+IQ%z@5V75$Y*?azbD z`nmfN1%YJ)C58o5qYaf>o0hOh#=6$mXBt&iQ|HsFTK(ALdM_$hL99fdehciCA4P*Q z@PplR8|?0Y>j9?HpsAf?=;qst-=O|^{q{0ofBzqoZB>(K$*%ZZKxut<_{}3f4$7q; f9je}){XqWMi`+CBnK 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 diff --git a/documentation/_build/html/.buildinfo b/documentation/_build/html/.buildinfo index 7db4065..5e8bb2c 100644 --- a/documentation/_build/html/.buildinfo +++ b/documentation/_build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: d325def9cbc62f774a29b7fa152439a4 +config: aa952c05dc8678fa4bab1d866c89bf40 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/documentation/_build/html/_sources/anatomy.rst.txt b/documentation/_build/html/_sources/anatomy.rst.txt index cc393f6..4a94f1d 100644 --- a/documentation/_build/html/_sources/anatomy.rst.txt +++ b/documentation/_build/html/_sources/anatomy.rst.txt @@ -1,122 +1,7 @@ .. _anatomy: -=================== -Anatomy of a Plugin -=================== +============== +Plugin Anatomy +============== -Plugins for Plugeth use Golang's `Native Plugin System`_. Plugin modules must export variables using specific names and types. These will be processed by the plugin loader, and invoked at certain points during Geth's operations. - -API -*** - -Flags ------ - -* **Name:** Flags -* **Type:** `flag.FlagSet`_ -* **Behavior:** This FlagSet will be parsed and your plugin will be able to access the resulting flags. Flags will be passed to Geth from the command line and are intended to of the plugin. Note that if any flags are provided, certain checks are disabled within Geth to avoid failing due to unexpected flags. - -Subcommands ------------ - -* **Name:** Subcommands -* **Type:** map[string]func(ctx `*cli.Context`_, args []string) error -* **Behavior:** If Geth is invoked with ``./geth YOUR_COMMAND``, the plugin loader will look for ``YOUR_COMMAND`` within this map, and invoke the corresponding function. This can be useful for certain behaviors like manipulating Geth's database without having to build a separate binary. - -Initialize ----------- - -* **Name:** Initialize -* **Type:** func(*cli.Context, core.PluginLoader, core.logs ) -* **Behavior:** Called as soon as the plugin is loaded, with the cli context and a reference to the plugin loader. This is your plugin's opportunity to initialize required variables as needed. Note that using the context object you can check arguments, and optionally can manipulate arguments if needed for your plugin. -:ref:`Core vs Restricted packages in Plugeth-utils` - -**todo: explain that plugin could provide node.Node with restricted.backend** - -InitializeNode --------------- - -* **Name:** InitializeNode -* **Type:** func(core.Node, core.Backend) -* **Behavior:** This is called as soon as the Geth node is initialized. The core.Node object represents the running node with p2p and RPC capabilities, while the Backend gives you access to a wide array of data you may need to access. - -Tracers -------- - -* **Name:** Tracers -* **Type:** map[string]TracerResult -* **Behavior:** When calling debug.traceX functions (such as ``debug_traceCall`` and ``debug_traceTransaction``) the tracer can be specified as a key to this map and the tracer used will be the TracerResult specified here. TracerResult objects must match the interface: - -.. code-block:: go - - ``// CaptureStart is called at the start of each transaction - CaptureStart(env core.EVM, from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {} - // CaptureState is called for each opcode - CaptureState(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {} - // CaptureFault is called when an error occurs in the EVM - CaptureFault(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {} - // CaptureEnd is called at the end of each transaction - CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {} - // GetResult should return a JSON serializable result object to respond to the trace call - GetResult() (interface{}, error) {}`` - - -.. warning:: Modifying the values passed into tracer functions can alter the - results of the EVM execution in unpredictable ways. Additonally, some objects may be reused acress calls, so data you wish to capture should be copied rather than retianed by reference. - -LiveTracer ----------- - -* **Name:** LiveTracers -* **Type:** core.Tracer -* **Behavior:** This tracer is used for tracing transactions as they are processed within blocks. Note that if a block does not validate, some transactions may be processed that don't end up in blocks, so be sure to check transactions against finalized blocks. - -The interface for a vm.Tracer is similar to a TracerResult (above), but does not require a ``GetResult()`` function. - -GetAPIs -------- - -* **Name:** GetAPIs -* **Type:** func(core.Node, core.Backend) []rpc.API -* **Behavior:** This allows you to register new RPC methods to run within Geth. - -The GetAPIs function itself will generally be fairly brief, and will looks something like this: - -.. code-block:: go - - ``func GetAPIs(stack *node.Node, backend core.Backend) []core.API { - return []rpc.API{ - { - Namespace: "mynamespace", - Version: "1.0", - Service: &MyService{backend}, - Public: true, - }, - } - }`` - -The bulk of the implementation will be in the ``MyService`` struct. MyService should be a struct with public functions. These functions can have two different types of signatures: - -* RPC Calls: For straight RPC calls, a function should have a ``context.Context`` object as the first argument, followed by an arbitrary number of JSON marshallable arguments, and return either a single JSON marshal object, or a JSON marshallable object and an error. The RPC framework will take care of decoding inputs to this function and encoding outputs, and if the error is non-nil it will serve an error response. - -* Subscriptions: For subscriptions (supported on IPC and websockets), a function should have a ``context.Context`` object as the first argument followed by an arbitrary number of JSON marshallable arguments, and should return an ``*rpc.Subscription`` object. The subscription object can be created with ``rpcSub := notifier.CreateSubscription()``, and JSON marshallable data can be sent to the subscriber with ``notifier.Notify(rpcSub.ID, b)``. - -A very simple MyService might look like: - -.. code-block:: go - - ``type MyService struct{} - - func (h MyService) HelloWorld(ctx context.Context) string { - return "Hello World" - }`` - -And the client could access this with an rpc call to -``mynamespace_helloworld`` - - - - -.. _*cli.Context: https://pkg.go.dev/github.com/urfave/cli#Context -.. _flag.FlagSet: https://pkg.go.dev/flag#FlagSet -.. _Native Plugin System: https://pkg.go.dev/plugin \ No newline at end of file +.. todo:: fill in disections of archetypal plugins \ No newline at end of file diff --git a/documentation/_build/html/_sources/api.rst.txt b/documentation/_build/html/_sources/api.rst.txt new file mode 100644 index 0000000..ef3ee53 --- /dev/null +++ b/documentation/_build/html/_sources/api.rst.txt @@ -0,0 +1,120 @@ +.. _api: + +=== +API +=== + +Plugins for Plugeth use Golang's `Native Plugin System`_. Plugin modules must export variables using specific names and types. These will be processed by the plugin loader, and invoked at certain points during Geth's operations. + +Flags +----- + +* **Name:** Flags +* **Type:** `flag.FlagSet`_ +* **Behavior:** This FlagSet will be parsed and your plugin will be able to access the resulting flags. Flags will be passed to Geth from the command line and are intended to of the plugin. Note that if any flags are provided, certain checks are disabled within Geth to avoid failing due to unexpected flags. + +Subcommands +----------- + +* **Name:** Subcommands +* **Type:** map[string]func(ctx `*cli.Context`_, args []string) error +* **Behavior:** If Geth is invoked with ``./geth YOUR_COMMAND``, the plugin loader will look for ``YOUR_COMMAND`` within this map, and invoke the corresponding function. This can be useful for certain behaviors like manipulating Geth's database without having to build a separate binary. + +Initialize +---------- + +* **Name:** Initialize +* **Type:** func(*cli.Context, core.PluginLoader, core.logs ) +* **Behavior:** Called as soon as the plugin is loaded, with the cli context and a reference to the plugin loader. This is your plugin's opportunity to initialize required variables as needed. Note that using the context object you can check arguments, and optionally can manipulate arguments if needed for your plugin. + +.. todo:: explain that plugin could provide node.Node with + restricted.backend + +InitializeNode +-------------- + +* **Name:** InitializeNode +* **Type:** func(core.Node, core.Backend) +* **Behavior:** This is called as soon as the Geth node is initialized. The core.Node object represents the running node with p2p and RPC capabilities, while the Backend gives you access to a wide array of data you may need to access. + +Tracers +------- + +* **Name:** Tracers +* **Type:** map[string]TracerResult +* **Behavior:** When calling debug.traceX functions (such as ``debug_traceCall`` and ``debug_traceTransaction``) the tracer can be specified as a key to this map and the tracer used will be the TracerResult specified here. TracerResult objects must match the interface: + +.. code-block:: go + + ``// CaptureStart is called at the start of each transaction + CaptureStart(env core.EVM, from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {} + // CaptureState is called for each opcode + CaptureState(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {} + // CaptureFault is called when an error occurs in the EVM + CaptureFault(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {} + // CaptureEnd is called at the end of each transaction + CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {} + // GetResult should return a JSON serializable result object to respond to the trace call + GetResult() (interface{}, error) {}`` + + +.. warning:: Modifying the values passed into tracer functions can + alter the + results of the EVM execution in unpredictable ways. Additonally, some objects may be reused acress calls, so data you wish to capture should be copied rather than retianed by reference. + +LiveTracer +---------- + +* **Name:** LiveTracers +* **Type:** core.Tracer +* **Behavior:** This tracer is used for tracing transactions as they are processed within blocks. Note that if a block does not validate, some transactions may be processed that don't end up in blocks, so be sure to check transactions against finalized blocks. + +The interface for a vm.Tracer is similar to a TracerResult (above), but does not require a ``GetResult()`` function. + +GetAPIs +------- + +* **Name:** GetAPIs +* **Type:** func(core.Node, core.Backend) []rpc.API +* **Behavior:** This allows you to register new RPC methods to run within Geth. + +The GetAPIs function itself will generally be fairly brief, and will looks something like this: + +.. code-block:: go + + ``func GetAPIs(stack *node.Node, backend core.Backend) []core.API { + return []rpc.API{ + { + Namespace: "mynamespace", + Version: "1.0", + Service: &MyService{backend}, + Public: true, + }, + } + }`` + +The bulk of the implementation will be in the ``MyService`` struct. MyService should be a struct with public functions. These functions can have two different types of signatures: + +* RPC Calls: For straight RPC calls, a function should have a ``context.Context`` object as the first argument, followed by an arbitrary number of JSON marshallable arguments, and return either a single JSON marshal object, or a JSON marshallable object and an error. The RPC framework will take care of decoding inputs to this function and encoding outputs, and if the error is non-nil it will serve an error response. + +* Subscriptions: For subscriptions (supported on IPC and websockets), a function should have a ``context.Context`` object as the first argument followed by an arbitrary number of JSON marshallable arguments, and should return an ``*rpc.Subscription`` object. The subscription object can be created with ``rpcSub := notifier.CreateSubscription()``, and JSON marshallable data can be sent to the subscriber with ``notifier.Notify(rpcSub.ID, b)``. + +A very simple MyService might look like: + +.. code-block:: go + + ``type MyService struct{} + + func (h MyService) HelloWorld(ctx context.Context) string { + return "Hello World" + }`` + +And the client could access this with an rpc call to +``mynamespace_helloworld`` + + + + +.. _*cli.Context: https://pkg.go.dev/github.com/urfave/cli#Context +.. _flag.FlagSet: https://pkg.go.dev/flag#FlagSet +.. _Native Plugin System: https://pkg.go.dev/plugin \ No newline at end of file diff --git a/documentation/_build/html/_sources/build.rst.txt b/documentation/_build/html/_sources/build.rst.txt index e81b8b7..28d302b 100644 --- a/documentation/_build/html/_sources/build.rst.txt +++ b/documentation/_build/html/_sources/build.rst.txt @@ -1,7 +1,8 @@ .. _build: -Build -===== +================ +Build and Deploy +================ .. contents:: :local: diff --git a/documentation/_build/html/_sources/core_restricted.rst.txt b/documentation/_build/html/_sources/core_restricted.rst.txt index 433318f..c224faf 100644 --- a/documentation/_build/html/_sources/core_restricted.rst.txt +++ b/documentation/_build/html/_sources/core_restricted.rst.txt @@ -4,4 +4,5 @@ Core vs Restricted packages in Plugeth-utils ============================================ -**todo: copy on core and restricted packages in utils. what, why, how.** + +.. todo:: need explinations of core vs restircted functionality. what, why, how. \ No newline at end of file diff --git a/documentation/_build/html/_sources/hooks.rst.txt b/documentation/_build/html/_sources/hooks.rst.txt index 397c22c..b7940ee 100644 --- a/documentation/_build/html/_sources/hooks.rst.txt +++ b/documentation/_build/html/_sources/hooks.rst.txt @@ -4,5 +4,4 @@ Plugin Hooks ============ - -**todo: discussion on plugin hooks** \ No newline at end of file +.. todo:: discussion of plugin hooks diff --git a/documentation/_build/html/_sources/index.rst.txt b/documentation/_build/html/_sources/index.rst.txt index f3ff255..ab2fd8a 100644 --- a/documentation/_build/html/_sources/index.rst.txt +++ b/documentation/_build/html/_sources/index.rst.txt @@ -8,11 +8,12 @@ PluGeth PluGeth is a fork of the `Go Ethereum Client Geth`_ that implements a plugin architecture, allowing developers to extend Geth's capabilities in a number of different ways using plugins, rather than having to create additional, new forks of Geth. -**WARNING: UNSTABLE API** +.. warning:: Right now PluGeth is in early development. We are + still settling on some of the plugin APIs, and are + not yet making official releases. From an operational + perspective, PluGeth should be as stable as upstream Geth less whatever isstability is added by plugins you might run. But if you plan to run PluGeth today, be aware that furture updates will likely break you plugins. -Right now PluGeth is in early development. We are still settling on some of the plugin APIs, and are not yet making official releases. From an operational perspective, PluGeth should be as stable as upstream Geth less whatever instability is added by plugins you might run. But if you plan to run PluGeth today, be aware that future updates will likely break your plugins. - Table of Contents ***************** @@ -26,6 +27,7 @@ Table of Contents types hooks anatomy + .. toctree:: :maxdepth: 1 @@ -37,8 +39,11 @@ Table of Contents :maxdepth: 1 :caption: Reference - sytem_req + system_req + plugin_loader + plugin_hooks core_restricted + api .. toctree:: :maxdepth: 1 diff --git a/documentation/_build/html/_sources/plugin_hooks.rst.txt b/documentation/_build/html/_sources/plugin_hooks.rst.txt new file mode 100644 index 0000000..601ee4a --- /dev/null +++ b/documentation/_build/html/_sources/plugin_hooks.rst.txt @@ -0,0 +1,7 @@ +.. _plugin_hooks: + +============ +Plugin Hooks +============ + +.. todo:: guide to writing plugin hooks \ No newline at end of file diff --git a/documentation/_build/html/_sources/plugin_loader.rst.txt b/documentation/_build/html/_sources/plugin_loader.rst.txt new file mode 100644 index 0000000..d1de719 --- /dev/null +++ b/documentation/_build/html/_sources/plugin_loader.rst.txt @@ -0,0 +1,7 @@ +.. _plugin_loader: + +============= +Plugin Loader +============= + +.. todo:: breakdown of plugin loader function \ No newline at end of file diff --git a/documentation/_build/html/_sources/project.rst.txt b/documentation/_build/html/_sources/project.rst.txt index 76d3919..315f726 100644 --- a/documentation/_build/html/_sources/project.rst.txt +++ b/documentation/_build/html/_sources/project.rst.txt @@ -37,14 +37,14 @@ Plugins are packages which contain premade plugins as well as a location provide Dependency Scheme ----------------- -**todo: copy on version number protocol** +.. todo:: needs elaboration of dependency scheme -.. _obscures security updates as optimixations: https://blog.openrelay.xyz/vulnerability-lifecycle-framework-geth/ +.. _obscures security updates as optimizations: https://blog.openrelay.xyz/vulnerability-lifecycle-framework-geth/ .. _PluGeth: https://github.com/openrelayxyz/plugeth .. _PluGeth-Utils: https://github.com/openrelayxyz/plugeth-utils .. _PluGeth-Plugins: https://github.com/openrelayxyz/plugeth-plugin \ No newline at end of file diff --git a/documentation/_build/html/anatomy.html b/documentation/_build/html/anatomy.html index ad59631..371a82a 100644 --- a/documentation/_build/html/anatomy.html +++ b/documentation/_build/html/anatomy.html @@ -3,7 +3,7 @@ - Anatomy of a Plugin — Plugeth Austin Roberts documentation + Plugin Anatomy — Plugeth Austin Roberts documentation + + + + + + + + + + + + +

+ + +
+ +
+
+
+ +
+
+
+
+ +
+

API

+

Plugins for Plugeth use Golang’s Native Plugin System. Plugin modules must export variables using specific names and types. These will be processed by the plugin loader, and invoked at certain points during Geth’s operations.

+
+

Flags

+
    +
  • Name: Flags

  • +
  • Type: flag.FlagSet

  • +
  • Behavior: This FlagSet will be parsed and your plugin will be able to access the resulting flags. Flags will be passed to Geth from the command line and are intended to of the plugin. Note that if any flags are provided, certain checks are disabled within Geth to avoid failing due to unexpected flags.

  • +
+
+
+

Subcommands

+
    +
  • Name: Subcommands

  • +
  • Type: map[string]func(ctx *cli.Context, args []string) error

  • +
  • Behavior: If Geth is invoked with ./geth YOUR_COMMAND, the plugin loader will look for YOUR_COMMAND within this map, and invoke the corresponding function. This can be useful for certain behaviors like manipulating Geth’s database without having to build a separate binary.

  • +
+
+
+

Initialize

+
    +
  • Name: Initialize

  • +
  • Type: func(*cli.Context, core.PluginLoader, core.logs )

  • +
  • Behavior: Called as soon as the plugin is loaded, with the cli context and a reference to the plugin loader. This is your plugin’s opportunity to initialize required variables as needed. Note that using the context object you can check arguments, and optionally can manipulate arguments if needed for your plugin.

  • +
+
+

Todo

+

explain that plugin could provide node.Node with +restricted.backend

+
+
+
+

InitializeNode

+
    +
  • Name: InitializeNode

  • +
  • Type: func(core.Node, core.Backend)

  • +
  • Behavior: This is called as soon as the Geth node is initialized. The core.Node object represents the running node with p2p and RPC capabilities, while the Backend gives you access to a wide array of data you may need to access.

  • +
+
+
+

Tracers

+
    +
  • Name: Tracers

  • +
  • Type: map[string]TracerResult

  • +
  • Behavior: When calling debug.traceX functions (such as debug_traceCall and debug_traceTransaction) the tracer can be specified as a key to this map and the tracer used will be the TracerResult specified here. TracerResult objects must match the interface:

  • +
+
``// CaptureStart is called at the start of each transaction
+CaptureStart(env core.EVM, from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {}
+// CaptureState is called for each opcode
+CaptureState(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {}
+// CaptureFault is called when an error occurs in the EVM
+CaptureFault(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {}
+// CaptureEnd is called at the end of each transaction
+CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
+// GetResult should return a JSON serializable result object to respond to the trace call
+GetResult() (interface{}, error) {}``
+
+
+
+

Warning

+

Modifying the values passed into tracer functions can +alter the +results of the EVM execution in unpredictable ways. Additonally, some objects may be reused acress calls, so data you wish to capture should be copied rather than retianed by reference.

+
+
+
+

LiveTracer

+
    +
  • Name: LiveTracers

  • +
  • Type: core.Tracer

  • +
  • Behavior: This tracer is used for tracing transactions as they are processed within blocks. Note that if a block does not validate, some transactions may be processed that don’t end up in blocks, so be sure to check transactions against finalized blocks.

  • +
+

The interface for a vm.Tracer is similar to a TracerResult (above), but does not require a GetResult() function.

+
+
+

GetAPIs

+
    +
  • Name: GetAPIs

  • +
  • Type: func(core.Node, core.Backend) []rpc.API

  • +
  • Behavior: This allows you to register new RPC methods to run within Geth.

  • +
+

The GetAPIs function itself will generally be fairly brief, and will looks something like this:

+
  ``func GetAPIs(stack *node.Node, backend core.Backend) []core.API {
+  return []rpc.API{
+   {
+     Namespace: "mynamespace",
+     Version:      "1.0",
+     Service:      &MyService{backend},
+     Public:              true,
+   },
+  }
+}``
+
+
+

The bulk of the implementation will be in the MyService struct. MyService should be a struct with public functions. These functions can have two different types of signatures:

+
    +
  • RPC Calls: For straight RPC calls, a function should have a context.Context object as the first argument, followed by an arbitrary number of JSON marshallable arguments, and return either a single JSON marshal object, or a JSON marshallable object and an error. The RPC framework will take care of decoding inputs to this function and encoding outputs, and if the error is non-nil it will serve an error response.

  • +
  • Subscriptions: For subscriptions (supported on IPC and websockets), a function should have a context.Context object as the first argument followed by an arbitrary number of JSON marshallable arguments, and should return an *rpc.Subscription object. The subscription object can be created with rpcSub := notifier.CreateSubscription(), and JSON marshallable data can be sent to the subscriber with notifier.Notify(rpcSub.ID, b).

  • +
+

A very simple MyService might look like:

+
``type MyService struct{}
+
+  func (h MyService) HelloWorld(ctx context.Context) string {
+    return "Hello World"
+  }``
+
+
+

And the client could access this with an rpc call to +mynamespace_helloworld

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/documentation/_build/html/build.html b/documentation/_build/html/build.html index 139d3e7..a905eb8 100644 --- a/documentation/_build/html/build.html +++ b/documentation/_build/html/build.html @@ -3,7 +3,7 @@ - Build — Plugeth Austin Roberts documentation + Build and Deploy — Plugeth Austin Roberts documentation + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Plugin Hooks

+
+

Todo

+

guide to writing plugin hooks

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/documentation/_build/html/plugin_loader.html b/documentation/_build/html/plugin_loader.html new file mode 100644 index 0000000..9e35e0e --- /dev/null +++ b/documentation/_build/html/plugin_loader.html @@ -0,0 +1,124 @@ + + + + + + Plugin Loader — Plugeth Austin Roberts documentation + + + + + + + + + + + + + + +
+ + +
+ +
+
+
+ +
+
+
+
+ +
+

Plugin Loader

+
+

Todo

+

breakdown of plugin loader function

+
+
+ + +
+
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/documentation/_build/html/plugins.html b/documentation/_build/html/plugins.html index 0c9f7ef..63f01a4 100644 --- a/documentation/_build/html/plugins.html +++ b/documentation/_build/html/plugins.html @@ -37,15 +37,19 @@
  • Project Design
  • Basic Types of Plugins
  • Plugin Hooks
  • -
  • Anatomy of a Plugin
  • +
  • Plugin Anatomy
  • Tutorials

    Reference

    Contact

    Tutorials

    Reference

    Contact

      @@ -92,7 +96,7 @@

      Design Goals

      The upstream Geth client exists primarily to serve as a client for the Ethereum mainnet, though it also supports a number of popular testnets. Supporting the Ethereum mainnet is a big enough challenge in its own right that the Geth team generally avoids changes to support other networks, or to provide features only a small handful of users would be interested in.

      The result is that many projects have forked Geth. Some implement their own consensus protocols or alter the behavior of the EVM to support other networks. Others are designed to extract information from the Ethereum mainnet in ways the standard Geth client does not support.

      -

      Creating numerous different forks to fill a variety of different needs comes with a number of drawbacks. Forks tend to drift apart from each other. Many networks that forked from Geth long ago have stopped merging updates from Geth; this makes some sense, given that those networks have moved in different directions than Geth and merging upstream changes while properly maintaining consensus rules of an existing network could prove quite challenging. But not merging changes from upstream can mean that security updates are easily missed, especially when the upstream team `obscures security updates as optimizations`_ as a matter of process.

      +

      Creating numerous different forks to fill a variety of different needs comes with a number of drawbacks. Forks tend to drift apart from each other. Many networks that forked from Geth long ago have stopped merging updates from Geth; this makes some sense, given that those networks have moved in different directions than Geth and merging upstream changes while properly maintaining consensus rules of an existing network could prove quite challenging. But not merging changes from upstream can mean that security updates are easily missed, especially when the upstream team obscures security updates as optimizations as a matter of process.

      PluGeth aims to provide a single Geth fork that developers can choose to extend rather than forking the Geth project. Out of the box, PluGeth behaves exactly like upstream Geth, but by installing plugins written in Golang, developers can extend its functionality in a wide variety of ways.

      Three Repositories

      @@ -112,7 +116,10 @@

      Dependency Scheme

      -

      todo: copy on version number protocol

      +
      +

      Todo

      +

      needs elaboration of dependency scheme

      +
      diff --git a/documentation/_build/html/search.html b/documentation/_build/html/search.html index 4dced0e..9bcc5bb 100644 --- a/documentation/_build/html/search.html +++ b/documentation/_build/html/search.html @@ -40,15 +40,19 @@
    • Project Design
    • Basic Types of Plugins
    • Plugin Hooks
    • -
    • Anatomy of a Plugin
    • +
    • Plugin Anatomy

    Tutorials

    Reference

    Contact

      diff --git a/documentation/_build/html/searchindex.js b/documentation/_build/html/searchindex.js index c68339c..f81bb50 100644 --- a/documentation/_build/html/searchindex.js +++ b/documentation/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["anatomy","build","contact","core_restricted","hooks","index","plugeth","plugins","project","system_req","types","utils"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,sphinx:56},filenames:["anatomy.rst","build.rst","contact.rst","core_restricted.rst","hooks.rst","index.rst","plugeth.rst","plugins.rst","project.rst","system_req.rst","types.rst","utils.rst"],objects:{},objnames:{},objtypes:{},terms:{"127":1,"350":[1,9],"8545":1,"break":5,"byte":0,"export":0,"final":0,"function":[0,8,10],"int":0,"long":8,"new":[0,1,5,8,10],"public":0,"return":[0,10],"true":0,"while":[0,8],And:0,But:[5,8],For:[0,8],The:[0,2,8],These:0,abl:0,abov:[0,10],access:[0,1],acress:0,added:[5,9],addit:5,addition:1,additon:0,address:0,against:0,ago:8,aim:8,all:[1,8],allow:[0,5],also:[8,10],alter:[0,8],analysi:8,anatomi:5,ani:[0,2],anxiou:2,apart:8,api:[1,5,10],append:[1,10],applic:[1,8],arbitrari:0,architectur:[5,8],archtyp:10,arg:[0,10],argument:[0,10],arrai:0,avail:[1,10],avoid:[0,8],awar:5,backend:[0,10],basic:5,been:[1,8],begin:1,behav:8,behavior:[0,1,8,10],best:2,big:[0,8],binari:0,block:0,bool:0,box:8,brief:0,build:[0,5],buildmod:1,built:[1,8],bulk:0,call:[0,1],can:[0,8,10],cannot:10,capabl:[0,5],captur:0,captureend:0,capturefault:0,capturest:0,capturestart:0,care:0,certain:0,challeng:8,chang:[1,8],channel:10,check:0,choos:[1,8],cli:0,client:[0,5,8],clone:1,cmd:1,come:8,command:[0,1,10],compact:1,compil:1,complet:1,concur:10,congradul:1,connect:[1,9,10],consensu:8,contact:5,contain:8,contant:10,content:1,context:[0,10],control:10,copi:[0,3,7,8,11],core:[0,5],correspond:0,cost:0,could:[0,8,10],cpu:[1,9],creat:[0,5,8],createsubscript:0,ctx:0,curl:1,custom:[8,10],data:[0,1,10],databas:0,debug:0,debug_tracecal:0,debug_tracetransact:0,decod:0,depend:[1,9],depth:0,design:5,detail:8,develop:[5,8],differ:[0,5,8],direct:8,directori:1,disabl:0,discord:2,discuss:[4,6],disk:[1,9],doe:[0,8],don:0,download:1,dozen:1,drawback:8,drift:8,drop:2,due:0,durat:0,dure:0,each:[0,8],earli:5,easili:8,either:0,enabl:8,encod:0,end:0,enough:8,env:0,err:0,error:[0,10],especi:8,ethereum:[1,5,8,9],everyon:1,evm:[0,8],exactli:8,execut:0,exist:8,explain:0,extend:[5,8],extract:8,fail:0,fairli:0,familiar:1,featur:8,file:1,fill:8,first:[0,1],flag:[1,10],flagset:0,folder:1,follow:0,forese:9,fork:[1,5,8],framework:0,freebsd:9,friend:1,from:[0,1,2,5,8],func:0,funtion:1,futur:[5,9],gas:0,gasus:0,gener:[0,8,10],get:[1,5],getapi:10,geth:[0,1,5,8,10],getresult:0,give:0,given:8,goal:8,golang:[0,8,9],hand:8,has:[1,8],have:[0,1,2,5,8,9],hear:2,hello:[0,1,2],helloworld:0,help:[1,2],here:[0,8],histor:10,home:1,hook:[5,8],how:3,howev:1,http:[1,10],hybrid:10,idea:2,implement:[0,5,8,9],includ:1,info:1,inform:[8,10],initi:[1,10],input:0,insid:1,instabl:5,instal:8,intend:0,interest:8,interfac:0,invok:0,ipc:0,its:[8,10],itself:0,json:[0,1,10],jsonrpc:[1,10],just:1,kei:0,largest:8,least:[1,9],less:5,like:[0,5,8],limit:10,line:[0,10],link:2,linux:9,list:1,livetrac:10,load:0,loader:[0,8,10],local:1,locat:[1,8],log:[0,1],logger:10,look:0,lot:10,maco:9,made:10,mai:[0,2],main:1,mainnet:[1,8,9],maintain:8,make:[5,8],mani:8,manipul:0,map:0,marshal:0,match:0,matter:8,mean:8,merg:8,method:[0,1],might:[0,5],miss:8,modifi:[0,8],modul:0,moment:1,more:[8,10],move:[1,8],must:[0,10],mymamespac:1,mynamespac:0,mynamespace_hello:1,mynamespace_helloworld:0,myservic:0,name:[0,10],namespac:0,namespace_subscrib:10,nativ:0,navig:1,need:[0,1,8,10],network:[1,8,9],next:1,nil:0,node:[0,1,10],non:0,note:0,notifi:0,now:5,number:[0,5,8],numer:8,object:0,obscur:8,occur:0,offici:5,onc:1,onli:[8,9],opcod:0,oper:[0,5,10],opportun:0,optim:8,option:0,order:[1,10],other:8,our:2,out:8,output:0,overview:5,own:[1,8,10],p2p:0,packag:[0,1,5,8],page:10,param:[1,10],pars:0,pass:[0,10],perspect:5,plan:5,plugeth:[0,1,2,9],plugethplugin:1,plugethutil:1,plugin:[5,9],pluginload:0,point:[0,1],popular:8,practic:1,premad:8,primari:1,primarili:8,problem:2,process:[0,1,8],produc:1,project:[1,5],properli:8,protocol:8,prove:8,provid:[0,1,8,10],quit:8,ram:[1,9],rather:[0,5,8],rdata:0,reach:2,read:1,readi:1,reason:8,reciev:10,redifin:10,refer:[0,5],regist:0,releas:5,reli:[9,10],repo:7,repositori:[1,6],repres:0,requir:[0,1,10],requirr:10,resid:8,respond:[0,1],respons:0,restrict:[0,5],result:[0,1,8],retian:0,reus:0,right:[5,8],rpc:[0,1],rpcsub:0,rule:8,run:[0,1,5,10],sai:2,scope:0,scopecontext:0,secur:8,see:[1,8],sens:8,sent:0,separ:0,seper:1,serializ:0,serv:[0,8],server:2,servic:[0,10],settl:5,should:[0,1,5,9],signatur:0,similar:0,simpl:0,singl:[0,8],singular:10,small:8,some:[0,5,8],someth:0,soon:0,space:1,specif:0,specifi:0,ssd:[1,9],stabl:[5,10],stack:0,stand:10,standard:[1,8],start:[0,1,10],still:5,stop:8,store:8,straight:0,string:0,struct:0,subscrib:0,subscript:0,subscriptionnam:10,support:[0,8,9],sure:0,system:[0,10],take:[0,1,10],team:[2,8],tend:8,testnet:8,than:[0,5,8],thankfulli:1,thei:[0,10],thi:[0,1,8,10],those:8,though:[1,8],three:1,through:[1,2],time:[0,1],todai:5,todo:[0,2,3,4,7,8,10,11],total:10,touch:5,trace:0,tracerresult:0,tracex:0,transact:0,tutori:[1,5],two:[0,1],type:[0,1,5],uint64:0,unexpect:0,unlik:9,unpredict:0,unstabl:5,updat:[5,8],upon:10,upstream:[5,8],use:[0,1],used:[0,8],useful:[0,1],user:8,using:[0,5],util:[0,5],valid:0,valu:0,vari:9,variabl:0,varieti:8,veri:0,verif:10,version:[0,8],wai:[0,2,5,8,10],want:2,warn:5,websocket:[0,10],well:[1,8],what:3,whatev:5,when:[0,8],wherea:10,which:[1,8,9,10],whichev:1,why:3,wide:[0,8],window:9,wish:0,within:0,without:[0,8],work:[2,10],world:[0,1],would:8,wrapper:8,written:8,yet:5,you:[0,1,2,5,9],your:[0,1,2,5,10],your_command:0},titles:["Anatomy of a Plugin","Build","Get in touch with us","Core vs Restricted packages in Plugeth-utils","Plugin Hooks","PluGeth","PluGeth","PluGeth Plugins","Project Design","System Requirements","Basic Types of Plugins","PluGeth Utils"],titleterms:{anatomi:0,api:0,basic:10,build:1,content:5,core:3,depend:8,design:8,environ:1,flag:0,get:2,getapi:0,hook:4,initi:0,initializenod:0,livetrac:0,method:10,packag:3,plugeth:[3,5,6,7,8,11],plugin:[0,1,4,7,8,10],project:8,repositori:8,requir:9,restrict:3,rpc:10,scheme:8,set:1,subcommand:[0,10],subscript:10,system:9,tabl:5,three:8,touch:2,tracer:[0,10],type:10,util:[3,8,11]}}) \ No newline at end of file +Search.setIndex({docnames:["anatomy","api","build","contact","core_restricted","hooks","index","plugeth","plugin_hooks","plugin_loader","plugins","project","system_req","types","utils"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":3,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":2,"sphinx.domains.rst":2,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,"sphinx.ext.todo":2,sphinx:56},filenames:["anatomy.rst","api.rst","build.rst","contact.rst","core_restricted.rst","hooks.rst","index.rst","plugeth.rst","plugin_hooks.rst","plugin_loader.rst","plugins.rst","project.rst","system_req.rst","types.rst","utils.rst"],objects:{},objnames:{},objtypes:{},terms:{"127":2,"350":[2,12],"8545":2,"break":6,"byte":1,"export":1,"final":1,"function":[1,4,9,11,13],"int":1,"long":11,"new":[1,2,6,11,13],"public":1,"return":[1,13],"true":1,"while":[1,11],And:1,But:[6,11],For:[1,11],The:[1,3,11],These:1,abl:1,abov:[1,13],access:[1,2],acress:1,added:[6,12],addit:6,addition:2,additon:1,address:1,against:1,ago:11,aim:11,all:[2,11],allow:[1,6],also:[11,13],alter:[1,11],analysi:11,anatomi:6,ani:[1,3],anxiou:3,apart:11,api:[2,6,13],append:[2,13],applic:[2,11],arbitrari:1,archetyp:0,architectur:[6,11],archtyp:13,arg:[1,13],argument:[1,13],arrai:1,avail:[2,13],avoid:[1,11],awar:6,backend:[1,13],basic:6,been:[2,11],begin:2,behav:11,behavior:[1,2,11,13],best:3,big:[1,11],binari:1,block:1,bool:1,box:11,breakdown:9,brief:1,build:[1,6],buildmod:2,built:[2,11],bulk:1,call:[1,2],can:[1,11,13],cannot:13,capabl:[1,6],captur:1,captureend:1,capturefault:1,capturest:1,capturestart:1,care:1,certain:1,challeng:11,chang:[2,11],channel:13,check:1,choos:[2,11],cli:1,client:[1,6,11],clone:2,cmd:2,come:11,command:[1,2,13],compact:2,compil:2,complet:2,concur:13,congradul:2,connect:[2,12,13],consensu:11,contact:6,contain:11,contant:13,content:2,context:[1,13],control:13,copi:[1,10,14],core:[1,6],correspond:1,cost:1,could:[1,11,13],cpu:[2,12],creat:[1,6,11],createsubscript:1,ctx:1,curl:2,custom:[11,13],data:[1,2,13],databas:1,debug:1,debug_tracecal:1,debug_tracetransact:1,decod:1,depend:[2,12],deploi:6,depth:1,design:6,detail:11,develop:[6,11],differ:[1,6,11],direct:11,directori:2,disabl:1,discord:3,discuss:[5,7],disect:0,disk:[2,12],doe:[1,11],don:1,download:2,dozen:2,drawback:11,drift:11,drop:3,due:1,durat:1,dure:1,each:[1,11],earli:6,easili:11,either:1,elabor:11,enabl:11,encod:1,end:1,enough:11,env:1,err:1,error:[1,13],especi:11,ethereum:[2,6,11,12],everyon:2,evm:[1,11],exactli:11,execut:1,exist:11,explain:1,explin:4,extend:[6,11],extract:11,fail:1,fairli:1,familiar:2,featur:11,file:2,fill:[0,11],first:[1,2],flag:[2,13],flagset:1,folder:2,follow:1,forese:12,fork:[2,6,11],framework:1,freebsd:12,friend:2,from:[1,2,3,6,11],func:1,funtion:2,furtur:6,futur:12,gas:1,gasus:1,gener:[1,11,13],get:[2,6],getapi:13,geth:[1,2,6,11,13],getresult:1,give:1,given:11,goal:11,golang:[1,11,12],guid:8,hand:11,has:[2,11],have:[1,2,3,6,11,12],hear:3,hello:[1,2,3],helloworld:1,help:[2,3],here:[1,11],histor:13,home:2,hook:[6,11],how:4,howev:2,http:[2,13],hybrid:13,idea:3,implement:[1,6,11,12],includ:2,info:2,inform:[11,13],initi:[2,13],input:1,insid:2,instal:11,intend:1,interest:11,interfac:1,invok:1,ipc:1,isstabl:6,its:[11,13],itself:1,json:[1,2,13],jsonrpc:[2,13],just:2,kei:1,largest:11,least:[2,12],less:6,like:[1,6,11],limit:13,line:[1,13],link:3,linux:12,list:2,livetrac:13,load:1,loader:[1,6,11,13],local:2,locat:[2,11],log:[1,2],logger:13,look:1,lot:13,maco:12,made:13,mai:[1,3],main:2,mainnet:[2,11,12],maintain:11,make:[6,11],mani:11,manipul:1,map:1,marshal:1,match:1,matter:11,mean:11,merg:11,method:[1,2],might:[1,6],miss:11,modifi:[1,11],modul:1,moment:2,more:[11,13],move:[2,11],must:[1,13],mymamespac:2,mynamespac:1,mynamespace_hello:2,mynamespace_helloworld:1,myservic:1,name:[1,13],namespac:1,namespace_subscrib:13,nativ:1,navig:2,need:[1,2,4,11,13],network:[2,11,12],next:2,nil:1,node:[1,2,13],non:1,note:1,notifi:1,now:6,number:[1,6,11],numer:11,object:1,obscur:11,occur:1,offici:6,onc:2,onli:[11,12],opcod:1,oper:[1,6,13],opportun:1,optim:11,option:1,order:[2,13],other:11,our:3,out:11,output:1,overview:6,own:[2,11,13],p2p:1,packag:[2,6,11],page:13,param:[2,13],pars:1,pass:[1,13],perspect:6,plan:6,plugeth:[1,2,3,12],plugethplugin:2,plugethutil:2,plugin:[1,6,12],pluginload:1,point:[1,2],popular:11,practic:2,premad:11,primari:2,primarili:11,problem:3,process:[1,2,11],produc:2,project:[2,6],properli:11,protocol:11,prove:11,provid:[1,2,11,13],quit:11,ram:[2,12],rather:[1,6,11],rdata:1,reach:3,read:2,readi:2,reason:11,reciev:13,redifin:13,refer:[1,6],regist:1,releas:6,reli:[12,13],repo:10,repositori:[2,7],repres:1,requir:[1,2,6,13],requirr:13,resid:11,respond:[1,2],respons:1,restirct:4,restrict:[1,6],result:[1,2,11],retian:1,reus:1,right:[6,11],rpc:[1,2],rpcsub:1,rule:11,run:[1,2,6,13],sai:3,scope:1,scopecontext:1,secur:11,see:[2,11],sens:11,sent:1,separ:1,seper:2,serializ:1,serv:[1,11],server:3,servic:[1,13],settl:6,should:[1,2,6,12],signatur:1,similar:1,simpl:1,singl:[1,11],singular:13,small:11,some:[1,6,11],someth:1,soon:1,space:2,specif:1,specifi:1,ssd:[2,12],stabl:[6,13],stack:1,stand:13,standard:[2,11],start:[1,2,13],still:6,stop:11,store:11,straight:1,string:1,struct:1,subscrib:1,subscript:1,subscriptionnam:13,support:[1,11,12],sure:1,system:[1,6,13],take:[1,2,13],team:[3,11],tend:11,testnet:11,than:[1,6,11],thankfulli:2,thei:[1,13],thi:[1,2,11,13],those:11,though:[2,11],three:2,through:[2,3],time:[1,2],todai:6,todo:[3,10,13,14],total:13,touch:6,trace:1,tracerresult:1,tracex:1,transact:1,tutori:[2,6],two:[1,2],type:[1,2,6],uint64:1,unexpect:1,unlik:12,unpredict:1,updat:[6,11],upon:13,upstream:[6,11],use:[1,2],used:[1,11],useful:[1,2],user:11,using:[1,6],util:6,valid:1,valu:1,vari:12,variabl:1,varieti:11,veri:1,verif:13,version:1,wai:[1,3,6,11,13],want:3,websocket:[1,13],well:[2,11],what:4,whatev:6,when:[1,11],wherea:13,which:[2,11,12,13],whichev:2,why:4,wide:[1,11],window:12,wish:1,within:1,without:[1,11],work:[3,13],world:[1,2],would:11,wrapper:11,write:8,written:11,yet:6,you:[1,2,3,6,12],your:[1,2,3,13],your_command:1},titles:["Plugin Anatomy","API","Build and Deploy","Get in touch with us","Core vs Restricted packages in Plugeth-utils","Plugin Hooks","PluGeth","PluGeth","Plugin Hooks","Plugin Loader","PluGeth Plugins","Project Design","System Requirements","Basic Types of Plugins","PluGeth Utils"],titleterms:{anatomi:0,api:1,basic:13,build:2,content:6,core:4,depend:11,deploi:2,design:11,environ:2,flag:1,get:3,getapi:1,hook:[5,8],initi:1,initializenod:1,livetrac:1,loader:9,method:13,packag:4,plugeth:[4,6,7,10,11,14],plugin:[0,2,5,8,9,10,11,13],project:11,repositori:11,requir:12,restrict:4,rpc:13,scheme:11,set:2,subcommand:[1,13],subscript:13,system:12,tabl:6,three:11,todo:[0,1,4,5,8,9,11],touch:3,tracer:[1,13],type:13,util:[4,11,14]}}) \ No newline at end of file diff --git a/documentation/_build/html/system_req.html b/documentation/_build/html/system_req.html index a7eb9e8..6d1f377 100644 --- a/documentation/_build/html/system_req.html +++ b/documentation/_build/html/system_req.html @@ -14,7 +14,9 @@ - + + + @@ -37,15 +39,19 @@
    • Project Design
    • Basic Types of Plugins
    • Plugin Hooks
    • -
    • Anatomy of a Plugin
    • +
    • Plugin Anatomy

    Tutorials

    Reference

    -

    Tutorials

    Reference

    Contact

    Tutorials

    Reference

    Contact

      diff --git a/documentation/anatomy.rst b/documentation/anatomy.rst index cc393f6..4a94f1d 100644 --- a/documentation/anatomy.rst +++ b/documentation/anatomy.rst @@ -1,122 +1,7 @@ .. _anatomy: -=================== -Anatomy of a Plugin -=================== +============== +Plugin Anatomy +============== -Plugins for Plugeth use Golang's `Native Plugin System`_. Plugin modules must export variables using specific names and types. These will be processed by the plugin loader, and invoked at certain points during Geth's operations. - -API -*** - -Flags ------ - -* **Name:** Flags -* **Type:** `flag.FlagSet`_ -* **Behavior:** This FlagSet will be parsed and your plugin will be able to access the resulting flags. Flags will be passed to Geth from the command line and are intended to of the plugin. Note that if any flags are provided, certain checks are disabled within Geth to avoid failing due to unexpected flags. - -Subcommands ------------ - -* **Name:** Subcommands -* **Type:** map[string]func(ctx `*cli.Context`_, args []string) error -* **Behavior:** If Geth is invoked with ``./geth YOUR_COMMAND``, the plugin loader will look for ``YOUR_COMMAND`` within this map, and invoke the corresponding function. This can be useful for certain behaviors like manipulating Geth's database without having to build a separate binary. - -Initialize ----------- - -* **Name:** Initialize -* **Type:** func(*cli.Context, core.PluginLoader, core.logs ) -* **Behavior:** Called as soon as the plugin is loaded, with the cli context and a reference to the plugin loader. This is your plugin's opportunity to initialize required variables as needed. Note that using the context object you can check arguments, and optionally can manipulate arguments if needed for your plugin. -:ref:`Core vs Restricted packages in Plugeth-utils` - -**todo: explain that plugin could provide node.Node with restricted.backend** - -InitializeNode --------------- - -* **Name:** InitializeNode -* **Type:** func(core.Node, core.Backend) -* **Behavior:** This is called as soon as the Geth node is initialized. The core.Node object represents the running node with p2p and RPC capabilities, while the Backend gives you access to a wide array of data you may need to access. - -Tracers -------- - -* **Name:** Tracers -* **Type:** map[string]TracerResult -* **Behavior:** When calling debug.traceX functions (such as ``debug_traceCall`` and ``debug_traceTransaction``) the tracer can be specified as a key to this map and the tracer used will be the TracerResult specified here. TracerResult objects must match the interface: - -.. code-block:: go - - ``// CaptureStart is called at the start of each transaction - CaptureStart(env core.EVM, from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {} - // CaptureState is called for each opcode - CaptureState(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {} - // CaptureFault is called when an error occurs in the EVM - CaptureFault(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {} - // CaptureEnd is called at the end of each transaction - CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {} - // GetResult should return a JSON serializable result object to respond to the trace call - GetResult() (interface{}, error) {}`` - - -.. warning:: Modifying the values passed into tracer functions can alter the - results of the EVM execution in unpredictable ways. Additonally, some objects may be reused acress calls, so data you wish to capture should be copied rather than retianed by reference. - -LiveTracer ----------- - -* **Name:** LiveTracers -* **Type:** core.Tracer -* **Behavior:** This tracer is used for tracing transactions as they are processed within blocks. Note that if a block does not validate, some transactions may be processed that don't end up in blocks, so be sure to check transactions against finalized blocks. - -The interface for a vm.Tracer is similar to a TracerResult (above), but does not require a ``GetResult()`` function. - -GetAPIs -------- - -* **Name:** GetAPIs -* **Type:** func(core.Node, core.Backend) []rpc.API -* **Behavior:** This allows you to register new RPC methods to run within Geth. - -The GetAPIs function itself will generally be fairly brief, and will looks something like this: - -.. code-block:: go - - ``func GetAPIs(stack *node.Node, backend core.Backend) []core.API { - return []rpc.API{ - { - Namespace: "mynamespace", - Version: "1.0", - Service: &MyService{backend}, - Public: true, - }, - } - }`` - -The bulk of the implementation will be in the ``MyService`` struct. MyService should be a struct with public functions. These functions can have two different types of signatures: - -* RPC Calls: For straight RPC calls, a function should have a ``context.Context`` object as the first argument, followed by an arbitrary number of JSON marshallable arguments, and return either a single JSON marshal object, or a JSON marshallable object and an error. The RPC framework will take care of decoding inputs to this function and encoding outputs, and if the error is non-nil it will serve an error response. - -* Subscriptions: For subscriptions (supported on IPC and websockets), a function should have a ``context.Context`` object as the first argument followed by an arbitrary number of JSON marshallable arguments, and should return an ``*rpc.Subscription`` object. The subscription object can be created with ``rpcSub := notifier.CreateSubscription()``, and JSON marshallable data can be sent to the subscriber with ``notifier.Notify(rpcSub.ID, b)``. - -A very simple MyService might look like: - -.. code-block:: go - - ``type MyService struct{} - - func (h MyService) HelloWorld(ctx context.Context) string { - return "Hello World" - }`` - -And the client could access this with an rpc call to -``mynamespace_helloworld`` - - - - -.. _*cli.Context: https://pkg.go.dev/github.com/urfave/cli#Context -.. _flag.FlagSet: https://pkg.go.dev/flag#FlagSet -.. _Native Plugin System: https://pkg.go.dev/plugin \ No newline at end of file +.. todo:: fill in disections of archetypal plugins \ No newline at end of file diff --git a/documentation/api.rst b/documentation/api.rst new file mode 100644 index 0000000..ef3ee53 --- /dev/null +++ b/documentation/api.rst @@ -0,0 +1,120 @@ +.. _api: + +=== +API +=== + +Plugins for Plugeth use Golang's `Native Plugin System`_. Plugin modules must export variables using specific names and types. These will be processed by the plugin loader, and invoked at certain points during Geth's operations. + +Flags +----- + +* **Name:** Flags +* **Type:** `flag.FlagSet`_ +* **Behavior:** This FlagSet will be parsed and your plugin will be able to access the resulting flags. Flags will be passed to Geth from the command line and are intended to of the plugin. Note that if any flags are provided, certain checks are disabled within Geth to avoid failing due to unexpected flags. + +Subcommands +----------- + +* **Name:** Subcommands +* **Type:** map[string]func(ctx `*cli.Context`_, args []string) error +* **Behavior:** If Geth is invoked with ``./geth YOUR_COMMAND``, the plugin loader will look for ``YOUR_COMMAND`` within this map, and invoke the corresponding function. This can be useful for certain behaviors like manipulating Geth's database without having to build a separate binary. + +Initialize +---------- + +* **Name:** Initialize +* **Type:** func(*cli.Context, core.PluginLoader, core.logs ) +* **Behavior:** Called as soon as the plugin is loaded, with the cli context and a reference to the plugin loader. This is your plugin's opportunity to initialize required variables as needed. Note that using the context object you can check arguments, and optionally can manipulate arguments if needed for your plugin. + +.. todo:: explain that plugin could provide node.Node with + restricted.backend + +InitializeNode +-------------- + +* **Name:** InitializeNode +* **Type:** func(core.Node, core.Backend) +* **Behavior:** This is called as soon as the Geth node is initialized. The core.Node object represents the running node with p2p and RPC capabilities, while the Backend gives you access to a wide array of data you may need to access. + +Tracers +------- + +* **Name:** Tracers +* **Type:** map[string]TracerResult +* **Behavior:** When calling debug.traceX functions (such as ``debug_traceCall`` and ``debug_traceTransaction``) the tracer can be specified as a key to this map and the tracer used will be the TracerResult specified here. TracerResult objects must match the interface: + +.. code-block:: go + + ``// CaptureStart is called at the start of each transaction + CaptureStart(env core.EVM, from core.Address, to core.Address, create bool, input []byte, gas uint64, value *big.Int) {} + // CaptureState is called for each opcode + CaptureState(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {} + // CaptureFault is called when an error occurs in the EVM + CaptureFault(env core.EVM, pc uint64, op core.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {} + // CaptureEnd is called at the end of each transaction + CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {} + // GetResult should return a JSON serializable result object to respond to the trace call + GetResult() (interface{}, error) {}`` + + +.. warning:: Modifying the values passed into tracer functions can + alter the + results of the EVM execution in unpredictable ways. Additonally, some objects may be reused acress calls, so data you wish to capture should be copied rather than retianed by reference. + +LiveTracer +---------- + +* **Name:** LiveTracers +* **Type:** core.Tracer +* **Behavior:** This tracer is used for tracing transactions as they are processed within blocks. Note that if a block does not validate, some transactions may be processed that don't end up in blocks, so be sure to check transactions against finalized blocks. + +The interface for a vm.Tracer is similar to a TracerResult (above), but does not require a ``GetResult()`` function. + +GetAPIs +------- + +* **Name:** GetAPIs +* **Type:** func(core.Node, core.Backend) []rpc.API +* **Behavior:** This allows you to register new RPC methods to run within Geth. + +The GetAPIs function itself will generally be fairly brief, and will looks something like this: + +.. code-block:: go + + ``func GetAPIs(stack *node.Node, backend core.Backend) []core.API { + return []rpc.API{ + { + Namespace: "mynamespace", + Version: "1.0", + Service: &MyService{backend}, + Public: true, + }, + } + }`` + +The bulk of the implementation will be in the ``MyService`` struct. MyService should be a struct with public functions. These functions can have two different types of signatures: + +* RPC Calls: For straight RPC calls, a function should have a ``context.Context`` object as the first argument, followed by an arbitrary number of JSON marshallable arguments, and return either a single JSON marshal object, or a JSON marshallable object and an error. The RPC framework will take care of decoding inputs to this function and encoding outputs, and if the error is non-nil it will serve an error response. + +* Subscriptions: For subscriptions (supported on IPC and websockets), a function should have a ``context.Context`` object as the first argument followed by an arbitrary number of JSON marshallable arguments, and should return an ``*rpc.Subscription`` object. The subscription object can be created with ``rpcSub := notifier.CreateSubscription()``, and JSON marshallable data can be sent to the subscriber with ``notifier.Notify(rpcSub.ID, b)``. + +A very simple MyService might look like: + +.. code-block:: go + + ``type MyService struct{} + + func (h MyService) HelloWorld(ctx context.Context) string { + return "Hello World" + }`` + +And the client could access this with an rpc call to +``mynamespace_helloworld`` + + + + +.. _*cli.Context: https://pkg.go.dev/github.com/urfave/cli#Context +.. _flag.FlagSet: https://pkg.go.dev/flag#FlagSet +.. _Native Plugin System: https://pkg.go.dev/plugin \ No newline at end of file diff --git a/documentation/build.rst b/documentation/build.rst index e81b8b7..28d302b 100644 --- a/documentation/build.rst +++ b/documentation/build.rst @@ -1,7 +1,8 @@ .. _build: -Build -===== +================ +Build and Deploy +================ .. contents:: :local: diff --git a/documentation/conf.py b/documentation/conf.py index 70bc998..c0b8d80 100644 --- a/documentation/conf.py +++ b/documentation/conf.py @@ -19,7 +19,7 @@ project = 'Plugeth' copyright = '2021, Philip Morlier' -author = 'Philip Morlier' +author = 'Philip Morlier, Austin Roberts' # The full version, including alpha/beta/rc tags release = 'Austin Roberts' @@ -31,8 +31,14 @@ release = 'Austin Roberts' # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + 'sphinx.ext.intersphinx', + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.todo', ] +todo_include_todos=True + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/documentation/core_restricted.rst b/documentation/core_restricted.rst index 433318f..c224faf 100644 --- a/documentation/core_restricted.rst +++ b/documentation/core_restricted.rst @@ -4,4 +4,5 @@ Core vs Restricted packages in Plugeth-utils ============================================ -**todo: copy on core and restricted packages in utils. what, why, how.** + +.. todo:: need explinations of core vs restircted functionality. what, why, how. \ No newline at end of file diff --git a/documentation/hooks.rst b/documentation/hooks.rst index 397c22c..b7940ee 100644 --- a/documentation/hooks.rst +++ b/documentation/hooks.rst @@ -4,5 +4,4 @@ Plugin Hooks ============ - -**todo: discussion on plugin hooks** \ No newline at end of file +.. todo:: discussion of plugin hooks diff --git a/documentation/index.rst b/documentation/index.rst index f3ff255..ab2fd8a 100644 --- a/documentation/index.rst +++ b/documentation/index.rst @@ -8,11 +8,12 @@ PluGeth PluGeth is a fork of the `Go Ethereum Client Geth`_ that implements a plugin architecture, allowing developers to extend Geth's capabilities in a number of different ways using plugins, rather than having to create additional, new forks of Geth. -**WARNING: UNSTABLE API** +.. warning:: Right now PluGeth is in early development. We are + still settling on some of the plugin APIs, and are + not yet making official releases. From an operational + perspective, PluGeth should be as stable as upstream Geth less whatever isstability is added by plugins you might run. But if you plan to run PluGeth today, be aware that furture updates will likely break you plugins. -Right now PluGeth is in early development. We are still settling on some of the plugin APIs, and are not yet making official releases. From an operational perspective, PluGeth should be as stable as upstream Geth less whatever instability is added by plugins you might run. But if you plan to run PluGeth today, be aware that future updates will likely break your plugins. - Table of Contents ***************** @@ -26,6 +27,7 @@ Table of Contents types hooks anatomy + .. toctree:: :maxdepth: 1 @@ -37,8 +39,11 @@ Table of Contents :maxdepth: 1 :caption: Reference - sytem_req + system_req + plugin_loader + plugin_hooks core_restricted + api .. toctree:: :maxdepth: 1 diff --git a/documentation/plugin_hooks.rst b/documentation/plugin_hooks.rst new file mode 100644 index 0000000..601ee4a --- /dev/null +++ b/documentation/plugin_hooks.rst @@ -0,0 +1,7 @@ +.. _plugin_hooks: + +============ +Plugin Hooks +============ + +.. todo:: guide to writing plugin hooks \ No newline at end of file diff --git a/documentation/plugin_loader.rst b/documentation/plugin_loader.rst new file mode 100644 index 0000000..d1de719 --- /dev/null +++ b/documentation/plugin_loader.rst @@ -0,0 +1,7 @@ +.. _plugin_loader: + +============= +Plugin Loader +============= + +.. todo:: breakdown of plugin loader function \ No newline at end of file diff --git a/documentation/project.rst b/documentation/project.rst index 76d3919..315f726 100644 --- a/documentation/project.rst +++ b/documentation/project.rst @@ -37,14 +37,14 @@ Plugins are packages which contain premade plugins as well as a location provide Dependency Scheme ----------------- -**todo: copy on version number protocol** +.. todo:: needs elaboration of dependency scheme -.. _obscures security updates as optimixations: https://blog.openrelay.xyz/vulnerability-lifecycle-framework-geth/ +.. _obscures security updates as optimizations: https://blog.openrelay.xyz/vulnerability-lifecycle-framework-geth/ .. _PluGeth: https://github.com/openrelayxyz/plugeth .. _PluGeth-Utils: https://github.com/openrelayxyz/plugeth-utils .. _PluGeth-Plugins: https://github.com/openrelayxyz/plugeth-plugin \ No newline at end of file