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

feat: implement emily client to get deposits and update broadcasted ones #609

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

Conversation

matteojug
Copy link
Collaborator

@matteojug matteojug commented Oct 3, 2024

Description

Closes: #602, #605

Changes

Implement the EmilyClient to get and update deposits status. And add an integration test for the Emily flow.

Testing Information

Added an integration test, to be run manually, to test the e2e flow wrt Emily: we generate the deposit request there, it's picked up by the block observer, then we accept it and trigger the sweep tx; finally we check that request status on Emily is updated to accepted. The test passes.

Checklist:

  • I have performed a self-review of my code

signer/src/emily_client.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@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.

This looks good so far.

Just had a comment about how we can make the generated Emily sources a little more pleasant to work with.

signer/src/emily_client.rs Outdated Show resolved Hide resolved
signer/src/emily_client.rs Outdated Show resolved Hide resolved
@matteojug matteojug marked this pull request as ready for review October 4, 2024 12:54
signer/tests/integration/emily.rs Outdated Show resolved Hide resolved
signer/src/emily_client.rs Outdated Show resolved Hide resolved
signer/tests/integration/emily.rs Outdated Show resolved Hide resolved
signer/tests/integration/emily.rs Outdated Show resolved Hide resolved
@matteojug matteojug changed the title feat: add emily call to update deposit after tx broadcast feat: implement emily client to get deposits and update broadcasted ones Oct 4, 2024
Copy link
Contributor

@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.

This basically looks good, I had a bunch of "add comment" suggestions. And I think we'll need to change the function signature for update_broadcasted_deposits to include enough stacks related information. We can do that either here or in another PR.

Comment on lines 107 to 108
// TODO: fetch multiple pages?
resp.deposits
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm, maybe. I suppose we'll have to dig into the source of the generated deposit_api::get_deposits code to see if that is handled for us, but I cannot imagine that it is.

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 page_size value seems to be passed to the emily api endpoint, using None should mean no limit since it's used here, but at the same time there's seems to be a "forced pagination" once the resulting data reach 1MB.

Comment on lines 52 to 56
/// Update deposits.
fn update_broadcasted_deposits<'a>(
&'a self,
transaction: &'a UnsignedTransaction<'a>,
bitcoin_chain_tip: &'a BitcoinBlockRef,
Copy link
Contributor

Choose a reason for hiding this comment

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

I would add a little more detail here for the comment. I think this function is supposed to be used after a sweep bitcoin transaction has been confirmed, but the stacks transaction minting sBTC has not been confirmed yet. And we probably need to add in information about the stacks chain tip here too (or add in a storage parameter so that we can fetch it).

Comment on lines 144 to 146
// TODO: use stacks tip/hash here?
last_update_block_hash: bitcoin_chain_tip.block_hash.to_string(),
last_update_height: bitcoin_chain_tip.block_height,
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah these are stacks related.

Comment on lines 234 to 238
// TODO: need to add a retry (somewhere else?) if this fails? Otherwise
// since we already submitted the bitcoin tx, we would never mark the request
// as accepted.
self.context
.get_emily_client()
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to explicitly retry here, since the fallback wrapper struct is supposed to do that for us.

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 was thinking about the case of Emily being offline or unreachable: since we already submitted the tx we would never mark it as accepted. That's why I was thinking of adding the retry in some other place, looking for inconsistencies.

I'll remove the comment though, since I guess it's the general make it robust thing.

Copy link
Member

Choose a reason for hiding this comment

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

Realistically what we should probably do here (long-term) is store all emily "updates" in the db as a persistent queue and push them from there in a separate task. Since it's only the signer coord that sends these, and we don't know how long emily could be unreachable (could be a local network issue), that would help us avoid eating memory storing these in ram and offer better reliability in-case the signer restarts.

Comment on lines 243 to 255
context
.with_bitcoin_client(|client| {
client
.expect_estimate_fee_rate()
.once()
.returning(|| Box::pin(async { Ok(1.3) }));

client
.expect_get_last_fee()
.once()
.returning(|_| Box::pin(async { Ok(None) }));
})
.await;
Copy link
Contributor

Choose a reason for hiding this comment

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

It might be helpful to add a comment about the significance of get_last_fee here, which is that it just tells the caller that they do not need to worry about replacing-by-fee another bitcoin transaction in the mempool.

Comment on lines 304 to 315
// Return the deposit tx block
client
.expect_get_block()
.once()
.returning(move |block_hash| {
let res = if *block_hash == deposit_block_hash {
Ok(Some(deposit_block.clone()))
} else {
Err(Error::MissingBlock)
};
Box::pin(async move { res })
});
Copy link
Contributor

Choose a reason for hiding this comment

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

I would also note in this comment that since we've saved the deposit block hash into the database already, we do not attempt to fetch any of it's parents.

Comment on lines 463 to 467
for signer_pub_key in signer_info[0]
.signer_public_keys
.iter()
.take(signing_threshold as usize)
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we break this out over multiple lines for readability? Something like:

let public_keys = signer_info[0]
    .signer_public_keys
    .iter()
    .take(signing_threshold as usize);

for signer_pub_key in public_keys {
    ...

Comment on lines 145 to 156
/// End to end test for deposits via Emily: a deposit request is created on Emily,
/// then is picked up by the block observer, inserted into the storage and accepted.
/// After a signing round, the sweep tx for the request is broadcasted and we check
/// that Emily is informed about it.
///
/// To run this test, concurrently run:
/// - make emily-integration-env-up
/// - AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar AWS_REGION=us-west-2 make emily-server
/// then, once Emily is up and running, run this test.
#[ignore = "This is an integration test that requires manually running emily"]
#[tokio::test]
async fn deposit_e2e() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a great test!

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.

[Feature]: Update deposit status (via Emily) after tx broadcast
4 participants