From 3e7531d34e97e5cfed7d4119382bff6745db2c72 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 4 Nov 2025 12:48:37 +1030 Subject: [PATCH 1/2] pytest: add test that we fixup "pending" payments which don't actually have HTLCs. And don't fix up a genuine pending one! Signed-off-by: Rusty Russell --- .../l1-pending-sendpays-with-no-htlc.sqlite3.xz | Bin 0 -> 9776 bytes tests/test_wallet.py | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 tests/data/l1-pending-sendpays-with-no-htlc.sqlite3.xz diff --git a/tests/data/l1-pending-sendpays-with-no-htlc.sqlite3.xz b/tests/data/l1-pending-sendpays-with-no-htlc.sqlite3.xz new file mode 100644 index 0000000000000000000000000000000000000000..4a32fba447921dd4e2852369e05b68b9b216dc77 GIT binary patch literal 9776 zcmV-0CePXZH+ooF000E$*0e?f03iV!0000G&sfalzyBreT>vSRMV(;C8Tck-h>j-y zF_rzthkyo`yX=3c34y#n3^PcgaR~etO!C5)IiAwVj~d^eCG(;PRXL>*SRr}XMtgN$ z>|K|n!2fO@3}sTWQ7OFx-_e~|oa?Py2PsS$cO^$aUb{p7oi(}_?tBk~)WzERd=Nge zAdRKJGgseKaE8b6=NKte%Uz1457;(&YO`j?G^UMlNRNw+5=QOGIv)_VwpEl?B%%+U zI@+0m*F2oEl8<6gwl4QvTCt!LK!mQTuLT}T&+*}CXi)_M*PlvJo!r1kpjsTL4qDhQ z0kJJ%t)M^(YmpGt6I5zV?IF2l)h5ieofkN_yyp2+|8B^71a!v2X9`9}Xin zyJm6TQPe}~VTWqzU55WL|2Z2^L0P8mZc=G1NM{hoP^drUPr&?}zBmhJp{Z&$1ySIp z=YR&D#P>Pt#&TW07-a38UjgV$aVSX$UHl$34=Z0Zd%B707pdg!+fZm5d+;827~X{% z1*&Ot+Z6RLQjyS4XrT(Sddd32CuBZK%J%?iD{HJlEGHie+I*Oi-ewQsOV(@XBStT7 zlZ{riPE&jWhZGI574dcaYT+bGbO-gT?WYVqi2jM%IhAWrO4%q{0i}JV#i|D_C;0`d zMCh4MvfH#`P)aqx~|Gw1OryK9YwEx-nhLa$}=s-D%pqwTOu>EhhI z)5wIha%J3awtWM!4=()9>2f!26?Mjp=)-vxna+4!g&#(1AHxXim<@%*xN#3kx7Z=X-b4X7(GQs4Epm}<&qfa ztGfU&*#3qN&h0hW^0MzVI()*^$~k-AD|_;>MOo!UG>{bgQ_h2N)Hv00Ms=3+Y&TVU z;zYLDcnkiJ)$)Wc47v9sJcv?mN%uL8^xB5R!=|H zzo}de|4<{rA~F?p*F*fmmHNgDjhG?R;y;f?osx@AR}A~xH2w$L5%(<#NcLP9P()-d z{HD(ppJQUB5hbVd=3+7op(7^@6XAz2>CY0-UjVK*%v8jNrC45kjd^JN*SHdwhh9)_ zC;V(*_ibkSZ(pcdzZ5kQBDG4m&cqnx-0x>${3#DLkvd2&J@#Y2&QQHZ;_Xw08=x!H zcDc#|c+8utjdAb95~)PhY`joUwtOmhpL}LBpN>FGD~52OF4YLB&)Ra_u9hqWxWPVc8|chCiFJcfv8 zmeR@W4;5e9ML zfcU5^9rfcM7s>VVzY$XXRdF_}H=j(Du2JhNj0I?Hvb~HrmqyZs^^AU#fB;` z`v{KU9?b-Ae7o3}+=m|ojjN6?owE@eLWW-;KS%#f4d0%d#-O67@B~_25Qcz7dLD)R z3@P@qv&@5_lZ@X2Ox|I!1nkz!C>rMeOMFEgU=Xd2-B>`bmSb&PGgPOlCZnO-^L(AQ<08O!&dJ@C+#U!xAN|lt=2HqW+MaZpPnB?3@T~7aACIpB|t0#NtZfkw=XqD zsR8>v|Auonn9Xgs@(Kq_Svk~U#qJ@oVcAk~LgT;VpxC^JT)9QhFM-rH9b%U`@7Moj z17g^);!JfE>Jw2<)1JS^oP)JHF`@a(dYJ}aQ|bl+T%}>h8LKzIYZnb=d^uj_XAkfJ z(mGZ!SjYv-`Vfk8+WO^>Ht07d!%2P{b0A1Fd!mkbf&x2h--Oacz83{vV7*JHjmT|$ zlTs}$sFkBnx<`fMYo5Y&C<(wGPy6f}{0^J1 zx^sFO%uDy<5JdJ;Yu(4owL0HovyE5{;eyBWqm^QS$UvnEY_Xsw+Esp0hA{1ZY<~Zo zpOAu(Yb4k~Txmz+GW+G5|GN&b;&`YNxrD)FI(>#oML5z*R93O^=f7+t)iu^iU4VCC zDG@*8Fy}GwIw`##^4Yk?vcVc$EIdRJ05u6#p4dj^^>A%Lp!pp^%k7?u8qj}=Heu2rkjf*P;i2Q?pPcQ?gO!r926|<=b#%RN*w^HiF&$(Re>nWkd z?YWCuNnnq4y+L;M4yB=Jo0zq=zS`G(WCcDmO}8E_9^F{z-Yz_?l)-c4d(2$Lw!pH?{3$I*~PyqgD_`D$)R9;YQ zg+dBWg#zMNkdQRS=h$#1Y#rZRkRIek8ns$dYm01c!Zr1Thd(o)hk=WJD&D|*T^qCM z5wRb=)A03))wi>cAR~$n+6ng==F^?K8K%HTmD&ovGeEMzVM>`G;*APjg47RtQ0f9S zR~vqOJ9S=UD}$3$M|oiNR;C=WG#xHpHJ!jUL-fC7e7kp(DGo4fg(G3sOq5J>LfHZG z^DNw76)b+SJJoD%G;*tN?$*KDnE55w-drqA+J@Yss(ziQGPuMY0zht7c~xyeT%I6M z=dHYNxw|Dn=M)Bcc+&h&vpaWP9zOuE@mI?Qva;4`s4+nX?~>z`)|R!Ay~d^gYCA@@ zdtKnzO^&6TlK4bML}pP9zt0AYQc>M?I#C{yixb{X#-NDJMRlD{& z$@yp*r*Z=0{`n8K!SxAWZZig~>Ji-`j zlTeqm0*>`U?EV0dN~%{yMbDBBtzaL6|BH{->*w=?4?&rh8mkkEkm?hSb9Z|YVtVc5 ztE1dO@CEsP&KaG?_tMPXN)VYMm>)|X%SQxZ^#i*_A%6S!+^5>aru~M~U$P?-&w1r% zBsP8_+$qM+E>godinyby_LxE3!{n&G?U;7`NiJ*pr#Z8-X*##nv5AanE#jbGAOWXIDdN3*YRC!e4p4@QW5Y zuXf-yqkf(5-<%B+FyFXQM5TQFrA?OGB$0*nnv?LzK=NueH;ke-H7783e9+@)4TV>z zqK1+4Nt#xSlo<|o)Zg8Nh@}L~d5-9{q1@1=K6>UmHz~^h+26PP3cVO(^bR3qz#SSy zrEhLWAXK(-O!q*kxXVvN&K_umOb@S!F-wJ%O2LV!AMi#?awii8cR6AeVq}wRW{CQf zxw(6`T;kl2@A^bvla(YIG`Kb)@lspN;vClr zDX3RWGn~%5iFv6+GKhlRsT~>i=0xIe5q(q7kmx%-@L=d34}?XkN4J>Ig-=DIX>|oo zRz@taWhfK9BK&Fl6ZT{}jd$rYVxMthAznyV`P1DD{`xqcQ)R33wDE!o1A&iiP%!df z#%7@zUl?yk(>-0|Z=t~);rc)$a}nuB)x_-7PSQy3$?oCcR$cbmDlCkcp)-A7$xG2& z99~!cZaIi!Le9&;JPSU_Nltv$Y+FWDF!UHl`&+ zs;v_i-Gt=qHprpL{LuuhUIO&AYwf05jsE7=N7L7+5Ev4~Rt4PcbQF8{9($xHp=kof z;O@Dczrt>?s*=_1+fbBUS7s(Jd}G4UCeH{;Z$YBF6V|;zNbSzgtJyQD%6mb>xMg+i zgav12yl@n%2%O5jXv+?B}W6p8Eitf%8-HwOURXNRA98Y3cZ>v=eDb--1uAR(NpbXH_ zDF<$JF)PGU?n8bE1;O!3fURWbqpq3t@$mk(R1&5hJEo<}?}N4jG;|TlF$Ja6brLuS zxLMv;c0+ek7iUb_lZ#{!SOI97GITm`F31;;N|3L$g~`XGEMRg^d!d04x{bMs(5*ud z23Ee+#(M*u`)Z-+*7egfo3Z18xQhkW_#m=5yz=98DzcDxR5zW1+Pe`|LN`Se+RwPU zur^tbv1JrXesX>i#O6q-sVcd)oFf@#jO6YQJ11rw*HWA6!X7Ub{y@3sm9Kfk3{Vf! zsAq9tO_wf--TO3Wx&a>ZaR|ns;gokF<5J|#UsCIx5p4woLe9H&^AC%nDR!eKp|#s8 zO=+A7DRB;ujviHs7Qy|Kd#wZwirnKFs8!Ed)Q@wYn^7SIn5f`N2!%JF3QRD0Hzo}) z>xz>bxx&Zb&T9Ne)0fP9XXc?xaX>7eAU17;z%6_i>vCSc1{K<1S}HbHMCbiC9e0P3 zjoEj*VR?VJFVX{~h$ngS=EQ&>{6|KD#EEi#2{-IZ<#GQ{4cp2X||U-rwDfXfo1sQIB> zvAF>0+gC^M3U4xm`K|xujyl9^QbN?LCK(b8+wgvF8xuVX*#`oRnQU5qi@$rw7*W~` z`1Jfeo7wyyhLU@P{%#6?F9|^*cpWW%wf_&_wehJz?Uh4&j7=~a?eF`T;j6{L^@0#o z02*G3#(;+Pu6V&4@m%o4rmv$R?`m4?(1hr6X4o?>>~JL(N1E2y8jqby!7w`^*2PH8J`Iw)_8`67K2E;4Dr+iV8AMH|D%6K{9ajE8Nnr ze+L;?T6hBNQ&+N<4L&haJ&j`u%4(eoEDso`;C#B5k#Ydmv@z*3x5XTmGin0F$f_2D zxtLy~HhIf_kG~K@3EBX<6Fxp`0xXN zAEqvUiPjac_n`!@uO>B#4~hkE-jDe2z^r$!Z{DlMyq|?JU_%ts0v2bskO78}5}tL} z&odVJcL~!#s-2R6`Xv+h!F|?AoAwa2VQ1iUdgpknGN3HrVF3QjxwusV<1v}ZR)*Ig zz?2D4h$_>j#h;DOZ5L;LlGCpc0z%24V!U{6e-9P}hF=<%`jt5>2N57Et_fSps}9bS=h zfay|ZvR<2luF>bf8f@>+$;j}At8PsIOt*Xv;kW_kAqbNej_y)AY`OWYR+?fcHV+gM zKTLa1wuxSS(aEfZx!Q_=g=J6qJ`4WW3*3N z07iYvLo?bqX{{slq5^lh*M1%_{?PoT!;jNHXuyFL#8lf#1H*6;Z3cVfdYNA_SK3k4 zBidl6pU-3m$J>A)`UDj%j&;C91)iaHxCoI#JMxs2LUg}2)6wYMogHgvlhfbs-!fBJ zSqM$q_H8OA?ZchNYPTQQ8&L;j1(Xmx`WzrNMRg#ia)N<}9;tKah{(>K-gdd|Axn{) z$l)5FnXu8@tDR?n##V&}Qwdmh?b$7Kv}hdNuR%@AkugVa+d*LcB05CG5aJOA_*L^G zV8VO7r)Cyx#UZD|BrSg6Worgn$j-`7i#{AeycI;+kxd0?+ zwULiD&Lys%s;-2_W0m>QQkMR)uHXr@K>R~(V@?fDdD^b+2gqk0mI2MnDiy>dwcf?} zX$s>3g0ON47t+?MNhBSIq-vD$qFk@9j6a*@ls(i?A8E;&Q>PZnBlw&Us|b2H;Txts zWI3QSBc>PSy*%oBfZ5-l|L|Wj0NKXtk2Q1KhrWQG`1w0hLsrLr6a1K7%S|1Z(1sHo z6r!kKa9eeIK7DGuIHn*VevMSvI_EdkN$z0?sHX5xNw%8Zh4dE4 ziN}%@7sgqLVc#+^VEm~O+8Z)2zW};?UQ(;QD{1`Z)KmcFYPFCf8dLYw0i37=2U5ZG2x@2tb z=1(AW{Wj>#-v_>`cm3;`fmx`5o7~XVWE6jfSIpE>J$CB6?s2^V7oI-(_1DP zu3-x#9*2j>(Ud3L06B~EWVNYt8MD zBUJR%UtVmX`W|0#01ESyise0~W+Vqgy+rK=NtqO#x85S2hSaOQojNH8%AHaCGw!+m z0``5&JzOSa(DpDL&VbRMPiwVlrEEenZJNsmNg95NN>Kb>Wt*!Rw@F1A7fDk7QWt2y z1Nw5l<7wO01b*|p_IX-=l;~_+Wbp6uB<17OUZLt<(Eu9zF`c)GRilLDI;00xCDZS8 zvA^1Ppdq84M0vfWsPom4vBjLvQ_ueE|A?u*fd*W}Zx){@aFcu~Uf_h~{*+Ow9(zkj z{DY32NKU)%{N{8{YO;W^r|NJuSK#)DIfreJ|#!TV66S6D|@0$L4!5G_HoQ*Hn8C96Oq zudtN@4NbnD;@;)NyWn|=5aCxXO2$cQP1vU&tTCAeY??*gwYxq?OD=tWDV$A9c!_Iu zy!~q9Io}tEzT6~)WC)yL>AwV+_+JS~p)?J3p5k&R2r$l~VV-YPQ?MqylDsNr@As;* zWl@(&YF{CkEfv|t>jpXiftn*)%60|D0c}I=qcfj9B#F2A9+fKTKb=)cx4T8cF*O?6 zup{s+@%mR?x$W&v#X7MkF1)c{Q%Rlo<{f>8|2sP*M>HGA5dg2M!!m+~E5buZvg2<% z&4@0VUFQQ-IB#pD~t^u&UL!DzYzsU1 zRZN?9bc5e<^-MT-VEu{|qI+(p$+u48u-hM0g@SA0T6hs^8l}IXZX0U~7D2pgE$Z8N zsXGxlHQY^LK$-)YB4SUk=Ug&g{sq#=|j0ytysLRN<#j*RQi=cUv)0F0{(el*`l{I6B62KQ=L>C_;WU z`^LV6-*k&xa5RRsq;){McJCzx70WmX{Y=AhL=#lpWV1fst!)Ff&txDO@=|6;?89oB zUS`)(UD14VzTj3M^$5_U91n3dcyxqZ>*y+Z+DM@4Q$rp=0FU}PAD#Dx!w%t>RFC&{ezA_}ne4?#%-*BSRWHp2+meLReV9O(uFG1#GK~-zd@(yNm z=D%Ba@MV!9rJM3$*?wrS^+F$1_)*f^fnMnQ><^8Z0<`Y({N3a$wE#>i7?^Cq`Y;o; z<7tP2^nsI7^mX3|l=O0)$c$5$Y_TL{ac(UeKb06`V)-AskeGY45PclIIgK2g;5mPK z2}egNVb^Vh&Z$!Yf3DL@?@&?)Al0>Dtv&5{aQsS`nyQS6U~*hBs(94$hJJpym_i|b znIE};(pe6I-ZBBg_PazjpJR`&l8RLUMD*Sf%AK9(%`eMdYh1`dlHO>8ebkWy`NNygm3YI-9HpAClV)l3%7=&1HjKP*S zTYv&6?1R#5YgQXur>3uGLsT$d ziA%H->D}{XQrn*O?&l8R83%_7q6d=eMVQ5C2d(Y^I*!HA(glB~4AF1CWl}osJE{9M z>cr4d2^?if)XJtf2M(ZDZdOM8v7{`t5!<#6prXE%7^?!--#vBXm%9D;K;% z+k^ph|Ct1fXdCua zk#e48K;|Hvbb*JzK|2v3q3RTmJN~K`mgb4zq@@yO4^N=T@daF!{neZ9R}OK3Xh#-L z2yMZD5^zHUh{UFVIu8)Nkf|t|410DVbUrSL;o&hZG@9uy0vqJul!}E{uf{5$7cO_a zR5r2)EU&i|p}z3#l4aOrp%EEhutJK8A!+B$|IQ^H=jeM)TQmrT8lO3$++bB;(9}RK zc~#RPCW`O-oBwK0h}jfB=^nMvZm%H%nN~gjW%h!*%6gHw!g0H^kT9fwfCWW4UvDkX zbG=)`YUc8UUinYX(Cn7PpcuH{XlbrRh6|U5Z570am({dY{2f$hApvNMI;}Y|QY~G1 zq7n(W80M{`VMJ}0>qdB2T&hOv+5Bzrj5)ds-%PU=o-Z-a-twG5N-|z)<3sEANU~`` z{z3=Xh~v_U)!tjyO6|vPwif&?nqo?QjWGr`M(&ZKwIu_J+P&A01Szr1*{!LrcXaZb zH^@K}xvO79q5nYOI@{I@4oCjKL%#ZZ$WX;1mqOYm9S($1dYTS8)6y{i{hCNrV{2YB zkAYjk&8Kq?;VsP<(oG2TCX-g^2LR^&Uy?Ngh$G^kRXII+g?h0%jAV~drNPR_Pn6Lg zw&!&tz{O#Ik^K%c+&A3vK-OA#lt|9~??lNLlBTj*&1ji9I6`INcmg=Lh^78iwglSN z3H?gIc2xD$$r*K)Zts7ZCy8H0!&6Z?&anuYe1oj?OboUnF4Sn*3)bo{!uk0&Q<+Hv zq)7W|holNFHtOW7#bz2W$~{*y{__A_U-nFL z`yunj16E^eG#+?kc`n$3W5w_)r!4#I)rrhf{woe2$D#v{WmVg{S9!R{O{?G&6RNt0 zQeb-Y`Kj%VEnH+tB@}cR>|ZFPo{q42l6Vu`Rl~0Q{K>%DU0(|+Ahwk;ynOv(w{0GH zt0=OOc?&k)lkX4slenUR9Ng2ARNQFrMrzpdOuGdhp(uPN<S%bceq_133_G zUE?#!ay)U-c)iHl038f>TC-fSbmWiuEa@bW{39Z}O6>CmXf^mp{o#(DjcBJXyRcZ6 z@j=9MKNCqT!#R5c(M0e$LDZ{}>6h^Y7+THp%rQG%=$&DLiYGp(mysp{2|#BwquRe^ z-c)jj6CZ4%5X5(Gx}((lw+DWk>6>ey**GFzFSRFyD|v(gW-+DB1cu57091ZHu8Uk{ zR$jR@Ss8W3(;lT`vp6x8*n~K=c4}E%-!LH}bj0Ty``!Ypzf}jvM?S{Drydk#S7NH7 z)0;sDafg=MKi)^3VZ^7rc&!lPc!cs(!Jd zeNhcZ-dtMrgf@&}R{&y`n%rNrnv+FKFXRkC05vX4Yy#RMleh?xwY)&2^QqkN@a|k$gLLz!TmNT%fT63}=6olPDLSZM$ zM&vFfr>=oBJ-VkjwYzwV77 Date: Tue, 4 Nov 2025 12:49:37 +1030 Subject: [PATCH 2/2] lightningd: db migration to clean up any pending payments where theres no htlc. Signed-off-by: Rusty Russell --- tests/test_wallet.py | 1 - wallet/db.c | 27 ++++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/test_wallet.py b/tests/test_wallet.py index ca4874b24ee6..074e01ebf0ec 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -2469,7 +2469,6 @@ def test_old_htlcs_cleanup(node_factory, bitcoind): assert l1.rpc.listhtlcs() == {'htlcs': []} -@pytest.mark.xfail(strict=True) @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "Makes use of the sqlite3 db") @unittest.skipIf(TEST_NETWORK != 'regtest', "sqlite3 snapshot is regtest") def test_pending_payments_cleanup(node_factory, bitcoind): diff --git a/wallet/db.c b/wallet/db.c index 2457349613f5..26e6af23f95d 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -84,6 +84,8 @@ static void migrate_convert_old_channel_keyidx(struct lightningd *ld, struct db *db); static void migrate_initialize_channel_htlcs_wait_indexes_and_fixup_forwards(struct lightningd *ld, struct db *db); +static void migrate_fail_pending_payments_without_htlcs(struct lightningd *ld, + struct db *db); /* Do not reorder or remove elements from this array, it is used to * migrate existing databases from a previous state, based on the @@ -1087,7 +1089,8 @@ static struct migration dbmigrations[] = { {SQL("CREATE INDEX chain_moves_utxo_idx ON chain_moves (utxo)"), NULL}, {NULL, migrate_from_account_db}, /* We accidentally allowed duplicate entries */ - {NULL, migrate_remove_chain_moves_duplicates} + {NULL, migrate_remove_chain_moves_duplicates}, + {NULL, migrate_fail_pending_payments_without_htlcs}, }; /** @@ -2117,3 +2120,25 @@ static void migrate_convert_old_channel_keyidx(struct lightningd *ld, db_bind_int(stmt, channel_state_in_db(CLOSED)); db_exec_prepared_v2(take(stmt)); } + +static void migrate_fail_pending_payments_without_htlcs(struct lightningd *ld, + struct db *db) +{ + /* If channeld died or was offline at the right moment, we + * could register a payment as pending, but then not create an + * HTLC. Clean those up. */ + struct db_stmt *stmt; + + stmt = db_prepare_v2(db, SQL("UPDATE payments AS p" + " SET status = ?" + " WHERE p.status = ?" + " AND NOT EXISTS (" + " SELECT 1" + " FROM channel_htlcs AS h" + " WHERE h.payment_hash = p.payment_hash" + " AND h.groupid = p.groupid" + " AND h.partid = p.partid);")); + db_bind_int(stmt, payment_status_in_db(PAYMENT_FAILED)); + db_bind_int(stmt, payment_status_in_db(PAYMENT_PENDING)); + db_exec_prepared_v2(take(stmt)); +}