Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure minimum non-dust amount as change output on regtest #5008

Conversation

janniks
Copy link
Contributor

@janniks janniks commented Jul 25, 2024

  • Adds DUST_UTXO_LIMIT to the to_spend amount for selecting utxos of the BitcoinRegtestController -- this ensures there will always be at least DUST_UTXO_LIMIT as a change output.
    • we now don't pass the total_spend to the serialize function (which selects utxos), but rather a tx_cost.
    • if we want to force a change output the target amount (for selecting utxos) is set to the tx_cost plus DUST_UTXO_LIMIT.
    • for actual "spending" on the transaction the tx_cost is still used, to ensure a change output >= DUST_UTXO_LIMIT if we force one.
    • Also updates estimated tx size for block commit tx to 380
  • Closes Ensure bitcoin ops always include a change address #4992

This might be a quick, good enough fix -- or are there implications for non-regtest code paths?
lmk if anybody has ideas on writing a test for this.

@janniks janniks requested a review from a team as a code owner July 25, 2024 13:34
@janniks janniks closed this Jul 25, 2024
@janniks janniks removed the request for review from a team July 25, 2024 13:50
@janniks janniks reopened this Jul 25, 2024
@janniks
Copy link
Contributor Author

janniks commented Jul 25, 2024

Does this make sense, my brain can't think this through right now 🫠

@janniks janniks requested a review from a team July 25, 2024 13:54
@saralab saralab requested review from obycode and jbencin July 25, 2024 14:08
@obycode
Copy link
Contributor

obycode commented Jul 25, 2024

This looks like it should work to me. Do you think you could add a unit test?

@obycode
Copy link
Contributor

obycode commented Jul 25, 2024

This looks like it should work to me. Do you think you could add a unit test?

There wasn't one before, so I think I'd merge this without, but if it's not terrible, it would be great to add.

obycode
obycode previously approved these changes Jul 25, 2024
@obycode obycode requested a review from kantai July 25, 2024 20:35
@wileyj wileyj enabled auto-merge July 25, 2024 22:43
@wileyj wileyj disabled auto-merge July 25, 2024 23:28
@wileyj
Copy link
Contributor

wileyj commented Jul 25, 2024

@janniks there are several test failures that seem to be a result of this change, ex: https://github.com/stacks-network/stacks-core/actions/runs/10102415322/job/27939605277?pr=5008

do these failing tests pass locally?

@jbencin
Copy link
Contributor

jbencin commented Jul 26, 2024

I think you have to make changes inside serialize_tx() also. You are adding everything up into a single variable, total_to_spend, and passing that to serialize_tx(), but the decision to make a change output in that function is made by:

     let value = total_consumed - total_to_spend;
     if value >= DUST_UTXO_LIMIT {
       // Make change output
     }

total_consumed here is just the minimum UTXO set that's larger than total_to_spend, so it's still possible for the difference to be less than DUST_UTXO_LIMIT

Copy link
Contributor

@obycode obycode left a comment

Choose a reason for hiding this comment

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

Good call Jeff 👍. After another look, I agree, it does need some changes.

@janniks
Copy link
Contributor Author

janniks commented Jul 26, 2024

Lol, yeah this is why I initially closed the PR again. Thanks @jbencin -- I think I'll edit the utxo collection condition in serialize, hoping this is okay for the bitcoin regtest controller.

@jbencin
Copy link
Contributor

jbencin commented Jul 26, 2024

I think you should have all the logic for this inside serialize_tx(). Here's an idea that I think would work: Add a force_change_output parameter to serialize_tx(), and if set, make sure to take a little extra from the UTXO set. See this commit: jbencin@416ff55

@janniks janniks force-pushed the 07-25-fix_ensure_minimum_non-dust_amount_as_change_output_on_regtest branch from 8ad2128 to 030fa64 Compare July 26, 2024 15:09
@janniks
Copy link
Contributor Author

janniks commented Jul 26, 2024

Update based on @jbencin suggestion. Please double check the logic:

  • we now don't pass the total_spend to the serialize function, but rather a tx_cost.
  • if we want to force a change output the target is set to the tx_cost plus DUST_UTXO_LIMIT.
  • for actual "spending" on the transaction the tx_cost is still used, to ensure a change output if we force one.

Won't be able to get a test done in time, should be small enough to review instead.

jbencin
jbencin previously approved these changes Jul 26, 2024
Copy link
Contributor

@jbencin jbencin left a comment

Choose a reason for hiding this comment

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

This looks correct to me now, but integration tests are still failing

@jcnelson
Copy link
Member

Seems several CI tests are still failing

@janniks
Copy link
Contributor Author

janniks commented Jul 29, 2024

cargo nextest run is successful for me locally (apart from two flaky tests, that seem unrelated)

@jbencin
Copy link
Contributor

jbencin commented Jul 29, 2024

cargo nextest run is successful for me locally (apart from two flaky tests, that seem unrelated)

It's the bitcoind integration tests that are failing, and those are skipped by default. If you want to run one of the failing tests locally, do this:

RUST_BACKTRACE=1 BITCOIND_TEST=1 cargo test -- --include-ignored stx_delegate_btc_integration_test

