Skip to content

Support Electrum protocol v1.6 #172

Open

Description

@tnull

The Electrum protocol v1.6 was just merged. See the docs for changes in the new version:

Changes

  • Breaking change for the version negotiation: we now mandate that the server.version() message must be the first message sent. That is, version negotiation must happen before any other messages.

  • Also for server.version(), the server must tolerate and ignore extraneous arguments, to allow for extensions in future protocol versions.

  • The status of a scripthash has its definition tightened in a backwards-compatible way: mempool txs now have a canonical ordering defined for the calculation (previously their order was undefined).

  • blockchain.scripthash.get_mempool() previously did not define an order for mempool transactions. We now mandate a specific ordering.

  • Optional mode argument added to blockchain.estimatefee().

  • blockchain.block.headers() now returns headers as a list, instead of a single concatenated hex string.

New methods

  • blockchain.transaction.broadcast_package() to broadcast a package of transactions (submitpackage).

  • mempool.get_info() to get more detailed and general relayfee info.

Removed methods

  • blockchain.relayfee() is removed. The minrelaytxfee field of the new mempool.get_info() RPC is a direct replacement.

It would be great if electrs could support the new features very soon. For us (LDK), support for the new blockchain.transaction.broadcast_package is particularly important, as we want to lean on TRUC/v3 transaction relay via Electrum ASAP.

