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

Validate reject-withdrawal-request #1336

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

xoloki
Copy link
Collaborator

@xoloki xoloki commented Feb 10, 2025

Description

Closes: #478

Changes

Testing Information

Checklist:

  • I have performed a self-review of my code
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@xoloki xoloki self-assigned this Feb 10, 2025
@djordon djordon added withdrawal The withdrawal sBTC operation. sbtc signer binary The sBTC Bootstrap Signer. labels Feb 11, 2025
@xoloki xoloki force-pushed the 478-validate-reject-withdrawal-request branch 2 times, most recently from 353028d to 8fe2632 Compare February 12, 2025 02:41
@xoloki xoloki requested a review from djordon February 12, 2025 03:01
@xoloki xoloki changed the base branch from main to 1308-implement-query-returning-withdrawalrequestreport February 12, 2025 05:31
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
Base automatically changed from 1308-implement-query-returning-withdrawalrequestreport to main February 12, 2025 20:58
…wo checks

call iter not into_iter for lint check

check that the withdrawal-request is final on the btc chain

use corrent block hash in storage requests and errors

use proper chain tip errors

create withdrawal-reject integration tests based on the withdrawal-accept tests

log error since we don't have good error returns yet

clean up error handling

disable most reject tests but leave in the ones that are analaguous to the accept ones

don't clone if you can copy

add some temporary logging

use block heights to determine if 6 blocks have passed since the withdrawal request

failure to get withdrawal signers or request report should map to RequestMissing

remove unused tests; use bitmap mismatch test

move QualifiedRequestId into common proto; RejectWithdrawalV1 now has a QualifiedRequestId in both code and proto; deal with fallout

fix tests to use QualifiedRequestId for RejectWithdrawalV1

map the DB error to the expected type

remove stacks/common.proto since the linter complained it wasn't being used

check reject threshold

use TestSweepSetup2 to try to fix problems with the signer set length

address review comments, though they seem to have made things worse

use sweep block height not fake data in TestSweepSetup2

hard wire the correct signing threshold into ReqContext

add TestSweep2 reject_withdrawal_request and call it from happy path test
@xoloki xoloki force-pushed the 478-validate-reject-withdrawal-request branch from 6c3a70b to e20193c Compare February 13, 2025 21:12
@xoloki xoloki marked this pull request as ready for review February 13, 2025 21:13
@xoloki
Copy link
Collaborator Author

xoloki commented Feb 13, 2025

Ok @djordon I have it all working now, with minimal changes to TestSweepSetup2, squashed and rebased on latest main.

signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@djordon djordon left a comment

Choose a reason for hiding this comment

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

I haven't finished looking through the tests but so far looking good.

signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
signer/src/stacks/contracts.rs Outdated Show resolved Hide resolved
Comment on lines 1179 to 1183
if rejected_count < reject_threshold {
return Err(
WithdrawalRejectErrorMsg::WithdrawalRequestNotRejected.into_error(req_ctx, self)
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This part is tricky since there are two reasons for why we would reject a withdrawal.

  1. The withdrawal request has enough votes against.
  2. The withdrawal request has expired. This happens after WITHDRAWAL_BLOCKS_EXPIRY blocks (the one from my PR here) from the height of the bitcoin_block_height in the WithdrawalRequestReport (it's block_height on main but we're renaming it).

So we need to check for either condition here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think that this one is done.

signer/tests/integration/setup.rs Show resolved Hide resolved
signer/tests/integration/withdrawal_reject.rs Outdated Show resolved Hide resolved
… use make_withdrawal_reject2 in reject_withdrawal_validation_bitmap_mismatch so it will have the chain tip in req_ctx; use req_ctx to get chain tip in validate
Copy link
Collaborator

@djordon djordon left a comment

Choose a reason for hiding this comment

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

We need to make add another check here, specifically, the reject-withdrawal-request transaction is valid if the request is expired or collectively rejected. We need to add the expired check, which is check to see if 24 or more blocks have arrived after the bitcoin_block_height of the withdrawal request. That field is also in the withdrawal request report.

And we need a few more tests here. In general, we should aim for a test of each of the different validation conditions that we check for, so basically one test per WithdrawalRejectErrorMsg variant. That might seem like a lot, but I believe that there are several error variants that we can remove after some of the recent edits; they're currently unused. And we don't need to add a test for the MissingStacksBlock at all, I think we can remove that variant in another PR.

Comment on lines +88 to +102
let tip_block_hash = db.get_bitcoin_canonical_chain_tip().await.unwrap().unwrap();
let tip_bitcoin_block = db
.get_bitcoin_block(&tip_block_hash)
.await
.unwrap()
.unwrap();

let tip_block_height = tip_bitcoin_block.block_height;

// This is what the current signer thinks is the state of things.
let req_ctx = ReqContext {
chain_tip: BitcoinBlockRef {
block_hash: tip_block_hash,
block_height: tip_block_height,
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: doesn't matter much, but this can be simplified to

    let chain_tip = db
        .get_bitcoin_canonical_chain_tip_ref()
        .await
        .unwrap()
        .unwrap();

    // This is what the current signer thinks is the state of things.
    let req_ctx = ReqContext {
        chain_tip,
        ...

let mut setup =
TestSweepSetup2::new_setup(test_signer_set.clone(), &faucet, &[deposit_amounts]);

setup.submit_sweep_tx(rpc, faucet, true);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmmm. So I think this means that the sweep transaction sweeping out the withdrawal gets confirmed. The store_sweep_tx function is supposed to store the sweep data in the right tables; I don't think that it does right now but will after #1359. When it does, the associated RejectWithdrawalV1 struct must fail validation. That's basically the double spend check from #478. Since this is the happy path, it's best to not submit the sweep tx using this function, moreover, I think store_sweep_tx panics if there is no sweep tx.

So for most of these tests we shouldn't submit a sweep transaction and store it in the database unless we want to test validation of a swept withdrawal request, which is the "The de-pegging check" from #478 (it used to say "The double spend check").

Comment on lines +365 to +372
let validation_result = reject_withdrawal_tx.validate(&ctx, &req_ctx).await;
match validation_result.unwrap_err() {
Error::WithdrawalRejectValidation(ref err) => {
assert_eq!(err.error, WithdrawalRejectErrorMsg::RequestNotFinal)
}
err => panic!("unexpected error during validation {err}"),
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

After this we should generate one more block and check that things validate then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sbtc signer binary The sBTC Bootstrap Signer. withdrawal The withdrawal sBTC operation.
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

[Feature]: Validate reject-withdrawal-request contract calls
2 participants