Skip to content

Commit 0782872

Browse files
authored
Merge pull request #208 from TheBlueMatt/202-04-wasm
Re-support WASM via simple stub headers
2 parents c39a1ca + affc6b4 commit 0782872

File tree

10 files changed

+132
-23
lines changed

10 files changed

+132
-23
lines changed

.travis.yml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
language: rust
2-
# cache:
3-
# directories:
4-
# - cargo_web
2+
cache:
3+
directories:
4+
- wasm
55

66
rust:
77
- stable
88
- beta
99
- nightly
1010
- 1.22.0
11+
distro: bionic
1112
os:
1213
- linux
1314
- windows
1415

1516
addons:
1617
chrome: stable
18+
apt:
19+
packages:
20+
- clang-9
21+
- nodejs
1722

1823
matrix:
1924
exclude:
@@ -46,8 +51,10 @@ script:
4651
cd no_std_test &&
4752
cargo run --release | grep -q "Verified Successfully";
4853
fi
49-
- #if [ ${TRAVIS_RUST_VERSION} == "stable" -a "$TRAVIS_OS_NAME" = "linux" ]; then
50-
#CARGO_TARGET_DIR=cargo_web cargo install --verbose --force cargo-web &&
51-
#cargo web build --verbose --target=asmjs-unknown-emscripten &&
52-
#cargo web test --verbose --target=asmjs-unknown-emscripten;
53-
#fi
54+
- if [ ${TRAVIS_RUST_VERSION} == "stable" -a "$TRAVIS_OS_NAME" = "linux" ]; then
55+
clang --version &&
56+
CARGO_TARGET_DIR=wasm cargo install --verbose --force wasm-pack &&
57+
sed -i 's/\[lib\]/[lib]\ncrate-type = ["cdylib", "rlib"]/' Cargo.toml &&
58+
CC=clang-9 wasm-pack build &&
59+
CC=clang-9 wasm-pack test --node;
60+
fi

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ rand_core = "0.4"
4646
serde_test = "1.0"
4747
bitcoin_hashes = "0.7"
4848

49+
[target.wasm32-unknown-unknown.dev-dependencies]
50+
wasm-bindgen-test = "0.3"
51+
rand = { version = "0.6", features = ["wasm-bindgen"] }
52+
4953
[dependencies.rand]
5054
version = "0.6"
5155
optional = true

secp256k1-sys/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ fn main() {
8484
.define("USE_SCALAR_8X32", Some("1"));
8585
}
8686

87+
if env::var("TARGET").unwrap() == "wasm32-unknown-unknown" {
88+
base_config.include("wasm-sysroot");
89+
}
90+
8791
// secp256k1
8892
base_config.file("depend/secp256k1/contrib/lax_der_parsing.c")
8993
.file("depend/secp256k1/src/secp256k1.c")

secp256k1-sys/src/lib.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ extern "C" {
152152

153153
// Contexts
154154
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_size")]
155-
pub fn secp256k1_context_preallocated_size(flags: c_uint) -> usize;
155+
pub fn secp256k1_context_preallocated_size(flags: c_uint) -> size_t;
156156

157157
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_create")]
158158
pub fn secp256k1_context_preallocated_create(prealloc: *mut c_void, flags: c_uint) -> *mut Context;
@@ -161,7 +161,7 @@ extern "C" {
161161
pub fn secp256k1_context_preallocated_destroy(cx: *mut Context);
162162

163163
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_clone_size")]
164-
pub fn secp256k1_context_preallocated_clone_size(cx: *const Context) -> usize;
164+
pub fn secp256k1_context_preallocated_clone_size(cx: *const Context) -> size_t;
165165

166166
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_context_preallocated_clone")]
167167
pub fn secp256k1_context_preallocated_clone(cx: *const Context, prealloc: *mut c_void) -> *mut Context;
@@ -174,19 +174,19 @@ extern "C" {
174174
// Pubkeys
175175
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_parse")]
176176
pub fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey,
177-
input: *const c_uchar, in_len: usize)
177+
input: *const c_uchar, in_len: size_t)
178178
-> c_int;
179179

180180
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_serialize")]
181181
pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar,
182-
out_len: *mut usize, pk: *const PublicKey,
182+
out_len: *mut size_t, pk: *const PublicKey,
183183
compressed: c_uint)
184184
-> c_int;
185185

186186
// Signatures
187187
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_parse_der")]
188188
pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, sig: *mut Signature,
189-
input: *const c_uchar, in_len: usize)
189+
input: *const c_uchar, in_len: size_t)
190190
-> c_int;
191191

192192
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_parse_compact")]
@@ -196,12 +196,12 @@ extern "C" {
196196

197197
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_parse_der_lax")]
198198
pub fn ecdsa_signature_parse_der_lax(cx: *const Context, sig: *mut Signature,
199-
input: *const c_uchar, in_len: usize)
199+
input: *const c_uchar, in_len: size_t)
200200
-> c_int;
201201

