def wait_sign(args): bm = BitmessageClient() while True: messages = bm.get_unread_messages() print "unread messages: %r" % len(messages) for msg in messages: if msg.subject[0:10] == 'final-sign': try: content = json.loads(msg.message) print content['pwtxid'] except: print "problem with message parsing" time.sleep(5) else: print "complete signed tx for pwtxid: %s" % content['pwtxid'] print "please forward this to Eligius pool ( http://eligius.st/~wizkid057/newstats/pushtxn.php ):" print content['transaction'] bm.mark_message_as_read(msg) time.sleep(5)
def wait_sign(args): bm = BitmessageClient() while True: messages = bm.get_unread_messages() print "unread messages: %r" % len(messages) for msg in messages: if msg.subject[0:10] == 'final-sign': try: content = json.loads(msg.message) print content['pwtxid'] except: print "problem with message parsing" time.sleep(5) else: print "complete signed tx for pwtxid: %s" % content[ 'pwtxid'] print "please forward this to Eligius pool ( http://eligius.st/~wizkid057/newstats/pushtxn.php ):" print content['transaction'] bm.mark_message_as_read(msg) time.sleep(5)
def pricecheck_create(args): if len(args)<5: print "USAGE: `%s pricecheck_create <pubkey_once> <locktime_minutes> <return_address_if_greater> <return_address_if_smaller> <value>`" % START_COMMAND print "- run `%s main` to obtain pubkey_once" % START_COMMAND print "- keep in mind that this is alpha, don't expect oracles to run properly for any extended periods of time" return btc = BitcoinClient() request = {} client_pubkey = args[0] request['locktime'] = time.time() + int(args[1])*60 request['return_if_greater'] = args[2] request['return_if_lesser'] = args[3] request['price'] = float(args[4]) print "fetching charter url" # hopefully it didn't check between running main1 and main2 charter = fetch_charter(CHARTER_URL) oracle_pubkeys = [] oracle_fees = {} oracle_bms = [] for o in charter['nodes']: oracle_pubkeys.append(o['pubkey']) oracle_fees[o['address']] = o['fee'] oracle_bms.append(o['bm']) oracle_fees[charter['org_address']] = charter['org_fee'] min_sigs = int(ceil(float(len(oracle_pubkeys))/2)) key_list = [client_pubkey] + oracle_pubkeys response = btc.create_multisig_address(min_sigs, key_list) msig_addr = response['address'] # we're using this as an identificator redeemScript = response['redeemScript'] request['message_id'] = "%s-%s" % (msig_addr, str(randrange(1000000000,9000000000))) request['pubkey_list'] = key_list request['miners_fee_satoshi'] = MINERS_FEE print "fetching transactions incoming to %s ..." % msig_addr # for production purposes you might want to fetch the data using bitcoind, but that's expensive address_json = liburl_wrapper.safe_read("https://blockchain.info/address/%s?format=json" % msig_addr, timeout_time=10) try: address_history = json.loads(address_json) except: print "blockchain.info problem" print address_json return prevtxs = [] sum_satoshi = 0 for tx in address_history['txs']: outputs = [] if 'out' in tx: outputs = outputs + tx['out'] if 'outputs' in tx: outputs = outputs + tx['outputs'] for vout in tx['out']: print vout if vout['addr'] == msig_addr: prevtx = { 'scriptPubKey' : vout['script'], 'vout': vout['n'], 'txid': tx['hash'], 'redeemScript': redeemScript, } sum_satoshi += vout['value'] prevtxs.append(prevtx) if len(prevtxs) == 0: print "ERROR: couldn't find transactions sending money to %s" % msig_addr return request['prevtxs'] = prevtxs request['outputs'] = oracle_fees request["req_sigs"] = min_sigs request['operation'] = 'pricecheck_create' request['sum_satoshi'] = sum_satoshi bm = BitmessageClient() print "sending: %r" % json.dumps(request) print bm.chan_address request_content = json.dumps(request) print bm.send_message(bm.chan_address, request['operation'], request_content)
def main2(args): if len(args)<3: print "USAGE: `%s main2 <pubkey_once> <locktime_minutes> <return_address>`" % START_COMMAND print "- run `%s main` to obtain pubkey_once" % START_COMMAND print "- keep in mind that this is alpha, don't expect oracles to run properly for any extended periods of time" return btc = BitcoinClient() request = {} client_pubkey = args[0] request['locktime'] = time.time() + int(args[1])*60 request['return_address'] = args[2] print "fetching charter url" # hopefully it didn't check between running main1 and main2 charter = fetch_charter(CHARTER_URL) oracle_pubkeys = [] oracle_fees = {} oracle_bms = [] for o in charter['nodes']: oracle_pubkeys.append(o['pubkey']) oracle_fees[o['address']] = o['fee'] oracle_bms.append(o['bm']) oracle_fees[charter['org_address']] = charter['org_fee'] min_sigs = int(ceil(float(len(oracle_pubkeys))/2)) key_list = [client_pubkey] + oracle_pubkeys response = btc.create_multisig_address(min_sigs, key_list) msig_addr = response['address'] # we're using this as an identificator redeemScript = response['redeemScript'] request['message_id'] = "%s-%s" % (msig_addr, str(randrange(1000000000,9000000000))) request['pubkey_list'] = key_list request['miners_fee_satoshi'] = MINERS_FEE print "fetching transactions incoming to %s ..." % msig_addr # for production purposes you might want to fetch the data using bitcoind, but that's expensive address_json = liburl_wrapper.safe_read("https://blockchain.info/address/%s?format=json" % msig_addr, timeout_time=10) try: address_history = json.loads(address_json) except: print "blockchain.info problem" print address_json return prevtxs = [] sum_satoshi = 0 for tx in address_history['txs']: outputs = [] if 'out' in tx: outputs = outputs + tx['out'] if 'outputs' in tx: outputs = outputs + tx['outputs'] for vout in tx['out']: print vout if vout['addr'] == msig_addr: prevtx = { 'scriptPubKey' : vout['script'], 'vout': vout['n'], 'txid': tx['hash'], 'redeemScript': redeemScript, } sum_satoshi += vout['value'] prevtxs.append(prevtx) if len(prevtxs) == 0: print "ERROR: couldn't find transactions sending money to %s" % msig_addr return request['prevtxs'] = prevtxs request['outputs'] = oracle_fees request["req_sigs"] = min_sigs request['operation'] = 'timelock_create' request['sum_satoshi'] = sum_satoshi bm = BitmessageClient() print "sending: %r" % json.dumps(request) print bm.chan_address request_content = json.dumps(request) print bm.send_message(bm.chan_address, request['operation'], request_content) print "" print "Gathering oracle responses. It may take BitMessage 30-60 seconds to deliver a message one way." print "Although we've seen delays up to half an hour, especially if BitMessage client was just launched." print "" oracles_confirmed = 0 while oracle_bms: messages = bm.get_unread_messages() print "oracles confirmed: {}".format(oracles_confirmed) for msg in messages: if msg.from_address in oracle_bms: try: content = json.loads(msg.message) except: print msg.message print 'failed decoding message' continue if 'in_reply_to' not in content: continue if content['in_reply_to'] == request['message_id']: print "[%r][%r] %r" % (msg.subject, msg.from_address, msg.message) print "" oracle_bms.remove(msg.from_address) if oracle_bms: #if still awaiting replies from some oracles time.sleep(10)
def __init__(self): self.client = BitmessageClient() # Do we really need it here? self.default_address = self.client.default_address logging.info("my BM address: %r" % self.client.default_address)
class OracleCommunication: def __init__(self): self.client = BitmessageClient() # Do we really need it here? self.default_address = self.client.default_address logging.info("my BM address: %r" % self.client.default_address) def corresponds_to_protocol(self, message): try: body = json.loads(message.message) except ValueError: logging.info('message is not a valid json') return False if not 'operation' in body: logging.info('message has no operation') return False if not body['operation'] in op_handlers: logging.info('operation %r not supported' % body['operation']) return False operation = body['operation'] if operation in OPERATION_REQUIRED_FIELDS: required_fields = OPERATION_REQUIRED_FIELDS[operation] for field in required_fields: if not field in body: logging.info( 'required field {0} for operation {1} missing'.format( field, operation)) return False else: logging.warning( 'operation %r has no OPERATION_REQUIRED_FIELDS defined' % operation) logging.info('operation {0}'.format(operation)) return operation def get_new_requests(self): messages = self.client.get_unread_messages() requests = [] for msg in messages: if msg.direct: self.response(msg, 'DirectMessage', 'direct message unsupported') continue operation = self.corresponds_to_protocol(msg) if operation: requests.append((operation, msg)) else: # If message is not corresponding to protocol, then mark it as read # All other messages will me marked later self.client.mark_message_as_read(msg) return requests def mark_request_done(self, request): operation, message = request self.client.mark_message_as_read(message) def response(self, message, subject, response): self.response_to_address(message.from_address, subject, response) def response_to_address(self, address, subject, response): body = {} body['version'] = PROTOCOL_VERSION body['response'] = response body_json = json.dumps(body) self.client.send_message(address, subject, body_json) def broadcast(self, subject, message): self.client.send_message(self.client.chan_address, subject, message) def broadcast_identity(self): IDENTITY_MESSAGE_RAW = { "response": "active", "version": PROTOCOL_VERSION } self.client.send_broadcast('IdentityBroadcast', json.dumps(IDENTITY_MESSAGE_RAW))
def main2(args): if len(args) < 3: print "USAGE: `%s main2 <pubkey_once> <locktime_minutes> <return_address>`" % START_COMMAND print "- run `%s main` to obtain pubkey_once" % START_COMMAND print "- keep in mind that this is alpha, don't expect oracles to run properly for any extended periods of time" return btc = BitcoinClient() request = {} client_pubkey = args[0] request['locktime'] = time.time() + int(args[1]) * 60 request['return_address'] = args[2] print "fetching charter url" # hopefully it didn't check between running main1 and main2 charter = fetch_charter(CHARTER_URL) oracle_pubkeys = [] oracle_fees = {} oracle_bms = [] for o in charter['nodes']: oracle_pubkeys.append(o['pubkey']) oracle_fees[o['address']] = o['fee'] oracle_bms.append(o['bm']) oracle_fees[charter['org_address']] = charter['org_fee'] min_sigs = int(ceil(float(len(oracle_pubkeys)) / 2)) key_list = [client_pubkey] + oracle_pubkeys response = btc.create_multisig_address(min_sigs, key_list) msig_addr = response['address'] # we're using this as an identificator redeemScript = response['redeemScript'] request['message_id'] = "%s-%s" % (msig_addr, str(randrange(1000000000, 9000000000))) request['pubkey_list'] = key_list request['miners_fee_satoshi'] = MINERS_FEE print "fetching transactions incoming to %s ..." % msig_addr # for production purposes you might want to fetch the data using bitcoind, but that's expensive address_json = liburl_wrapper.safe_read( "https://blockchain.info/address/%s?format=json" % msig_addr, timeout_time=10) try: address_history = json.loads(address_json) except: print "blockchain.info problem" print address_json return prevtxs = [] sum_satoshi = 0 for tx in address_history['txs']: outputs = [] if 'out' in tx: outputs = outputs + tx['out'] if 'outputs' in tx: outputs = outputs + tx['outputs'] for vout in tx['out']: print vout if vout['addr'] == msig_addr: prevtx = { 'scriptPubKey': vout['script'], 'vout': vout['n'], 'txid': tx['hash'], 'redeemScript': redeemScript, } sum_satoshi += vout['value'] prevtxs.append(prevtx) if len(prevtxs) == 0: print "ERROR: couldn't find transactions sending money to %s" % msig_addr return request['prevtxs'] = prevtxs request['outputs'] = oracle_fees request["req_sigs"] = min_sigs request['operation'] = 'timelock_create' request['sum_satoshi'] = sum_satoshi bm = BitmessageClient() print "sending: %r" % json.dumps(request) print bm.chan_address request_content = json.dumps(request) print bm.send_message(bm.chan_address, request['operation'], request_content) print "" print "Gathering oracle responses. It may take BitMessage 30-60 seconds to deliver a message one way." print "Although we've seen delays up to half an hour, especially if BitMessage client was just launched." print "" oracles_confirmed = 0 while oracle_bms: messages = bm.get_unread_messages() print "oracles confirmed: {}".format(oracles_confirmed) for msg in messages: if msg.from_address in oracle_bms: try: content = json.loads(msg.message) except: print msg.message print 'failed decoding message' continue if 'in_reply_to' not in content: continue if content['in_reply_to'] == request['message_id']: print "[%r][%r] %r" % (msg.subject, msg.from_address, msg.message) print "" oracle_bms.remove(msg.from_address) if oracle_bms: #if still awaiting replies from some oracles time.sleep(10)
class OracleCommunication: def __init__(self): self.client = BitmessageClient() # Do we really need it here? self.default_address = self.client.default_address logging.info("my BM address: %r" % self.client.default_address) def corresponds_to_protocol(self, message): try: body = json.loads(message.message) except ValueError: logging.info('message is not a valid json') return False if not 'operation' in body: logging.info('message has no operation') return False if not body['operation'] in op_handlers: logging.info('operation %r not supported' % body['operation']) return False operation = body['operation'] if operation in OPERATION_REQUIRED_FIELDS: required_fields = OPERATION_REQUIRED_FIELDS[operation] for field in required_fields: if not field in body: logging.info('required field {0} for operation {1} missing'.format(field, operation)) return False else: logging.warning('operation %r has no OPERATION_REQUIRED_FIELDS defined' % operation) logging.info('operation {0}'.format(operation)) return operation def get_new_requests(self): messages = self.client.get_unread_messages() requests = [] for msg in messages: if msg.direct: self.response(msg, 'DirectMessage', 'direct message unsupported') continue operation = self.corresponds_to_protocol(msg) if operation: requests.append((operation, msg)) else: # If message is not corresponding to protocol, then mark it as read # All other messages will me marked later self.client.mark_message_as_read(msg) return requests def mark_request_done(self, request): operation, message = request self.client.mark_message_as_read(message) def response(self, message, subject, response): self.response_to_address(message.from_address, subject, response) def response_to_address(self, address, subject, response): body = {} body['version'] = PROTOCOL_VERSION body['response'] = response body_json = json.dumps(body) self.client.send_message( address, subject, body_json) def broadcast(self, subject, message): self.client.send_message(self.client.chan_address, subject, message) def broadcast_identity(self): IDENTITY_MESSAGE_RAW = { "response": "active", "version": PROTOCOL_VERSION } self.client.send_broadcast( 'IdentityBroadcast', json.dumps(IDENTITY_MESSAGE_RAW))