async def validate_unconfirmed(request): start = time() post = await web_base.content_type_json_check(request) try: txhash = unhexlify(post['hash'].encode()) tx = tx_builder.get_tx(txhash=txhash) if tx is None or tx.height is not None: return web_base.error_res('You cannot validate tx. {}'.format(tx)) with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() new_tx = create_signed_tx_as_validator(tx=tx) assert tx is not new_tx, 'tx={}, new_tx={}'.format( id(tx), id(new_tx)) if not send_newtx(new_tx=new_tx, outer_cur=cur): raise Exception('Failed to send new tx.') db.commit() return web_base.json_res({ 'hash': hexlify(new_tx.hash).decode(), 'gas_amount': new_tx.gas_amount, 'gas_price': new_tx.gas_price, 'fee': new_tx.gas_amount * new_tx.gas_price, 'time': round(time() - start, 3) }) except Exception: return web_base.error_res()
async def conclude_contract(request): start = time() post = await web_base.content_type_json_check(request) try: start_hash = unhexlify(post['start_hash'].encode()) start_tx = tx_builder.get_tx(txhash=start_hash) if start_tx is None: return web_base.error_res('Not found start_tx {}'.format( post['start_hash'])) c_address, c_method, redeem_address, c_args = bjson.loads( start_tx.message) send_pairs = post.get('send_pairs', None) c_storage = post.get('storage', None) tx = create_conclude_tx(c_address=c_address, start_tx=start_tx, redeem_address=redeem_address, send_pairs=send_pairs, c_storage=c_storage) if not send_newtx(new_tx=tx): raise Exception('Failed to send new tx.') return web_base.json_res({ 'hash': hexlify(tx.hash).decode(), 'gas_amount': tx.gas_amount, 'gas_price': tx.gas_price, 'fee': tx.gas_amount * tx.gas_price, 'time': round(time() - start, 3) }) except Exception: return web_base.error_res()
async def watching_info(request): try: f_pickle = bool(request.query.get('pickle', False)) if not P.F_WATCH_CONTRACT: return web_base.error_res( errors='You need to enable watching option!') return web_base.json_res([{ 'hash': hexlify(txhash).decode(), 'type': tx.type, 'tx': b64encode(pickle.dumps(tx)).decode() if f_pickle else str(tx), 'time': time, 'c_address': c_address, 'related': related_list, 'args': tuple(map(decode, args)), } for txhash, (time, tx, related_list, c_address, *args) in watching_tx.items()]) except Exception as e: logging.error(e) return web_base.error_res()
async def issue_mint_tx(request): start = time() post = await web_base.content_type_json_check(request) with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() try: user_name = post.get('from', C.ANT_NAME_UNKNOWN) sender = read_name2user(user_name, cur) mint_id, tx = issue_mintcoin( name=post['name'], unit=post['unit'], digit=post.get('digit', 8), amount=post['amount'], cur=cur, description=post.get('description', None), image=post.get('image', None), additional_issue=post.get('additional_issue', True), sender=sender) if not send_newtx(new_tx=tx, outer_cur=cur): raise BaseException('Failed to send new tx.') db.commit() return web_base.json_res({ 'hash': hexlify(tx.hash).decode(), 'gas_amount': tx.gas_amount, 'gas_price': tx.gas_price, 'fee': tx.gas_amount * tx.gas_price, 'time': round(time() - start, 3), 'mint_id': mint_id }) except BaseException: return web_base.error_res()
async def get_mintcoin_info(request): try: mint_id = int(request.query.get('mint_id', 0)) m = get_mintcoin_object(coin_id=mint_id) return web_base.json_res(m.info) except Exception: return web_base.error_res()
async def send_many_user(request): start = time.time() if P.F_NOW_BOOTING: return web.Response(text='Now booting...', status=403) post = await web_base.content_type_json_check(request) with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() try: user_name = post.get('from', C.ANT_NAME_UNKNOWN) user_id = read_name2user(user_name, cur) send_pairs = list() for address, coin_id, amount in post['pairs']: send_pairs.append((address, int(coin_id), int(amount))) message = post.get('message', None) if message: msg_type = C.MSG_PLAIN msg_body = message.encode() else: msg_type = C.MSG_NONE msg_body = b'' new_tx = send_many(user_id, send_pairs, cur, msg_type=msg_type, msg_body=msg_body) if not send_newtx(new_tx=new_tx, outer_cur=cur): raise BaseException('Failed to send new tx.') db.commit() return web_base.json_res({ 'txhash': hexlify(new_tx.hash).decode(), 'time': round(time.time() - start, 3) }) except Exception as e: db.rollback() return web_base.error_res()
async def contract_transfer(request): start = time() post = await web_base.content_type_json_check(request) try: c_address = post['c_address'] c_method = post['c_method'] c_args = post['c_args'] send_pairs = post.get('send_pairs', None) sender_name = post.get('from', C.ANT_NAME_UNKNOWN) with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() sender = read_name2user(sender_name, cur) tx = create_contract_transfer_tx(c_address=c_address, cur=cur, c_method=c_method, c_args=c_args, send_pairs=send_pairs, sender=sender) if not send_newtx(new_tx=tx, outer_cur=cur): raise Exception('Failed to send new tx.') db.commit() return web_base.json_res({ 'hash': hexlify(tx.hash).decode(), 'gas_amount': tx.gas_amount, 'gas_price': tx.gas_price, 'fee': tx.gas_amount * tx.gas_price, 'time': round(time() - start, 3) }) except Exception: return web_base.error_res()
async def validator_edit(request): start = time() post = await web_base.content_type_json_check(request) c_address = post.get('c_address', None) new_address = post.get('new_address', None) flag = int(post.get('flag', F_NOP)) sig_diff = int(post.get('sig_diff', 0)) try: with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() if c_address is None: c_address = create_new_user_keypair(name=C.ANT_NAME_CONTRACT, cur=cur) tx = create_validator_edit_tx(c_address=c_address, new_address=new_address, flag=flag, sig_diff=sig_diff) if not send_newtx(new_tx=tx, outer_cur=cur): raise Exception('Failed to send new tx.') db.commit() return web_base.json_res({ 'hash': hexlify(tx.hash).decode(), 'gas_amount': tx.gas_amount, 'gas_price': tx.gas_price, 'fee': tx.gas_amount * tx.gas_price, 'time': round(time() - start, 3) }) except Exception: return web_base.error_res()
async def contract_create(request): post = await web_base.content_type_json_check(request) with closing(create_db(V.DB_ACCOUNT_PATH, f_on_memory=True)) as db: cur = db.cursor() try: # バイナリをピックルしオブジェクトに戻す c_bin = unhexlify(post['hex'].encode()) c_cs = { k.encode(errors='ignore'): v.encode(errors='ignore') for k, v in post.get('c_cs', dict()).items() } binary2contract(c_bin) # can compile? sender_name = post.get('account', C.ANT_NAME_UNKNOWN) sender_id = read_name2user(sender_name, cur) c_address, c_tx = create_contract_tx(c_bin, cur, sender_id, c_cs) if not send_newtx(new_tx=c_tx, outer_cur=cur): raise BaseException('Failed to send new tx.') db.commit() data = { 'txhash': hexlify(c_tx.hash).decode(), 'c_address': c_address, 'time': c_tx.time, 'fee': { 'gas_price': c_tx.gas_price, 'gas_amount': c_tx.gas_amount, 'total': c_tx.gas_price * c_tx.gas_amount } } return web_base.json_res(data) except BaseException: return web_base.error_res()
async def change_mint_tx(request): start = time() post = await web_base.content_type_json_check(request) with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() try: user_name = post.get('from', C.ANT_NAME_UNKNOWN) sender = read_name2user(user_name, cur) tx = change_mintcoin(mint_id=post['mint_id'], cur=cur, amount=post.get('amount'), description=post.get('description'), image=post.get('image'), setting=post.get('setting'), new_address=post.get('new_address'), sender=sender) if not send_newtx(new_tx=tx, outer_cur=cur): raise BaseException('Failed to send new tx.') db.commit() return web_base.json_res({ 'hash': hexlify(tx.hash).decode(), 'gas_amount': tx.gas_amount, 'gas_price': tx.gas_price, 'fee': tx.gas_amount * tx.gas_price, 'time': round(time() - start, 3) }) except BaseException: return web_base.error_res()
async def sign_raw_tx(request): post = await web_base.content_type_json_check(request) try: binary = unhexlify(post['hex'].encode()) other_pairs = dict() for sk in post.get('pairs', list()): pk = public_key(sk=sk) ck = get_address(pk=pk, prefix=V.BLOCK_PREFIX) other_pairs[ck] = (pk, sign(msg=binary, sk=sk, pk=pk)) tx = TX(binary=binary) for txhash, txindex in tx.inputs: input_tx = tx_builder.get_tx(txhash) address, coin_id, amount = input_tx.outputs[txindex] try: tx.signature.append( message2signature(raw=tx.b, address=address)) except BlockChainError: if address not in other_pairs: raise BlockChainError( 'Not found secret key "{}"'.format(address)) tx.signature.append(other_pairs[address]) data = tx.getinfo() return web_base.json_res({ 'hash': data['hash'], 'signature': data['signature'], 'hex': hexlify(tx.b).decode() }) except BaseException: return web_base.error_res()
async def change_mint_tx(request): post = await web_base.content_type_json_check(request) with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() try: user_name = post.get('account', C.ANT_NAME_UNKNOWN) sender = read_name2user(user_name, cur) mint, mintcoin_tx = change_mintcoin( mint_id=int(post['mint_id']), cur=cur, amount=int(post.get('amount', 0)), message=post.get('message', None), image=post.get('image', None), additional_issue=bool(post['additional_issue']) if 'additional_issue' in post else None, sender=sender) if not send_newtx(new_tx=mintcoin_tx, outer_cur=cur): raise BaseException('Failed to send new tx.') db.commit() data = mintcoin_tx.getinfo() return web_base.json_res({ 'txhash': data['hash'], 'mintcoin': mint.getinfo() }) except BaseException: return web_base.error_res()
async def validator_info(request): try: c_address = request.query['c_address'] f_confirmed = bool(request.query.get('confirmed', False)) best_block = builder.best_block if f_confirmed else None v = get_validator_object(c_address=c_address, best_block=best_block) return web_base.json_res(v.info) except Exception as e: logging.error(e) return web_base.error_res()
async def get_mintcoin_info(request): try: mint_id = int(request.query.get('mint_id', 0)) mint = get_mintcoin(mint_id) if mint: return web_base.json_res(mint.getinfo()) else: return web.Response(text='Not found mintcoin {}'.format(mint_id), status=400) except BaseException: return web_base.error_res()
async def validator_info(request): try: validator_cks, required_num = get_validator_info() return web_base.json_res({ 'im_a_validator': im_a_validator(), 'validator_address': V.CONTRACT_VALIDATOR_ADDRESS, 'validators': list(validator_cks), 'all': len(validator_cks), 'require': required_num }) except BaseException: return web_base.error_res()
async def broadcast_tx(request): post = await web_base.content_type_json_check(request) try: binary = unhexlify(post['hex'].encode()) new_tx = TX(binary=binary) new_tx.signature = [(pk, unhexlify(sign.encode())) for pk, sign in post['signature']] if not send_newtx(new_tx=new_tx): raise BaseException('Failed to send new tx.') return web_base.json_res({'txhash': hexlify(new_tx.hash).decode()}) except BaseException: return web_base.error_res()
async def get_mintcoin_history(request): try: mint_id = int(request.query.get('mint_id', 0)) data = list() for index, txhash, params, setting in builder.db.read_coins_iter(coin_id=mint_id): data.append({ 'index': index, 'txhash': hexlify(txhash).decode(), 'params': params, 'setting': setting}) return web_base.json_res(data) except BaseException: return web_base.error_res()
async def get_block_by_hash(request): try: blockhash = request.query.get('hash') blockhash = unhexlify(blockhash.encode()) block = builder.get_block(blockhash) if block is None: return web.Response(text="Not found block.", status=400) data = block.getinfo() data['size'] = block.getsize() data['hex'] = hexlify(block.b).decode() return web_base.json_res(data) except Exception as e: return web_base.error_res()
async def contract_storage(request): try: c_address = request.query['c_address'] f_confirmed = bool(request.query.get('confirmed', False)) best_block = builder.best_block if f_confirmed else None c = get_contract_object(c_address=c_address, best_block=best_block) if c is None: return web_base.json_res({}) storage = {decode(k): decode(v) for k, v in c.storage.items()} return web_base.json_res(storage) except Exception as e: logging.error(e) return web_base.error_res()
async def contract_storage(request): try: c_address = request.query['address'] cs = get_contract_storage(c_address) data = { 'storage': { k.decode(errors='ignore'): v.decode(errors='ignore') for k, v in cs.items() }, 'version': cs.version } return web_base.json_res(data) except BaseException: return web_base.error_res()
async def get_tx_by_hash(request): try: txhash = request.query.get('hash') txhash = unhexlify(txhash.encode()) tx = tx_builder.get_tx(txhash) if tx is None: return web.Response(text="Not found tx.", status=400) data = tx.getinfo() data['size'] = tx.getsize() data['hex'] = hexlify(tx.b).decode() data['signature'] = [(pubkey, hexlify(sign).decode()) for pubkey, sign in tx.signature] return web_base.json_res(data) except Exception as e: return web_base.error_res()
async def create_raw_tx(request): # [version=1] [type=TRANSFER] [time=now] [deadline=now+10800] # [inputs:list()] [outputs:list()] # [gas_price=MINIMUM_PRICE] [gas_amount=MINIMUM_AMOUNT] # [message_type=None] [message=None] post = await web_base.content_type_json_check(request) try: publish_time = post.get('time', int(time.time() - V.BLOCK_GENESIS_TIME)) deadline_time = post.get('deadline', publish_time + 10800) message_type = post.get('message_type', C.MSG_NONE) if message_type == C.MSG_NONE: message = b'' elif message_type == C.MSG_BYTE: message = unhexlify(post['message'].encode()) elif message_type == C.MSG_PLAIN: message = post['message'].encode() else: message_type = C.MSG_NONE message = b'' inputs = list() input_address = set() for txhash, txindex in post.get('inputs', list()): txhash = unhexlify(txhash.encode()) inputs.append((txhash, txindex)) input_tx = tx_builder.get_tx(txhash) address, coin_id, amount = input_tx.outputs[txindex] input_address.add(address) tx = TX( tx={ 'version': post.get('version', __chain_version__), 'type': post.get('type', C.TX_TRANSFER), 'time': publish_time, 'deadline': deadline_time, 'inputs': inputs, 'outputs': post.get('outputs', list()), 'gas_price': post.get('gas_price', V.COIN_MINIMUM_PRICE), 'gas_amount': 0, 'message_type': message_type, 'message': message }) tx_size = tx.getsize() + len(input_address) * 96 tx.gas_amount = post.get('gas_amount', tx_size) tx.serialize() return web_base.json_res({ 'tx': tx.getinfo(), 'hex': hexlify(tx.b).decode() }) except BaseException: return web_base.error_res()
async def chain_private_info(request): try: main_chain = [block.getinfo() for block in builder.best_chain] orphan_chain = [ block.getinfo() for block in builder.chain.values() if block not in builder.best_chain ] data = { 'main': main_chain, 'orphan': sorted(orphan_chain, key=lambda x: x['height']), 'root': builder.root_block.getinfo() } return web_base.json_res(data) except Exception: return web_base.error_res()
async def network_info(request): try: data = { 'p2p_ver': p2p_python.__version__, 'status': V.PC_OBJ.p2p.get_server_header(), 'networks': list()} for user in V.PC_OBJ.p2p.user: info = user.getinfo() del info['aeskey'], info['sock'] info['neers'] = ["{}:{}".format(*conn) for conn in info['neers']] info['host_port'] = "{}:{}".format(*info['host_port']) data['networks'].append(info) return web_base.json_res(data) except BaseException: return web_base.error_res()
async def validator_info(request): try: c_address = request.query['c_address'] f_confirmed = bool(request.query.get('confirmed', False)) stop_hash = request.query.get('stophash', None) if stop_hash: stop_hash = a2b_hex(stop_hash) best_block = builder.best_block if f_confirmed else None v = get_validator_object(c_address=c_address, best_block=best_block, stop_txhash=stop_hash) return web_base.json_res(v.info) except Exception as e: logging.error(e) return web_base.error_res()
async def contract_history(request): try: c_address = request.query['address'] data = list() for index, start_hash, finish_hash, height, on_memory in get_contract_history_iter( c_address): data.append({ 'index': index, 'height': height, 'on_memory': on_memory, 'start_hash': hexlify(start_hash).decode(), 'finish_hash': hexlify(finish_hash).decode() }) return web_base.json_res(data) except BaseException: return web_base.error_res()
async def get_keypair(request): try: with closing(create_db(V.DB_ACCOUNT_PATH)) as db: cur = db.cursor() address = request.query['address'] uuid, sk, pk = read_address2keypair(address, cur) return web_base.json_res({ 'uuid': uuid, 'address': address, 'private_key': sk, 'public_key': pk }) except BlockChainError as e: return web.Response(text=str(e), status=400) except Exception: return web_base.error_res()
async def get_contract_history(request): try: c_address = request.query['c_address'] data = list() # database for index, start_hash, finish_hash, (c_method, c_args, c_storage) in\ builder.db.read_contract_iter(c_address=c_address): data.append({ 'index': index, 'height': index // 0xffffffff, 'start_hash': hexlify(start_hash).decode(), 'finish_hash': hexlify(finish_hash).decode(), 'c_method': c_method, 'c_args': [decode(a) for a in c_args], 'c_storage': {decode(k): decode(v) for k, v in c_storage.items()} if c_storage else None }) # memory for block in reversed(builder.best_chain): for tx in block.txs: if tx.type != C.TX_CONCLUDE_CONTRACT: continue _c_address, start_hash, c_storage = bjson.loads(tx.message) if _c_address != c_address: continue start_tx = tx_builder.get_tx(txhash=start_hash) dummy, c_method, redeem_address, c_args = bjson.loads( start_tx.message) index = start_tx2index(start_tx=start_tx) data.append({ 'index': index, 'height': tx.height, 'start_hash': hexlify(start_hash).decode(), 'finish_hash': hexlify(tx.hash).decode(), 'c_method': c_method, 'c_args': [decode(a) for a in c_args], 'c_storage': {decode(k): decode(v) for k, v in c_storage.items()} if c_storage else None, # 'redeem_address': redeem_address, }) return web_base.json_res(data) except Exception as e: logging.error(e) return web_base.error_res()
async def source_compile(request): post = await web_base.content_type_json_check(request) try: if 'source' in post: source = str(post['source']) c_obj = string2contract(source, limit_global=False) elif 'path' in post: c_obj = path2contract(path=post['path'], limit_global=False) else: raise BaseException('You need set "source" or "path".') c_bin = contract2binary(c_obj) c_dis = contract2dis(c_obj) return web_base.json_res({ 'hex': hexlify(c_bin).decode(), 'dis': c_dis }) except BaseException: return web_base.error_res()
async def broadcast_tx(request): start = time() post = await web_base.content_type_json_check(request) try: binary = unhexlify(post['hex'].encode()) new_tx = TX(binary=binary) new_tx.signature = [(pk, unhexlify(_sign.encode())) for pk, _sign in post['signature']] if not send_newtx(new_tx=new_tx): raise BaseException('Failed to send new tx.') return web_base.json_res({ 'hash': hexlify(new_tx.hash).decode(), 'gas_amount': new_tx.gas_amount, 'gas_price': new_tx.gas_price, 'fee': new_tx.gas_amount * new_tx.gas_price, 'time': round(time() - start, 3) }) except BaseException: return web_base.error_res()