Skip to content

Conversation

@xyephy
Copy link
Contributor

@xyephy xyephy commented Oct 28, 2025

Previously only the first coinbase output was serialized, breaking merge mining and multi-payout pool scenarios.

This change iterates through all outputs in m_coinbase_tx_outputs and serializes them sequentially using VectorWriter.

Also adds debug logging to track the number of outputs and total size for observability.

Fixes #18

@Sjors
Copy link
Collaborator

Sjors commented Oct 28, 2025

Thanks, it would be good to have some tests for this, maybe in https://github.com/Sjors/sv2-tp/blob/master/src/test/sv2_messages_tests.cpp

@xyephy
Copy link
Contributor Author

xyephy commented Oct 28, 2025

Thanks, it would be good to have some tests for this, maybe in https://github.com/Sjors/sv2-tp/blob/master/src/test/sv2_messages_tests.cpp

Let me work on that, thank you for the feedback.

xyephy added a commit to xyephy/sv2-tp that referenced this pull request Oct 28, 2025
Adds Sv2NewTemplate_MultipleOutputs_test which verifies that all
coinbase outputs are serialized correctly, not just the first one.

The test creates a NewTemplate message with 3 different outputs
(100, 200, and 300 sats) and checks that the serialized bytes
match the expected format with all three outputs included.

Requested by maintainer in PR stratum-mining#55.
@xyephy xyephy force-pushed the support-multiple-coinbase-outputs branch from 3d24164 to 1adcfcf Compare October 28, 2025 21:47
@xyephy
Copy link
Contributor Author

xyephy commented Oct 28, 2025

@Sjors I have pushed some test updates, looking forward to hear what you think.

@Sjors
Copy link
Collaborator

Sjors commented Oct 29, 2025

Thanks! Will review in more detail soon. I assume the test fails if you omit the first commit?

It would be nice to also (manually) test this in a Bitcoin Core + sv2_tp + SRI integration. I guess we'd need a patch or Bitcoin Core to actually add a second output, it can just be nonsense, on e.g. signet.

@xyephy
Copy link
Contributor Author

xyephy commented Oct 29, 2025

Thanks! Will review in more detail soon. I assume the test fails if you omit the first commit?

It would be nice to also (manually) test this in a Bitcoin Core + sv2_tp + SRI integration. I guess we'd need a patch or Bitcoin Core to actually add a second output, it can just be nonsense, on e.g. signet.

I think it should work, the only time it failed is when I did 3 commits so I was forced to squash one and test passed, do you want me to make it one commit instead of two?

I will try do a manual simulation as you have advised and then share my findings, hopefully today or latest tomorrow.

@Sjors
Copy link
Collaborator

Sjors commented Oct 29, 2025

one commit instead of two

No, two is fine. I'll try it.

manual simulation as you have advised and then share my findings

Thanks, please share the steps. I haven't worked on merge mining ever, so not sure what the easiest way is.

@xyephy
Copy link
Contributor Author

xyephy commented Oct 29, 2025

Thanks, please share the steps. I haven't worked on merge mining ever, so not sure what the easiest way is.

Let me share the steps once I've figured out the merge mining and patch needed for bitcoin core

@xyephy xyephy force-pushed the support-multiple-coinbase-outputs branch from b202a40 to b8363fc Compare October 29, 2025 14:02
@Sjors
Copy link
Collaborator

Sjors commented Oct 29, 2025

CI is finding test failures:

test/sv2_template_provider_tests.cpp(98): fatal error: in "sv2_template_provider_tests/client_tests": Unexpected message size while receiving initial template broadcast

@xyephy xyephy force-pushed the support-multiple-coinbase-outputs branch from b8363fc to 3ccbe50 Compare October 29, 2025 17:14
@xyephy
Copy link
Contributor Author

xyephy commented Oct 29, 2025

CI is finding test failures:

test/sv2_template_provider_tests.cpp(98): fatal error: in "sv2_template_provider_tests/client_tests": Unexpected message size while receiving initial template broadcast

working on a fix to solve the ci fail

@xyephy xyephy force-pushed the support-multiple-coinbase-outputs branch from 3ccbe50 to 820bd71 Compare October 31, 2025 12:12
@xyephy
Copy link
Contributor Author

xyephy commented Oct 31, 2025

@Sjors I've pushed the new update, here's are the steps I used to test with https://gist.github.com/xyephy/13aff2a54c6286316ce7f8f089862c7f . Let me know if changes are now working.

Copy link
Collaborator

@Sjors Sjors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the elaborate testing instructions!

It made me realise there's a problem: the node always adds a dummy output script (typically OP_TRUE) with the full coinbase reward. We need to exclude that (or the pool will make an invalid block because it tries to spend that amount again).

I think the most robust solution is to filter the coinbase outputs for OP_RETURN. That includes SegWit and (hopefully) all merge mining schemes.

A cleaner solution would require an update to Bitcoin Core to either:

  1. Stop adding the dummy output; or
  2. Add a method similar to getWitnessCommitmentIndex() to indicate which other inputs are commitments that need to be included.