Activity

  1. landabaso commented on Jan 8, 2026

    @landabaso

    The next version of RewindBitcoin would also greatly benefit from adding support for broadcast_package. In the meantime, we are using Esplora's txs/package endpoint as a workaround.

  2. tnull commented on Jan 9, 2026

    @tnull
    Author

    The next version of RewindBitcoin would also greatly benefit from adding support for broadcast_package. In the meantime, we are using Esplora's txs/package endpoint as a workaround.

    Note that it is already available in the original romanz/electrs: romanz#1242. So if you don't need Esplora you could just switch to the original electrs.

  3. EddieHouston commented on Jun 17, 2026

    @EddieHouston
    Collaborator

    Opened #227, which adds blockchain.transaction.broadcast_package to the Esplora/Blockstream electrs Electrum server — directly addressing the package-relay need raised here (TRUC/v3 for LDK, and RewindBitcoin's current txs/package REST workaround).

    It's ported from @romanz's implementation (romanz#1242) but built on the submitpackage plumbing already present here from the POST /txs/package REST endpoint (5e36b93), so the same code path now backs both REST and Electrum. The PR also fixes a related issue where accepted package txs weren't added to electrs' local mempool, so scripthash subscription/history updates now reflect them immediately (this fix applies to the existing REST endpoint too).

    This only covers the broadcast_package item from the 1.6 list. The remaining v1.6 work is still open and would need separate changes:

    • blockchain.transaction.broadcast_package (feat(electrum): add blockchain.transaction.broadcast_package #227)
    • mempool.get_info
    • remove blockchain.relayfee (replaced by mempool.get_info)
    • blockchain.scripthash.get_mempool canonical ordering (+ aligning the scripthash status-hash ordering)
    • blockchain.block.headers returning a list instead of concatenated hex
    • optional mode arg on blockchain.estimatefee
    • server.version must be first message / tolerate extra args
    • bump advertised PROTOCOL_VERSION to 1.6 once the above land

    (Note: blockchain.scripthash.get_mempool itself was recently added in #226, just without the 1.6 canonical sort yet.)

  4. EddieHouston commented on Jul 2, 2026

    @EddieHouston
    Collaborator

    @tnull @landabaso broadcast_package --> #227

  5. PeteClubSeven commented on Jul 10, 2026

    @PeteClubSeven

    Hi guys, thanks for adding broadcast_package support. I tried implementing electrum support in bark, typically we use core RPC or the REST API in this version of electrs. Unfortunately it looks like you've broken RBF'ing a TRUC package. It worked for a long time via the REST API but I updated to master so I can enable electrum support but both protocols are broken. I had Claude investigate it and it thinks the issue started when #227 was merged. Here is the summary it wrote up for additional context:

    Affected: new-index branch since 7fed8f41 ("feat(electrum): add blockchain.transaction.broadcast_package", merged 2026-07-02 via #227). Reproduced at HEAD 4b348320. Both interfaces are affected — REST POST /txs/package and electrum blockchain.transaction.broadcast_package — since both go through Query::submit_package.

    Symptom: the main thread panics and the daemon dies:

    thread 'main' panicked at src/new_index/mempool.rs:519:17:
    missing mempool edge for outpoint <O> (tx <C>)
    

    Mechanism: Query::submit_package now calls Mempool::add_by_txids for the accepted txids immediately after bitcoind's submitpackage (src/new_index/query.rs, ~line 96–114). This bypasses the invariant the poll-based Mempool::update maintains — evicted txs are always removed before new ones are added, so two conflicting spenders of one outpoint never coexist in the view:

    1. Tx A spending outpoint O is indexed via the normal poll.
    2. A package containing tx C that RBF-replaces A (also spends O) is submitted; bitcoind evicts A, accepts C.
    3. add_by_txids inserts C while A is still indexed → edges[O] is overwritten with C's entry.
    4. Next poll evicts A → remove(A) deletes edges[O] (actually C's entry).
    5. When C is later confirmed or evicted, remove(C) finds no edge for O → the assert! at mempool.rs:519 panics.

    Repro: deterministic within seconds on regtest: index a spend of some outpoint, then submit a package containing a replacement of that spend between two mempool polls, then let both removals happen (mine a block). We hit it from wallet integration tests doing anchor/CPFP package broadcasts after an RBF bump.

    Suggested direction: before add_by_txids, evict from the local view any indexed tx (plus descendants) that conflicts with an incoming package tx's prevouts — mirroring what the poll's remove-before-add ordering guarantees. For reference, mempool/electrs is unaffected because its submit_package proxies to bitcoind without touching the local view.

  6. EddieHouston commented on Jul 16, 2026

    @EddieHouston
    Collaborator

    Hi guys, thanks for adding broadcast_package support. I tried implementing electrum support in bark, typically we use core RPC or the REST API in this version of electrs. Unfortunately it looks like you've broken RBF'ing a TRUC package. It worked for a long time via the REST API but I updated to master so I can enable electrum support but both protocols are broken. I had Claude investigate it and it thinks the issue started when #227 was merged. Here is the summary it wrote up for additional context:

    Affected: new-index branch since 7fed8f41 ("feat(electrum): add blockchain.transaction.broadcast_package", merged 2026-07-02 via #227). Reproduced at HEAD 4b348320. Both interfaces are affected — REST POST /txs/package and electrum blockchain.transaction.broadcast_package — since both go through Query::submit_package.

    Symptom: the main thread panics and the daemon dies:

    thread 'main' panicked at src/new_index/mempool.rs:519:17:
    missing mempool edge for outpoint <O> (tx <C>)
    

    Mechanism: Query::submit_package now calls Mempool::add_by_txids for the accepted txids immediately after bitcoind's submitpackage (src/new_index/query.rs, ~line 96–114). This bypasses the invariant the poll-based Mempool::update maintains — evicted txs are always removed before new ones are added, so two conflicting spenders of one outpoint never coexist in the view:

    1. Tx A spending outpoint O is indexed via the normal poll.
    2. A package containing tx C that RBF-replaces A (also spends O) is submitted; bitcoind evicts A, accepts C.
    3. add_by_txids inserts C while A is still indexed → edges[O] is overwritten with C's entry.
    4. Next poll evicts A → remove(A) deletes edges[O] (actually C's entry).
    5. When C is later confirmed or evicted, remove(C) finds no edge for O → the assert! at mempool.rs:519 panics.

    Repro: deterministic within seconds on regtest: index a spend of some outpoint, then submit a package containing a replacement of that spend between two mempool polls, then let both removals happen (mine a block). We hit it from wallet integration tests doing anchor/CPFP package broadcasts after an RBF bump.

    Suggested direction: before add_by_txids, evict from the local view any indexed tx (plus descendants) that conflicts with an incoming package tx's prevouts — mirroring what the poll's remove-before-add ordering guarantees. For reference, mempool/electrs is unaffected because its submit_package proxies to bitcoind without touching the local view.

    #234 should resolve this (or at least make it work like broadcast_raw and not panic). #236 (comment)

  7. PeteClubSeven commented on Jul 16, 2026

    @PeteClubSeven

    I can confirm it fixes the issue

  8. Randy808 commented on Jul 16, 2026

    @Randy808
    Collaborator

    Thanks for reporting and testing the issue @PeteClubSeven!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions