def execute(self, arguments): path = PromptUtils.get_arg(arguments, 0) if not path: print("Please specify a path") return if os.path.exists(path): print("File already exists") return if PromptData.Wallet: PromptData.close_wallet() try: passwd1 = prompt("[password]> ", is_password=True) passwd2 = prompt("[password again]> ", is_password=True) except KeyboardInterrupt: print("Wallet creation cancelled") return if passwd1 != passwd2 or len(passwd1) < 10: print( "Please provide matching passwords that are at least 10 characters long" ) return password_key = to_aes_key(passwd1) try: PromptData.Wallet = UserWallet.Create(path=path, password=password_key) contract = PromptData.Wallet.GetDefaultContract() key = PromptData.Wallet.GetKey(contract.PublicKeyHash) print("Wallet %s" % json.dumps(PromptData.Wallet.ToJson(), indent=4)) print("Pubkey %s" % key.PublicKey.encode_point(True)) except Exception as e: print("Exception creating wallet: %s" % e) PromptData.Wallet = None if os.path.isfile(path): try: os.remove(path) except Exception as e: print("Could not remove {}: {}".format(path, e)) return if PromptData.Wallet: asyncio.create_task( PromptData.Wallet.sync_wallet( start_block=PromptData.Wallet._current_height)) return PromptData.Wallet
def execute(self, arguments): if PromptData.Wallet: PromptData.close_wallet() path = PromptUtils.get_arg(arguments, 0) if not path: print("Please specify the required parameter") return if not os.path.exists(path): print("Wallet file not found") return try: passwd = prompt("[password]> ", is_password=True) except KeyboardInterrupt: print("Wallet opening cancelled") return password_key = to_aes_key(passwd) try: PromptData.Wallet = UserWallet.Open(path, password_key) print("Opened wallet at %s" % path) asyncio.create_task( PromptData.Wallet.sync_wallet( start_block=PromptData.Wallet._current_height)) return PromptData.Wallet except Exception as e: print("Could not open wallet: %s" % e)
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) != 1: print("Please specify the required parameter") return False nep2_key = arguments[0] passphrase = prompt("[key password] ", is_password=True) try: kp = KeyPair.PrivateKeyFromNEP2(nep2_key, passphrase) except ValueError as e: print(str(e)) return False try: key = wallet.CreateKey(kp) print(f"Imported key: {nep2_key}") pub_key = key.PublicKey.encode_point(True).decode('utf-8') print(f"Pubkey: {pub_key}") print(f"Address: {key.GetAddress()}") except Exception as e: # couldn't find an exact call that throws this but it was in the old code. Leaving it in for now. print(f"Key creation error: {str(e)}") return False
def do_token_transfer(token, wallet, from_address, to_address, amount, fee=Fixed8.Zero(), tx_attributes=None): if not tx_attributes: tx_attributes = [] p_fee = fee # because we cannot differentiate between a normal and multisig from_addr, and because we want to make # sending NEP5 tokens straight forward even when sending from multisig addresses, we include the script_hash # for verification by default to the transaction attributes. See PR/Issue: https://github.com/CityOfZion/neo-python/pull/491 from_script_hash = binascii.unhexlify( bytes(wallet.ToScriptHash(from_address).ToString2(), 'utf-8')) tx_attributes.append( TransactionAttribute(usage=TransactionAttributeUsage.Script, data=from_script_hash)) tx, fee, results = token.Transfer(wallet, from_address, to_address, amount, tx_attributes=tx_attributes) if tx is not None and results is not None and len(results) > 0: if results[0].GetBigInteger() == 1: print( "\n-----------------------------------------------------------" ) print("Will transfer %s %s from %s to %s" % (string_from_amount( token, amount), token.symbol, from_address, to_address)) print("Transfer fee: %s " % (fee.value / Fixed8.D)) print( "-------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Transfer Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Transfer cancelled") return False if not wallet.ValidatePassword(passwd): print("incorrect password") return False return InvokeContract(wallet, tx, comb_fee) print("could not transfer tokens") return False
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) != 1: print("Please specify the required parameter") return False address = arguments[0] try: passphrase = prompt("[key password] ", is_password=True) len_pass = len(passphrase) if len_pass < 10: print( f"Passphrase is too short, length: {len_pass}. Minimum length is 10" ) return False passphrase_confirm = prompt("[key password again] ", is_password=True) if passphrase != passphrase_confirm: print("Please provide matching passwords") return False keys = wallet.GetKeys() for key in keys: if key.GetAddress() == address: passwd = prompt("[wallet password]> ", is_password=True) if not wallet.ValidatePassword(passwd): return print("Incorrect password") print(f"NEP2: {key.ExportNEP2(passphrase)}") return True except KeyboardInterrupt: return print("Export cancelled") else: print(f"Could not find address {address} in wallet") return False
def GatherContractDetails(function_code): print("Please fill out the following contract details:") name = prompt("[Contract Name] > ") version = prompt("[Contract Version] > ") author = prompt("[Contract Author] > ") email = prompt("[Contract Email] > ") description = prompt("[Contract Description] > ") print("Creating smart contract....") print(" Name: %s " % name) print(" Version: %s" % version) print(" Author: %s " % author) print(" Email: %s " % email) print(" Description: %s " % description) print(" Needs Storage: %s " % function_code.HasStorage) print(" Needs Dynamic Invoke: %s " % function_code.HasDynamicInvoke) print(" Is Payable: %s " % function_code.IsPayable) print(json.dumps(function_code.ToJson(), indent=4)) return generate_deploy_script(function_code.Script, name, version, author, email, description, function_code.ContractProperties, function_code.ReturnTypeBigInteger, function_code.ParameterList)
def token_mint(token, wallet, to_addr, asset_attachments=[], fee=Fixed8.Zero(), invoke_attrs=None): if not invoke_attrs: invoke_attrs = [] p_fee = fee tx, fee, results = token.Mint(wallet, to_addr, asset_attachments, invoke_attrs=invoke_attrs) if tx is not None and results is not None: if len(results) > 0 and results[0] is not None: print( "\n-----------------------------------------------------------" ) print(f"[{token.symbol}] Will mint tokens to address: {to_addr}") print(f"Invocation Fee: {fee.value / Fixed8.D}") print( "-------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Invocation Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Token mint cancelled") return False if not wallet.ValidatePassword(passwd): print("incorrect password") return False return InvokeWithTokenVerificationScript(wallet, tx, token, comb_fee, invoke_attrs=invoke_attrs) print("Failed to mint tokens") return False
def start_output_config(): # temporarily mute stdout while we try to reconfigure our settings # components like `network` set at DEBUG level will spam through the console # making it impractical to configure output levels log_manager.mute_stdio() print("Select your desired configuration per component.") print("(1) DEBUG (2) INFO (3) ERROR (enter) keep current") print("") configurations = [] level_conversion = {1: logging.DEBUG, 2: logging.INFO, 3: logging.ERROR} # cycle through all known components for component, logger in log_manager.loggers.items(): component_name = component.replace(log_manager.root, "") current_level = logging.getLevelName(logger.handlers[0].level) line = "[{}] current: {} new: ".format(component_name, current_level) choice = None try: choice = int(prompt(line)) except ValueError: pass # invalid choice or enter == keep current if not choice: continue new_log_level = level_conversion.get(choice, logging.NOTSET) if new_log_level != logging.NOTSET: configurations.append((component_name, new_log_level)) # finally apply new settings if configurations: log_manager.config_stdio(configurations) # and re-enable stdio log_manager.unmute_stdio() # provide confirmation of new settings print("\nNew Output Levels:") new_settings = {} for component, logger in log_manager.loggers.items(): component_name = component.replace(log_manager.root, "") current_level = logging.getLevelName(logger.handlers[0].level) new_settings["%s" % component_name] = current_level print("[{}] new: {}".format(component_name, current_level)) return new_settings
def gather_signatures(context, itx, owners): do_exit = False print("\n\n*******************\n") print("Gather Signatures for Transaction:\n%s " % json.dumps(itx.ToJson(), indent=4)) print("Please use a client to sign the following: %s " % itx.GetHashData()) owner_index = 0 while not context.Completed and not do_exit: next_script = owners[owner_index] next_addr = scripthash_to_address(next_script.Data) try: print("\n*******************\n") owner_input = prompt('Public Key and Signature for %s> ' % next_addr) items = owner_input.split(' ') pubkey = ECDSA.decode_secp256r1(items[0]).G sig = items[1] contract = Contract.CreateSignatureContract(pubkey) if contract.Address == next_addr: context.Add(contract, 0, sig) print("Adding signature %s " % sig) owner_index += 1 else: print("Public Key does not match address %s " % next_addr) except ValueError: # expected from ECDSA if public key is invalid print(f"Invalid public key: {items[0]}") do_exit = True except EOFError: # Control-D pressed: quit do_exit = True except KeyboardInterrupt: # Control-C pressed: do nothing do_exit = True except Exception as e: print("Could not parse input %s " % e) if context.Completed: print("Signatures complete") itx.scripts = context.GetScripts() return True else: print("Could not finish signatures") return False
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) != 1: print("Please specify the required parameter") return False address = arguments[0] keys = wallet.GetKeys() for key in keys: if key.GetAddress() == address: try: passwd = prompt("[wallet password]> ", is_password=True) if not wallet.ValidatePassword(passwd): return print("Incorrect password") except KeyboardInterrupt: return print("Export cancelled.") print(f"WIF: {key.Export()}") return True else: print(f"Could not find address {address} in wallet") return False
def execute(self, arguments): wallet = PromptData.Wallet if not wallet: print("Please open a wallet") return False arguments, from_addr = PromptUtils.get_from_addr(arguments) arguments, priority_fee = PromptUtils.get_fee(arguments) arguments, invoke_attrs = PromptUtils.get_tx_attr_from_args(arguments) arguments, owners = PromptUtils.get_owners_from_params(arguments) arguments, return_type = PromptUtils.get_return_type_from_args( arguments) if len(arguments) < 1: print("Please specify the required parameters") return False hash_string = arguments[0] try: script_hash = UInt160.ParseString(hash_string) except Exception: # because UInt160 throws a generic exception. Should be fixed in the future print("Invalid script hash") return False p_fee = Fixed8.Zero() if priority_fee is not None: p_fee = priority_fee if p_fee is False: logger.debug("invalid fee") return False tx, fee, results, num_ops, engine_success = TestInvokeContract( wallet, arguments, from_addr=from_addr, invoke_attrs=invoke_attrs, owners=owners) if tx is not None and results is not None: if return_type is not None: try: parameterized_results = [ ContractParameter.AsParameterType( ContractParameterType.FromString(return_type), item).ToJson() for item in results ] except ValueError: logger.debug("invalid return type") return False else: parameterized_results = [ ContractParameter.ToParameter(item).ToJson() for item in results ] print( "\n-------------------------------------------------------------------------------------------------------------------------------------" ) print("Test invoke successful") print(f"Total operations: {num_ops}") print(f"Results {str(parameterized_results)}") print(f"Invoke TX GAS cost: {tx.Gas.value / Fixed8.D}") print(f"Invoke TX fee: {fee.value / Fixed8.D}") print( "-------------------------------------------------------------------------------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Invoke TX Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print("Enter your password to send this invocation to the network") tx.Attributes = invoke_attrs try: passwd = prompt("[password]> ", is_password=True) except KeyboardInterrupt: print("Invocation cancelled") return False if not wallet.ValidatePassword(passwd): return print("Incorrect password") return InvokeContract(wallet, tx, comb_fee, from_addr=from_addr, owners=owners) else: print("Error testing contract invoke") return False
def get_input_prompt(message): return prompt(message)
async def setup_and_start(loop): parser = argparse.ArgumentParser() # Network options group_network_container = parser.add_argument_group( title="Network options") group_network = group_network_container.add_mutually_exclusive_group( required=True) group_network.add_argument("--mainnet", action="store_true", default=False, help="Use MainNet") group_network.add_argument("--testnet", action="store_true", default=False, help="Use TestNet") group_network.add_argument("--privnet", action="store_true", default=False, help="Use PrivNet") group_network.add_argument("--coznet", action="store_true", default=False, help="Use CozNet") group_network.add_argument("--config", action="store", help="Use a specific config file") # Ports for RPC and REST api group_modes = parser.add_argument_group(title="Mode(s)") group_modes.add_argument( "--port-rpc", type=int, help="port to use for the json-rpc api (eg. 10332)") group_modes.add_argument("--port-rest", type=int, help="port to use for the rest api (eg. 80)") # Advanced logging setup group_logging = parser.add_argument_group(title="Logging options") group_logging.add_argument("--logfile", action="store", type=str, help="Logfile") group_logging.add_argument( "--syslog", action="store_true", help= "Log to syslog instead of to log file ('user' is the default facility)" ) group_logging.add_argument( "--syslog-local", action="store", type=int, choices=range(0, 7 + 1), metavar="[0-7]", help= "Log to a local syslog facility instead of 'user'. Value must be between 0 and 7 (e.g. 0 for 'local0')." ) group_logging.add_argument("--disable-stderr", action="store_true", help="Disable stderr logger") # Where to store stuff parser.add_argument("--datadir", action="store", help="Absolute path to use for database directories") # peers parser.add_argument("--minpeers", action="store", type=int, choices=range(1, 10 + 1), metavar="[1-10]", help="Min peers to use for P2P Joining") parser.add_argument("--maxpeers", action="store", type=int, choices=range(1, 10 + 1), metavar="[1-10]", help="Max peers to use for P2P Joining") # If a wallet should be opened parser.add_argument( "--wallet", action="store", help= "Open wallet. Will allow you to use methods that require an open wallet" ) # host parser.add_argument("--host", action="store", type=str, help="Hostname ( for example 127.0.0.1)", default="0.0.0.0") # Now parse args = parser.parse_args() # print(args) if not args.port_rpc and not args.port_rest: print("Error: specify at least one of --port-rpc / --port-rest") parser.print_help() raise SystemExit if args.port_rpc == args.port_rest: print("Error: --port-rpc and --port-rest cannot be the same") parser.print_help() raise SystemExit if args.logfile and (args.syslog or args.syslog_local): print("Error: Cannot only use logfile or syslog at once") parser.print_help() raise SystemExit # Setting the datadir must come before setting the network, else the wrong path is checked at net setup. if args.datadir: settings.set_data_dir(args.datadir) # Network configuration depending on command line arguments. By default, the testnet settings are already loaded. if args.config: settings.setup(args.config) elif args.mainnet: settings.setup_mainnet() elif args.testnet: settings.setup_testnet() elif args.privnet: settings.setup_privnet() elif args.coznet: settings.setup_coznet() def set_min_peers(num_peers) -> bool: try: settings.set_min_peers(num_peers) print("Minpeers set to ", num_peers) return True except ValueError: print("Please supply a positive integer for minpeers") return False def set_max_peers(num_peers) -> bool: try: settings.set_max_peers(num_peers) print("Maxpeers set to ", num_peers) return True except ValueError: print("Please supply a positive integer for maxpeers") return False minpeers = args.minpeers maxpeers = args.maxpeers if minpeers and maxpeers: if minpeers > maxpeers: print("minpeers setting cannot be bigger than maxpeers setting") return if not set_min_peers(minpeers) or not set_max_peers(maxpeers): return elif minpeers: if not set_min_peers(minpeers): return if minpeers > settings.CONNECTED_PEER_MAX: if not set_max_peers(minpeers): return elif maxpeers: if not set_max_peers(maxpeers): return if maxpeers < settings.CONNECTED_PEER_MIN: if not set_min_peers(maxpeers): return if args.syslog or args.syslog_local is not None: # Setup the syslog facility if args.syslog_local is not None: print("Logging to syslog local%s facility" % args.syslog_local) syslog_facility = SysLogHandler.LOG_LOCAL0 + args.syslog_local else: print("Logging to syslog user facility") syslog_facility = SysLogHandler.LOG_USER # Setup logzero to only use the syslog handler logzero.syslog(facility=syslog_facility) else: # Setup file logging if args.logfile: logfile = os.path.abspath(args.logfile) if args.disable_stderr: print("Logging to logfile: %s" % logfile) else: print("Logging to stderr and logfile: %s" % logfile) logzero.logfile(logfile, maxBytes=LOGFILE_MAX_BYTES, backupCount=LOGFILE_BACKUP_COUNT, disableStderrLogger=args.disable_stderr) else: print("Logging to stdout and stderr") if args.wallet: if not os.path.exists(args.wallet): print("Wallet file not found") return passwd = os.environ.get('NEO_PYTHON_JSONRPC_WALLET_PASSWORD', None) if not passwd: try: passwd = prompt("[password]> ", is_password=True) except KeyboardInterrupt: print("Wallet opening cancelled") return password_key = to_aes_key(passwd) try: wallet = UserWallet.Open(args.wallet, password_key) asyncio.create_task( wallet.sync_wallet(start_block=wallet._current_height)) except Exception as e: print(f"Could not open wallet {e}") return else: wallet = None # Disable logging smart contract events settings.set_log_smart_contract_events(False) # Write a PID file to easily quit the service write_pid_file() # Instantiate the blockchain and subscribe to notifications blockchain = Blockchain(getBlockchainDB()) Blockchain.RegisterBlockchain(blockchain) p2p = NetworkService() p2p_task = loop.create_task(p2p.start()) loop.create_task(custom_background_code()) NotificationDB.instance().start() if args.port_rpc: logger.info("Starting json-rpc api server on http://%s:%s" % (args.host, args.port_rpc)) try: rpc_class = load_class_from_path(settings.RPC_SERVER) except ValueError as err: logger.error(err) sys.exit() api_server_rpc = rpc_class(wallet=wallet) runner = web.AppRunner(api_server_rpc.app) await runner.setup() site = web.TCPSite(runner, args.host, args.port_rpc) await site.start() if args.port_rest: logger.info("Starting REST api server on http://%s:%s" % (args.host, args.port_rest)) try: rest_api = load_class_from_path(settings.REST_SERVER) except ValueError as err: logger.error(err) sys.exit() api_server_rest = rest_api() runner = web.AppRunner(api_server_rest.app) await runner.setup() site = web.TCPSite(runner, args.host, args.port_rpc) await site.start() return wallet
def ClaimGas(wallet, from_addr_str=None, to_addr_str=None): """ Args: wallet: from_addr_str: Returns: (claim transaction, relayed status) if successful: (tx, True) if unsuccessful: (None, False) """ if not wallet: print("Please open a wallet") return None, False unclaimed_coins = wallet.GetUnclaimedCoins() unclaimed_count = len(unclaimed_coins) if unclaimed_count == 0: print("No claims to process") return None, False unclaimed_coin_refs = [coin.Reference for coin in unclaimed_coins] available_bonus = Blockchain.Default().CalculateBonusIgnoreClaimed( unclaimed_coin_refs) if available_bonus == Fixed8.Zero(): print("No gas to claim") return None, False claim_tx = ClaimTransaction() claim_tx.Claims = unclaimed_coin_refs claim_tx.Attributes = [] claim_tx.inputs = [] script_hash = wallet.GetChangeAddress() # the following can be used to claim gas that is in an imported contract_addr # example, wallet claim --from-addr={smart contract addr} if from_addr_str: script_hash = None script_hash = PromptUtils.lookup_addr_str(wallet, from_addr_str) if script_hash is None: logger.debug("invalid source address") return None, False standard_contract = wallet.GetStandardAddress() claim_tx.Attributes = [ TransactionAttribute(usage=TransactionAttributeUsage.Script, data=standard_contract.Data) ] if to_addr_str: script_hash = None script_hash = PromptUtils.lookup_addr_str(wallet, to_addr_str) if script_hash is None: logger.debug("invalid destination address") return None, False claim_tx.outputs = [ TransactionOutput(AssetId=Blockchain.SystemCoin().Hash, Value=available_bonus, script_hash=script_hash) ] context = ContractParametersContext(claim_tx) wallet.Sign(context) print("\n---------------------------------------------------------------") print(f"Will make claim for {available_bonus.ToString()} GAS") print( "------------------------------------------------------------------\n") print("Enter your password to complete this claim") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Claim transaction cancelled") return None, False if not wallet.ValidatePassword(passwd): print("Incorrect password") return None, False if context.Completed: claim_tx.scripts = context.GetScripts() print("claim tx: %s " % json.dumps(claim_tx.ToJson(), indent=4)) nodemgr = NodeManager() relayed = nodemgr.relay(claim_tx) if relayed: print("Relayed Tx: %s " % claim_tx.Hash.ToString()) wallet.SaveTransaction(claim_tx) else: print("Could not relay tx %s " % claim_tx.Hash.ToString()) return claim_tx, relayed else: print("could not sign tx") return None, False
def __init__(self, db, skip_version_check=False, skip_header_check=False): self._db = db self._header_index = [] self._header_index.append( Blockchain.GenesisBlock().Header.Hash.ToBytes()) self.TXProcessed = 0 version = self._db.get(DBPrefix.SYS_Version) if skip_version_check: self._db.write(DBPrefix.SYS_Version, self._sysversion) version = self._sysversion if version == self._sysversion: # or in the future, if version doesn't equal the current version... ba = bytearray(self._db.get(DBPrefix.SYS_CurrentBlock, 0)) self._current_block_height = int.from_bytes(ba[-4:], 'little') if not skip_header_check: ba = bytearray(self._db.get(DBPrefix.SYS_CurrentHeader, 0)) current_header_height = int.from_bytes(ba[-4:], 'little') current_header_hash = bytes(ba[:64].decode('utf-8'), encoding='utf-8') hashes = [] try: with self._db.openIter( DBProperties(DBPrefix.IX_HeaderHashList)) as it: for key, value in it: ms = StreamManager.GetStream(value) reader = BinaryReader(ms) hlist = reader.Read2000256List() key = int.from_bytes(key[-4:], 'little') hashes.append({'k': key, 'v': hlist}) StreamManager.ReleaseStream(ms) except Exception as e: logger.info("Could not get stored header hash list: %s " % e) if len(hashes): hashes.sort(key=lambda x: x['k']) genstr = Blockchain.GenesisBlock().Hash.ToBytes() for hlist in hashes: for hash in hlist['v']: if hash != genstr: self._header_index.append(hash) self._stored_header_count += 1 if self._stored_header_count == 0: logger.info( "Current stored headers empty, re-creating from stored blocks..." ) headers = [] logger.info('Recreate headers') with self._db.openIter(DBProperties( DBPrefix.DATA_Block)) as it: for key, value in it: dbhash = bytearray(value)[8:] headers.append( Header.FromTrimmedData( binascii.unhexlify(dbhash), 0)) headers.sort(key=lambda h: h.Index) for h in headers: if h.Index > 0: self._header_index.append(h.Hash.ToBytes()) if len(headers): self.OnAddHeader(headers[-1]) elif current_header_height > self._stored_header_count: try: hash = current_header_hash targethash = self._header_index[-1] newhashes = [] while hash != targethash: header = self.GetHeader(hash) newhashes.insert(0, header) hash = header.PrevHash.ToBytes() self.AddHeaders(newhashes) except Exception as e: pass elif version is None: wait_for(self.Persist(Blockchain.GenesisBlock())) self._db.write(DBPrefix.SYS_Version, self._sysversion) else: logger.error("\n\n") logger.warning("Database schema has changed from %s to %s.\n" % (version, self._sysversion)) logger.warning( "You must either resync from scratch, or use the np-bootstrap command to bootstrap the chain." ) res = prompt( "Type 'continue' to erase your current database and sync from new. Otherwise this program will exit:\n> " ) if res == 'continue': with self._db.getBatch() as wb: with self._db.openIter( DBProperties(include_value=False)) as it: for key in it: wb.delete(key) wait_for(self.Persist(Blockchain.GenesisBlock())) self._db.write(DBPrefix.SYS_Version, self._sysversion) else: raise Exception("Database schema changed")
def SplitUnspentCoin(wallet, asset_id, from_addr, index, divisions, fee=Fixed8.Zero()): """ Split unspent asset vins into several vouts Args: wallet (neo.Wallet): wallet to show unspent coins from. asset_id (UInt256): a bytearray (len 32) representing an asset on the blockchain. from_addr (UInt160): a bytearray (len 20) representing an address. index (int): index of the unspent vin to split divisions (int): number of vouts to create fee (Fixed8): A fee to be attached to the Transaction for network processing purposes. Returns: neo.Core.TX.Transaction.ContractTransaction: contract transaction created """ if wallet is None: print("Please open a wallet.") return unspent_items = wallet.FindUnspentCoinsByAsset(asset_id, from_addr=from_addr) if not unspent_items: print(f"No unspent assets matching the arguments.") return if index < len(unspent_items): unspent_item = unspent_items[index] else: print(f"unspent-items: {unspent_items}") print( f"Could not find unspent item for asset {asset_id} with index {index}" ) return outputs = split_to_vouts(asset_id, from_addr, unspent_item.Output.Value, divisions) # subtract a fee from the first vout if outputs[0].Value > fee: outputs[0].Value -= fee else: print("Fee could not be subtracted from outputs.") return contract_tx = ContractTransaction(outputs=outputs, inputs=[unspent_item.Reference]) ctx = ContractParametersContext(contract_tx) wallet.Sign(ctx) print("Splitting: %s " % json.dumps(contract_tx.ToJson(), indent=4)) try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Splitting cancelled") return if not wallet.ValidatePassword(passwd): print("incorrect password") return if ctx.Completed: contract_tx.scripts = ctx.GetScripts() nodemgr = NodeManager() # this blocks, consider moving this wallet function to async instead relayed = nodemgr.relay(contract_tx) if relayed: wallet.SaveTransaction(contract_tx) print("Relayed Tx: %s " % contract_tx.Hash.ToString()) return contract_tx else: print("Could not relay tx %s " % contract_tx.Hash.ToString())
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) < 4: print("Please specify the required parameters") return False arguments, priority_fee = PromptUtils.get_fee(arguments) token_str = arguments[0] from_addr = arguments[1] to_addr = arguments[2] try: amount = float(arguments[3]) except ValueError: print(f"{arguments[3]} is not a valid amount") return False p_fee = Fixed8.Zero() if priority_fee is not None: p_fee = priority_fee if p_fee is False: logger.debug("invalid fee") return False try: token = _validate_nep5_args(wallet, token_str, from_addr, to_addr, amount) except ValueError as e: print(str(e)) return False decimal_amount = amount_from_string(token, amount) tx, fee, results = token.Approve(wallet, from_addr, to_addr, decimal_amount) if tx is not None and results is not None: if results[0].GetBigInteger() == 1: print( "\n-----------------------------------------------------------" ) print( f"Approve allowance of {amount} {token.symbol} from {from_addr} to {to_addr}" ) print(f"Invocation fee: {fee.value / Fixed8.D}") print( "-------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Invocation Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Allowance approval cancelled") return False if not wallet.ValidatePassword(passwd): print("incorrect password") return False return InvokeContract(wallet, tx, comb_fee) print( "Failed to approve tokens. Make sure you are entitled for approving." ) return False
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) < 4: print("Please specify the required parameters") return False arguments, priority_fee = PromptUtils.get_fee(arguments) token_str = arguments[0] from_addr = arguments[1] to_addr = arguments[2] try: amount = float(arguments[3]) except ValueError: print(f"{arguments[3]} is not a valid amount") return False p_fee = Fixed8.Zero() if priority_fee is not None: p_fee = priority_fee if p_fee is False: logger.debug("invalid fee") return False try: token, tx, fee, results = test_token_send_from( wallet, token_str, from_addr, to_addr, amount) except ValueError as e: # invalid arguments or bad allowance print(str(e)) return False except Exception as e: # we act as the final capturing place print("Something really unexpected happened") logger.error(traceback.format_exc()) return False if tx is not None and results is not None: vm_result = results[0].GetBigInteger() if vm_result == 1: print( "\n-----------------------------------------------------------" ) print("Transfer of %s %s from %s to %s" % (string_from_amount( token, amount), token.symbol, from_addr, to_addr)) print("Transfer fee: %s " % (fee.value / Fixed8.D)) print( "-------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Transfer Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Transaction cancelled") return False if not wallet.ValidatePassword(passwd): print("incorrect password") return False return InvokeContract(wallet, tx, comb_fee) print( f"Could not transfer tokens. Virtual machine returned: {vm_result}" ) return False print( f"Could not transfer tokens. An unknown error occurred resulting in no Transaction object or VM output." ) return False
def execute(self, arguments): wallet = PromptData.Wallet if not wallet: print("Please open a wallet") return False if len(arguments) < 5: print("Please specify the required parameters") return False args, from_addr = PromptUtils.get_from_addr(arguments) arguments, priority_fee = PromptUtils.get_fee(arguments) p_fee = Fixed8.Zero() if priority_fee is not None: p_fee = priority_fee if p_fee is False: logger.debug("invalid fee") return False path = args[0] try: needs_storage = bool(util.strtobool(args[1])) needs_dynamic_invoke = bool(util.strtobool(args[2])) is_payable = bool(util.strtobool(args[3])) except ValueError: print("Invalid boolean option") return False params = args[4] return_type = args[5] try: function_code = LoadContract(path, needs_storage, needs_dynamic_invoke, is_payable, params, return_type) except (ValueError, Exception) as e: print(str(e)) return False try: contract_script = GatherContractDetails(function_code) except KeyboardInterrupt: print("Deployment cancelled") return False if not contract_script: print("Failed to generate deploy script") return False tx, fee, results, num_ops, engine_success = test_invoke( contract_script, wallet, [], from_addr=from_addr) if tx is not None and results is not None: print( "\n-------------------------------------------------------------------------------------------------------------------------------------" ) print("Test deploy invoke successful") print(f"Total operations executed: {num_ops}") print("Results:") print([item.GetInterface() for item in results]) print(f"Deploy Invoke TX GAS cost: {tx.Gas.value / Fixed8.D}") print(f"Deploy Invoke TX Fee: {fee.value / Fixed8.D}") print( "-------------------------------------------------------------------------------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Deploy Invoke TX Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print( "Enter your password to deploy this contract on the blockchain" ) try: passwd = prompt("[password]> ", is_password=True) except KeyboardInterrupt: print("Deployment cancelled") return False if not wallet.ValidatePassword(passwd): print("Incorrect password") return False return InvokeContract(wallet, tx, comb_fee, from_addr=from_addr) else: print("Test invoke failed") print(f"TX is {tx}, results are {results}") return False
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) < 2: print("Please specify the required parameters") return False arguments, priority_fee = PromptUtils.get_fee(arguments) token_str = arguments[0] try: token = PromptUtils.get_token(wallet, token_str) except ValueError as e: print(str(e)) return False register_addr = arguments[1:] addr_list = [] for addr in register_addr: if isValidPublicAddress(addr): addr_list.append(addr) else: print(f"{addr} is not a valid address") return False p_fee = Fixed8.Zero() if priority_fee is not None: p_fee = priority_fee if p_fee is False: logger.debug("invalid fee") return False tx, fee, results = token.CrowdsaleRegister(wallet, addr_list) if tx is not None and results is not None: if len(results) > 0 and results[0].GetBigInteger() > 0: print( "\n-----------------------------------------------------------" ) print("[%s] Will register addresses for crowdsale: %s " % (token.symbol, register_addr)) print("Invocation Fee: %s " % (fee.value / Fixed8.D)) print( "-------------------------------------------------------------\n" ) comb_fee = p_fee + fee if comb_fee != fee: print( f"Priority Fee ({p_fee.value / Fixed8.D}) + Invocation Fee ({fee.value / Fixed8.D}) = {comb_fee.value / Fixed8.D}\n" ) print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Registration cancelled") return False if not wallet.ValidatePassword(passwd): print("incorrect password") return False return InvokeContract(wallet, tx, comb_fee) print("Could not register address(es)") return False
def construct_send_many(wallet, arguments): if len(arguments) is 0: print("Please specify the required parameter") return outgoing = get_arg(arguments, convert_to_int=True) if outgoing is None: print("Invalid outgoing number") return if outgoing < 1: print("Outgoing number must be >= 1") return arguments, from_address = get_from_addr(arguments) arguments, change_address = get_change_addr(arguments) arguments, priority_fee = get_fee(arguments) arguments, owners = get_owners_from_params(arguments) arguments, user_tx_attributes = get_tx_attr_from_args(arguments) output = [] for i in range(outgoing): try: print('Outgoing Number ', i + 1) to_send = prompt("Asset to send: ") assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") return if type(assetId) is NEP5Token: print('sendmany does not support NEP5 tokens') return address_to = prompt("Address to: ") scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: logger.debug("invalid destination address") return amount = prompt("Amount to send: ") f8amount = get_asset_amount(amount, assetId) if f8amount is False: logger.debug("invalid amount") return if float(amount) == 0: print("Amount cannot be 0") return tx_output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) output.append(tx_output) except KeyboardInterrupt: print('Transaction cancelled') return contract_tx = ContractTransaction(outputs=output) scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if scripthash_from is None: logger.debug("invalid source address") return scripthash_change = None if change_address is not None: scripthash_change = lookup_addr_str(wallet, change_address) if scripthash_change is None: logger.debug("invalid change address") return fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee if fee is False: logger.debug("invalid fee") return print(f"Sending with fee: {fee.ToString()}") return [ contract_tx, scripthash_from, scripthash_change, fee, owners, user_tx_attributes ]
def process_transaction(wallet, contract_tx, scripthash_from=None, scripthash_change=None, fee=None, owners=None, user_tx_attributes=None): try: tx = wallet.MakeTransaction(tx=contract_tx, change_address=scripthash_change, fee=fee, from_addr=scripthash_from) except ValueError: print( "Insufficient funds. No unspent outputs available for building the transaction.\n" "If you are trying to sent multiple transactions in 1 block, then make sure you have enough 'vouts'\n." "Use `wallet unspent` and `wallet address split`, or wait until the first transaction is processed before sending another." ) return if tx is None: logger.debug("insufficient funds") return try: print("Validate your transaction details") print("-" * 33) input_coinref = wallet.FindCoinsByVins(tx.inputs)[0] source_addr = input_coinref.Address for order in tx.outputs: dest_addr = order.Address value = order.Value.ToString() # fixed8 if order.AssetId == Blockchain.Default().SystemShare().Hash: asset_name = 'NEO' else: asset_name = 'GAS' if source_addr != dest_addr: print( f"Sending {value} {asset_name} from {source_addr} to {dest_addr}" ) else: print( f"Returning {value} {asset_name} as change to {dest_addr}") print(" ") print("Enter your password to send to the network") try: passwd = prompt("[Password]> ", is_password=True) except KeyboardInterrupt: print("Transaction cancelled") return if not wallet.ValidatePassword(passwd): print("Incorrect password") return standard_contract = wallet.GetStandardAddress() if scripthash_from is not None: signer_contract = wallet.GetContract(scripthash_from) else: signer_contract = wallet.GetContract(standard_contract) if not signer_contract.IsMultiSigContract and owners is None: data = standard_contract.Data tx.Attributes = [ TransactionAttribute(usage=TransactionAttributeUsage.Script, data=data) ] # insert any additional user specified tx attributes tx.Attributes = tx.Attributes + user_tx_attributes if owners: owners = list(owners) for owner in owners: tx.Attributes.append( TransactionAttribute( usage=TransactionAttributeUsage.Script, data=owner)) context = ContractParametersContext( tx, isMultiSig=signer_contract.IsMultiSigContract) wallet.Sign(context) if owners: owners = list(owners) gather_signatures(context, tx, owners) if context.Completed: tx.scripts = context.GetScripts() passed, reason = validate_simple_policy(tx) if not passed: print(reason) return nodemgr = NodeManager() relayed = nodemgr.relay(tx) if relayed: wallet.SaveTransaction(tx) print("Relayed Tx: %s " % tx.Hash.ToString()) return tx else: print("Could not relay tx %s " % tx.Hash.ToString()) else: print( "Transaction initiated, but the signature is incomplete. Use the `sign` command with the information below to complete signing." ) print(json.dumps(context.ToJson(), separators=(',', ':'))) return except Exception as e: print("Could not send: %s " % e) traceback.print_stack() traceback.print_exc() return
def start(self): self.continue_debug = True # pprint.pprint(self.debug_map) dbg_title = self.debug_map['avm']['name'] print("\n") print("======= debug engine enter =======") ctx = self.get_context() ctx.print() while self.continue_debug: try: result = prompt("[%s debug]> " % dbg_title) except EOFError: # Control-D pressed: quit self.continue_debug = False except KeyboardInterrupt: # Control-C pressed: do nothing self.continue_debug = False command, arguments = self.parser.parse_input(result) if command is not None and len(command) > 0: command = command.lower() if command in ['quit', 'exit', 'cont']: self.continue_debug = False elif command == 'estack': if self.engine._InvocationStack.Count > 0: # eval stack now only available via ExecutionContext objects in the istack if len(self.engine.CurrentContext.EvaluationStack.Items): for item in self.engine.CurrentContext.EvaluationStack.Items: print(ContractParameter.ToParameter(item).ToJson()) else: print("Evaluation stack empty") else: print("Evaluation stack empty") elif command == 'istack': print("Invocation Stack:") for item in self.engine.InvocationStack.Items: pprint.pprint(item) print(vars(item)) elif command == 'astack': if len(self.engine.AltStack.Items): for item in self.engine.AltStack.Items: print(ContractParameter.ToParameter(item).ToJson()) else: print("Alt Stack Empty") elif command == 'rstack': items = self.engine.ResultStack.Items if len(items): for item in items: pprint.pprint(item) else: print("Result stack empty") elif command == 'ctx': ctx.print() elif command == 'file': ctx.print_file() elif command == 'ops': ctx.print_method_ops() elif command == 'pdb': pdb.set_trace() elif command == 'help': print("Use one of [estack, istack, astack, exit, quit, ctx, file, ops, pdb, or any local variable]") elif command in ctx.method.scope: try: idx = ctx.method.scope[command] value = self.engine.AltStack.Items[-1].GetArray()[idx] param = ContractParameter.ToParameter(value) print("\n") if param.Type == ContractParameterType.InteropInterface: cmd_value = json.dumps(param.Value.ToJson(), indent=4) else: cmd_value = param.Value print(f"{command} = {cmd_value} [{param.Type}]") print("\n") except Exception as e: logger.error("Could not lookup item %s: %s " % (command, e)) else: print("unknown command: %s " % command) print("======= debug engine exit =======") print("\n")