-
Notifications
You must be signed in to change notification settings - Fork 14
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: construct BTC transactions #128
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great stuff so far. The only blocker I see is that we shouldn't dictate the output type for withdrawals.
signer/src/utxo.rs
Outdated
/// The public key that will be able to spend the output. | ||
pub public_key: PublicKey, |
There was a problem hiding this comment.
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 should assume a public key in the withdraw request. Perhaps the user wants to withdraw to a multisig address? Or another script?
Instead, I think this should be an Address
, alternatively a ScriptBuf
representing the output scriptPubKey if we want to be more low-level here.
/// The public key that will be able to spend the output. | |
pub public_key: PublicKey, | |
/// The public key that will be able to spend the output. | |
pub public_key: bitcoin::address::Address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That all makes sense to me, but I think that would lead us being off the low-level designs in the Deposit API LLD and the Clarity LLD. I was following the Deposit API LLD, which uses the public key, while the clarity LLD uses a tuple of a 1 byte version
field with a 32 byte hashbytes
field (which I think is a compressed public key).
I'm okay changing the designs and it's all equally easy for me to update here. Just want to call out that this would lead to a mismatch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(for reference) We've synced with the team and agreed that this is a LLD bug, and that we want to use addresses here.
signer/src/utxo.rs
Outdated
/// The maximum acceptable number of votes against for any given | ||
/// request. | ||
pub reject_capacity: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: It's more intuitive for me to work with the converse: accept_threshold
. That's the parameter that we already use in many places in wsts
and the Nakamoto signer (just called threshold
there). Would you be okay with swapping it here?
/// The maximum acceptable number of votes against for any given | |
/// request. | |
pub reject_capacity: u32, | |
/// The minimum acceptable number of votes for any given request. | |
pub threshold: u32, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it is more intuitive. I think I had that design originally but with an additional field noting the total number of signers so that we could compute the reject capacity (the accept threshold alone is not enough). I'm okay with switching to that version of things with the additional field.
signer/src/utxo.rs
Outdated
/// The public key used in the deposit script. | ||
pub deposit_public_key: PublicKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which public key is this? There should only be one public key in the deposit script, and that's the signer aggregate key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, so this should be the aggregate key. Can we rename it?
/// The public key used in the deposit script. | |
pub deposit_public_key: PublicKey, | |
/// The public key used in the deposit script. | |
pub signer_aggregate_key: PublicKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. Are you opposed to signers_public_key
?
signer/src/utxo.rs
Outdated
|
||
/// Helper function for generating dummy Schnorr signatures. | ||
fn generate_dummy_signature() -> Signature { | ||
let key_pair = Keypair::new_global(&mut secp256k1::rand::thread_rng()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We might as well include rand
as an explicit dependency since I'm sure we'll use it more times than just here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we've defaulted to using OsRng in many places in the nakamoto signer already. I don't have strong opinions on either, but it's nice to be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool beans, will update.
Updated! @netrome would you mind taking another look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general this is pretty great, but I have a question around computing the optimal tx. If what I'm talking about is known and out of scope for this PR, that totally makes sense too!
// Create a list of requests where each request can be approved on its own. | ||
let items = deposits.chain(withdrawals); | ||
|
||
compute_optimal_packages(items, self.reject_capacity()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused as to where input/output weight come into play here. In general, inputs will be very similar size (though not exact), and outputs will be varying in size (depending on the type of address). So, wouldn't this function need to have some mechanism of knowing a request's "cost"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. The compute_optimal_packages
function computes approval sets using only how the signers have voted on each of the requests. The number of rejections is the request's "weight", it is completely separate from input/output weight of a BTC transaction. That function doesn't care about the BTC weight at all.
You know, I should rename that term but I couldn't think of anything better (size? heaviness? pounds? lbs?). Everything I thought of kinda missed the mark a little but maybe weight is even worse.
Thanks, will do 👀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for updating, looks good to me!
signer/src/utxo.rs
Outdated
/// The public key that will be able to spend the output. | ||
pub public_key: PublicKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(for reference) We've synced with the team and agreed that this is a LLD bug, and that we want to use addresses here.
Description
Closes #75.
We need to take a set of deposit and withdrawal requests and turn them into BTC transactions that can be signed by the signers. This PR gets us part of the way there.
Type of Change
This is new code that takes the current state of the signers UTXO, the current market rate in sats-per-vbyte, along with outstanding deposit and withdrawal requests and creates a set of BTC transactions.
Notes
There are several things worth noting though:
Does this introduce a breaking change?
No breaking changes
Testing information
There are unit tests here that test for most of the asserted functionality and/or invariants. But some further integration testing is required to ensure that properly signed witness data is indeed correct. These tests will happen in another PR (such as one addressing #67).
Checklist