Browse Source

py3port: rewrite secp256k1 extension module

MMGen 6 years ago
parent
commit
59007ee697
1 changed files with 57 additions and 10 deletions
  1. 57 10
      extmod/secp256k1mod.c

+ 57 - 10
extmod/secp256k1mod.c

@@ -23,39 +23,86 @@ static PyObject * priv2pub(PyObject *self, PyObject *args) {
 	const unsigned char * privkey;
 	const unsigned char * privkey;
 	const int klen;
 	const int klen;
 	const int compressed;
 	const int compressed;
-	if (!PyArg_ParseTuple(args, "t#I", &privkey, &klen, &compressed))
+	if (!PyArg_ParseTuple(args, "y#I", &privkey, &klen, &compressed)) {
+		PyErr_SetString(PyExc_ValueError, "Unable to parse extension mod arguments");
 		return NULL;
 		return NULL;
+	}
 	if (klen != 32) {
 	if (klen != 32) {
 		PyErr_SetString(PyExc_ValueError, "Private key length not 32 bytes");
 		PyErr_SetString(PyExc_ValueError, "Private key length not 32 bytes");
 		return NULL;
 		return NULL;
 	}
 	}
 	secp256k1_pubkey pubkey;
 	secp256k1_pubkey pubkey;
-	size_t pubkeyclen = compressed == 1 ? 33: 65;
+	size_t pubkeyclen = compressed == 1 ? 33 : 65;
 	unsigned char pubkeyc[pubkeyclen];
 	unsigned char pubkeyc[pubkeyclen];
 	static secp256k1_context *ctx = NULL;
 	static secp256k1_context *ctx = NULL;
 	if (ctx == NULL) {
 	if (ctx == NULL) {
 	/*	puts ("Initializing context"); */
 	/*	puts ("Initializing context"); */
 		ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
 		ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
 	}
 	}
+	if (ctx == NULL) {
+		PyErr_SetString(PyExc_RuntimeError, "Context initialization failed");
+		return NULL;
+	}
 	if (secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) != 1) {
 	if (secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) != 1) {
 		PyErr_SetString(PyExc_RuntimeError, "Public key creation failed");
 		PyErr_SetString(PyExc_RuntimeError, "Public key creation failed");
 		return NULL;
 		return NULL;
 	}
 	}
 	if (secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey,
 	if (secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey,
-			compressed == 1 ? SECP256K1_EC_COMPRESSED: SECP256K1_EC_UNCOMPRESSED) != 1) {
+			compressed == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED) != 1) {
 		PyErr_SetString(PyExc_RuntimeError, "Public key serialization failed");
 		PyErr_SetString(PyExc_RuntimeError, "Public key serialization failed");
 		return NULL;
 		return NULL;
 	}
 	}
-	return Py_BuildValue("s#", pubkeyc,pubkeyclen);
+	return Py_BuildValue("y#", pubkeyc,pubkeyclen);
 }
 }
 
 
-static PyMethodDef secp256k1Methods[] = {
+/* https://docs.python.org/3/howto/cporting.html */
+
+struct module_state {
+    PyObject *error;
+};
+
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+
+static PyMethodDef secp256k1_methods[] = {
 	{"priv2pub", priv2pub, METH_VARARGS, "Generate pubkey from privkey using libsecp256k1"},
 	{"priv2pub", priv2pub, METH_VARARGS, "Generate pubkey from privkey using libsecp256k1"},
-	{NULL, NULL, 0, NULL} /* Sentinel */
+    {NULL, NULL}
 };
 };
 
 
-PyMODINIT_FUNC initsecp256k1(void) {
-	PyObject *m;
-	m = Py_InitModule("secp256k1", secp256k1Methods);
-	if (m == NULL) return;
+static int secp256k1_traverse(PyObject *m, visitproc visit, void *arg) {
+    Py_VISIT(GETSTATE(m)->error);
+    return 0;
+}
+
+static int secp256k1_clear(PyObject *m) {
+    Py_CLEAR(GETSTATE(m)->error);
+    return 0;
+}
+
+static struct PyModuleDef moduledef = {
+        PyModuleDef_HEAD_INIT,
+        "secp256k1",
+        NULL,
+        sizeof(struct module_state),
+        secp256k1_methods,
+        NULL,
+        secp256k1_traverse,
+        secp256k1_clear,
+        NULL
+};
+
+#define INITERROR return NULL
+
+PyMODINIT_FUNC PyInit_secp256k1(void) {
+    PyObject *module = PyModule_Create(&moduledef);
+
+    if (module == NULL)
+        INITERROR;
+    struct module_state *st = GETSTATE(module);
+
+    st->error = PyErr_NewException("secp256k1.Error", NULL, NULL);
+    if (st->error == NULL) {
+        Py_DECREF(module);
+        INITERROR;
+    }
+    return module;
 }
 }