def get_op_return_data(txid): """ Method used to get op_return data from transaction Args: Transaction id (str) Returns: Embedded metadata (str) Author address (str) """ rpc = AuthServiceProxy( ("http://%s:%[email protected]:%s/") % (config['RPC_USER'], config['RPC_PASS'], config['RPC_PORT'])) raw_tx = rpc.getrawtransaction(txid) tx_data = rpc.decoderawtransaction(raw_tx) for data in tx_data["vout"]: if data["scriptPubKey"]["asm"][:9] == "OP_RETURN": op_return_data = str(unhexlify(data["scriptPubKey"]["asm"][10:]), encoding='utf-8') else: op_return_data = None try: author = tx_data['vout'][0]['scriptPubKey']['addresses'][0] except KeyError as e: author = None return op_return_data, author
def gettxs(): """Return FLO txid""" con = conn() access = AuthServiceProxy("http://%s:%[email protected]:%s" % (app.config['CURRENCY_B_RPC_USER'], app.config['CURRENCY_B_RPC_PASSWORD'], app.config['CURRENCY_B_RPC_PORT'])) # Check for the existing txid cur = con.cursor(prepared=True) txid = request.form.get("btc_txid") cur.execute("SELECT * FROM action WHERE txidreceive = %s;", [txid]) result = cur.fetchone() if not result: cur.close() con.close() return 'nothing-yet' rawtx = access.getrawtransaction(str(result[2])) txinfo = access.decoderawtransaction(rawtx) cur.close() con.close() return str(result[2]) + "/////" + str(txinfo)
def main(): access = ServiceProxy("http://*****:*****@127.0.0.1:8332") txid = sys.argv[1] # print txid txinfo = access.gettransaction(txid) pprint.pprint(txinfo) # Check the details to make sure it's an incoming transaction # Ensure everything is incoming, to avoid # mirroring change/consolidation transactions. myaddresses = set() for details in txinfo["details"]: # print details if details["category"] != "receive": return myaddresses.add(details["address"]) tx = access.decoderawtransaction(txinfo["hex"]) pprint.pprint(tx) # Now gather all the outputs to send back newtx_inputs = [] total_amount = Decimal(0) for vout in tx["vout"]: for address in vout["scriptPubKey"]["addresses"]: if address in myaddresses: newtx_inputs.append({"txid":txid,"vout":vout["n"]}) total_amount += vout["value"] break print newtx_inputs print total_amount # Now find the sendign addresses, and choose one at random # to receive the funds. total_inputs = Decimal("0") addresses = [] for vin in tx["vin"]: intxid = vin["txid"] invout = vin["vout"] # Get the outputs of the input transaction intx = access.getrawtransaction(intxid,1) # print intxid, invout vout = intx["vout"][invout] # pprint.pprint(vout) total_inputs += vout["value"] addresses.extend(vout["scriptPubKey"]["addresses"]) print "Total inputs: %f" % total_inputs print addresses to_address = random.choice(addresses) # Build a transaction with the output of the original transaction as input # and to_address as output. newtx_hex = access.createrawtransaction(newtx_inputs,{to_address:float(total_amount)}) newtx_hex = access.signrawtransaction(newtx_hex)["hex"] print newtx_hex # print >>open("/home/user/a.txt","a"), access.decoderawtransaction(newtx_hex) access.sendrawtransaction(newtx_hex)
def main(): rpc_user = '******' rpc_password = '******' rpc = AuthServiceProxy(f'http://{rpc_user}:{rpc_password}@127.0.0.1:18332/') #rpc = AuthServiceProxy(f'http://{rpc_user}:{rpc_password}@172.17.0.2:18332/') print(rpc.getinfo()) best_block_hash = rpc.getbestblockhash() print(rpc.getblock(best_block_hash)) blhash = rpc.getblockhash(0) #blhashはブロックのhash文字列 bl = rpc.getblock(blhash) #blはブロック情報 print(bl) dummy_address = '2MudgRfNaaw96kqAWziZ5JGsPbo2pzQp7Jy' change_address = '2NAVrak22jX3DQyDqnoqdm5ZTak1RgXWPzo' filename = 'mark_token.btc.json' url='https://drive.google.com/file/d/1ZR6Q5sCM_acUpPy7s3d9GJH8I2Plh4FI/view?usp=sharing' with open(filename, 'rb') as f: data2 = f.read() hashdata=hashlib.sha256(data2).hexdigest() js={'file_hash':hashdata,'url':url} data=json.dumps(js).encode("UTF-8") while True: if len(data) >= 80: buffer = data[:80] data = data[80:] elif len(data) == 0: break else: buffer = data data = b'' first_unspent = rpc.listunspent()[0] txid = first_unspent['txid'] vout = first_unspent['vout'] input_amount = first_unspent['amount'] SATOSHI = Decimal("0.00000001") change_amount = input_amount - Decimal("0.005") - SATOSHI tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}],[{change_address: change_amount}, {'data': hexlify(buffer).decode('utf-8')}, ]) tx = rpc.signrawtransactionwithwallet(tx)['hex'] rpc.sendrawtransaction(tx) block_hash = rpc.generatetoaddress(1, change_address)[0] block = rpc.getblock(block_hash) txs = block['tx'][1:] print(f'# of txs: {len(txs)}') pprint(txs) for tx_hash in txs: raw_tx = rpc.gettransaction(tx_hash)['hex'] decoded_tx = rpc.decoderawtransaction(raw_tx) # pprint(decoded_tx) print(decoded_tx['vout'][1]['scriptPubKey']['asm'])
class ParsingBlock(Parsing_block): def __init__(self, from_block=0, db_name="pars", collection="data3", to_block=-1): self.client = ClientHistory() self.from_block = from_block self.to_block = to_block self.qtum = AuthServiceProxy(qtum_server) self.db_wallet = Table_new(db_name, collection) def check(self, vout): try: for vout_i in vout: try: script_pub_key = vout_i["scriptPubKey"] addresses = script_pub_key["addresses"] value = vout_i["value"] value_float = float(value) value_int = int(value * (10**8)) for adr in addresses: data = self.client.getbalance(adr) if data == {'error': 404}: pass else: db_coin = self.db_wallet.insert_new( **{ "adr": adr, "value": value_int }) update_data_1 = self.client.incbalance( adr, value_float) #logging.critical(update_data_1) except: pass except: pass def decode_raw_transaction_vout(self, encoded_datas=None): try: if not encoded_datas: encoded_datas = self.get_raw_transaction() for encoded_data in encoded_datas: transaction_data = self.qtum.decoderawtransaction(encoded_data) vin = transaction_data["vin"] vout = transaction_data["vout"] self.check(vout) self.show_db() except: pass def getblockcount(self): return self.qtum.getblockcount()
def create_raw_op_return_transaction(metadata): """ Method used to create a transaction with embedded data through OP_RETURN Args: metadata (str) Returns: Raw transaction (hex) Author address (str) """ rpc = AuthServiceProxy( ("http://%s:%[email protected]:%s/") % (config['RPC_USER'], config['RPC_PASS'], config['RPC_PORT'])) if sys.getsizeof(metadata) > MAX_OP_RETURN_BYTES: raise Exception("Metadata size is over MAX_OP_RETURN_BYTES") if len(metadata) < 4: raise Exception( "This tool set does not currently support reading op_return data with less than 4 chars" ) input_tx = get_input() init_raw_tx = rpc.createrawtransaction( [{ "txid": input_tx["txid"], "vout": input_tx["vout"] }], { input_tx["address"]: TX_BURN_AMOUNT, rpc.getnewaddress(): round(float(input_tx["amount"]) - 1.1 * TX_BURN_AMOUNT, 8) }) oldScriptPubKey = init_raw_tx[len(init_raw_tx) - 60:len(init_raw_tx) - 8] newScriptPubKey = b"6a" + hexlify( bytes(chr(len(metadata)), encoding='utf-8')) + hexlify( bytes(metadata, encoding='utf-8')) newScriptPubKey = hexlify( bytes(chr(len(unhexlify(newScriptPubKey))), encoding='utf-8')) + newScriptPubKey if oldScriptPubKey not in init_raw_tx: raise Exception("Something broke!") op_return_tx = init_raw_tx.replace(oldScriptPubKey, newScriptPubKey.decode('ascii')) print(rpc.decoderawtransaction(op_return_tx)['vout']) return op_return_tx, input_tx["address"]
def rpc_loop(ncurses_q, json_q): config = ConfigParser.ConfigParser() config.read('bitcoind-ncurses.conf') rpcuser = config.get('rpc', 'rpcuser') rpcpassword = config.get('rpc', 'rpcpassword') rpcip = config.get('rpc', 'rpcip') rpcport = config.get('rpc', 'rpcport') rpcurl = "http://" + rpcuser + ":" + rpcpassword + "@" + rpcip + ":" + rpcport rpchandle = AuthServiceProxy(rpcurl, None, 500) last_blockcount = 0 # ensures block info is updated initially last_update = time.time() - 2 while 1: try: s = json_q.get(False) except: s = {} if 'blockheight' in s: blockhash = rpchandle.getblockhash(s['blockheight']) blockinfo = rpchandle.getblock(blockhash) ncurses_q.put(blockinfo) last_blockcount = cur_blockcount elif 'txid' in s: raw_tx = rpchandle.getrawtransaction(s['txid']) decoded_tx = rpchandle.decoderawtransaction(raw_tx) ncurses_q.put(decoded_tx) if (time.time() - last_update) > 2: info = rpchandle.getinfo() ncurses_q.put(info) nettotals = rpchandle.getnettotals() ncurses_q.put(nettotals) walletinfo = rpchandle.getwalletinfo() ncurses_q.put(walletinfo) cur_blockcount = info['blocks'] if (cur_blockcount != last_blockcount): # minimise RPC calls #if (last_blockcount == 0): lastblocktime = {'lastblocktime': time.time()} ncurses_q.put(lastblocktime) blockhash = rpchandle.getblockhash(cur_blockcount) blockinfo = rpchandle.getblock(blockhash) ncurses_q.put(blockinfo) last_blockcount = cur_blockcount last_update = time.time() time.sleep(0.5) # minimise RPC calls
def block_updater(): logger = logging.getLogger('Block Updater') logger.setLevel(logging.INFO) while 1: rpc_connection = AuthServiceProxy(config.config["rpc_server_uri"]) block = rpc_connection.getblock(config.config["current_block"]) logger.info(f"Update Tip: Block={config.config['current_block']},Height={block['height']}") if "confirmations" in block and "nextblockhash" in block: config.config["current_block"] = block["nextblockhash"] config.save_config() for i in block["tx"]: tx = rpc_connection.decoderawtransaction(rpc_connection.getrawtransaction(i)) decode_opreturn_msg(tx, block) else: time.sleep(6)
class BitcoinCLI: def __init__(self): self.rpc_connection = AuthServiceProxy(config.endpoint) def get_best_block_hash(self): return self.rpc_connection.getbestblockhash() def get_block_count(self): return self.rpc_connection.getblockcount() def get_best_block(self): return self.rpc_connection.getblock(self.rpc_connection.getbestblockhash()) def get_block_hash(self, height): return self.rpc_connection.getblockhash(height) def get_block(self, hash): return self.rpc_connection.getblock(hash) def get_transaction(self, hash): return self.rpc_connection.gettransaction(hash) def get_txn_list_from_block(self, hash): block = self.get_block(hash) if 'tx' in block: return block['tx'] else: raise KeyError('Block {0} has no attribute tx'.format(hash)) def get_raw_transaction(self, tx_id): out = self.rpc_connection.getrawtransaction(tx_id, 1) return out def decoderawtransaction(self, tx_id): out = self.rpc_connection.decoderawtransaction(raw) return out def get_tx_outputs(self, tx_id): tx = self.rpc_connection.getrawtransaction(tx_id, 1) outputs = [float(i['value']) for i in tx['vout']] return outputs def get_tx_details(self, tx_id): tx = self.rpc_connection.getrawtransaction(tx_id, 1) outputs = [float(i['value']) for i in tx['vout']] return outputs
def get_tx_burn_amount(txid): """ Method used to get burn output amount for transactions (for op_return transactions) Args: Transaction id (str) Returns: Sum of input values, i.e. burn amount (float) """ rpc = AuthServiceProxy( ("http://%s:%[email protected]:%s/") % (config['RPC_USER'], config['RPC_PASS'], config['RPC_PORT'])) raw_tx = rpc.getrawtransaction(txid) tx_data = rpc.decoderawtransaction(raw_tx) for data in tx_data["vout"]: if data["scriptPubKey"]["asm"][:9] == "OP_RETURN": return data['value']
class LocalBlockchainRPCReader(object): """Fetches blockchain data from bitcoind RPC interface.""" def __init__(self, username=None, password=None, host=None, port=None): if None in (username, password, host, port): username, password, host, port, _ = get_config_settings() self.rpc_connection = AuthServiceProxy( "http://%s:%s@%s:%s" % (username, password, host, port)) def get_block_hash_at_height(self, block_height): """Get the hash of the block at the specified height.""" return self.rpc_connection.getblockhash(block_height) def get_json_for_block_hash(self, block_hash): """Get a JSON representation of all transactions at specified height.""" return self.rpc_connection.getblock(block_hash) def _get_raw_tx(self, tx_id): """Returns tx in raw format. If the requested transaction is the sole transaction of the genesis block, bitcoind's RPC interface will throw an error 'No information available about transaction (code -5)' so we preempt this by raising an error. Iterating callers should just move on to the next tx or block. """ if tx_id == ( '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7af' 'deda33b'): raise NoDataAvailableForGenesisBlockError else: return self.rpc_connection.getrawtransaction(tx_id) def get_decoded_tx(self, tx_id): """Returns a human-readable string of the transaction in JSON format.""" #print "DEBUG: get_decoded_tx %s" % tx_id try: return self.rpc_connection.decoderawtransaction( self._get_raw_tx(tx_id)) except NoDataAvailableForGenesisBlockError: #bitcoind won't generate this, but here's what it would look like genesis_json = { 'txid': ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2' '127b7afdeda33b'), 'version': 1, 'locktime': 0, 'vin': [{ "sequence": 4294967295, 'coinbase': ('04ffff001d0104455468652054696d65732030332f4a6' '16e2f32303039204368616e63656c6c6f72206f6e2062' '72696e6b206f66207365636f6e64206261696c6f75742' '0666f722062616e6b73') }], 'vout': [{ 'value': 50.00000000, 'n': 0, 'scriptPubKey': { 'asm': ('04678afdb0fe5548271967f1a67130b7105cd6a828' 'e03909a67962e0ea1f61deb649f6bc3f4cef38c4f3' '5504e51ec112de5c384df7ba0b8d578a4c702b6bf1' '1d5f OP_CHECKSIG'), 'hex': ('4104678afdb0fe5548271967f1a67130b7105cd6a8' '28e03909a67962e0ea1f61deb649f6bc3f4cef38c4' 'f35504e51ec112de5c384df7ba0b8d578a4c702b6b' 'f11d5fac'), 'reqSigs': 1, 'type': 'pubkey', 'addresses': ['1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'] } }] } return genesis_json def get_decoded_script(self, asm): """Convert bitcoind's 'asm' value to decoded format.""" return self.rpc_connection.decodescript(asm)
def main(): # Example # ------- # This asset: https://blockstream.info/liquid/asset/f266a3f15e78b71481adfedff9aefe47c69501a181ffc68527bb5fb26da6a4b2 # Was issued in transaction: https://blockstream.info/liquid/tx/49cc1ca72be5b5ca3375348274cee22ccb686f4c3a8f8bc7767156680ca61d92 # Which was included in block: 1038078 # You can run the script with: # ASSET_ID = 'f266a3f15e78b71481adfedff9aefe47c69501a181ffc68527bb5fb26da6a4b2' # START_BLOCK_HEIGHT = 1038078 # STOP_AT_BLOCK_HEIGHT = None # That will trawl every block since issuance to check for any reissuances # or burns for the asset so you can validate the amounts shown on the # liquid assets page above. ########################################################################### # BEFORE RUNNING THE SCRIPT SET THE VALUES BELOW ########################################################################### # REQUIRED # -------- # Elements RPC Credentials # You need to change all 3 after setting them in your elements.conf file. # See associated README for example config file format. RPC_USER = '******' RPC_PASSWORD = '******' RPC_PORT = 18885 # BLOCK RANGE CONTROL # ------------------- # The script will save the last block processed to file and will pick up # from there if you set this to True. False will ignore the contents of # the LAST_BLOCK file and use START_BLOCK_HEIGHT. If there is no # LAST_BLOCK file it will use START_BLOCK_HEIGHT. START_FROM_LAST_BLOCK_PROCESSED = True # If START_FROM_LAST_BLOCK_PROCESSED is False or the script has not been # run before you can specify the initial start block height. # This may be useful if you know an initial issuance was done at a # particular block height and do not need to process earlier blocks. # After running the script the last block processed will saved in the file # LAST_BLOCK. START_BLOCK_HEIGHT = 0 # Stop processing at a particular block height (inclusive). # Set to None to process until chain tip. # If a value is given and the value is equal to the value in LAST_BLOCK the # script will exit. # If a value is given and the value is lower than the height in # the LAST_BLOCK_HEIGHT file it will be ignored and the script will run to # chain tip. STOP_AT_BLOCK_HEIGHT = None # OPTIONAL ASSET ID TO LOOK FOR # ----------------------------- # Set the following to an asset hex if you want to report on a specific # asset, otherwise leave it as None to report on all assets: # Note: the L-BTC asset id is 6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d # This script will track burns of L-BTC but not pegs in or out yet. ASSET_ID = None ########################################################################### # BEFORE RUNNING THE SCRIPT SET THE VALUES ABOVE ########################################################################### block_count = 0 block_hash = '' rpc_ready = False end_of_chain = False block_height = START_BLOCK_HEIGHT saved_block_height = None if START_FROM_LAST_BLOCK_PROCESSED: saved_block_height = readLastBlockHeight() if saved_block_height: if STOP_AT_BLOCK_HEIGHT: if saved_block_height > STOP_AT_BLOCK_HEIGHT: # If the last block processed is greater than the stop height # process up to chain tip instead. STOP_AT_BLOCK_HEIGHT = None if saved_block_height == STOP_AT_BLOCK_HEIGHT: print( f'LAST_BLOCK value is {saved_block_height} and so is STOP_AT_BLOCK_HEIGHT. Exiting.' ) print( f'Note: set STOP_AT_BLOCK_HEIGHT to None to process to chain tip.' ) sys.exit() if saved_block_height > START_BLOCK_HEIGHT: # If the last block processed is greater than the start height # process from last block processed. This avoids writing duplicate # entries to the asset files. block_height = saved_block_height + 1 message_block_stop_at = 'chain tip' if STOP_AT_BLOCK_HEIGHT: message_block_stop_at = f'block {str(STOP_AT_BLOCK_HEIGHT)}' print( f'Will process from block {block_height} to {message_block_stop_at}.') print('Do you want to start processing blocks? (y/n)') x = input() if x.upper() == 'N' or x.upper() == 'No': print(f'Exiting.') sys.exit() print(f'Processing...') # Delete any old asset files if we are starting from genesis: if block_height == 0: removeAssetFiles() # Check node is ready for RPC calls while not rpc_ready: try: rpc_connection = AuthServiceProxy( f'http://{RPC_USER}:{RPC_PASSWORD}@127.0.0.1:{RPC_PORT}') block_count = rpc_connection.getblockcount() rpc_ready = True except Exception as e: print(f'Cannot connect to node or node not ready for RPC: {e}') print('Sleeping for 5 seconds...') time.sleep(5) print('Connected to node using RPC') last_existing_block = None while not end_of_chain: try: print(f'Processing block at height {block_height}') block_hash = rpc_connection.getblockhash(block_height) block = rpc_connection.getblock(block_hash) last_existing_block = block_height txs = block['tx'] for tx in txs: tx_hash = rpc_connection.getrawtransaction(tx) tx_details = rpc_connection.decoderawtransaction(tx_hash) #Issuances and Reissuances: for vin in tx_details['vin']: issuance = vin.get('issuance') if issuance: if ASSET_ID is None or ASSET_ID == issuance['asset']: print(f"Found asset: {issuance['asset']}") writeIssueOrReissue(issuance, block_height) #Burns: for vout in tx_details['vout']: vout_value = str(vout.get('value', '0E-8')) if vout_value != '0.00000000' and vout_value != '0E-8': script_pubkey = vout.get('scriptPubKey') if script_pubkey: asm = script_pubkey.get('asm') script_type = script_pubkey.get('type') if asm and script_type: if asm == 'OP_RETURN' and script_type == 'nulldata': if ASSET_ID is None or ASSET_ID == vout[ 'asset']: writeBurn(vout, block_height) if STOP_AT_BLOCK_HEIGHT: if STOP_AT_BLOCK_HEIGHT == block_height: end_of_chain = True block_height = block_height + 1 except Exception as e: if hasattr(e, 'message'): if e.message == 'Block height out of range': print(f'No block at height {block_height}. Stopping.') else: print(f'Error: {e.message}') else: print(f'Error: {e}') end_of_chain = True if last_existing_block: print( f'Last block processed was at height {last_existing_block}. Saved last block height to "LAST_BLOCK" file.' ) writeLastBlockHeight(last_existing_block)
# Find the price data that was the latest before the block was mined while not (block['time'] >= (int(row[0])) and block['time'] <= int(row[0])+600): row = next(priceDataReader) btcPrice = float(row[7]) t3 = time.time() # Iterate through every tx in a block. Don't want to include the coinbase tx when iterating through # each tx in a block for txid in block['tx'][1:]: totalIn = 0 totalOut = 0 rpcLookupCount += 1 # Get data of a tx tx = node.decoderawtransaction(node.getrawtransaction(txid), True) try: # Need the total Bitcoins being used as inputs for input in tx['vin']: inputCount += 1 rpcLookupCount += 1 # Need to know which index of an output of this tx is being spent index = input['vout'] # The node only refers to the txid of the output that's being spent in this input, so need to fetch # that first txo = node.decoderawtransaction(node.getrawtransaction(input['txid']), True) # Need to get the actual output of this tx being spent to get the amount totalIn += txo['vout'][index]['value'] # Need the total Bitcoins being spent as outputs
class RPCConnection: """Creates a continuous connection to the bitcoind RPC interface. RPC connections are configured by the configuration file referred to by `CONFIG_FILENAME`. Attributes: conn (`AuthServiceProxy`): A connection to the RPC interface. """ def __init__(self): config_parser = ConfigParser.ConfigParser() config_parser.read(CONFIG_FILENAME) username = config_parser.get(section='RPC', option='rpc_username') password = config_parser.get(section='RPC', option='rpc_password') host = config_parser.get(section='RPC', option='rpc_host') port = config_parser.get(section='RPC', option='rpc_port') self.conn = AuthServiceProxy("http://%s:%s@%s:%s" % (username, password, host, port)) def get_block_hash_at_height(self, block_height): """Get the hash of the block at the specified block height.""" return self.conn.getblockhash(block_height) def get_json_for_block_hash(self, block_hash): """Get a JSON represntation of the specified block.""" return self.conn.getblock(block_hash) def get_tx_ids_at_height(self, block_height): """Get a list of transaction IDs contained in the specified block.""" block_hash = self.get_block_hash_at_height(block_height) tx_json = self.get_json_for_block_hash(block_hash) tx_ids = [] for tx_id in tx_json['tx']: tx_ids.append(tx_id) return tx_ids def get_raw_tx(self, tx_id): """Return transaction in raw format. If the requested transaction is the sole transaction of the genesis block, bitcoind's RPC interface will throw an error 'No information available about transaction (code -5)' so we preempt this by raising a custom error that callers should handle; iterating callers should just move onto the next tx. """ if tx_id == ( '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7af' 'deda33b'): raise IndexError else: return self.conn.getrawtransaction(tx_id) def get_decoded_tx(self, tx_id): """Gets the transaction in JSON format from the RPC interface.""" try: return self.conn.decoderawtransaction(self.get_raw_tx(tx_id)) except IndexError: #bitcoind won't generate this, but here's what it would look like genesis_json = { 'txid': ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2' '127b7afdeda33b'), 'version': 1, 'locktime': 0, 'vin': [{ "sequence": 4294967295, 'coinbase': ('04ffff001d0104455468652054696d65732030332f4a6' '16e2f32303039204368616e63656c6c6f72206f6e2062' '72696e6b206f66207365636f6e64206261696c6f75742' '0666f722062616e6b73') }], 'vout': [{ 'value': 50.00000000, 'n': 0, 'scriptPubKey': { 'asm': ('04678afdb0fe5548271967f1a67130b7105cd6a828' 'e03909a67962e0ea1f61deb649f6bc3f4cef38c4f3' '5504e51ec112de5c384df7ba0b8d578a4c702b6bf1' '1d5f OP_CHECKSIG'), 'hex': ('4104678afdb0fe5548271967f1a67130b7105cd6a8' '28e03909a67962e0ea1f61deb649f6bc3f4cef38c4' 'f35504e51ec112de5c384df7ba0b8d578a4c702b6b' 'f11d5fac'), 'reqSigs': 1, 'type': 'pubkey', 'addresses': ['1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'] } }] } return genesis_json
class WalletBase: def __init__(self, pay_tx_fee, min_tx_fee, prio_threshold, dust_soft_limit, free_tx_size): self.proxy = None self.pay_tx_fee = pay_tx_fee self.min_tx_fee = min_tx_fee self.prio_threshold = prio_threshold self.dust_soft_limit = dust_soft_limit self.free_tx_size = free_tx_size def set_size(self, base_size, input_size, output_size): self.base_size = base_size self.input_size = input_size self.output_size = output_size def load_config(self, config_path): # trick to load a config file without sections con = open(config_path, 'r').read() dummy_fp = io.StringIO(("[%s]\n" % TMP_SECTION) + con) config = configparser.ConfigParser() config.readfp(dummy_fp) ## utility function def get_conf(key, default=None): if config.has_option(TMP_SECTION, key): return config.get(TMP_SECTION, key) return default self.rpc_user = get_conf('rpcuser') self.rpc_pass = get_conf('rpcpassword') self.rpc_port = int(get_conf('rpcport')) self.rpc_host = get_conf('rpcconnect', '127.0.0.1') if config.has_option(TMP_SECTION, 'paytxfee'): self.pay_tx_fee = int(float(get_conf('paytxfee')) * 10**8) if config.has_option(TMP_SECTION, 'mintxfee'): self.min_tx_fee = int(float(get_conf('mintxfee')) * 10**8) def connect(self): self.proxy = AuthServiceProxy('http://%s:%s@%s:%d/' % (self.rpc_user, self.rpc_pass, self.rpc_host, self.rpc_port)) def get_size(self, inputs, outputs): raw = self.proxy.createrawtransaction(inputs, outputs) return len(raw) / 2 ## Deprecate after official supports for getrawchangeaddress in major coins def get_change_address(self): groups = self.proxy.listaddressgroupings() for group in groups: for entry in group: if len(entry) == 3: ## maybe with account continue elif len(entry) == 2: res = self.proxy.validateaddress(entry[0]) if 'account' not in res: return entry[0] else: raise RuntimeError('never reach') return self.proxy.getnewaddress() ## ref: wallet.cpp CWallet::CreateTransaction def calculate(self, inputs, address, amount, chgaddress): tmp = {address: float(amount) / 10**8, chgaddress: 1 } size = self.get_size(inputs, tmp) total = 0 prio = 0 for inp in inputs: raw = self.proxy.getrawtransaction(inp['txid']) tx = self.proxy.decoderawtransaction(raw) value = tx['vout'][inp['vout']]['value'] conf = self.proxy.gettransaction(inp['txid'])['confirmations'] total += int(value * 10**8) prio += int(value * 10**8) * (conf + 1) prio = int(prio / size) payfee = self.pay_tx_fee * (1 + int(size / 1000)) minfee = self.min_tx_fee * (1 + int(size / 1000)) if prio >= self.prio_threshold and size < self.free_tx_size: minfee = 0 if amount < self.dust_soft_limit: minfee += self.min_tx_fee if total-amount-minfee < self.dust_soft_limit: minfee += self.min_tx_fee fee = max(payfee, minfee) change = total - amount - fee if change <= 0: raise RuntimeError('Insufficient inputs: change = %f' % (float(change) / 10**8)) return { 'total': total, 'fee': fee, 'change': change, 'size': size, 'prio': prio } def send(self, inputs, address, amount): chgaddress = self.get_change_address() res = self.calculate(inputs, address, amount, chgaddress) outputs = { address: float(amount) / 10**8, chgaddress: float(res['change']) / 10**8 } raw = self.proxy.createrawtransaction(inputs, outputs) signed = self.proxy.signrawtransaction(raw) if not signed['complete']: raise RuntimeError('signatures are missing') return self.proxy.sendrawtransaction(signed['hex']) def show_send_info(self, inputs, address, amount): chgaddress = self.get_change_address() res = self.calculate(inputs, address, amount, chgaddress) print('Total amount: %f' % (float(res['total']) / 10**8)) print('Send: %f to %s' % (float(amount) / 10**8, address)) print('Change: %f to %s' % (float(res['change']) / 10**8, chgaddress)) print('Fee: %f' % (float(res['fee']) / 10**8)) print('Size: %d bytes' % res['size']) print('Priority: %d' % res['prio']) def unspent_coins(self): coins = self.proxy.listunspent(6) for c in coins: c['amount'] = int(c['amount'] * 10**8) c['prio'] = c['amount'] * (c['confirmations'] + 1) return coins
curblock = curblock + 1 totalblk = rpcpipe.getblockcount() if (curblock > totalblk - txnconf): with open('/root/moonaudit/progress.dat', 'w') as progress: progress.write(str(curblock - 1)) progress.closed exit() rawblockhash = rpcpipe.getblockhash(curblock) rawblockdata = rpcpipe.getblock(rawblockhash) print 'checking block %08d' % (curblock) timestamp = find_between(str(rawblockdata), 'time\': ', ', u\'bits') sendnum = 0 for txhash in rawblockdata['tx']: sendnum = sendnum + 1 txraw = rpcpipe.getrawtransaction(txhash) txdata = rpcpipe.decoderawtransaction(txraw) curvout = -1 for outputs in txdata['vout']: curvout = curvout + 1 address = '' value = 0 address = find_between(str(outputs), '[u\'', '\']') value = find_between(str(outputs), 'Decimal(\'', '\')') if (float(str(value)) > 28999999.99999999): print 'block number: %08d;' % ( curblock, ) + ' unixtime: ' + timestamp + '; address: ' + address + '; coins sent in one operation: ' + str( value) + '; txid of transaction: ' + txhash with open('/var/www/moonsend_working.log', 'a') as moonaudit: moonaudit.write( 'block number: %08d;' % (curblock, ) + ' unixtime: ' +
print("Wallet Info:") print("-----------") pprint(wallet_info) print("---------------------------------------------------------------\n") ## List UTXOs utxos = rpc_client.listunspent() print("Utxos: ") print("-----") pprint(utxos) print("------------------------------------------\n") ## Select a UTXO - first one selected here utxo_txid = utxos[0]['txid'] ## Get UTXO Hex utxo_hex = rpc_client.gettransaction(utxo_txid)['hex'] ## Get tx Details utxo_tx_details = rpc_client.decoderawtransaction(utxo_hex) print("Details of Utxo with txid:", utxo_txid) print("---------------------------------------------------------------") print("UTXO Details:") print("------------") pprint(utxo_tx_details) print("---------------------------------------------------------------\n")
class Parsing_block(): def __init__(self, from_block=0, to_block=-1, db_name="pars", collection="wallet7"): self.from_block = from_block self.to_block = to_block self.qtum = AuthServiceProxy("http://%s:%[email protected]:8333" % ("qtumuser", "qtum2018")) self.db_wallet = Table_new(db_name, collection) def block_hash_num(self, block=None): try: if not block: block = self.from_block block_hash = self.qtum.getblockhash(block) return block_hash except: pass def get_transaction_in_block(self, block_hash=None): try: if not block_hash: block_hash = self.block_hash_num() block = self.qtum.getblock(block_hash) list_tx = block["tx"] return list_tx except: pass def get_raw_transaction(self, transaction_blocks=None): try: if not transaction_blocks: transaction_blocks = self.get_transaction_in_block() transaction_list = [] for transaction_block in transaction_blocks: try: transaction_data = self.qtum.getrawtransaction( transaction_block) except JSONRPCException: try: send_data = self.qtum.sendrawtransaction( transaction_block) pprint(send_data) except JSONRPCException: pass else: transaction_list += [transaction_data] return transaction_list except: pass ''' def insert_db(self, vout): for vout_i in vout: try: n_dict = {} script_pub_key = vout_i["scriptPubKey"] addresses = script_pub_key["addresses"] value = vout_i["value"] n = vout_i["n"] n_str = str(n) list_adr = [] for iter_adr in addresses: list_adr += [{iter_adr: value}] n_dict[n_str] = list_adr print(n_dict) except KeyError: pass ''' def transaction_in(self, vin): try: for vin_i in vin: try: txid = vin_i["txid"] vout_num = vin_i["vout"] encoded_datas = self.get_raw_transaction([txid]) for i in encoded_datas: transaction_data = self.qtum.decoderawtransaction(i) vout_prev = transaction_data["vout"] vout_prev_data = vout_prev[vout_num] value_dec = vout_prev_data["value"] script_pub_key = vout_prev_data["scriptPubKey"] addresses = script_pub_key["addresses"] value_int = int(value_dec * (10**8)) for address in addresses: news = self.db_wallet.update_inc( address, "value", -value_int) except KeyError: pass except: pass def transaction_out(self, vout): try: for vout_i in vout: try: script_pub_key = vout_i["scriptPubKey"] addresses = script_pub_key["addresses"] value = vout_i["value"] value_int = int(value * (10**8)) for adr in addresses: if not self.db_wallet.find({'id': adr}): data = self.db_wallet.insert(adr, **{"value": 0}) news = self.db_wallet.update_inc( adr, "value", value_int) #self.db_wallet.delete(adr) except KeyError: pass except: pass def decode_raw_transaction(self, encoded_datas=None): try: if not encoded_datas: encoded_datas = self.get_raw_transaction() for encoded_data in encoded_datas: transaction_data = self.qtum.decoderawtransaction(encoded_data) vin = transaction_data["vin"] vout = transaction_data["vout"] self.transaction_out(vout) self.transaction_in(vin) except: pass def show_db(self): return self.db_wallet.show_db()
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException # rpc_user and rpc_password are set in the bitcoin.conf file rpc_btc = AuthServiceProxy("http://%s:%[email protected]:8332"%('rpc_user', 'rpc_password')) blockchain = open('blockchain.txt', 'ab+') #you will need to make this blank file in your python folder before running the program for i in range(1,416570,1): #the range of blocks to grab data for, in this case blocks 1 to 416570, incrementing 1 block at a time get_block_hash = rpc_btc.getblockhash(i) block = rpc_btc.getblock(get_block_hash) coinbase = rpc_btc.decoderawtransaction(rpc_btc.getrawtransaction(block['tx'][0])) value = coinbase['vout'][0]['value'] #this gets total block reward print(i) blockchain.write(str(block['height'])+', '+str(value)+', '+str(block['hash'])+', '+str(block['size'])+', '+str(len(block['tx']))+', '+str(block['version'])+', '+str(block['merkleroot'])+', '+str(block['time'])+', '+str(block['nonce'])+', '+str(block['bits'])+', '+str(block['difficulty'])+', '+str(block['chainwork'])+'\n') blockchain.close() print('done')
class SearchTransaction(): def __init__(self, from_block=0, qtum_host=qtum_host_def): self.qtum = AuthServiceProxy(qtum_host) self.from_block = from_block self.client = self.conection_stor() self.balance = ClientBalance(balance_server) def abi_to_params(self, abi, output_types): decode_hex = codecs.getdecoder("hex_codec") encode_hex = codecs.getencoder("hex_codec") data = decode_hex(abi)[0] return decode_abi(output_types, data) def search_transaction(self, txid, address_smart_contract, vouts): signatures = {'8c3ce5d7': ['makeCid({0[0]}, {0[1]}, {0[2]}, {0[3]}, {0[4]})', ['string', 'address', 'string', 'uint256', 'uint256'], self.new_cid], '65d72416': ['newOffer({0[0]}, {0[1]}, {0[2]}, {0[3]}, {0[4]})', ['uint256', 'address', 'uint256', 'uint256', 'string'], self.new_offer], '715c084b': ['sellContent({0[0]}, {0[1]}, {0[2]})', ['uint256', 'address', 'string', 'string'], self.confirm_balance], 'bbfd5e53': ['changeOwner({0[0]}, {0[1]}, {0[2]})', ['uint256', 'address', 'string', 'string'], self.confirm_balance], '41309af4': ["newReview({0[0]}, {0[1]}, {0[2]}, {0[3]})", ["uint256", "address", "string"], self.update_review], 'a9059cbb': ["", ['address', 'uint'], self.balance_put] } list_data = [] # hex_block = self.qtum.getrawtransaction(txid) # decode_block = self.qtum.decoderawtransaction(hex_block) # pprint(decode_block) # vouts = decode_block["vout"] for vout in vouts: script_pub_key = vout["scriptPubKey"] types = script_pub_key["type"] if types == "call": asm = script_pub_key["asm"] asm_split = asm.split() asm_data = asm_split[3] smart_contr_address = asm_split[4] if smart_contr_address in address_smart_contract: hex_address = asm_data[:8] data = asm_data[8:] signatures_list = signatures[hex_address] signatures_list_type = signatures_list[1] # signatures_list_text = signatures_list[0] # print(data, signatures_list_type) try: decode = self.abi_to_params(data, signatures_list_type) new_decode = self.change_decode(signatures_list_type, decode) data_write = [txid] + new_decode method = signatures_list[2] method_call = method(data_write) # print(map(signatures_list[2], data)) # print(data) # decode_string = signatures_list_text.format(new_decode) # print(decode_string) list_data += data except Exception as e: print(e) return list_data def change_decode(self, signatures_list_type, decode): decode = list(decode) if "address" in signatures_list_type: index_adr = signatures_list_type.index("address") decode_index_adr = decode[index_adr] new_adr = decode_index_adr[2:] decode[index_adr] = new_adr if "string" in signatures_list_type: index_str = signatures_list_type.index("string") decode_index_str = decode[index_str] new_str = decode_index_str.decode() decode[index_str] = new_str return decode def block_hash_num(self, block=None): # get block hash try: if not block: block = self.from_block block_hash = self.qtum.getblockhash(block) return block_hash except: pass def get_transaction_in_block(self, block_hash=None): # get list transaction in block try: if not block_hash: block_hash = self.block_hash_num() block = self.qtum.getblock(block_hash) list_tx = block["tx"] return list_tx except: pass def get_raw_transaction(self, transaction_blocks=None): # get raw transaction try: if not transaction_blocks: transaction_blocks = self.get_transaction_in_block() transaction_list = [] for transaction_block in transaction_blocks: try: transaction_data = [self.qtum.getrawtransaction(transaction_block)] transaction_data += [transaction_block] transaction_list += [transaction_data] except JSONRPCException: try: transaction_data = [self.qtum.gettransaction(transaction_block)] transaction_data += [transaction_block] transaction_list += [transaction_data] except JSONRPCException: pass # print(transaction_block) return transaction_list except: pass def decode_raw_transaction(self, address_smart_contract, encoded_datas=None): # decode raw transaction try: if not encoded_datas: try: encoded_datas = self.get_raw_transaction() except: pass for encoded_data in encoded_datas: try: # encoded_data = encoded_datas[2] # print(encoded_data) transaction_data = self.qtum.decoderawtransaction(encoded_data[0]) # print(transaction_data) # vin = transaction_data["vin"] # print(vin) txid = encoded_data[1] vout = transaction_data["vout"] # print(vout) result = self.search_transaction(txid, address_smart_contract, vout) except: pass except: pass def balance_put(self, data): txid = data[0] address = data[1] address = Qtum.hex_to_qtum_address(address, mainnet=False) ammount = data[2] check = self.balance.get_balance(address, "PUT") if type(check) == list: update_data_1 = self.balance.inc_balance(address, ammount, "PUT") def new_cid(self, data): tx_hash = data[0] cid = data[1] result = self.client.update_users_content(txid=tx_hash) def new_offer(self, data): txid = data[0] cid = data[1] address = data[2] offer_type = data[3] price = data[4] self.client.update_offer(txid) mail = self.client.mailed_confirm(cid=cid, buyer_address=address, offer_type=offer_type, price=price) def confirm_balance(self, data): tx_hash = data[0] cid = data[1] address = data[2] result = self.balance.confirm_balance(txid=tx_hash, cid=cid, buyer_address=address) def update_review(self, data): txid = data[0] self.client.update_review(txid) def conection_stor(self): while True: try: cli = ClientStorge(storghost) return cli except: sleep(1) def run(self, from_i, address_smart_contract): while True: getlastblock = self.qtum.getblockcount() # print(getlastblock) if getlastblock >= from_i: pars = SearchTransaction(from_i) result = pars.decode_raw_transaction(address_smart_contract) print(from_i) from_i += 1 else: sleep(1)
class RPCConnection: """Creates a continuous connection to the bitcoind RPC interface. RPC connections are configured by the configuration file referred to by `CONFIG_FILENAME`. Attributes: conn (`AuthServiceProxy`): A connection to the RPC interface. """ def __init__(self): config_parser = ConfigParser.ConfigParser() config_parser.read(CONFIG_FILENAME) username = config_parser.get(section='RPC', option='rpc_username') password = config_parser.get(section='RPC', option='rpc_password') host = config_parser.get(section='RPC', option='rpc_host') port = config_parser.get(section='RPC', option='rpc_port') self.conn = AuthServiceProxy("http://%s:%s@%s:%s" % (username, password, host, port)) def get_block_hash_at_height(self, block_height): """Get the hash of the block at the specified block height.""" return self.conn.getblockhash(block_height) def get_json_for_block_hash(self, block_hash): """Get a JSON represntation of the specified block.""" return self.conn.getblock(block_hash) def get_tx_ids_at_height(self, block_height): """Get a list of transaction IDs contained in the specified block.""" block_hash = self.get_block_hash_at_height(block_height) tx_json = self.get_json_for_block_hash(block_hash) tx_ids = [] for tx_id in tx_json['tx']: tx_ids.append(tx_id) return tx_ids def get_raw_tx(self, tx_id): """Return transaction in raw format. If the requested transaction is the sole transaction of the genesis block, bitcoind's RPC interface will throw an error 'No information available about transaction (code -5)' so we preempt this by raising a custom error that callers should handle; iterating callers should just move onto the next tx. """ if tx_id == ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7af' 'deda33b'): raise IndexError else: return self.conn.getrawtransaction(tx_id) def get_decoded_tx(self, tx_id): """Gets the transaction in JSON format from the RPC interface.""" try: return self.conn.decoderawtransaction(self.get_raw_tx(tx_id)) except IndexError: #bitcoind won't generate this, but here's what it would look like genesis_json = { 'txid': ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2' '127b7afdeda33b'), 'version': 1, 'locktime': 0, 'vin': [{ "sequence":4294967295, 'coinbase': ('04ffff001d0104455468652054696d65732030332f4a6' '16e2f32303039204368616e63656c6c6f72206f6e2062' '72696e6b206f66207365636f6e64206261696c6f75742' '0666f722062616e6b73') }], 'vout': [ { 'value': 50.00000000, 'n': 0, 'scriptPubKey': { 'asm': ('04678afdb0fe5548271967f1a67130b7105cd6a828' 'e03909a67962e0ea1f61deb649f6bc3f4cef38c4f3' '5504e51ec112de5c384df7ba0b8d578a4c702b6bf1' '1d5f OP_CHECKSIG'), 'hex': ('4104678afdb0fe5548271967f1a67130b7105cd6a8' '28e03909a67962e0ea1f61deb649f6bc3f4cef38c4' 'f35504e51ec112de5c384df7ba0b8d578a4c702b6b' 'f11d5fac'), 'reqSigs': 1, 'type': 'pubkey', 'addresses': ['1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'] } } ] } return genesis_json
cht = os.popen('%s %s -create in=%s:%d:%s:%d outaddr=%s:"%s"' % (sidechain_tx_path, "-testnet" if is_testnet == 1 else "", args.sidechainClaimTx, 0, str(prev_out["value"]), 0x100000000 - int(prev_script[9]) - 1, str(prev_out["value"]), sidechain.getnewaddress())) tx_hex = cht.read().split("\n")[0] assert(cht.close() == None) tx_hex = sidechain.signrawtransaction(tx_hex, [{"txid": args.sidechainClaimTx, "vout": 0, "scriptPubKey": prev_out["scriptPubKey"]["hex"], "redeemScript": p2sh_res["redeemScript"], "nValue": prev_out["serValue"]}], [sidechain.dumpprivkey(args.sidechainAddress)]) if tx_hex["complete"] != True: print("Got incomplete transaction (signing failed to create spendable transaction):") print(tx_hex["hex"]) else: print("Submitting tx to mempool...") sidechain.sendrawtransaction(tx_hex["hex"]) print("Success!") elif args.command == "send-to-mainchain": p2sh_tx_test = bitcoin.decoderawtransaction(bitcoin.createrawtransaction([], {args.p2shMainAddress: 0.1}))["vout"][0]["scriptPubKey"] if p2sh_tx_test["type"] != "scripthash": print("You must use a P2SH address") exit(1) p2sh_hex = p2sh_tx_test["asm"].split(" ")[1] cht = os.popen('%s -create outscript=%s:"0x1850325348%s OP_DROP 0x20%s 0x14%s WITHDRAWPROOFVERIFY"' % (sidechain_tx_path, args.coinAmt, p2sh_hex, inverse_bitcoin_genesis_hash, secondScriptPubKeyHash)) res_tx = cht.read().split("\n")[0] assert(cht.close() == None) donation = sidechain.fundrawtransaction(res_tx)["fee"] if donation > 0: if donation < 550: # Probably dust donation = 550 cht = os.popen('%s -create outscript=%s:"0x1850325348%s OP_DROP 0x20%s 0x14%s WITHDRAWPROOFVERIFY" outscript=%s:"RETURN"' % (sidechain_tx_path, args.coinAmt, p2sh_hex, inverse_bitcoin_genesis_hash, secondScriptPubKeyHash, str(Decimal(donation) / Decimal(100000000)))) res_tx = cht.read().split("\n")[0]
class chainxdSSH(object): def __init__(self, host, port, username): self.host = host self.port = port self.username = username self.ssh = None self.channel = None self.fw_channel = None self.connected = False self.ssh_thread = None def __del__(self): self.disconnect() def remote_command(self, cmd): channel = None try: channel = self.ssh.get_transport().open_session() channel.exec_command(cmd) ret_code = channel.recv_exit_status() if ret_code == 0: for idx in range(1, 20): if channel.recv_ready(): break time.sleep(0.1) if not channel.recv_ready(): raise Exception('Data not ready') data = channel.recv(500) return data.decode().split('\n') else: for idx in range(1, 20): if channel.recv_stderr_ready(): break time.sleep(0.1) if channel.recv_stderr_ready(): data = channel.recv_stderr(500) error = data.decode() raise Exception(error) else: raise UnknownError('Unknown error executing remote command: ' + cmd) finally: if channel: channel.close() def connect(self): import paramiko self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) password = None pass_message = None while True: try: self.ssh.connect(self.host, port=int(self.port), username=self.username, password=password) self.connected = True if password: SshPassCache.save_password(self.username, self.host, password) break except PasswordRequiredException as e: # private key with password protection is used; ask user for password pass_message = "Enter passphrase for <b>private key</b> or password for %s" % \ (self.username + '@' + self.host) while True: password = SshPassCache.get_password(self.username, self.host, message=pass_message) if password: break chain_port = self.remote_port except AuthenticationException as e: # This exception will be raised in the following cases: # 1. a private key with password protectection is used but the user enters incorrect password # 2. a private key exists but user's public key is not added to the server's allowed keys # 3. normal login to server is performed but the user enters bad password # So, in the first case, the second query for password will ask for normal password to server, not # for a private key. WndUtils.errorMsg(message='Incorrect password, try again...') while True: password = SshPassCache.get_password(self.username, self.host, message=pass_message) if password: break except SSHException as e: if e.args and e.args[0] == 'No authentication methods available': while True: password = SshPassCache.get_password(self.username, self.host) if password: break else: raise except Exception as e: raise def open_tunnel(self, local_port, remote_ip, remote_port): if self.connected: ready_event = threading.Event() self.ssh_thread = SSHTunnelThread(local_port, remote_ip, remote_port, self.ssh.get_transport(), ready_event) self.ssh_thread.start() ready_event.wait(10) print('Started local port forwarding 127.0.0.1:%s -> %s:%s' % (str(local_port), remote_ip, str(remote_port))) else: raise Exception('SSH not connected') self.config = config # conn configurations are used from the first item in the list; if one fails, then next is taken if connection: # this parameter is used for testing specific connection self.connections = [connection] else: # get connection list orderd by priority of use self.connections = self.config.get_ordered_conn_list() self.cur_conn_index = 0 if self.connections: self.cur_conn_def = self.connections[self.cur_conn_index] else: self.cur_conn_def = None # below is the connection with which particular RPC call has started; if connection is switched because of # problems with some nodes, switching stops if we close round and return to the starting connection self.starting_conn = None self.ssh = None self.window = window self.active = False self.rpc_url = None self.proxy = None self.http_conn = None # HTTPConnection object passed to the AuthServiceProxy (for convinient connection reset) self.on_connection_begin_callback = on_connection_begin_callback self.on_connection_try_fail_callback = on_connection_try_fail_callback self.on_connection_finished_callback = on_connection_finished_callback self.last_error_message = None def apply_new_cfg(self): """ Called after any of connection config changed. """ # get connection list orderd by priority of use self.disconnect() self.connections = self.config.get_ordered_conn_list() self.cur_conn_index = 0 if not len(self.connections): raise Exception('There is no connections to chainx network enabled in the configuration.') self.cur_conn_def = self.connections[self.cur_conn_index] def disconnect(self): if self.active: if self.ssh: self.ssh.disconnect() del self.ssh self.ssh = None self.active = False def mark_call_begin(self): self.starting_conn = self.cur_conn_def def switch_to_next_config(self): """ If there is another chainxd config not used recently, switch to it. Called only when there was a problem with current connection config. :return: True if successfully switched ot False if there was no another config """ if self.cur_conn_def: self.config.conn_cfg_failure(self.cur_conn_def) # mark connection as defective if self.cur_conn_index < len(self.connections)-1: idx = self.cur_conn_index + 1 else: idx = 0 conn = self.connections[idx] if conn != self.starting_conn: self.disconnect() self.cur_conn_index = idx self.cur_conn_def = conn if not self.open(): return self.switch_to_next_config() else: return True else: return False def mark_cur_conn_cfg_is_ok(self): if self.cur_conn_def: self.config.conn_cfg_success(self.cur_conn_def) def open(self): """ Opens connection to chainx RPC. If it fails, then the next enabled conn config will be used, if any exists. :return: True if successfully connected, False if user cancelled the operation. If all of the attempts fail, then appropriate exception will be raised. """ try: if not self.cur_conn_def: raise Exception('There is no connections to chainx network enabled in the configuration.') while True: try: if self.open_internal(): break else: if not self.switch_to_next_config(): return False except UserCancelledConnection: return False except (socket.gaierror, ConnectionRefusedError, TimeoutError, socket.timeout) as e: # exceptions raised by not likely functioning chainxd node; try to switch to another node # if there is any in the config if not self.switch_to_next_config(): raise e # couldn't use another conn config, raise exception else: break except Exception as e: self.last_error_message = str(e) raise return True def open_internal(self): """ Try to establish connection to chainxd RPC daemon for current connection config. :return: True, if connection successfully establishes, False if user Cancels the operation (not always cancelling will be possible - only when user is prompted for a password). """ if not self.active: if self.cur_conn_def.use_ssh_tunnel: # RPC over SSH while True: self.ssh = ChainxdSSH(self.cur_conn_def.ssh_conn_cfg.host, self.cur_conn_def.ssh_conn_cfg.port, self.cur_conn_def.ssh_conn_cfg.username) try: logging.info('starting ssh.connect') self.ssh.connect() logging.info('finished ssh.connect') break except Exception as e: logging.error('error in ssh.connect') raise # configure SSH tunnel # get random local unprivileged port number to establish SSH tunnel success = False local_port = None for try_nr in range(1, 10): try: logging.info('beginning ssh.open_tunnel') local_port = randint(2000, 50000) self.ssh.open_tunnel(local_port, self.cur_conn_def.host, int(self.cur_conn_def.port)) success = True break except Exception as e: logging.error('error in ssh.open_tunnel loop') pass logging.info('finished ssh.open_tunnel loop') if not success: logging.error('finished ssh.open_tunnel loop with error') return False else: rpc_user = self.cur_conn_def.username rpc_password = self.cur_conn_def.password rpc_host = '127.0.0.1' # SSH tunnel on loopback rpc_port = local_port else: # direct RPC rpc_host = self.cur_conn_def.host rpc_port = self.cur_conn_def.port rpc_user = self.cur_conn_def.username rpc_password = self.cur_conn_def.password if self.cur_conn_def.use_ssl: self.rpc_url = 'https://' self.http_conn = httplib.HTTPSConnection(rpc_host, rpc_port, timeout=5, context=ssl._create_unverified_context()) else: self.rpc_url = 'http://' self.http_conn = httplib.HTTPConnection(rpc_host, rpc_port, timeout=5) logging.info('AuthServiceProxy begin') self.rpc_url += rpc_user + ':' + rpc_password + '@' + rpc_host + ':' + str(rpc_port) self.proxy = AuthServiceProxy(self.rpc_url, timeout=1000, connection=self.http_conn) logging.info('AuthServiceProxy end') try: if self.on_connection_begin_callback: try: # make the owner know, we are connecting logging.info('on_connection_begin_callback begin') self.on_connection_begin_callback() logging.info('on_connection_begin_callback end') except: pass # check the connection logging.info('starting http_conn.connect()') self.http_conn.connect() logging.info('finished http_conn.connect()') if self.on_connection_finished_callback: try: # make the owner know, we successfully finished connection self.on_connection_finished_callback() except: pass except: if self.on_connection_try_fail_callback: try: # make the owner know, connection attempt failed self.on_connection_try_fail_callback() except: pass raise finally: logging.info('http_conn.close()') self.http_conn.close() # timeout hase been initially set to 5 seconds to perform 'quick' connection test self.http_conn.timeout = 20 self.active = True return self.active def get_active_conn_description(self): if self.cur_conn_def: return self.cur_conn_def.get_description() else: return '???' @control_rpc_call def getblockcount(self): if self.open(): return self.proxy.getblockcount() else: raise Exception('Not connected') @control_rpc_call def getblockhash(self, block): if self.open(): return self.proxy.getblockhash(block) else: raise Exception('Not connected') @control_rpc_call def getinfo(self): if self.open(): return self.proxy.getinfo() else: raise Exception('Not connected') @control_rpc_call def issynchronized(self): if self.open(): # if connecting to HTTP(S) proxy do not check if chainxd daemon is synchronized if self.cur_conn_def.is_http_proxy(): return True else: syn = self.proxy.mnsync('status') return syn.get('IsSynced') else: raise Exception('Not connected') @control_rpc_call def mnsync(self): if self.open(): # if connecting to HTTP(S) proxy do not call this function - it will not be exposed if self.cur_conn_def.is_http_proxy(): return {} else: return self.proxy.mnsync('status') else: raise Exception('Not connected') @control_rpc_call def masternodebroadcast(self, what, hexto): if self.open(): return self.proxy.masternodebroadcast(what, hexto) else: raise Exception('Not connected') @control_rpc_call def get_masternodelist(self, *args): if self.open(): return self.proxy.masternodelist(*args) else: raise Exception('Not connected') @control_rpc_call def get_masternodeaddr(self): if self.open(): return self.proxy.masternodelist('addr') else: raise Exception('Not connected') @control_rpc_call def getaddressbalance(self, address): if self.open(): return self.proxy.getaddressbalance({'addresses': [address]}).get('balance') else: raise Exception('Not connected') @control_rpc_call def getaddressutxos(self, addresses): if self.open(): return self.proxy.getaddressutxos({'addresses': addresses}) else: raise Exception('Not connected') @control_rpc_call def getrawtransaction(self, txid, verbose): if self.open(): return self.proxy.getrawtransaction(txid, verbose) else: raise Exception('Not connected') @control_rpc_call def getblockhash(self, blockid): if self.open(): return self.proxy.getblockhash(blockid) else: raise Exception('Not connected') @control_rpc_call def getblockheader(self, blockhash): if self.open(): return self.proxy.getblockheader(blockhash) else: raise Exception('Not connected') @control_rpc_call def validateaddress(self, address): if self.open(): return self.proxy.validateaddress(address) else: raise Exception('Not connected') @control_rpc_call def decoderawtransaction(self, tx): if self.open(): return self.proxy.decoderawtransaction(tx) else: raise Exception('Not connected') @control_rpc_call def sendrawtransaction(self, tx): if self.open(): return self.proxy.sendrawtransaction(tx) else: raise Exception('Not connected')
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException import json import time # rpc_user and rpc_password are set in the bitcoin.conf file rpc_doge = AuthServiceProxy("http://%s:%[email protected]:22555"%('dogecoinrpcuser', 'dogecoinrpcpassword')) outset = set() cache = set() while True: mempool = rpc_doge.getrawmempool() for item in mempool: if item not in cache: cache.add(item) tx = rpc_doge.decoderawtransaction(rpc_doge.getrawtransaction(item)) for i in range(0,len(tx['vout']),1): try: out = (tx['vout'][i]['value']) outset.add(out) except: continue if len(str(int(round(sum(outset),-1)))) == 1: print(''+str(int(round(sum(outset,-1))))) elif len(str(int(round(sum(outset),-1)))) == 2: print(' /\\') print(' '+str(int(round(sum(outset,-1))))) print(' \\/') elif len(str(int(round(sum(outset),-1)))) == 3: print(' _') print(' / \\') print(' '+str(int(round(sum(outset,-1)))))
class ParsingBlock(): """ Parsing all transaction in all blocks """ def __init__(self, from_block=0, to_block=-1, db_host=None, db_name=None): self.from_block = from_block self.to_block = to_block self.coinid = coin_id self.qtum = AuthServiceProxy(qtum_server) self.client = ClientBalance(settings.balanceurl) self.db = TablePars(db_host, db_name) self.storge = ClientStorge(settings.storageurl) def block_hash_num(self, block=None): # get block hash try: if not block: block = self.from_block block_hash = self.qtum.getblockhash(block) return block_hash except: pass def get_transaction_in_block(self, block_hash=None): # get list transaction in block try: if not block_hash: block_hash = self.block_hash_num() block = self.qtum.getblock(block_hash) list_tx = block["tx"] return list_tx except: pass def get_raw_transaction(self, transaction_blocks=None): # get raw transaction try: if not transaction_blocks: transaction_blocks = self.get_transaction_in_block() transaction_list = [] for transaction_block in transaction_blocks: try: transaction_data = self.qtum.getrawtransaction( transaction_block) transaction_list += [transaction_data] except JSONRPCException: try: transaction_data = self.qtum.gettransaction( transaction_block) transaction_list += [transaction_data] except JSONRPCException: pass return transaction_list except: pass def transaction_in(self, vin): # parsing input try: list_address = [] for vin_i in vin: try: txid = vin_i["txid"] vout_num = vin_i["vout"] encoded_datas = self.get_raw_transaction([txid]) for i in encoded_datas: try: transaction_data = self.qtum.decoderawtransaction( i) vout_prev = transaction_data["vout"] vout_prev_data = vout_prev[vout_num] value_dec = vout_prev_data["value"] script_pub_key = vout_prev_data["scriptPubKey"] addresses = script_pub_key["addresses"] value_int = int(value_dec * (10**8)) for adr in addresses: list_address += [{adr: value_int}] except: pass except: pass return list_address except: pass def transaction_out(self, vout, txid): # parsing output try: list_address = [False] for vout_i in vout: try: script_pub_key = vout_i["scriptPubKey"] types = script_pub_key["type"] if types == "call" and self.coinid == coin_id: asm = script_pub_key["asm"] asm_split = asm.split() gasLimit = asm_split[1] gasPrice = asm_split[2] asm_data = asm_split[3] hex_address = asm_data[:8] smart_contr_address = asm_split[4] if smart_contr_address in address_smart_contract and hex_address == sign_transfer: data = asm_data[8:] signatures_list_type = ['address', 'uint'] try: decode = self.abi_to_params( data, signatures_list_type) new_decode = self.change_decode( signatures_list_type, decode) address_token = new_decode[0] value_int = new_decode[1] address_token = Qtum.hex_to_qtum_address( address_token, mainnet=mainnet_status) result = self.db.check_address( address=address_token, coinid=coin_id_put) result_keys = result.keys() if "address" in result_keys: update_data_1 = self.client.inc_balance( address_token, value_int, coin_id_put) self.storge.log_transaction( **{ "coinid": coin_id_put, "blocknumber": self.from_block, "blockhash": self.block_hash_num(), "vin": [], "vout": [{ address_token: value_int }], "txid": txid, "gasLimit": gasLimit, "gasPrice": gasPrice }) except Exception as e: # print(e) pass addresses = script_pub_key["addresses"] value = vout_i["value"] value_int = int(value * (10**8)) for adr in addresses: data = self.db.check_address(adr, self.coinid) result_keys = data.keys() if "address" in result_keys: update_data_1 = self.client.inc_balance( adr, value_int, coin_id) list_address[0] = True list_address += [{adr: value_int}] except: pass return list_address except: pass def decode_raw_transaction(self, encoded_datas=None): # decode raw transaction try: if not encoded_datas: encoded_datas = self.get_raw_transaction() for encoded_data in encoded_datas: try: transaction_data = self.qtum.decoderawtransaction( encoded_data) # vin = transaction_data["vin"] vout = transaction_data["vout"] txid = transaction_data["txid"] # self.transaction_in(vin) vout_res = self.transaction_out(vout, txid) if vout_res[0]: vin_res = self.transaction_in(transaction_data["vin"]) self.storge.log_transaction( **{ "coinid": self.coinid, "blocknumber": self.from_block, "blockhash": self.block_hash_num(), "vin": vin_res, "vout": vout_res[1:], "txid": txid }) except: pass except: pass def change_decode(self, signatures_list_type, decode): decode = list(decode) if "address" in signatures_list_type: index_adr = signatures_list_type.index("address") decode_index_adr = decode[index_adr] new_adr = decode_index_adr[2:] decode[index_adr] = new_adr if "string" in signatures_list_type: index_str = signatures_list_type.index("string") decode_index_str = decode[index_str] new_str = decode_index_str.decode() decode[index_str] = new_str return decode def abi_to_params(self, abi, output_types): decode_hex = codecs.getdecoder("hex_codec") encode_hex = codecs.getencoder("hex_codec") data = decode_hex(abi)[0] return decode_abi(output_types, data) def get_block_count(self): # Get count documents in db return self.qtum.getblockcount()
inputsList.append({ "txid": u["txid"], "vout": u["vout"], "address": changeAddress }) inputsWithScriptKeysList.append({ "txid": u["txid"], "vout": u["vout"], "scriptPubKey": u["scriptPubKey"] }) # createrawtransaction [{"txid":txid,"vout":n},...] {address:amount,...} print() logger.info("Creating tx hash going to address {}...".format(toAddresses)) createTxHex = rpcConnection.createrawtransaction(inputsList, toAddresses) createTxJson = rpcConnection.decoderawtransaction(createTxHex) if len(createTxHex.strip()) > 0: # pprint(rpcConnection.decodescript(createTxHex)); # pprint(rpcConnection.decoderawtransaction(createTxHex)); createTxID = createTxJson["txid"] logger.info( "TX was successfulling created. TxID is: {}".format(createTxID)) else: logger.error("Failed to create tx. Aborting.") exit() # signrawtransaction <hex string> [{"txid":txid,"vout":n,"scriptPubKey":hex,"redeemScript":hex},...] [<privatekey1>,...] [sighashtype="ALL"] print() logger.info("Signing tx...") signTxResult = rpcConnection.signrawtransaction(createTxHex, inputsWithScriptKeysList)
"redeemScript": p2sh_res["redeemScript"], "nValue": prev_out["serValue"] }], [sidechain.dumpprivkey(args.sidechainAddress)]) if tx_hex["complete"] != True: print( "Got incomplete transaction (signing failed to create spendable transaction):" ) print(tx_hex["hex"]) else: print("Submitting tx to mempool...") sidechain.sendrawtransaction(tx_hex["hex"]) print("Success!") elif args.command == "send-to-mainchain": p2sh_tx_test = bitcoin.decoderawtransaction( bitcoin.createrawtransaction( [], {args.p2shMainAddress: 0.1}))["vout"][0]["scriptPubKey"] if p2sh_tx_test["type"] != "scripthash": print("You must use a P2SH address") exit(1) p2sh_hex = p2sh_tx_test["asm"].split(" ")[1] cht = os.popen( '%s -create outscript=%s:"0x1850325348%s OP_DROP 0x20%s 0x14%s WITHDRAWPROOFVERIFY"' % (sidechain_tx_path, args.coinAmt, p2sh_hex, inverse_bitcoin_genesis_hash, secondScriptPubKeyHash)) res_tx = cht.read().split("\n")[0] assert (cht.close() == None) donation = sidechain.fundrawtransaction(res_tx)["fee"] if donation > 0:
class DaemonBTC: def __init__(self, url, timeout=90): self.rpc = AuthServiceProxy(url, timeout=timeout) def get_block(self, i): block = self.rpc.getblockhash(i) block_data = self.rpc.getblock(block) block_data['transactions'] = len(block_data['tx']) # Elasticsearch struggles with these as integers #block_data['chainwork_int'] = int(block_data['chainwork'], 16) block_data['difficulty'] = int(block_data['difficulty']) del (block_data['tx']) # Figure out how many coins moved value = 0 txs = self.get_block_transactions(i) # This is the data we need for value # txs[0]['vout'][0]['value'] for tx in txs: for vout in tx['vout']: if vout['scriptPubKey']['type'] == 'nonstandard': pass else: value = value + vout['value'] block_data['value'] = value return block_data def get_transaction(self, tx): rtx = self.rpc.getrawtransaction(tx) dtx = self.rpc.decoderawtransaction(rtx) return dtx def get_transactions(self, txs): rtx = self.rpc.batch_([["getrawtransaction", t] for t in txs]) dtx = self.rpc.batch_([["decoderawtransaction", t] for t in rtx]) return dtx def get_block_transactions(self, block): # The genesis block is special if block == 0: return [] blockhash = self.rpc.getblockhash(block) block_data = self.rpc.getblock(blockhash) transactions = [] rtx = self.rpc.batch_([["getrawtransaction", t] for t in block_data['tx']]) dtx = self.rpc.batch_([["decoderawtransaction", t] for t in rtx]) for tx in dtx: tx['height'] = block_data['height'] tx['block'] = block_data['hash'] tx['time'] = block_data['time'] # We can't use this data, let's get rid of it for i in tx['vin']: if 'scriptSig' in i: del (i['scriptSig']) for i in tx['vout']: if 'hex' in i['scriptPubKey']: del (i['scriptPubKey']['hex']) if 'asm' in i['scriptPubKey']: del (i['scriptPubKey']['asm']) transactions.append(tx) return transactions def get_block_transactions_bulk(self, block): "Return an iterable object for bulk transactions" transactions = self.get_block_transactions(block) tx = Transactions() for i in transactions: tx.add_transaction(i) return tx def get_blocks_bulk(self, blocks): rbh = self.rpc.batch_([["getblockhash", t] for t in blocks]) dbh = self.rpc.batch_([["get_block", t] for t in rbh]) output = [] for block_data in dbh: block_data['transactions'] = len(block_data['tx']) block_data['chainwork_int'] = int(block_data['chainwork'], 16) del (block_data['tx']) output.append(block_data) return output def get_max_block(self): return self.rpc.getblockcount()
class RpcClient: def __init__(self): self.rpc_ip, self.rpc_port, self.rpc_user, self.rpc_passwd = readRPCfile() rpc_url = "http://%s:%s@%s:%d" % (self.rpc_user, self.rpc_passwd, self.rpc_ip, self.rpc_port) try: self.conn = AuthServiceProxy(rpc_url, timeout=8) except JSONRPCException as e: err_msg = 'remote or local PIVX-cli running?' printException(getCallerName(), getFunctionName(), err_msg, e) except Exception as e: err_msg = 'remote or local PIVX-cli running?' printException(getCallerName(), getFunctionName(), err_msg, e) def decodeRawTransaction(self, rawTx): try: return self.conn.decoderawtransaction(rawTx) except Exception as e: err_msg = 'error in decodeRawTransaction' printException(getCallerName(), getFunctionName(), err_msg, e.args) def getAddressUtxos(self, addresses): try: return self.conn.getaddressutxos({'addresses': addresses}) except Exception as e: err_msg = "error in getAddressUtxos" if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) else: printException(getCallerName(), getFunctionName(), err_msg, e.args) raise e def getBlockCount(self): try: n = self.conn.getblockcount() return n except Exception as e: err_msg = 'remote or local PIVX-cli running?' if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) else: printException(getCallerName(), getFunctionName(), err_msg, e.args) def getBlockHash(self, blockNum): try: h = self.conn.getblockhash(blockNum) return h except Exception as e: err_msg = 'remote or local PIVX-cli running?' if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) else: printException(getCallerName(), getFunctionName(), err_msg, e.args) def getFeePerKb(self): try: # get transaction data from last 10 blocks feePerKb = float(self.conn.getfeeinfo(10)['feeperkb']) return (feePerKb if feePerKb > MINIMUM_FEE else MINIMUM_FEE) except Exception as e: err_msg = 'error in getFeePerKb' if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) else: printException(getCallerName(), getFunctionName(), err_msg, e.args) def getMNStatus(self, address): try: mnStatusList = self.conn.listmasternodes(address) if not mnStatusList: return None mnStatus = mnStatusList[0] mnStatus['mnCount'] = self.conn.getmasternodecount()['enabled'] return mnStatus except Exception as e: err_msg = "error in getMNStatus" if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) else: printException(getCallerName(), getFunctionName(), err_msg, e.args) def getProtocolVersion(self): try: prot_version = self.conn.getinfo().get('protocolversion') return int(prot_version) except Exception as e: err_msg = 'error in getProtocolVersion' printException(getCallerName(), getFunctionName(), err_msg, e.args) return DEFAULT_PROTOCOL_VERSION def getRawTransaction(self, txid): try: return self.conn.getrawtransaction(txid) except Exception as e: err_msg = "is Blockchain synced?" if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) return None def getStatus(self): status = False n = 0 try: n = self.conn.getblockcount() if n > 0: status = True except Exception as e: # If loading block index set lastBlock=1 if str(e.args[0]) == "Loading block index..." or str(e.args[0]) == "Verifying blocks...": printDbg(str(e.args[0])) n = 1 #else: #err_msg = "Error while contacting RPC server" #printException(getCallerName(), getFunctionName(), err_msg, e.args) return status, n def getStatusMess(self, status=None): if status == None: status = self.getStatus() if status: return "RPC status: CONNECTED!!!" else: return "RPC status: NOT CONNECTED. remote or local PIVX-cli running?" def isBlockchainSynced(self): try: return self.conn.mnsync('status').get("IsBlockchainSynced") except Exception as e: err_msg = "error in isBlockchainSynced" printException(getCallerName(), getFunctionName(), err_msg, e.args) return False def decodemasternodebroadcast(self, work): try: return self.conn.decodemasternodebroadcast(work.strip()) except Exception as e: err_msg = "error in decodemasternodebroadcast" printException(getCallerName(), getFunctionName(), err_msg, e.args) return "" def relaymasternodebroadcast(self, work): try: return self.conn.relaymasternodebroadcast(work.strip()) except Exception as e: err_msg = "error in relaymasternodebroadcast" printException(getCallerName(), getFunctionName(), err_msg, e.args) return "" def sendRawTransaction(self, tx_hex): try: tx_id = self.conn.sendrawtransaction(tx_hex) return tx_id except Exception as e: err_msg = 'error in rpcClient.sendRawTransaction' if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) else: printException(getCallerName(), getFunctionName(), err_msg, e.args) def verifyMessage(self, pivxaddress, signature, message): try: return self.conn.verifymessage(pivxaddress, signature, message) except Exception as e: err_msg = "error in verifyMessage" printException(getCallerName(), getFunctionName(), err_msg, e.args)
class FullNode: def __init__(self, conf_dir=None, rpcuser=None, rpcpassword=None, rpcport=None, rpchost='127.0.0.1', network="main"): if rpcport is None: rpcport = {'main':8332,'test':18332,'stn':9332, 'regtest':18332}[network] if conf_dir is None: if platform.system() == 'Darwin': conf_dir = os.path.expanduser('~/Library/Application Support/Bitcoin/') elif platform.system() == 'Windows': conf_dir = os.path.join(os.environ['APPDATA'], 'Bitcoin') else: conf_dir = os.path.expanduser('~/.bitcoin') if network == 'regtest': conf_dir = os.path.join(conf_dir, 'regtest') if network == 'test': conf_dir = os.path.join(conf_dir, 'testnet3') elif network == 'stn': conf_dir = os.path.join(conf_dir, 'stn') if rpcuser is None: cookie = os.path.join(conf_dir, '.cookie') with open(cookie) as f: rpcuserpass = f.read() # Use cookie if no rpcuser specified if rpcuser: uri = "http://{}:{}@{}:{}".format(rpcuser, rpcpassword, rpchost, rpcport) else: uri = "http://{}@{}:{}".format(rpcuserpass, rpchost, rpcport) self.network = network self.conf_dir = conf_dir self.uri = uri self.rpc = AuthServiceProxy(self.uri) self.rpcport = rpcport self.rpchost = rpchost self.network = network rpcnet = self.rpc.getblockchaininfo()['chain'] if rpcnet != network: raise ValueError("rpc server is on '%s' network, you passed '%s'" % (rpcnet, network)) def __getattr__(self, rpc_method): return RPCMethod(rpc_method, self) def __dir__(self): fulllist = [] fulllist.extend(bitsv_methods) fulllist.extend(standardmethods) fulllist.extend(self.__dict__.keys()) return fulllist def rpc_connect(self): return AuthServiceProxy(self.uri) def rpc_reconnect(self): self.rpc = AuthServiceProxy(self.uri) class Decorators: @classmethod def handle_broken_pipe(cls, f): @wraps(f) def reconnect_if_needed(self, *args, **kwargs): try: return f(self, *args, **kwargs) except BrokenPipeError: self.rpc_reconnect() # reconnect and try again return f(self, *args) return reconnect_if_needed @Decorators.handle_broken_pipe def get_balance(self, address): return sum(unspent.amount for unspent in self.get_unspents(address)) @Decorators.handle_broken_pipe def get_transactions(self, address): acct = self.rpc.getaccount(address) txs = self.rpc.listtransactions(acct) txids = (tx['txid'] for tx in txs) txids = list(txids) return txids @Decorators.handle_broken_pipe def get_transaction(self, txid): rawtx = self.rpc.getrawtransaction(txid) txjson = self.rpc.decoderawtransaction(rawtx) inputs = [] outputs = [] amount_in = 0 amount_out = 0 for vin in txjson['vin']: src = self.rpc.getrawtransaction(vin['txid'], True) src = self.rpc.decoderawtransaction(src['hex']) src = src['vout'][vin['vout']] addr = None if 'addresses' in src['scriptPubKey']: addr = src['scriptPubKey']['addresses'][0] amount = int((src['value'] * BSV_TO_SAT_MULTIPLIER).normalize()) amount_in += amount part = TxInput(addr, amount) inputs += [part] for vout in txjson['vout']: addr = None if 'addresses' in vout['scriptPubKey']: addr = vout['scriptPubKey']['addresses'][0] amount = int((vout['value'] * BSV_TO_SAT_MULTIPLIER).normalize()) amount_out += amount part = TxOutput(addr, amount, asm=vout['scriptPubKey']['asm']) outputs += [part] tx = Transaction(txjson['txid'], amount_in, amount_out) for part in inputs: tx.add_input(part) for part in outputs: tx.add_output(part) return tx @Decorators.handle_broken_pipe def get_unspents(self, address): unspents = self.rpc.listunspent(0, 9999999, [address], True) return [Unspent( amount=int((tx['amount'] * BSV_TO_SAT_MULTIPLIER).normalize()), confirmations=tx['confirmations'], script=tx['scriptPubKey'], txid=tx['txid'], txindex=tx['vout'] ) for tx in unspents] @Decorators.handle_broken_pipe def send_transaction(self, tx_hex): return self.rpc.sendrawtransaction(tx_hex, True)
class DashdInterface(WndUtils): def __init__(self, config, window, connection=None, on_connection_begin_callback=None, on_connection_try_fail_callback=None, on_connection_finished_callback=None): WndUtils.__init__(self, app_path=config.app_path) assert isinstance(config, AppConfig) self.config = config # conn configurations are used from the first item in the list; if one fails, then next is taken if connection: # this parameter is used for testing specific connection self.connections = [connection] else: # get connection list orderd by priority of use self.connections = self.config.get_ordered_conn_list() self.cur_conn_index = 0 if self.connections: self.cur_conn_def = self.connections[self.cur_conn_index] else: self.cur_conn_def = None # below is the connection with which particular RPC call has started; if connection is switched because of # problems with some nodes, switching stops if we close round and return to the starting connection self.starting_conn = None self.ssh = None self.window = window self.active = False self.rpc_url = None self.proxy = None self.http_conn = None # HTTPConnection object passed to the AuthServiceProxy (for convinient connection reset) self.on_connection_begin_callback = on_connection_begin_callback self.on_connection_try_fail_callback = on_connection_try_fail_callback self.on_connection_finished_callback = on_connection_finished_callback self.last_error_message = None def apply_new_cfg(self): """ Called after any of connection config changed. """ # get connection list orderd by priority of use self.disconnect() self.connections = self.config.get_ordered_conn_list() self.cur_conn_index = 0 if not len(self.connections): raise Exception( 'There is no connections to Dash network enabled in the configuration.' ) self.cur_conn_def = self.connections[self.cur_conn_index] def disconnect(self): if self.active: if self.ssh: self.ssh.disconnect() del self.ssh self.ssh = None self.active = False def mark_call_begin(self): self.starting_conn = self.cur_conn_def def switch_to_next_config(self): """ If there is another dashd config not used recently, switch to it. Called only when there was a problem with current connection config. :return: True if successfully switched ot False if there was no another config """ if self.cur_conn_def: self.config.conn_cfg_failure( self.cur_conn_def) # mark connection as defective if self.cur_conn_index < len(self.connections) - 1: idx = self.cur_conn_index + 1 else: idx = 0 conn = self.connections[idx] if conn != self.starting_conn: self.disconnect() self.cur_conn_index = idx self.cur_conn_def = conn if not self.open(): return self.switch_to_next_config() else: return True else: return False def mark_cur_conn_cfg_is_ok(self): if self.cur_conn_def: self.config.conn_cfg_success(self.cur_conn_def) def open(self): """ Opens connection to dash RPC. If it fails, then the next enabled conn config will be used, if any exists. :return: True if successfully connected, False if user cancelled the operation. If all of the attempts fail, then appropriate exception will be raised. """ try: if not self.cur_conn_def: raise Exception( 'There is no connections to Dash network enabled in the configuration.' ) while True: try: if self.open_internal(): break else: if not self.switch_to_next_config(): return False except UserCancelledConnection: return False except (socket.gaierror, ConnectionRefusedError, TimeoutError, socket.timeout) as e: # exceptions raised by not likely functioning dashd node; try to switch to another node # if there is any in the config if not self.switch_to_next_config(): raise e # couldn't use another conn config, raise exception else: break except Exception as e: self.last_error_message = str(e) raise return True def open_internal(self): """ Try to establish connection to dash RPC daemon for current connection config. :return: True, if connection successfully establishes, False if user Cancels the operation (not always cancelling will be possible - only when user is prompted for a password). """ if not self.active: if self.cur_conn_def.use_ssh_tunnel: # RPC over SSH while True: self.ssh = DashdSSH( self.cur_conn_def.ssh_conn_cfg.host, self.cur_conn_def.ssh_conn_cfg.port, self.cur_conn_def.ssh_conn_cfg.username) try: logging.info('starting ssh.connect') self.ssh.connect() logging.info('finished ssh.connect') break except Exception as e: logging.error('error in ssh.connect') raise # configure SSH tunnel # get random local unprivileged port number to establish SSH tunnel success = False local_port = None for try_nr in range(1, 10): try: logging.info('beginning ssh.open_tunnel') local_port = randint(2000, 50000) self.ssh.open_tunnel(local_port, self.cur_conn_def.host, int(self.cur_conn_def.port)) success = True break except Exception as e: logging.error('error in ssh.open_tunnel loop') pass logging.info('finished ssh.open_tunnel loop') if not success: logging.error('finished ssh.open_tunnel loop with error') return False else: rpc_user = self.cur_conn_def.username rpc_password = self.cur_conn_def.password rpc_host = '127.0.0.1' # SSH tunnel on loopback rpc_port = local_port else: # direct RPC rpc_host = self.cur_conn_def.host rpc_port = self.cur_conn_def.port rpc_user = self.cur_conn_def.username rpc_password = self.cur_conn_def.password if self.cur_conn_def.use_ssl: self.rpc_url = 'https://' self.http_conn = httplib.HTTPSConnection( rpc_host, rpc_port, timeout=5, context=ssl._create_unverified_context()) else: self.rpc_url = 'http://' self.http_conn = httplib.HTTPConnection(rpc_host, rpc_port, timeout=5) logging.info('AuthServiceProxy begin') self.rpc_url += rpc_user + ':' + rpc_password + '@' + rpc_host + ':' + str( rpc_port) self.proxy = AuthServiceProxy(self.rpc_url, timeout=1000, connection=self.http_conn) logging.info('AuthServiceProxy end') try: if self.on_connection_begin_callback: try: # make the owner know, we are connecting logging.info('on_connection_begin_callback begin') self.on_connection_begin_callback() logging.info('on_connection_begin_callback end') except: pass # check the connection logging.info('starting http_conn.connect()') self.http_conn.connect() logging.info('finished http_conn.connect()') if self.on_connection_finished_callback: try: # make the owner know, we successfully finished connection self.on_connection_finished_callback() except: pass except: if self.on_connection_try_fail_callback: try: # make the owner know, connection attempt failed self.on_connection_try_fail_callback() except: pass raise finally: logging.info('http_conn.close()') self.http_conn.close() # timeout hase been initially set to 5 seconds to perform 'quick' connection test self.http_conn.timeout = 20 self.active = True return self.active def get_active_conn_description(self): if self.cur_conn_def: return self.cur_conn_def.get_description() else: return '???' @control_rpc_call def getblockcount(self): if self.open(): return self.proxy.getblockcount() else: raise Exception('Not connected') @control_rpc_call def getblockhash(self, block): if self.open(): return self.proxy.getblockhash(block) else: raise Exception('Not connected') @control_rpc_call def getinfo(self): if self.open(): return self.proxy.getinfo() else: raise Exception('Not connected') @control_rpc_call def issynchronized(self): if self.open(): # if connecting to HTTP(S) proxy do not check if dash daemon is synchronized if self.cur_conn_def.is_http_proxy(): return True else: syn = self.proxy.mnsync('status') return syn.get('IsSynced') else: raise Exception('Not connected') @control_rpc_call def mnsync(self): if self.open(): # if connecting to HTTP(S) proxy do not call this function - it will not be exposed if self.cur_conn_def.is_http_proxy(): return {} else: return self.proxy.mnsync('status') else: raise Exception('Not connected') @control_rpc_call def masternodebroadcast(self, what, hexto): if self.open(): return self.proxy.masternodebroadcast(what, hexto) else: raise Exception('Not connected') @control_rpc_call def get_masternodelist(self, *args): if self.open(): return self.proxy.masternodelist(*args) else: raise Exception('Not connected') @control_rpc_call def get_masternodeaddr(self): if self.open(): return self.proxy.masternodelist('addr') else: raise Exception('Not connected') @control_rpc_call def getaddressbalance(self, address): if self.open(): return self.proxy.getaddressbalance({ 'addresses': [address] }).get('balance') else: raise Exception('Not connected') @control_rpc_call def getaddressutxos(self, addresses): if self.open(): return self.proxy.getaddressutxos({'addresses': addresses}) else: raise Exception('Not connected') @control_rpc_call def getrawtransaction(self, txid, verbose): if self.open(): return self.proxy.getrawtransaction(txid, verbose) else: raise Exception('Not connected') @control_rpc_call def getblockhash(self, blockid): if self.open(): return self.proxy.getblockhash(blockid) else: raise Exception('Not connected') @control_rpc_call def getblockheader(self, blockhash): if self.open(): return self.proxy.getblockheader(blockhash) else: raise Exception('Not connected') @control_rpc_call def validateaddress(self, address): if self.open(): return self.proxy.validateaddress(address) else: raise Exception('Not connected') @control_rpc_call def decoderawtransaction(self, tx): if self.open(): return self.proxy.decoderawtransaction(tx) else: raise Exception('Not connected') @control_rpc_call def sendrawtransaction(self, tx): if self.open(): return self.proxy.sendrawtransaction(tx) else: raise Exception('Not connected')
class RpcClient: def __init__(self): # Lock for threads self.lock = threading.Lock() self.rpc_ip, self.rpc_port, self.rpc_user, self.rpc_passwd = readRPCfile( ) rpc_url = "http://%s:%s@%s:%d" % (self.rpc_user, self.rpc_passwd, self.rpc_ip, self.rpc_port) try: self.lock.acquire() self.conn = AuthServiceProxy(rpc_url, timeout=120) except JSONRPCException as e: err_msg = 'remote or local PIVX-cli running?' printException(getCallerName(), getFunctionName(), err_msg, e) except Exception as e: err_msg = 'remote or local PIVX-cli running?' printException(getCallerName(), getFunctionName(), err_msg, e) finally: self.lock.release() def decodeRawTransaction(self, rawTx): try: self.lock.acquire() res = self.conn.decoderawtransaction(rawTx) except Exception as e: err_msg = 'error in decodeRawTransaction' printException(getCallerName(), getFunctionName(), err_msg, e.args) res = None finally: self.lock.release() return res def getAddressUtxos(self, addresses): try: self.lock.acquire() res = self.conn.getaddressutxos({'addresses': addresses}) except Exception as e: err_msg = "error in getAddressUtxos" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = None finally: self.lock.release() return res def getBlockCount(self): try: self.lock.acquire() n = self.conn.getblockcount() except Exception as e: err_msg = 'remote or local PIVX-cli running?' if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) n = 0 finally: self.lock.release() return n def getBlockHash(self, blockNum): try: self.lock.acquire() h = self.conn.getblockhash(blockNum) except Exception as e: err_msg = 'remote or local PIVX-cli running?' printException(getCallerName(), getFunctionName(), err_msg, e.args) h = None finally: self.lock.release() return h def getBudgetVotes(self, proposal): try: self.lock.acquire() votes = self.conn.getbudgetvotes(proposal) except Exception as e: err_msg = 'remote or local PIVX-cli running?' printException(getCallerName(), getFunctionName(), err_msg, e.args) votes = {} finally: self.lock.release() return votes def getFeePerKb(self): try: self.lock.acquire() # get transaction data from last 200 blocks feePerKb = float(self.conn.getfeeinfo(200)['feeperkb']) res = (feePerKb if feePerKb > MINIMUM_FEE else MINIMUM_FEE) except Exception as e: err_msg = 'error in getFeePerKb' printException(getCallerName(), getFunctionName(), err_msg, e.args) res = MINIMUM_FEE finally: self.lock.release() return res def getMNStatus(self, address): try: self.lock.acquire() mnStatusList = self.conn.listmasternodes(address) if not mnStatusList: return None mnStatus = mnStatusList[0] mnStatus['mnCount'] = self.conn.getmasternodecount()['enabled'] except Exception as e: err_msg = "error in getMNStatus" printException(getCallerName(), getFunctionName(), err_msg, e.args) mnStatus = None finally: self.lock.release() return mnStatus def getMasternodeCount(self): try: self.lock.acquire() ans = self.conn.getmasternodecount() except Exception as e: err_msg = "error in getMasternodeCount" printException(getCallerName(), getFunctionName(), err_msg, e.args) ans = None finally: self.lock.release() return ans def getMasternodes(self): mnList = {} mnList['last_update'] = now() score = [] try: self.lock.acquire() masternodes = self.conn.listmasternodes() except Exception as e: err_msg = "error in getMasternodes" printException(getCallerName(), getFunctionName(), err_msg, e.args) masternodes = [] finally: self.lock.release() for mn in masternodes: if mn.get('status') == 'ENABLED': if mn.get('lastpaid') == 0: mn['score'] = mn.get('activetime') else: lastpaid_ago = now() - mn.get('lastpaid') mn['score'] = min(lastpaid_ago, mn.get('activetime')) else: mn['score'] = 0 score.append(mn) score.sort(key=lambda x: x['score'], reverse=True) for mn in masternodes: mn['queue_pos'] = score.index(mn) mnList['masternodes'] = masternodes return mnList def getNextSuperBlock(self): try: self.lock.acquire() n = self.conn.getnextsuperblock() except Exception as e: err_msg = 'remote or local PIVX-cli running?' if str(e.args[0]) != "Request-sent": printException(getCallerName(), getFunctionName(), err_msg, e.args) n = 0 finally: self.lock.release() return n def getProposals(self): proposals = [] try: self.lock.acquire() data = self.conn.getbudgetinfo() except Exception as e: err_msg = "error getting proposals" printException(getCallerName(), getFunctionName(), err_msg, e.args) data = [] finally: self.lock.release() for p in data: new_proposal = Proposal(p.get('Name'), p.get('URL'), p.get('Hash'), p.get('FeeHash'), p.get('BlockStart'), p.get('BlockEnd'), p.get('TotalPaymentCount'), p.get('RemainingPaymentCount'), p.get('PaymentAddress'), p.get('Yeas'), p.get('Nays'), p.get('Abstains'), float(p.get('TotalPayment')), float(p.get('MonthlyPayment'))) proposals.append(new_proposal) return proposals def getProposalsProjection(self): proposals = [] try: self.lock.acquire() data = self.conn.getbudgetprojection() except Exception as e: err_msg = "error getting proposals projection" printException(getCallerName(), getFunctionName(), err_msg, e.args) data = [] finally: self.lock.release() for p in data: new_proposal = Proposal(p.get('Name'), p.get('URL'), p.get('Hash'), p.get('FeeHash'), p.get('BlockStart'), p.get('BlockEnd'), p.get('TotalPaymentCount'), p.get('RemainingPaymentCount'), p.get('PaymentAddress'), p.get('Yeas'), p.get('Nays'), p.get('Abstains'), p.get('TotalPayment'), p.get('MonthlyPayment')) new_proposal = {} new_proposal['Name'] = p.get('Name') new_proposal['Allotted'] = float(p.get("Alloted")) new_proposal['Votes'] = p.get('Yeas') - p.get('Nays') new_proposal['Total_Allotted'] = float(p.get('TotalBudgetAlloted')) proposals.append(new_proposal) return proposals def getProtocolVersion(self): try: self.lock.acquire() prot_version = self.conn.getinfo().get('protocolversion') res = int(prot_version) except Exception as e: err_msg = 'error in getProtocolVersion' printException(getCallerName(), getFunctionName(), err_msg, e.args) res = DEFAULT_PROTOCOL_VERSION finally: self.lock.release() return res def getRawTransaction(self, txid): try: self.lock.acquire() res = self.conn.getrawtransaction(txid) except Exception as e: err_msg = "is Blockchain synced?" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = None finally: self.lock.release() return res def getStatus(self): status = False statusMess = "Unable to connect to a PIVX RPC server.\n" statusMess += "Either the local PIVX wallet is not open, or the remote RPC server is not responding." n = 0 try: self.lock.acquire() n = self.conn.getblockcount() if n > 0: status = True statusMess = "Connected to PIVX RPC client" except Exception as e: # If loading block index set lastBlock=1 if str(e.args[0]) == "Loading block index..." or str( e.args[0]) == "Verifying blocks...": printDbg(str(e.args[0])) statusMess = "PIVX wallet is connected but still synchronizing / verifying blocks" n = 1 elif str(e.args[0]) != "Request-sent" and str( e.args[0]) != "10061": err_msg = "Error while contacting RPC server" printException(getCallerName(), getFunctionName(), err_msg, e.args) finally: self.lock.release() return status, statusMess, n def isBlockchainSynced(self): try: self.lock.acquire() res = self.conn.mnsync('status').get("IsBlockchainSynced") except Exception as e: if str(e.args[0]) != "Request-sent": err_msg = "error in isBlockchainSynced" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = False finally: self.lock.release() return res def mnBudgetRawVote(self, mn_tx_hash, mn_tx_index, proposal_hash, vote, time, vote_sig): try: self.lock.acquire() res = self.conn.mnbudgetrawvote(mn_tx_hash, mn_tx_index, proposal_hash, vote, time, vote_sig) except Exception as e: err_msg = "error in mnBudgetRawVote" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = None finally: self.lock.release() return res def decodemasternodebroadcast(self, work): try: self.lock.acquire() res = self.conn.decodemasternodebroadcast(work.strip()) except Exception as e: err_msg = "error in decodemasternodebroadcast" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = "" finally: self.lock.release() return res def relaymasternodebroadcast(self, work): try: self.lock.acquire() res = self.conn.relaymasternodebroadcast(work.strip()) except Exception as e: err_msg = "error in relaymasternodebroadcast" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = "" finally: self.lock.release() return res def sendRawTransaction(self, tx_hex, use_swiftx): try: self.lock.acquire() tx_id = self.conn.sendrawtransaction(tx_hex, True, bool(use_swiftx)) except Exception as e: err_msg = 'error in rpcClient.sendRawTransaction' printException(getCallerName(), getFunctionName(), err_msg, e.args) tx_id = None finally: self.lock.release() return tx_id def verifyMessage(self, pivxaddress, signature, message): try: self.lock.acquire() res = self.conn.verifymessage(pivxaddress, signature, message) except Exception as e: err_msg = "error in verifyMessage" printException(getCallerName(), getFunctionName(), err_msg, e.args) res = False finally: self.lock.release() return res
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException CSVFiles = "D:\BTC CSV" rpc_connection = AuthServiceProxy("http://%s:%[email protected]:8332"%("username", "password")) blockCount = rpc_connection.getblockcount() for i in range(100000, 100100):#blockCount): currentHash = rpc_connection.getblockhash(i) currentBlock = rpc_connection.getblock(currentHash) currentTime = currentBlock['time'] for transaction in currentBlock['tx']: txInfo = rpc_connection.getrawtransaction(transaction) txDecoded = rpc_connection.decoderawtransaction(txInfo) processed = [txDecoded['txid'], currentTime, txDecoded['weight']] for output in txDecoded['vout']: processed.append(str(output['value'])) print("Processed: " + str(processed)) print("Done with block " + str(i))
class CoinbaseTxData(object): def __init__(self): # rpc_user and rpc_password are set in the bitcoin.conf file rpc_user = "******" rpc_password = "******" self.rpc_connection = AuthServiceProxy("http://%s:%[email protected]:8332" % (rpc_user, rpc_password)) dir_path = os.path.dirname(os.path.realpath(__file__)) self.data_root_path = dir_path + '/EmpiricalData' if not os.path.exists(self.data_root_path): os.makedirs(self.data_root_path) def extract_coinbase_data(self, block_height): block_hash = self.rpc_connection.getblockhash(block_height) block = self.rpc_connection.getblock(block_hash) txs = block["tx"] if block_height > 0: raw_coinbase_tx = self.rpc_connection.getrawtransaction(txs[0]) coinbase_tx = self.rpc_connection.decoderawtransaction( raw_coinbase_tx) # coinbase_tx for genesis block is not retrievable via rpc elif block_height == 0: coinbase_tx = { "txid": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b", "version": 1, "locktime": 0, "vin": [{ "coinbase": "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73", "sequence": 4294967295 }], "vout": [{ "value": 50.00000000, "n": 0, "scriptPubKey": { "asm": "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG", "hex": "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac", "reqSigs": 1, "type": "pubkey", "addresses": ["1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"] } }] } return coinbase_tx["vin"][0]["coinbase"].decode("hex") def save_coinbase_tx_data(self): # Check if data has already been saved try: self.load_coinbase_tx_data() coinbase_data = self.df['coinbase_tx_data'].tolist() start = len(coinbase_data) # Could not load data except (IOError): start = 0 coinbase_data = [] max_block_height = self.rpc_connection.getblockcount() # for i in range(start, max_block_height): for i in range(start, start + 300): try: coinbase_data.append([self.extract_coinbase_data(i)]) except (JSONRPCException): print("Could not find coinbase transaction for block %i" % (i)) coinbase_data.append([None]) df = pd.DataFrame(coinbase_data) df.to_csv(self.data_root_path + "/coinbase_tx_data.txt") def load_coinbase_tx_data(self): self.df = pd.read_csv(self.data_root_path + "/coinbase_tx_data.txt") self.df.columns = ["block_height", "coinbase_tx_data"] def scrape_db_for_matches(self, pools): pool_strings = set(pools.values()) pool_counts = pools for pool_name in pools.keys(): pool_counts[pool_name] = 0 self.load_coinbase_tx_data() for string in self.df['coinbase_tx_data']: for target in pool_strings: try: match = re.search(target, string) if match: for pool_name in pools.keys(): if pools[pool_name] == target: pool_counts[pool_name] += 1 # No identifying string for pool except (TypeError): pass return pool_counts
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException alice_secret_atomic_swap = "thisIsASecretPassword123".encode('utf-8') print("Alice's secret is: ", alice_secret_atomic_swap) print("length of Alice's secret is: ", len(alice_secret_atomic_swap)) # rpc_user and rpc_password are set in the bitcoin.conf file rpc_connection = AuthServiceProxy("http://%s:%[email protected]:18332"%('abel', 'abel')) tx_alice_id = '394cb59fedc3f2a14aeb667416bb1844ebbd0ce5658db8d99c0f4ce7505143c4' raw = rpc_connection.getrawtransaction(tx_alice_id) print(raw) decode_tx = rpc_connection.decoderawtransaction(raw) print(decode_tx) # print(rpc_connection.getaccount('n4mNGWL1ycLk45xgvEEn8V2uKbnpa7wr93')) # # best_block_hash = rpc_connection.getbestblockhash() # print(rpc_connection.getblock(best_block_hash)) # # batch support : print timestamps of blocks 0 to 99 in 2 RPC round-trips: # commands = [ [ "getblockhash", height] for height in range(100) ] # block_hashes = rpc_connection.batch_(commands) # blocks = rpc_connection.batch_([ [ "getblock", h ] for h in block_hashes ]) # block_times = [ block["time"] for block in blocks ] # print(block_times) # block_hash: '0000000093d5f3e8f846c86f85a1a038fd58299d0cb2dc62594c8cb74072901c' # block_height: 1612350
def block_explorer(request): with open(r'static/keys/tokens.txt', 'r') as keys_File: keys = [line.rstrip('\n') for line in keys_File] # Get BlockBot Login Info rpc_user = keys[1] rpc_password = keys[2] block_Value = 0 # rpc_user and rpc_password are set in the bitcoin.conf file rpc_connection = AuthServiceProxy("http://%s:%[email protected]:8332" % (rpc_user, rpc_password)) request.method == 'GET' get_Block_Hash = (request.GET['get_Block']) # Pulling information from the Blockchain # get_Block_Hash = rpc_connection.getblockhash(block_Num) block_Hash = rpc_connection.getblock(get_Block_Hash) block_Num = block_Hash['height'] transactions = block_Hash['tx'] trans_Dict = {} trans_Dict['key'] = [] block_Value = 0 ts = block_Hash['time'] time_Convert = datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') coinbase = 'Coinbase' address_Dict = {} address_Dict['trx'] = [] for txid in transactions: #address_Dict['Transaction'] = [] temp_Address_Dict = {} temp_Address_Dict[txid] = [] tx_Value = 0 raw_Tx = rpc_connection.getrawtransaction(txid) decoded_Tx = rpc_connection.decoderawtransaction(raw_Tx) segwit_Test = raw_Tx[8:10] # If segwit transaction it adds the appropriate flag (True) to the transaction # ensuring it will be processed as a segwit transaction # Adds the transaction out values to the total block value if segwit_Test != '00': trans_Dict['key'].append(decoded_Tx) for output in decoded_Tx['vout']: tx_Value = tx_Value + output['value'] if output['value'] > 0: scriptPubKey_Data = (output['scriptPubKey']) script_Dict = {'scriptPubKey': scriptPubKey_Data} for script_Key, script_Value in script_Dict.items(): if script_Value['addresses']: for adds in script_Value['addresses']: #print (adds) temp_Address_Dict.get(txid).append(adds) block_Value = block_Value + tx_Value else: flag = True segwit_Tx = rpc_connection.decoderawtransaction(raw_Tx, flag) trans_Dict['key'].append(segwit_Tx) for output in segwit_Tx['vout']: tx_Value = tx_Value + output['value'] if output['value'] > 0: scriptPubKey_Data = (output['scriptPubKey']) script_Dict = {'scriptPubKey': scriptPubKey_Data} for script_Key, script_Value in script_Dict.items(): if script_Value['addresses']: for adds in script_Value['addresses']: #print (adds) temp_Address_Dict.get(txid).append(adds) block_Value = block_Value + tx_Value address_Dict.get('trx').append(temp_Address_Dict) print(address_Dict) return render( request, 'crypto/block_explorer.html', { 'block_Num': block_Num, 'block_Hash': block_Hash, 'block_Value': block_Value, 'trans_Dict': trans_Dict, 'time_Convert': time_Convert, 'address_Dict': address_Dict, 'coinbase': coinbase })
class LocalBlockchainRPCReader(BlockExplorerReader): rpc_connection = None #transaction_output_cache = None ''' deprecated ''' def __init__(self, database_connector = None): BlockExplorerReader.__init__(self, database_connector) #super self.rpc_connection = AuthServiceProxy( "http://%s:%s@%s:%s" % (self.config.RPC_USERNAME, self.config.RPC_PASSWORD, self.config.RPC_HOST, self.config.RPC_PORT)) def get_current_blockchain_block_height(self): return self.rpc_connection.getblockcount() #TODO: Error checking? - This should already be an integer. #Retreives a list of transactions at specified block height. Each tx # will be formatted as a BCI-like tuple per # get_bci_like_tuple_for_tx_id(). #param0: block_height: Height at which to get a list of txs for. #param1: use_tx_out_addr_cache_only (Optional): When looking up addresses # for previous transactions, ONLY refer to cache in SQLite database, # rather than slower option of using RPC interface. If set to True, # process will sleep until the data is available in the cache. Default: # False. def get_tx_list(self, block_height, use_tx_out_addr_cache_only = False): ids = self.get_tx_ids_at_height(block_height) txs = [] for tx_id in ids: bci_like_tuple = self.get_bci_like_tuple_for_tx_id( tx_id, use_tx_out_addr_cache_only) txs.append(bci_like_tuple) return txs #Checks if the specified transaction is the first time the specified address # has received funds. If it is, it will cache this for the specified # block height in the database so subsequent lookups will answer # correctly. IMPORTANT: This function assumes that that blocks are being # processed in a complete, monotonically-increasing fashion from the # genesis block. Otherwise, correct results not guaranteed! It is the # caller's responsibility to ensure that enough blocks have been # processed. def is_first_transaction_for_address(self, addr, tx_id, block_height, benchmarker = None): if self.database_connector.has_address_been_seen_cache_if_not(addr, block_height): dprint("Address %s at block height %d was already seen." % (addr, block_height)) return False else: dprint("Address %s at block height %d has no prior tx history." % (addr, block_height)) return True def get_block_hash_at_height(self, block_height): return self.rpc_connection.getblockhash(block_height) def get_tx_json_for_block_hash(self, block_hash): return self.rpc_connection.getblock(block_hash) def get_tx_ids_at_height(self, block_height): block_hash = self.get_block_hash_at_height(block_height) tx_json = self.get_tx_json_for_block_hash(block_hash) tx_ids = [] for tx_id in tx_json['tx']: tx_ids.append(tx_id) return tx_ids #Returns the transaction in raw format. If the requested transaction is # the sole transaction of the genesis block, bitcoind's RPC interface # will throw an error 'No information available about transaction # (code -5)' so we preempt this by raising a custom error that callers # should handle; iterating callers should just move onto the next tx. #throws: NoDataAvailableForGenesisBlockError def get_raw_tx(self, tx_id): if tx_id == ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7af' 'deda33b'): raise custom_errors.NoDataAvailableForGenesisBlockError() else: return self.rpc_connection.getrawtransaction(tx_id) #Gets a human-readable string of the transaction in JSON format. def get_decoded_tx(self, tx_id): try: return self.rpc_connection.decoderawtransaction( self.get_raw_tx(tx_id)) except custom_errors.NoDataAvailableForGenesisBlockError: #bitcoind won't generate this, but here's what it would look like genesis_json = { 'txid': ('4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2' '127b7afdeda33b'), 'version': 1, 'locktime': 0, 'vin': [{ "sequence":4294967295, 'coinbase': ('04ffff001d0104455468652054696d65732030332f4a6' '16e2f32303039204368616e63656c6c6f72206f6e2062' '72696e6b206f66207365636f6e64206261696c6f75742' '0666f722062616e6b73') }], 'vout': [ { 'value': 50.00000000, 'n': 0, 'scriptPubKey': { 'asm': ('04678afdb0fe5548271967f1a67130b7105cd6a828' 'e03909a67962e0ea1f61deb649f6bc3f4cef38c4f3' '5504e51ec112de5c384df7ba0b8d578a4c702b6bf1' '1d5f OP_CHECKSIG'), 'hex': ('4104678afdb0fe5548271967f1a67130b7105cd6a8' '28e03909a67962e0ea1f61deb649f6bc3f4cef38c4' 'f35504e51ec112de5c384df7ba0b8d578a4c702b6b' 'f11d5fac'), 'reqSigs': 1, 'type': 'pubkey', 'addresses': ['1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'] } } ] } return genesis_json #Converts required infromation from local bitcoind RPC into a format similar # to that returned by Blockchain.info's API. This helps to make the code # more agnostic as to the source of blockchain data. #Note: When an output address cannot be decoded, BCI excludes the "addr" # field from the JSON returned. Therefore, this function will do the same. # See: # https://blockchain.info/tx/cee16a9b222f636cd27d734da0a131cee5dd7a1d09cb5f14f4d1330b22aaa38e #Note: When a previous output address for an input cannot be decoded, BCI # excludes the "addr" field from the JSON returned. Therefore, this # function will do the same. See: # https://blockchain.info/tx/8ebe1df6ebf008f7ec42ccd022478c9afaec3ca0444322243b745aa2e317c272 #param0: tx_id: Specified transaction hash #param1: use_tx_out_addr_cache_only (Optional): When looking up addresses # for previous transactions, ONLY refer to cache in SQLite database, # rather than slower option of using RPC interface. If set to True, # process will sleep until the data is available in the cache. Default: # False. def get_bci_like_tuple_for_tx_id(self, tx_id, use_tx_out_addr_cache_only = False): json_tuple = {} json_tuple['hash'] = tx_id json_tuple['inputs'] = [] json_tuple['out'] = [] subscription = None if use_tx_out_addr_cache_only: subscription = data_subscription.TxOutputAddressCacheSubscriber( database = self.database_connector) tx_json = self.get_decoded_tx(tx_id) #populate input addresses for vin in tx_json['vin']: #look up address based on its previous transaction prev_txid = None if 'txid' in vin: prev_txid = vin['txid'] prev_vout = None if 'vout' in vin: prev_vout_num = vin['vout'] #yes, this RPC field is poorly named prev_out = {'n': prev_vout_num} try: if use_tx_out_addr_cache_only: #flag specifies that we will wait for cache to catch up # before continuing this operation. Process/thread # will sleep until then. subscription.next_tx_id_needed = prev_txid subscription.next_prev_tx_ouput_pos_needed = prev_vout_num dprint(("get_bci_like_tuple_for_tx_id: May sleep until " "tx output address is cached...")) subscription.do_sleep_until_producers_ready() address = self.get_output_address(prev_txid, prev_vout_num) prev_out['addr'] = address except custom_errors.PrevOutAddressCannotBeDecodedError: pass current_input = {'prev_out': prev_out} json_tuple['inputs'].append(current_input) else: #If there's no index specifying the txo from prev tx, there's # probably nothing to do here. Should only come up for # coinbase transactions. continue #populate output addresses for vout in tx_json['vout']: output_index = vout['n'] current_output = {'n':output_index} if 'scriptPubKey' in vout and 'addresses' in vout['scriptPubKey']: address = vout['scriptPubKey']['addresses'][0] current_output['addr'] = address json_tuple['out'].append(current_output) return json_tuple #Returns an ordered list of output addresses for the specified transaction # JSON as returned by the bitcoind RPC interface. If an address cannot be # decoded for one of the outputs, a value of None will be inserted # at that position in the list. #TODO: This does not properly handle multisig outputs that list multiple # addresses per output. See: # http://bitcoin.stackexchange.com/questions/4687/can-a-scriptpubkey-have-multiple-addresses # When support for this is added, make sure to add a test case. def get_output_addresses(self, tx_json): assert 'vout' in tx_json output_addresses = [] for vout in tx_json['vout']: assert 'scriptPubKey' in vout if 'addresses' in vout['scriptPubKey']: ouput_address = vout['scriptPubKey']['addresses'][0] output_addresses.append(ouput_address) else: output_addresses.append(None) return output_addresses #Raises: custom_errors.PrevOutAddressCannotBeDecoded #TODO: This does not properly handle multisig outputs that list multiple # addresses per output. def get_output_address(self, tx_id, output_index, tx_json = None): if USE_TX_OUTPUT_ADDR_CACHE_FIRST: addr = self.database_connector.get_output_address(tx_id, output_index) if addr is not None: return addr #not in cache, fall back to querying RPC interface if tx_json is None: tx_json = self.get_decoded_tx(tx_id) if 'vout' in tx_json and len(tx_json['vout']) > output_index and \ 'scriptPubKey' in tx_json['vout'][output_index]: if 'addresses' not in tx_json['vout'][output_index]['scriptPubKey']: raise custom_errors.PrevOutAddressCannotBeDecodedError else: return tx_json['vout'][output_index]['scriptPubKey'][ 'addresses'][0] else: msg = ("Missing element for vout in get_output_address() with tx " "id %s and output index %d") % (tx_id, output_index) logger.log_and_die(msg)
tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}], \ {change_address: change_amount, \ dummy_address: SATOSHI}) # Pattern to replace # Represents length of script, then OP_DUP OP_HASH160, # then length of hash, then 20 bytes of zeros, OP_EQUALVERIFY OP_CHECKSIG oldScriptPubKey = "1976a914000000000000000000000000000000000000000088ac" # Data to insert data = "Melons." if len(data) > 75: raise Exception("Can't contain this much data-use OP_PUSHDATA1") newScriptPubKey = "6a" + hexlify(chr(len(data))) + hexlify(data) #Append int of length to start newScriptPubKey = hexlify(chr(len(unhexlify(newScriptPubKey)))) + newScriptPubKey if oldScriptPubKey not in tx: raise Exception("Something broke!") tx = tx.replace(oldScriptPubKey, newScriptPubKey) rpc.decoderawtransaction(tx) tx = rpc.signrawtransaction(tx)['hex'] rpc.sendrawtransaction(tx)