@wileyj
Copy link
Contributor

wileyj commented Jul 29, 2024

and to emulate how the test will run in ci, something like this (which uses nextest):

RUST_BACKTRACE=full BITCOIND_TEST=1 cargo nextest run --no-capture \
    --verbose \
    --tests \
    --workspace \
    --run-ignored all \
    --bin stacks-node \
    --package stacks-node \
    --retries 0  \
    --no-fail-fast \
    -E "test(=tests::neon_integrations::stx_delegate_btc_integration_test)"

I've run a few the failing tests locally, and this is the error i see:

ERRO [1722285437.277667] [testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs:1876] [tests::nakamoto_integrations::stack_stx_burn_op_integration_test] Bitcoin RPC failure: transaction submission failed - Network("Bitcoin RPC: status(500) != success, body is 'Object {\"error\": Object {\"code\": Number(-22), \"message\": String(\"TX decode failed. Make sure the tx has at least one input.\")}, \"id\": String(\"stacks\"), \"result\": Null}'")

with the failing tests being:

    tests::neon_integrations::stx_delegate_btc_integration_test
    tests::neon_integrations::stx_transfer_btc_integration_test
    tests::neon_integrations::stack_stx_burn_op_test
    tests::neon_integrations::vote_for_aggregate_key_burn_op_test
    tests::epoch_25::microblocks_disabled
    tests::nakamoto_integrations::vote_for_aggregate_key_burn_op
    tests::nakamoto_integrations::stack_stx_burn_op_integration_test

@janniks janniks force-pushed the 07-25-fix_ensure_minimum_non-dust_amount_as_change_output_on_regtest branch from 08da287 to df7e9e1 Compare July 30, 2024 15:36
@janniks
Copy link
Contributor Author

janniks commented Jul 30, 2024

Updated tx-size estimates for ops in the regtest controller -- those were too low in cases and didn't find matching UTXOs. Thanks @obycode for finding.

Ready for rereview assuming tests pass 🫡

@kantai Do we have exact values for these estimates, or do you have a good way of figuring them out?

jbencin
jbencin previously approved these changes Jul 30, 2024
@obycode
Copy link
Contributor

obycode commented Jul 30, 2024

Yup, this looks good to me, but I would appreciate someone who is more familiar with the bitcoin transactions checking the sizes.

jbencin
jbencin previously approved these changes Jul 30, 2024
kantai
kantai previously approved these changes Jul 30, 2024
@wileyj
Copy link
Contributor

wileyj commented Jul 30, 2024

two tests still failing (locally) with same error:

tests::neon_integrations::stack_stx_burn_op_test 
tests::nakamoto_integrations::stack_stx_burn_op_integration_test 
    ERRO [1722355798.568427] [testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs:1882] [tests::neon_integrations::stack_stx_burn_op_test] Bitcoin RPC failure: transaction submission failed - Network("Bitcoin RPC: status(500) != success, body is 'Object {\"error\": Object {\"code\": Number(-22), \"message\": String(\"TX decode failed. Make sure the tx has at least one input.\")}, \"id\": String(\"stacks\"), \"result\": Null}'")

@obycode
Copy link
Contributor

obycode commented Jul 30, 2024

I think there are two unknowns that need to be investigated:

  1. Are those maximum tx size values accurate?
  2. Could it be that the change adds an extra input utxo which causes the size to be bigger than expected? How should that be handled?

@janniks
Copy link
Contributor Author

janniks commented Jul 30, 2024

two tests still failing (locally) with same error:


tests::neon_integrations::stack_stx_burn_op_test 

tests::nakamoto_integrations::stack_stx_burn_op_integration_test 


    ERRO [1722355798.568427] [testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs:1882] [tests::neon_integrations::stack_stx_burn_op_test] Bitcoin RPC failure: transaction submission failed - Network("Bitcoin RPC: status(500) != success, body is 'Object {\"error\": Object {\"code\": Number(-22), \"message\": String(\"TX decode failed. Make sure the tx has at least one input.\")}, \"id\": String(\"stacks\"), \"result\": Null}'")

Thx for these, trying to figure out what's wrong here. Maybe the StackStx estimate is also off, but it seems to be off by a large margin, so I'm not sure..

@janniks janniks dismissed stale reviews from kantai and jbencin via 9e9aa77 July 30, 2024 22:13
@janniks
Copy link
Contributor Author

janniks commented Jul 31, 2024

Updated to only force the change output for block commits (according to the from_tx parse code it seems that's the only type which really needs the change output)

Copy link
Contributor

@obycode obycode left a comment

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@jbencin jbencin left a comment

Choose a reason for hiding this comment

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

LGTM

@wileyj
Copy link
Contributor

wileyj commented Jul 31, 2024

looks good, thanks @janniks

still see this failure : tests::signer::v0::empty_sortition but it seems unrelated to this PR

@wileyj wileyj added this pull request to the merge queue Jul 31, 2024
Merged via the queue into develop with commit 228597e Jul 31, 2024
1 check passed
@wileyj wileyj deleted the 07-25-fix_ensure_minimum_non-dust_amount_as_change_output_on_regtest branch July 31, 2024 15:14
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.

6 participants