def do_RPC(env, send_resp): _, args, cur = urlparse.parse_qs( env['QUERY_STRING']), env['PATH_INFO'].split( '/')[2:], sqc.dbpool.get().cursor() send_resp('200 OK', [('Content-Type', 'application/json')]) result = [] if args[0] == "getblockcount": result = json.dumps(sqc.cfg['block']) elif args[0] == "getinfo": result = json.dumps({ 'blocks': sqc.cfg['block'], 'difficulty': bits2diff(gethdr(sqc.cfg['block'], sqc.cfg, 'bits')) }) elif args[0] == "getdifficulty": result = json.dumps( bits2diff(gethdr(sqc.cfg['block'], sqc.cfg, 'bits'))) else: rpc = AuthServiceProxy(sqc.cfg['rpc']) if args[0] == "getblock": result = json.dumps(rpc.getblock(args[1]), cls=btcEncoder) elif args[0] == "getblockhash": result = json.dumps(rpc.getblockhash(int(args[1]))) elif args[0] == "getrawtransaction": result = json.dumps(rpc.getrawtransaction(args[1], 1), cls=btcEncoder) elif args[0] == "gettxout": result = json.dumps(rpcTxOut(cur, args[1], args[2])) elif args[0] == "getmempoolinfo": result = json.dumps(rpc.getmempoolinfo(), cls=btcEncoder) elif args[0] == "getrawmempool": result = json.dumps(rpc.getrawmempool(False), cls=btcEncoder) return result
def apiTx(cur, txhash, args): if 'output' in args: return txoAddr(cur, txhash, args[-1]) if 'addrs' in args: return txAddrs(cur, txhash) data = { 'txid':txhash } txh = txhash.decode('hex')[::-1] cur.execute("select id,hash,txdata,block_id div {0},ins,outs,txsize from trxs where id>=%s and hash=%s limit 1;".format(MAX_TX_BLK), (txh2id(txh), txh)) for tid,txh,txdata,blkid,ins,outs,txsize in cur: blob = getBlobData(txdata, ins, outs, txsize) if [i for i in ['rawtx','html'] if i in args]: return mkRawTx(cur, args, tid, blob, blkid) data['blockheight'] = blkid data['confirmations'] = sqc.cfg['block'] - blkid + 1 if blkid >= 0 else 0 data['version'],data['locktime'] = blob['hdr'][4],blob['hdr'][5] data['valueIn'],data['vin'] = apiInputs(cur, blkid, blob['ins']) data['valueOut'],data['vout'] = apiOutputs(cur, int(tid), blob['outs']) data['fees'] = round(data['valueIn'] - data['valueOut'],8) data['size'] = blob['size'] cur.execute("select hash from blocks where id=%s limit 1;", (blkid,)) for txhash2, in cur: data['blockhash'] = txhash2[::-1].encode('hex') data['time'] = data['blocktime'] = gethdr(blkid, sqc.cfg, 'time') if 'coinbase' in data['vin'][0]: del data['valueIn'] del data['fees'] data['isCoinBase'] = True return data return {}
def bciBlock(cur, blkhash): data = {'hash': blkhash, 'tx': []} cur.execute("select id from blocks where hash=%s limit 1;", (blkhash.decode('hex')[::-1], )) for blkid, in cur: data['height'] = data['block_index'] = int(blkid) hdr = gethdr(data['height'], sqc.cfg) data['ver'] = hdr['version'] data['time'] = hdr['time'] data['prev_block'] = hdr['previousblockhash'][::-1].encode('hex') data['mrkl_root'] = hdr['merkleroot'][::-1].encode('hex') data['nonce'] = hdr['nonce'] data['bits'] = hdr['bits'] data['main_chain'] = True cur.execute( "select hash from trxs where block_id>=%s and block_id<%s;", (blkid * MAX_TX_BLK, blkid * MAX_TX_BLK + MAX_TX_BLK)) for txhash, in cur: data['tx'].append(bciTx(cur, txhash[::-1].encode('hex'))) data['n_tx'] = len(data['tx']) data['fee'] = -(5000000000 >> (data['height'] / 210000)) for out in data['tx'][0]['out']: data['fee'] += out['value'] #log('DEBUG:'+str(data)) return data return None
def bciBlockWS(cur, block): # inconsistent websocket sub has different labels data = {'height': int(block), 'tx': [], 'txIndexes': []} cur.execute("select hash from blocks where id=%s limit 1;", (block, )) for data['hash'], in cur: data['hash'] = data['hash'][::-1].encode('hex') hdr = gethdr(data['height'], sqc.cfg) data['blockIndex'] = data['height'] data['version'] = hdr['version'] data['time'] = hdr['time'] data['prevBlockIndex'] = data['height'] - 1 data['mrklRoot'] = hdr['merkleroot'][::-1].encode('hex') data['nonce'] = hdr['nonce'] data['bits'] = hdr['bits'] cur.execute( "select hash from trxs where block_id>=%s and block_id<%s;", (block * MAX_TX_BLK, block * MAX_TX_BLK + MAX_TX_BLK)) for txhash, in cur: data['tx'].append(bciTx(cur, txhash[::-1].encode('hex'))) data['txIndexes'].append(txhash[::-1].encode('hex')) data['nTx'] = len(data['tx']) data['reward'] = 0 for out in data['tx'][0]['out']: data['reward'] += out['value'] data['totalBTCSent'] = 0 for tx in data['tx']: for out in tx['out']: data['totalBTCSent'] += out['value'] del data['tx'] return data return None
def apiHeader(cur, blk, args): if blk.isdigit(): cur.execute("select id,hash from blocks where id=%s limit 1;", (blk,)) else: cur.execute("select id,hash from blocks order by id desc limit 1;") for blkid,blkhash in cur: hdr = gethdr(int(blkid), sqc.cfg) if 'electrum' in args: return { 'block_height':int(blkid), 'version':hdr['version'], 'time':hdr['time'], 'bits':hdr['bits'], 'nonce':hdr['nonce'], 'merkle_root':hdr['merkleroot'][::-1].encode('hex'), 'prev_block_hash':hdr['previousblockhash'][::-1].encode('hex') } return { 'blockHash': blkhash[::-1].encode('hex') } return {}
def apiMerkle(cur, txhash): txh = txhash.decode('hex')[::-1] cur.execute("select block_id from trxs where id>=%s and hash=%s limit 1", (txh2id(txh), txh)) for blkid, in cur: blk,pos = divmod(int(blkid), MAX_TX_BLK) cur.execute("select hash from trxs where block_id>=%s and block_id<%s order by block_id;", (blk*MAX_TX_BLK, blk*MAX_TX_BLK+MAX_TX_BLK)) mkt = [ tx for tx, in cur ] mkb,t = [],pos while len(mkt) > 1: if len(mkt) % 2 == 1: mkt.append(mkt[-1]) mkb.append(mkt[t-1][::-1].encode('hex') if t % 2 == 1 else mkt[t+1][::-1].encode('hex')) mkt = [ sha256(sha256(mkt[i]+mkt[i+1]).digest()).digest() for i in range(0,len(mkt),2) ] t //= 2 if mkt[0] != gethdr(blk, sqc.cfg, 'merkleroot'): logts("Panic! Merkle tree failure, tx %s" % txhash ) return { "block_height": blk, "merkle": mkb, "pos": pos } return []
def bciTx(cur, txhash): data = {'hash': txhash} txh = txhash.decode('hex')[::-1] cur.execute( "select id,txdata,(block_id div {0}),ins,txsize from trxs where id>=%s and hash=%s limit 1;" .format(MAX_TX_BLK), (txh2id(txh), txh)) for txid, blob, blkid, ins, txsize in cur: hdr = getBlobHdr(int(blob), sqc.cfg) data['tx_index'] = int(txid) data['block_height'] = int(blkid) data['ver'], data['lock_time'] = hdr[4:6] # pylint:disable=unbalanced-tuple-unpacking data['inputs'], data['vin_sz'] = bciInputs(cur, int(blob), int(ins)) data['out'], data['vout_sz'] = bciOutputs(cur, int(txid), int(blob)) data['time'] = gethdr(data['block_height'], sqc.cfg, 'time') if int(blkid) > -1 else 0 data['size'] = txsize if txsize < 0xFF00 else (txsize & 0xFF) << 16 + hdr[3] return data return None
def apiBlock(cur, blkhash): data = { 'hash':blkhash, 'tx':[] } cur.execute("select id,chainwork,blksize from blocks where hash=%s limit 1;", (blkhash.decode('hex')[::-1],)) for blk,work,blksz in cur: data['height'] = int(blk) data['confirmations'] = sqc.cfg['block'] - data['height'] + 1 data.update(gethdr(data['height'], sqc.cfg)) data['previousblockhash'] = data['previousblockhash'][::-1].encode('hex') data['merkleroot'] = data['merkleroot'][::-1].encode('hex') data['difficulty'] = zF(int(bits2diff(data['bits'])*1e8)/1e8) data['bits'] = '%08x' % data['bits'] data['reward'] = zF(coin_reward(data['height'])) data['isMainChain'] = True data['size'] = blksz data['chainwork'] = work.encode('hex') data['poolInfo'] = {} cur.execute("select hash from trxs where block_id>=%s and block_id<%s;", (blk*MAX_TX_BLK, blk*MAX_TX_BLK+MAX_TX_BLK)) for txhash, in cur: data['tx'].append(txhash[::-1].encode('hex')) cur.execute("select hash from blocks where id=%s limit 1;", (data['height']+1,)) for txhash, in cur: data['nextblockhash'] = txhash[::-1].encode('hex') return data return {}
def addrUTXOs(cur, addr_id, addr, get): offset = int(get['from'][0]) if 'from' in get else 0 limit = min(int(get['to'][0])-offset, RESULT_ROW_LIMIT) if 'to' in get else RESULT_ROW_LIMIT data = [] cur.execute("select value,o.id,hash,block_id div {1} from trxs t left join outputs o on t.id=(o.id div {0}) and o.tx_id is null where addr_id=%s order by block_id limit %s,%s;".format(MAX_IO_TX,MAX_TX_BLK), (addr_id,limit,offset)) for value,out_id,txhash,blk in cur: data.append({ 'address':addr, 'txid':txhash[::-1].encode('hex'), 'vout':int(out_id)%MAX_IO_TX, 'amount':float(value)/1e8, 'confirmations':sqc.cfg['block']-int(blk)+1 if blk>=0 else 0, 'ts':gethdr(int(blk), sqc.cfg, 'time') if blk>=0 else 0 }) return data