Skip to content

Commit

Permalink
Merge pull request #7 from vbmithr/vb
Browse files Browse the repository at this point in the history
improve interface, more efficient binding
  • Loading branch information
dakk authored Nov 2, 2017
2 parents a6b1989 + 8ecbb81 commit 7a0a140
Show file tree
Hide file tree
Showing 5 changed files with 311 additions and 240 deletions.
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
_build
*.install
**/.merlin
secp256*
setup.data
setup.log
test.native
*.clib
**/.merlin
257 changes: 188 additions & 69 deletions src/secp256k1.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ module BA = struct

let compare a b =
compare_rec a b 0 (length a) (length b)

let create len =
Bigarray.(create char c_layout len)
end

type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
Expand Down Expand Up @@ -49,137 +52,253 @@ module Secret = struct
external verify :
Context.t -> buffer -> bool = "ml_secp256k1_ec_seckey_verify"

let length = 32

type t = buffer

let compare = BA.compare

let of_bytes ctx buf =
if BA.length buf <> 32 then
invalid_arg "Secret.of_bytes: inputs must be 32 bytes long" ;
let of_bytes ctx ?(pos=0) buf =
let buflen = BA.length buf in
if pos < 0 || pos > buflen - length then
invalid_arg "Secret.of_bytes: pos < 0 or pos + 32 > buflen" ;
let buf = BA.sub buf pos length in
match verify ctx buf with
| true -> Some buf
| false -> None

let of_bytes_exn ctx buf =
let of_bytes_exn ctx ?pos buf =
match of_bytes ctx buf with
| None -> failwith "Secret.of_bytes_exn"
| Some sk -> sk

let to_bytes t = t

let write buf ?(pos=0) t =
let buflen = BA.length buf in
if pos < 0 || pos > buflen - length then
invalid_arg "Secret.write: pos < 0 or pos + 32 > buflen" ;
let buf = BA.sub buf pos length in
BA.blit t buf
end

module Public = struct
type t = buffer

let compare = BA.compare

external of_bytes :
Context.t -> buffer -> t = "ml_secp256k1_ec_pubkey_parse"
let length = 64

external to_bytes :
Context.t -> t -> bool -> buffer = "ml_secp256k1_ec_pubkey_serialize"

external of_secret :
Context.t -> Secret.t -> t = "ml_secp256k1_ec_pubkey_create"

let of_bytes ctx buf =
if BA.(length buf <> 33 && length buf <> 65) then
invalid_arg "Public.of_bytes: input must be either 33 or 65 bytes long" ;
try Some (of_bytes ctx buf) with _ -> None
let compare = BA.compare

let of_bytes_exn ctx buf =
match of_bytes ctx buf with
external parse :
Context.t -> buffer -> buffer -> unit = "ml_secp256k1_ec_pubkey_parse"

external write :
Context.t -> buffer -> t -> unit = "ml_secp256k1_ec_pubkey_serialize"

external create :
Context.t -> buffer -> Secret.t -> unit = "ml_secp256k1_ec_pubkey_create"

let of_secret ctx seckey =
let buf = BA.create length in
create ctx buf seckey ;
buf

let of_bytes ctx ?(pos=0) inbuf =
let pklen = BA.length inbuf in
if pos < 0 || pos > pklen - 33 then
invalid_arg "Public.of_bytes: pos < 0 or pos > buflen - 33" ;
let inbuf = BA.(sub inbuf pos (length inbuf)) in
if BA.(length inbuf < 33) then
invalid_arg "Public.of_bytes: input must be at least 33 bytes long" ;
let outbuf = BA.create length in
try
parse ctx outbuf inbuf ;
Some outbuf
with _ -> None

let of_bytes_exn ctx ?pos buf =
match of_bytes ctx ?pos buf with
| None -> failwith "Public.of_bytes_exn"
| Some pk -> pk

let to_bytes ?(compress=true) ctx t =
to_bytes ctx t compress
let buf = BA.create (if compress then 33 else 65) in
write ctx buf t ;
buf

let write ?(compress=true) ctx buf ?(pos=0) t =
let buflen = BA.length buf in
if pos < 0 || (compress && pos > buflen - 33) || pos > buflen - 65 then
invalid_arg "Public.write: pos < 0 or pos > buflen - (33|65)" ;
let len = if compress then 33 else 65 in
let buf = BA.sub buf pos len in
write ctx buf t
end

