Browse Source

Version 0.8.6

New features/improvements:

	* Address generation using secp256k1 library (Linux only)

Instructions for installing the secp256k1 library on your system:

	doc/wiki/install-linux/Install-MMGen-on-Debian-or-Ubuntu-Linux.md

If secp256k1 is not installed on the system, MMGen remains usable. It just falls
back to 'keyconv', or failing that, python-ecdsa for generating addresses.
philemon 8 years ago
parent
commit
0be6059674
4 changed files with 52 additions and 25 deletions
  1. 45 19
      extmod/secp256k1mod.c
  2. 1 1
      mmgen/globalvars.py
  3. 4 3
      setup.py
  4. 2 2
      test/gentest.py

+ 45 - 19
extmod/secp256k1mod.c

@@ -1,35 +1,61 @@
+/*
+  mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
+  Copyright (C)2013-2016 Philemon <mmgen-py@yandex.com>
+
+  This program is free software: you can redistribute it and/or modify it under
+  the terms of the GNU General Public License as published by the Free Software
+  Foundation, either version 3 of the License, or (at your option) any later
+  version.
+
+  This program is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+  details.
+
+  You should have received a copy of the GNU General Public License along with
+  this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
 #include <Python.h>
 #include <secp256k1.h>
 
 static PyObject * priv2pub(PyObject *self, PyObject *args) {
-    const unsigned char * privkey;
-    const int klen;
-    const int compressed;
-    if (!PyArg_ParseTuple(args, "t#I", &privkey, &klen, &compressed))
-        return NULL;
-    if (klen != 32) return NULL;
-    secp256k1_pubkey pubkey;
-    size_t pubkeyclen = compressed == 1 ? 33: 65;
-    unsigned char pubkeyc[pubkeyclen];
+	const unsigned char * privkey;
+	const int klen;
+	const int compressed;
+	if (!PyArg_ParseTuple(args, "t#I", &privkey, &klen, &compressed))
+		return NULL;
+	if (klen != 32) {
+		PyErr_SetString(PyExc_ValueError, "Private key length not 32 bytes");
+		return NULL;
+	}
+	secp256k1_pubkey pubkey;
+	size_t pubkeyclen = compressed == 1 ? 33: 65;
+	unsigned char pubkeyc[pubkeyclen];
 	static secp256k1_context *ctx = NULL;
 	if (ctx == NULL) {
 	/*	puts ("Initializing context"); */
 		ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
 	}
-    if (secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) != 1) return NULL;
-    if (secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey,
-			compressed == 1 ? SECP256K1_EC_COMPRESSED: SECP256K1_EC_UNCOMPRESSED) != 1)
-				return NULL;
-    return Py_BuildValue("s#", pubkeyc,pubkeyclen);
+	if (secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) != 1) {
+		PyErr_SetString(PyExc_RuntimeError, "Public key creation failed");
+		return NULL;
+	}
+	if (secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey,
+			compressed == 1 ? SECP256K1_EC_COMPRESSED: SECP256K1_EC_UNCOMPRESSED) != 1) {
+		PyErr_SetString(PyExc_RuntimeError, "Public key serialization failed");
+		return NULL;
+	}
+	return Py_BuildValue("s#", pubkeyc,pubkeyclen);
 }
 
 static PyMethodDef secp256k1Methods[] = {
-    {"priv2pub", priv2pub, METH_VARARGS, "Generate pubkey from privkey using libsecp256k1"},
-    {NULL, NULL, 0, NULL} /* Sentinel */
+	{"priv2pub", priv2pub, METH_VARARGS, "Generate pubkey from privkey using libsecp256k1"},
+	{NULL, NULL, 0, NULL} /* Sentinel */
 };
 
 PyMODINIT_FUNC initsecp256k1(void) {
-    PyObject *m;
-    m = Py_InitModule("secp256k1", secp256k1Methods);
-    if (m == NULL) return;
+	PyObject *m;
+	m = Py_InitModule("secp256k1", secp256k1Methods);
+	if (m == NULL) return;
 }

+ 1 - 1
mmgen/globalvars.py

@@ -51,7 +51,7 @@ prog_name = os.path.basename(sys.argv[0])
 author    = 'Philemon'
 email     = '<mmgen-py@yandex.com>'
 Cdates    = '2013-2016'
-version   = '0.8.6rc1'
+version   = '0.8.6'
 
 required_opts = [
 	'quiet','verbose','debug','outdir','echo_passphrase','passwd_file',

+ 4 - 3
setup.py

@@ -18,7 +18,7 @@
 
 from distutils.core import setup,Extension
 from distutils.command.build_ext import build_ext
-import os
+import sys,os
 from shutil import copy2
 
 # install extension module in repository after building
@@ -45,7 +45,7 @@ module1 = Extension(
 setup(
 		name         = 'mmgen',
 		description  = 'A complete Bitcoin offline/online wallet solution for the command line',
-		version      = '0.8.6rc1',
+		version      = '0.8.6',
 		author       = 'Philemon',
 		author_email = 'mmgen-py@yandex.com',
 		url          = 'https://github.com/mmgen/mmgen',
@@ -53,7 +53,8 @@ setup(
 		platforms    = 'Linux, MS Windows, Raspberry PI',
 		keywords     = 'Bitcoin, wallet, cold storage, offline storage, open-source, command-line, Python, Bitcoin Core, bitcoind, hd, deterministic, hierarchical, secure, anonymous',
 		cmdclass     = { 'build_ext': my_build_ext },
-		ext_modules = [module1],
+		# disable building of secp256k1 extension module on Windows
+		ext_modules = [module1] if sys.platform[:5] == 'linux' else [],
 		py_modules = [
 			'mmgen.__init__',
 			'mmgen.addr',

+ 2 - 2
test/gentest.py

@@ -48,8 +48,8 @@ opts_data = {
 as specified by the user:
 
     1) with the native Python ecdsa library (very slow)
-    2) with the 'keyconv' utility from the 'vanitygen' package (the default)
-    3) using bitcoincore.org's secp256k1 library (very fast, experimental)
+    2) with the 'keyconv' utility from the 'vanitygen' package (old default)
+    3) using bitcoincore.org's secp256k1 library (default from v0.8.6)
 
 This test suite compares the output of these different methods against each
 other over set of randomly generated secret keys ({snum} by default).