pylibswarm

Python3 wrapper for libswarm-ng
git clone git://git.defalsify.org/pylibswarm.git
Log | Files | Refs | Submodules | README | LICENSE

commit 991e6e303c289f9447fd0ce796a341edda18797b
parent 27b3f29a888d9d00aab1bd651483b099d720d2e5
Author: nolash <dev@holbrook.no>
Date:   Fri, 24 Sep 2021 05:40:10 +0200

Add missing files

Diffstat:
Apylibswarm/arg.py | 18++++++++++++++++++
Apylibswarm/io.py | 29+++++++++++++++++++++++++++++
Apylibswarm/runnable/soc.py | 176+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apylibswarm/soc.py | 6++++++
Arequirements.txt | 2++
5 files changed, 231 insertions(+), 0 deletions(-)

diff --git a/pylibswarm/arg.py b/pylibswarm/arg.py @@ -0,0 +1,18 @@ +# standard imports +import select +import sys + + +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 + return None diff --git a/pylibswarm/io.py b/pylibswarm/io.py @@ -0,0 +1,29 @@ +# standard imports +import os +import logging + +logg = logging.getLogger(__name__) + + +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)) diff --git a/pylibswarm/runnable/soc.py b/pylibswarm/runnable/soc.py @@ -0,0 +1,176 @@ +# standard imports +import argparse +import sys +import logging +import os + +# external imports +from hexathon import ( + pad as hex_pad, + strip_0x, + ) + +# local imports +from pylibswarm.soc import from_str as soc_meta_from_str +from pylibswarm.sign import DefaultSigner +from pylibswarm.arg import stdin_arg +from pylibswarm.io import Outputter + + +logging.basicConfig(level=logging.WARNING) +logg = logging.getLogger() + +argparser = argparse.ArgumentParser() +argparser.add_argument('-n', action='store_true', help='skip newline at end of output. (stdout output only)') +argparser.add_argument('-b', action='store_true', help='output raw bytes.') +argparser.add_argument('-v', action='store_true', help='verbose output') +argparser.add_argument('-vv', action='store_true', help='very verbose output') +argparser.add_argument('-y', type=str, help='key provider (path to keyfile)') +argparser.add_argument('-o', type=str, help='chunk output location') +argparser.add_argument('-f', type=str, help='data input location') +argparser.add_argument('-l', dest='data_length', type=int, help='length of data represented by preimage') +argparser.add_argument('-u', action='store_true', help='treat input as utf-8 string') +argparser.add_argument('--topic-string', dest='topic_string', type=str, help='string to use as soc topic.') +argparser.add_argument('-t', '--topic', type=str, help='hex value to use as soc topic. overrides --topic-string.') +argparser.add_argument('--index-string', dest='index_string', type=str, help='string to use as soc index.') +argparser.add_argument('-i', '--index', type=str, help='hex value to use as soc index. overrides --index-string.') +argparser.add_argument('--id', action='store_true', help='output identifier only') +argparser.add_argument('--prepend-hash', dest='prepend_hash', action='store_true', help='prepend hash bytes to chunk output (no effect without -o)') +argparser.add_argument('data', nargs='?', type=str, help='data to embed in soc.') +largs = argparser.parse_args(sys.argv[1:]) + + +if largs.vv: + logg.setLevel(logging.DEBUG) +elif largs.v: + logg.setLevel(logging.INFO) + +filepath = None +input_data = None +if largs.f: + filepath = os.path.realpath(largs.f) + f = open(filepath, 'rb') + data = f.read() + f.close() + logg.info('data read from file: {}'.format(filepath)) +else: + data = largs.data + if data == None: + data = stdin_arg() + logg.info('data read from positional argument'.format(filepath)) + else: + logg.info('data read from stdin'.format(filepath)) + + +input_data = data +if not largs.u: + input_data.rstrip() + if isinstance(input_data, str): + input_data = data.encode('utf-8') + +input_data_length = len(input_data) +data_length = input_data_length +if largs.data_length != None: + data_length = largs.data_length +logg.debug('input length {}'.format(input_data_length)) +logg.debug('span length {}'.format(data_length)) + +src_topic = None +src_index = None +soc_topic = None +soc_index = None + +if largs.topic: + src_topic = largs.topic + soc_topic = hex_pad(largs.topic, 20) +elif largs.topic_string: + src_topic = largs.topic_string + try: + soc_topic = soc_meta_from_str(largs.topic_string, 20, 'topic') + except ValueError as e: + sys.stderr.write(str(e)) + sys.exit(1) +logg.debug('topic "{}" parsed as {}'.format(src_topic, soc_topic)) + +if largs.index: + src_index = largs.index + soc_index = hex_pad(largs.index, 32) +elif largs.index_string: + src_index = largs.index_string + try: + soc_index = soc_meta_from_str(largs.index_string, 32, 'index') + except ValueError as e: + sys.stderr.write(str(e)) + sys.exit(1) +logg.debug('index "{}" parsed as {}'.format(src_index, soc_index)) + + +if not largs.id: + keystore = DefaultSigner() + keystore.from_keyfile(largs.y, os.environ.get('WALLET_PASSPHRASE', '')) + address = keystore.get_signer_address() + logg.info('using keyfile wallet for address {}'.format(address)) + + +outputter = None +if largs.o: + outputter = Outputter(largs.o, prepend_hash=largs.prepend_hash) + + + +def main(): + soc_topic_bytes = bytes.fromhex(soc_topic) + soc_index_bytes = bytes.fromhex(soc_index) + out_data = None + + import swarm + #soc_identifier_bytes = swarm.soc_identifier(soc_topic_bytes, soc_index_bytes) + soc_identifier_bytes = bytes(32) + logg.info('generated identifier {}'.format(soc_identifier_bytes.hex())) + if largs.id: + out_data = soc_identifier_bytes + else: + soc_sig = None + soc_hash = None + soc_chunk = None + if outputter: + (soc_sig, soc_hash, soc_chunk) = swarm.soc_create( + soc_identifier_bytes, + bytes.fromhex(strip_0x(address)), + input_data, + input_data_length, + data_length, + keystore.sign, + outputter.dump, + ) + else: + (soc_sig, soc_hash, soc_chunk) = swarm.soc_create( + soc_identifier_bytes, + bytes.fromhex(strip_0x(address)), + input_data, + input_data_length, + data_length, + keystore.sign, + None, + ) + + #logg.debug('signature {}'.format(soc_sig.hex())) + #logg.debug('hash {}'.format(soc_hash.hex())) + #logg.debug('chunk {}'.format(soc_chunk.hex())) + logg.debug('signature {}'.format(soc_sig)) + logg.debug('hash {}'.format(soc_hash)) + logg.debug('chunk {}'.format(soc_chunk)) + + out_data = soc_hash + + if largs.b: + sys.stdout.buffer.write(out_data) + else: + s = '{}'.format(out_data.hex()) + if not largs.n: + s += '\n' + sys.stdout.write(s) + + +if __name__ == '__main__': + main() diff --git a/pylibswarm/soc.py b/pylibswarm/soc.py @@ -0,0 +1,6 @@ +def from_str(s, target_length, label): + if len(s) > target_length: + raise ValueError('{} value {} exceeded max length {}'.format(label, s, target_length)) + b = s.encode('utf-8') + fmt = '{' + ':<0{}s'.format(target_length * 2) + '}' + return fmt.format(b.hex()) diff --git a/requirements.txt b/requirements.txt @@ -0,0 +1,2 @@ +crypto-dev-signer>=0.4.15rc1,<0.5.0 +chainlib-eth>=0.0.9a14,<0.1.0