diff --git a/hackfest/Product Data Lungo Tavolo - Pants.csv b/hackfest/Product Data Lungo Tavolo - Pants.csv new file mode 100644 index 0000000..25b852c --- /dev/null +++ b/hackfest/Product Data Lungo Tavolo - Pants.csv @@ -0,0 +1,49 @@ +Category,Subcategory 1,Subcategory 2,Subcategory 3,Subcategory 4,Subcategory 5,Subcategory 6 +Productname,wrap and strap pants,"=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP101a.jpg"")",,,, +Producttype,Pants,White,Mid,,, +Suggested Sex,Unisex,Donna,Uomo,,, +Ref.,LT SP 101,,,,, +Series,Summer,,,,, +Limited Edition,1/400,,,,, +Designer,Sergio Perruci,,,,, +Year,2015,,,,, +In Collaboration with,cws,,,,, +Description,Pants in Italian linen with a double wrap belted waist in signature black double satin. Wear them with the belt wrapped twice around your waist and let the extra length of the ribbon flow loosely along your leg,"=image(""https://s-media-cache-ak0.pinimg.com/564x/26/b3/a5/26b3a584ecbe16bd5dbb00c36895265f.jpg"")","=image(""https://s-media-cache-ak0.pinimg.com/originals/4c/c8/74/4cc874b4f7f8dc25fa92138a2eed94a4.png"")",,, +Detail,wrap front panel detail raw cut on the grain taped edges and hems sandwich bonded belt double satin ribbon invisible selvedge ribbon width 2.5 cm ribbon length from waist 40 cm rectangular double ring buckle raw stainless steel nickel free hem label at strap tip entirely made in Italy,"=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP101g.jpg"")","=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP101c.jpg"")",,, +Fabric 1,Linen,100%,,,, +Origin,Italy,,,,, +Colour 1,White,"=image (""http://www.lungotavolo.it/wp-content/uploads/2016/05/colwhite.jpg"")",,,, +Pantone,PANTONE 11-4001 TPG,,,,, +HEX/HTML,EFF0F1,,,,, +Colour 2,Khaki,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/05/colkhaki.jpg"")",,,, +Pantone,PANTONE 15-1216 TPX,,,,, +HEX/HTML,C0B290,,,,, +Colour 3,Stone,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/05/colgrey.jpg"")",,,, +Pantone,PANTONE PQ-CoolGray8C,,,,, +HEX/HTML,888B8D,,,,, +Ref.,LT SP 101,,,,, +Series,Print,,,,, +Limited Edition,1/400,,,,, +Designer,Sergio Perruci,,,,, +Year,2016,,,,, +In Collaboration with,cws,,,,, +Background Colour 3 ,Stripes,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/09/colstripe.jpg"")",,,, +Pantone,PANTONE 11-4001 TPG,,,,, +HEX/HTML,EFF0F1,,,,, +Pantone,PANTONE 19-0000 TPG,,,,, +HEX/HTML,454546,,,,, +Background Colour 1 ,Dots,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/09/colpois.jpg"")",,,, +Pantone,PANTONE 11-4001 TPG,,,,, +HEX/HTML,EFF0F1,,,,, +Pantone,PANTONE 19-0000 TPG,,,,, +HEX/HTML,454546,,,,, +Sizes Available,XS:waist:74cm,S:waist:80cm,M:waist:84cm,L:waist:88cm,XL:waist:92cm,XXL:waist:96cm +Price,EUR 270,USD 289,GBP 229,CAD 389,, +Aesthetic,#Elegant,#Leisure,#Italian,#Minimalism,#Zen, +Quality Trait,"=""Made in Italy""",Fair Labour,Sustainable,Verified Product,, +Quality Seal,"=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/666115-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/580362-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/580361-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/204428-200.png"")",, +Quality Statement,Produced in Italy according to Italian Law.,Produced under fair labour conditions according International Labour Organization. Excelling standards according to internal code of ethics.,"Produced under ecologically sustainable conditions according to the statues of rainforest Alliance, Certified Supply Chain. Business auditited and advised by Eco Age Ltd",This Garment was designed to inspire you. Believe in the beauty of imagination - unapolagetically! Have the courage to be who you want to be. This will set you free. ,, +Designed by,Sergio Perruci,"=image(""https://s-media-cache-ak0.pinimg.com/originals/1b/cd/ce/1bcdce55fba1809a7639b5e2235f068b.png"")",CWS,"=image(""https://s-media-cache-ak0.pinimg.com/originals/8d/3b/cc/8d3bcc1b1b148d4f741cc19303a35820.png"")",, +Country of Production,Italy,"=image (""https://upload.wikimedia.org/wikipedia/commons/thumb/0/03/Flag_of_Italy.svg/2000px-Flag_of_Italy.svg.png"")",,,, +Designed Studio,10144 Turin,"Via Treviso, 45","=image(""https://s-media-cache-ak0.pinimg.com/564x/91/70/13/9170135385ce2441ad75970fc18d408d.jpg"")","=image(""https://s-media-cache-ak0.pinimg.com/564x/6b/ce/b9/6bceb98a5d7620cac2374534e3dbfb1b.jpg"")",, +Produced in,12051 Alba,,"=image(""https://s-media-cache-ak0.pinimg.com/originals/e0/01/86/e0018641c80d305614bf19643425cd26.png"")","=image(""http://www.anselmaitalia.com/img_sito/testata/homepage/ristorante-italia_05.jpg"")",, diff --git a/hackfest/Product Data Lungo Tavolo - Skirt.csv b/hackfest/Product Data Lungo Tavolo - Skirt.csv new file mode 100644 index 0000000..87848ee --- /dev/null +++ b/hackfest/Product Data Lungo Tavolo - Skirt.csv @@ -0,0 +1,33 @@ +Category,Subcategory 1,Subcagetory 2,Subcagetory 3,Subcategory 4,Subcategory 5 +Productname,wrap and strap skirt,"=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP104a.jpg"")",,, +Producttype,Skirt,Stone,Mid,, +Suggested Sex,Unisex,Donna,Uomo,, +Collection,LT SP 104,,,, +Series,Summer,,,, +Limited Edition,1/400,,,, +Designer,Sergio Perruci,,,, +Year,2015,,,, +In Collaboration with,cws,,,, +Description,a skirt in Italian linen with a double wrap belted waist in signature black double satin wear it with the belt wrapped twice around your waist and let the extra length of the ribbon flow loosely along your leg,"=image(""https://s-media-cache-ak0.pinimg.com/originals/87/f5/0b/87f50be844c989171fdd531d9468204a.png"")","=image(""https://s-media-cache-ak0.pinimg.com/564x/3f/8a/5c/3f8a5c2d4ce602af1968fb0a3d501241.jpg"")",, +Detail,wrap front panel detail raw cut on the grain taped edges and hems sandwich bonded belt double satin ribbon invisible selvedge ribbon width 2.5 cm ribbon length from waist 40 cm rectangular double ring buckle raw stainless steel nickel free hem label at strap tip entirely made in Italy,"=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP104d.jpg"")","=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP104e.jpg"")",, +Fabric 1,Linen,100%,Pure,, +Origin,Italy,,,, +Colour 1,White,"=image (""http://www.lungotavolo.it/wp-content/uploads/2016/05/colwhite.jpg"")",,, +Pantone,PANTONE 11-4001 TPG,,,, +HEX/HTML,EFF0F1,,,, +Colour 2,Khaki,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/05/colkhaki.jpg"")",,, +Pantone,PANTONE 15-1216 TPX,,,, +HEX/HTML,C0B290,,,, +Colour 3,Stone,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/05/colgrey.jpg"")",,, +Pantone,PANTONE PQ-CoolGray8C,,,, +HEX/HTML,888B8D,,,, +Sizes Available,Short,Mid,Long,, +Price,EUR 190,USD 219,GBP 169,CAD 279, +Aesthetic,#Elegant,#Leisure,#Italian,#Minimalism,#Zen +Quality Trait,"=""Made in Italy""",Fair Labour,Sustainable,Verified Product, +Quality Seal,"=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/666115-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/580362-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/580361-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/204428-200.png"")", +Quality Statement,Produced in Italy according to Italian Law.,Produced under fair labour conditions according International Labour Organization. Excelling standards according to internal code of ethics.,"Produced under ecologically sustainable conditions according to the statues of rainforest Alliance, Certified Supply Chain. Business auditited and advised by Eco Age Ltd",This Garment was designed to inspire you. Believe in the beauty of imagination - unapolagetically! Have the courage to be who you want to be. This will set you free. , +Designed by,Sergio Perruci,"=image(""https://s-media-cache-ak0.pinimg.com/originals/1b/cd/ce/1bcdce55fba1809a7639b5e2235f068b.png"")",CWS,"=image(""https://s-media-cache-ak0.pinimg.com/originals/8d/3b/cc/8d3bcc1b1b148d4f741cc19303a35820.png"")", +Country of Production,Italy,"=image (""https://upload.wikimedia.org/wikipedia/commons/thumb/0/03/Flag_of_Italy.svg/2000px-Flag_of_Italy.svg.png"")",,, +Designed Studio,10144 Turin,"Via Treviso, 45","=image(""https://s-media-cache-ak0.pinimg.com/564x/91/70/13/9170135385ce2441ad75970fc18d408d.jpg"")","=image(""https://s-media-cache-ak0.pinimg.com/564x/6b/ce/b9/6bceb98a5d7620cac2374534e3dbfb1b.jpg"")", +Produced in,12051 Alba,,"=image(""https://s-media-cache-ak0.pinimg.com/originals/e0/01/86/e0018641c80d305614bf19643425cd26.png"")","=image(""http://www.anselmaitalia.com/img_sito/testata/homepage/ristorante-italia_05.jpg"")", diff --git a/hackfest/Product Data Lungo Tavolo - Top.csv b/hackfest/Product Data Lungo Tavolo - Top.csv new file mode 100644 index 0000000..9847eed --- /dev/null +++ b/hackfest/Product Data Lungo Tavolo - Top.csv @@ -0,0 +1,45 @@ +Category,Subcategory 1,Subcagetory 2,Subcagetory 3,Subcategory 4,Subcategory 5,Subcategory 6 +Productname,drop and strap top,"=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP106a.jpg"")",,,, +Producttype,Top,Khaki,,,, +Sugessted Sex,Women,Donna,,,, +Collection,LT SP 106,,,,, +Series,Summer,,,,, +Limited Edition,1/400,,,,, +Designer,Sergio Perruci,,,,, +Year,2015,,,,, +In Collaboration with,cws,,,,, +Description,a scarf top in Italian linen with a belt in signature black double satin wear it with the belt fastened at the back of your waist and let the extra length of the ribbon flow loosely behind you,"=image(""https://s-media-cache-ak0.pinimg.com/originals/0f/50/a6/0f50a6ed9c7162cfc157693969232ac4.png"")",,,, +Detail,"wrap front panel detail +raw cut on the grain +taped edges and hems +sandwich bonded belt +double satin ribbon +invisible selvedge +ribbon width 2.5 cm +ribbon length from waist 40 cm +rectangular double ring buckle +raw stainless steel +nickel free +hem label at strap tip +entirely made in Italy","=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP106e.jpg"")","=image(""http://www.lungotavolo.it/wp-content/uploads/2015/12/LTSP106c.jpg"")",,, +Fabric 1,Linen,100%,Pure,,, +Origin,Italy,,,,, +Colour 1,White,"=image (""http://www.lungotavolo.it/wp-content/uploads/2016/05/colwhite.jpg"")",,,, +Pantone,PANTONE 11-4001 TPG,,,,, +HEX/HTML,EFF0F1,,,,, +Colour 2,Khaki,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/05/colkhaki.jpg"")",,,, +Pantone,PANTONE 15-1216 TPX,,,,, +HEX/HTML,C0B290,,,,, +Colour 3,Stone,"=image(""http://www.lungotavolo.it/wp-content/uploads/2016/05/colgrey.jpg"")",,,, +Pantone,PANTONE PQ-CoolGray8C,,,,, +HEX/HTML,888B8D,,,,, +Size,One Size,,,,, +Price,EUR 105,USD 120,GBP 90,CAD 180,, +Aesthetic,#Elegant,#Leisure,#Italian,#Minimalism,#Zen, +Quality Trait,"=""Made in Italy""",Fair Labour,Sustainable,Verified Product,, +Quality Seal,"=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/666115-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/580362-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/580361-200.png"")","=image(""https://d30y9cdsu7xlg0.cloudfront.net/png/204428-200.png"")",, +Quality Statement,Produced in Italy according to Italian Law.,Produced under fair labour conditions according International Labour Organization. Excelling standards according to internal code of ethics.,"Produced under ecologically sustainable conditions according to the statues of rainforest Alliance, Certified Supply Chain. Business auditited and advised by Eco Age Ltd",This Garment was designed to inspire you. Believe in the beauty of imagination - unapolagetically! Have the courage to be who you want to be. This will set you free. ,, +Designed by,Sergio Perruci,"=image(""https://s-media-cache-ak0.pinimg.com/originals/1b/cd/ce/1bcdce55fba1809a7639b5e2235f068b.png"")",CWS,"=image(""https://s-media-cache-ak0.pinimg.com/originals/8d/3b/cc/8d3bcc1b1b148d4f741cc19303a35820.png"")",, +Country of Production,Italy,"=image (""https://upload.wikimedia.org/wikipedia/commons/thumb/0/03/Flag_of_Italy.svg/2000px-Flag_of_Italy.svg.png"")",,,, +Designed Studio,10144 Turin,"Via Treviso, 45","=image(""https://s-media-cache-ak0.pinimg.com/564x/91/70/13/9170135385ce2441ad75970fc18d408d.jpg"")","=image(""https://s-media-cache-ak0.pinimg.com/564x/6b/ce/b9/6bceb98a5d7620cac2374534e3dbfb1b.jpg"")",, +Produced in,12051 Alba,,"=image(""https://s-media-cache-ak0.pinimg.com/originals/e0/01/86/e0018641c80d305614bf19643425cd26.png"")","=image(""http://www.anselmaitalia.com/img_sito/testata/homepage/ristorante-italia_05.jpg"")",, diff --git a/hackfest/Product Data Lungo Tavolo.xlsx b/hackfest/Product Data Lungo Tavolo.xlsx new file mode 100644 index 0000000..29fad5e Binary files /dev/null and b/hackfest/Product Data Lungo Tavolo.xlsx differ diff --git a/hackfest/lungo_tavolo.py b/hackfest/lungo_tavolo.py new file mode 100644 index 0000000..3d7a76b --- /dev/null +++ b/hackfest/lungo_tavolo.py @@ -0,0 +1,105 @@ +from argparse import ArgumentParser +from logging import getLogger, Formatter, DEBUG +from logging.handlers import SysLogHandler +from bigchaindb_driver import BigchainDB +from json import dumps as json_dumps +from time import strftime, gmtime + + +class Provenance(object): + def __init__(self, log, bdb_ip, bdb_port, public_key, private_key, + file_path): + self.bdb = BigchainDB('http://{0}:{1}'.format(bdb_ip, bdb_port)) + self.keypair = { + 'private_key': private_key, + 'public_key': public_key + } + self.file_path = file_path + self.logger = log + # end __init__ + + def start(self): + # open the csv file, every file is an asset + asset = {} + asset['asset_class'] = 'lungo_tavolo_product' + with open(self.file_path) as fh: + # ignore the headers for now + fh.readline() + for line in fh: + columns = line.split(',') + # sanitize the columns, remove null strings + new_columns = [] + for cell in columns: + if cell != '': + cell = cell.rstrip('\r\n') + new_columns.append(cell) + # end if + # end for + # define the asset + # remove '.' from the column[0] as mongo does not allow '.' + # in key fields: http://stackoverflow.com/questions/28664383/mongodb-not-allowing-using-in-key + new_columns[0] = new_columns[0].replace('.', '') + asset[new_columns[0]] = ','.join(new_columns[1:]) + # end for + self.logger.debug(json_dumps(asset)) + # end with + # defin the metadata + asset_metadata = { + 'from_file': self.file_path, + 'create_at': strftime('%Y-%m-%d_%H:%M:%S', gmtime()), + } + # send to bdb + self.send_to_bdb(asset, asset_metadata) + # end start + + def send_to_bdb(self, asset, metadata): + bdb_asset = { + 'data': asset + } + prepared_creation_tx = self.bdb.transactions.prepare( + operation='CREATE', + signers=self.keypair['public_key'], + asset=bdb_asset, + metadata=metadata + ) + fulfilled_tx = self.bdb.transactions.fulfill( + prepared_creation_tx, + private_keys=self.keypair['private_key'] + ) + self.bdb.transactions.send(fulfilled_tx) + self.logger.debug(fulfilled_tx['id']) + # end send_to_bdb +# end class Provenance + + +if __name__ == '__main__': + # argument parsing + parser = ArgumentParser(description='BDB/LungoTavolo') + req_group = parser.add_argument_group('required arguments') + req_group.add_argument('--bdb-ip', type=str, required=True, + help='bdb hostname/ip address') + req_group.add_argument('--bdb-port', type=int, required=True, + help='bdb port number') + req_group.add_argument('--public-key', type=str, required=True, + help='lungo tavolo public key') + req_group.add_argument('--private-key', type=str, required=True, + help='lungo tavolo private key') + req_group.add_argument('--file', type=str, required=True, + help='path to csv file') + args = parser.parse_args() + # set up logging + logger = getLogger('provenance_service') + logger.setLevel(DEBUG) + # local syslog + local_formatter = Formatter( + "%(name)s %(threadName)s %(levelname)s -- %(message)s", + datefmt='%Y-%m-%d %H:%M:%S') + local_syslog = SysLogHandler(address='/dev/log', + facility=SysLogHandler.LOG_SYSLOG) + local_syslog.setFormatter(local_formatter) + logger.addHandler(local_syslog) + + provenance = Provenance(logger, args.bdb_ip, args.bdb_port, args.public_key, + args.private_key, args.file) + provenance.start() +# end main diff --git a/hackfest/rest_api.py b/hackfest/rest_api.py new file mode 100644 index 0000000..f848315 --- /dev/null +++ b/hackfest/rest_api.py @@ -0,0 +1,178 @@ +from flask import Flask, jsonify, make_response, abort, request, current_app +from argparse import ArgumentParser +from logging import getLogger, Formatter, DEBUG +from logging.handlers import SysLogHandler +from bigchaindb_driver import BigchainDB +from bigchaindb_driver.exceptions import NotFoundError +from time import sleep, strftime, gmtime +from transactions import create_asset, create_transfer + +app = Flask(__name__) + + +@app.route('/') +def index(): + return "Hello, World!" + + +@app.route('/tomtom', methods=['POST']) +def post_tomtom_data(): + if not request.json: + abort(404) + print(request.json) + return jsonify({'ok': 1}) + + +@app.route('/pubkey', methods=['POST']) +def post_pubkey(): + device_id = request.form.get('device_id', None) + pubkey = request.form.get('pubkey', None) + message = request.form.get('message', None) + if not pubkey or not device_id: + return jsonify({'error': 'invalid request'}), 404 + + print(device_id, pubkey, message) + return make_response(jsonify({'ok': 1})) + + +@app.errorhandler(404) +def not_found(error): + """jsonify 404""" + return make_response(jsonify({'error': 'not found'}), 404) + + +@app.route('/telemetry', methods=['POST']) +def handle_telemetry_data(): + if not request.json: + abort(404) + print(request.json) + # parse the request? + # should be signed req + # can't be mangled here + # send it to bdb as is (?!) + json_data = request.json + vehicle_id = request.json.pop('vehicleId') + send_data_to_bdb(json_data, vehicle_id) + # TODO - bubble up any errors + return make_response(jsonify({'ok': 1})) +# end handle_telemetry_data + + +def init_system(app, bdb_ip, bdb_port, pub_key, pr_key): + bdb = BigchainDB('http://{0}:{1}'.format(bdb_ip, bdb_port)) + keypair = { + 'private_key': pr_key, + 'public_key': pub_key + } + + asset_data = { + 'data': { + 'asset_class': 'vehicle_telemetry', + 'asset_author': 'hackfest-berlin-2017-team' + } + } + + app.config['bdb'] = bdb + app.config['keypair'] = keypair + app.config['asset'] = asset_data + app.config['txids'] = {} +# end init_system + + +def record_data(bdb_conn, data, metadata, keypair, tx_id, vehicle_id): + fulfilled_tx = None + if tx_id != '': + logger.debug('Transfer tx!') + previous_tx = bdb_conn.transactions.retrieve(tx_id) + if 'id' in previous_tx['asset']: + asset_id = previous_tx['asset']['id'] + else: + asset_id = previous_tx['id'] + + transfer_tx = create_transfer(previous_tx, keypair['private_key'], + keypair['public_key'], vehicle_id, + metadata, asset_id) + bdb_conn.transactions.send(transfer_tx.to_dict()) + fulfilled_tx = transfer_tx.to_dict() + else: + logger.debug('Create tx!') + create_tx = create_asset(keypair['private_key'], keypair['public_key'], + vehicle_id, data, metadata) + bdb_conn.transactions.send(create_tx.to_dict()) + fulfilled_tx = create_tx.to_dict() + # end if + + # verify if the tx was registered in the bigchain + trials = 0 + while trials < 10: + try: + if bdb_conn.transactions.status( + fulfilled_tx['id'] + ).get('status') == 'valid': + print('Tx valid in:', trials, 'secs') + break + except NotFoundError: + trials += 1 + sleep(1) + # end try + # end while + + if trials == 10: + print('Cannot connect to backend... Exiting!') + exit(0) + # end if + return fulfilled_tx['id'] +# end record_data + + +def send_data_to_bdb(telemetry_data, vehicle_id): + bdb = current_app.config['bdb'] + keypair = current_app.config['keypair'] + tx_id = current_app.config['txids'].get(vehicle_id, '') + asset_data = current_app.config['asset'] + + asset_metadata = { + 'company': 'vw', + 'financer': 'commerzbank', + 'owner': 'microsoft', + 'source': 'riddle_and_code', + 'dest': 'bdb', + 'timestamp': strftime('%Y-%m-%d_%H:%M:%S', gmtime()), + 'data': telemetry_data + } + + # record data to bigchain + tx_id = record_data(bdb, asset_data, asset_metadata, keypair, tx_id, vehicle_id) + logger.debug('tx_id: ' + tx_id) + current_app.config['txids'].update({vehicle_id: tx_id}) +# end send_data_to_bdb + + +if __name__ == '__main__': + # argument parsing + parser = ArgumentParser(description='BDB/IoT') + req_group = parser.add_argument_group('required arguments') + req_group.add_argument('--bdb-ip', type=str, required=True, + help='bdb hostname/ip address') + req_group.add_argument('--bdb-port', type=int, required=True, + help='bdb port number') + req_group.add_argument('--public-key', type=str, required=True, + help='api service public key') + req_group.add_argument('--private-key', type=str, required=True, + help='api service private key') + args = parser.parse_args() + # set up logging + logger = getLogger('telemetry_service') + logger.setLevel(DEBUG) + # local syslog + local_formatter = Formatter( + "%(name)s %(threadName)s %(levelname)s -- %(message)s", + datefmt='%Y-%m-%d %H:%M:%S') + local_syslog = SysLogHandler(address='/dev/log', + facility=SysLogHandler.LOG_SYSLOG) + local_syslog.setFormatter(local_formatter) + logger.addHandler(local_syslog) + init_system(app, args.bdb_ip, args.bdb_port, args.public_key, + args.private_key) + app.run(debug=True, host='0.0.0.0') +# end main diff --git a/hackfest/transactions.py b/hackfest/transactions.py new file mode 100644 index 0000000..ed86e5c --- /dev/null +++ b/hackfest/transactions.py @@ -0,0 +1,117 @@ +import json +import sha3 + +from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment +from cryptoconditions.crypto import Ed25519SigningKey + +from bigchaindb.models import Transaction +from bigchaindb.common.crypto import generate_key_pair +from bigchaindb.common.transaction import Output + +VW_SK, VW_PK = generate_key_pair() +TEL_SK, TEL_PK = generate_key_pair() + + +def create_asset(vw_sk, vw_pk, vehicle_id, data, metadata): + # Create asset VW -> [VW, TEL] + # Custom crypto condition multisig 1-2 + threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1) + + vw_fulfillment = Ed25519Fulfillment(public_key=vw_pk) + tel_fulfillment = Ed25519Fulfillment(public_key=vehicle_id) + + threshold_fulfillment.add_subfulfillment(vw_fulfillment) + threshold_fulfillment.add_subfulfillment(tel_fulfillment) + + output = { + 'amount': 1, + 'condition': { + 'details': threshold_fulfillment.to_dict(), + 'uri': threshold_fulfillment.condition.serialize_uri() + }, + 'public_keys': [vw_pk, vehicle_id] + } + + # Create the transaction + tx_create = Transaction.create([vw_pk], [([vw_pk, vehicle_id], 1)], + asset=data, metadata=metadata) + # Override the condition we our custom build one + tx_create.outputs[0] = Output.from_dict(output) + + # Sign the transaction + tx_create_signed = tx_create.sign([vw_sk]) + + return tx_create_signed + + +def create_transfer(prev_tx, vw_sk, vw_pk, vehicle_id, metadata, asset_id): + prev_tx = Transaction.from_dict(prev_tx) + # Create asset VW -> [VW, TEL] + # Custom crypto condition multisig 1-2 + threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1) + + vw_fulfillment = Ed25519Fulfillment(public_key=vw_pk) + tel_fulfillment = Ed25519Fulfillment(public_key=vehicle_id) + + threshold_fulfillment.add_subfulfillment(vw_fulfillment) + threshold_fulfillment.add_subfulfillment(tel_fulfillment) + + output = { + 'amount': 1, + 'condition': { + 'details': threshold_fulfillment.to_dict(), + 'uri': threshold_fulfillment.condition.serialize_uri() + }, + 'public_keys': [vw_pk, vehicle_id], + } + + # The yet to be fulfilled input: + input_ = { + 'fulfillment': None, + 'fulfills': { + 'txid': prev_tx.id, + 'output': 0, + }, + 'owners_before': [vw_pk, vehicle_id], + } + + # Craft the payload: + transfer_tx = { + 'operation': 'TRANSFER', + 'asset': {'id': asset_id}, + 'metadata': metadata, + 'outputs': [output], + 'inputs': [input_], + 'version': '0.9', + } + + # Generate the id, by hashing the encoded json formatted string + # representation of the transaction: + json_str_tx = json.dumps( + transfer_tx, + sort_keys=True, + separators=(',', ':'), + ensure_ascii=False, + ) + + txid = sha3.sha3_256(json_str_tx.encode()).hexdigest() + + transfer_tx['id'] = txid + + # Sign the transaction: + message = json.dumps( + transfer_tx, + sort_keys=True, + separators=(',', ':'), + ensure_ascii=False, + ) + + threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1) + + vw_fulfillment.sign(message.encode(), private_key=Ed25519SigningKey(vw_sk)) + threshold_fulfillment.add_subfulfillment(vw_fulfillment) + threshold_fulfillment.add_subcondition(tel_fulfillment.condition) + + fulfillment_uri = threshold_fulfillment.serialize_uri() + transfer_tx['inputs'][0]['fulfillment'] = fulfillment_uri + return Transaction.from_dict(transfer_tx) diff --git a/log_assets.py b/log_assets.py index 4d96181..d8ee615 100644 --- a/log_assets.py +++ b/log_assets.py @@ -39,7 +39,6 @@ def init_system(bosun_ip, bosun_port, bdb_ip, bdb_port): # record data to bigchain tx_id = record_data(asset_data, keypair, tx_id, bdb_ip, bdb_port) time.sleep(5) - init_done = True # end while