module Sign = struct
type t = buffer

let compare = BA.compare

let length = 64

external parse :
Context.t -> buffer -> bool -> t = "ml_secp256k1_ecdsa_signature_parse"
Context.t -> buffer -> buffer -> bool -> unit = "ml_secp256k1_ecdsa_signature_parse"
external serialize :
Context.t -> t -> bool -> buffer = "ml_secp256k1_ecdsa_signature_serialize"

let to_compact ctx t = serialize ctx t true
let to_der ctx t = serialize ctx t false

let of_compact ctx buf =
try Some (parse ctx buf true) with _ -> None

let of_compact_exn ctx buf =
Context.t -> buffer -> t -> bool -> int = "ml_secp256k1_ecdsa_signature_serialize"

let to_compact ctx t =
let buf = BA.create length in
let (_:int) = serialize ctx buf t true in
buf

let to_der ctx t =
let buf = BA.create 72 in
let len = serialize ctx buf t false in
BA.sub buf 0 len

let write compact ctx buf ?(pos=0) t =
let buf = BA.(sub buf pos (length buf)) in
serialize ctx buf t compact

let write_compact = write true
let write_der = write false

let of_compact ctx ?(pos=0) inbuf =
let buflen = BA.length inbuf in
if pos < 0 || pos > buflen - length then
invalid_arg "Sign.of_compact: pos < 0 or pos > buflen - 64" ;
let outbuf = BA.create length in
try
parse ctx outbuf (BA.sub inbuf pos length) true ;
Some outbuf
with _ -> None

let of_compact_exn ctx ?pos buf =
match of_compact ctx buf with
| None -> failwith "Sign.of_compact_exn"
| Some signature -> signature

let of_der ctx buf =
try Some (parse ctx buf false) with _ -> None

let of_der_exn ctx buf =
let of_der ctx ?(pos=0) inbuf =
let buflen = BA.length inbuf in
if pos < 0 || pos > buflen - length then
invalid_arg "Sign.of_der: pos < 0 or pos > buflen - 72" ;
let buf = BA.create length in
try
parse ctx buf BA.(sub inbuf pos (length inbuf)) false ;
Some buf
with _ -> None

let of_der_exn ctx ?pos buf =
match of_der ctx buf with
| None -> failwith "Sign.of_der_exn"
| Some signature -> signature

external sign :
Context.t -> Secret.t -> buffer -> t = "ml_secp256k1_ecdsa_sign"
Context.t -> buffer -> Secret.t -> buffer -> unit = "ml_secp256k1_ecdsa_sign"

external verify :
Context.t -> Public.t -> buffer -> t -> bool = "ml_secp256k1_ecdsa_verify"

let sign ctx ~seckey ~msg =
if BA.length msg <> 32 then
invalid_arg "Sign.sign: msg must be 32 bytes long" ;
sign ctx seckey msg

let verify ctx ~pubkey ~msg ~signature =
if BA.length msg <> 32 then
invalid_arg "Sign.verify: msg must be 32 bytes long" ;
verify ctx pubkey msg signature
let write_sign ctx ~seckey ~outbuf ?(outpos=0) ~inbuf ?(inpos=0) () =
let inbuflen = BA.length inbuf in
if inpos < 0 || inpos > inbuflen - 32 then
invalid_arg "Sign.sign: inpos < 0 or inpos > msglen - 32" ;
let outbuflen = BA.length outbuf in
if outpos < 0 || outpos > outbuflen - length then
invalid_arg "Sign.write_sign: outpos < 0 or outpos > outbuf - 64" ;
sign ctx (BA.sub outbuf outpos length) seckey (BA.sub inbuf inpos 32)

let sign ctx ~seckey ?(pos=0) inbuf =
let buflen = BA.length inbuf in
if pos < 0 || pos > buflen - 32 then
invalid_arg "Sign.sign: pos < 0 || pos > msglen - 32" ;
let outbuf = BA.create length in
sign ctx outbuf seckey (BA.sub inbuf pos 32) ;
outbuf

let verify ctx ~pubkey ~signature ?(pos=0) msg =
let msglen = BA.length msg in
if pos < 0 || pos > msglen - 32 then
invalid_arg "Sign.verify: msg must be at least 32 bytes long" ;
verify ctx pubkey (BA.sub msg pos 32) signature
end

module RecoverableSign = struct
type t = buffer

let length = 65

let compare = BA.compare

