-
Notifications
You must be signed in to change notification settings - Fork 55
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: expose the recover() function #69
feat: expose the recover() function #69
Conversation
tiny-secp256k1 (WASM): 424.34 us/op (2356.61 op/s), ±4.35 %
Perhaps create a type alias for recid and export it. Also, I wonder how this affects WASM binary size. Needs some more tests, but overall LGTM. |
Adds about 2.7kB to the WASM binary size. Pretty reasonable. It might take a couple weeks for me to publish since I have some personal issues I am taking care of. |
Looks like 0 is returned for a lot of input errors as well... perhaps we should validate for them and only return null for the infinity case (at the very end)
These should all throw errors. If 0 comes back from these, it is the infinity point and should be null. |
My |
2 and 3 can be done with JS before calling into WASM. |
P-N is
So you can just add this to the validate TS file as a const for comparing the r value of the signature when recid & 2 !== 0 |
|
looks good so far. r > p-n when recid & 2 seems like it should be a "bad recid" problem... Since the recid second bit only exists to tell which value r is (r or r+n) when below p-n. But the signature is not... so recid is incorrect most likely. |
also, new rust version added a new lint. just swap with the suggestion in the error. |
|
Needs to update the README also, we need a method for signing and retrieving the recid. (we need it for signing bolt11 invoices. LGTM so far. |
|
Adding the signRecoverable method only added about 800B to the wasm binary. I was thinking maybe we could make it more efficient by joining sign and signRecoverable to some helper method, but it looks like the secp256k1 functions already are using the same code. I'm going to leave this up for a few days before merging. LGTM @fanatid If you have any comments I'd appreciate 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.
Overall looks good, thanks @motorina0!
monkey-see-monkey-do
skills
TIL 😅
it looks like the secp256k1 functions already are using the same code.
@junderw yes, internally they call the same function:
sign with recovery: https://github.com/bitcoin-core/secp256k1/blob/a1102b12196ea27f44d6201de4d25926a2ae9640/src/modules/recovery/main_impl.h#L132
sign: https://github.com/bitcoin-core/secp256k1/blob/a1102b12196ea27f44d6201de4d25926a2ae9640/src/secp256k1.c#L519
@motorina0 I invited you to the bitcoinjs organization |
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.
Needs README for privateKeyNegate
Validation for private will prevent the only cases where 0 will return from the C function. So all null cases will result in Throws before returning. So it is ok to assume null is impossible. Your branch wasn't open to fixes, so I will paste a diff: diff --git a/README.md b/README.md
index f8ad9fd..16e8489 100644
--- a/README.md
+++ b/README.md
@@ -212,6 +212,18 @@ Returns `null` if result is equal to `0`.
- `Expected Private` if `!isPrivate(d)`
- `Expected Tweak` if `tweak` is not in `[0...order - 1]`
+### privateNegate (d)
+
+```haskell
+privateNegate :: Buffer -> Buffer
+```
+
+Returns the negation of d on the order n (`n - d`)
+
+##### Throws:
+
+- `Expected Private` if `!isPrivate(d)`
+
### xOnlyPointAddTweak (p, tweak)
```haskell
diff --git a/src/lib.rs b/src/lib.rs
index 80046f0..5eb9ab6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -421,14 +421,12 @@ pub extern "C" fn private_sub() -> i32 {
#[allow(clippy::missing_panics_doc)]
#[no_mangle]
#[export_name = "privateNegate"]
-pub extern "C" fn private_key_negate() -> i32 {
+pub extern "C" fn private_negate() {
unsafe {
- if secp256k1_ec_seckey_negate(secp256k1_context_no_precomp, PRIVATE_INPUT.as_mut_ptr()) == 1
- {
+ assert_eq!(
+ secp256k1_ec_seckey_negate(secp256k1_context_no_precomp, PRIVATE_INPUT.as_mut_ptr()),
1
- } else {
- 0
- }
+ );
}
}
diff --git a/src_ts/index.ts b/src_ts/index.ts
index 94e1103..1374ba8 100644
--- a/src_ts/index.ts
+++ b/src_ts/index.ts
@@ -244,14 +244,13 @@ export function privateSub(
}
}
-export function privateNegate(d: Uint8Array): Uint8Array | null {
+export function privateNegate(d: Uint8Array): Uint8Array {
validate.validatePrivate(d);
try {
PRIVATE_KEY_INPUT.set(d);
- return wasm.privateNegate() === 1
- ? PRIVATE_KEY_INPUT.slice(0, validate.PRIVATE_KEY_SIZE)
- : null;
+ wasm.privateNegate();
+ return PRIVATE_KEY_INPUT.slice(0, validate.PRIVATE_KEY_SIZE);
} finally {
PRIVATE_KEY_INPUT.fill(0);
}
diff --git a/src_ts/wasm_loader.ts b/src_ts/wasm_loader.ts
index e967e31..8706d82 100644
--- a/src_ts/wasm_loader.ts
+++ b/src_ts/wasm_loader.ts
@@ -48,7 +48,7 @@ interface Secp256k1WASM {
pointMultiply: (p: number, outputlen: number) => number;
privateAdd: () => number;
privateSub: () => number;
- privateNegate: () => number;
+ privateNegate: () => void;
sign: (e: number) => void;
signRecoverable: (e: number) => 0 | 1 | 2 | 3;
signSchnorr: (e: number) => void; |
Thanks!
|
Summary
Exposing the
recover()
function allows other libraries (likebitcoinjs-message
andbolt11
) to usetiny-secp256k1
(instead ofsecp256k1
).Details in this issue: #68
Test Plan
Screenshots
Further Comments
Benchmark