commit 27b3f29a888d9d00aab1bd651483b099d720d2e5
parent 71fbcb72534670a7068afce8a346753bfc61cfd7
Author: nolash <dev@holbrook.no>
Date: Thu, 23 Sep 2021 21:15:20 +0200
Add requirements to install
Diffstat:
4 files changed, 144 insertions(+), 50 deletions(-)
diff --git a/pylibswarm/runnable/bmt.py b/pylibswarm/runnable/bmt.py
@@ -4,6 +4,10 @@ import sys
import logging
import select
+# local imports
+from pylibswarm.arg import stdin_arg
+
+
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
@@ -17,22 +21,6 @@ argparser.add_argument('data', nargs='?', type=str, help='data input for BMT has
largs = argparser.parse_args(sys.argv[1:])
-def stdin_arg():
- """Retreive input arguments from stdin if they exist.
-
- Method does not block, and expects arguments to be ready on stdin before being called.
-
- :rtype: str
- :returns: Input arguments string
- """
- h = select.select([sys.stdin.buffer], [], [])
- if len(h[0]) > 0:
- v = h[0][0].read()
- #return v.rstrip()
- return v
- return None
-
-
if largs.v:
logg.setLevel(logging.DEBUG)
@@ -58,7 +46,7 @@ logg.info('hashing {} bytes input with {} length prefix'.format(int(input_data_
def main():
# TODO: why does this segfault just one line before? - probably refcount related
import swarm
- r = swarm.bmt(input_data, input_data_length, data_length)
+ r = swarm.bmt_hash(input_data, input_data_length, data_length)
if largs.b:
sys.stdout.buffer.write(r[:32])
diff --git a/pylibswarm/runnable/file.py b/pylibswarm/runnable/file.py
@@ -4,6 +4,10 @@ import sys
import argparse
import logging
+# local imports
+from pylibswarm.io import Outputter
+
+
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
@@ -18,30 +22,6 @@ argparser.add_argument('file', nargs='?', type=str, help='file to hash')
largs = argparser.parse_args(sys.argv[1:])
-class Outputter:
-
- def __init__(self, outdir, prepend_hash=False):
- self.outdir = outdir
- self.prepend_hash = prepend_hash
- os.makedirs(self.outdir, exist_ok=True)
- logg.info('outputter set to {}'.format(self.outdir))
-
-
- def dump(self, hsh, data):
- hsh_hex = hsh.hex()
- fp = os.path.join(self.outdir, hsh_hex)
- f = open(fp, 'wb')
-
- l = len(data)
- if self.prepend_hash:
- l += len(hsh)
- f.write(hsh)
- f.write(data)
- f.close()
-
- logg.debug('wrote {} bytes for chunk file {}'.format(l, hsh_hex))
-
-
if largs.vv:
logg.setLevel(logging.DEBUG)
elif largs.v:
diff --git a/setup.py b/setup.py
@@ -6,6 +6,16 @@ root_dir = os.path.dirname(os.path.realpath(__file__))
default_swarm_dir = os.path.join(root_dir, 'aux', 'libswarm-ng')
swarm_dir = os.environ.get('LIBSWARM_DIR', default_swarm_dir)
+requirements = []
+f = open('requirements.txt', 'r')
+while True:
+ l = f.readline()
+ if l == '':
+ break
+ requirements.append(l.rstrip())
+f.close()
+
+
def main():
setup(
name="swarm",
@@ -13,6 +23,7 @@ def main():
description="Swarm tooling",
author="Louis Holbrook",
author_email="dev@holbrook.no",
+ install_requires=requirements,
ext_modules=[
Extension("swarm", [
"src/python_swarm.c",
diff --git a/src/python_swarm.c b/src/python_swarm.c
@@ -7,22 +7,36 @@
#include "bmt.h"
#include "swarmfile.h"
+#include "soc.h"
-static void filehash_callback(const char *hash, const char *data, size_t data_length, void *callback_static) {
+static void client_callback_do(const unsigned char *hash, const unsigned char *data, size_t data_length, void *callback_static) {
PyObject *callback = (PyObject*)callback_static;
PyObject_CallFunction(callback, "y#y#", hash, SWARM_WORD_SIZE, data, data_length);
}
-static bmt_spansize_t filehash_path(filehash_t *fctx, const char *filepath) {
+static void soc_sign_callback(char *z, const unsigned char *address, const unsigned char *data, void *callback_static) {
+ PyObject *callback = (PyObject*)callback_static;
+ PyObject *r;
+ unsigned char *signature_bytes;
+
+
+ r = PyObject_CallFunction(callback, "y#y#", address, SWARM_ADDRESS_SIZE, data, SWARM_WORD_SIZE);
+ signature_bytes = PyBytes_AsString(r);
+
+ memcpy(z, signature_bytes, SWARM_SIGNATURE_SIZE);
+}
+
+
+static bmt_spansize_t filehash_path(filehash_t *fctx, const unsigned char *filepath) {
int fd;
int r;
int c;
size_t l;
struct stat st;
- char buf[SWARM_BLOCK_SIZE];
+ unsigned char buf[SWARM_BLOCK_SIZE];
fd = open(filepath, O_RDONLY);
if (fd == -1) {
@@ -60,20 +74,25 @@ static bmt_spansize_t filehash_path(filehash_t *fctx, const char *filepath) {
}
-static PyObject* method_bmt(PyObject *self, PyObject *args) {
+static PyObject* method_bmt_hash(PyObject *self, PyObject *args) {
bmt_t bctx;
- const char *input;
+ const unsigned char *input;
Py_ssize_t input_length;
bmt_spansize_t data_length;
int r;
r = PyArg_ParseTuple(args, "yIL", &input, &input_length, &data_length);
if (r != 1) {
+ PyErr_SetString(PyExc_ValueError, "could not build values");
return NULL;
}
bmt_init(&bctx, (char*)input, input_length, data_length);
- bmt_sum(&bctx);
+ r = bmt_sum(&bctx);
+ if (r != 0) {
+ PyErr_SetString(PyExc_RuntimeError, "bmt hashing failed");
+ return NULL;
+ }
return Py_BuildValue("y#", &bctx.buf, SWARM_WORD_SIZE);
}
@@ -81,29 +100,125 @@ static PyObject* method_bmt(PyObject *self, PyObject *args) {
static PyObject* method_filehash_path(PyObject *self, PyObject *args) {
filehash_t fctx;
- const char *inpath;
+ const unsigned char *inpath;
PyObject *client_callback;
int r;
r = PyArg_ParseTuple(args, "s|O", &inpath, &client_callback);
if (r != 1) {
+ PyErr_SetString(PyExc_ValueError, "could not build values");
return NULL;
}
if (client_callback == NULL) {
filehash_init(&fctx);
} else {
- filehash_init_callback(&fctx, filehash_callback, client_callback);
+ filehash_init_callback(&fctx, client_callback_do, client_callback);
}
r = filehash_path(&fctx, inpath);
+ if (r == -1) {
+ PyErr_Format(PyExc_RuntimeError, "file hashing failed for path %s", inpath);
+ return NULL;
+ }
return Py_BuildValue("y#", &fctx.buf, SWARM_WORD_SIZE);
}
+static PyObject* method_soc_identifier(PyObject *self, PyObject *args) {
+ int r;
+ const PyBytesObject *topic;
+ const PyBytesObject *index;
+ const unsigned char *topic_bytes;
+ const unsigned char *index_bytes;
+ char out[128];
+
+ r = PyArg_ParseTuple(args, "SS", &topic, &index);
+ if (r != 1) {
+ PyErr_SetString(PyExc_ValueError, "could not build values");
+ return NULL;
+ }
+
+ topic_bytes = PyBytes_AsString((PyObject*)topic);
+ index_bytes = PyBytes_AsString((PyObject*)index);
+ r = soc_identifier(out, topic_bytes, index_bytes);
+ if (r != 0) {
+ PyErr_SetString(PyExc_RuntimeError, "could not build identifier");
+ return NULL;
+ }
+
+ return Py_BuildValue("y#", &out, SWARM_WORD_SIZE);
+}
+
+
+static PyObject* method_soc_create(PyObject *self, PyObject *args) {
+ int r;
+ bmt_t bctx;
+ const PyBytesObject *identifier;
+ unsigned char *identifier_bytes;
+ const PyBytesObject *input;
+ const PyBytesObject *address;
+ unsigned char *address_bytes;
+ size_t input_length;
+ unsigned char *p;
+ unsigned char soc_hash[128];
+ bmt_spansize_t data_length;
+ unsigned char soc_serialized[SWARM_DATA_LENGTH_TYPESIZE + SWARM_BLOCK_SIZE];
+ soc_chunk_t chunk;
+ PyObject *client_callback;
+ PyObject *keystore_callback;
+
+ client_callback = NULL;
+
+ r = PyArg_ParseTuple(args, "SSSILO|O", &identifier, &address, &input, &input_length, &data_length, &keystore_callback, &client_callback);
+ if (r != 1) {
+ PyErr_SetString(PyExc_ValueError, "could not build values");
+ return NULL;
+ }
+ memcpy(&chunk.data.payload_sz, &input_length, sizeof(input_length));
+ memcpy(chunk.data.span, &data_length, SWARM_DATA_LENGTH_TYPESIZE);
+ if (data_length > SWARM_BLOCK_SIZE) {
+ PyErr_Format(PyExc_ValueError, "data payload size %d exceeds maximum of %d bytes", chunk.data.payload_sz, SWARM_BLOCK_SIZE);
+ return NULL;
+ }
+ chunk.data.payload = PyBytes_AsString((PyObject*)input);
+ identifier_bytes = PyBytes_AsString((PyObject*)identifier);
+ address_bytes = PyBytes_AsString((PyObject*)address);
+ memcpy(chunk.identifier, identifier_bytes, SWARM_SOC_IDENTIFIER_SIZE);
+ bmt_init(&bctx, (char*)chunk.data.payload, data_length, data_length);
+ r = bmt_sum(&bctx);
+ if (r != 0) {
+ PyErr_SetString(PyExc_RuntimeError, "bmt hashing failed");
+ return NULL;
+ }
+ memcpy(chunk.data.hash, bctx.buf, SWARM_WORD_SIZE);
+ r = soc_digest(&chunk, soc_hash);
+ if (r != 0) {
+ PyErr_SetString(PyExc_RuntimeError, "soc digest failed");
+ return NULL;
+ }
+ soc_sign_callback(&chunk.signature, address_bytes, soc_hash, keystore_callback);
+
+ p = soc_serialize(&chunk, soc_serialized, &input_length);
+ if (p == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "soc serialize failed");
+ return NULL;
+ }
+
+ if (client_callback != NULL) {
+// client_callback_do(soc_hash, soc_serialized, input_length, client_callback);
+ }
+
+ return Py_BuildValue("y#y#y#", chunk.signature, SWARM_SIGNATURE_SIZE, soc_hash, SWARM_WORD_SIZE, soc_serialized, input_length);
+
+}
+
+
static PyMethodDef SwarmMethods[] = {
- {"bmt", method_bmt, METH_VARARGS, "Calculate the BMT hash of the given data"},
+ {"bmt_hash", method_bmt_hash, METH_VARARGS, "Calculate the BMT hash of the given data"},
{"filehash_path", method_filehash_path, METH_VARARGS, "Calculate the Swarm file hash of the data from the given file path, with optional callback to receive chunks"},
+ {"soc_identifier", method_soc_identifier, METH_VARARGS, "Build an SOC identifier from given topic and index"},
+ {"soc_create", method_soc_create, METH_VARARGS, "Build an SOC chunk from given data and identifier"},
{NULL, NULL, 0, NULL},
};