external parse :
Context.t -> buffer -> int -> t = "ml_secp256k1_ecdsa_recoverable_signature_parse_compact"

let of_compact ctx buf recid =
try Some (parse ctx buf recid) with _ -> None

let of_compact_exn ctx buf recid =
match of_compact ctx buf recid with
Context.t -> buffer -> buffer -> int -> unit = "ml_secp256k1_ecdsa_recoverable_signature_parse_compact"

let of_compact ctx ~recid ?(pos=0) inbuf =
let buflen = BA.length inbuf in
if pos < 0 || pos > buflen - Sign.length then
invalid_arg "RecoverableSign.of_compact: pos < 0 or pos > buflen - 64" ;
let buf = BA.create length in
try
parse ctx buf (BA.sub inbuf pos Sign.length) recid ;
Some buf
with _ -> None

let of_compact_exn ctx ~recid ?pos inbuf =
match of_compact ctx ~recid ?pos inbuf with
| None -> failwith "RecoverableSign.of_compact_exn"
| Some signature -> signature

external serialize :
Context.t -> t -> (buffer * int) = "ml_secp256k1_ecdsa_recoverable_signature_serialize_compact"
Context.t -> buffer -> t -> int = "ml_secp256k1_ecdsa_recoverable_signature_serialize_compact"

let to_compact ctx sign =
let buf = BA.create 64 in
let recid = serialize ctx buf sign in
buf, recid

let to_compact ctx sign = serialize ctx sign
let write_compact ctx buf ?(pos=0) sign =
let buflen = BA.length buf in
if pos < 0 || pos > buflen - Sign.length then
invalid_arg "RecoverableSign.write_compact: pos < 0 or pos > buflen - 64" ;
serialize ctx (BA.sub buf pos Sign.length) sign

external convert :
Context.t -> t -> Sign.t = "ml_secp256k1_ecdsa_recoverable_signature_convert"
Context.t -> buffer -> t -> unit = "ml_secp256k1_ecdsa_recoverable_signature_convert"

let convert ctx sign = convert ctx sign
let convert ctx sign =
let buf = BA.create Sign.length in
convert ctx buf sign ;
buf

external sign :
Context.t -> Secret.t -> buffer -> t = "ml_secp256k1_ecdsa_sign_recoverable"

let sign ctx ~seckey ~msg =
if BA.length msg <> 32 then
invalid_arg "RecoverableSign.sign: msg must be 32 bytes long" ;
sign ctx seckey msg
Context.t -> buffer -> Secret.t -> buffer -> unit = "ml_secp256k1_ecdsa_sign_recoverable"

let write_sign ctx ~seckey ~outbuf ?(outpos=0) ~inbuf ?(inpos=0) () =
let inbuf_len = BA.length inbuf in
if inpos < 0 || inpos > inbuf_len - 32 then
invalid_arg "RecoverableSign.write_sign: inpos < 0 or inpos > inbuflen - 32" ;
let outbuf_len = BA.length outbuf in
if outpos < 0 || outpos > outbuf_len - length then
invalid_arg "RecoverableSign.write_sign: outpos < 0 or outpos > outbuflen - 65" ;
sign ctx (BA.sub outbuf outpos length) seckey (BA.sub inbuf inpos 32)

let sign ctx ~seckey ?(pos=0) inbuf =
let inbuflen = BA.length inbuf in
if pos < 0 || pos > inbuflen - 32 then
invalid_arg "RecoverableSign.sign: buf must be at least 32 bytes long" ;
let outbuf = BA.create length in
sign ctx outbuf seckey (BA.sub inbuf pos 32) ;
outbuf

external recover :
Context.t -> t -> buffer -> Public.t = "ml_secp256k1_ecdsa_recover"

let recover ctx sign ~msg =
if BA.length msg <> 32 then
invalid_arg "RecoverableSign.recover: msg must be 32 bytes long" ;
recover ctx sign msg

Context.t -> buffer -> t -> buffer -> unit = "ml_secp256k1_ecdsa_recover"

let recover ctx sign ?(pos=0) inbuf =
let inbuflen = BA.length inbuf in
if pos < 0 || pos > inbuflen - 32 then
invalid_arg "RecoverableSign.recover: pos < 0 or pos > msglen - 32" ;
let buf = BA.create Public.length in
recover ctx buf sign (BA.sub inbuf pos 32) ;
buf
end
Loading

0 comments on commit 7a0a140

Please sign in to comment.