def test_valid_block_hash(self): # None type self.assertFalse(Validators.is_valid_block_hash(None)) # Non-hex strings self.assertFalse(Validators.is_valid_block_hash('1234')) self.assertFalse(Validators.is_valid_block_hash('Appditto LLC')) self.assertFalse( Validators.is_valid_block_hash( 'ban_1bananobh5rat99qfgt1ptpieie5swmoth87thi74qgbfrij7dcgjiij94xr' )) # Too short self.assertFalse( Validators.is_valid_block_hash( '5E5B7C8F97BDA8B90FAA243050D99647F80C25EB4A07E7247114CBB129BDA18' )) # Too long self.assertFalse( Validators.is_valid_block_hash( '5E5B7C8F97BDA8B90FAA243050D99647F80C25EB4A07E7247114CBB129BDA1888' )) # Non-hex character self.assertFalse( Validators.is_valid_block_hash( '5E5B7C8F97BDA8B90FAA243050D99647F80C25EB4A07E7247114CBB129BDA18Z' )) # Valid self.assertTrue( Validators.is_valid_block_hash( '5E5B7C8F97BDA8B90FAA243050D99647F80C25EB4A07E7247114CBB129BDA188' ))
async def wallet_change_seed(self, request: web.Request, request_json: dict): """RPC wallet_change_seed""" if 'wallet' not in request_json or 'seed' not in request_json: return self.generic_error() elif not Validators.is_valid_block_hash(request_json['seed']): return self.json_response(data={'error': 'Invalid seed'}) # Retrieve wallet try: wallet = await Wallet.get_wallet(request_json['wallet']) except WalletNotFound: return self.json_response(data={'error': 'wallet not found'}) except WalletLocked: return self.json_response(data={'error': 'wallet locked'}) # Reset password if wallet.encrypted: await wallet.encrypt_wallet('') # Change key await wallet.change_seed(request_json['seed']) # Get newest account newest = await wallet.get_newest_account() return self.json_response( data={ "success": "", "last_restored_account": newest.address, "restored_count": newest.account_index + 1 })
async def wallet_create(self, request: web.Request, request_json: dict): """Route for creating new wallet""" if 'seed' in request_json: if not Validators.is_valid_block_hash(request_json['seed']): return self.json_response(data={'error': 'Invalid seed'}) new_seed = request_json['seed'] else: new_seed = RandomUtil.generate_seed() async with in_transaction() as conn: wallet = Wallet(seed=new_seed) await wallet.save(using_db=conn) await wallet.account_create(using_db=conn) return self.json_response(data={'wallet': str(wallet.id)})
async def receive(self, request: web.Request, request_json: dict): """RPC receive""" if 'wallet' not in request_json or 'account' not in request_json or 'block' not in request_json: return self.generic_error() elif not Validators.is_valid_address(request_json['account']): return self.json_response(data={'error': 'Invalid address'}) elif not Validators.is_valid_block_hash(request_json['block']): return self.json_response(data={'error': 'Invalid block'}) work = request_json['work'] if 'work' in request_json else None # Retrieve wallet try: wallet = await Wallet.get_wallet(request_json['wallet']) except WalletNotFound: return self.json_response(data={'error': 'wallet not found'}) except WalletLocked: return self.json_response(data={'error': 'wallet locked'}) # Retrieve account on wallet account = await wallet.get_account(request_json['account']) if account is None: return self.json_response(data={'error': 'Account not found'}) # Try to receive block wallet = WalletUtil(account, wallet) try: response = await wallet.receive(request_json['block'], work=work) except BlockNotFound: return self.json_response(data={'error': 'Block not found'}) except WorkFailed: return self.json_response( data={'error': 'Failed to generate work'}) except ProcessFailed: return self.json_response(data={'error': 'RPC Process failed'}) if response is None: return self.json_response( data={'error': 'Unable to receive block'}) return self.json_response(data=response)
async def work_generate(self, request: web.Request, request_json: dict): """Route for running work_generate""" if 'hash' in request_json: if not Validators.is_valid_block_hash(request_json['hash']): return self.json_response(data={'error': 'Invalid hash'}) else: return self.generic_error() difficulty = DifficultyModel.instance().send_difficulty if 'difficulty' in request_json: difficulty = request_json['difficulty'] elif 'subtype' in request_json and request_json['subtype'] == 'receive': difficulty = DifficultyModel.instance().receive_difficulty # Generate work work = await WorkClient.instance().work_generate( request_json['hash'], difficulty) if work is None: return self.json_response( data={'error': 'Failed to generate work'}) return self.json_response(data={'work': work})
async def wallet_add(self, request: web.Request, request_json: dict): """RPC wallet_add""" if 'wallet' not in request_json or 'key' not in request_json: return self.generic_error() elif not Validators.is_valid_block_hash(request_json['key']): return self.json_response(data={'error': 'Invalid key'}) # Retrieve wallet try: wallet = await Wallet.get_wallet(request_json['wallet']) except WalletNotFound: return self.json_response(data={'error': 'wallet not found'}) except WalletLocked: return self.json_response(data={'error': 'wallet locked'}) # Add account try: address = await wallet.adhoc_account_create(request_json['key']) except AccountAlreadyExists: return self.json_response(data={'error': 'account already exists'}) return self.json_response(data={'account': address})
def main(): loop = asyncio.new_event_loop() try: loop.run_until_complete(DBConfig().init_db()) if options.command == 'wallet_list': loop.run_until_complete(wallet_list()) elif options.command == 'wallet_create': if options.seed is not None: if not Validators.is_valid_block_hash(options.seed): print("Invalid seed specified") exit(1) loop.run_until_complete(wallet_create(options.seed)) elif options.command == 'wallet_change_seed': if options.seed is not None: if not Validators.is_valid_block_hash(options.seed): print("Invalid seed specified") exit(1) else: while True: try: options.seed = getpass.getpass(prompt='Enter new wallet seed:') if Validators.is_valid_block_hash(options.seed): break print("**Invalid seed**, should be a 64-character hex string") except KeyboardInterrupt: break exit(0) password = '' if options.encrypt: while True: try: password = getpass.getpass(prompt='Enter password to encrypt wallet:') if password.strip() == '': print("**Bad password** - cannot be blanke") break except KeyboardInterrupt: break exit(0) loop.run_until_complete(wallet_change_seed(options.wallet, options.seed, password)) elif options.command == 'wallet_view_seed': loop.run_until_complete(wallet_view_seed(options.wallet, options.password, options.all_keys)) elif options.command == 'account_create': if options.key is not None: if not Validators.is_valid_block_hash(options.key): print("Invalid Private Key") exit(0) elif options.key is not None and options.count is not None: print("You can only specify one: --key or --count") print("--count can only be used for deterministic accounts") elif options.count is not None: if options.count < 1: print("Count needs to be at least 1...") loop.run_until_complete(account_create(options.wallet, options.key, options.count)) elif options.command == 'wallet_destroy': loop.run_until_complete(wallet_destroy(options.wallet)) elif options.command == 'wallet_representative_get': loop.run_until_complete(wallet_representative_get(options.wallet)) elif options.command == 'wallet_representative_set': loop.run_until_complete(wallet_representative_set(options.wallet, options.representatives, update_existing=options.update_existing)) else: parser.print_help() except Exception as e: print(str(e)) raise e finally: loop.run_until_complete(Tortoise.close_connections()) loop.close()