def __init__(self): self.communication = OracleCommunication() self.db = OracleDb() self.btc = BitcoinClient() self.kv = KeyValue(self.db) self.task_queue = TaskQueue(self.db) self.handlers = op_handlers self.signer = TransactionSigner(self)
def __init__(self): self.communication = OracleCommunication() self.db = OracleDb() self.btc = BitcoinClient() self.evaluator = Evaluator() self.task_queue = TaskQueue(self.db) self.operations = { 'TransactionRequest': self.add_transaction, }
def test_password_transaction_request_corresponds_to_protocol(self): oc = OracleCommunication() operation, message = self.create_password_transaction_request() self.assertEqual(oc.corresponds_to_protocol(message), 'password_transaction')
class Oracle: def __init__(self): self.communication = OracleCommunication() self.db = OracleDb() self.btc = BitcoinClient() self.kv = KeyValue(self.db) self.task_queue = TaskQueue(self.db) self.handlers = op_handlers self.signer = TransactionSigner(self) def handle_request(self, request): logging.debug(request) operation, message = request if not operation in self.handlers: logging.debug("operation {} not supported".format(operation)) return handler = self.handlers[operation] try: message.message = json.loads(message.message) if 'message_id' in message.message: logging.info('parsing message_id: %r' % message.message['message_id']) handler(self).handle_request(message) except: logging.debug(message) logging.exception('error handling the request') # Save object to database for future reference db_class = self.db.operations[operation] if db_class: db_class(self.db).save(message) def handle_task(self, task): operation = task['operation'] assert (operation in self.handlers) handler = self.handlers[operation] handler(self).handle_task(task) operation = task['operation'] handler = self.handlers[operation] if handler: if handler(self).valid_task(task): return task else: logging.debug('Task marked as invalid by handler') self.task_queue.done(task) return None else: logging.debug("Task has invalid operation") self.task_queue.done(task) return None def is_fee_sufficient(self, addr, fee): if addr != self.oracle_address: return False if fee < Decimal(ORACLE_FEE): return False return True def run(self): if not ORACLE_ADDRESS: self.oracle_address = self.kv.get_by_section_key( 'config', 'ORACLE_ADDRESS') if self.oracle_address is None: new_addr = self.btc.server.getnewaddress() self.oracle_address = new_addr logging.error("created a new address: '%s'" % new_addr) self.kv.store('config', 'ORACLE_ADDRESS', new_addr) else: self.oracle_address = ORACLE_ADDRESS logging.info("my multisig address is %s" % self.oracle_address) logging.info("my pubkey: %r" % self.btc.validate_address(self.oracle_address)['pubkey']) logging.debug("awaiting requests...") count = 0 while True: # Proceed all requests requests = self.communication.get_new_requests() if len(requests) == 0: count = count + 1 if count > 30: logging.debug("{0} new requests".format(len(requests))) count = 0 else: logging.debug("{0} new requests".format(len(requests))) for request in requests: self.handle_request(request) self.communication.mark_request_done(request) task = self.task_queue.get_oldest_task() while task is not None: self.handle_task(task) self.task_queue.done(task) task = self.task_queue.get_oldest_task() time.sleep(1)
class Oracle: def __init__(self): self.communication = OracleCommunication() self.db = OracleDb() self.btc = BitcoinClient() self.evaluator = Evaluator() self.task_queue = TaskQueue(self.db) self.operations = { 'TransactionRequest': self.add_transaction, } def condition_valid(self, condition): return self.evaluator.valid(condition) def transaction_valid(self, transaction): return self.btc.is_valid_transaction(transaction) def add_transaction(self, message): body = json.loads(message.message) condition = body['condition'] # Future reference - add parsing condition. Now assumed true if not self.condition_valid(condition): logging.debug("condition invalid") return transaction = body['raw_transaction'] prevtx = body['prevtx'] pubkey_list = body['pubkey_json'] try: req_sigs = int(body['req_sigs']) except ValueError: logging.debug("req_sigs must be a number") return try: self.btc.add_multisig_address(req_sigs, pubkey_list) except ProtocolError: logging.debug("cant add multisig address") return if not self.transaction_valid(transaction): logging.debug("transaction invalid") return if not self.btc.transaction_need_signature(transaction): logging.debug("transaction does not need a signature") return if not self.btc.transaction_contains_org_fee(transaction): logging.debug("org fee not found") return if not self.btc.transaction_contains_oracle_fee(transaction): logging.debug("oracle fee not found") self.communication.broadcast(SUBJECT.NO_FEE, RESPONSE.NO_FEE) return if self.btc.transaction_already_signed(transaction, prevtx): logging.debug("transaction already signed") return inputs, output = self.btc.get_inputs_outputs(transaction) used_input_db = UsedInput(self.db) for i in inputs: used_input = used_input_db.get_input(i) if used_input: if used_input["json_out"] != output: self.broadcast( SUBJECT.ADDRESS_DUPLICATE, RESPONSE.ADDRESS_DUPLICATE) return for i in inputs: print i used_input_db.save({ 'input_hash': i, 'json_out': output }) locktime = int(body['locktime']) task_queue = TaskQueue(self.db).save({ "json_data": message.message, "done": 0, "next_check": locktime }) def handle_request(self, request): operation, message = request fun = self.operations[operation] fun(message) # Save object to database for future reference db_class = self.db.operations[operation] if db_class: db_class(self.db).save(message) def check_condition(self, condition): return self.evaluator.evaluate(condition) def handle_task(self, task): body = json.loads(task["json_data"]) condition = body["condition"] transaction = body["raw_transaction"] prevtx = body["prevtx"] if not self.check_condition(condition): self.task_queue.done(task) return if not self.transaction_valid(transaction): self.task_queue.done(task) return signed_transaction = self.btc.sign_transaction(transaction, prevtx) body["raw_transaction"] = signed_transaction SignedTransaction(self.db).save({"hex_transaction": signed_transaction, "prevtx":json.dumps(prevtx)}) self.communication.broadcast_signed_transaction(json.dumps(body)) self.task_queue.done(task) def run(self): if not ORACLE_ADDRESS: new_addr = self.btc.server.getnewaddress() logging.error("first run? add '%s' to ORACLE_ADDRESS in settings_local.py" % new_addr) exit() logging.info("my multisig address is %s" % ORACLE_ADDRESS) logging.debug("private key: %s" % self.btc.server.dumpprivkey(ORACLE_ADDRESS)) while True: # Proceed all requests requests = self.communication.get_new_requests() logging.debug("{0} new requests".format(len(requests))) for request in requests: self.handle_request(request) self.communication.mark_request_done(request) task = self.task_queue.get_oldest_task() if task: self.handle_task(task) time.sleep(1)
class Oracle: def __init__(self): self.communication = OracleCommunication() self.db = OracleDb() self.btc = BitcoinClient() self.kv = KeyValue(self.db) self.task_queue = TaskQueue(self.db) self.handlers = op_handlers self.signer = TransactionSigner(self) def handle_request(self, request): logging.debug(request) operation, message = request if not operation in self.handlers: logging.debug("operation {} not supported".format(operation)) return handler = self.handlers[operation] try: message.message = json.loads(message.message) if 'message_id' in message.message: logging.info('parsing message_id: %r' % message.message['message_id']) handler(self).handle_request(message) except: logging.debug(message) logging.exception('error handling the request') # Save object to database for future reference db_class = self.db.operations[operation] if db_class: db_class(self.db).save(message) def handle_task(self, task): operation = task['operation'] assert(operation in self.handlers) handler = self.handlers[operation] handler(self).handle_task(task) operation = task['operation'] handler = self.handlers[operation] if handler: if handler(self).valid_task(task): return task else: logging.debug('Task marked as invalid by handler') self.task_queue.done(task) return None else: logging.debug("Task has invalid operation") self.task_queue.done(task) return None def is_fee_sufficient(self, addr, fee): if addr != self.oracle_address: return False if fee < Decimal(ORACLE_FEE): return False return True def run(self): if not ORACLE_ADDRESS: self.oracle_address = self.kv.get_by_section_key('config','ORACLE_ADDRESS') if self.oracle_address is None: new_addr = self.btc.server.getnewaddress() self.oracle_address = new_addr logging.error("created a new address: '%s'" % new_addr) self.kv.store('config','ORACLE_ADDRESS',new_addr) else: self.oracle_address = ORACLE_ADDRESS logging.info("my multisig address is %s" % self.oracle_address) logging.info( "my pubkey: %r" % self.btc.validate_address(self.oracle_address)['pubkey'] ) logging.debug("awaiting requests...") count = 0 while True: # Proceed all requests requests = self.communication.get_new_requests() if len(requests) == 0: count = count + 1 if count > 30: logging.debug("{0} new requests".format(len(requests))) count = 0 else: logging.debug("{0} new requests".format(len(requests))) for request in requests: self.handle_request(request) self.communication.mark_request_done(request) task = self.task_queue.get_oldest_task() while task is not None: self.handle_task(task) self.task_queue.done(task) task = self.task_queue.get_oldest_task() time.sleep(1)