From 5c0db96180c9250e08611a664c6a3bdccd7efdb4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 9 Jul 2013 10:49:13 -0400 Subject: [PATCH 1/4] Import BitcoinKey/eckey from bitcoinjs-server. --- .gitignore | 3 + binding.gyp | 35 ++++ package.json | 7 +- src/common.h | 17 ++ src/eckey.cc | 571 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/eckey.h | 93 +++++++++ 6 files changed, 725 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 binding.gyp create mode 100644 src/common.h create mode 100644 src/eckey.cc create mode 100644 src/eckey.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2e6e6e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +build/ + diff --git a/binding.gyp b/binding.gyp new file mode 100644 index 0000000..68f8350 --- /dev/null +++ b/binding.gyp @@ -0,0 +1,35 @@ +{ + 'variables': { + 'node_shared_openssl%': 'true' + }, + 'targets': [ + { + 'target_name': 'eckey', + 'sources': [ + 'src/eckey.cc' + ], + 'conditions': [ + ['node_shared_openssl=="false"', { + # so when "node_shared_openssl" is "false", then OpenSSL has been + # bundled into the node executable. So we need to include the same + # header files that were used when building node. + 'include_dirs': [ + '<(node_root_dir)/deps/openssl/openssl/include' + ], + "conditions" : [ + ["target_arch=='ia32'", { + "include_dirs": [ "<(node_root_dir)/deps/openssl/config/piii" ] + }], + ["target_arch=='x64'", { + "include_dirs": [ "<(node_root_dir)/deps/openssl/config/k8" ] + }], + ["target_arch=='arm'", { + "include_dirs": [ "<(node_root_dir)/deps/openssl/config/arm" ] + }] + ] + }] + ] + } + ] +} + diff --git a/package.json b/package.json index 5fa496b..1b9cc5b 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,10 @@ "name": "Stephen Pair", "email": "stephen@bitpay.com" }, + "contributors": [ + {"name": "Stefan Thomas", "email": "moon@justmoon.net"}, + {"name": "Jeff Garzik", "email": "jgarzik@bitpay.com"} + ], "main": "./index", "keywords": [ "bitcoin", @@ -22,7 +26,8 @@ "scripts": {}, "dependencies": { "classtool": ">=1.0.0", - "base58-native": ">=0.1.1" + "base58-native": ">=0.1.1", + "bindings": "1.1.0" }, "devDependencies": {}, "license": "MIT" diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..2f588b5 --- /dev/null +++ b/src/common.h @@ -0,0 +1,17 @@ +#ifndef BITCOINJS_SERVER_INCLUDE_COMMON_H_ +#define BITCOINJS_SERVER_INCLUDE_COMMON_H_ + +#include + +#define REQ_FUN_ARG(I, VAR) \ + if (args.Length() <= (I) || !args[I]->IsFunction()) \ + return v8::ThrowException(v8::Exception::TypeError( \ + v8::String::New("Argument " #I " must be a function"))); \ + v8::Local VAR = v8::Local::Cast(args[I]); + +static v8::Handle VException(const char *msg) { + v8::HandleScope scope; + return v8::ThrowException(v8::Exception::Error(v8::String::New(msg))); +} + +#endif diff --git a/src/eckey.cc b/src/eckey.cc new file mode 100644 index 0000000..9be3745 --- /dev/null +++ b/src/eckey.cc @@ -0,0 +1,571 @@ + +#include + +#include + +#include +#include +#include + +#include +#include + +#include "common.h" +#include "eckey.h" + +using namespace std; +using namespace v8; +using namespace node; + +int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key) +{ + int ok = 0; + BN_CTX *ctx = NULL; + EC_POINT *pub_key = NULL; + + if (!eckey) return 0; + + const EC_GROUP *group = EC_KEY_get0_group(eckey); + + if ((ctx = BN_CTX_new()) == NULL) + goto err; + + pub_key = EC_POINT_new(group); + + if (pub_key == NULL) + goto err; + + if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) + goto err; + + EC_KEY_set_private_key(eckey,priv_key); + EC_KEY_set_public_key(eckey,pub_key); + + ok = 1; + + err: + + if (pub_key) + EC_POINT_free(pub_key); + if (ctx != NULL) + BN_CTX_free(ctx); + + return(ok); +} + +void BitcoinKey::Generate() +{ + if (!EC_KEY_generate_key(ec)) { + lastError = "Error from EC_KEY_generate_key"; + return; + } + + hasPublic = true; + hasPrivate = true; +} + +int BitcoinKey::VerifySignature(const unsigned char *digest, int digest_len, + const unsigned char *sig, int sig_len) +{ + return ECDSA_verify(0, digest, digest_len, sig, sig_len, ec); +} + +void BitcoinKey::EIO_VerifySignature(uv_work_t *req) +{ + verify_sig_baton_t *b = static_cast(req->data); + + b->result = b->key->VerifySignature( + b->digest, b->digestLen, + b->sig, b->sigLen + ); +} + +ECDSA_SIG *BitcoinKey::Sign(const unsigned char *digest, int digest_len) +{ + ECDSA_SIG *sig; + + sig = ECDSA_do_sign(digest, digest_len, ec); + if (sig == NULL) { + // TODO: ERROR + } + + return sig; +} + +void BitcoinKey::Init(Handle target) +{ + HandleScope scope; + Local t = FunctionTemplate::New(New); + + s_ct = Persistent::New(t); + s_ct->InstanceTemplate()->SetInternalFieldCount(1); + s_ct->SetClassName(String::NewSymbol("BitcoinKey")); + + // Accessors + s_ct->InstanceTemplate()->SetAccessor(String::New("private"), + GetPrivate, SetPrivate); + s_ct->InstanceTemplate()->SetAccessor(String::New("public"), + GetPublic, SetPublic); + + // Methods + NODE_SET_PROTOTYPE_METHOD(s_ct, "verifySignature", VerifySignature); + NODE_SET_PROTOTYPE_METHOD(s_ct, "verifySignatureSync", VerifySignatureSync); + NODE_SET_PROTOTYPE_METHOD(s_ct, "regenerateSync", RegenerateSync); + NODE_SET_PROTOTYPE_METHOD(s_ct, "toDER", ToDER); + NODE_SET_PROTOTYPE_METHOD(s_ct, "signSync", SignSync); + + // Static methods + NODE_SET_METHOD(s_ct->GetFunction(), "generateSync", GenerateSync); + NODE_SET_METHOD(s_ct->GetFunction(), "fromDER", FromDER); + + target->Set(String::NewSymbol("BitcoinKey"), + s_ct->GetFunction()); +} + +BitcoinKey::BitcoinKey() : + lastError(NULL), + hasPrivate(false), + hasPublic(false) +{ + ec = EC_KEY_new_by_curve_name(NID_secp256k1); + if (ec == NULL) { + lastError = "Error from EC_KEY_new_by_curve_name"; + } +} + +BitcoinKey::~BitcoinKey() +{ + EC_KEY_free(ec); +} + +BitcoinKey* +BitcoinKey::New() +{ + HandleScope scope; + + Local k = s_ct->GetFunction()->NewInstance(0, NULL); + if (k.IsEmpty()) return NULL; + + return ObjectWrap::Unwrap(k); +} + +Handle +BitcoinKey::New(const Arguments& args) +{ + if (!args.IsConstructCall()) { + return FromConstructorTemplate(s_ct, args); + } + + HandleScope scope; + + BitcoinKey* key = new BitcoinKey(); + if (key->lastError != NULL) { + return VException(key->lastError); + } + + key->Wrap(args.Holder()); + + return scope.Close(args.This()); +} + +Handle +BitcoinKey::GenerateSync(const Arguments& args) +{ + HandleScope scope; + + BitcoinKey* key = BitcoinKey::New(); + + key->Generate(); + + if (key->lastError != NULL) { + return VException(key->lastError); + } + + return scope.Close(key->handle_); +} + +Handle +BitcoinKey::GetPrivate(Local property, const AccessorInfo& info) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + + if (!key->hasPrivate) { + return scope.Close(Null()); + } + + const BIGNUM *bn = EC_KEY_get0_private_key(key->ec); + int priv_size = BN_num_bytes(bn); + + if (bn == NULL) { + // TODO: ERROR: "Error from EC_KEY_get0_private_key(pkey)" + return scope.Close(Null()); + } + + if (priv_size > 32) { + // TODO: ERROR: "Secret too large (Incorrect curve parameters?)" + return scope.Close(Null()); + } + + unsigned char *priv = (unsigned char *)malloc(32); + + int n = BN_bn2bin(bn, &priv[32 - priv_size]); + + if (n != priv_size) { + // TODO: ERROR: "Error from BN_bn2bin(bn, &priv[32 - priv_size])" + return scope.Close(Null()); + } + + Buffer *priv_buf = Buffer::New(32); + memcpy(Buffer::Data(priv_buf), priv, 32); + + free(priv); + + return scope.Close(priv_buf->handle_); +} + +void +BitcoinKey::SetPrivate(Local property, Local value, const AccessorInfo& info) +{ + BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + Handle buffer = value->ToObject(); + const unsigned char *data = (const unsigned char*) Buffer::Data(buffer); + + BIGNUM *bn = BN_bin2bn(data,Buffer::Length(buffer),BN_new()); + EC_KEY_set_private_key(key->ec, bn); + BN_clear_free(bn); + + key->hasPrivate = true; +} + +Handle +BitcoinKey::GetPublic(Local property, const AccessorInfo& info) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + + if (!key->hasPublic) { + return scope.Close(Null()); + } + + // Export public + int pub_size = i2o_ECPublicKey(key->ec, NULL); + if (!pub_size) { + // TODO: ERROR: "Error from i2o_ECPublicKey(key->ec, NULL)" + return scope.Close(Null()); + } + unsigned char *pub_begin, *pub_end; + pub_begin = pub_end = (unsigned char *)malloc(pub_size); + + if (i2o_ECPublicKey(key->ec, &pub_end) != pub_size) { + // TODO: ERROR: "Error from i2o_ECPublicKey(key->ec, &pub)" + return scope.Close(Null()); + } + Buffer *pub_buf = Buffer::New(pub_size); + memcpy(Buffer::Data(pub_buf), pub_begin, pub_size); + + free(pub_begin); + + return scope.Close(pub_buf->handle_); +} + +void +BitcoinKey::SetPublic(Local property, Local value, const AccessorInfo& info) +{ + BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + Handle buffer = value->ToObject(); + const unsigned char *data = (const unsigned char*) Buffer::Data(buffer); + + if (!o2i_ECPublicKey(&(key->ec), &data, Buffer::Length(buffer))) { + // TODO: Error + return; + } + + key->hasPublic = true; +} + +Handle +BitcoinKey::RegenerateSync(const Arguments& args) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + + if (!key->hasPrivate) { + return VException("Regeneration requires a private key."); + } + + EC_KEY *old = key->ec; + + key->ec = EC_KEY_new_by_curve_name(NID_secp256k1); + if (EC_KEY_regenerate_key(key->ec, EC_KEY_get0_private_key(old)) == 1) { + key->hasPublic = true; + } + + EC_KEY_free(old); + + return scope.Close(Undefined()); +} + +Handle +BitcoinKey::ToDER(const Arguments& args) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + + if (!key->hasPrivate || !key->hasPublic) { + return scope.Close(Null()); + } + + // Export DER + int der_size = i2d_ECPrivateKey(key->ec, NULL); + if (!der_size) { + // TODO: ERROR: "Error from i2d_ECPrivateKey(key->ec, NULL)" + return scope.Close(Null()); + } + unsigned char *der_begin, *der_end; + der_begin = der_end = (unsigned char *)malloc(der_size); + + if (i2d_ECPrivateKey(key->ec, &der_end) != der_size) { + // TODO: ERROR: "Error from i2d_ECPrivateKey(key->ec, &der_end)" + return scope.Close(Null()); + } + Buffer *der_buf = Buffer::New(der_size); + memcpy(Buffer::Data(der_buf), der_begin, der_size); + + free(der_begin); + + return scope.Close(der_buf->handle_); +} + +Handle +BitcoinKey::FromDER(const Arguments& args) +{ + HandleScope scope; + + if (args.Length() != 1) { + return VException("One argument expected: der"); + } + if (!Buffer::HasInstance(args[0])) { + return VException("Argument 'der' must be of type Buffer"); + } + + BitcoinKey* key = new BitcoinKey(); + if (key->lastError != NULL) { + return VException(key->lastError); + } + + Handle der_buf = args[0]->ToObject(); + const unsigned char *data = (const unsigned char*) Buffer::Data(der_buf); + + if (!d2i_ECPrivateKey(&(key->ec), &data, Buffer::Length(der_buf))) { + return VException("Error from d2i_ECPrivateKey(&key, &data, len)"); + } + + key->hasPrivate = true; + key->hasPublic = true; + + Handle cons = s_ct->GetFunction(); + Handle external = External::New(key); + Handle result = cons->NewInstance(1, &external); + + return scope.Close(result); +} + +Handle +BitcoinKey::VerifySignature(const Arguments& args) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + + if (args.Length() != 3) { + return VException("Three arguments expected: hash, sig, callback"); + } + if (!Buffer::HasInstance(args[0])) { + return VException("Argument 'hash' must be of type Buffer"); + } + if (!Buffer::HasInstance(args[1])) { + return VException("Argument 'sig' must be of type Buffer"); + } + REQ_FUN_ARG(2, cb); + if (!key->hasPublic) { + return VException("BitcoinKey does not have a public key set"); + } + + Handle hash_buf = args[0]->ToObject(); + Handle sig_buf = args[1]->ToObject(); + + if (Buffer::Length(hash_buf) != 32) { + return VException("Argument 'hash' must be Buffer of length 32 bytes"); + } + + verify_sig_baton_t *baton = new verify_sig_baton_t(); + baton->key = key; + baton->digest = (unsigned char *)Buffer::Data(hash_buf); + baton->digestLen = Buffer::Length(hash_buf); + baton->digestBuf = Persistent::New(hash_buf); + baton->sig = (unsigned char *)Buffer::Data(sig_buf); + baton->sigLen = Buffer::Length(sig_buf); + baton->sigBuf = Persistent::New(sig_buf); + baton->result = -1; + baton->cb = Persistent::New(cb); + + key->Ref(); + + uv_work_t *req = new uv_work_t; + req->data = baton; + + uv_queue_work(uv_default_loop(), req, EIO_VerifySignature, VerifySignatureCallback); + + return scope.Close(Undefined()); +} + +void +BitcoinKey::VerifySignatureCallback(uv_work_t *req, int status) +{ + HandleScope scope; + verify_sig_baton_t *baton = static_cast(req->data); + + baton->key->Unref(); + baton->digestBuf.Dispose(); + baton->sigBuf.Dispose(); + + Local argv[2]; + + argv[0] = Local::New(Null()); + argv[1] = Local::New(Null()); + if (baton->result == -1) { + argv[0] = Exception::TypeError(String::New("Error during ECDSA_verify")); + } else if (baton->result == 0) { + // Signature invalid + argv[1] = Local::New(Boolean::New(false)); + } else if (baton->result == 1) { + // Signature valid + argv[1] = Local::New(Boolean::New(true)); + } else { + argv[0] = Exception::TypeError( + String::New("ECDSA_verify gave undefined return value")); + } + + TryCatch try_catch; + + baton->cb->Call(Context::GetCurrent()->Global(), 2, argv); + + + baton->cb.Dispose(); + + delete baton; + delete req; + + if (try_catch.HasCaught()) { + FatalException(try_catch); + } +} + +Handle +BitcoinKey::VerifySignatureSync(const Arguments& args) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + + if (args.Length() != 2) { + return VException("Two arguments expected: hash, sig"); + } + if (!Buffer::HasInstance(args[0])) { + return VException("Argument 'hash' must be of type Buffer"); + } + if (!Buffer::HasInstance(args[1])) { + return VException("Argument 'sig' must be of type Buffer"); + } + if (!key->hasPublic) { + return VException("BitcoinKey does not have a public key set"); + } + + Handle hash_buf = args[0]->ToObject(); + Handle sig_buf = args[1]->ToObject(); + + const unsigned char *hash_data = (unsigned char *) Buffer::Data(hash_buf); + const unsigned char *sig_data = (unsigned char *) Buffer::Data(sig_buf); + + unsigned int hash_len = Buffer::Length(hash_buf); + unsigned int sig_len = Buffer::Length(sig_buf); + + if (hash_len != 32) { + return VException("Argument 'hash' must be Buffer of length 32 bytes"); + } + + // Verify signature + int result = key->VerifySignature(hash_data, hash_len, sig_data, sig_len); + + if (result == -1) { + return VException("Error during ECDSA_verify"); + } else if (result == 0) { + // Signature invalid + return scope.Close(Boolean::New(false)); + } else if (result == 1) { + // Signature valid + return scope.Close(Boolean::New(true)); + } else { + return VException("ECDSA_verify gave undefined return value"); + } +} + +Handle +BitcoinKey::SignSync(const Arguments& args) +{ + HandleScope scope; + BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + + if (args.Length() != 1) { + return VException("One argument expected: hash"); + } + if (!Buffer::HasInstance(args[0])) { + return VException("Argument 'hash' must be of type Buffer"); + } + if (!key->hasPrivate) { + return VException("BitcoinKey does not have a private key set"); + } + + Handle hash_buf = args[0]->ToObject(); + + const unsigned char *hash_data = (unsigned char *) Buffer::Data(hash_buf); + + unsigned int hash_len = Buffer::Length(hash_buf); + + if (hash_len != 32) { + return VException("Argument 'hash' must be Buffer of length 32 bytes"); + } + + // Create signature + ECDSA_SIG *sig = key->Sign(hash_data, hash_len); + + // Export DER + int der_size = i2d_ECDSA_SIG(sig, NULL); + if (!der_size) { + // TODO: ERROR: "Error from i2d_ECPrivateKey(key->ec, NULL)" + return scope.Close(Null()); + } + unsigned char *der_begin, *der_end; + der_begin = der_end = (unsigned char *)malloc(der_size); + + if (i2d_ECDSA_SIG(sig, &der_end) != der_size) { + // TODO: ERROR: "Error from i2d_ECPrivateKey(key->ec, &der_end)" + return scope.Close(Null()); + } + Buffer *der_buf = Buffer::New(der_size); + memcpy(Buffer::Data(der_buf), der_begin, der_size); + + free(der_begin); + ECDSA_SIG_free(sig); + + return scope.Close(der_buf->handle_); +} + +Persistent BitcoinKey::s_ct; + +extern "C" void +init (Handle target) +{ + BitcoinKey::Init(target); +} + +NODE_MODULE(native, init) diff --git a/src/eckey.h b/src/eckey.h new file mode 100644 index 0000000..72d9d10 --- /dev/null +++ b/src/eckey.h @@ -0,0 +1,93 @@ +#ifndef BITCOINJS_SERVER_INCLUDE_ECKEY_H_ +#define BITCOINJS_SERVER_INCLUDE_ECKEY_H_ + +#include +#include + +using namespace v8; +using namespace node; + +class BitcoinKey : ObjectWrap +{ +private: + + const char *lastError; + EC_KEY *ec; + + bool hasPrivate; + bool hasPublic; + + void Generate(); + + struct verify_sig_baton_t { + // Parameters + BitcoinKey *key; + const unsigned char *digest; + const unsigned char *sig; + int digestLen; + int sigLen; + Persistent digestBuf; + Persistent sigBuf; + + // Result + // -1 = error, 0 = bad sig, 1 = good + int result; + Persistent cb; + }; + + int VerifySignature(const unsigned char *digest, int digest_len, + const unsigned char *sig, int sig_len); + + static void EIO_VerifySignature(uv_work_t *req); + + ECDSA_SIG *Sign(const unsigned char *digest, int digest_len); + +public: + + static Persistent s_ct; + + static void Init(Handle target); + + BitcoinKey(); + ~BitcoinKey(); + + static BitcoinKey* New(); + + static Handle New(const Arguments& args); + static Handle GenerateSync(const Arguments& args); + + static Handle + GetPrivate(Local property, const AccessorInfo& info); + + static void + SetPrivate(Local property, Local value, const AccessorInfo& info); + + static Handle + GetPublic(Local property, const AccessorInfo& info); + + static void + SetPublic(Local property, Local value, const AccessorInfo& info); + + static Handle + RegenerateSync(const Arguments& args); + + static Handle + ToDER(const Arguments& args); + + static Handle + FromDER(const Arguments& args); + + static Handle + VerifySignature(const Arguments& args); + + static void + VerifySignatureCallback(uv_work_t *req, int status); + + static Handle + VerifySignatureSync(const Arguments& args); + + static Handle + SignSync(const Arguments& args); +}; + +#endif From 7da3c3b969430c558e31efdfc60603d7f6284ce9 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 9 Jul 2013 10:51:26 -0400 Subject: [PATCH 2/4] Rename BitcoinKey object to Key --- src/common.h | 4 +-- src/eckey.cc | 84 ++++++++++++++++++++++++++-------------------------- src/eckey.h | 14 ++++----- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/common.h b/src/common.h index 2f588b5..68a163c 100644 --- a/src/common.h +++ b/src/common.h @@ -1,5 +1,5 @@ -#ifndef BITCOINJS_SERVER_INCLUDE_COMMON_H_ -#define BITCOINJS_SERVER_INCLUDE_COMMON_H_ +#ifndef LIBCOIN_SERVER_INCLUDE_COMMON_H_ +#define LIBCOIN_SERVER_INCLUDE_COMMON_H_ #include diff --git a/src/eckey.cc b/src/eckey.cc index 9be3745..9b59276 100644 --- a/src/eckey.cc +++ b/src/eckey.cc @@ -53,7 +53,7 @@ int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key) return(ok); } -void BitcoinKey::Generate() +void Key::Generate() { if (!EC_KEY_generate_key(ec)) { lastError = "Error from EC_KEY_generate_key"; @@ -64,13 +64,13 @@ void BitcoinKey::Generate() hasPrivate = true; } -int BitcoinKey::VerifySignature(const unsigned char *digest, int digest_len, +int Key::VerifySignature(const unsigned char *digest, int digest_len, const unsigned char *sig, int sig_len) { return ECDSA_verify(0, digest, digest_len, sig, sig_len, ec); } -void BitcoinKey::EIO_VerifySignature(uv_work_t *req) +void Key::EIO_VerifySignature(uv_work_t *req) { verify_sig_baton_t *b = static_cast(req->data); @@ -80,7 +80,7 @@ void BitcoinKey::EIO_VerifySignature(uv_work_t *req) ); } -ECDSA_SIG *BitcoinKey::Sign(const unsigned char *digest, int digest_len) +ECDSA_SIG *Key::Sign(const unsigned char *digest, int digest_len) { ECDSA_SIG *sig; @@ -92,14 +92,14 @@ ECDSA_SIG *BitcoinKey::Sign(const unsigned char *digest, int digest_len) return sig; } -void BitcoinKey::Init(Handle target) +void Key::Init(Handle target) { HandleScope scope; Local t = FunctionTemplate::New(New); s_ct = Persistent::New(t); s_ct->InstanceTemplate()->SetInternalFieldCount(1); - s_ct->SetClassName(String::NewSymbol("BitcoinKey")); + s_ct->SetClassName(String::NewSymbol("Key")); // Accessors s_ct->InstanceTemplate()->SetAccessor(String::New("private"), @@ -118,11 +118,11 @@ void BitcoinKey::Init(Handle target) NODE_SET_METHOD(s_ct->GetFunction(), "generateSync", GenerateSync); NODE_SET_METHOD(s_ct->GetFunction(), "fromDER", FromDER); - target->Set(String::NewSymbol("BitcoinKey"), + target->Set(String::NewSymbol("Key"), s_ct->GetFunction()); } -BitcoinKey::BitcoinKey() : +Key::Key() : lastError(NULL), hasPrivate(false), hasPublic(false) @@ -133,24 +133,24 @@ BitcoinKey::BitcoinKey() : } } -BitcoinKey::~BitcoinKey() +Key::~Key() { EC_KEY_free(ec); } -BitcoinKey* -BitcoinKey::New() +Key* +Key::New() { HandleScope scope; Local k = s_ct->GetFunction()->NewInstance(0, NULL); if (k.IsEmpty()) return NULL; - return ObjectWrap::Unwrap(k); + return ObjectWrap::Unwrap(k); } Handle -BitcoinKey::New(const Arguments& args) +Key::New(const Arguments& args) { if (!args.IsConstructCall()) { return FromConstructorTemplate(s_ct, args); @@ -158,7 +158,7 @@ BitcoinKey::New(const Arguments& args) HandleScope scope; - BitcoinKey* key = new BitcoinKey(); + Key* key = new Key(); if (key->lastError != NULL) { return VException(key->lastError); } @@ -169,11 +169,11 @@ BitcoinKey::New(const Arguments& args) } Handle -BitcoinKey::GenerateSync(const Arguments& args) +Key::GenerateSync(const Arguments& args) { HandleScope scope; - BitcoinKey* key = BitcoinKey::New(); + Key* key = Key::New(); key->Generate(); @@ -185,10 +185,10 @@ BitcoinKey::GenerateSync(const Arguments& args) } Handle -BitcoinKey::GetPrivate(Local property, const AccessorInfo& info) +Key::GetPrivate(Local property, const AccessorInfo& info) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + Key* key = node::ObjectWrap::Unwrap(info.Holder()); if (!key->hasPrivate) { return scope.Close(Null()); @@ -225,9 +225,9 @@ BitcoinKey::GetPrivate(Local property, const AccessorInfo& info) } void -BitcoinKey::SetPrivate(Local property, Local value, const AccessorInfo& info) +Key::SetPrivate(Local property, Local value, const AccessorInfo& info) { - BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + Key* key = node::ObjectWrap::Unwrap(info.Holder()); Handle buffer = value->ToObject(); const unsigned char *data = (const unsigned char*) Buffer::Data(buffer); @@ -239,10 +239,10 @@ BitcoinKey::SetPrivate(Local property, Local value, const Accesso } Handle -BitcoinKey::GetPublic(Local property, const AccessorInfo& info) +Key::GetPublic(Local property, const AccessorInfo& info) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + Key* key = node::ObjectWrap::Unwrap(info.Holder()); if (!key->hasPublic) { return scope.Close(Null()); @@ -270,9 +270,9 @@ BitcoinKey::GetPublic(Local property, const AccessorInfo& info) } void -BitcoinKey::SetPublic(Local property, Local value, const AccessorInfo& info) +Key::SetPublic(Local property, Local value, const AccessorInfo& info) { - BitcoinKey* key = node::ObjectWrap::Unwrap(info.Holder()); + Key* key = node::ObjectWrap::Unwrap(info.Holder()); Handle buffer = value->ToObject(); const unsigned char *data = (const unsigned char*) Buffer::Data(buffer); @@ -285,10 +285,10 @@ BitcoinKey::SetPublic(Local property, Local value, const Accessor } Handle -BitcoinKey::RegenerateSync(const Arguments& args) +Key::RegenerateSync(const Arguments& args) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + Key* key = node::ObjectWrap::Unwrap(args.This()); if (!key->hasPrivate) { return VException("Regeneration requires a private key."); @@ -307,10 +307,10 @@ BitcoinKey::RegenerateSync(const Arguments& args) } Handle -BitcoinKey::ToDER(const Arguments& args) +Key::ToDER(const Arguments& args) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + Key* key = node::ObjectWrap::Unwrap(args.This()); if (!key->hasPrivate || !key->hasPublic) { return scope.Close(Null()); @@ -338,7 +338,7 @@ BitcoinKey::ToDER(const Arguments& args) } Handle -BitcoinKey::FromDER(const Arguments& args) +Key::FromDER(const Arguments& args) { HandleScope scope; @@ -349,7 +349,7 @@ BitcoinKey::FromDER(const Arguments& args) return VException("Argument 'der' must be of type Buffer"); } - BitcoinKey* key = new BitcoinKey(); + Key* key = new Key(); if (key->lastError != NULL) { return VException(key->lastError); } @@ -372,10 +372,10 @@ BitcoinKey::FromDER(const Arguments& args) } Handle -BitcoinKey::VerifySignature(const Arguments& args) +Key::VerifySignature(const Arguments& args) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + Key* key = node::ObjectWrap::Unwrap(args.This()); if (args.Length() != 3) { return VException("Three arguments expected: hash, sig, callback"); @@ -388,7 +388,7 @@ BitcoinKey::VerifySignature(const Arguments& args) } REQ_FUN_ARG(2, cb); if (!key->hasPublic) { - return VException("BitcoinKey does not have a public key set"); + return VException("Key does not have a public key set"); } Handle hash_buf = args[0]->ToObject(); @@ -420,7 +420,7 @@ BitcoinKey::VerifySignature(const Arguments& args) } void -BitcoinKey::VerifySignatureCallback(uv_work_t *req, int status) +Key::VerifySignatureCallback(uv_work_t *req, int status) { HandleScope scope; verify_sig_baton_t *baton = static_cast(req->data); @@ -462,10 +462,10 @@ BitcoinKey::VerifySignatureCallback(uv_work_t *req, int status) } Handle -BitcoinKey::VerifySignatureSync(const Arguments& args) +Key::VerifySignatureSync(const Arguments& args) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + Key* key = node::ObjectWrap::Unwrap(args.This()); if (args.Length() != 2) { return VException("Two arguments expected: hash, sig"); @@ -477,7 +477,7 @@ BitcoinKey::VerifySignatureSync(const Arguments& args) return VException("Argument 'sig' must be of type Buffer"); } if (!key->hasPublic) { - return VException("BitcoinKey does not have a public key set"); + return VException("Key does not have a public key set"); } Handle hash_buf = args[0]->ToObject(); @@ -510,10 +510,10 @@ BitcoinKey::VerifySignatureSync(const Arguments& args) } Handle -BitcoinKey::SignSync(const Arguments& args) +Key::SignSync(const Arguments& args) { HandleScope scope; - BitcoinKey* key = node::ObjectWrap::Unwrap(args.This()); + Key* key = node::ObjectWrap::Unwrap(args.This()); if (args.Length() != 1) { return VException("One argument expected: hash"); @@ -522,7 +522,7 @@ BitcoinKey::SignSync(const Arguments& args) return VException("Argument 'hash' must be of type Buffer"); } if (!key->hasPrivate) { - return VException("BitcoinKey does not have a private key set"); + return VException("Key does not have a private key set"); } Handle hash_buf = args[0]->ToObject(); @@ -560,12 +560,12 @@ BitcoinKey::SignSync(const Arguments& args) return scope.Close(der_buf->handle_); } -Persistent BitcoinKey::s_ct; +Persistent Key::s_ct; extern "C" void init (Handle target) { - BitcoinKey::Init(target); + Key::Init(target); } NODE_MODULE(native, init) diff --git a/src/eckey.h b/src/eckey.h index 72d9d10..b506051 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -1,5 +1,5 @@ -#ifndef BITCOINJS_SERVER_INCLUDE_ECKEY_H_ -#define BITCOINJS_SERVER_INCLUDE_ECKEY_H_ +#ifndef LIBCOIN_SERVER_INCLUDE_ECKEY_H_ +#define LIBCOIN_SERVER_INCLUDE_ECKEY_H_ #include #include @@ -7,7 +7,7 @@ using namespace v8; using namespace node; -class BitcoinKey : ObjectWrap +class Key : ObjectWrap { private: @@ -21,7 +21,7 @@ private: struct verify_sig_baton_t { // Parameters - BitcoinKey *key; + Key *key; const unsigned char *digest; const unsigned char *sig; int digestLen; @@ -48,10 +48,10 @@ public: static void Init(Handle target); - BitcoinKey(); - ~BitcoinKey(); + Key(); + ~Key(); - static BitcoinKey* New(); + static Key* New(); static Handle New(const Arguments& args); static Handle GenerateSync(const Arguments& args); From 7e23e5ba0e4fd2a9d6518b0101e7d65ae9ae2308 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 9 Jul 2013 10:53:04 -0400 Subject: [PATCH 3/4] Wrap C++ Key object inside "bitcoin" namespace. --- src/eckey.cc | 6 +++++- src/eckey.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/eckey.cc b/src/eckey.cc index 9b59276..8c99e20 100644 --- a/src/eckey.cc +++ b/src/eckey.cc @@ -53,6 +53,8 @@ int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key) return(ok); } +namespace bitcoin { + void Key::Generate() { if (!EC_KEY_generate_key(ec)) { @@ -562,10 +564,12 @@ Key::SignSync(const Arguments& args) Persistent Key::s_ct; +}; // namespace bitcoin + extern "C" void init (Handle target) { - Key::Init(target); + bitcoin::Key::Init(target); } NODE_MODULE(native, init) diff --git a/src/eckey.h b/src/eckey.h index b506051..00a0ae1 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -7,6 +7,8 @@ using namespace v8; using namespace node; +namespace bitcoin { + class Key : ObjectWrap { private: @@ -90,4 +92,6 @@ public: SignSync(const Arguments& args); }; +}; // namespace bitcoin + #endif From adc3a99b960966215fdfa992cc00646b0198c39b Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 9 Jul 2013 10:57:21 -0400 Subject: [PATCH 4/4] .gitignore: update to match base58-native module --- .gitignore | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index a2e6e6e..e3fbd98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ - -build/ - +build +node_modules