ipc: crash on submitSolution call with invalid coinbase #33341

issue marcofleon openend 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.

     0node0 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 = "") 
     1 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)} 
     2 test  2025-09-08T11:26:56.207859Z TestFramework (ERROR): Unexpected exception 
     3                                   Traceback (most recent call last):
     4                                     File "/root/bitcoin/test/functional/test_framework/test_framework.py", line 199, in main
     5                                       self.run_test()
     6                                     File "/root/bitcoin/./debugbuild/test/functional/interface_ipc.py", line 186, in run_test
     7                                       self.run_mining_test()
     8                                     File "/root/bitcoin/./debugbuild/test/functional/interface_ipc.py", line 182, in run_mining_test
     9                                       asyncio.run(capnp.run(async_routine()))
    10                                     File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
    11                                       return runner.run(main)
    12                                              ^^^^^^^^^^^^^^^^
    13                                     File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
    14                                       return self._loop.run_until_complete(task)
    15                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    16                                     File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    17                                       return future.result()
    18                                              ^^^^^^^^^^^^^^^
    19                                     File "capnp/lib/capnp.pyx", line 1965, in run
    20                                     File "capnp/lib/capnp.pyx", line 1966, in capnp.lib.capnp.run
    21                                     File "/root/bitcoin/./debugbuild/test/functional/interface_ipc.py", line 128, in async_routine
    22                                       result = await template.result.submitSolution(ctx, 0, 0, 0, b"")
    23                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    24                                   capnp.lib.capnp.KjException: capnp/rpc.c++:2778: disconnected: Peer disconnected.
    25                                   stack: 7fd1cba914c4 7fd1cba87d10 7fd1cba777c0 7fd1cb9164f0 7fd1cb9187d0
    26 test  2025-09-08T11:26:56.218026Z TestFramework (DEBUG): Closing down network thread 
    27 test  2025-09-08T11:26:56.268255Z TestFramework (INFO): Not stopping nodes as test failed. The dangling processes will be cleaned up later. 
    28 test  2025-09-08T11:26:56.268354Z TestFramework (WARNING): Not cleaning up dir /tmp/bitcoin_func_test_jp4hfh13 
    29 test  2025-09-08T11:26:56.268384Z TestFramework (ERROR): Test failed. Test logging available at /tmp/bitcoin_func_test_jp4hfh13/test_framework.log 
    30 test  2025-09-08T11:26:56.268453Z TestFramework (ERROR): 
    31 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 
    32 test  2025-09-08T11:26:56.268547Z TestFramework (ERROR): 
    33 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. 
    34 test  2025-09-08T11:26:56.268603Z TestFramework (ERROR): https://github.com/bitcoin/bitcoin/issues 
    35 test  2025-09-08T11:26:56.268627Z TestFramework (ERROR): 
    36
    37 node0 stderr terminate called after throwing an instance of 'std::ios_base::failure[abi:cxx11]'
    38  what():  SpanReader::read(): end of data: iostream error 
    

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

    0await 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:

    0libc++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


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: 2025-09-12 15:13 UTC

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