mirror of
https://github.com/aljazceru/python-teos.git
synced 2025-12-17 22:24:23 +01:00
Working on integration with client and responder testing
This commit is contained in:
committed by
Sergi Delgado Segura
parent
dea4a78edc
commit
40cdcfa913
2
pisa-btc/TODO.md
Normal file
2
pisa-btc/TODO.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Check all the interactions with core, figure out the edge cases and error codes
|
||||
i.e: The justice transaction can already be in the blockchain the first time we push it
|
||||
@@ -1,60 +1,57 @@
|
||||
import threading
|
||||
from pisa import *
|
||||
from pisa.watcher import Watcher
|
||||
from pisa.inspector import Inspector
|
||||
from multiprocessing.connection import Listener
|
||||
from flask import Flask, request, Response
|
||||
import json
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
def manage_api(debug, logging, host=HOST, port=PORT):
|
||||
listener = Listener((host, port))
|
||||
@app.route('/', methods=['POST'])
|
||||
def add_appointment():
|
||||
remote_addr = request.environ.get('REMOTE_ADDR')
|
||||
remote_port = request.environ.get('REMOTE_PORT')
|
||||
|
||||
if debug:
|
||||
logging.info('[API] connection accepted from {}:{}'.format(remote_addr, remote_port))
|
||||
|
||||
# Check content type once if properly defined
|
||||
# FIXME: Temporary patch until Paddy set's the client properly
|
||||
request_data = json.loads(request.form['data'])
|
||||
appointment = inspector.inspect(request_data, debug)
|
||||
|
||||
if appointment:
|
||||
appointment_added = watcher.add_appointment(appointment, debug, logging)
|
||||
rcode = 200
|
||||
|
||||
# FIXME: Response should be signed receipt (created and signed by the API)
|
||||
if appointment_added:
|
||||
response = "Appointment accepted"
|
||||
else:
|
||||
response = "Appointment rejected"
|
||||
# FIXME: change the response code maybe?
|
||||
|
||||
else:
|
||||
rcode = 400
|
||||
response = "Appointment rejected. Request does not match the standard"
|
||||
|
||||
# Send response back. Change multiprocessing.connection for an http based connection
|
||||
if debug:
|
||||
logging.info('[API] sending response and disconnecting: {} --> {}:{}'.format(response, remote_addr,
|
||||
remote_port))
|
||||
|
||||
return Response(response, status=rcode, mimetype='text/plain')
|
||||
|
||||
|
||||
def start_api(d, l):
|
||||
# FIXME: Pretty ugly but I haven't found a proper way to pass it to add_appointment
|
||||
global debug, logging, watcher, inspector
|
||||
debug = d
|
||||
logging = l
|
||||
watcher = Watcher()
|
||||
inspector = Inspector()
|
||||
|
||||
while True:
|
||||
conn = listener.accept()
|
||||
# Setting Flask log t ERROR only so it does not mess with out logging
|
||||
logging.getLogger('werkzeug').setLevel(logging.ERROR)
|
||||
|
||||
remote_addr, remote_port = listener.last_accepted
|
||||
|
||||
if debug:
|
||||
logging.info('[API] connection accepted from {}:{}'.format(remote_addr, remote_port))
|
||||
|
||||
# Maintain metadata up to date.
|
||||
t_serve = threading.Thread(target=manage_request, args=[conn, remote_addr, remote_port, inspector, watcher,
|
||||
debug, logging])
|
||||
t_serve.start()
|
||||
|
||||
|
||||
def manage_request(conn, remote_addr, remote_port, inspector, watcher, debug, logging):
|
||||
while not conn.closed:
|
||||
try:
|
||||
response = "Unknown command"
|
||||
msg = conn.recv()
|
||||
|
||||
if type(msg) == tuple:
|
||||
if len(msg) is 2:
|
||||
command, arg = msg
|
||||
|
||||
if command == "add_appointment":
|
||||
appointment = inspector.inspect(arg, debug)
|
||||
if appointment:
|
||||
appointment_added = watcher.add_appointment(appointment, debug, logging)
|
||||
|
||||
# FIXME: Response should be signed receipt (created and signed by the API)
|
||||
if appointment_added:
|
||||
response = "Appointment accepted"
|
||||
else:
|
||||
response = "Appointment rejected"
|
||||
else:
|
||||
response = "Appointment rejected"
|
||||
|
||||
# Send response back. Change multiprocessing.connection for an http based connection
|
||||
if debug:
|
||||
logging.info('[API] sending response and disconnecting: {} --> {}:{}'.format(response, remote_addr,
|
||||
remote_port))
|
||||
conn.close()
|
||||
|
||||
except (IOError, EOFError):
|
||||
if debug:
|
||||
logging.info('[API] disconnecting from {}:{}'.format(remote_addr, remote_port))
|
||||
|
||||
conn.close()
|
||||
app.run(host=HOST, port=PORT)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
|
||||
# Basic appointment structure
|
||||
# DISCUSS: about the field the appointment will have
|
||||
class Appointment:
|
||||
def __init__(self, locator, start_time, end_time, dispute_delta, encrypted_blob, cypher):
|
||||
self.locator = locator
|
||||
@@ -9,6 +8,6 @@ class Appointment:
|
||||
self.end_time = end_time
|
||||
self.dispute_delta = dispute_delta
|
||||
self.encrypted_blob = encrypted_blob
|
||||
self.cypher = cypher
|
||||
self.cipher = cypher
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,50 @@
|
||||
from pisa.appointment import Appointment
|
||||
|
||||
|
||||
# FIXME: Implement a proper inspector
|
||||
class Inspector:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def inspect(self, appointment, debug):
|
||||
# Return Appointment if success, None otherwise
|
||||
return Appointment(appointment, None, None, None, None, None)
|
||||
def inspect(self, data, debug):
|
||||
# TODO: We need to define standard names for the json fields, using Paddy's ones for now
|
||||
|
||||
appointment = None
|
||||
|
||||
locator = data.get('txlocator')
|
||||
start_time = data.get('startblock')
|
||||
end_time = data.get('endblock')
|
||||
|
||||
# Missing for now
|
||||
dispute_delta = data.get('dispute_delta')
|
||||
|
||||
# FIXME: this will be eventually be replaced, here for testing now
|
||||
encrypted_blob = data.get('rawtx')
|
||||
# encrypted_blob = data.get('encrypted_blob')
|
||||
|
||||
cipher = data.get('cipher')
|
||||
|
||||
if self.check_locator(locator, debug) and self.check_start_time(start_time, debug) and \
|
||||
self.check_end_time(end_time, debug) and self.check_delta(dispute_delta, debug) and \
|
||||
self.check_blob(encrypted_blob, debug) and self.check_cipher(cipher, debug):
|
||||
appointment = Appointment(locator, start_time, end_time, dispute_delta, encrypted_blob, cipher)
|
||||
|
||||
return appointment
|
||||
|
||||
# FIXME: Define checks
|
||||
def check_locator(self, locator, debug):
|
||||
return True
|
||||
|
||||
def check_start_time(self, start_time, debug):
|
||||
return True
|
||||
|
||||
def check_end_time(self, end_time, debug):
|
||||
return True
|
||||
|
||||
def check_delta(self, dispute_delta, debug):
|
||||
return True
|
||||
|
||||
def check_blob(self, encrypted_blob, debug):
|
||||
return True
|
||||
|
||||
def check_cipher(self, cipher, debug):
|
||||
return True
|
||||
|
||||
@@ -3,7 +3,7 @@ from sys import argv
|
||||
from getopt import getopt
|
||||
from conf import LOG_FILE
|
||||
from threading import Thread
|
||||
from pisa.api import manage_api
|
||||
from pisa.api import start_api
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -14,10 +14,10 @@ if __name__ == '__main__':
|
||||
debug = True
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(format='%(asctime)s %(name)s: %(message)s', level=logging.INFO, handlers=[
|
||||
logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO, handlers=[
|
||||
logging.FileHandler(LOG_FILE),
|
||||
logging.StreamHandler()
|
||||
])
|
||||
|
||||
api_thread = Thread(target=manage_api, args=[debug, logging])
|
||||
api_thread = Thread(target=start_api, args=[debug, logging])
|
||||
api_thread.start()
|
||||
|
||||
2
pisa-btc/pisa/tools.py
Normal file
2
pisa-btc/pisa/tools.py
Normal file
@@ -0,0 +1,2 @@
|
||||
def decrypt_tx(m, k, cypher):
|
||||
return m
|
||||
@@ -87,9 +87,13 @@ class Watcher:
|
||||
|
||||
matches = self.check_potential_matches(potential_matches, bitcoin_cli, debug, logging)
|
||||
|
||||
for locator, appointment_pos, txid, tx in matches:
|
||||
# FIXME: Notify responder with every match.
|
||||
responder.add_response(txid, tx, self.appointments[locator].end_time, debug, logging)
|
||||
for locator, appointment_pos, dispute_txid, txid, rawtx in matches:
|
||||
if debug:
|
||||
logging.error("[Watcher] notifying responder about {}:{} and deleting appointment".format(
|
||||
locator, appointment_pos))
|
||||
|
||||
responder.add_response(dispute_txid, txid, rawtx,
|
||||
self.appointments[locator][appointment_pos].end_time, debug, logging)
|
||||
|
||||
# If there was only one appointment that matches the locator we can delete the whole list
|
||||
# DISCUSS: We may want to use locks before adding / removing appointment
|
||||
@@ -99,9 +103,6 @@ class Watcher:
|
||||
# Otherwise we just delete the appointment that matches locator:appointment_pos
|
||||
del self.appointments[locator][appointment_pos]
|
||||
|
||||
if debug:
|
||||
logging.error("[Watcher] notifying responder about {}:{} and deleting appointment"
|
||||
.format(locator, appointment_pos))
|
||||
except JSONRPCException as e:
|
||||
if debug:
|
||||
logging.error("[Watcher] JSONRPCException. Error code {}".format(e))
|
||||
@@ -119,18 +120,15 @@ class Watcher:
|
||||
for locator, k in potential_matches:
|
||||
for appointment_pos, appointment in enumerate(self.appointments.get(locator)):
|
||||
try:
|
||||
txid = locator + k
|
||||
# FIXME: Put this back
|
||||
# tx = decrypt_tx(appointment.encrypted_blob, k, appointment.cypher)
|
||||
# FIXME: Remove this. Temporary hack, since we are not working with blobs but with ids for now
|
||||
# FIXME: just get the raw transaction that matches both parts of the id
|
||||
tx = bitcoin_cli.getrawtransaction(txid)
|
||||
dispute_txid = locator + k
|
||||
rawtx = decrypt_tx(appointment.encrypted_blob, k, appointment.cipher)
|
||||
|
||||
bitcoin_cli.decoderawtransaction(tx)
|
||||
matches.append((locator, appointment_pos, txid, tx))
|
||||
txid = bitcoin_cli.decoderawtransaction(rawtx).get('txid')
|
||||
matches.append((locator, appointment_pos, dispute_txid, txid, rawtx))
|
||||
|
||||
if debug:
|
||||
logging.error("[Watcher] match found for {}:{}! {}".format(locator, appointment_pos, locator+k))
|
||||
logging.error("[Watcher] match found for {}:{}! {}".format(locator, appointment_pos,
|
||||
dispute_txid))
|
||||
except JSONRPCException as e:
|
||||
# Tx decode failed returns error code -22, maybe we should be more strict here. Leaving it simple
|
||||
# for the POC
|
||||
|
||||
Reference in New Issue
Block a user