From 2aeae07d0b4b439a1c56fffd269792db9218f949 Mon Sep 17 00:00:00 2001 From: Sami Ahmed Date: Mon, 29 Jun 2026 13:45:59 -0700 Subject: [PATCH] feat: I2P integration (process-based) + updated icons + Qt UI for I2P address display --- doc/i2p.md | 68 ++++ snap/gui/triangles.png | Bin 8360 -> 17744 bytes src/CMakeLists.txt | 2 + src/i2p.cpp | 466 ++++++++++++++++++++++ src/i2p.h | 95 +++++ src/i2p_process.cpp | 368 +++++++++++++++++ src/i2p_process.h | 70 ++++ src/init.cpp | 47 +++ src/main.cpp | 12 + src/net.cpp | 92 ++++- src/net.h | 2 + src/netbase.cpp | 48 ++- src/netbase.h | 8 +- src/qt/forms/mainwindow.ui | 70 +++- src/qt/res/icons/menu_16/triangles-16.png | Bin 477 -> 844 bytes src/qt/res/icons/triangles-128.png | Bin 3718 -> 7743 bytes src/qt/res/icons/triangles-16.png | Bin 477 -> 844 bytes src/qt/res/icons/triangles-32.png | Bin 795 -> 1499 bytes src/qt/res/icons/triangles.ico | Bin 118032 -> 119678 bytes src/qt/res/icons/triangles.png | Bin 20232 -> 17744 bytes src/qt/trianglesgui.cpp | 53 +++ src/qt/trianglesgui.h | 2 + src/rpcnet.cpp | 25 ++ src/rpcwallet.cpp | 10 + 24 files changed, 1407 insertions(+), 31 deletions(-) create mode 100644 doc/i2p.md create mode 100644 src/i2p.cpp create mode 100644 src/i2p.h create mode 100644 src/i2p_process.cpp create mode 100644 src/i2p_process.h diff --git a/doc/i2p.md b/doc/i2p.md new file mode 100644 index 0000000..755b803 --- /dev/null +++ b/doc/i2p.md @@ -0,0 +1,68 @@ +# I2P support (SAM v3) + +Triangles runs over I2P in addition to Tor, giving the wallet a second +anonymous network and a `.b32.i2p` address shown directly above the `.onion` +address in the status bar. + +I2P is **on by default** and works the same way as the embedded Tor: the wallet +auto-launches a bundled **i2pd** router as a managed child process, enables its +SAM bridge, and connects to it. The user does not have to install or configure +anything — provided the i2pd binary ships with the wallet. + +## Shipping the i2pd binary + +Like `tor.exe`, the wallet looks for an `i2pd` executable in several places and +launches the first one it finds: + +1. Next to the wallet executable (recommended): `i2pd.exe` (Windows) / `i2pd` + (Linux/macOS), or in an `i2pd/` subfolder beside it. +2. In the data directory (or its `i2pd/` subfolder). +3. Common system locations (`/usr/bin/i2pd`, Homebrew, `C:\i2pd\…`, etc.). + +Get i2pd from https://i2pd.website/ (or your package manager) and place the +binary next to the wallet in your build/packaging step. That's the only manual +part, and it's a packaging concern, not something the end user does. + +If no i2pd binary is found, the wallet logs a notice and continues with **Tor +only** — I2P is strictly additive and never blocks start-up. + +## What happens at start-up + +1. If a SAM bridge is already listening on `127.0.0.1:7656` (e.g. you run your + own router), the wallet uses it and does **not** launch its own. +2. Otherwise it writes `i2pd.conf` into `/i2pd/` (SAM enabled, other + services off), launches i2pd, and waits for the SAM bridge to come up. +3. The SAM client then loads/creates a persistent destination + (`/i2p_private_key`), opens a STREAM session, derives the + `.b32.i2p` address (`base32(SHA-256(destination))`), accepts inbound I2P + streams, and dials outbound `.b32.i2p` peers. +4. On wallet exit, the SAM session is closed and the i2pd child process is + terminated (an external router you started yourself is left running). + +The first session takes a little longer while i2pd builds tunnels; the address +appears once the bridge is ready. + +## Options + +``` +-i2p Enable I2P; auto-launches bundled i2pd (default: 1; -i2p=0 to disable) +-i2psam= SAM bridge address (default: 127.0.0.1:7656). + A non-loopback address disables the bundled router and + connects to that external bridge instead. +``` + +## Checking it + +* GUI: the `.b32.i2p` address sits on top of the `.onion` in the status bar; + click either to copy. +* RPC: `getinfo` shows `toraddress` and `i2paddress`; `getnetworkinfo` shows + `toraddress` and an `i2p` object (`enabled`, `active`, `address`, `peers`). + +## Notes / limitations + +* The address serialization format carries a flag for I2P addresses, so **all + nodes must run this build** to exchange I2P peers; an old `peers.dat` is + discarded. +* `i2p_private_key` is your stable I2P identity — back it up, don't delete it. +* This was implemented without a build/CI environment here; build and test + against a real i2pd before relying on it. diff --git a/snap/gui/triangles.png b/snap/gui/triangles.png index 781f95ad31dbdc1812d8ec3003e4e33f701e1a9b..f1a86f7a5523970e06570156c74afdb928420ac3 100644 GIT binary patch literal 17744 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

