ipc: crash on `submitSolution` call with invalid coinbase #33341

issue marcofleon opened this issue on September 8, 2025
  1. marcofleon commented at 12:53 PM on September 8, 2025: contributor

    There seems to be an unhandled exception when deserializing an invalid coinbase in submitSolution.

    <details> <summary>log</summary>

    node0 2025-09-08T11:26:56.165687Z [capnp-loop] [../../../src/ipc/capnp/protocol.cpp:35] [void ipc::capnp::(anonymous namespace)::IpcLogFn(bool, std::string)] [ipc] {bitcoin-node-166995/b-capnp-loop-166997} IPC server recv request  [#14](/bitcoin-bitcoin/14/) BlockTemplate.submitSolution$Params (context = (thread = <external capability>), version = 0, timestamp = 0, nonce = 0, coinbase = "") 
     node0 2025-09-08T11:26:56.165711Z [capnp-loop] [../../../src/ipc/capnp/protocol.cpp:35] [void ipc::capnp::(anonymous namespace)::IpcLogFn(bool, std::string)] [ipc] {bitcoin-node-166995/b-capnp-loop-166997} IPC server post request  [#14](/bitcoin-bitcoin/14/) {bitcoin-node-166995/b-capnp-loop-167036 (from pythread)} 
     test  2025-09-08T11:26:56.207859Z TestFramework (ERROR): Unexpected exception 
                                       Traceback (most recent call last):
                                         File "/root/bitcoin/test/functional/test_framework/test_framework.py", line 199, in main
                                           self.run_test()
                                         File "/root/bitcoin/./debugbuild/test/functional/interface_ipc.py", line 186, in run_test
                                           self.run_mining_test()
                                         File "/root/bitcoin/./debugbuild/test/functional/interface_ipc.py", line 182, in run_mining_test
                                           asyncio.run(capnp.run(async_routine()))
                                         File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
                                           return runner.run(main)
                                                  ^^^^^^^^^^^^^^^^
                                         File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
                                           return self._loop.run_until_complete(task)
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                         File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
                                           return future.result()
                                                  ^^^^^^^^^^^^^^^
                                         File "capnp/lib/capnp.pyx", line 1965, in run
                                         File "capnp/lib/capnp.pyx", line 1966, in capnp.lib.capnp.run
                                         File "/root/bitcoin/./debugbuild/test/functional/interface_ipc.py", line 128, in async_routine
                                           result = await template.result.submitSolution(ctx, 0, 0, 0, b"")
                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                       capnp.lib.capnp.KjException: capnp/rpc.c++:2778: disconnected: Peer disconnected.
                                       stack: 7fd1cba914c4 7fd1cba87d10 7fd1cba777c0 7fd1cb9164f0 7fd1cb9187d0
     test  2025-09-08T11:26:56.218026Z TestFramework (DEBUG): Closing down network thread 
     test  2025-09-08T11:26:56.268255Z TestFramework (INFO): Not stopping nodes as test failed. The dangling processes will be cleaned up later. 
     test  2025-09-08T11:26:56.268354Z TestFramework (WARNING): Not cleaning up dir /tmp/bitcoin_func_test_jp4hfh13 
     test  2025-09-08T11:26:56.268384Z TestFramework (ERROR): Test failed. Test logging available at /tmp/bitcoin_func_test_jp4hfh13/test_framework.log 
     test  2025-09-08T11:26:56.268453Z TestFramework (ERROR): 
     test  2025-09-08T11:26:56.268517Z TestFramework (ERROR): Hint: Call /root/bitcoin/test/functional/combine_logs.py '/tmp/bitcoin_func_test_jp4hfh13' to consolidate all logs 
     test  2025-09-08T11:26:56.268547Z TestFramework (ERROR): 
     test  2025-09-08T11:26:56.268569Z TestFramework (ERROR): If this failure happened unexpectedly or intermittently, please file a bug and provide a link or upload of the combined log. 
     test  2025-09-08T11:26:56.268603Z TestFramework (ERROR): https://github.com/bitcoin/bitcoin/issues 
     test  2025-09-08T11:26:56.268627Z TestFramework (ERROR): 
    
     node0 stderr terminate called after throwing an instance of 'std::ios_base::failure[abi:cxx11]'
      what():  SpanReader::read(): end of data: iostream error 
    

    </details>

    I found this while using fuzzamoto to test the mining interface, but the easiest way to reproduce would be to just add

    await template.result.submitSolution(ctx, 0, 0, 0, b"")
    

    after creating the block template in the IPC functional test (interface_ipc.py).

  2. fanquake commented at 12:55 PM on September 8, 2025: member
  3. fanquake added the label interfaces on Sep 8, 2025
  4. Sjors commented at 1:07 PM on September 8, 2025: member

    Thanks, I was able to reproduce that. Will add a guard and test.

  5. Sjors commented at 1:14 PM on September 8, 2025: member

    @ryanofsky looks like libmultiprocess needs to catch this earlier, because even if I make bool submitSolution immediately return false it crashes.

    The node crashes with:

    libc++abi: terminating due to uncaught exception of type std::__1::ios_base::failure: SpanReader::read(): end of data: unspecified iostream_category error
    
  6. ryanofsky commented at 2:40 PM on September 8, 2025: contributor

    Nice find. This behavior is expected but should be improved, and shouldn't be hard to improve.

    It's similar to https://github.com/bitcoin-core/libmultiprocess/issues/206 in that if a bad request is sent to the node, the node will crash instead of returning an error, when it could just as easily return an error, and it would make sense to do that for the sake of stability and to make development easier with other languages like rust and python.

    Similar to https://github.com/bitcoin-core/libmultiprocess/issues/206 this type of error is difficult to trigger from c++ unless you call the function with an argument that can only be serialized but not deserialized.

    It should not be hard to add some code to serverInvoke to catch and log uncaught exceptions and reject the request. I can follow up with a PR to address this and https://github.com/bitcoin-core/libmultiprocess/issues/206

  7. marcofleon commented at 2:47 PM on February 27, 2026: contributor

    cc @Sjors

  8. ryanofsky commented at 2:57 PM on February 27, 2026: contributor

    It should not be hard to add some code to serverInvoke to catch and log uncaught exceptions and reject the request. I can follow up with a PR to address this [...]

    The uncaught exceptions should now be caught with https://github.com/bitcoin-core/libmultiprocess/commit/c4762c7b513abf66e3275b2bd3f2cf0cb980a8f7 in https://github.com/bitcoin-core/libmultiprocess/pull/240 and #34422. So this issue should be resolved #34422 although it might be good to add a test to check the error message that's returned.

  9. ryanofsky commented at 4:09 PM on February 27, 2026: contributor

    Confirmed following test passes locally with #34422

    --- a/test/functional/interface_ipc_mining.py
    +++ b/test/functional/interface_ipc_mining.py
    @@ -277,6 +277,14 @@ class IPCMiningTest(BitcoinTestFramework):
                     block.hashMerkleRoot = block.calc_merkle_root()
                     original_version = block.nVersion
     
    +                self.log.debug("Submit solution that can't be deserialized")
    +                try:
    +                    await template.submitSolution(ctx, 0, 0, 0, b"")
    +                    raise AssertionError("submitSolution unexpectedly succeeded")
    +                except capnp.lib.capnp.KjException as e:
    +                    assert_equal(e.description, "remote exception: std::exception: SpanReader::read(): end of data: iostream error")
    +                    assert_equal(e.type, "FAILED")
    +
                     self.log.debug("Submit a block with a bad version")
                     block.nVersion = 0
                     block.solve()
    

    I think this would be good to add as a followup to #34422, maybe bundled with other followups already discussed #34422 (review). The test might also need to be adjusted to work on different CI jobs

  10. enirox001 referenced this in commit 6c4c62d9ad on Mar 9, 2026
  11. enirox001 referenced this in commit 79d3f77cb7 on Mar 9, 2026
  12. enirox001 referenced this in commit ca5fdb5d9d on Mar 9, 2026
  13. enirox001 referenced this in commit 3477c4300c on Mar 9, 2026
  14. enirox001 referenced this in commit b46dd5a0ee on Mar 11, 2026
  15. enirox001 referenced this in commit daf405d7b5 on Mar 11, 2026
  16. enirox001 referenced this in commit 730b93ae92 on Mar 11, 2026
  17. enirox001 referenced this in commit 400f9272da on Mar 12, 2026
  18. enirox001 referenced this in commit 9b6985c1ed on Mar 12, 2026
  19. enirox001 referenced this in commit 6865cc46cf on Mar 12, 2026
  20. enirox001 referenced this in commit f65687b59b on Mar 13, 2026
  21. Sjors commented at 12:05 PM on March 13, 2026: member

    #34727 adds test coverage for this

  22. enirox001 referenced this in commit e7a918b69a on Mar 20, 2026
  23. fanquake added this to the milestone 31.0 on Mar 23, 2026
  24. hodlinator commented at 9:41 AM on March 23, 2026: contributor

    #33341 adds test coverage for this

    Correction: #34727

  25. achow101 closed this on Mar 24, 2026

  26. pull[bot] referenced this in commit 4ecf473c36 on Mar 24, 2026
  27. fanquake referenced this in commit 39c87621d5 on Mar 25, 2026
  28. ryanofsky commented at 10:35 PM on April 8, 2026: contributor

    #34644 (review) reports a similar issue probably caused by the same bug


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-16 21:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me