From cd7f157929b4588fdfb370aea172dd9f7dd1a178 Mon Sep 17 00:00:00 2001 From: NyanCatTW1 <17372086+NyanCatTW1@users.noreply.github.com> Date: Tue, 19 May 2026 18:04:50 +0800 Subject: [PATCH 1/2] Implement ASERT --- electrum/asert/__init__.py | 0 electrum/asert/asert_table.h | 528 ++++++++++++++++++++++++++++++ electrum/asert/asert_table.py | 517 +++++++++++++++++++++++++++++ electrum/asert/gen_asert_table.py | 69 ++++ electrum/blockchain.py | 176 +++++++++- 5 files changed, 1281 insertions(+), 9 deletions(-) create mode 100644 electrum/asert/__init__.py create mode 100644 electrum/asert/asert_table.h create mode 100644 electrum/asert/asert_table.py create mode 100644 electrum/asert/gen_asert_table.py diff --git a/electrum/asert/__init__.py b/electrum/asert/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/electrum/asert/asert_table.h b/electrum/asert/asert_table.h new file mode 100644 index 000000000..f571a4cc7 --- /dev/null +++ b/electrum/asert/asert_table.h @@ -0,0 +1,528 @@ +// Copyright (c) 2026 The FACTOR developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_ASERT_TABLE_H +#define BITCOIN_ASERT_TABLE_H + +#include + +// log2(compute(nBits)) in Q32.32 fixed-point for every valid even nBits. +// Index i corresponds to nBits = 2*(i+1). +// Formula: log2_compute(n) = 0.0301 * log2(3.8) * n + 2 * log2(n) +// Generated by scripts/gen_compute_table.py +inline constexpr int64_t LOG2_COMPUTE_TABLE[511] = { + 9087915284LL, /* nBits= 2 */ + 18175830568LL, /* nBits= 4 */ + 23698600879LL, /* nBits= 6 */ + 27761726543LL, /* nBits= 8 */ + 31025048513LL, /* nBits= 10 */ + 33782477547LL, /* nBits= 12 */ + 36190794592LL, /* nBits= 14 */ + 38343583902LL, /* nBits= 16 */ + 40301209242LL, /* nBits= 18 */ + 42104886564LL, /* nBits= 20 */ + 43784013531LL, /* nBits= 22 */ + 45360296289LL, /* nBits= 24 */ + 46850218726LL, /* nBits= 26 */ + 48266594026LL, /* nBits= 28 */ + 49619579643LL, /* nBits= 30 */ + 50917364029LL, /* nBits= 32 */ + 52166644806LL, /* nBits= 34 */ + 53372970060LL, /* nBits= 36 */ + 54540987228LL, /* nBits= 38 */ + 55674628074LL, /* nBits= 40 */ + 56777248489LL, /* nBits= 42 */ + 57851735733LL, /* nBits= 44 */ + 58900591829LL, /* nBits= 46 */ + 59925999183LL, /* nBits= 48 */ + 60929872812LL, /* nBits= 50 */ + 61913902311LL, /* nBits= 52 */ + 62879585906LL, /* nBits= 54 */ + 63828258303LL, /* nBits= 56 */ + 64761113651LL, /* nBits= 58 */ + 65679224612LL, /* nBits= 60 */ + 66583558300LL, /* nBits= 62 */ + 67474989689LL, /* nBits= 64 */ + 68354312963LL, /* nBits= 66 */ + 69222251158LL, /* nBits= 68 */ + 70079464424LL, /* nBits= 70 */ + 70926557104LL, /* nBits= 72 */ + 71764083859LL, /* nBits= 74 */ + 72592554964LL, /* nBits= 76 */ + 73412440924LL, /* nBits= 78 */ + 74224176502LL, /* nBits= 80 */ + 75028164248LL, /* nBits= 82 */ + 75824777608LL, /* nBits= 84 */ + 76614363661LL, /* nBits= 86 */ + 77397245544LL, /* nBits= 88 */ + 78173724609LL, /* nBits= 90 */ + 78944082332LL, /* nBits= 92 */ + 79708582028LL, /* nBits= 94 */ + 80467470378LL, /* nBits= 96 */ + 81220978804LL, /* nBits= 98 */ + 81969324698LL, /* nBits= 100 */ + 82712712539LL, /* nBits= 102 */ + 83451334890LL, /* nBits= 104 */ + 84185373310LL, /* nBits= 106 */ + 84914999177LL, /* nBits= 108 */ + 85640374433LL, /* nBits= 110 */ + 86361652265LL, /* nBits= 112 */ + 87078977728LL, /* nBits= 114 */ + 87792488305LL, /* nBits= 116 */ + 88502314430LL, /* nBits= 118 */ + 89208579958LL, /* nBits= 120 */ + 89911402603LL, /* nBits= 122 */ + 90610894337LL, /* nBits= 124 */ + 91307161756LL, /* nBits= 126 */ + 92000306419LL, /* nBits= 128 */ + 92690425161LL, /* nBits= 130 */ + 93377610384LL, /* nBits= 132 */ + 94061950317LL, /* nBits= 134 */ + 94743529271LL, /* nBits= 136 */ + 95422427863LL, /* nBits= 138 */ + 96098723229LL, /* nBits= 140 */ + 96772489223LL, /* nBits= 142 */ + 97443796601LL, /* nBits= 144 */ + 98112713190LL, /* nBits= 146 */ + 98779304047LL, /* nBits= 148 */ + 99443631613LL, /* nBits= 150 */ + 100105755844LL, /* nBits= 152 */ + 100765734347LL, /* nBits= 154 */ + 101423622496LL, /* nBits= 156 */ + 102079473553LL, /* nBits= 158 */ + 102733338766LL, /* nBits= 160 */ + 103385267475LL, /* nBits= 162 */ + 104035307204LL, /* nBits= 164 */ + 104683503747LL, /* nBits= 166 */ + 105329901255LL, /* nBits= 168 */ + 105974542310LL, /* nBits= 170 */ + 106617468000LL, /* nBits= 172 */ + 107258717987LL, /* nBits= 174 */ + 107898330575LL, /* nBits= 176 */ + 108536342769LL, /* nBits= 178 */ + 109172790332LL, /* nBits= 180 */ + 109807707843LL, /* nBits= 182 */ + 110441128746LL, /* nBits= 184 */ + 111073085403LL, /* nBits= 186 */ + 111703609134LL, /* nBits= 188 */ + 112332730267LL, /* nBits= 190 */ + 112960478176LL, /* nBits= 192 */ + 113586881323LL, /* nBits= 194 */ + 114211967294LL, /* nBits= 196 */ + 114835762833LL, /* nBits= 198 */ + 115458293880LL, /* nBits= 200 */ + 116079585600LL, /* nBits= 202 */ + 116699662412LL, /* nBits= 204 */ + 117318548024LL, /* nBits= 206 */ + 117936265455LL, /* nBits= 208 */ + 118552837062LL, /* nBits= 210 */ + 119168284567LL, /* nBits= 212 */ + 119782629081LL, /* nBits= 214 */ + 120395891125LL, /* nBits= 216 */ + 121008090654LL, /* nBits= 218 */ + 121619247073LL, /* nBits= 220 */ + 122229379264LL, /* nBits= 222 */ + 122838505598LL, /* nBits= 224 */ + 123446643957LL, /* nBits= 226 */ + 124053811752LL, /* nBits= 228 */ + 124660025936LL, /* nBits= 230 */ + 125265303021LL, /* nBits= 232 */ + 125869659096LL, /* nBits= 234 */ + 126473109838LL, /* nBits= 236 */ + 127075670526LL, /* nBits= 238 */ + 127677356057LL, /* nBits= 240 */ + 128278180958LL, /* nBits= 242 */ + 128878159395LL, /* nBits= 244 */ + 129477305187LL, /* nBits= 246 */ + 130075631820LL, /* nBits= 248 */ + 130673152453LL, /* nBits= 250 */ + 131269879931LL, /* nBits= 252 */ + 131865826793LL, /* nBits= 254 */ + 132461005285LL, /* nBits= 256 */ + 133055427367LL, /* nBits= 258 */ + 133649104720LL, /* nBits= 260 */ + 134242048758LL, /* nBits= 262 */ + 134834270634LL, /* nBits= 264 */ + 135425781249LL, /* nBits= 266 */ + 136016591259LL, /* nBits= 268 */ + 136606711082LL, /* nBits= 270 */ + 137196150905LL, /* nBits= 272 */ + 137784920692LL, /* nBits= 274 */ + 138373030189LL, /* nBits= 276 */ + 138960488930LL, /* nBits= 278 */ + 139547306246LL, /* nBits= 280 */ + 140133491268LL, /* nBits= 282 */ + 140719052932LL, /* nBits= 284 */ + 141303999988LL, /* nBits= 286 */ + 141888341002LL, /* nBits= 288 */ + 142472084362LL, /* nBits= 290 */ + 143055238282LL, /* nBits= 292 */ + 143637810811LL, /* nBits= 294 */ + 144219809832LL, /* nBits= 296 */ + 144801243068LL, /* nBits= 298 */ + 145382118090LL, /* nBits= 300 */ + 145962442314LL, /* nBits= 302 */ + 146542223012LL, /* nBits= 304 */ + 147121467314LL, /* nBits= 306 */ + 147700182207LL, /* nBits= 308 */ + 148278374544LL, /* nBits= 310 */ + 148856051048LL, /* nBits= 312 */ + 149433218310LL, /* nBits= 314 */ + 150009882796LL, /* nBits= 316 */ + 150586050852LL, /* nBits= 318 */ + 151161728701LL, /* nBits= 320 */ + 151736922453LL, /* nBits= 322 */ + 152311638102LL, /* nBits= 324 */ + 152885881533LL, /* nBits= 326 */ + 153459658523LL, /* nBits= 328 */ + 154032974742LL, /* nBits= 330 */ + 154605835758LL, /* nBits= 332 */ + 155178247040LL, /* nBits= 334 */ + 155750213958LL, /* nBits= 336 */ + 156321741786LL, /* nBits= 338 */ + 156892835705LL, /* nBits= 340 */ + 157463500804LL, /* nBits= 342 */ + 158033742086LL, /* nBits= 344 */ + 158603564463LL, /* nBits= 346 */ + 159172972765LL, /* nBits= 348 */ + 159741971737LL, /* nBits= 350 */ + 160310566045LL, /* nBits= 352 */ + 160878760273LL, /* nBits= 354 */ + 161446558930LL, /* nBits= 356 */ + 162013966448LL, /* nBits= 358 */ + 162580987185LL, /* nBits= 360 */ + 163147625426LL, /* nBits= 362 */ + 163713885388LL, /* nBits= 364 */ + 164279771214LL, /* nBits= 366 */ + 164845286983LL, /* nBits= 368 */ + 165410436707LL, /* nBits= 370 */ + 165975224331LL, /* nBits= 372 */ + 166539653740LL, /* nBits= 374 */ + 167103728754LL, /* nBits= 376 */ + 167667453134LL, /* nBits= 378 */ + 168230830579LL, /* nBits= 380 */ + 168793864733LL, /* nBits= 382 */ + 169356559180LL, /* nBits= 384 */ + 169918917451LL, /* nBits= 386 */ + 170480943019LL, /* nBits= 388 */ + 171042639306LL, /* nBits= 390 */ + 171604009681LL, /* nBits= 392 */ + 172165057461LL, /* nBits= 394 */ + 172725785912LL, /* nBits= 396 */ + 173286198253LL, /* nBits= 398 */ + 173846297651LL, /* nBits= 400 */ + 174406087229LL, /* nBits= 402 */ + 174965570062LL, /* nBits= 404 */ + 175524749180LL, /* nBits= 406 */ + 176083627567LL, /* nBits= 408 */ + 176642208165LL, /* nBits= 410 */ + 177200493871LL, /* nBits= 412 */ + 177758487542LL, /* nBits= 414 */ + 178316191993LL, /* nBits= 416 */ + 178873609998LL, /* nBits= 418 */ + 179430744292LL, /* nBits= 420 */ + 179987597569LL, /* nBits= 422 */ + 180544172489LL, /* nBits= 424 */ + 181100471670LL, /* nBits= 426 */ + 181656497695LL, /* nBits= 428 */ + 182212253111LL, /* nBits= 430 */ + 182767740431LL, /* nBits= 432 */ + 183322962130LL, /* nBits= 434 */ + 183877920651LL, /* nBits= 436 */ + 184432618403LL, /* nBits= 438 */ + 184987057762LL, /* nBits= 440 */ + 185541241072LL, /* nBits= 442 */ + 186095170645LL, /* nBits= 444 */ + 186648848761LL, /* nBits= 446 */ + 187202277670LL, /* nBits= 448 */ + 187755459594LL, /* nBits= 450 */ + 188308396722LL, /* nBits= 452 */ + 188861091216LL, /* nBits= 454 */ + 189413545209LL, /* nBits= 456 */ + 189965760805LL, /* nBits= 458 */ + 190517740084LL, /* nBits= 460 */ + 191069485094LL, /* nBits= 462 */ + 191620997861LL, /* nBits= 464 */ + 192172280381LL, /* nBits= 466 */ + 192723334628LL, /* nBits= 468 */ + 193274162547LL, /* nBits= 470 */ + 193824766061LL, /* nBits= 472 */ + 194375147068LL, /* nBits= 474 */ + 194925307441LL, /* nBits= 476 */ + 195475249031LL, /* nBits= 478 */ + 196024973664LL, /* nBits= 480 */ + 196574483146LL, /* nBits= 482 */ + 197123779257LL, /* nBits= 484 */ + 197672863757LL, /* nBits= 486 */ + 198221738385LL, /* nBits= 488 */ + 198770404857LL, /* nBits= 490 */ + 199318864870LL, /* nBits= 492 */ + 199867120097LL, /* nBits= 494 */ + 200415172195LL, /* nBits= 496 */ + 200963022797LL, /* nBits= 498 */ + 201510673519LL, /* nBits= 500 */ + 202058125957LL, /* nBits= 502 */ + 202605381688LL, /* nBits= 504 */ + 203152442270LL, /* nBits= 506 */ + 203699309243LL, /* nBits= 508 */ + 204245984127LL, /* nBits= 510 */ + 204792468427LL, /* nBits= 512 */ + 205338763628LL, /* nBits= 514 */ + 205884871200LL, /* nBits= 516 */ + 206430792594LL, /* nBits= 518 */ + 206976529245LL, /* nBits= 520 */ + 207522082571LL, /* nBits= 522 */ + 208067453975LL, /* nBits= 524 */ + 208612644842LL, /* nBits= 526 */ + 209157656543LL, /* nBits= 528 */ + 209702490432LL, /* nBits= 530 */ + 210247147850LL, /* nBits= 532 */ + 210791630120LL, /* nBits= 534 */ + 211335938551LL, /* nBits= 536 */ + 211880074440LL, /* nBits= 538 */ + 212424039066LL, /* nBits= 540 */ + 212967833696LL, /* nBits= 542 */ + 213511459581LL, /* nBits= 544 */ + 214054917961LL, /* nBits= 546 */ + 214598210060LL, /* nBits= 548 */ + 215141337089LL, /* nBits= 550 */ + 215684300248LL, /* nBits= 552 */ + 216227100721LL, /* nBits= 554 */ + 216769739681LL, /* nBits= 556 */ + 217312218288LL, /* nBits= 558 */ + 217854537689LL, /* nBits= 560 */ + 218396699020LL, /* nBits= 562 */ + 218938703403LL, /* nBits= 564 */ + 219480551949LL, /* nBits= 566 */ + 220022245759LL, /* nBits= 568 */ + 220563785919LL, /* nBits= 570 */ + 221105173507LL, /* nBits= 572 */ + 221646409586LL, /* nBits= 574 */ + 222187495212LL, /* nBits= 576 */ + 222728431427LL, /* nBits= 578 */ + 223269219263LL, /* nBits= 580 */ + 223809859743LL, /* nBits= 582 */ + 224350353876LL, /* nBits= 584 */ + 224890702664LL, /* nBits= 586 */ + 225430907097LL, /* nBits= 588 */ + 225970968155LL, /* nBits= 590 */ + 226510886809LL, /* nBits= 592 */ + 227050664020LL, /* nBits= 594 */ + 227590300737LL, /* nBits= 596 */ + 228129797904LL, /* nBits= 598 */ + 228669156450LL, /* nBits= 600 */ + 229208377300LL, /* nBits= 602 */ + 229747461366LL, /* nBits= 604 */ + 230286409553LL, /* nBits= 606 */ + 230825222757LL, /* nBits= 608 */ + 231363901863LL, /* nBits= 610 */ + 231902447750LL, /* nBits= 612 */ + 232440861287LL, /* nBits= 614 */ + 232979143334LL, /* nBits= 616 */ + 233517294746LL, /* nBits= 618 */ + 234055316364LL, /* nBits= 620 */ + 234593209026LL, /* nBits= 622 */ + 235130973559LL, /* nBits= 624 */ + 235668610784LL, /* nBits= 626 */ + 236206121513LL, /* nBits= 628 */ + 236743506550LL, /* nBits= 630 */ + 237280766691LL, /* nBits= 632 */ + 237817902727LL, /* nBits= 634 */ + 238354915439LL, /* nBits= 636 */ + 238891805601LL, /* nBits= 638 */ + 239428573980LL, /* nBits= 640 */ + 239965221336LL, /* nBits= 642 */ + 240501748423LL, /* nBits= 644 */ + 241038155986LL, /* nBits= 646 */ + 241574444764LL, /* nBits= 648 */ + 242110615490LL, /* nBits= 650 */ + 242646668887LL, /* nBits= 652 */ + 243182605676LL, /* nBits= 654 */ + 243718426569LL, /* nBits= 656 */ + 244254132270LL, /* nBits= 658 */ + 244789723479LL, /* nBits= 660 */ + 245325200890LL, /* nBits= 662 */ + 245860565188LL, /* nBits= 664 */ + 246395817053LL, /* nBits= 666 */ + 246930957161LL, /* nBits= 668 */ + 247465986180LL, /* nBits= 670 */ + 248000904771LL, /* nBits= 672 */ + 248535713591LL, /* nBits= 674 */ + 249070413291LL, /* nBits= 676 */ + 249605004514LL, /* nBits= 678 */ + 250139487901LL, /* nBits= 680 */ + 250673864085LL, /* nBits= 682 */ + 251208133693LL, /* nBits= 684 */ + 251742297348LL, /* nBits= 686 */ + 252276355666LL, /* nBits= 688 */ + 252810309260LL, /* nBits= 690 */ + 253344158735LL, /* nBits= 692 */ + 253877904693LL, /* nBits= 694 */ + 254411547729LL, /* nBits= 696 */ + 254945088434LL, /* nBits= 698 */ + 255478527393LL, /* nBits= 700 */ + 256011865187LL, /* nBits= 702 */ + 256545102392LL, /* nBits= 704 */ + 257078239579LL, /* nBits= 706 */ + 257611277312LL, /* nBits= 708 */ + 258144216154LL, /* nBits= 710 */ + 258677056661LL, /* nBits= 712 */ + 259209799384LL, /* nBits= 714 */ + 259742444871LL, /* nBits= 716 */ + 260274993663LL, /* nBits= 718 */ + 260807446299LL, /* nBits= 720 */ + 261339803313LL, /* nBits= 722 */ + 261872065233LL, /* nBits= 724 */ + 262404232584LL, /* nBits= 726 */ + 262936305886LL, /* nBits= 728 */ + 263468285655LL, /* nBits= 730 */ + 264000172404LL, /* nBits= 732 */ + 264531966639LL, /* nBits= 734 */ + 265063668865LL, /* nBits= 736 */ + 265595279580LL, /* nBits= 738 */ + 266126799280LL, /* nBits= 740 */ + 266658228457LL, /* nBits= 742 */ + 267189567597LL, /* nBits= 744 */ + 267720817184LL, /* nBits= 746 */ + 268251977697LL, /* nBits= 748 */ + 268783049613LL, /* nBits= 750 */ + 269314033403LL, /* nBits= 752 */ + 269844929535LL, /* nBits= 754 */ + 270375738474LL, /* nBits= 756 */ + 270906460681LL, /* nBits= 758 */ + 271437096611LL, /* nBits= 760 */ + 271967646720LL, /* nBits= 762 */ + 272498111457LL, /* nBits= 764 */ + 273028491268LL, /* nBits= 766 */ + 273558786596LL, /* nBits= 768 */ + 274088997881LL, /* nBits= 770 */ + 274619125558LL, /* nBits= 772 */ + 275149170061LL, /* nBits= 774 */ + 275679131819LL, /* nBits= 776 */ + 276209011256LL, /* nBits= 778 */ + 276738808798LL, /* nBits= 780 */ + 277268524862LL, /* nBits= 782 */ + 277798159864LL, /* nBits= 784 */ + 278327714219LL, /* nBits= 786 */ + 278857188336LL, /* nBits= 788 */ + 279386582621LL, /* nBits= 790 */ + 279915897479LL, /* nBits= 792 */ + 280445133310LL, /* nBits= 794 */ + 280974290511LL, /* nBits= 796 */ + 281503369478LL, /* nBits= 798 */ + 282032370602LL, /* nBits= 800 */ + 282561294271LL, /* nBits= 802 */ + 283090140872LL, /* nBits= 804 */ + 283618910787LL, /* nBits= 806 */ + 284147604396LL, /* nBits= 808 */ + 284676222078LL, /* nBits= 810 */ + 285204764206LL, /* nBits= 812 */ + 285733231152LL, /* nBits= 814 */ + 286261623285LL, /* nBits= 816 */ + 286789940971LL, /* nBits= 818 */ + 287318184574LL, /* nBits= 820 */ + 287846354455LL, /* nBits= 822 */ + 288374450972LL, /* nBits= 824 */ + 288902474481LL, /* nBits= 826 */ + 289430425335LL, /* nBits= 828 */ + 289958303885LL, /* nBits= 830 */ + 290486110478LL, /* nBits= 832 */ + 291013845460LL, /* nBits= 834 */ + 291541509175LL, /* nBits= 836 */ + 292069101962LL, /* nBits= 838 */ + 292596624160LL, /* nBits= 840 */ + 293124076105LL, /* nBits= 842 */ + 293651458129LL, /* nBits= 844 */ + 294178770565LL, /* nBits= 846 */ + 294706013741LL, /* nBits= 848 */ + 295233187982LL, /* nBits= 850 */ + 295760293613LL, /* nBits= 852 */ + 296287330956LL, /* nBits= 854 */ + 296814300330LL, /* nBits= 856 */ + 297341202053LL, /* nBits= 858 */ + 297868036439LL, /* nBits= 860 */ + 298394803801LL, /* nBits= 862 */ + 298921504450LL, /* nBits= 864 */ + 299448138694LL, /* nBits= 866 */ + 299974706841LL, /* nBits= 868 */ + 300501209193LL, /* nBits= 870 */ + 301027646054LL, /* nBits= 872 */ + 301554017722LL, /* nBits= 874 */ + 302080324498LL, /* nBits= 876 */ + 302606566675LL, /* nBits= 878 */ + 303132744548LL, /* nBits= 880 */ + 303658858410LL, /* nBits= 882 */ + 304184908550LL, /* nBits= 884 */ + 304710895256LL, /* nBits= 886 */ + 305236818814LL, /* nBits= 888 */ + 305762679509LL, /* nBits= 890 */ + 306288477622LL, /* nBits= 892 */ + 306814213434LL, /* nBits= 894 */ + 307339887224LL, /* nBits= 896 */ + 307865499267LL, /* nBits= 898 */ + 308391049839LL, /* nBits= 900 */ + 308916539213LL, /* nBits= 902 */ + 309441967659LL, /* nBits= 904 */ + 309967335447LL, /* nBits= 906 */ + 310492642844LL, /* nBits= 908 */ + 311017890117LL, /* nBits= 910 */ + 311543077529LL, /* nBits= 912 */ + 312068205342LL, /* nBits= 914 */ + 312593273818LL, /* nBits= 916 */ + 313118283214LL, /* nBits= 918 */ + 313643233788LL, /* nBits= 920 */ + 314168125796LL, /* nBits= 922 */ + 314692959490LL, /* nBits= 924 */ + 315217735125LL, /* nBits= 926 */ + 315742452949LL, /* nBits= 928 */ + 316267113212LL, /* nBits= 930 */ + 316791716161LL, /* nBits= 932 */ + 317316262042LL, /* nBits= 934 */ + 317840751099LL, /* nBits= 936 */ + 318365183575LL, /* nBits= 938 */ + 318889559710LL, /* nBits= 940 */ + 319413879744LL, /* nBits= 942 */ + 319938143916LL, /* nBits= 944 */ + 320462352461LL, /* nBits= 946 */ + 320986505614LL, /* nBits= 948 */ + 321510603610LL, /* nBits= 950 */ + 322034646679LL, /* nBits= 952 */ + 322558635054LL, /* nBits= 954 */ + 323082568961LL, /* nBits= 956 */ + 323606448630LL, /* nBits= 958 */ + 324130274286LL, /* nBits= 960 */ + 324654046155LL, /* nBits= 962 */ + 325177764460LL, /* nBits= 964 */ + 325701429422LL, /* nBits= 966 */ + 326225041262LL, /* nBits= 968 */ + 326748600201LL, /* nBits= 970 */ + 327272106455LL, /* nBits= 972 */ + 327795560241LL, /* nBits= 974 */ + 328318961774LL, /* nBits= 976 */ + 328842311269LL, /* nBits= 978 */ + 329365608938LL, /* nBits= 980 */ + 329888854993LL, /* nBits= 982 */ + 330412049642LL, /* nBits= 984 */ + 330935193096LL, /* nBits= 986 */ + 331458285562LL, /* nBits= 988 */ + 331981327245LL, /* nBits= 990 */ + 332504318351LL, /* nBits= 992 */ + 333027259083LL, /* nBits= 994 */ + 333550149645LL, /* nBits= 996 */ + 334072990237LL, /* nBits= 998 */ + 334595781059LL, /* nBits=1000 */ + 335118522311LL, /* nBits=1002 */ + 335641214189LL, /* nBits=1004 */ + 336163856891LL, /* nBits=1006 */ + 336686450612LL, /* nBits=1008 */ + 337208995546LL, /* nBits=1010 */ + 337731491886LL, /* nBits=1012 */ + 338253939823LL, /* nBits=1014 */ + 338776339550LL, /* nBits=1016 */ + 339298691254LL, /* nBits=1018 */ + 339820995126LL, /* nBits=1020 */ + 340343251351LL, /* nBits=1022 */ +}; + +#endif // BITCOIN_ASERT_TABLE_H diff --git a/electrum/asert/asert_table.py b/electrum/asert/asert_table.py new file mode 100644 index 000000000..c39d50d17 --- /dev/null +++ b/electrum/asert/asert_table.py @@ -0,0 +1,517 @@ +"""ASERT log2(compute) lookup table — generated from asert_table.h.""" +# Generated by gen_asert_table.py. Do not edit by hand. +# Source of truth: electrum/asert/asert_table.h (verbatim from FACTOR). + +LOG2_COMPUTE_TABLE: tuple[int, ...] = ( + 9087915284, # nBits= 2 + 18175830568, # nBits= 4 + 23698600879, # nBits= 6 + 27761726543, # nBits= 8 + 31025048513, # nBits= 10 + 33782477547, # nBits= 12 + 36190794592, # nBits= 14 + 38343583902, # nBits= 16 + 40301209242, # nBits= 18 + 42104886564, # nBits= 20 + 43784013531, # nBits= 22 + 45360296289, # nBits= 24 + 46850218726, # nBits= 26 + 48266594026, # nBits= 28 + 49619579643, # nBits= 30 + 50917364029, # nBits= 32 + 52166644806, # nBits= 34 + 53372970060, # nBits= 36 + 54540987228, # nBits= 38 + 55674628074, # nBits= 40 + 56777248489, # nBits= 42 + 57851735733, # nBits= 44 + 58900591829, # nBits= 46 + 59925999183, # nBits= 48 + 60929872812, # nBits= 50 + 61913902311, # nBits= 52 + 62879585906, # nBits= 54 + 63828258303, # nBits= 56 + 64761113651, # nBits= 58 + 65679224612, # nBits= 60 + 66583558300, # nBits= 62 + 67474989689, # nBits= 64 + 68354312963, # nBits= 66 + 69222251158, # nBits= 68 + 70079464424, # nBits= 70 + 70926557104, # nBits= 72 + 71764083859, # nBits= 74 + 72592554964, # nBits= 76 + 73412440924, # nBits= 78 + 74224176502, # nBits= 80 + 75028164248, # nBits= 82 + 75824777608, # nBits= 84 + 76614363661, # nBits= 86 + 77397245544, # nBits= 88 + 78173724609, # nBits= 90 + 78944082332, # nBits= 92 + 79708582028, # nBits= 94 + 80467470378, # nBits= 96 + 81220978804, # nBits= 98 + 81969324698, # nBits= 100 + 82712712539, # nBits= 102 + 83451334890, # nBits= 104 + 84185373310, # nBits= 106 + 84914999177, # nBits= 108 + 85640374433, # nBits= 110 + 86361652265, # nBits= 112 + 87078977728, # nBits= 114 + 87792488305, # nBits= 116 + 88502314430, # nBits= 118 + 89208579958, # nBits= 120 + 89911402603, # nBits= 122 + 90610894337, # nBits= 124 + 91307161756, # nBits= 126 + 92000306419, # nBits= 128 + 92690425161, # nBits= 130 + 93377610384, # nBits= 132 + 94061950317, # nBits= 134 + 94743529271, # nBits= 136 + 95422427863, # nBits= 138 + 96098723229, # nBits= 140 + 96772489223, # nBits= 142 + 97443796601, # nBits= 144 + 98112713190, # nBits= 146 + 98779304047, # nBits= 148 + 99443631613, # nBits= 150 + 100105755844, # nBits= 152 + 100765734347, # nBits= 154 + 101423622496, # nBits= 156 + 102079473553, # nBits= 158 + 102733338766, # nBits= 160 + 103385267475, # nBits= 162 + 104035307204, # nBits= 164 + 104683503747, # nBits= 166 + 105329901255, # nBits= 168 + 105974542310, # nBits= 170 + 106617468000, # nBits= 172 + 107258717987, # nBits= 174 + 107898330575, # nBits= 176 + 108536342769, # nBits= 178 + 109172790332, # nBits= 180 + 109807707843, # nBits= 182 + 110441128746, # nBits= 184 + 111073085403, # nBits= 186 + 111703609134, # nBits= 188 + 112332730267, # nBits= 190 + 112960478176, # nBits= 192 + 113586881323, # nBits= 194 + 114211967294, # nBits= 196 + 114835762833, # nBits= 198 + 115458293880, # nBits= 200 + 116079585600, # nBits= 202 + 116699662412, # nBits= 204 + 117318548024, # nBits= 206 + 117936265455, # nBits= 208 + 118552837062, # nBits= 210 + 119168284567, # nBits= 212 + 119782629081, # nBits= 214 + 120395891125, # nBits= 216 + 121008090654, # nBits= 218 + 121619247073, # nBits= 220 + 122229379264, # nBits= 222 + 122838505598, # nBits= 224 + 123446643957, # nBits= 226 + 124053811752, # nBits= 228 + 124660025936, # nBits= 230 + 125265303021, # nBits= 232 + 125869659096, # nBits= 234 + 126473109838, # nBits= 236 + 127075670526, # nBits= 238 + 127677356057, # nBits= 240 + 128278180958, # nBits= 242 + 128878159395, # nBits= 244 + 129477305187, # nBits= 246 + 130075631820, # nBits= 248 + 130673152453, # nBits= 250 + 131269879931, # nBits= 252 + 131865826793, # nBits= 254 + 132461005285, # nBits= 256 + 133055427367, # nBits= 258 + 133649104720, # nBits= 260 + 134242048758, # nBits= 262 + 134834270634, # nBits= 264 + 135425781249, # nBits= 266 + 136016591259, # nBits= 268 + 136606711082, # nBits= 270 + 137196150905, # nBits= 272 + 137784920692, # nBits= 274 + 138373030189, # nBits= 276 + 138960488930, # nBits= 278 + 139547306246, # nBits= 280 + 140133491268, # nBits= 282 + 140719052932, # nBits= 284 + 141303999988, # nBits= 286 + 141888341002, # nBits= 288 + 142472084362, # nBits= 290 + 143055238282, # nBits= 292 + 143637810811, # nBits= 294 + 144219809832, # nBits= 296 + 144801243068, # nBits= 298 + 145382118090, # nBits= 300 + 145962442314, # nBits= 302 + 146542223012, # nBits= 304 + 147121467314, # nBits= 306 + 147700182207, # nBits= 308 + 148278374544, # nBits= 310 + 148856051048, # nBits= 312 + 149433218310, # nBits= 314 + 150009882796, # nBits= 316 + 150586050852, # nBits= 318 + 151161728701, # nBits= 320 + 151736922453, # nBits= 322 + 152311638102, # nBits= 324 + 152885881533, # nBits= 326 + 153459658523, # nBits= 328 + 154032974742, # nBits= 330 + 154605835758, # nBits= 332 + 155178247040, # nBits= 334 + 155750213958, # nBits= 336 + 156321741786, # nBits= 338 + 156892835705, # nBits= 340 + 157463500804, # nBits= 342 + 158033742086, # nBits= 344 + 158603564463, # nBits= 346 + 159172972765, # nBits= 348 + 159741971737, # nBits= 350 + 160310566045, # nBits= 352 + 160878760273, # nBits= 354 + 161446558930, # nBits= 356 + 162013966448, # nBits= 358 + 162580987185, # nBits= 360 + 163147625426, # nBits= 362 + 163713885388, # nBits= 364 + 164279771214, # nBits= 366 + 164845286983, # nBits= 368 + 165410436707, # nBits= 370 + 165975224331, # nBits= 372 + 166539653740, # nBits= 374 + 167103728754, # nBits= 376 + 167667453134, # nBits= 378 + 168230830579, # nBits= 380 + 168793864733, # nBits= 382 + 169356559180, # nBits= 384 + 169918917451, # nBits= 386 + 170480943019, # nBits= 388 + 171042639306, # nBits= 390 + 171604009681, # nBits= 392 + 172165057461, # nBits= 394 + 172725785912, # nBits= 396 + 173286198253, # nBits= 398 + 173846297651, # nBits= 400 + 174406087229, # nBits= 402 + 174965570062, # nBits= 404 + 175524749180, # nBits= 406 + 176083627567, # nBits= 408 + 176642208165, # nBits= 410 + 177200493871, # nBits= 412 + 177758487542, # nBits= 414 + 178316191993, # nBits= 416 + 178873609998, # nBits= 418 + 179430744292, # nBits= 420 + 179987597569, # nBits= 422 + 180544172489, # nBits= 424 + 181100471670, # nBits= 426 + 181656497695, # nBits= 428 + 182212253111, # nBits= 430 + 182767740431, # nBits= 432 + 183322962130, # nBits= 434 + 183877920651, # nBits= 436 + 184432618403, # nBits= 438 + 184987057762, # nBits= 440 + 185541241072, # nBits= 442 + 186095170645, # nBits= 444 + 186648848761, # nBits= 446 + 187202277670, # nBits= 448 + 187755459594, # nBits= 450 + 188308396722, # nBits= 452 + 188861091216, # nBits= 454 + 189413545209, # nBits= 456 + 189965760805, # nBits= 458 + 190517740084, # nBits= 460 + 191069485094, # nBits= 462 + 191620997861, # nBits= 464 + 192172280381, # nBits= 466 + 192723334628, # nBits= 468 + 193274162547, # nBits= 470 + 193824766061, # nBits= 472 + 194375147068, # nBits= 474 + 194925307441, # nBits= 476 + 195475249031, # nBits= 478 + 196024973664, # nBits= 480 + 196574483146, # nBits= 482 + 197123779257, # nBits= 484 + 197672863757, # nBits= 486 + 198221738385, # nBits= 488 + 198770404857, # nBits= 490 + 199318864870, # nBits= 492 + 199867120097, # nBits= 494 + 200415172195, # nBits= 496 + 200963022797, # nBits= 498 + 201510673519, # nBits= 500 + 202058125957, # nBits= 502 + 202605381688, # nBits= 504 + 203152442270, # nBits= 506 + 203699309243, # nBits= 508 + 204245984127, # nBits= 510 + 204792468427, # nBits= 512 + 205338763628, # nBits= 514 + 205884871200, # nBits= 516 + 206430792594, # nBits= 518 + 206976529245, # nBits= 520 + 207522082571, # nBits= 522 + 208067453975, # nBits= 524 + 208612644842, # nBits= 526 + 209157656543, # nBits= 528 + 209702490432, # nBits= 530 + 210247147850, # nBits= 532 + 210791630120, # nBits= 534 + 211335938551, # nBits= 536 + 211880074440, # nBits= 538 + 212424039066, # nBits= 540 + 212967833696, # nBits= 542 + 213511459581, # nBits= 544 + 214054917961, # nBits= 546 + 214598210060, # nBits= 548 + 215141337089, # nBits= 550 + 215684300248, # nBits= 552 + 216227100721, # nBits= 554 + 216769739681, # nBits= 556 + 217312218288, # nBits= 558 + 217854537689, # nBits= 560 + 218396699020, # nBits= 562 + 218938703403, # nBits= 564 + 219480551949, # nBits= 566 + 220022245759, # nBits= 568 + 220563785919, # nBits= 570 + 221105173507, # nBits= 572 + 221646409586, # nBits= 574 + 222187495212, # nBits= 576 + 222728431427, # nBits= 578 + 223269219263, # nBits= 580 + 223809859743, # nBits= 582 + 224350353876, # nBits= 584 + 224890702664, # nBits= 586 + 225430907097, # nBits= 588 + 225970968155, # nBits= 590 + 226510886809, # nBits= 592 + 227050664020, # nBits= 594 + 227590300737, # nBits= 596 + 228129797904, # nBits= 598 + 228669156450, # nBits= 600 + 229208377300, # nBits= 602 + 229747461366, # nBits= 604 + 230286409553, # nBits= 606 + 230825222757, # nBits= 608 + 231363901863, # nBits= 610 + 231902447750, # nBits= 612 + 232440861287, # nBits= 614 + 232979143334, # nBits= 616 + 233517294746, # nBits= 618 + 234055316364, # nBits= 620 + 234593209026, # nBits= 622 + 235130973559, # nBits= 624 + 235668610784, # nBits= 626 + 236206121513, # nBits= 628 + 236743506550, # nBits= 630 + 237280766691, # nBits= 632 + 237817902727, # nBits= 634 + 238354915439, # nBits= 636 + 238891805601, # nBits= 638 + 239428573980, # nBits= 640 + 239965221336, # nBits= 642 + 240501748423, # nBits= 644 + 241038155986, # nBits= 646 + 241574444764, # nBits= 648 + 242110615490, # nBits= 650 + 242646668887, # nBits= 652 + 243182605676, # nBits= 654 + 243718426569, # nBits= 656 + 244254132270, # nBits= 658 + 244789723479, # nBits= 660 + 245325200890, # nBits= 662 + 245860565188, # nBits= 664 + 246395817053, # nBits= 666 + 246930957161, # nBits= 668 + 247465986180, # nBits= 670 + 248000904771, # nBits= 672 + 248535713591, # nBits= 674 + 249070413291, # nBits= 676 + 249605004514, # nBits= 678 + 250139487901, # nBits= 680 + 250673864085, # nBits= 682 + 251208133693, # nBits= 684 + 251742297348, # nBits= 686 + 252276355666, # nBits= 688 + 252810309260, # nBits= 690 + 253344158735, # nBits= 692 + 253877904693, # nBits= 694 + 254411547729, # nBits= 696 + 254945088434, # nBits= 698 + 255478527393, # nBits= 700 + 256011865187, # nBits= 702 + 256545102392, # nBits= 704 + 257078239579, # nBits= 706 + 257611277312, # nBits= 708 + 258144216154, # nBits= 710 + 258677056661, # nBits= 712 + 259209799384, # nBits= 714 + 259742444871, # nBits= 716 + 260274993663, # nBits= 718 + 260807446299, # nBits= 720 + 261339803313, # nBits= 722 + 261872065233, # nBits= 724 + 262404232584, # nBits= 726 + 262936305886, # nBits= 728 + 263468285655, # nBits= 730 + 264000172404, # nBits= 732 + 264531966639, # nBits= 734 + 265063668865, # nBits= 736 + 265595279580, # nBits= 738 + 266126799280, # nBits= 740 + 266658228457, # nBits= 742 + 267189567597, # nBits= 744 + 267720817184, # nBits= 746 + 268251977697, # nBits= 748 + 268783049613, # nBits= 750 + 269314033403, # nBits= 752 + 269844929535, # nBits= 754 + 270375738474, # nBits= 756 + 270906460681, # nBits= 758 + 271437096611, # nBits= 760 + 271967646720, # nBits= 762 + 272498111457, # nBits= 764 + 273028491268, # nBits= 766 + 273558786596, # nBits= 768 + 274088997881, # nBits= 770 + 274619125558, # nBits= 772 + 275149170061, # nBits= 774 + 275679131819, # nBits= 776 + 276209011256, # nBits= 778 + 276738808798, # nBits= 780 + 277268524862, # nBits= 782 + 277798159864, # nBits= 784 + 278327714219, # nBits= 786 + 278857188336, # nBits= 788 + 279386582621, # nBits= 790 + 279915897479, # nBits= 792 + 280445133310, # nBits= 794 + 280974290511, # nBits= 796 + 281503369478, # nBits= 798 + 282032370602, # nBits= 800 + 282561294271, # nBits= 802 + 283090140872, # nBits= 804 + 283618910787, # nBits= 806 + 284147604396, # nBits= 808 + 284676222078, # nBits= 810 + 285204764206, # nBits= 812 + 285733231152, # nBits= 814 + 286261623285, # nBits= 816 + 286789940971, # nBits= 818 + 287318184574, # nBits= 820 + 287846354455, # nBits= 822 + 288374450972, # nBits= 824 + 288902474481, # nBits= 826 + 289430425335, # nBits= 828 + 289958303885, # nBits= 830 + 290486110478, # nBits= 832 + 291013845460, # nBits= 834 + 291541509175, # nBits= 836 + 292069101962, # nBits= 838 + 292596624160, # nBits= 840 + 293124076105, # nBits= 842 + 293651458129, # nBits= 844 + 294178770565, # nBits= 846 + 294706013741, # nBits= 848 + 295233187982, # nBits= 850 + 295760293613, # nBits= 852 + 296287330956, # nBits= 854 + 296814300330, # nBits= 856 + 297341202053, # nBits= 858 + 297868036439, # nBits= 860 + 298394803801, # nBits= 862 + 298921504450, # nBits= 864 + 299448138694, # nBits= 866 + 299974706841, # nBits= 868 + 300501209193, # nBits= 870 + 301027646054, # nBits= 872 + 301554017722, # nBits= 874 + 302080324498, # nBits= 876 + 302606566675, # nBits= 878 + 303132744548, # nBits= 880 + 303658858410, # nBits= 882 + 304184908550, # nBits= 884 + 304710895256, # nBits= 886 + 305236818814, # nBits= 888 + 305762679509, # nBits= 890 + 306288477622, # nBits= 892 + 306814213434, # nBits= 894 + 307339887224, # nBits= 896 + 307865499267, # nBits= 898 + 308391049839, # nBits= 900 + 308916539213, # nBits= 902 + 309441967659, # nBits= 904 + 309967335447, # nBits= 906 + 310492642844, # nBits= 908 + 311017890117, # nBits= 910 + 311543077529, # nBits= 912 + 312068205342, # nBits= 914 + 312593273818, # nBits= 916 + 313118283214, # nBits= 918 + 313643233788, # nBits= 920 + 314168125796, # nBits= 922 + 314692959490, # nBits= 924 + 315217735125, # nBits= 926 + 315742452949, # nBits= 928 + 316267113212, # nBits= 930 + 316791716161, # nBits= 932 + 317316262042, # nBits= 934 + 317840751099, # nBits= 936 + 318365183575, # nBits= 938 + 318889559710, # nBits= 940 + 319413879744, # nBits= 942 + 319938143916, # nBits= 944 + 320462352461, # nBits= 946 + 320986505614, # nBits= 948 + 321510603610, # nBits= 950 + 322034646679, # nBits= 952 + 322558635054, # nBits= 954 + 323082568961, # nBits= 956 + 323606448630, # nBits= 958 + 324130274286, # nBits= 960 + 324654046155, # nBits= 962 + 325177764460, # nBits= 964 + 325701429422, # nBits= 966 + 326225041262, # nBits= 968 + 326748600201, # nBits= 970 + 327272106455, # nBits= 972 + 327795560241, # nBits= 974 + 328318961774, # nBits= 976 + 328842311269, # nBits= 978 + 329365608938, # nBits= 980 + 329888854993, # nBits= 982 + 330412049642, # nBits= 984 + 330935193096, # nBits= 986 + 331458285562, # nBits= 988 + 331981327245, # nBits= 990 + 332504318351, # nBits= 992 + 333027259083, # nBits= 994 + 333550149645, # nBits= 996 + 334072990237, # nBits= 998 + 334595781059, # nBits=1000 + 335118522311, # nBits=1002 + 335641214189, # nBits=1004 + 336163856891, # nBits=1006 + 336686450612, # nBits=1008 + 337208995546, # nBits=1010 + 337731491886, # nBits=1012 + 338253939823, # nBits=1014 + 338776339550, # nBits=1016 + 339298691254, # nBits=1018 + 339820995126, # nBits=1020 + 340343251351, # nBits=1022 +) diff --git a/electrum/asert/gen_asert_table.py b/electrum/asert/gen_asert_table.py new file mode 100644 index 000000000..3edc75a99 --- /dev/null +++ b/electrum/asert/gen_asert_table.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Convert asert_table.h (C++) into asert_table.py (Python). + +Parses the 511 ``int64_t`` literals inside ``LOG2_COMPUTE_TABLE`` and emits a +Python module exposing them as ``LOG2_COMPUTE_TABLE: tuple[int, ...]``. The +math itself is owned by FACTOR's scripts/gen_compute_table.py — this script +only re-shapes the already-computed integers. + +Re-run after pulling a new asert_table.h from FACTOR: + python3 electrum/asert/gen_asert_table.py +""" +import os +import re + + +HERE = os.path.dirname(os.path.abspath(__file__)) +HEADER_PATH = os.path.join(HERE, "asert_table.h") +OUTPUT_PATH = os.path.join(HERE, "asert_table.py") +EXPECTED_ENTRIES = 511 + + +def load_table(header_path: str) -> list[int]: + table: list[int] = [] + in_array = False + with open(header_path, "r") as f: + for line in f: + if "LOG2_COMPUTE_TABLE" in line and "{" in line: + in_array = True + continue + if not in_array: + continue + if "};" in line: + break + for m in re.finditer(r"(-?\d+)LL", line): + table.append(int(m.group(1))) + if len(table) != EXPECTED_ENTRIES: + raise SystemExit( + f"Expected {EXPECTED_ENTRIES} entries in {header_path}, " + f"got {len(table)}" + ) + return table + + +def emit_python(table: list[int]) -> str: + lines = [ + '"""ASERT log2(compute) lookup table — generated from asert_table.h."""', + "# Generated by gen_asert_table.py. Do not edit by hand.", + "# Source of truth: electrum/asert/asert_table.h (verbatim from FACTOR).", + "", + "LOG2_COMPUTE_TABLE: tuple[int, ...] = (", + ] + for i, value in enumerate(table): + nbits = 2 * (i + 1) + lines.append(f" {value:>20}, # nBits={nbits:>4d}") + lines.append(")") + lines.append("") + return "\n".join(lines) + + +def main() -> None: + table = load_table(HEADER_PATH) + output = emit_python(table) + with open(OUTPUT_PATH, "w") as f: + f.write(output) + print(f"Wrote {OUTPUT_PATH} ({len(table)} entries)") + + +if __name__ == "__main__": + main() diff --git a/electrum/blockchain.py b/electrum/blockchain.py index 2fc994581..c6a180dca 100644 --- a/electrum/blockchain.py +++ b/electrum/blockchain.py @@ -32,6 +32,7 @@ from .util import bfh, with_lock from .logging import get_logger, Logger from .gHash import gHash +from .asert.asert_table import LOG2_COMPUTE_TABLE from sympy import isprime if TYPE_CHECKING: @@ -67,6 +68,18 @@ "min_activation_height": 0 }, "active": false + }, + "asert": { + "type": "bip9", + "bip9": { + "status": "active", + "start_time": 1772323200, + "timeout": 1803859200, + "since": 176064, + "min_activation_height": 0 + }, + "height": 176064, + "active": true } }, (...) @@ -79,11 +92,36 @@ INTERIM_DAA_PERIOD = 42 INTERIM_DAA_TARGET_TIMESPAN = (INTERIM_DAA_PERIOD - 1) * 30 * 60 # 73800 seconds +# ASERT params mirror chainparams.cpp mainnet (`nPowTargetSpacing`, +# `nASERTHalfLife`, `nBitsMin`, `nBitsMax`). The anchor is the last LOCKED_IN +# block; ASERT is computed from the anchor's nBits and the time/height drift +# since it (see src/pow.cpp::GetNextFACTORASERTWorkRequired). +MAINNET_ASERT_ACTIVATION_HEIGHT = 176064 # first ASERT-computed block ("since") +MAINNET_ASERT_ANCHOR_HEIGHT = MAINNET_ASERT_ACTIVATION_HEIGHT - 1 # 176063 +ASERT_TARGET_SPACING = 30 * 60 # seconds per block +ASERT_HALF_LIFE = 2 * 24 * 60 * 60 # seconds +ASERT_NBITS_MIN = 32 +ASERT_NBITS_MAX = 1022 +# Sentinel matching the C++ "clampedHigh" chain-halt: nBits=1024 is rejected +# by every other code path (>1023 is outside the valid range). +ASERT_CLAMPED_HIGH_SENTINEL = 1024 + def is_interim_daa_active(height: int) -> bool: return MAINNET_INTERIM_DAA_ACTIVATION_HEIGHT <= height < MAINNET_INTERIM_DAA_END_HEIGHT +def is_asert_active(height: int) -> bool: + """Whether ASERT consensus rules apply at the given height. + + Mainnet-only: real FACTOR testnet/signet/regtest enable ASERT from genesis + (ALWAYS_ACTIVE in chainparams.cpp), but this wallet only supports mainnet + ASERT, so testnet stays on the old DAA path.""" + if constants.net.TESTNET: + return False + return height >= MAINNET_ASERT_ACTIVATION_HEIGHT + + def calculate_interim_daa_delta(nBits: int, proportion: float) -> int: # See CalculateInterimDifficultyDelta in src/pow.cpp delta = 0 @@ -106,6 +144,69 @@ def calculate_interim_daa_delta(nBits: int, proportion: float) -> int: return delta +def calculate_factor_asert(anchor_nbits: int, time_diff: int, height_diff: int) -> int: + """Pure-Python port of CalculateFACTORASERT (src/pow.cpp). + + Returns the new nBits, or ASERT_CLAMPED_HIGH_SENTINEL (1024) when the + exponent pushes past nBitsMax — matching the C++ chain-halt behavior. + Mirrors the validated reference impl in + FACTOR/contrib/testgen/validate_nbits_aserti3_2d.py. + """ + anchor_nbits &= ~1 # round down to even + if anchor_nbits < ASERT_NBITS_MIN: + anchor_nbits = ASERT_NBITS_MIN + elif anchor_nbits > ASERT_NBITS_MAX: + anchor_nbits = ASERT_NBITS_MAX + + anchor_idx = anchor_nbits // 2 - 1 + anchor_log2_compute = LOG2_COMPUTE_TABLE[anchor_idx] + + expected_elapsed = height_diff * ASERT_TARGET_SPACING + time_error = expected_elapsed - time_diff + + # C++ truncation-toward-zero, not Python's floor-toward-minus-infinity. + if time_error >= 0: + integer_part = time_error // ASERT_HALF_LIFE + remainder = time_error % ASERT_HALF_LIFE + else: + integer_part = -((-time_error) // ASERT_HALF_LIFE) + remainder = -((-time_error) % ASERT_HALF_LIFE) + + frac_num = remainder << 32 + if frac_num >= 0: + frac_part = frac_num // ASERT_HALF_LIFE + else: + frac_part = -((-frac_num) // ASERT_HALF_LIFE) + + exponent_q32 = (integer_part << 32) + frac_part + target_log2_compute = anchor_log2_compute + exponent_q32 + + idx_min = ASERT_NBITS_MIN // 2 - 1 + idx_max = ASERT_NBITS_MAX // 2 - 1 + + clamped_high = target_log2_compute > LOG2_COMPUTE_TABLE[idx_max] + + if target_log2_compute <= LOG2_COMPUTE_TABLE[idx_min]: + result_idx = idx_min + elif target_log2_compute >= LOG2_COMPUTE_TABLE[idx_max]: + result_idx = idx_max + else: + lo, hi = idx_min, idx_max + while lo + 1 < hi: + mid = lo + (hi - lo) // 2 + if LOG2_COMPUTE_TABLE[mid] <= target_log2_compute: + lo = mid + else: + hi = mid + dist_lo = target_log2_compute - LOG2_COMPUTE_TABLE[lo] + dist_hi = LOG2_COMPUTE_TABLE[hi] - target_log2_compute + result_idx = lo if dist_lo <= dist_hi else hi + + if clamped_high: + return ASERT_CLAMPED_HIGH_SENTINEL + return (result_idx + 1) * 2 + + class MissingHeader(Exception): pass @@ -416,7 +517,17 @@ def verify_chunk(self, index: int, data: bytes) -> None: num = len(data) // HEADER_SIZE start_height = index * constants.CHUNK_SIZE prev_hash = self.get_hash(start_height - 1) - target = self.get_target(index-1) + end_height = start_height + num - 1 + asert_in_chunk = is_asert_active(end_height) + # legacy chunk target is still meaningful for any pre-ASERT block in this chunk + legacy_target = self.get_target(index - 1) if not is_asert_active(start_height) else None + # for ASERT, we need the timestamp of the block just before the first ASERT block in this chunk + prev_timestamp = None + if asert_in_chunk and is_asert_active(start_height): + prev_h = self.read_header(start_height - 1) + if not prev_h: + raise MissingHeader(start_height - 1) + prev_timestamp = prev_h['timestamp'] for i in range(num): height = start_height + i try: @@ -425,8 +536,13 @@ def verify_chunk(self, index: int, data: bytes) -> None: expected_header_hash = None raw_header = data[i*HEADER_SIZE : (i+1)*HEADER_SIZE] header = deserialize_header(raw_header, index * constants.CHUNK_SIZE + i) + if asert_in_chunk and is_asert_active(height): + target = self.get_asert_target(height, prev_timestamp) + else: + target = legacy_target self.verify_header(header, prev_hash, target, expected_header_hash) prev_hash = hash_header(header) + prev_timestamp = header['timestamp'] @with_lock def path(self): @@ -666,6 +782,18 @@ def get_epoch_target(self, epoch_index: int) -> int: return new_target + def get_asert_target(self, height: int, prev_timestamp: int) -> int: + """ASERT nBits for the block at `height`, given the timestamp of block (height-1). + + Requires the anchor header (MAINNET_ASERT_ANCHOR_HEIGHT) to be on disk.""" + anchor = self.read_header(MAINNET_ASERT_ANCHOR_HEIGHT) + if not anchor: + raise MissingHeader(MAINNET_ASERT_ANCHOR_HEIGHT) + anchor_nbits = int(anchor['bits']) + time_diff = prev_timestamp - anchor['timestamp'] + height_diff = (height - 1) - MAINNET_ASERT_ANCHOR_HEIGHT + return calculate_factor_asert(anchor_nbits, time_diff, height_diff) + def get_interim_daa_target(self, chunk_index: int) -> int: """Compute target for chunk chunk_index+1 using the 42-block interim DAA.""" first_height = chunk_index * constants.CHUNK_SIZE @@ -720,8 +848,14 @@ def target_to_bits(cls, target: int) -> int: def chainwork_of_header_at_height(self, height: int) -> int: """work done by single header at given height""" - chunk_idx = height // constants.CHUNK_SIZE - 1 - target = self.get_target(chunk_idx) + if is_asert_active(height): + prev = self.read_header(height - 1) + if not prev: + raise MissingHeader(height - 1) + target = self.get_asert_target(height, prev['timestamp']) + else: + chunk_idx = height // constants.CHUNK_SIZE - 1 + target = self.get_target(chunk_idx) work = ((2 ** 256 - target - 1) // (target + 1)) + 1 return work @@ -741,15 +875,33 @@ def get_chainwork(self, height=None) -> int: cached_height -= constants.CHUNK_SIZE assert cached_height >= -1, cached_height running_total = _CHAINWORK_CACHE[self.get_hash(cached_height)] + # Under ASERT, every header in a chunk has its own nBits, so the + # per-block-work × CHUNK_SIZE shortcut no longer holds. + # Fragility: assumes ASERT activation falls on a chunk boundary (true + # for mainnet: 176064 = 262 × 672). A chunk straddling activation + # would take the legacy branch and incorrectly multiply the ASERT- + # derived work of end_h across the chunk's pre-ASERT prefix. + def work_in_chunk_ending_at(end_h: int) -> int: + first_h = end_h - constants.CHUNK_SIZE + 1 + if is_asert_active(first_h): + return sum(self.chainwork_of_header_at_height(h) + for h in range(first_h, end_h + 1)) + return constants.CHUNK_SIZE * self.chainwork_of_header_at_height(end_h) while cached_height < last_retarget: cached_height += constants.CHUNK_SIZE - work_in_single_header = self.chainwork_of_header_at_height(cached_height) - work_in_chunk = constants.CHUNK_SIZE * work_in_single_header - running_total += work_in_chunk + running_total += work_in_chunk_ending_at(cached_height) _CHAINWORK_CACHE[self.get_hash(cached_height)] = running_total + # trailing partial chunk: sum per-block if any of its blocks are under ASERT cached_height += constants.CHUNK_SIZE - work_in_single_header = self.chainwork_of_header_at_height(cached_height) - work_in_last_partial_chunk = (height % constants.CHUNK_SIZE + 1) * work_in_single_header + partial_first = cached_height - constants.CHUNK_SIZE + 1 + partial_last = partial_first + (height % constants.CHUNK_SIZE) + if is_asert_active(partial_last): + work_in_last_partial_chunk = sum( + self.chainwork_of_header_at_height(h) + for h in range(partial_first, partial_last + 1)) + else: + work_in_single_header = self.chainwork_of_header_at_height(cached_height) + work_in_last_partial_chunk = (height % constants.CHUNK_SIZE + 1) * work_in_single_header return running_total + work_in_last_partial_chunk def can_connect(self, header: dict, check_height: bool=True) -> bool: @@ -767,7 +919,13 @@ def can_connect(self, header: dict, check_height: bool=True) -> bool: if prev_hash != header.get('prev_block_hash'): return False try: - target = self.get_target(height // constants.CHUNK_SIZE - 1) + if is_asert_active(height): + prev_header = self.read_header(height - 1) + if not prev_header: + return False + target = self.get_asert_target(height, prev_header['timestamp']) + else: + target = self.get_target(height // constants.CHUNK_SIZE - 1) except MissingHeader: return False try: From daa62bfc745794f1c96a897c60f4f212cc48a9db Mon Sep 17 00:00:00 2001 From: NyanCatTW1 <17372086+NyanCatTW1@users.noreply.github.com> Date: Tue, 19 May 2026 18:24:18 +0800 Subject: [PATCH 2/2] Bump to 4.8 --- electrum/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/electrum/version.py b/electrum/version.py index 0717f5911..e57a076d9 100644 --- a/electrum/version.py +++ b/electrum/version.py @@ -1,5 +1,5 @@ -ELECTRUM_VERSION = '4.7' # version of the client package -APK_VERSION = '4.7.0.0' # read by buildozer.spec +ELECTRUM_VERSION = '4.8' # version of the client package +APK_VERSION = '4.8.0.0' # read by buildozer.spec PROTOCOL_VERSION = '1.4' # protocol version requested