VectorWriter{outputs_bytes, outputs_bytes.size(), output};
}

LogPrintLevel(BCLog::SV2, BCLog::Level::Debug, "Serialized %zu coinbase output(s), total size: %zu bytes\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe downgrade to trace?

4 + // coinbase_tx_outputs_count (0)
2 + // B0_64K length for outputs array (0)
4 + // coinbase_tx_outputs_count (1 - mock creates 1 output)
2 + 10 + // B0_64K: length(10) + 1 output (8 bytes nValue + 2 bytes script)
Copy link
Collaborator

@Sjors Sjors Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was initially confused why this changed, but it's because we're now including all coinbase outputs.

Let's make the mock more realistic add give it:

  1. a dummy anyone-can-spend output, e.g. OP_TRUE with 50BTC
  2. a (fake) segwit commitment rather than the current OP_RETURN, and have the mock getWitnessCommitmentIndex return that position.
  3. a (fake) merge mining commitment

// U32 ffffffff coinbase tx input sequence
// U64 0040075af0750700 coinbase tx value remaining
// U32 03000000 coinbase tx outputs count (3 outputs)
// B0_64K 2100 coinbase_tx_outputs (33 bytes total)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add an anyone-can-spend output here, because the node will provide one and we need to omit it.

if (witness_commitment_index != NO_WITNESS_COMMITMENT) {
m_coinbase_tx_outputs_count = 1;
m_coinbase_tx_outputs = {coinbase_tx->vout[witness_commitment_index]};
// Extract ALL coinbase outputs to support merge mining and other use cases
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to filter this to cover only OP_RETURNs, otherwise we include the dummy output added by the node and since the spends the full reward, the pool would make an invalid block.

@xyephy
Copy link
Contributor Author

xyephy commented Oct 31, 2025

@Sjors thank you for the detailed review, let me look into it and add the recommendations you've made so as to have a much better solution.

xyephy added a commit to xyephy/sv2-tp that referenced this pull request Nov 3, 2025
Implement PR stratum-mining#55 review feedback from Sjors:

- Changed NewTemplate to only include OP_RETURN outputs instead of all
  coinbase outputs. Bitcoin Core adds a dummy output with the full block
  reward that must be filtered out, otherwise pools would create invalid
  blocks trying to spend that amount again.

- Removed unused witness_commitment_index parameter from
  Sv2NewTemplateMsg constructor.

- Changed output serialization log from Debug to Trace level to reduce
  log noise.

- Updated test mocks to create realistic coinbase transactions with
  multiple outputs (1 reward + 2 OP_RETURN) to properly test filtering.

- Updated all test expectations to reflect filtered OP_RETURN behavior.

Testing:
- All 19 unit tests pass
- End-to-end tested with SRI mining-device: 397 blocks mined successfully
- Zero coinbase validation errors across all mined blocks
@Sjors
Copy link
Collaborator

Sjors commented Nov 3, 2025

Thanks, that looks better at first glance. Can you squash both commits?

@xyephy
Copy link
Contributor Author

xyephy commented Nov 3, 2025

@Sjors I have pushed new fixes as you recommended, I've managed to solo mine with Sri mining-device without getting any invalid blocks. Let me know if this works on your end and if there are any further changes I need to add, thank you.

@xyephy
Copy link
Contributor Author

xyephy commented Nov 3, 2025

Thanks, that looks better at first glance. Can you squash both commits?

let me do that

This change enables sv2-tp to handle block templates with multiple
coinbase outputs, which is required for merge mining and other use
cases where additional coinbase outputs are needed.

Implementation:
- Changed NewTemplate to only include OP_RETURN outputs instead of all
  coinbase outputs. Bitcoin Core adds a dummy output with the full block
  reward that must be filtered out, otherwise pools would create invalid
  blocks trying to spend that amount again.

- Removed unused witness_commitment_index parameter from
  Sv2NewTemplateMsg constructor.

- Changed output serialization log from Debug to Trace level to reduce
  log noise.

- Updated test mocks to create realistic coinbase transactions with
  multiple outputs (1 reward + 2 OP_RETURN) to properly test filtering.

- Updated all test expectations to reflect filtered OP_RETURN behavior.

Testing:
- All 19 unit tests pass
- End-to-end tested with SRI mining-device: 397 blocks mined successfully
- Zero coinbase validation errors across all mined blocks

Fixes: stratum-mining#18
@xyephy xyephy force-pushed the support-multiple-coinbase-outputs branch from 36a7ed1 to 9e68692 Compare November 3, 2025 10:23
@Sjors Sjors merged commit d812921 into stratum-mining:master Nov 3, 2025
19 checks passed
@Sjors
Copy link
Collaborator

Sjors commented Nov 3, 2025

Looks great, thanks!

@Sjors
Copy link
Collaborator

Sjors commented Nov 3, 2025

It would be good to round-trip test this in SRI: stratum-mining/sv2-apps#58

@xyephy
Copy link
Contributor Author

xyephy commented Nov 3, 2025

It would be good to round-trip test this in SRI: stratum-mining/sv2-apps#58

let me do that.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support multiple coinbase outputs

2 participants