-
Notifications
You must be signed in to change notification settings - Fork 14
Reference implementation of CT descriptors #31
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
Reference implementation of CT descriptors #31
Conversation
6b678bb
to
76ca5be
Compare
Oops, missed some files. Added and force-pushed. I squashed everything because the individual commits weren't split out right; let me know if I should split them up again. |
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.
Should we remove the Blinded
descriptors now? Should this struct also be called Descriptor
?
src/confidential/mod.rs
Outdated
/// The first public key is included outside of the `Vec` to reduce allocations | ||
/// and to enforce that the list of keys is not empty; but it is not special in | ||
/// any way. | ||
HashToSk(Pk, Vec<Pk>), |
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.
This makes creating the Key
really annoying. Can we just have a Vec instead? To ensure that there is at least one element, we should wrap this in a struct and add constructors.
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.
IMO, we should really make things convenient for users by adding some extra code and allocations 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.
lol, okay, agreed
let spk = self.descriptor.script_pubkey(); | ||
self.descriptor | ||
.blinded_address(self.key.to_public_key(secp, &spk), params) | ||
} |
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.
We should add other descriptor APIs later.
let mut addr = elements::Address::from_str("2dpWh6jbhAowNsQ5agtFzi7j6nKscj6UnEr").unwrap(); | ||
addr.blinding_pubkey = Some(mbk.blinding_key(&secp, &spk)); | ||
assert_eq!(addr.to_string(), "CTEkf75DFff5ReB7juTg2oehrj41aMj21kvvJaQdWsEAQohz1EDhu7Ayh6goxpz3GZRVKidTtaXaXYEJ"); | ||
} |
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 did not know this code, but I tested this with elements 22.0 and it works as expected. Perhaps, you can also add this test?
#[test]
fn local_test_elements_22_0() {
// Local test on elements 22.0
let mbk = MasterBlindingKey::from_hex(
"64269a8de756da06ebe35d26dccb4dd46bddcf858b54eeaae315490cfe6cacc0",
)
.unwrap();
let addr = elements::Address::from_str(
"el1qqg2pz79c0reryhr6hzxrzueju9m2asllwydrhexs6vj854cvwlen4tryh4thsdt2a26rte3fe87rf3my9t90wt78pcqrxv733",
)
.unwrap();
let derived_blinding_key = mbk.blinding_private_key(&addr.script_pubkey());
assert_eq!(
derived_blinding_key,
secp256k1_zkp::SecretKey::from_slice(&unhex(
"791a1081ae2ad98a5ad603737c648247f19d3c26e2beb54617638172edb230e7"
))
.unwrap()
);
}
@sanket1729 regarding "should we remove the |
@apoelstra, agreed on both things |
So, where I'm at with this is that I need
|
Thanks for the enumerated list. Left some feedback on the rust-elements repo. |
@apoelstra, what is the status of this project/PR? |
@sanket1729 I intend to finish this and merge it. I think I've got everything I need now? Will try to do it over the weekend or early next week. |
7b35e15
to
47eee43
Compare
Rebase only. |
440aaa6
to
c3b356c
Compare
cc @sanket1729 I have finally finished this PR, with test vectors and everything. No rush, but ready for review. |
It would be nice to have |
On @LeoComandini out-of-band advice we may modify this scheme so that the "bare pubkey" variant p2c-commits to the scriptpubkey. Conveniently, even when the scriptpubkey is exposed alongside the resulting key, nobody can "undo" the p2c and learn the original public key. So we get very good on-chain privacy here, even when one participant in a multiparty setup is reusing keys. Will update after some more thought. Writing here so I don't forget. |
Can now be rebased |
In a previous incarnation of CT descriptors we considered "musig" and "slip77" expressions to constitute keys, allowing them to be parsed in contexts where normally only keys would be allowed (and _not_ expanding them as expression trees which would then need to be reconstructed). This is still plausibly the direction we want to go in for MuSig keys, but it never made a lot of sense for SLIP77, and indeed, we now want to go a different direction, where SLIP77 expressions are allowed only as the first argument of a CT descriptor.
c3b356c
to
a332208
Compare
Nice. I need to add some xpub-based test vectors but this is otherwise ready for review. |
Need to re-think the API for this; but sufficient to produce a test vector.
cc @sanket1729 ready for review |
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.
ACK 725f450.
Checked against the spec. Any reason why don't have wildcards in BlindedKey
?
"d12a140aca856fbb917b931f263c42f064608985e2ce17ae5157daa17c55e8d9", | ||
); | ||
|
||
// And hash of 100 bytes |
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: 80 bytes
There isn't a type called Generic key types don't, in general, have wildcards. Normally, wildcards are handled by people taking a generic descriptor, using So, when the descriptor has an extra "blinding key" which needs to be updated in tandem with the the rest of the keys, our generic-key model breaks down. I think the right way to handle this would be to link Does this make sense? Basically the issue is that we're mixing a generic keytype and a concrete one, and our API does not handle this gracefully. |
@apoelstra, I get the issues with I guess this is more a question of a spec. Perhaps, I am misunderstanding something here, if |
@sanket1729 I don't understand what you're saying. The spec allows wildcards. The reference implementation just doesn't support it because I didn't want to do the rearchitecture work required for it. |
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.
2 minor comment suggestions
impl MasterBlindingKey { | ||
/// Compute a master blinding key from a seed | ||
/// | ||
/// The recommended in (SLIP-39) source of this seed is to obtain the |
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.
/// The recommended in (SLIP-39) source of this seed is to obtain the | |
/// The recommended source of this seed (in SLIP-39) is to obtain the |
test.check(&secp); | ||
} | ||
// Uncomment to regenerate test vectors; to see the output, run | ||
// cargo test confidential::tests:;confidential_descriptor -- --nocapture |
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.
// cargo test confidential::tests:;confidential_descriptor -- --nocapture | |
// cargo test confidential::tests::confidential_descriptor -- --nocapture |
Going to merge this; can address comment nits in a followup PR. |
I'm aware that there are already a basic form of CT descriptors in this library, and this does not remove them, it just adds a new module which should act as a reference implementation for ElementsProject/ELIPs#1
WIP because it needs a new rust-elements release to get tagged hashes in
bitcoin_hashes
.