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: emily validate deposits #1197

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

fix: emily validate deposits #1197

wants to merge 16 commits into from

Conversation

Jiloc
Copy link
Collaborator

@Jiloc Jiloc commented Jan 9, 2025

Description

Closes: #1116,

Changes

  • add a new transaction_hex mandatory field to the create_deposit endpoint
  • add validation on all request fields and the new one
  • add validation to check if the raw transaction data is an sbtc transaction and its content corresponds to the txid, deposit and reclaim scripts
  • extract deposit amount from the tx - previously we were hardcoding a 0.
  • add validation to check if the deposit amount is withint the per-deposit limits:
    • the validation is simple by design. We want to avoid requests that are clearly malicious to be accepted by Emily, but the refined validation (e.g. amount - paid fee > dust fee) are still expected from the signers.
  • save recipients with their real string value instead of their hex representation. e.g. SP5ZH8581RX20N9MJXZ0V7G0QKCBKGDKM4EK3700 insead of 05160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a1

Testing Information

  • added real txs fixtures and unit tests for the validation
  • modified tx_setup to create transactions with mulitple deposits
  • updated unit and integration tests

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

@Jiloc Jiloc self-assigned this Jan 9, 2025
emily/handler/src/api/handlers/deposit.rs Outdated Show resolved Hide resolved
emily/handler/src/api/models/deposit/requests.rs Outdated Show resolved Hide resolved
emily/handler/src/api/models/deposit/requests.rs Outdated Show resolved Hide resolved
@Jiloc
Copy link
Collaborator Author

Jiloc commented Jan 13, 2025

We'll keep this PR in Draft till after the rotate-key release

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.

Looks good.

Left a suggestion. I'm just refraining from approving until after key rotation work.

Comment on lines 100 to 109
let amount = tx
.tx_out(self.bitcoin_tx_output_index as usize)
.map_err(|_| {
Error::HttpRequest(
StatusCode::BAD_REQUEST,
"invalid bitcoin_output_index".to_string(),
)
})?
.value
.to_sat();
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: you can remove this if you move up the validate_tx call, which I think also has a dedicated error message for this check:

Suggested change
let amount = tx
.tx_out(self.bitcoin_tx_output_index as usize)
.map_err(|_| {
Error::HttpRequest(
StatusCode::BAD_REQUEST,
"invalid bitcoin_output_index".to_string(),
)
})?
.value
.to_sat();
let deposit_info = deposit_req
.validate_tx(&tx)
.map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string()))?;

Then below just do

...
if deposit_info.amount < min {
    ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I noticed this, but I preferred the current approach because I wanted the deposit's amount to be validated before the transaction matching, and I found the error message for the existing validation (could not get outpoint f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de:10 from BTC transaction: invalid output index) too verbose. Said that, I am aware that my motivations are just a small subjective preference, so I am open to change if you think the other approach would be clearer!

@Jiloc Jiloc requested a review from fabergat January 20, 2025 17:17
@fabergat
Copy link
Collaborator

The CDK part looks good to me

@Jiloc Jiloc marked this pull request as ready for review January 27, 2025 16:30
emily/handler/src/api/models/deposit/requests.rs Outdated Show resolved Hide resolved
emily/handler/src/api/models/deposit/requests.rs Outdated Show resolved Hide resolved
Comment on lines 123 to 138
// Even if no limits are set, the deposit amount should be higher than the dust limit.
let min = limits.per_deposit_minimum.unwrap_or(DEPOSIT_DUST_LIMIT);
if amount < min {
return Err(Error::HttpRequest(
StatusCode::BAD_REQUEST,
format!("deposit amount below minimum ({})", min),
));
}

let cap = limits.per_deposit_cap.unwrap_or(Amount::MAX_MONEY.to_sat());
if amount > cap {
return Err(Error::HttpRequest(
StatusCode::BAD_REQUEST,
format!("deposit amount exceeds cap ({})", cap),
));
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm a bit worried about validating the limits here (other than the dust), as there's a time difference between when the bridge checks for the limits and when Emily does. And in particular, if the request is not on emily the bridge cannot offer a recovery via reclaim. So maybe it's better to not enforce the limits checks in 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.

The main idea was that it would also validate requests that won't arrive from the bridge. if they arrive from the bridge and it's properly handling the limits, this should never happen. With the exception of a very unfortunate race condition of us changing the limits while a deposit is being validated. I am find with removing it if you still think it's safer though

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if we want to keep the dust limit check or not (I know previously I said so, sorry 🙏 ): it's kinda a constant of the system so I would be inclined to keep it, but OTOH there's the usual: what if someone else (the bridge, some external wallet) doesn't enforce it? Then we are back to the usual more work for the signers but users can reclaim easily thingy

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

🤣 no worries, it makes sense to me. Any kind of enforcement on Emily's side makes sense only if the create deposit call could be sent and validated before the bitcoin TX is sent, but given that it's not the case..

emily/handler/src/api/models/deposit/requests.rs Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Ensure integrity of deposit requests submitted
5 participants