Skip to content

Commit 4534c4a

Browse files
author
Michael Müller
authored
Upgrade libsecp256k1 from 0.3.5 ➔ 0.7.0 (#967)
* Upgrade `libsecp256k1` from `0.3.5` ➔ `0.7.0` * Include off-chain dependencies only when necessary * Include off-chain dependency only when necessary * Include off-chain dependency only when necessary * Switch to `secp256k1` for `eth_compatibility` crate * Remove conditional dependency * Fix serialize * Switch to `secp256k1` crate everywhere * Switch to `secp256k1` crate everywhere * Fix compilation for `wasm32` target * Ensure enabled features are not merged for targets * Make clippy happy * Use resolver `2` in all examples * Switch to `libsecp256k1` 0.7.0 * Use default features * Bring comment back * Reduce diff * Remove unnecessary import * Update rustfmt config to edition 2018 * Use resolver `2` for workspace
1 parent c90da11 commit 4534c4a

File tree

11 files changed

+98
-13
lines changed

11 files changed

+98
-13
lines changed

.rustfmt.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ trailing_comma = "Vertical"
4343
match_block_trailing_comma = false
4444
blank_lines_upper_bound = 1
4545
blank_lines_lower_bound = 0
46-
edition = "2018" # changed
46+
edition = "2021" # changed
4747
version = "One"
4848
merge_derives = true
4949
use_try_shorthand = true # changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[workspace]
2+
resolver = "2"
23
members = [
34
"crates/metadata",
45
"crates/allocator",

crates/engine/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ sha3 = { version = "0.9" }
2323
blake2 = { version = "0.9" }
2424

2525
# ECDSA for the off-chain environment.
26-
libsecp256k1 = { version = "0.3.5", default-features = false }
26+
libsecp256k1 = { version = "0.7.0" }
2727

2828
[features]
2929
default = ["std"]

crates/engine/src/ext.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ impl Engine {
428428
message_hash: &[u8; 32],
429429
output: &mut [u8; 33],
430430
) -> Result {
431-
use secp256k1::{
431+
use libsecp256k1::{
432432
recover,
433433
Message,
434434
RecoveryId,
@@ -443,7 +443,7 @@ impl Engine {
443443
signature[64]
444444
};
445445
let message = Message::parse(message_hash);
446-
let signature = Signature::parse_slice(&signature[0..64])
446+
let signature = Signature::parse_standard_slice(&signature[0..64])
447447
.unwrap_or_else(|error| panic!("Unable to parse the signature: {}", error));
448448

449449
let recovery_id = RecoveryId::parse(recovery_byte)

crates/engine/src/tests.rs

+76
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ use crate::ext::{
1616
Engine,
1717
Error,
1818
};
19+
use libsecp256k1::{
20+
Message,
21+
PublicKey,
22+
SecretKey,
23+
};
1924

2025
/// The public methods of the `contracts` pallet write their result into an
2126
/// `output` buffer instead of returning them. Since we aim to emulate this
@@ -192,3 +197,74 @@ fn must_panic_when_buffer_too_small() {
192197
// then
193198
unreachable!("`get_storage` must already have panicked");
194199
}
200+
201+
#[test]
202+
fn ecdsa_recovery_test_from_contracts_pallet() {
203+
// given
204+
let mut engine = Engine::new();
205+
#[rustfmt::skip]
206+
let signature: [u8; 65] = [
207+
161, 234, 203, 74, 147, 96, 51, 212, 5, 174, 231, 9, 142, 48, 137, 201,
208+
162, 118, 192, 67, 239, 16, 71, 216, 125, 86, 167, 139, 70, 7, 86, 241,
209+
33, 87, 154, 251, 81, 29, 160, 4, 176, 239, 88, 211, 244, 232, 232, 52,
210+
211, 234, 100, 115, 230, 47, 80, 44, 152, 166, 62, 50, 8, 13, 86, 175,
211+
28,
212+
];
213+
#[rustfmt::skip]
214+
let message_hash: [u8; 32] = [
215+
162, 28, 244, 179, 96, 76, 244, 178, 188, 83, 230, 248, 143, 106, 77, 117,
216+
239, 95, 244, 171, 65, 95, 62, 153, 174, 166, 182, 28, 130, 73, 196, 208
217+
];
218+
219+
// when
220+
let mut output = [0; 33];
221+
engine
222+
.ecdsa_recover(&signature, &message_hash, &mut output)
223+
.expect("must work");
224+
225+
// then
226+
#[rustfmt::skip]
227+
const EXPECTED_COMPRESSED_PUBLIC_KEY: [u8; 33] = [
228+
2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11,
229+
7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23,
230+
152,
231+
];
232+
assert_eq!(output, EXPECTED_COMPRESSED_PUBLIC_KEY);
233+
}
234+
235+
#[test]
236+
fn ecdsa_recovery_with_secp256k1_crate() {
237+
// given
238+
let mut engine = Engine::new();
239+
let seckey = [
240+
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203,
241+
174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
242+
];
243+
let pubkey = PublicKey::parse_compressed(&[
244+
2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245,
245+
41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
246+
])
247+
.expect("pubkey creation failed");
248+
249+
let mut msg_hash = [0; 32];
250+
crate::hashing::sha2_256(b"Some message", &mut msg_hash);
251+
252+
let msg = Message::parse(&msg_hash);
253+
let seckey = SecretKey::parse(&seckey).expect("secret key creation failed");
254+
let (signature, recovery_id) = libsecp256k1::sign(&msg, &seckey);
255+
256+
let mut signature = signature.serialize().to_vec();
257+
signature.push(recovery_id.serialize());
258+
let signature_with_recovery_id: [u8; 65] = signature
259+
.try_into()
260+
.expect("unable to create signature with recovery id");
261+
262+
// when
263+
let mut output = [0; 33];
264+
engine
265+
.ecdsa_recover(&signature_with_recovery_id, &msg.serialize(), &mut output)
266+
.expect("ecdsa recovery failed");
267+
268+
// then
269+
assert_eq!(output, pubkey.serialize_compressed());
270+
}

crates/env/Cargo.toml

+7-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ categories = ["no-std", "embedded"]
1515
include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
1616

1717
[dependencies]
18-
ink_engine = { version = "3.0.0-rc6", path = "../engine/", default-features = false, optional = true }
1918
ink_metadata = { version = "3.0.0-rc6", path = "../metadata/", default-features = false, features = ["derive"], optional = true }
2019
ink_allocator = { version = "3.0.0-rc6", path = "../allocator/", default-features = false }
2120
ink_primitives = { version = "3.0.0-rc6", path = "../primitives/", default-features = false }
@@ -30,13 +29,19 @@ arrayref = "0.3"
3029
static_assertions = "1.1"
3130
sp-arithmetic = { version = "3.0", default-features = false }
3231

32+
[target.'cfg(target_arch = "wasm32")'.dependencies]
33+
libsecp256k1 = { version = "0.7.0", default-features = false }
34+
35+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
36+
ink_engine = { version = "3.0.0-rc6", path = "../engine/", default-features = false, optional = true }
37+
3338
# Hashes for the off-chain environment.
3439
sha2 = { version = "0.9", optional = true }
3540
sha3 = { version = "0.9", optional = true }
3641
blake2 = { version = "0.9", optional = true }
3742

3843
# ECDSA for the off-chain environment.
39-
libsecp256k1 = { version = "0.3.5", default-features = false }
44+
libsecp256k1 = { version = "0.7.0" }
4045

4146
# Only used in the off-chain environment.
4247
#

crates/env/src/engine/experimental_off_chain/impls.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::{
3434
Clear,
3535
EnvBackend,
3636
Environment,
37+
Error,
3738
RentParams,
3839
RentStatus,
3940
Result,
@@ -252,7 +253,7 @@ impl EnvBackend for EnvInstance {
252253
message_hash: &[u8; 32],
253254
output: &mut [u8; 33],
254255
) -> Result<()> {
255-
use secp256k1::{
256+
use libsecp256k1::{
256257
recover,
257258
Message,
258259
RecoveryId,
@@ -267,7 +268,7 @@ impl EnvBackend for EnvInstance {
267268
signature[64]
268269
};
269270
let message = Message::parse(message_hash);
270-
let signature = Signature::parse_slice(&signature[0..64])
271+
let signature = Signature::parse_standard_slice(&signature[0..64])
271272
.unwrap_or_else(|error| panic!("Unable to parse the signature: {}", error));
272273

273274
let recovery_id = RecoveryId::parse(recovery_byte)
@@ -279,7 +280,7 @@ impl EnvBackend for EnvInstance {
279280
*output = pub_key.serialize_compressed();
280281
Ok(())
281282
}
282-
Err(_) => Err(crate::Error::EcdsaRecoverFailed),
283+
Err(_) => Err(Error::EcdsaRecoverFailed),
283284
}
284285
}
285286

crates/env/src/engine/off_chain/impls.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl EnvBackend for EnvInstance {
201201
message_hash: &[u8; 32],
202202
output: &mut [u8; 33],
203203
) -> Result<()> {
204-
use secp256k1::{
204+
use libsecp256k1::{
205205
recover,
206206
Message,
207207
RecoveryId,
@@ -216,7 +216,7 @@ impl EnvBackend for EnvInstance {
216216
signature[64]
217217
};
218218
let message = Message::parse(message_hash);
219-
let signature = Signature::parse_slice(&signature[0..64])
219+
let signature = Signature::parse_standard_slice(&signature[0..64])
220220
.unwrap_or_else(|error| panic!("Unable to parse the signature: {}", error));
221221

222222
let recovery_id = RecoveryId::parse(recovery_byte)

crates/eth_compatibility/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ include = ["Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"]
1616

1717
[dependencies]
1818
ink_env = { version = "3.0.0-rc6", path = "../env", default-features = false }
19-
libsecp256k1 = { version = "0.3.5", default-features = false }
19+
libsecp256k1 = { version = "0.7.0", default-features = false }
2020

2121
[features]
2222
default = ["std"]

crates/eth_compatibility/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#![no_std]
16+
1617
use ink_env::{
1718
DefaultEnvironment,
1819
Environment,
@@ -92,7 +93,7 @@ impl ECDSAPublicKey {
9293
/// ```
9394
pub fn to_eth_address(&self) -> EthereumAddress {
9495
use ink_env::hash;
95-
use secp256k1::PublicKey;
96+
use libsecp256k1::PublicKey;
9697

9798
// Transform compressed public key into uncompressed.
9899
let pub_key = PublicKey::parse_compressed(&self.0)

crates/storage/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ scale-info = { version = "1.0", default-features = false, features = ["derive"],
2727
cfg-if = "1.0"
2828
array-init = { version = "2.0", default-features = false }
2929

30+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
3031
# Workaround: we actually just need criterion as a dev-dependency, but
3132
# there is an issue with a doubly included std lib when executing
3233
# `cargo check --no-default-features --target wasm32-unknown-unknown`.

0 commit comments

Comments
 (0)