Skip to content

Commit be13e3c

Browse files
authored
Merge pull request #289 from ethereumproject/develop
Add libsecp256k1 support
2 parents caeb643 + eff8649 commit be13e3c

4 files changed

Lines changed: 52 additions & 11 deletions

File tree

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ os:
1212
script:
1313
- cargo build --release --all --verbose
1414
- cargo test --release --all --verbose
15-
- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo build --no-default-features; fi
15+
- if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cargo build --no-default-features --features rust-secp256k1; fi
1616

1717
matrix:
1818
allow_failures:

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ etcommon-bigint = { version = "0.2", default-features = false, features = ["rlp"
2121

2222
etcommon-block = { version = "0.3", optional = true }
2323
secp256k1-plus = { version = "0.5.7", optional = true }
24+
libsecp256k1 = { version = "0.1", optional = true }
2425

2526
[dev-dependencies]
2627
etcommon-hexutil = "0.2"
2728

2829
[features]
29-
default = ["std"]
30-
std = ["etcommon-block-core/std", "etcommon-rlp/std", "etcommon-bigint/std", "etcommon-block", "secp256k1-plus"]
30+
default = ["std", "c-secp256k1"]
31+
c-secp256k1 = ["secp256k1-plus"]
32+
rust-secp256k1 = ["libsecp256k1"]
33+
std = ["etcommon-block-core/std", "etcommon-rlp/std", "etcommon-bigint/std", "etcommon-block"]
3134

3235
[workspace]
3336
members = [

src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,14 @@ extern crate ripemd160;
3030
extern crate sha2;
3131
extern crate digest;
3232

33+
#[cfg(feature = "c-secp256k1")]
34+
extern crate secp256k1;
35+
36+
#[cfg(feature = "rust-secp256k1")]
37+
extern crate secp256k1;
38+
3339
#[cfg(feature = "std")]
3440
extern crate block;
35-
#[cfg(feature = "std")]
36-
extern crate secp256k1;
3741

3842
mod util;
3943
mod memory;

src/patch/precompiled.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@ use alloc::Vec;
55
#[cfg(feature = "std")] use std::rc::Rc;
66

77
use bigint::Gas;
8-
#[cfg(feature = "std")] use std::cmp::min;
8+
#[cfg(all(feature = "std", any(feature = "rust-secp256k1", feature = "c-secp256k1")))] use std::cmp::min;
9+
#[cfg(all(not(feature = "std"), any(feature = "rust-secp256k1", feature = "c-secp256k1")))] use core::cmp::min;
910

1011
use errors::{RuntimeError, OnChainError};
1112
use sha2::Sha256;
12-
#[cfg(feature = "std")] use sha3::Keccak256;
13+
#[cfg(any(feature = "rust-secp256k1", feature = "c-secp256k1"))]
14+
use sha3::Keccak256;
1315
use ripemd160::Ripemd160;
1416
use digest::{Digest, FixedOutput};
1517

16-
#[cfg(feature = "std")]
18+
#[cfg(feature = "c-secp256k1")]
1719
use secp256k1::{SECP256K1, RecoverableSignature, Message, RecoveryId, Error};
20+
#[cfg(feature = "rust-secp256k1")]
21+
use secp256k1::{recover, Message, RecoveryId, Signature, Error};
1822

1923
/// Represent a precompiled contract.
2024
pub trait Precompiled: Sync {
@@ -96,7 +100,7 @@ pub static SHA256_PRECOMPILED: SHA256Precompiled = SHA256Precompiled;
96100

97101
/// ECREC precompiled contract.
98102
pub struct ECRECPrecompiled;
99-
#[cfg(feature = "std")]
103+
#[cfg(any(feature = "c-secp256k1", feature = "rust-secp256k1"))]
100104
impl Precompiled for ECRECPrecompiled {
101105
fn gas(&self, _: &[u8]) -> Gas {
102106
Gas::from(3000u64)
@@ -118,7 +122,7 @@ impl Precompiled for ECRECPrecompiled {
118122
}
119123
}
120124
}
121-
#[cfg(not(feature = "std"))]
125+
#[cfg(all(not(feature = "c-secp256k1"), not(feature = "rust-secp256k1")))]
122126
impl Precompiled for ECRECPrecompiled {
123127
fn gas_and_step(&self, _: &[u8], _: Gas) -> Result<(Gas, Rc<Vec<u8>>), RuntimeError> {
124128
use errors::NotSupportedError;
@@ -136,7 +140,7 @@ fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
136140
}
137141
}
138142

139-
#[cfg(feature = "std")]
143+
#[cfg(feature = "c-secp256k1")]
140144
fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
141145
let message = Message::from_slice(&data[0..32])?;
142146
let recid_raw = match data[63] {
@@ -157,3 +161,33 @@ fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
157161

158162
Ok(ret)
159163
}
164+
165+
#[cfg(feature = "rust-secp256k1")]
166+
fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
167+
let mut message_raw = [0u8; 32];
168+
for i in 0..32 {
169+
message_raw[i] = data[i];
170+
}
171+
let message = Message::parse(&message_raw);
172+
let recid_raw = match data[63] {
173+
27 | 28 if data[32..63] == [0; 31] => data[63] - 27,
174+
_ => return Err(Error::InvalidRecoveryId),
175+
};
176+
let recid = RecoveryId::parse(recid_raw)?;
177+
let mut sig_raw = [0u8; 64];
178+
for i in 0..64 {
179+
sig_raw[i] = data[64 + i];
180+
}
181+
let sig = Signature::parse(&sig_raw);
182+
let recovered = recover(&message, &sig, &recid)?;
183+
let key = recovered.serialize();
184+
185+
let ret_generic = Keccak256::digest(&key[1..65]);
186+
let mut ret = [0u8; 32];
187+
188+
for i in 0..32 {
189+
ret[i] = ret_generic[i];
190+
}
191+
192+
Ok(ret)
193+
}

0 commit comments

Comments
 (0)