<s> from oracle_db import OracleDb , TaskQueue , KeyValue <EOL> from handlers . handlers import op_handlers <EOL> from settings_local import ORACLE_ADDRESS , ORACLE_FEE <EOL> from shared . bitcoind_client . bitcoinclient import BitcoinClient <EOL> from shared . fastproto import ( <EOL> generateKey , <EOL> broadcastMessage , <EOL> getMessages ) <EOL> import json <EOL> from handlers . transactionsigner import TransactionSigner <EOL> import time <EOL> import logging <EOL> from decimal import Decimal <EOL> HEURISTIC_ADD_TIME = <NUM_LIT> * <NUM_LIT:3> <EOL> class FastcastMessage : <EOL> def __init__ ( self , req ) : <EOL> body = json . loads ( req [ '<STR_LIT:body>' ] ) <EOL> self . from_address = req [ '<STR_LIT:source>' ] <EOL> self . received_time = int ( req [ '<STR_LIT>' ] ) <EOL> if '<STR_LIT>' in body : <EOL> self . msgid = body [ '<STR_LIT>' ] <EOL> else : <EOL> self . msgid = '<STR_LIT>' <EOL> self . subject = "<STR_LIT>" <EOL> self . message = req [ '<STR_LIT:body>' ] <EOL> class MissingOperationError ( Exception ) : <EOL> pass <EOL> CONFIRMATIONS = <NUM_LIT:0> <EOL> class FastcastProtocolError ( Exception ) : <EOL> pass <EOL> class Oracle : <EOL> def __init__ ( self ) : <EOL> self . db = OracleDb ( ) <EOL> self . btc = BitcoinClient ( ) <EOL> self . kv = KeyValue ( self . db ) <EOL> self . task_queue = TaskQueue ( self . db ) <EOL> self . handlers = op_handlers <EOL> self . signer = TransactionSigner ( self ) <EOL> last_received = self . kv . get_by_section_key ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> if not last_received : <EOL> self . kv . store ( '<STR_LIT>' , '<STR_LIT>' , { '<STR_LIT>' : <NUM_LIT:0> } ) <EOL> if not self . kv . exists ( '<STR_LIT>' , '<STR_LIT:address>' ) : <EOL> pub , priv = generateKey ( ) <EOL> self . kv . store ( '<STR_LIT>' , '<STR_LIT:address>' , { "<STR_LIT>" : pub , "<STR_LIT>" : priv } ) <EOL> logging . info ( '<STR_LIT>' % self . kv . get_by_section_key ( '<STR_LIT>' , '<STR_LIT:address>' ) [ '<STR_LIT>' ] ) <EOL> def broadcast_with_fastcast ( self , message ) : <EOL> data = self . kv . get_by_section_key ( '<STR_LIT>' , '<STR_LIT:address>' ) <EOL> pub = data [ '<STR_LIT>' ] <EOL> priv = data [ '<STR_LIT>' ] <EOL> broadcastMessage ( message , pub , priv ) <EOL> def handle_request ( self , request ) : <EOL> logging . debug ( request ) <EOL> operation , message = request <EOL> if not operation in self . handlers : <EOL> logging . debug ( "<STR_LIT>" . format ( operation ) ) <EOL> return <EOL> handler = self . handlers [ operation ] <EOL> try : <EOL> message . message = json . loads ( message . message ) <EOL> if '<STR_LIT>' in message . message : <EOL> logging . info ( '<STR_LIT>' % message . message [ '<STR_LIT>' ] ) <EOL> handler ( self ) . handle_request ( message ) <EOL> except : <EOL> logging . debug ( message ) <EOL> logging . exception ( '<STR_LIT>' ) <EOL> db_class = self . db . operations [ operation ] <EOL> if db_class : <EOL> db_class ( self . db ) . save ( message ) <EOL> def get_last_block_number ( self ) : <EOL> val = KeyValue ( self . db ) . get_by_section_key ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> if not val : <EOL> return <NUM_LIT:0> <EOL> last_block = val [ '<STR_LIT>' ] <EOL> return last_block <EOL> def set_last_block ( self ) : <EOL> last_block_number = self . btc . get_block_count ( ) <EOL> satisfied = False <EOL> while not satisfied : <EOL> block_hash = self . btc . get_block_hash ( last_block_number ) <EOL> block = self . btc . get_block ( block_hash ) <EOL> if block [ '<STR_LIT>' ] >= CONFIRMATIONS : <EOL> satisfied = True <EOL> else : <EOL> last_block_number -= <NUM_LIT:1> <EOL> print "<STR_LIT>" % last_block_number <EOL> KeyValue ( self . db ) . store ( '<STR_LIT>' , '<STR_LIT>' , { '<STR_LIT>' : last_block_number } ) <EOL> return last_block_number <EOL> def get_new_block ( self ) : <EOL> last_block_number = self . get_last_block_number ( ) <EOL> logging . debug ( "<STR_LIT>" % last_block_number ) <EOL> if last_block_number == <NUM_LIT:0> : <EOL> last_block_number = self . set_last_block ( ) <EOL> newer_block = last_block_number + <NUM_LIT:1> <EOL> block_hash = self . btc . get_block_hash ( newer_block ) <EOL> logging . info ( "<STR_LIT>" % block_hash ) <EOL> if not block_hash : <EOL> return None <EOL> block = self . btc . get_block ( block_hash ) <EOL> if block [ '<STR_LIT>' ] < CONFIRMATIONS : <EOL> return None <EOL> logging . info ( "<STR_LIT>" . format ( newer_block ) ) <EOL> return block <EOL> def handle_task ( self , task ) : <EOL> operation = task [ '<STR_LIT>' ] <EOL> assert ( operation in self . handlers ) <EOL> handler = self . handlers [ operation ] <EOL> handler ( self ) . handle_task ( task ) <EOL> operation = task [ '<STR_LIT>' ] <EOL> handler = self . handlers [ operation ] <EOL> if handler : <EOL> if handler ( self ) . valid_task ( task ) : <EOL> return task <EOL> else : <EOL> logging . debug ( '<STR_LIT>' ) <EOL> self . task_queue . done ( task ) <EOL> return None <EOL> else : <EOL> logging . debug ( "<STR_LIT>" ) <EOL> self . task_queue . done ( task ) <EOL> return None <EOL> def is_fee_sufficient ( self , addr , fee ) : <EOL> if addr != self . oracle_address : <EOL> return False <EOL> if fee < Decimal ( ORACLE_FEE ) : <EOL> return False <EOL> return True <EOL> def prepare_request ( self , request ) : <EOL> try : <EOL> fmsg = FastcastMessage ( request ) <EOL> except : <EOL> raise FastcastProtocolError ( ) <EOL> msg_body = json . loads ( fmsg . message ) <EOL> if not '<STR_LIT>' in msg_body : <EOL> raise MissingOperationError ( ) <EOL> operation = msg_body [ '<STR_LIT>' ] <EOL> return ( operation , fmsg ) <EOL> def filter_requests ( self , old_req ) : <EOL> new_req = [ ] <EOL> last_received = self . kv . get_by_section_key ( '<STR_LIT>' , '<STR_LIT>' ) [ '<STR_LIT>' ] <EOL> max_received = last_received <EOL> for r in old_req : <EOL> received_epoch = int ( r [ '<STR_LIT>' ] ) <EOL> if received_epoch > last_received : <EOL> new_req . append ( r ) <EOL> max_received = max ( max_received , received_epoch ) <EOL> if len ( new_req ) > <NUM_LIT:0> : <EOL> self . kv . update ( '<STR_LIT>' , '<STR_LIT>' , { '<STR_LIT>' : max_received } ) <EOL> return new_req <EOL> def run ( self ) : <EOL> if not ORACLE_ADDRESS : <EOL> self . oracle_address = self . kv . get_by_section_key ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> if self . oracle_address is None : <EOL> new_addr = self . btc . server . getnewaddress ( ) <EOL> self . oracle_address = new_addr <EOL> logging . error ( "<STR_LIT>" % new_addr ) <EOL> self . kv . store ( '<STR_LIT>' , '<STR_LIT>' , new_addr ) <EOL> else : <EOL> self . oracle_address = ORACLE_ADDRESS <EOL> logging . info ( "<STR_LIT>" % ORACLE_FEE ) <EOL> logging . info ( "<STR_LIT>" % self . oracle_address ) <EOL> logging . info ( "<STR_LIT>" % self . btc . validate_address ( self . oracle_address ) [ '<STR_LIT>' ] ) <EOL> while True : <EOL> requests = getMessages ( ) <EOL> requests = requests [ '<STR_LIT>' ] <EOL> requests = self . filter_requests ( requests ) <EOL> for prev_request in requests : <EOL> try : <EOL> request = self . prepare_request ( prev_request ) <EOL> except MissingOperationError : <EOL> logging . info ( '<STR_LIT>' ) <EOL> logging . info ( prev_request ) <EOL> continue <EOL> except FastcastProtocolError : <EOL> logging . info ( '<STR_LIT>' ) <EOL> logging . info ( prev_request ) <EOL> continue <EOL> self . handle_request ( request ) <EOL> task = self . task_queue . get_oldest_task ( ) <EOL> while task is not None : <EOL> self . handle_task ( task ) <EOL> self . task_queue . done ( task ) <EOL> task = self . task_queue . get_oldest_task ( ) <EOL> try : <EOL> new_block = self . get_new_block ( ) <EOL> except : <EOL> new_block = None <EOL> logging . exception ( '<STR_LIT>' ) <EOL> if new_block : <EOL> handlers = op_handlers . iteritems ( ) <EOL> addresses_per_handler = { } <EOL> all_addresses = set ( ) <EOL> for name , handler in handlers : <EOL> addresses = handler ( self ) . get_observed_addresses ( ) <EOL> addresses_per_handler [ name ] = addresses <EOL> for address in addresses : <EOL> all_addresses . add ( address ) <EOL> transactions = self . btc . get_transactions_from_block ( new_block , list ( all_addresses ) ) <EOL> handlers = op_handlers . iteritems ( ) <EOL> for name , handler in handlers : <EOL> addresses = addresses_per_handler [ name ] <EOL> handler_transactions = [ ] <EOL> for address in addresses : <EOL> if address in transactions : <EOL> handler_transactions . extend ( transactions [ address ] ) <EOL> handler ( self ) . handle_new_transactions ( handler_transactions ) <EOL> KeyValue ( self . db ) . update ( '<STR_LIT>' , '<STR_LIT>' , { '<STR_LIT>' : new_block [ '<STR_LIT>' ] } ) <EOL> time . sleep ( <NUM_LIT:10> ) </s>