202202
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_serialize_der")]
203203
pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar,
204-
out_len: *mut usize, sig: *const Signature)
204+
out_len: *mut size_t, sig: *const Signature)
205205
-> c_int;
206206

207207
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ecdsa_signature_serialize_compact")]
@@ -462,12 +462,12 @@ mod fuzz_dummy {
462462
}
463463

464464
/// Return dummy size of context struct.
465-
pub unsafe fn secp256k1_context_preallocated_size(_flags: c_uint) -> usize {
465+
pub unsafe fn secp256k1_context_preallocated_size(_flags: c_uint) -> size_t {
466466
mem::size_of::<Context>()
467467
}
468468

469469
/// Return dummy size of context struct.
470-
pub unsafe fn secp256k1_context_preallocated_clone_size(_cx: *mut Context) -> usize {
470+
pub unsafe fn secp256k1_context_preallocated_clone_size(_cx: *mut Context) -> size_t {
471471
mem::size_of::<Context>()
472472
}
473473

@@ -494,7 +494,7 @@ mod fuzz_dummy {
494494
// Pubkeys
495495
/// Parse 33/65 byte pubkey into PublicKey, losing compressed information
496496
pub unsafe fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey,
497-
input: *const c_uchar, in_len: usize)
497+
input: *const c_uchar, in_len: size_t)
498498
-> c_int {
499499
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
500500
match in_len {
@@ -521,7 +521,7 @@ mod fuzz_dummy {
521521

522522
/// Serialize PublicKey back to 33/65 byte pubkey
523523
pub unsafe fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar,
524-
out_len: *mut usize, pk: *const PublicKey,
524+
out_len: *mut size_t, pk: *const PublicKey,
525525
compressed: c_uint)
526526
-> c_int {
527527
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
@@ -546,7 +546,7 @@ mod fuzz_dummy {
546546

547547
// Signatures
548548
pub unsafe fn secp256k1_ecdsa_signature_parse_der(_cx: *const Context, _sig: *mut Signature,
549-
_input: *const c_uchar, _in_len: usize)
549+
_input: *const c_uchar, _in_len: size_t)
550550
-> c_int {
551551
unimplemented!();
552552
}
@@ -562,14 +562,14 @@ mod fuzz_dummy {
562562
}
563563

564564
pub unsafe fn ecdsa_signature_parse_der_lax(_cx: *const Context, _sig: *mut Signature,
565-
_input: *const c_uchar, _in_len: usize)
565+
_input: *const c_uchar, _in_len: size_t)
566566
-> c_int {
567567
unimplemented!();
568568
}
569569

570570
/// Copies up to 72 bytes into output from sig
571571
pub unsafe fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar,
572-
out_len: *mut usize, sig: *const Signature)
572+
out_len: *mut size_t, sig: *const Signature)
573573
-> c_int {
574574
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
575575

secp256k1-sys/src/types.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use core::fmt;
44
pub type c_int = i32;
55
pub type c_uchar = u8;
66
pub type c_uint = u32;
7+
pub type size_t = usize;
78

89
/// This might not match C's `c_char` exactly.
910
/// The way we use it makes it fine either way but this type shouldn't be used outside of the library.
1011
pub type c_char = i8;
1112

1213
/// This is an exact copy of https://doc.rust-lang.org/core/ffi/enum.c_void.html
1314
/// It should be Equivalent to C's void type when used as a pointer.
14-
///
15+
///
1516
/// We can replace this with `core::ffi::c_void` once we update the rustc version to >=1.30.0.
1617
#[repr(u8)]
1718
pub enum c_void {
@@ -39,3 +40,42 @@ mod tests {
3940
assert_eq!(TypeId::of::<types::c_char>(), TypeId::of::<raw::c_char>());
4041
}
4142
}
43+
44+
45+
#[doc(hidden)]
46+
#[cfg(target_arch = "wasm32")]
47+
pub fn sanity_checks_for_wasm() {
48+
use std::mem::{size_of, align_of};
49+
extern "C" {
50+
pub static WASM32_INT_SIZE: c_uchar;
51+
pub static WASM32_INT_ALIGN: c_uchar;
52+
53+
pub static WASM32_UNSIGNED_INT_SIZE: c_uchar;
54+
pub static WASM32_UNSIGNED_INT_ALIGN: c_uchar;
55+
56+
pub static WASM32_SIZE_T_SIZE: c_uchar;
57+
pub static WASM32_SIZE_T_ALIGN: c_uchar;
58+
59+
pub static WASM32_UNSIGNED_CHAR_SIZE: c_uchar;
60+
pub static WASM32_UNSIGNED_CHAR_ALIGN: c_uchar;
61+
62+
pub static WASM32_PTR_SIZE: c_uchar;
63+
pub static WASM32_PTR_ALIGN: c_uchar;
64+
}
65+
unsafe {
66+
assert_eq!(size_of::<c_int>(), WASM32_INT_SIZE as usize);
67+
assert_eq!(align_of::<c_int>(), WASM32_INT_ALIGN as usize);
68+
69+
assert_eq!(size_of::<c_uint>(), WASM32_UNSIGNED_INT_SIZE as usize);
70+
assert_eq!(align_of::<c_uint>(), WASM32_UNSIGNED_INT_ALIGN as usize);
71+
72+
assert_eq!(size_of::<size_t>(), WASM32_SIZE_T_SIZE as usize);
73+
assert_eq!(align_of::<size_t>(), WASM32_SIZE_T_ALIGN as usize);
74+
75+
assert_eq!(size_of::<c_uchar>(), WASM32_UNSIGNED_CHAR_SIZE as usize);
76+
assert_eq!(align_of::<c_uchar>(), WASM32_UNSIGNED_CHAR_ALIGN as usize);
77+
78+
assert_eq!(size_of::<*const ()>(), WASM32_PTR_SIZE as usize);
79+
assert_eq!(align_of::<*const ()>(), WASM32_PTR_ALIGN as usize);
80+
}
81+
}

secp256k1-sys/wasm-sysroot/stdio.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <stddef.h>
2+
#define alignof(type) offsetof (struct { char c; type member; }, member)
3+
4+
extern const unsigned char WASM32_INT_SIZE = sizeof(int);
5+
extern const unsigned char WASM32_INT_ALIGN = alignof(int);
6+
7+
extern const unsigned char WASM32_UNSIGNED_INT_SIZE = sizeof(unsigned int);
8+
extern const unsigned char WASM32_UNSIGNED_INT_ALIGN = alignof(unsigned int);
9+
10+
extern const unsigned char WASM32_SIZE_T_SIZE = sizeof(size_t);
11+
extern const unsigned char WASM32_SIZE_T_ALIGN = alignof(size_t);
12+
13+
extern const unsigned char WASM32_UNSIGNED_CHAR_SIZE = sizeof(unsigned char);
14+
extern const unsigned char WASM32_UNSIGNED_CHAR_ALIGN = alignof(unsigned char);
15+
16+
extern const unsigned char WASM32_PTR_SIZE = sizeof(void*);
17+
extern const unsigned char WASM32_PTR_ALIGN = alignof(void*);

secp256k1-sys/wasm-sysroot/stdlib.h

Whitespace-only changes.

secp256k1-sys/wasm-sysroot/string.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#include <stddef.h>
2+
void *memset(void *s, int c, size_t n);
3+
void *memcpy(void *dest, const void *src, size_t n);
4+
int memcmp(const void *s1, const void *s2, size_t n);

src/context.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ mod std_only {
106106
impl<C: Context> Secp256k1<C> {
107107
/// Lets you create a context in a generic manner(sign/verify/all)
108108
pub fn gen_new() -> Secp256k1<C> {
109+
#[cfg(target_arch = "wasm32")]
110+
ffi::types::sanity_checks_for_wasm();
111+
109112
let buf = vec![0u8; Self::preallocate_size_gen()].into_boxed_slice();
110113
let ptr = Box::into_raw(buf);
111114
Secp256k1 {
@@ -192,6 +195,9 @@ unsafe impl<'buf> Context for AllPreallocated<'buf> {
192195
impl<'buf, C: Context + 'buf> Secp256k1<C> {
193196
/// Lets you create a context with preallocated buffer in a generic manner(sign/verify/all)
194197
pub fn preallocated_gen_new(buf: &'buf mut [u8]) -> Result<Secp256k1<C>, Error> {
198+
#[cfg(target_arch = "wasm32")]
199+
ffi::types::sanity_checks_for_wasm();
200+
195201
if buf.len() < Self::preallocate_size_gen() {
196202
return Err(Error::NotEnoughMemory);
197203
}

src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,33 @@ mod tests {
10601060
assert_tokens(&sig.compact(), &[Token::BorrowedBytes(&SIG_BYTES[..])]);
10611061
assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
10621062
}
1063+
1064+
// For WASM, just run through our general tests in this file all at once.
1065+
#[cfg(target_arch = "wasm32")]
1066+
extern crate wasm_bindgen_test;
1067+
#[cfg(target_arch = "wasm32")]
1068+
use self::wasm_bindgen_test::*;
1069+
#[cfg(target_arch = "wasm32")]
1070+
#[wasm_bindgen_test]
1071+
fn stuff() {
1072+
test_manual_create_destroy();
1073+
test_raw_ctx();
1074+
// Note that, sadly, WASM doesn't currently properly unwind panics, so use of the library
1075+
// via unsafe primitives may cause abort() instead of catch-able panics.
1076+
/*assert!(std::panic::catch_unwind(|| {
1077+
test_panic_raw_ctx();
1078+
}).is_err());*/
1079+
test_preallocation();
1080+
capabilities();
1081+
signature_serialize_roundtrip();
1082+
signature_display();
1083+
signature_lax_der();
1084+
sign_and_verify();
1085+
sign_and_verify_extreme();
1086+
sign_and_verify_fail();
1087+
test_bad_slice();
1088+
test_low_s();
1089+
}
10631090
}
10641091

10651092
#[cfg(all(test, feature = "unstable"))]

0 commit comments

Comments
 (0)