bdMj;x^lCvim11}ijWV`v>eb?PyLpYRD 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 literal 8360 zcmZvCc{tQx`1WUpVa$vrG!(LLAzSt^+4rSLC|g9?vW09zmaK`guPKBqVJun37KNy& zu`h|pR%9^D{66}=*Y#fS?|T1W7Uw$We9rSc_jBL(5pQOqOOH5<004kqUr*}_06@UE z5CBdCzTEIFzYV_7-P5!713&4U{6JWrYF-Avr1jS~)~21MV`Wj{D7a+u765nveXYwD zL6aN#Q|ULxpDlMbnyg(}Qfd~rDmA7{@)Y?lbDmGDTyy4n!wdO}p|qKWpHI$4MMZi^pW_~b90NiWaK2Z#XO1x`y>nq}mkjXX!?Rtk#edgx$oiiD97yeQvOC>E z^#XN@a*{MNVx`Sb@)(kBVvB z_>KK`cFB*oBo}nYXDZ3-G7iFThAMnGwRLP$p_oJO%^HMk2OzAx*mUmu7$-H|iKtex}0bMv(mAy79;~ zMOfErgrwfmux_t2y19AzTlO_3aLM1g%J~?R+p8{f-E&74bX)3EyW}5D4AtjgZG-5f z`^s_34`W1t7YeU5edri4)~Bwwz9m&}bahg;y^l(Otgg}fnOgJv+kUINZ2ugc$6p1T+U9WM+1rLh+$NQ)Jnj&&)Z(`y6hu*;Q zgg>}5-E+^+P-9D9$(m9^-9lO4j!4-5{S7YNn@P-UGlV2JJR5;N$d-tMVsHgY01SAh zn1a?a^7vayp(3Jd4w?&tR6USuuK~_&9?#1NVB%1BpN;Otlb5q@opGfGL37#50bB=D zamTp%__>5ip}wC1w47xUdJrDlF_P{nU&R4EYq@PclV>&R!^GD$)H)CVT`$hf^6<}b z8IbzAYe?$hn+pvYZJ)wTr>!)0|HN<{CU=sn=Fk?vxMIrvoZ^qVU{>ZD-c%0jD1y;h z?6&MQ{@@_zf08vGG7T<;VpVfr9&}N6-_`<09sWTAJ^ppti*Q?scsfVnVtD*`QFA5Z+XfL==(SLHOm^$iaTisO zir#nx#mK)T>bm~)cKekZJVnY^pR>9_oTK01V^xG-VaF;t`hm4a@2VUrPUF!TN6cXA z9Gy;`J5KSo;dM&ntG*(xqlD^jG0y_$iB+;x1Z1G}?XJYOx;Dp7^>D8_HdrW(^~z!K3{SoTRSoWthc9j9$u3zT9Wp77UIDo^^i$J#-H;a zLXScGQO%0u+fozrAr~mHc6L6AzJCTi&r}>U_;dZ504v~2wS*V~KIvb>)!6|1M z8u{rYx7}SCq6U;K((BxO^tmqK<`ft+a7UN67&nwzFAHAK0i*`|^&vdpV(GSV@L8Ry z_R~MLy(z5bn!LKaDx`FtViy*zj&$1(ET^%I2^+Mnp6o zU|)U8?9c#4$KS_{)0%(y8whkIt~p@=#`eUGD;MkfGL}v!t-60)P|W3qIs9B9S3H`> zK6%3@rQETCBXh__>?*h?LDO)_iI^C$z_7f!fKf?R;%hStk%2P`aF*Q|*nI>tb+Q_rzo3g(Tedp}#SNnu+3m^TZMoZcam8D1D0ucCAhGT69 zsUgdYGj{Qy~v%`3M{H8Juw4fk+SU6naa4iicHGrzKEAn(=;(N z_{*x$xe2yf*q4jy(f6vUG$8DHYrq~<@hn>j1x+~n_SAS7F2Uh5Gt6vrOg{evu-MVm z3BFLJI-P*RrI=;R%^d|QoWm{s8-i!PH06J{z(S?={TCNiaQ1HN90@gBt{U$RFL0!m zcs_YlGay|IpwLsmrP0RY&?nONs%B9gIrK}7q_iv#s`X6k+s~>cuHOP%Bx-ZoJ~cO> zlC&T4R>kh-Il?arenRMOIvLhgSW~s6n-=W@WyN;A5P}L{uWub;EDdBl3WE#E#w&N3 z9oGCD)8JvnMn2E|Zd&mEXgn;%_^Da=E2V9s%!IN{KKR(T- zqF~!Zd;iFIrajDUv)|bvutbE%1)nWtlM0nm%z{QVg3l_sDOMcRs$@Z2df(GA8Re9` zvsj@o&AeiEYYjkPI%O*nZ#4o6RSgF<1MR(#0tyol2bK9eJz*c97}yo-FFt9=XTH2k zQy>1Oz>pEUN4~UC2a|;C8D&_@r68qxICD?IioCt6*%5pqMV>ME)~~wZ^_LomuHPnv z*3!Fn9W%>V9@WNQ0S=#l?MK$)yQ0m2%-i*B5~aK~2Q{`4a7v?nm|&tI3>a$+s%nG5Gx?wfxPM6i@>7bWTjm?+S$w#(MG ziZ!^Bg#JkK>=b6q3@U+!uFa0?n_U3zLojkF{ElFa6_t6H0xEqxSY*JpruObx_1>S^ zLd#`GxcT?u!(}XRD{4_dRi6uwGr^mV!L>-oOZ5%M)mqIoQ2@Wo@B+Iq2J&;*Hn=%= z*$_G&HX9L(jIersZ!d5^p&xw_kG3%kKJDUC1+LTdfZ~-S2?9OMwF=_2`FwJ#f!ew2 z0?8m~!!*lEp(FQ#yCKa0 zTvp%%zRQ*AbCW$c!QEv4_6xVY_m=A^`O zM!G3U47tnSCfMma$d?tLXpV9yXo`o{S}xrl;N9Q4lk<40%kujt&F>}b>ix5n2Q3FN zLgyxbHNn{4T%=e)TZV*;AOyr3a1F3nblR=q3o;IGyn7TuY1f`D=WxE88DVoeUPI@@ z`FrIjcAJ90{EFGDbR)3m|8%m?aoKXMxT5c#&jAl1KfZy5B7T=~ zESH?+?fM&%o1vacqd_;D8kE6)h`+r@=2M((JRSlOJf39m$gTs=(U=k{>3}R?@)>uM zW@cYIi8hC^F{>1<@#H9md}#JqySk7u-}as3V+j##dsct2;Dz`S5K#zvYg>eHALjf4 znUza^lr7UQds8Btj8Bay>Kj6wlZSyo$;ni4vOQ0l1xBiF{Mp=BkvH$AwRhU;G#8M( z_xwvMPq0E4<50zQ(#h!oXU-we!5=cVAQ;`w5!;F^_UklZ;STCmt`7Bk{+dnh| zyx_uL-)}u@podItm2^68bxu6Bw|Q3=kIBP-=nGX&>2pI~0lcDZTz%tL zchu68UMcrn%2kHVSFDg{*3_;rF!HLm^u~1B@me^w%lf)cxj=juqIh8Q=gT!~zbILx zoluVakv$UHv$KG|mfiiojx~k~m=!|cpY@aRxqO5a+|;QoQbZQce#HDiUHk+cCCcHJ zi=cX%z%(lcay?hc|Id--cf|)ngX?J^>DV=&3~x7ZGru;>GlR2pO)mqYRU-O6QTxi& z&ULC;cURZn*#BjzW1{eTK#j6o)OT^X4Dx&aQ0Y7pvR? z&A&zJYl#8{7c?TzGkd-;R2s6MaqZt(KPE+b(|C0KQ)KA&4bHpsX#lKf(8nAPu`xL% zT1nbfX`)5nY056f;--Y4@94}yY26t3IaIK(+{Z3&hY)VcRl4!b`-o6~oh0utay#2{ zQ8DVwmpF4^n{?s$LY^nmFh+Q-=AcUv=vyw~!2)>9{=VjSCkDy{Y&>bmhl=PxlvM2&~h#7=#^-g_F~ z$Cr>Y2?jI_;UiyWkpz`WwhIw`%4o5yrrfeLWl#@AE zBQ`q*y^+eN*gqheixbhD6_vxq1Iz<{)@vKb+_SbCf1sY7mtFdIj6ssy!~=JK0it*O zWGX#0cG=gxBDH!W4!gltp`uF@=U^14T$Bf`=HLLCj5va?oaa-_*Wj8BVk4E{&&o4% zsl4-|BYZVkg!drRz!s|seA3Y51>{aGee4pHVhgG+e&FZ4O$hs^Ioc_>)Y6vXtB3-q z6fgvpk_83Ap>~G#64-Mca_)4*CS#J~Uct}%a4I>7cwFX+MdpDu+8p%h?Hpxai|$8e z^R|LVQo)_YF02G$;B%-@B!LN)N_&WKE#B7x^IPX*;m?QQG?`{qaT+}QE~gcT7=rTf z82kM5_f*K&&gKWtRLoMIgbA`*&$zmY<{fjLBWfd|ID*XwF_B+Ik}!rUVCatUFx!XJ zQOnukH8sr6L~2yBCZ2LA zr!SXK%=#>ZzkdqwL|X2(=Z}Z!W!i#lm`Yx>)8Gpy(@*SV6qPXG_mld_sNbg{%Y_Cs z0Q##oHD@16(kx~E8QDyOSNKSO_*C~4?Cf&~-}Tb;_y^la$L^p&z>bFvgfxTQO0Dyo zH}ZnNXO|m5J46+ry<^r!hmm?-{A23gb3K{$^@$%%3H;`u0QOTHq9@qkF?86g^M2R@ zBiq^kOE`K>cmKdH`4mdVmrpo>x-;R;GAnj=>9VCFt)5b-WjeU2YJ7gA#XUY6{YfU- zG1>t%=OeLKn)7+ZIjkitD}CAhdm(AymMs4q-+3$nCun4}WGkjfVLnAs@d73Qi$h)g z_R0_WYeZhF_p~SY4C2+iI&PL6nhaI&tz9ENF$*Zf zXtD7s7>LB=oiB2EPC};%6|VT(gcI3*=-)M0zKH$0<}VoNDuN$YF+9!TlBbfQ-tAMnDGq?&MUK z5h>kvC)11!yb|hIs)L=b1>4qRz$r|sV{`Rts8s+reg5hg$Blh{+aBQ>2V~B#W4EpX z)wgF^TVyRjrRr;+Q{!FR$~fWF(TI~^-|%PndyWCUHscU1?SJK{L84*gkRMDlToz-E zBl7IzW}3f5<+%Ww5MS!;%{8@TOh6&_wB|tRPDAJCr}^tT$mQGRK8SmsppHK{_>j=q zI-&(C1K)+myEJdXHpNJY8o6z)mM);mAwKN~-LBS3w1K0Ji6EQcZ`U3`Pt))~cV(2H zRf+&sIfsdkXH)yexHpI|!vvGSJ+4aM&%3)gNTSMp`1v9QRa8yeKcyOA5MY@__ae!x z)_(K>uXE)=?=MGNvk%x76D=_qzDJzeTP5y93XCK^tZ8NRRR8=vlvJx8@Akc|`RJrztk`Z6Jv&_y6PyY4vojgTz3SsdZ&7p}x*sP#7}&P6Nqi(hVBrU|GMEfPu>|Na zVaGM}Miwfy8leR36L$=8JL@~^JR>{n7rLbu@xRN&8q;UBzr@+ddJ)^?6MyWW5|Izu zL0{;4{|>B&430c!(4L*xuDLLuvDuOct|+-TZ4NgIfJME5RtrCeH65XhB1gc^;x8Ka zdh?ij%Dy{gWrCDWb|S5!&+SY^(frq;_B0yiGYT|r&c^Q$MX3!Z>U0bAL*sVz}3Tf$OmG@dEft$a+(HA#5VjcceF&7i|5_#tp* zuSkX?^okeN5@x`tALjiAJ)w(gt!q0W+O?|2T%$htSOZ{fhP(Qm&u-Eq)$jVh!{$%& z?_p$(M4?Q5Vf=Nul#+a4IZhw&6-g0DWwBl}{&O%2+O;Y@G3qkxZCgexjG+AM6CY;u zDwb$o?XlW3NUK7nek=?sh0le_k9CU89dd}IJ8Izqa8t-sIJ)TQ6i$cxf?(-K-9Y(fo9Dh6}xsjeM;JhRe-@BNyg zSKYu*xCPbK+>q0zftMDsyUzexKpKW^V86YOMMgO9 zk6Ouwj(^$f8#2LV{NWdIAKQX5#V;_N())}XZ46zv+#@?Hw(yVcS)y_pp5$tJKJ@IO zS9!o?RlT{R35HJdBe6^s$K!ysUas(ArbGF0C^8ewf|b$)d>0qBy~8OJ@yrHbU}Eza zI~tO1v5+4?)oojzn)VCU(Ko;pw1DN-@iy3K)Xvual%K+v&{J=|zOC(rURRP83z%u0I`TaJo{>UQRihrti{ zOK0H{@cZKaRAy6Hx2^zHC$6acj|*-xXbJIGeqbW!f_r+DS;KvT))EZ@H4a9Z`8{<3 zoAuxRx|v{caFi$8uln6~3uyzo16i-#^RU$`ktss)N0f7|)>y+);7;ibFqiKxlCv2jS&&9aV=n<-AKMC>Xbb?FepnoaGM{9B9wHK8g8DRt5_&% z5PWtJ#=^xe5DDRPYD2SyslU41vvaTC(x3L1DfL#4`>sHUn;W&yJwuI;|CpjK+0@Z} zGKkkXI}s9vOMZm$9!0l#L9(c7sW5^mC0^5iDr66SjmS(sPUTq8)otHOmG~z$K65m{ zYHR^c*0^taJ96rl-6G%_`f4WSdp=)o8r_%xuYvT^rp?}Ae;rOKS&DFiem=BwD{#cK zyG(aLSxRoT3Dy))I{yH|B^G{F7dZVipssNVq}g-!|CGWK+?w`3y%9Nl`A*IVl<$d0 z3NWOv@Lt$v6znH-li|@-V(F2A2B$}51V&!l2KrIKiiDsKi*3YpkbED5L5`6LX2=9n z0ZI!gpD{KpaO)GpiWKdH;y;q%O~V`pdP02?V15k5-m}G{ryXNA+}`5g)pBO@6|f?j zBDjOl1)WaB(Fa#tS*Ss@2ajopN0%Y?xXK-A*P&y(T>;~XTEsxDQH1cqxxr#}UXJ1F zdgC$SW6PMc)*0OGCqp_^$`X#arX=s}zrws^(HJ;nPC~PSoHO&@Uwy5bHQT6^jiynX z55wst`<1i?V2!Gs(U6bi8d3P2HG;lK(3t!{VKxhV)`Jxb_e4WoV@2-R^44zcGl0Q& zzS`n0VY__|&nd;Ntsn&W@tHxu>p2PM>>mX!6von)xx&=f^RId$1)g`FR!C>%ALLrI zs)c=H1wj8oF{9JA<>$>4|3c$HaFZzPEJkS8d9mS?@k0pvJ|G1|@33%$n+KUIBH|FV z?4mscBOlqy0$;2gk!v;-nfiZDWXXo^z%|(irSS)%of1JZhC3qyOgBk#_QuAI>C2TU zI#0>jo;9`TUFwicacZ(Qs4a#UqI{s0YWXpXZ~V%IZcScib}hJQKL-M~#)H_6POk;A zNVl$-uUG7}t!Ktl04>y%7SN!25T+6u4F+>nR1IW-Foq~JHD;zhe(SN?D=HEHN|HED z1?i~VVCr$I-I7X&-i=eXtUk}2qVV&E+SPQ;NzX@I-{mu6KSin+ez^O}z4K4%} zVPwwHmCqO1M%F2xjs@2*^?~JMx4aBOwcCeIp8Xxr{}GQQyrm%{0LBUpE{7i`*^=Dp zMmySi_EMI6H3!}-+GCBd70};07dKB&Ymx5M5M;**D#{b-pf|_V9tts?UP)xBotui< z5{KQrjLq%i!3>=5^*s5zz0Zm}IS>cXY9ndpn?)|JO@=39H;5;uMf5Iz2X%YPqZ8|_ znm2JqD)%^tDa2sx=&<{s&{(%Nzgz diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9b5fd86..060c31e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,8 @@ set(CORE_SOURCES net.cpp net_bootstrap.cpp netbase.cpp + i2p.cpp + i2p_process.cpp protocol.cpp script.cpp sync.cpp diff --git a/src/i2p.cpp b/src/i2p.cpp new file mode 100644 index 0000000..fb365e6 --- /dev/null +++ b/src/i2p.cpp @@ -0,0 +1,466 @@ +// Copyright (c) 2024 Triangles developers +// I2P (SAM v3) transport support +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "i2p.h" + +#include "util.h" +#include "netbase.h" +#include "protocol.h" // CAddress +#include "net.h" // AddI2PInboundNode(), GetListenPort() + +#include + +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#ifndef closesocket +#define closesocket close +#endif +#endif + +// I2P uses a base64 variant where '+' -> '-' and '/' -> '~'. +static const char* pI2PBase64 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-~"; + +static std::vector DecodeI2PBase64(const std::string& str) +{ + int table[256]; + for (int i = 0; i < 256; i++) table[i] = -1; + for (int i = 0; i < 64; i++) table[(unsigned char)pI2PBase64[i]] = i; + + std::vector out; + int bits = 0; uint32_t buf = 0; + for (char c : str) { + if (c == '=' || c == '\r' || c == '\n') continue; + int v = table[(unsigned char)c]; + if (v < 0) continue; // skip anything unexpected + buf = (buf << 6) | v; + bits += 6; + if (bits >= 8) { + bits -= 8; + out.push_back((unsigned char)((buf >> bits) & 0xFF)); + } + } + return out; +} + +CI2PSession* CI2PSession::GetInstance() +{ + static CI2PSession instance; + return &instance; +} + +CI2PSession::CI2PSession() + : samHost(I2P_DEFAULT_SAM_HOST), samPort(I2P_DEFAULT_SAM_PORT), + hSession(INVALID_SOCKET), fEnabled(false), fActive(false), fShutdown(false) +{ +} + +CI2PSession::~CI2PSession() +{ + Stop(); +} + +std::string CI2PSession::GetB32Address() +{ + std::lock_guard lock(cs); + return b32Address; +} + +// --- low level SAM helpers ------------------------------------------------- + +bool CI2PSession::SamConnect(SOCKET& hSocketRet) +{ + SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (hSocket == INVALID_SOCKET) + return false; + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((unsigned short)samPort); + addr.sin_addr.s_addr = inet_addr(samHost.c_str()); + + if (connect(hSocket, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { + closesocket(hSocket); + return false; + } + + hSocketRet = hSocket; + return true; +} + +bool CI2PSession::SamSendLine(SOCKET hSocket, const std::string& strLine) +{ + std::string out = strLine + "\n"; + const char* p = out.c_str(); + size_t left = out.size(); + while (left > 0) { + int n = send(hSocket, p, (int)left, MSG_NOSIGNAL); + if (n <= 0) + return false; + p += n; + left -= n; + } + return true; +} + +bool CI2PSession::SamRecvLine(SOCKET hSocket, std::string& strLineRet) +{ + strLineRet.clear(); + char c; + // SAM replies are newline terminated; read one byte at a time so we stop + // exactly at the boundary and leave any following stream data untouched. + for (int i = 0; i < 16384; i++) { + int n = recv(hSocket, &c, 1, 0); + if (n <= 0) + return false; + if (c == '\n') + return true; + if (c != '\r') + strLineRet += c; + } + return false; +} + +std::string CI2PSession::SamGetValue(const std::string& strReply, const std::string& strKey) +{ + // Tokens are space separated KEY=VALUE pairs. VALUE runs to the next space. + std::string needle = strKey + "="; + size_t pos = strReply.find(needle); + if (pos == std::string::npos) + return ""; + pos += needle.size(); + size_t end = strReply.find(' ', pos); + if (end == std::string::npos) + end = strReply.size(); + return strReply.substr(pos, end - pos); +} + +bool CI2PSession::SamHandshake(SOCKET hSocket) +{ + if (!SamSendLine(hSocket, "HELLO VERSION MIN=3.1 MAX=3.3")) + return false; + std::string reply; + if (!SamRecvLine(hSocket, reply)) + return false; + if (SamGetValue(reply, "RESULT") != "OK") { + printf("I2P: SAM handshake failed: %s\n", reply.c_str()); + return false; + } + return true; +} + +std::string CI2PSession::DestToB32(const std::string& strB64Dest) +{ + std::vector dest = DecodeI2PBase64(strB64Dest); + if (dest.empty()) + return ""; + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256(dest.data(), dest.size(), hash); + std::string b32 = EncodeBase32(hash, SHA256_DIGEST_LENGTH); + // I2P b32 addresses are unpadded. + while (!b32.empty() && b32[b32.size() - 1] == '=') + b32.erase(b32.size() - 1); + return b32 + ".b32.i2p"; +} + +// --- session bring-up ------------------------------------------------------ + +bool CI2PSession::LoadOrCreateDestination(std::string& strPrivKeyRet) +{ + fs::path keyPath = GetDataDir() / "i2p_private_key"; + + // Reuse an existing persistent destination if we have one. + { + std::ifstream f(keyPath.string().c_str()); + if (f.is_open()) { + std::string line; + std::getline(f, line); + while (!line.empty() && + (line[line.size() - 1] == '\r' || line[line.size() - 1] == '\n')) + line.erase(line.size() - 1); + if (!line.empty()) { + strPrivKeyRet = line; + printf("I2P: loaded persistent destination from %s\n", + keyPath.string().c_str()); + return true; + } + } + } + + // Generate a fresh destination via the bridge (Ed25519, SIGNATURE_TYPE=7). + SOCKET hSocket = INVALID_SOCKET; + if (!SamConnect(hSocket) || !SamHandshake(hSocket)) { + if (hSocket != INVALID_SOCKET) closesocket(hSocket); + return false; + } + + bool ok = false; + if (SamSendLine(hSocket, "DEST GENERATE SIGNATURE_TYPE=7")) { + std::string reply; + if (SamRecvLine(hSocket, reply)) { + std::string priv = SamGetValue(reply, "PRIV"); + if (!priv.empty()) { + strPrivKeyRet = priv; + std::ofstream out(keyPath.string().c_str(), std::ios::trunc); + if (out.is_open()) { + out << priv << std::endl; + out.close(); + printf("I2P: generated and saved new persistent destination\n"); + ok = true; + } else { + printf("I2P: WARNING could not write %s\n", keyPath.string().c_str()); + ok = true; // still usable for this run + } + } + } + } + closesocket(hSocket); + return ok; +} + +bool CI2PSession::CreateSession() +{ + if (!SamConnect(hSession)) + return false; + if (!SamHandshake(hSession)) + return false; + + std::ostringstream id; + id << "triangles-" << (uint64_t)GetTime() << "-" << (uint64_t)(GetRand(1000000)); + sessionId = id.str(); + + std::string cmd = "SESSION CREATE STYLE=STREAM ID=" + sessionId + + " DESTINATION=" + privateKey + " SIGNATURE_TYPE=7"; + if (!SamSendLine(hSession, cmd)) + return false; + + std::string reply; + if (!SamRecvLine(hSession, reply)) + return false; + + if (SamGetValue(reply, "RESULT") != "OK") { + printf("I2P: SESSION CREATE failed: %s\n", reply.c_str()); + return false; + } + + // The bridge echoes the (possibly newly assigned) private key back. + std::string echoed = SamGetValue(reply, "DESTINATION"); + if (!echoed.empty()) + privateKey = echoed; + + return true; +} + +bool CI2PSession::ResolveMyB32() +{ + SOCKET hSocket = INVALID_SOCKET; + if (!SamConnect(hSocket) || !SamHandshake(hSocket)) { + if (hSocket != INVALID_SOCKET) closesocket(hSocket); + return false; + } + + bool ok = false; + if (SamSendLine(hSocket, "NAMING LOOKUP NAME=ME")) { + std::string reply; + if (SamRecvLine(hSocket, reply) && SamGetValue(reply, "RESULT") == "OK") { + std::string dest = SamGetValue(reply, "VALUE"); + std::string b32 = DestToB32(dest); + if (!b32.empty()) { + std::lock_guard lock(cs); + b32Address = b32; + ok = true; + } + } + } + closesocket(hSocket); + return ok; +} + +bool CI2PSession::Start() +{ + if (!GetBoolArg("-i2p", true)) { + printf("I2P: disabled (-i2p=0)\n"); + return false; + } + fEnabled.store(true); + + // -i2psam=host:port overrides the default SAM bridge endpoint. + std::string sam = GetArg("-i2psam", ""); + if (!sam.empty()) { + int port = I2P_DEFAULT_SAM_PORT; + std::string host; + SplitHostPort(sam, port, host); + if (!host.empty()) samHost = host; + if (port > 0) samPort = port; + } + + printf("I2P: connecting to SAM bridge at %s:%d\n", samHost.c_str(), samPort); + + if (!LoadOrCreateDestination(privateKey)) { + printf("I2P: ERROR could not obtain a destination. Is an I2P router with " + "the SAM bridge enabled running at %s:%d?\n", samHost.c_str(), samPort); + return false; + } + + if (!CreateSession()) { + printf("I2P: ERROR failed to create SAM STREAM session\n"); + if (hSession != INVALID_SOCKET) { closesocket(hSession); hSession = INVALID_SOCKET; } + return false; + } + + if (!ResolveMyB32()) + printf("I2P: WARNING could not resolve our own .b32.i2p address yet\n"); + + fActive.store(true); + fShutdown.store(false); + + printf("I2P: session active. Our address: %s\n", GetB32Address().c_str()); + + // Register our I2P address as a local address so peers can learn it. + CService meI2P; + if (!b32Address.empty() && meI2P.SetSpecial(b32Address)) { + meI2P.SetPort((unsigned short)GetListenPort()); + AddLocal(meI2P, LOCAL_MANUAL); + } + + acceptThread = std::thread(&CI2PSession::AcceptLoop, this); + return true; +} + +void CI2PSession::Stop() +{ + if (!fEnabled.load()) + return; + fShutdown.store(true); + fActive.store(false); + + if (hSession != INVALID_SOCKET) { + closesocket(hSession); + hSession = INVALID_SOCKET; + } + if (acceptThread.joinable()) + acceptThread.join(); + fEnabled.store(false); + printf("I2P: session stopped\n"); +} + +// --- inbound --------------------------------------------------------------- + +void CI2PSession::AcceptLoop() +{ + while (!fShutdown.load()) { + SOCKET hSocket = INVALID_SOCKET; + if (!SamConnect(hSocket) || !SamHandshake(hSocket)) { + if (hSocket != INVALID_SOCKET) closesocket(hSocket); + if (fShutdown.load()) break; + MilliSleep(2000); + continue; + } + + // Block here until a peer dials us; the router then streams the remote + // destination on its own line, after which the socket carries data. + if (!SamSendLine(hSocket, "STREAM ACCEPT ID=" + sessionId + " SILENT=false")) { + closesocket(hSocket); + MilliSleep(1000); + continue; + } + + std::string status; + if (!SamRecvLine(hSocket, status) || SamGetValue(status, "RESULT") != "OK") { + if (!fShutdown.load()) + printf("I2P: STREAM ACCEPT rejected: %s\n", status.c_str()); + closesocket(hSocket); + MilliSleep(1000); + continue; + } + + std::string remoteDest; + if (!SamRecvLine(hSocket, remoteDest)) { + closesocket(hSocket); + continue; + } + if (fShutdown.load()) { + closesocket(hSocket); + break; + } + + // The first token is the remote full destination (base64). + std::string destTok = remoteDest; + size_t sp = destTok.find(' '); + if (sp != std::string::npos) + destTok = destTok.substr(0, sp); + + std::string b32 = DestToB32(destTok); + CAddress addr; + if (b32.empty() || !addr.SetSpecial(b32)) { + printf("I2P: could not parse inbound remote destination\n"); + closesocket(hSocket); + continue; + } + addr.nServices = 0; + addr.nTime = GetTime(); + + // Hand the live data socket to the net layer as an inbound peer. + printf("I2P: inbound connection from %s\n", b32.c_str()); + AddI2PInboundNode(hSocket, addr); + } +} + +// --- outbound -------------------------------------------------------------- + +bool CI2PSession::Connect(const std::string& strDest, SOCKET& hSocketRet) +{ + if (!fActive.load()) + return false; + + SOCKET hSocket = INVALID_SOCKET; + if (!SamConnect(hSocket) || !SamHandshake(hSocket)) { + if (hSocket != INVALID_SOCKET) closesocket(hSocket); + return false; + } + + if (!SamSendLine(hSocket, "STREAM CONNECT ID=" + sessionId + + " DESTINATION=" + strDest + " SILENT=false")) { + closesocket(hSocket); + return false; + } + + std::string status; + if (!SamRecvLine(hSocket, status) || SamGetValue(status, "RESULT") != "OK") { + printf("I2P: STREAM CONNECT to %s failed: %s\n", strDest.c_str(), status.c_str()); + closesocket(hSocket); + return false; + } + + // Socket is now a bidirectional stream to the peer. + hSocketRet = hSocket; + return true; +} + +bool StartI2P() +{ + return CI2PSession::GetInstance()->Start(); +} + +void StopI2P() +{ + CI2PSession::GetInstance()->Stop(); +} diff --git a/src/i2p.h b/src/i2p.h new file mode 100644 index 0000000..ae35516 --- /dev/null +++ b/src/i2p.h @@ -0,0 +1,95 @@ +// Copyright (c) 2024 Triangles developers +// I2P (SAM v3) transport support +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +// This module gives Triangles real I2P connectivity that mirrors the existing +// embedded-Tor design: instead of a SOCKS proxy it talks the SAM v3 protocol +// to a locally running I2P router (i2pd or Java I2P) and obtains a persistent +// I2P destination whose ".b32.i2p" address is shown alongside the .onion +// address. The wallet: +// * creates / loads a persistent destination (i2p_private_key in datadir), +// * runs a STREAM session so peers can dial us, +// * accepts inbound I2P streams and feeds them to the net layer, +// * dials outbound ".b32.i2p" peers through the same session. +// +// A running I2P router with its SAM bridge enabled (default 127.0.0.1:7656) is +// required; nothing is bundled. Enable with -i2p and optionally -i2psam=host:port. + +#ifndef TRIANGLES_I2P_H +#define TRIANGLES_I2P_H + +#include +#include +#include +#include + +#include "compat.h" // SOCKET / INVALID_SOCKET + +// Default SAM bridge endpoint exposed by i2pd / Java I2P. +#define I2P_DEFAULT_SAM_HOST "127.0.0.1" +#define I2P_DEFAULT_SAM_PORT 7656 + +// Manages a single persistent I2P STREAM session over SAM v3. +class CI2PSession +{ +public: + static CI2PSession* GetInstance(); + + // Bring the session up: connect to the SAM bridge, load/generate the + // persistent destination and start accepting inbound streams. + // Returns false (and logs) if no router/SAM bridge is reachable. + bool Start(); + + // Tear the session down and stop the accept loop. + void Stop(); + + bool IsEnabled() const { return fEnabled.load(); } + bool IsActive() const { return fActive.load(); } + + // Our own ".b32.i2p" address (empty until the session is up). + std::string GetB32Address(); + + // Dial a remote ".b32.i2p" (or full base64 destination) through the + // session. On success hSocketRet is a connected, blocking data socket the + // caller can hand to a CNode. The caller takes ownership of the socket. + bool Connect(const std::string& strDest, SOCKET& hSocketRet); + +private: + CI2PSession(); + ~CI2PSession(); + + // --- low level SAM helpers --- + bool SamConnect(SOCKET& hSocketRet); // raw TCP to the bridge + bool SamHandshake(SOCKET hSocket); // HELLO VERSION + bool SamSendLine(SOCKET hSocket, const std::string& strLine); + bool SamRecvLine(SOCKET hSocket, std::string& strLineRet); + static std::string SamGetValue(const std::string& strReply, const std::string& strKey); + + bool LoadOrCreateDestination(std::string& strPrivKeyRet); + bool CreateSession(); // SESSION CREATE + bool ResolveMyB32(); // NAMING LOOKUP ME + void AcceptLoop(); // inbound STREAM ACCEPT + + // Compute the ".b32.i2p" address from a base64 (I2P alphabet) destination. + static std::string DestToB32(const std::string& strB64Dest); + + std::string samHost; + int samPort; + std::string sessionId; + std::string privateKey; // persistent destination private key (base64) + std::string b32Address; // our own .b32.i2p + SOCKET hSession; // long-lived control socket owning the session + + std::atomic fEnabled; + std::atomic fActive; + std::atomic fShutdown; + std::thread acceptThread; + std::mutex cs; +}; + +// Convenience: start/stop from init.cpp. +bool StartI2P(); +void StopI2P(); + +#endif // TRIANGLES_I2P_H diff --git a/src/i2p_process.cpp b/src/i2p_process.cpp new file mode 100644 index 0000000..bc037ab --- /dev/null +++ b/src/i2p_process.cpp @@ -0,0 +1,368 @@ +// Copyright (c) 2024 Triangles developers +// I2P Router Process Manager - launches and manages a bundled i2pd binary +// Distributed under the MIT/X11 software license + +#ifdef WIN32 +#define NOMINMAX +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif +#endif + +#include "i2p_process.h" +#include "util.h" + +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace fs = std::filesystem; + +static CI2PProcess* i2pProcessInstance = nullptr; + +CI2PProcess* CI2PProcess::GetInstance() +{ + if (!i2pProcessInstance) + i2pProcessInstance = new CI2PProcess(); + return i2pProcessInstance; +} + +CI2PProcess::CI2PProcess() + : samPort(7656) + , running(false) + , fExternal(false) +#ifdef WIN32 + , hProcess(nullptr) + , hJob(nullptr) + , processId(0) +#else + , processId(0) +#endif +{ +} + +CI2PProcess::~CI2PProcess() +{ + Stop(); +} + +// Try a quick TCP connect; success means something is already listening +// (e.g. the SAM bridge is up, or an external router is running). +bool CI2PProcess::CanConnect(const std::string& host, int port) +{ +#ifdef WIN32 + SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s == INVALID_SOCKET) return false; +#else + int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) return false; +#endif + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((unsigned short)port); + addr.sin_addr.s_addr = inet_addr(host.c_str()); + bool ok = (connect(s, (struct sockaddr*)&addr, sizeof(addr)) == 0); +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif + return ok; +} + +std::string CI2PProcess::FindI2pdBinary() +{ + std::vector candidates; + +#ifdef WIN32 + const char* exeName = "i2pd.exe"; +#else + const char* exeName = "i2pd"; +#endif + + // 1. Next to the wallet executable (this is how tor.exe is shipped). + try { + fs::path exeDir; +#ifdef WIN32 + char buf[MAX_PATH]; + if (GetModuleFileNameA(nullptr, buf, MAX_PATH) > 0) + exeDir = fs::path(buf).parent_path(); +#else + exeDir = fs::current_path(); +#endif + if (!exeDir.empty()) { + candidates.push_back((exeDir / exeName).string()); + candidates.push_back((exeDir / "i2pd" / exeName).string()); + candidates.push_back((exeDir / "I2P" / exeName).string()); + } + } catch (...) {} + + // 2. In / next to the data directory. + candidates.push_back((GetDataDir() / exeName).string()); + candidates.push_back((GetDataDir() / "i2pd" / exeName).string()); + + // 3. Common system locations. +#ifdef WIN32 + if (const char* pf = getenv("ProgramFiles")) + candidates.push_back(std::string(pf) + "\\i2pd\\" + exeName); + if (const char* pfx = getenv("ProgramFiles(x86)")) + candidates.push_back(std::string(pfx) + "\\i2pd\\" + exeName); + candidates.push_back(std::string("C:\\i2pd\\") + exeName); +#else + candidates.push_back("/usr/bin/i2pd"); + candidates.push_back("/usr/local/bin/i2pd"); + candidates.push_back("/opt/i2pd/bin/i2pd"); + candidates.push_back("/opt/homebrew/bin/i2pd"); + candidates.push_back("/usr/local/opt/i2pd/bin/i2pd"); +#endif + + for (const std::string& c : candidates) { + try { + if (fs::exists(c) && fs::is_regular_file(c)) { + printf("I2P: found i2pd binary at %s\n", c.c_str()); + return c; + } + } catch (...) {} + } + + return ""; +} + +bool CI2PProcess::WriteConfig() +{ + fs::path dir(dataDir); + try { + fs::create_directories(dir); + } catch (const std::exception& e) { + lastError = std::string("Cannot create i2pd data directory: ") + e.what(); + return false; + } + + confPath = (dir / "i2pd.conf").string(); + fs::path logPath = dir / "i2pd.log"; + + std::ofstream conf(confPath.c_str(), std::ios::trunc); + if (!conf.is_open()) { + lastError = "Cannot write i2pd.conf to " + confPath; + return false; + } + + conf << "# Triangles Wallet I2P configuration (auto-generated)\n"; + conf << "# Do not edit - this file is overwritten on startup\n\n"; + conf << "daemon = false\n"; + conf << "log = file\n"; + conf << "logfile = " << logPath.string() << "\n"; + conf << "datadir = " << dir.string() << "\n\n"; + + // The bridge our SAM client talks to. + conf << "[sam]\n"; + conf << "enabled = true\n"; + conf << "address = 127.0.0.1\n"; + conf << "port = " << samPort << "\n\n"; + + // We only need SAM; keep everything else off to minimise footprint. + conf << "[httpproxy]\nenabled = false\n\n"; + conf << "[socksproxy]\nenabled = false\n\n"; + conf << "[http]\nenabled = false\n\n"; + conf << "[i2pcontrol]\nenabled = false\n"; + + conf.close(); + printf("I2P: wrote i2pd config to %s (SAM port %d)\n", confPath.c_str(), samPort); + return true; +} + +bool CI2PProcess::Start(const std::string& dataDirIn, int samPortIn) +{ + dataDir = dataDirIn; + samPort = samPortIn; + fExternal = false; + lastError.clear(); + + // If a SAM bridge is already up, use it instead of launching our own. + if (CanConnect("127.0.0.1", samPort)) { + printf("I2P: detected an I2P router already listening on SAM port %d; using it\n", samPort); + fExternal = true; + return true; + } + + binaryPath = FindI2pdBinary(); + if (binaryPath.empty()) { + lastError = "No i2pd binary found (ship i2pd alongside the wallet, like tor)"; + printf("I2P: %s\n", lastError.c_str()); + return false; + } + + if (!WriteConfig()) + return false; + + printf("I2P: starting i2pd: %s --conf %s\n", binaryPath.c_str(), confPath.c_str()); + +#ifdef WIN32 + STARTUPINFOA si; + PROCESS_INFORMATION pi; + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + ZeroMemory(&pi, sizeof(pi)); + + std::string cmdLine = "\"" + binaryPath + "\" --conf \"" + confPath + "\""; + + if (!CreateProcessA(nullptr, (LPSTR)cmdLine.c_str(), nullptr, nullptr, + FALSE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi)) { + DWORD err = ::GetLastError(); + lastError = strprintf("CreateProcess failed for i2pd '%s' (Windows error %lu)", binaryPath.c_str(), err); + printf("I2P: ERROR %s\n", lastError.c_str()); + return false; + } + + hProcess = pi.hProcess; + processId = pi.dwProcessId; + CloseHandle(pi.hThread); + + // Kill i2pd if the wallet dies (matches the embedded Tor behaviour). + hJob = CreateJobObject(nullptr, nullptr); + if (hJob) { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {}; + jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo)); + if (!AssignProcessToJobObject(hJob, hProcess)) + printf("I2P: WARNING could not assign i2pd to Job Object (error %lu)\n", GetLastError()); + } + + printf("I2P: i2pd started (PID %lu)\n", processId); +#else + pid_t pid = fork(); + if (pid < 0) { + lastError = "Failed to fork for i2pd process"; + printf("I2P: ERROR %s\n", lastError.c_str()); + return false; + } + if (pid == 0) { + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); + execl(binaryPath.c_str(), binaryPath.c_str(), + "--conf", confPath.c_str(), (char*)nullptr); + _exit(1); + } + processId = pid; + printf("I2P: i2pd started (PID %d)\n", processId); +#endif + + running = true; + + // Wait for the SAM bridge to come up. The bridge opens quickly; tunnel + // build (needed for actual connectivity) continues in the background. + printf("I2P: waiting for SAM bridge on port %d...\n", samPort); + for (int i = 0; i < 45; i++) { + MilliSleep(1000); + if (fShutdown) { + Stop(); + return false; + } + if (CanConnect("127.0.0.1", samPort)) { + printf("I2P: SAM bridge ready on port %d (took %ds)\n", samPort, i + 1); + return true; + } + if (!IsRunning()) { + lastError = "i2pd exited during start-up before the SAM bridge became ready"; + printf("I2P: ERROR %s\n", lastError.c_str()); + running = false; + return false; + } + } + + lastError = strprintf("i2pd started but SAM port %d not ready after 45s", samPort); + printf("I2P: WARNING %s (it may still be building tunnels)\n", lastError.c_str()); + return true; +} + +void CI2PProcess::Stop() +{ + if (fExternal) { + // We never launched it; leave the user's router running. + running = false; + return; + } + if (!running) return; + +#ifdef WIN32 + if (hProcess != nullptr) { + printf("I2P: stopping i2pd (PID %lu)...\n", processId); + TerminateProcess(hProcess, 0); + WaitForSingleObject(hProcess, 5000); + CloseHandle(hProcess); + hProcess = nullptr; + } + if (hJob != nullptr) { + CloseHandle(hJob); + hJob = nullptr; + } +#else + if (processId > 0) { + printf("I2P: stopping i2pd (PID %d)...\n", processId); + kill(processId, SIGTERM); + for (int i = 0; i < 50; i++) { + int status; + pid_t result = waitpid(processId, &status, WNOHANG); + if (result != 0) break; + MilliSleep(100); + } + kill(processId, SIGKILL); + waitpid(processId, nullptr, 0); + } +#endif + + processId = 0; + running = false; + printf("I2P: i2pd stopped\n"); +} + +bool CI2PProcess::IsRunning() +{ + if (fExternal) return true; + if (!running) return false; + +#ifdef WIN32 + if (hProcess == nullptr) return false; + DWORD exitCode; + if (GetExitCodeProcess(hProcess, &exitCode)) + return (exitCode == STILL_ACTIVE); + return false; +#else + if (processId <= 0) return false; + int status; + pid_t result = waitpid(processId, &status, WNOHANG); + return (result == 0); // 0 => still running +#endif +} + +bool StartEmbeddedI2P(const std::string& dataDir, int samPort) +{ + return CI2PProcess::GetInstance()->Start(dataDir, samPort); +} + +void StopEmbeddedI2P() +{ + CI2PProcess::GetInstance()->Stop(); +} diff --git a/src/i2p_process.h b/src/i2p_process.h new file mode 100644 index 0000000..05e4a5f --- /dev/null +++ b/src/i2p_process.h @@ -0,0 +1,70 @@ +// Copyright (c) 2024 Triangles developers +// I2P Router Process Manager - launches and manages a bundled i2pd binary +// Distributed under the MIT/X11 software license +// +// Mirrors tor_process.cpp: locate an i2pd executable shipped alongside the +// wallet (or installed on the system), write an auto-generated config that +// enables the SAM bridge, launch it as a managed child process, and shut it +// down when the wallet exits. The SAM session in i2p.cpp then connects to it, +// so the user does not have to install or run a separate I2P router. + +#ifndef TRIANGLES_I2P_PROCESS_H +#define TRIANGLES_I2P_PROCESS_H + +#include + +#ifdef WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif + +class CI2PProcess +{ +public: + static CI2PProcess* GetInstance(); + + CI2PProcess(); + ~CI2PProcess(); + + // Bring up the router. If something is already listening on the SAM port we + // assume an external router and do not launch our own (fExternal=true). + // Returns true if a SAM bridge is (or will shortly be) reachable. + bool Start(const std::string& dataDir, int samPort = 7656); + + // Terminate the launched router (no-op for an external one). + void Stop(); + + bool IsRunning(); + bool IsExternal() const { return fExternal; } + std::string GetLastError() const { return lastError; } + std::string GetBinaryPath() const { return binaryPath; } + +private: + std::string FindI2pdBinary(); + bool WriteConfig(); + static bool CanConnect(const std::string& host, int port); + + int samPort; + bool running; + bool fExternal; + std::string dataDir; + std::string binaryPath; + std::string confPath; + std::string lastError; + +#ifdef WIN32 + HANDLE hProcess; + HANDLE hJob; + DWORD processId; +#else + int processId; +#endif +}; + +// Convenience wrappers for init.cpp. +bool StartEmbeddedI2P(const std::string& dataDir, int samPort); +void StopEmbeddedI2P(); + +#endif // TRIANGLES_I2P_PROCESS_H diff --git a/src/init.cpp b/src/init.cpp index 2efc495..51a1290 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -19,6 +19,8 @@ #include "tor/tor_embedded.h" #include "tor/onion_v3.h" #include "tor/tor_process.h" +#include "i2p.h" +#include "i2p_process.h" #ifdef ENABLE_ZMQ #include "zmqpublishnotifier.h" #endif @@ -241,6 +243,10 @@ void Shutdown(void* parg) pScriptCheckQueue.reset(); } + // Stop the I2P SAM session and its accept loop, then the i2pd router. + StopI2P(); + StopEmbeddedI2P(); + // NOW safe to destroy Tor state - all threads have stopped ShutdownTorV3(); StopEmbeddedTor(); @@ -421,6 +427,8 @@ std::string HelpMessage() " -torsocks= " + _("Set embedded or managed Tor SOCKS proxy port (default: 19099)") + "\n" + " -torhiddenservice " + _("Enable the managed Tor hidden service (default: 1)") + "\n" + " -torhsport= " + _("Set embedded or managed Tor hidden service port (default: wallet listen port)") + "\n" + + " -i2p " + _("Enable I2P connectivity; auto-launches a bundled i2pd router (default: 1)") + "\n" + + " -i2psam= " + _("I2P SAM bridge address; non-loopback disables the bundled router (default: 127.0.0.1:7656)") + "\n" + //" -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + " -port= " + _("Listen for connections on (default: 24112 or testnet: 24111)") + "\n" + " -maxconnections= " + _("Maintain at most connections to peers (default: 125)") + "\n" + @@ -1437,6 +1445,45 @@ bool AppInit2() if (!NewThread(ThreadTorMaintenance, nullptr)) printf("Warning: ThreadTorMaintenance could not be started\n"); } + + // Bring up I2P (SAM) transport alongside Tor so the wallet has both a + // .onion and a .b32.i2p address. On by default; disable with -i2p=0. + // A bundled i2pd router is launched automatically (mirroring embedded + // Tor); if -i2psam points at a non-loopback bridge, or a router is + // already running, we use that instead. + if (GetBoolArg("-i2p", true)) { + int64_t nI2PStart = GetTimeMillis(); + + // Resolve the SAM endpoint (default 127.0.0.1:7656). + std::string sam = GetArg("-i2psam", "127.0.0.1:7656"); + int samPort = I2P_DEFAULT_SAM_PORT; + std::string samHost = "127.0.0.1"; + SplitHostPort(sam, samPort, samHost); + if (samPort <= 0) samPort = I2P_DEFAULT_SAM_PORT; + bool loopback = samHost.empty() || samHost == "127.0.0.1" || samHost == "localhost"; + + // Auto-launch our own i2pd only when the bridge is local. + if (loopback) { + uiInterface.InitMessage(_("Starting the I2P router...")); + if (!StartEmbeddedI2P((GetDataDir() / "i2pd").string(), samPort)) { + printf("NOTICE: bundled I2P router unavailable (%s).\n", + CI2PProcess::GetInstance()->GetLastError().c_str()); + printf(" I2P will use an external router if one is running on %s.\n", sam.c_str()); + } + } + + uiInterface.InitMessage(_("Connecting to the I2P network...")); + bool i2pStarted = StartI2P(); + StartupPerfLog("i2p_start", GetTimeMillis() - nI2PStart, strprintf("started=%d", i2pStarted)); + if (i2pStarted) { + SetReachable(NET_I2P, true); + std::string i2pAddr = CI2PSession::GetInstance()->GetB32Address(); + printf("I2P network enabled. Our address: %s\n", i2pAddr.c_str()); + } else { + printf("NOTICE: I2P not available this session; continuing with Tor only\n"); + StopEmbeddedI2P(); + } + } } // ********************************************************* Step 9: import blocks diff --git a/src/main.cpp b/src/main.cpp index aa30f2f..f109d39 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3831,6 +3831,18 @@ bool FastImportBlockFile() int nApplied = 0; for (CBlockIndex* pindex : vMain) { + // Genesis (height 0) is a hardcoded special block that is not + // re-read from disk this way; it contributes nothing to supply + // and the genesis-walk audit skips it identically. Carry the + // running supply (0) forward and move on. + if (pindex->nHeight == 0) + { + pindex->nMint = 0; + pindex->nMoneySupply = nRunningSupply; // still 0 here + txdb.WriteBlockIndex(CDiskBlockIndex(pindex)); + continue; + } + CBlock blockMain; if (!blockMain.ReadFromDisk(pindex)) return error("FastImportBlockFile: ReadFromDisk failed at height %d", pindex->nHeight); diff --git a/src/net.cpp b/src/net.cpp index c0d9db2..b5f9b7d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -11,6 +11,7 @@ #include "addrman.h" #include "ui_interface.h" #include "onionseed.h" +#include "i2p.h" #include #include @@ -494,14 +495,26 @@ CNode* FindNode(const CService& addr) CNode* ConnectNode(CAddress addrConnect, const char *pszDest) { - // TOR-NATIVE: Reject all non-.onion addresses + // PRIVACY-NATIVE: only anonymous networks are allowed. Accept Tor (.onion) + // and I2P (.i2p / .b32.i2p); reject everything else (clearnet). std::string addrStr = pszDest ? std::string(pszDest) : addrConnect.ToStringIP(); - if (addrStr.find(".onion") == std::string::npos) { + bool fI2P = (addrStr.find(".i2p") != std::string::npos); + if (!fI2P && addrStr.find(".onion") == std::string::npos) { if (fDebug) - printf("ConnectNode(): REJECTED non-onion address: %s (Tor-native mode)\n", addrStr.c_str()); + printf("ConnectNode(): REJECTED non-anonymous address: %s (privacy-native mode)\n", addrStr.c_str()); return nullptr; } + // For I2P make sure addrConnect carries the destination so the resulting + // CNode is labelled correctly even when we were given a bare pszDest. + if (fI2P && !addrConnect.IsI2P()) { + std::string i2pHost = addrStr; + size_t i2pEnd = i2pHost.find(".i2p"); + if (i2pEnd != std::string::npos) + i2pHost = i2pHost.substr(0, i2pEnd + 4); + addrConnect.SetSpecial(i2pHost); + } + if (pszDest == nullptr) { if (IsLocal(addrConnect)) return nullptr; @@ -525,8 +538,20 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); // Connect - SOCKET hSocket; - if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket)) + SOCKET hSocket = INVALID_SOCKET; + bool fConnected; + if (fI2P) { + // Route through the I2P SAM session. Strip any :port suffix; I2P peers + // are reached purely by destination. + std::string i2pDest = addrStr; + size_t i2pEnd = i2pDest.find(".i2p"); + if (i2pEnd != std::string::npos) + i2pDest = i2pDest.substr(0, i2pEnd + 4); + fConnected = CI2PSession::GetInstance()->Connect(i2pDest, hSocket); + } else { + fConnected = pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket); + } + if (fConnected) { addrman.Attempt(addrConnect); @@ -561,6 +586,54 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) } } +// Adopt a connected I2P SAM data socket (from the accept loop in i2p.cpp) as an +// inbound peer. The socket arrives in blocking mode; switch it to non-blocking +// to match the rest of the socket handler, then register the node. +void AddI2PInboundNode(SOCKET hSocket, const CAddress& addr) +{ + if (hSocket == INVALID_SOCKET) + return; + + if (CNode::IsBanned(addr)) { + printf("I2P inbound from %s dropped (banned)\n", addr.ToString().c_str()); + closesocket(hSocket); + return; + } + + // Honour the inbound connection limit. + int nInbound = 0; + { + LOCK(cs_vNodes); + for (CNode* pnode : vNodes) + if (pnode->fInbound) + nInbound++; + } + int nMaxInbound = GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS; + if (nInbound >= nMaxInbound) { + printf("I2P inbound from %s dropped (too many inbound)\n", addr.ToString().c_str()); + closesocket(hSocket); + return; + } + +#ifdef WIN32 + u_long nOne = 1; + if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) + printf("AddI2PInboundNode() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError()); +#else + if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) + printf("AddI2PInboundNode() : fcntl non-blocking setting failed, error %d\n", errno); +#endif + + printf("accepted I2P connection %s\n", addr.ToString().c_str()); + CNode* pnode = new CNode(hSocket, addr, "", true); + pnode->AddRef(); + pnode->nTimeConnected = GetTime(); + { + LOCK(cs_vNodes); + vNodes.push_back(pnode); + } +} + void CNode::CloseSocketDisconnect() { fDisconnect = true; @@ -1726,11 +1799,16 @@ bool ThreadHTTPSeedFetch2(void* parg) // For .onion addresses, the last colon before port is after ".onion" size_t onionPos = addrStr.find(".onion:"); + size_t i2pPos = addrStr.find(".b32.i2p:"); if (onionPos != std::string::npos) { port = atoi(addrStr.substr(onionPos + 7).c_str()); addrStr = addrStr.substr(0, onionPos + 6); // keep ".onion" - } else if (addrStr.find(".onion") == std::string::npos) { - // Tor-native: skip non-.onion addresses + } else if (i2pPos != std::string::npos) { + port = atoi(addrStr.substr(i2pPos + 9).c_str()); + addrStr = addrStr.substr(0, i2pPos + 8); // keep ".b32.i2p" + } else if (addrStr.find(".onion") == std::string::npos && + addrStr.find(".i2p") == std::string::npos) { + // Privacy-native: skip clearnet addresses continue; } diff --git a/src/net.h b/src/net.h index 5f40e29..6a6685c 100644 --- a/src/net.h +++ b/src/net.h @@ -35,6 +35,8 @@ void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const CService& ip); CNode* ConnectNode(CAddress addrConnect, const char *strDest = nullptr); +// Adopt a connected I2P SAM data socket as an inbound peer (called from i2p.cpp). +void AddI2PInboundNode(SOCKET hSocket, const CAddress& addr); void MapPort(); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); diff --git a/src/netbase.cpp b/src/netbase.cpp index 216fd4e..6a84901 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -600,6 +600,7 @@ void CNetAddr::Init() memset(ip, 0, sizeof(ip)); memset(tor_v3_pubkey, 0, sizeof(tor_v3_pubkey)); m_is_tor_v3 = false; + m_is_i2p = false; } void CNetAddr::SetIP(const CNetAddr& ipIn) @@ -607,6 +608,7 @@ void CNetAddr::SetIP(const CNetAddr& ipIn) memcpy(ip, ipIn.ip, sizeof(ip)); memcpy(tor_v3_pubkey, ipIn.tor_v3_pubkey, sizeof(tor_v3_pubkey)); m_is_tor_v3 = ipIn.m_is_tor_v3; + m_is_i2p = ipIn.m_is_i2p; } static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; @@ -650,6 +652,22 @@ bool CNetAddr::SetSpecial(const std::string &strName) ip[i + sizeof(pchGarliCat)] = vchAddr[i]; return true; } + // Modern I2P base32 address: 52 base32 chars = SHA-256(destination) (32 bytes) + // rendered as ".b32.i2p". Store the hash and flag this as an I2P address. + if (strName.size()>8 && strName.substr(strName.size() - 8, 8) == ".b32.i2p") { + std::string addrPart = strName.substr(0, strName.size() - 8); + std::vector vchAddr = DecodeBase32(addrPart.c_str()); + if (vchAddr.size() != 32) + return false; + // Keep the GarliCat prefix in ip[] so legacy reachability checks that + // look for unique-local space still treat this as a routable overlay. + memcpy(ip, pchGarliCat, sizeof(pchGarliCat)); + memset(ip + sizeof(pchGarliCat), 0, 16 - sizeof(pchGarliCat)); + memcpy(tor_v3_pubkey, vchAddr.data(), 32); + m_is_i2p = true; + m_is_tor_v3 = false; + return true; + } return false; } @@ -772,7 +790,7 @@ bool CNetAddr::IsTorV3() const bool CNetAddr::IsI2P() const { - return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0); + return m_is_i2p || (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0); } bool CNetAddr::IsLocal() const @@ -878,6 +896,13 @@ std::string CNetAddr::ToStringIP() const } if (IsTor()) return EncodeBase32(&ip[6], 10) + ".onion"; + if (m_is_i2p) { + // Modern I2P: base32 of the 32-byte destination hash, unpadded. + std::string b32 = EncodeBase32(tor_v3_pubkey, 32); + while (!b32.empty() && b32[b32.size() - 1] == '=') + b32.erase(b32.size() - 1); + return b32 + ".b32.i2p"; + } if (IsI2P()) return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p"; CService serv(*this, 0); @@ -911,12 +936,14 @@ bool operator==(const CNetAddr& a, const CNetAddr& b) { if (a.m_is_tor_v3 || b.m_is_tor_v3) return a.m_is_tor_v3 == b.m_is_tor_v3 && memcmp(a.tor_v3_pubkey, b.tor_v3_pubkey, 32) == 0; + if (a.m_is_i2p || b.m_is_i2p) + return a.m_is_i2p == b.m_is_i2p && memcmp(a.tor_v3_pubkey, b.tor_v3_pubkey, 32) == 0; return (memcmp(a.ip, b.ip, 16) == 0); } bool operator!=(const CNetAddr& a, const CNetAddr& b) { - return (memcmp(a.ip, b.ip, 16) != 0); + return !(a == b); } bool operator<(const CNetAddr& a, const CNetAddr& b) @@ -925,6 +952,10 @@ bool operator<(const CNetAddr& a, const CNetAddr& b) return !a.m_is_tor_v3; // non-v3 sorts before v3 if (a.m_is_tor_v3) return memcmp(a.tor_v3_pubkey, b.tor_v3_pubkey, 32) < 0; + if (a.m_is_i2p != b.m_is_i2p) + return !a.m_is_i2p; // non-i2p sorts before i2p + if (a.m_is_i2p) + return memcmp(a.tor_v3_pubkey, b.tor_v3_pubkey, 32) < 0; return (memcmp(a.ip, b.ip, 16) < 0); } @@ -948,6 +979,17 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const // no two connections will be attempted to addresses with the same group std::vector CNetAddr::GetGroup() const { + // Modern I2P addresses keep their identifying bytes in the 32-byte + // destination-hash field (ip[] only holds the overlay prefix), so derive + // the group from the hash to keep peers in distinct groups. + if (m_is_i2p) { + std::vector vch; + vch.push_back(NET_I2P); + vch.push_back(tor_v3_pubkey[0]); + vch.push_back(tor_v3_pubkey[1]); + return vch; + } + std::vector vchRet; int nClass = NET_IPV6; int nStartByte = 0; @@ -1022,7 +1064,7 @@ std::vector CNetAddr::GetGroup() const uint64_t CNetAddr::GetHash() const { uint256 hash; - if (m_is_tor_v3) + if (m_is_tor_v3 || m_is_i2p) hash = Hash(&tor_v3_pubkey[0], &tor_v3_pubkey[32]); else hash = Hash(&ip[0], &ip[16]); diff --git a/src/netbase.h b/src/netbase.h index 57eeadd..b6859b1 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -36,8 +36,12 @@ class CNetAddr { protected: unsigned char ip[16]; // in network byte order - unsigned char tor_v3_pubkey[32]; // Ed25519 public key for Tor v3 onion addresses + // For Tor v3 this holds the 32-byte Ed25519 public key. When m_is_i2p is + // set it instead holds the 32-byte SHA-256 of the I2P destination (the + // value rendered as the ".b32.i2p" address). A CNetAddr is never both. + unsigned char tor_v3_pubkey[32]; bool m_is_tor_v3; + bool m_is_i2p; public: CNetAddr(); @@ -90,6 +94,7 @@ class CNetAddr READWRITE(FLATDATA(ip)); READWRITE(FLATDATA(tor_v3_pubkey)); READWRITE(m_is_tor_v3); + READWRITE(m_is_i2p); ) }; @@ -133,6 +138,7 @@ class CService : public CNetAddr READWRITE(FLATDATA(ip)); READWRITE(FLATDATA(tor_v3_pubkey)); READWRITE(m_is_tor_v3); + READWRITE(m_is_i2p); unsigned short portN = htons(port); READWRITE(portN); if (fRead) diff --git a/src/qt/forms/mainwindow.ui b/src/qt/forms/mainwindow.ui index 56b10c0..ff6c973 100644 --- a/src/qt/forms/mainwindow.ui +++ b/src/qt/forms/mainwindow.ui @@ -1413,27 +1413,57 @@ QLabel { - - - - 8 - 75 - true - + + + 0 - - PointingHandCursor - - - Click to copy .onion address - - - - - - Qt::NoTextInteraction - - + + + + + 8 + 75 + true + + + + PointingHandCursor + + + Click to copy .b32.i2p address + + + + + + Qt::NoTextInteraction + + + + + + + + 8 + 75 + true + + + + PointingHandCursor + + + Click to copy .onion address + + + + + + Qt::NoTextInteraction + + + + diff --git a/src/qt/res/icons/menu_16/triangles-16.png b/src/qt/res/icons/menu_16/triangles-16.png index fa196f3a808b1d12eb07da72a6c03d92dc8039b6..ec058f0d808f502d55677f4b6ca9a3a0110d946b 100644 GIT binary patch delta 821 zcmcc1e1>g;NO>_%)r2R7=#&*=dVZs3bL1Y z`ns~eV&h}h;ZY0iO>QOGM7OH03V z0)GX0oFa6mEK<1Sv?OD~Ho;2`U$*OTa|LxoZOI6Be3U+ITVhb>bd*Ns3Udt#w_CthhKc! zalW+jPQ7^H8&T8WtHi$q`K6rCEZMWaS#x3QtBggn8J@0OYyQIM^S7H9H+RHl&Q2D$ zjGw-^LZNG`a?zJdZWB3QAK7*E&6_LQ$^RO6%$1OjmI(-t?r&DM{V;K(`4Wk@tX$SC zj8YrJ%`fjg_~pfc3;WV|zJJ%_xuIXbIJ{K+TG6Mhomu&(>Yq*bf0LluEx+pM-KqEO zr1OI&?`&|sedxuXUwr#zt_TS{(-e0+c~6sJ&XLz1rxw2WasJ5h2YNLUlC!uieAwpg z;L#FRiajCoiht+%*hFc+5sFK(<2bNEx6bBy6SKCia^3fT z-T|x2ZGSx|nm1E!k8IFcwW%NCBYD0=^i@y)tmStl;FiGKEH1fISJ*|BS81=&HC@`o z!22dPQL;Ar@_l>G+S15C31QjPReKXx9*=ygy~c3ylZ}Ukg$3u{S|zgCQ@LJ4=s=Me zL&k*coZDtsmK;s9zaq_WewFO`TNU>#vlG3F(q=_DM=!{fT6a8N-<+Aj!CRrhep%=K z{hw|(Id4@n2PQAo64!{5l*E!$tK_0oAjM#0U}UCiV5Vzm5@KL%Wnye)Y^-fyU}a$N jGL>@*iiX^Ly_C$fO58eTSZve)>R|A6^>bP0l+XkK=uldO delta 451 zcmV;!0X+W92HgXYB!3BTNLh0L09-}@09-}^6qG|j00007bV*G`2i^%36ag=vZgTPf z00DeSL_t(I%cYVrNSk30hM)WXlSHCPlV22DMH9M77h6zt5K0i0LWe@4I5>0?L?>q# zL2#;rwjB!&g@TJqM(GftLnmz~2L&x{U9}SRKL;%&F~-02g@0S_dp~&Y-h(fT_CjFp*+C$gXab>3a=^{N}wjrw}hXUeMjT@fCX{DNNkpy?;#d*6cP_VDKWvTDiA^U%1`F0k67o4t*s?Vgkp4j!v}x^xoo08YY{2xKBObMAg? t1bQ}(gY}A|a%Hm^U^Uq+8psp=S62d)WA+zfKBoWx002ovPDHLkV1nB<(3b!J diff --git a/src/qt/res/icons/triangles-128.png b/src/qt/res/icons/triangles-128.png index 57fc6c4916d51bb92ebe1e95b79ba13c97a3bf5d..9167edf39199d209c723a06c2f27b5872e4516f7 100644 GIT binary patch literal 7743 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 diff --git a/src/qt/res/icons/triangles-16.png b/src/qt/res/icons/triangles-16.png index fa196f3a808b1d12eb07da72a6c03d92dc8039b6..ec058f0d808f502d55677f4b6ca9a3a0110d946b 100644 GIT binary patch delta 821 zcmcc1e1>g;NO>_%)r2R7=#&*=dVZs3bL1Y z`ns~eV&h}h;ZY0iO>QOGM7OH03V z0)GX0oFa6mEK<1Sv?OD~Ho;2`U$*OTa|LxoZOI6Be3U+ITVhb>bd*Ns3Udt#w_CthhKc! zalW+jPQ7^H8&T8WtHi$q`K6rCEZMWaS#x3QtBggn8J@0OYyQIM^S7H9H+RHl&Q2D$ zjGw-^LZNG`a?zJdZWB3QAK7*E&6_LQ$^RO6%$1OjmI(-t?r&DM{V;K(`4Wk@tX$SC zj8YrJ%`fjg_~pfc3;WV|zJJ%_xuIXbIJ{K+TG6Mhomu&(>Yq*bf0LluEx+pM-KqEO zr1OI&?`&|sedxuXUwr#zt_TS{(-e0+c~6sJ&XLz1rxw2WasJ5h2YNLUlC!uieAwpg z;L#FRiajCoiht+%*hFc+5sFK(<2bNEx6bBy6SKCia^3fT z-T|x2ZGSx|nm1E!k8IFcwW%NCBYD0=^i@y)tmStl;FiGKEH1fISJ*|BS81=&HC@`o z!22dPQL;Ar@_l>G+S15C31QjPReKXx9*=ygy~c3ylZ}Ukg$3u{S|zgCQ@LJ4=s=Me zL&k*coZDtsmK;s9zaq_WewFO`TNU>#vlG3F(q=_DM=!{fT6a8N-<+Aj!CRrhep%=K z{hw|(Id4@n2PQAo64!{5l*E!$tK_0oAjM#0U}UCiV5Vzm5@KL%Wnye)Y^-fyU}a$N jGL>@*iiX^Ly_C$fO58eTSZve)>R|A6^>bP0l+XkK=uldO delta 451 zcmV;!0X+W92HgXYB!3BTNLh0L09-}@09-}^6qG|j00007bV*G`2i^%36ag=vZgTPf z00DeSL_t(I%cYVrNSk30hM)WXlSHCPlV22DMH9M77h6zt5K0i0LWe@4I5>0?L?>q# zL2#;rwjB!&g@TJqM(GftLnmz~2L&x{U9}SRKL;%&F~-02g@0S_dp~&Y-h(fT_CjFp*+C$gXab>3a=^{N}wjrw}hXUeMjT@fCX{DNNkpy?;#d*6cP_VDKWvTDiA^U%1`F0k67o4t*s?Vgkp4j!v}x^xoo08YY{2xKBObMAg? t1bQ}(gY}A|a%Hm^U^Uq+8psp=S62d)WA+zfKBoWx002ovPDHLkV1nB<(3b!J diff --git a/src/qt/res/icons/triangles-32.png b/src/qt/res/icons/triangles-32.png index 59ae10a73dcd88fa3c355381de3b0b6a011a0d4c..542e5a2ec2581ff2ed2b8d5a9dda90300ae4fd70 100644 GIT binary patch delta 1456 zcmV;h1yA~$2HOjeBsm0UK}|sb0I`n?{9y$E001CkNK#Dz0D2|>0Dy!50Qvv`0D$NK z0Cg|`0P0`>06Lfe02gqax=}olAsl}W!vFvd!vV){sAK>D00(qQO+^Rl1`Y!(3?@~H z3jhEF%1J~)R9M5+R&8ukRTzHGy|?Wc3mr1nbzM8gVBc%mM2Ku4Q*dBr!te`)UPU#y~(#G?JK@s4$oq0YQe0jiO<0z&1;^u3OiZ_V%tH_qKn%#~%xE zlkTHs`@!??zUTdT&U4=PoC`dR_~Dx`uu-eS_G06r*9(ds-H@We>7&Qu%EiVLl;QM3 zOrMvSYU!w-84y;5jf+oMTbiXSy}dE#Vqy*0v%VTq>t!U~{PUTm%+T7$8Q-de&cD|M zFE`=v&Rx^5fKjP}kY>>2d#rzlmMNwAb6Ltc#faXLRoLL}?i^}$I;M}n!L3`tHa0@R z(jCi*P^0B2Q4l~$<#d}rEm_Q0)4&nxjeK3%K|&0)x}UCmG; zgd*7|wb^IIKI`Ch!8_@klkS0cR<1-_$_uIg6|I7Tj##Gv(l{9f5#dF3~D zBKn)UoKs<^UAX3Q#!uj*S2v^V+*$B5*xf6Luu;R&amxe1@K{E)1Cq=i{l{`~zs-hU z%;xwAEZ}*xYqZ6s0mp$-Whj}D3F`v@W-*iuh3SIX$Bv)Bd#itA;2O`5={sf*yu0#A zSeLC)=)8_MjhvXtO|m!uaD>3bNqU`ku+CLhsoYb!CN>53*KWhW`CpOjwy$0iy1Or5 z8A$*pPXGXBG89r+o^S6TXbpCEc2_@Jg>&s4lOs^5P{5s{Q|CJG99*sl6eTdR6$eI+ zr98JQBmX3Ixx{}Kd;i2o@cH}ifi_=3N?+G=CipAVV~pKIpa9e?U}Az5I+yhY-(O~Y zd*G9a6)^BT{ON|wB5!~FQl+G0W8eHJs2R$-Lo};DyXdsdZ01`XqhHHW3VghI6RzI4 zK{PH~?IKPzCB*!e_KJaPQ5D!-R*s&6$CMd@qt3{Q4=nviummu2qR!xR)maOd zDBmtCA5GxmiJ#zUx`cVR%ug4?zdn_VukprHVJ-(0!C$R!Z&~fX-iqHF8ivUMz|7lS z@MUH{lIMTwIaH<$=BlP}_xC^msEMp{NL168SK44Xe=g8$>jS&Lb_>K)r!a#=YRW0U zO|Os{8snuiS*REahROz;PqK#E+gmohwG-?-504?OKFj2@*DqCtG)xRvZag}u8Ope& zNYy1L{4mxInQwMF(}aJb~0{EbTdN$F&s+b!u&3> z#gJJd`GZ8h=O2-yM#^$@J0db5%Tf4JP05UK#HZ3qVEip7yFf%$dGdeRfD=;uRFfi$536uZ; z03~!qSaf7zbY(hiZ)9m^c>ppnGBzzRHZ3tUR4_9-G&4FgGb=DKIxsMpII$=I0000< KMNUMnLSTZ2+OgsQ delta 749 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 literal 118032 zcmeDk1wd5GcF5fYq(s1??ZR#aMFGJA3oPtzumkMwRumiCCngq(4G1VUN+>A?7R~%~ z=I$)3Prv$}SZ^=P-rc)*@0>mpXU-6!MAV6{E`hU{3{)eeKOw}-O!(|CCgcWOv$n?1 zX2ib?A!D@(v9S?8mv2UhNi9OWy``VUN~GmjcmN!D|JF8y44!X+2)@fFd3pIH=5ahJVtS2emcC9N zMaPkxTngXikzNDO6H+XW5W_gqqu+VBmP>NsyZn3#=R9)Z!abs77(&!7liJ7UGtXq#GqlL#!brBs#2v^*(ObG8XD9gb?en{Pz8<#_3PCo zbwt*rdX1W8Yt<@Svqo)VEmBe<6)IM$T%}6oN>!^7CHSaHEUn6vEnCj2JiJwcOQlMi zn3|cHTa+#a--01ABu2)?iBh}Q2 zs)*wX_bIEu?}V@a-7DHzGblDtWOi2d^L7^PDcYvnQIE;Z$Y`*W`NYX-C27`diOg;W z9tZoPcNpx-QF7!^5XsGXN9r|PMM&{jLP|a%HR`M)S(&fF_T`ebs{#noI6=f^Q{jAy zEL(Drq^2a1(pGB-DJ|Gbb+CQJB!v_=UrQ1bo-!LhX7n~fw64PMQoz>2_eHLg;ls8H zHXm$vWOx*j82AxYi!`vEvCQVGnZ*)S%jZO-zlDT_M3VOH*Mlv+1GY4g*=w}Ds!+sM z31C0(5$D!xnV-l7oGIA-fJ5h@&V58w<~bpn2grea=ScP1s|hiV2S4ycu)D>dkg7FS zlZ^N2WXYm~0N*pf>kL^qe?Lih`h*ypts_c+i;`(7F*I3Ep2WqGp+mL+{2_2}GWdXG zcppXv4)h}-*CL3z{#K#}FstcpBiAm61MSgwSlZw?=lecePkh!z=!TsRNG=j*SS$j$B z>2YpMN4iVF^?XTzI`?kq8$$Oc|!WY`-|s8h>Fg3qGt7+sOat>7cYcD z{aK`$9q_H#LxAfkz!goJ!{=>&C*b)3fFHo5ahPo1a+0LKN+VVk0H%_OK({BPOvTmY zb^3EM-P@l?fDUSAF=XcS-Q?b#heW^hE<()T0xwg67O6xD-W!vTsxqJHoxdY{P)O~X2PBgiB3*=RCFbb$>s8rJU{88ykWC}QP^yo3+IF82&cAN}k z$Enk2cJA`uy@wrp_u;YsfN&fM_<0rZ<>w&5rukYpmfPE?AFQy>=ZbMwTpHR^7V3@U8r7^`XmGkYY-`=gnWR zu-@OkcdXZc(c*c%m6SA~SvC7_52$ZlefFHWL<1ayCGqxguP3dZSJ0rIyUz?_3AS8G zg-o0@dCG?n)VH28dFnKxqJ+k|7#TaRO*#Hc;aslG_zCa@e2@NM#K=*j9UTkqaC96q z%F|2gDI{>;;33UF0I~YeVZ-6FgmF(vsdt~g{TkM*#~)C?UjG3D2LWzU<^qo0d(@CU z0C4N+(F<_nyjQAdNji6N<3y@o&%J9mhMVjLWzyco)l|T-zO^a%YN9OrxqxHq;vC0v z;JT%_$sV9Y3|iVdAdZfX4&cc@@`5%*108yG#Gra}yB6?s8~$5%R#H;0Si26o^m^#% zo62zGcPUjOm8(>(20yP+vz8ogvhRr{0ry_6T-ov!h-F1N;H7scDU*`S ziV;I2W8>l_KEh3QgOWsO4t#_g{~j6#L{qDXHlX_H18^iFF;V{;Zv1u-HB~hxRQ$?^ zXAnkZV9Vce`|!3O`U%@9(4{0EP?U%nyux86*G>_xfDg*2(0{|z2WPnYUH;fZv4a0o zpg#&+T%6Xv_xj@MmOEBE?wdEq*`)|u7 zR-ck?1i(Cou3LMMNlL3$vnVNgjcQg*r_i23OwsO6{}YCsDSoyR8$7!UVRolu>TB$oy!Zh z+3?`Fpg+c=bt`X5bWX$Xo-sSbpYV2VHe>AKXdp) zL!+pu$atz|0rr&99&{OW=tsdX)P?myu}EUDgoWPz0DcZPKXZIIZ$=DVPKjt2vsq|Q znJ)hT`@?ySbuxP?@~6WA7Cbm?999lHKjU>6uVf#Sl2T}i(qpJnsc5iW34$(vY_|&q zAD}t6m!%%j;-x%kVqyw|31Ryj?05tJj^nv}>29!D%YhCrWx6cLQ(@UuK}H4IqrF@~ zmoN2auydF=jO^kkUhsQQEOc7Dj8<97nUW zvlx`}aD4*o4=w=)pvywL;z$6rN7a467Ci^P3VKjDI0&@II3cJw9;xh4dIG_x{jIGok z+`4(6YU+#y`AL+@kDz1U&z|z@o}*SXKzQ98mICO$?j8P)+tajXFQ}>c7)nas2YU*9VE*ji%Mfql zs98RRXFs5&O+9I9N*V+3OZM_hSa7^K9oDZs05)yWhxYVe`DFor!Ct-{bEYAJ{pMHf%5v`kGg$I`j##zr^VG4|P}-{UJPq*-L}#v~Jz;VE1yE z?(up*2iLb;$7gX{bo$g4Xje=H_=UEe(60D)IpTPu%@J9Fy%c%V6UQ$xu!Oq4-d=tQ z7fuU~Lsz%ClxPNkJ;gRQ`m}G=W9-{OKM{V5HkoK0qn$en{c)^=*Y_p3zU6y-ChxD^ zzaK-ji+WKNb{u^~!zI~}`mO!=iyy)$yhYTF71MB+U2Y)8ltErPWLO;j%LtXx= zeh#NS+Dp(`^(}P5xU~#i{%l@XVc@`@o&M@IEmPK$65~72*A(n2m+Ai}PuyOj4JIY- zQF9AV`aJC=0~MdmpZ~pK$LH~9b2@GHI|?>$KFDxE`}F_e@Il)ieuK7n92QW}M-+mVDIlVXyxh^<5Oog$#vux~+wT;kTf^8*w7pZO2 zN$h95UH`LTm&bwI)9cqjel(?XA*jRHz5{!SHun6vQ1%mUbNKIn_L=bjfZ#GQc+gU? z@BXZ9$;K}=4pEOD^BI_U4{GbLLVHd-gopd&r%#ipaf#7jPh+5s`jqMw^P~{R&2If! z_L9T-xihCH=fToNJHV%HhO&ds^x4FI#=qnDe(qU6>pH^4Vav(MrWGoTp`}fR(s%FP zGmzxJ|5-48sb0W9);99r6+}004rD*!<9QsvFFogHeb3>;Gs?QWyz}pV7HnTzFNc%E zkH6#BzV;bkd!IB6NOAf}6u>ww8z|mTWN}(>LAGuOuH*5w{QPt8leUqW^93wFKL72) z$2a`T&;Q`(*sTBhf|eKkhx9jyB7e`$_?`3~;m!|Ug_}P?7x*pQ`0oom;)fg`!-|!{ zHEc8f)B>@2xzP6emV)h-9GH9h>hh`k*)?Ha|A)~37p){X_%^+C8Op^7D3PpOlsgAs z2&dmt&IjF~-%^6k-JoaBhC&JZ>T>#Y2t9K;^sCG1Qz0;>Bww!6(`O=R;OTJc<~|2v z=A5ar%1Ag5hB8!IhQJvMejfG>h5!C*&)@QF`Fn>0OkZ2@cX;mzc2-t~@d)BXyLDdx zF;l6uRLQf#d}9&D*Z4Twm(Mt+%jPX`EUu6X zj(cd7g%|`fh^|~A%m+eio@QodQ|l`IVSHpC%zp{-1bjTduwmlQXLLYXd}ZOk`?@pm zk;gA+`_r1$2SWS>j5mPa=Y8LU2O(aUcz}$+9Jq9>6z3too&VoD=O(?M&3WP&?N^qs znA=0xkv@#3fRorV25{^_j|N<3a*wzp4fq&So7R(HoNoo_K|!pl{CGDX_xpX$sDA?Q zB{-+1wv@JSJC)%s8!MBxf$(B@cr+DD+^JgWn=C%<-_B$IY&r@2$FYBi87&n-H8kAl z&6_a-{utlO+Jr*eI438ET^~7e1<1%GDq(XT!n_T$1vuvT6*Bj0+#|@m!239m=jVXa zMCv(a6~mFqJtEKkh4w#=3E+{O@{*P;*@G$*{+ao=UjtvM4MAC#!ph(U zn}_pnO2y95(xrOP)Mvu{f^3|dVGLvd8-NG5g{xOWJPP;-N!cWsZ<0OtmzD!LKB3)% zf;bQ|kgi$%|L1dA9}wsu_=G%KyB4$si|mw(R~DZA!Ti}TrVmWtrTjs;W%12gJ89iI zL&3%ixN$tCte2gnA^`UZ@r5UjU!z2+JNS%f@P~47|LC87F}!8)a2-Y71I%KJM}R{Q zdh%ol!&C5cg5JvzmwUr$!)ef|!!(EmSPZtXVBSlh@vlh(4x21S8DQ_+(OZf;`uYN0 zmqWYYEy_Q9;!gM`a6KNR4BmiPVd}_XZW%4 zYJA59on8Itg^7kBAKVsBoUjh;$2e#=Kc^}XqrhU*K*u<(WwQ4ZbwYqefJp_`B56ST z4Pl-Du;amSk;CmHtpE0r>j8f8{P`PdVdep`(kIw_Blm{_9exct;Jje4!JMd)!Aa=f z^`dD2J09}*unS*!!Ta&xGT`eA@kFE_l|cWL^IvFJ|9t#8?-@K`_cY3&zw1voY&h}( z4jdWpau5Cv*2k)r2%$RK?)3hHrwkzm zGvfcvl3zd%t^;_^$rk#DJ`gj2>!KwPAN-*&_;ECl?~5P|2n!*ebm~-J20Yqr&Ubz; z!0H>`N$H39^XH_$&Y128=&>E61Jt!yVfp9*p#+5*Q;ckbi7@6*di|xTC(I&4cpYL_&hA!7T7g|F?7j#st)5MGJl9L6>2-M;Q4Gk6Y3_Kz7W4Qiebe4oq#(C z?RP%#xqPhf%H=4ks^(7BP47Zq3)@Ag|6B%84ho?FzXjcgdcX&Z%8M%WvpMn`QQ(y%lsk3ndv|w;EuFKnj#HA@7WqumSO-3BR)(@OGvu^zQ_JH=53v;m2S@SU7J!1h#NK zp^R}kd!La-t5oU-b4Lfj7h#(K#vGZRem@B=8^W z|fX#%WSTE*hQA!njg2GA$`b2;F+hAx-=!fNY$6-}kS5SRe|Q0N~n zU$zfqU@)}HF_r>lUup}#kp?o^hi6F2!n!cT_1CG~cWr5!#$c!rd7JVwlW$fR3o;{n}nxAF!7!aR$ z5qMJI4_({CdLy-ER0MNJ*gyQ5cA;P^1RBWN_@Xt`(P12`F&E~jc|AYa-F*V%zh6Sw zxGjvj6+<;OF_r@6jv!AIYqz5wV7uru{4enLa1Z!9kqP805_P2^A@>FRrEAdtUh}VU zh3f&AQ7_NcAiEQ(M!AA^G3yt7QV#%U>2)@yg?)RasdVt*MGU!L!QXv}%7Sd-c&T8N z)6!m3v(i0b?&uW6_F-NHh^=Bcek=n5?t;ySybs_zm5nY?W8-c#A>lczmOT^g-j{&* ziQhBm&=#)G1m(?0soXreRMuJhPHGd-=CK?@I(w;gwShDvQ)pB0=Y3V> zzralbp9*}zsZ*gaPSlmn�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

bdMj;x^lCvim11}ijWV`v>eb?PyLpYRD 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 literal 20232 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::PointingHandCursor); labelOnionAddress->installEventFilter(this); + // I2P address, stacked directly above the .onion address (click to copy) + labelI2PAddress = ui->label_i2p; + labelI2PAddress->setVisible(false); + labelI2PAddress->setCursor(Qt::PointingHandCursor); + labelI2PAddress->installEventFilter(this); + // V3 indicator next to staking icon (hidden until onion is active) labelV3Icon = ui->label_v3; labelV3Icon->setVisible(false); @@ -357,6 +364,11 @@ TrianglesGUI::TrianglesGUI(bool fIsTestnet, QWidget *parent): timerOnion->start(5000); updateOnionAddress(); + QTimer *timerI2P = new QTimer(this); + connect(timerI2P, SIGNAL(timeout()), this, SLOT(updateI2PAddress())); + timerI2P->start(5000); + updateI2PAddress(); + QTimer *timerShutdown = new QTimer(this); connect(timerShutdown, SIGNAL(timeout()), this, SLOT(detectShutdown())); timerShutdown->start(200); @@ -1327,6 +1339,16 @@ bool TrianglesGUI::eventFilter(QObject *object, QEvent *event) } return true; } + if (object == labelI2PAddress && event->type() == QEvent::MouseButtonPress) + { + QString addr = labelI2PAddress->text(); + if (!addr.isEmpty()) + { + QApplication::clipboard()->setText(addr); + QToolTip::showText(QCursor::pos(), tr("Copied!"), labelI2PAddress); + } + return true; + } return QMainWindow::eventFilter(object, event); } @@ -1453,6 +1475,7 @@ void TrianglesGUI::menuOperationsRequested() QAction* unlockWalletStaking = menu.addAction(QIcon(":/menu_16/unlock"), tr("&Unlock Wallet...").remove('&').remove("...")); QAction* lockWallet = menu.addAction(QIcon(":/menu_16/lock"), tr("&Lock Wallet...").remove('&').remove("...")); QAction* changePassword = menu.addAction(QIcon(":/menu_16/passphrase"), tr("&Change Passphrase...").remove('&').remove("...")); + QAction* hdSeed = menu.addAction(QIcon(":/menu_16/passphrase"), tr("Seed Phrase (HD Backup)...")); QAction* signMessage = menu.addAction(QIcon(":/menu_16/sign"), tr("Sign &message...").remove('&').remove("...")); QAction* verifySignature = menu.addAction(QIcon(":/menu_16/verify"), tr("&Verify message...").remove('&').remove("...")); @@ -1513,6 +1536,10 @@ void TrianglesGUI::menuOperationsRequested() if (walletModel->getEncryptionStatus() == WalletModel::Unlocked || walletModel->getEncryptionStatus() == WalletModel::Locked) changePassphrase(); } + else if (selected == hdSeed) + { + hdSeedManager(); + } else if (selected == signMessage) { gotoSignMessageTab(); @@ -1798,6 +1825,32 @@ void TrianglesGUI::updateOnionAddress() labelOnionAddress->setVisible(true); } +void TrianglesGUI::updateI2PAddress() +{ + if (!labelI2PAddress) + return; + + std::string i2pAddress; + if (CI2PSession::GetInstance()->IsActive()) + i2pAddress = CI2PSession::GetInstance()->GetB32Address(); + + // Respect the same visibility preference as the onion address. + if (clientModel && clientModel->getOptionsModel() && + !clientModel->getOptionsModel()->getShowOnionAddress()) { + labelI2PAddress->setVisible(false); + return; + } + + if (i2pAddress.empty()) { + labelI2PAddress->setVisible(false); + return; + } + + labelI2PAddress->setText(QString::fromStdString(i2pAddress)); + labelI2PAddress->setToolTip(tr("This wallet's I2P .b32.i2p address. Selectable — right-click to copy.")); + labelI2PAddress->setVisible(true); +} + void TrianglesGUI::on_bHelp_clicked() { diff --git a/src/qt/trianglesgui.h b/src/qt/trianglesgui.h index 8f61e0e..24be5af 100644 --- a/src/qt/trianglesgui.h +++ b/src/qt/trianglesgui.h @@ -110,6 +110,7 @@ private: QLabel *labelConnectionsIcon; QLabel *labelBlocksIcon; QLabel *labelOnionAddress; + QLabel *labelI2PAddress; QLabel *labelV3Icon; QLabel *progressBarLabel; QProgressBar *progressBar; @@ -178,6 +179,7 @@ public slots: void setWalletTransactionSyncState(bool syncing); void setWalletTransactionSyncProgress(bool syncing, int pendingNotifications); void updateOnionAddress(); + void updateI2PAddress(); /** Notify the user of an error in the network or transaction handling code. */ void error(const QString &title, const QString &message, bool modal); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 3d70e85..7610242 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -10,6 +10,9 @@ #include "db.h" #include "walletdb.h" #include "net_bootstrap.h" +#include "i2p.h" +#include "tor/onion_v3.h" +#include "tor/tor_embedded.h" using namespace json_spirit; using namespace std; @@ -34,12 +37,34 @@ Value getnetworkinfo(const Array& params, bool fHelp) healthObj.push_back(Pair("lastblocktime", static_cast(health.lastBlockTime))); healthObj.push_back(Pair("networkmode", "tor_native")); + // Tor .onion address (wallet hidden service). + std::string onionAddress = CTorV3Manager::GetInstance()->GetWalletOnionAddress(); + if (onionAddress.empty()) + onionAddress = CTorEmbedded::GetInstance()->GetOnionAddress(); + + // I2P session state and .b32.i2p address. + CI2PSession* i2p = CI2PSession::GetInstance(); + int nI2PPeers = 0; + { + LOCK(cs_vNodes); + for (CNode* pnode : vNodes) + if (pnode->addr.IsI2P()) + nI2PPeers++; + } + Object i2pObj; + i2pObj.push_back(Pair("enabled", i2p->IsEnabled())); + i2pObj.push_back(Pair("active", i2p->IsActive())); + i2pObj.push_back(Pair("address", i2p->GetB32Address())); + i2pObj.push_back(Pair("peers", nI2PPeers)); + Object obj; obj.push_back(Pair("version", FormatFullVersion())); obj.push_back(Pair("protocolversion", (int)PROTOCOL_VERSION)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); + obj.push_back(Pair("toraddress", onionAddress)); + obj.push_back(Pair("i2p", i2pObj)); obj.push_back(Pair("localservices", strprintf("%016"PRIx64, nLocalServices))); obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("networkhealth", healthObj)); diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 1e41ba2..8586156 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -9,6 +9,9 @@ #include "init.h" #include "base58.h" #include "smessage.h" +#include "i2p.h" +#include "tor/onion_v3.h" +#include "tor/tor_embedded.h" using namespace json_spirit; using namespace std; @@ -100,6 +103,13 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); + // Anonymous network identities. + std::string onionAddress = CTorV3Manager::GetInstance()->GetWalletOnionAddress(); + if (onionAddress.empty()) + onionAddress = CTorEmbedded::GetInstance()->GetOnionAddress(); + obj.push_back(Pair("toraddress", onionAddress)); + obj.push_back(Pair("i2paddress", CI2PSession::GetInstance()->GetB32Address())); + diff.push_back(Pair("proof-of-work", GetDifficulty())); diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); obj.push_back(Pair("difficulty", diff));