Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
  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,
    }
Ejemplo n.º 3
0
  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)
Ejemplo n.º 4
0
 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')
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
 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')
Ejemplo n.º 8
0
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)