diff --git a/.gitignore b/.gitignore index 962ffeaabcaf..7f0a76c10af9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,9 @@ build/ dist/ tmp/ *.egg/ -/electrum.py contrib/pyinstaller/ Electrum_MONA.egg-info/ -gui/qt/icons_rc.py +electrum/gui/qt/icons_rc.py locale/ .devlocaltmp/ *_trial_temp diff --git a/.pytest_cache/v/cache/nodeids b/.pytest_cache/v/cache/nodeids new file mode 100644 index 000000000000..54c38df33b3a --- /dev/null +++ b/.pytest_cache/v/cache/nodeids @@ -0,0 +1,255 @@ +[ + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_add_number_to_script", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_address_to_script", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_aes_decode_with_invalid_password", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_aes_deencode_without_password", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_aes_encode_without_password", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_aes_homomorphic", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_crypto", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_decrypt_message", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_ecc_sanity", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_encrypt_message", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_hash", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_int_to_hex", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_libsecp256k1_is_available", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_msg_signing", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_op_push", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_push_script", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_pycryptodomex_is_available", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_script_num_to_hex", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_sign_transaction", + "electrum/tests/test_bitcoin.py::Test_bitcoin::test_var_int", + "electrum/tests/test_bitcoin.py::Test_bitcoin_testnet::test_address_to_script", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_bip32", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_is_bip32_derivation", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_is_xprv", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_is_xpub", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_version_bytes", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_xpub_from_xprv", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_xpub_type", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub::test_xtype_from_derivation", + "electrum/tests/test_bitcoin.py::Test_xprv_xpub_testnet::test_version_bytes", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_address_from_private_key", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_address_to_scripthash", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_is_compressed", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_is_minikey", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_is_private_key", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_is_private_key_old", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_is_valid_address", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_public_key_from_private_key", + "electrum/tests/test_bitcoin.py::Test_keyImport::test_serialize_privkey", + "electrum/tests/test_bitcoin.py::Test_seeds::test_new_seed", + "electrum/tests/test_bitcoin.py::Test_seeds::test_old_seed", + "electrum/tests/test_bitcoin.py::Test_seeds::test_seed_type", + "electrum/tests/test_commands.py::TestCommands::test_setconfig_auth", + "electrum/tests/test_commands.py::TestCommands::test_setconfig_non_auth_boolean", + "electrum/tests/test_commands.py::TestCommands::test_setconfig_non_auth_list", + "electrum/tests/test_commands.py::TestCommands::test_setconfig_non_auth_number", + "electrum/tests/test_commands.py::TestCommands::test_setconfig_non_auth_number_as_string", + "electrum/tests/test_dnssec.py::TestDnsSec::test_python_validate_rrsig_ecdsa", + "electrum/tests/test_dnssec.py::TestDnsSec::test_python_validate_rrsig_rsa", + "electrum/tests/test_interface.py::TestInterface::test_check_host_name", + "electrum/tests/test_interface.py::TestInterface::test_match_host_name", + "electrum/tests/test_mnemonic.py::Test_NewMnemonic::test_random_seeds", + "electrum/tests/test_mnemonic.py::Test_NewMnemonic::test_to_seed", + "electrum/tests/test_mnemonic.py::Test_OldMnemonic::test", + "electrum/tests/test_mnemonic.py::Test_BIP39Checksum::test", + "electrum/tests/test_scrypt.py::Test_scrypt::test_scrypt", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_can_set_options_set_in_user_config", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_cannot_set_options_passed_by_command_line", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_depth_target_to_fee", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_fee_to_depth", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_simple_config_command_line_overrides_everything", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_simple_config_key_rename", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_simple_config_user_config_is_used_if_others_arent_specified", + "electrum/tests/test_simple_config.py::Test_SimpleConfig::test_user_config_is_not_written_with_read_only_config", + "electrum/tests/test_simple_config.py::TestUserConfig::test_no_path_means_no_result", + "electrum/tests/test_simple_config.py::TestUserConfig::test_path_with_reprd_object", + "electrum/tests/test_simple_config.py::TestUserConfig::test_path_without_config_file", + "electrum/tests/test_storage_upgrade.py::TestStorageUpgrade::test_upgrade_from_client_2_9_3_importedkeys", + "electrum/tests/test_storage_upgrade.py::TestStorageUpgrade::test_upgrade_from_client_2_9_3_multisig", + "electrum/tests/test_storage_upgrade.py::TestStorageUpgrade::test_upgrade_from_client_2_9_3_seeded", + "electrum/tests/test_storage_upgrade.py::TestStorageUpgrade::test_upgrade_from_client_2_9_3_watchaddresses", + "electrum/tests/test_transaction.py::TestBCDataStream::test_bytes", + "electrum/tests/test_transaction.py::TestBCDataStream::test_compact_size", + "electrum/tests/test_transaction.py::TestBCDataStream::test_string", + "electrum/tests/test_transaction.py::TestTransaction::test_errors", + "electrum/tests/test_transaction.py::TestTransaction::test_estimated_output_size", + "electrum/tests/test_transaction.py::TestTransaction::test_get_address_from_output_script", + "electrum/tests/test_transaction.py::TestTransaction::test_parse_xpub", + "electrum/tests/test_transaction.py::TestTransaction::test_tx_signed", + "electrum/tests/test_transaction.py::TestTransaction::test_tx_signed_segwit", + "electrum/tests/test_transaction.py::TestTransaction::test_tx_unsigned", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0001", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0002", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0003", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0004", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0005", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0006", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0007", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0008", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0009", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0010", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0011", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0012", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0013", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0014", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0015", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0016", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0017", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0018", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0019", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0020", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0021", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0022", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0023", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0024", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0025", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0026", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0027", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0028", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0029", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0030", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0031", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0032", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0033", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0034", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0035", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0036", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0037", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0038", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0039", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0040", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0041", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0042", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0043", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0044", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0045", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0046", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0047", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0048", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0049", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0050", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0051", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0052", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0053", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0054", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0055", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0056", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0057", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0058", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0059", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0060", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0061", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0062", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0063", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0064", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0065", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0066", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0067", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0068", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0069", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0070", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0071", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0072", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0073", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0074", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0075", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0076", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0077", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0078", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0079", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0080", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0081", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0082", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0083", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0084", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0085", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0086", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0087", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0088", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0089", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0090", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0091", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_bitcoin_core_0092", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_coinbase_to_p2pk", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_coinbase_to_p2pkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_input_p2wsh_p2sh_not_multisig", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_negative_version_num", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2pk_to_p2pkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2pk_to_p2sh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2pk_to_p2wpkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2pkh_to_p2pkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2pkh_to_p2sh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2pkh_to_p2wpkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2sh_to_p2pkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2sh_to_p2sh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2sh_to_p2wpkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2wpkh_to_p2pkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2wpkh_to_p2sh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_p2wpkh_to_p2wpkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_regression_issue_3899", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_regression_issue_4333", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_segwit_coinbase_to_p2pk", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_segwit_coinbase_to_p2pkh", + "electrum/tests/test_transaction.py::TestTransaction::test_txid_segwit_coinbase_to_p2sh", + "electrum/tests/test_transaction.py::TestTransaction::test_version_field", + "electrum/tests/test_transaction.py::TestTransactionTestnet::test_txid_partial_segwit_p2wpkh", + "electrum/tests/test_transaction.py::TestTransactionTestnet::test_txid_partial_segwit_p2wpkh_p2sh_mixed_outputs", + "electrum/tests/test_transaction.py::TestTransactionTestnet::test_txid_partial_segwit_p2wpkh_p2sh_simple", + "electrum/tests/test_util.py::TestUtil::test_format_fee", + "electrum/tests/test_util.py::TestUtil::test_format_fee_precision", + "electrum/tests/test_util.py::TestUtil::test_format_satoshis", + "electrum/tests/test_util.py::TestUtil::test_format_satoshis_diff_negative", + "electrum/tests/test_util.py::TestUtil::test_format_satoshis_diff_positive", + "electrum/tests/test_util.py::TestUtil::test_format_satoshis_negative", + "electrum/tests/test_util.py::TestUtil::test_format_satoshis_whitespaces", + "electrum/tests/test_util.py::TestUtil::test_format_satoshis_whitespaces_negative", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_address", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_address_amount", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_address_label", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_address_message", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_address_request_url", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_ignore_args", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_invalid", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_invalid_address", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_multiple_args", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_no_address_request_url", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_only_address", + "electrum/tests/test_util.py::TestUtil::test_parse_URI_parameter_polution", + "electrum/tests/test_wallet.py::TestWalletStorage::test_read_dictionary_from_file", + "electrum/tests/test_wallet.py::TestWalletStorage::test_write_dictionary_to_file", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip32_extended_version_bytes", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip39_multisig_seed_bip45_standard", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip39_multisig_seed_p2sh_segwit", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip39_seed_bip44_standard", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip39_seed_bip44_standard_passphrase", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip39_seed_bip49_p2sh_segwit", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_bip39_seed_bip84_native_segwit", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_electrum_multisig_seed_segwit", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_electrum_multisig_seed_standard", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_electrum_seed_old", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_electrum_seed_segwit", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_electrum_seed_segwit_passphrase", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForMainnet::test_electrum_seed_standard", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForTestnet::test_bip32_extended_version_bytes", + "electrum/tests/test_wallet_vertical.py::TestWalletKeystoreAddressIntegrityForTestnet::test_bip39_multisig_seed_p2sh_segwit_testnet", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_bump_fee_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_bump_fee_p2wpkh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_cpfp_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_cpfp_p2wpkh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_sending_between_p2sh_1of2_and_p2wpkh_p2sh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_sending_between_p2sh_2of3_and_uncompressed_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_sending_between_p2wpkh_and_compressed_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_sending_between_p2wsh_2of3_and_p2wsh_p2sh_2of2", + "electrum/tests/test_wallet_vertical.py::TestWalletSending::test_sweep_p2pk", + "electrum/tests/test_wallet_vertical.py::TestWalletOfflineSigning::test_sending_offline_wif_online_addr_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletOfflineSigning::test_sending_offline_xprv_online_addr_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletOfflineSigning::test_sending_offline_xprv_online_xpub_p2pkh", + "electrum/tests/test_wallet_vertical.py::TestWalletOfflineSigning::test_sending_offline_xprv_online_xpub_p2wpkh", + "electrum/tests/test_wallet_vertical.py::TestWalletOfflineSigning::test_sending_offline_xprv_online_xpub_p2wpkh_p2sh", + "electrum/tests/test_wallet_vertical.py::TestWalletHistory_SimpleRandomOrder::test_restoring_old_wallet_txorder1", + "electrum/tests/test_wallet_vertical.py::TestWalletHistory_SimpleRandomOrder::test_restoring_old_wallet_txorder2", + "electrum/tests/test_wallet_vertical.py::TestWalletHistory_SimpleRandomOrder::test_restoring_old_wallet_txorder3", + "electrum/tests/test_wallet_vertical.py::TestWalletHistory_EvilGapLimit::test_restoring_wallet_txorder1" +] \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index bd28dcbdbd4c..86c6b71fcd64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ jobs: install: - sudo docker build --no-cache -t electrum-mona-wine-builder-img ./contrib/build-wine/docker/ script: - - sudo docker run --name electrum-mona-wine-builder-cont -v $PWD:/opt/electrum-mona --rm --workdir /opt/electrum-mona/contrib/build-wine electrum-mona-wine-builder-img ./build.sh $TRAVIS_COMMIT + - sudo docker run --name electrum-mona-wine-builder-cont -v $PWD:/opt/wine64/drive_c/electrum-mona --rm --workdir /opt/wine64/drive_c/electrum-mona/contrib/build-wine electrum-mona-wine-builder-img ./build.sh after_success: true - os: osx language: c diff --git a/README.rst b/README.rst index 69298eae3bcb..161395896eec 100644 --- a/README.rst +++ b/README.rst @@ -34,7 +34,7 @@ Electrum-mona from its root directory, without installing it on your system; all the python dependencies are included in the 'packages' directory. To run Electrum-mona from its root directory, just do:: - ./electrum-mona + ./run_electrum You can also install Electrum-mona on your system, by running this command:: @@ -75,12 +75,12 @@ Render the SVG icons to PNGs (optional):: Compile the icons file for Qt:: sudo apt-get install pyqt5-dev-tools - pyrcc5 icons.qrc -o gui/qt/icons_rc.py + pyrcc5 icons.qrc -o electrum/gui/qt/icons_rc.py Compile the protobuf description file:: sudo apt-get install protobuf-compiler - protoc --proto_path=lib/ --python_out=lib/ lib/paymentrequest.proto + protoc --proto_path=electrum --python_out=electrum electrum/paymentrequest.proto Create translations (optional):: @@ -114,4 +114,4 @@ See `contrib/build-wine/`. Android ------- -See `gui/kivy/Readme.txt` file. +See `electrum/gui/kivy/Readme.md` file. diff --git a/contrib/build-osx/make_osx b/contrib/build-osx/make_osx index 43d6cceeddf0..b2ab984d3be2 100755 --- a/contrib/build-osx/make_osx +++ b/contrib/build-osx/make_osx @@ -46,8 +46,8 @@ git submodule update rm -rf $BUILDDIR > /dev/null 2>&1 mkdir $BUILDDIR -cp -R ./contrib/deterministic-build/electrum-locale/locale/ ./lib/locale/ -cp ./contrib/deterministic-build/electrum-icons/icons_rc.py ./gui/qt/ +cp -R ./contrib/deterministic-build/electrum-locale/locale/ ./electrum/locale/ +cp ./contrib/deterministic-build/electrum-icons/icons_rc.py ./electrum/gui/qt/ info "Downloading libusb..." diff --git a/contrib/build-osx/osx.spec b/contrib/build-osx/osx.spec index 30ed822a48b7..ad09d40b9e02 100644 --- a/contrib/build-osx/osx.spec +++ b/contrib/build-osx/osx.spec @@ -1,98 +1,96 @@ -# -*- mode: python -*- - -from PyInstaller.utils.hooks import collect_data_files, collect_submodules, collect_dynamic_libs - -import sys -import os - -PACKAGE='Electrum-mona' -PYPKG='electrum_mona' -MAIN_SCRIPT='electrum-mona' -ICONS_FILE='electrum.icns' - -for i, x in enumerate(sys.argv): - if x == '--name': - VERSION = sys.argv[i+1] - break -else: - raise Exception('no version') - -electrum = os.path.abspath(".") + "/" -block_cipher = None - -# see https://github.com/pyinstaller/pyinstaller/issues/2005 -hiddenimports = [] -hiddenimports += collect_submodules('trezorlib') -hiddenimports += collect_submodules('btchip') -hiddenimports += collect_submodules('keepkeylib') -hiddenimports += collect_submodules('websocket') - -datas = [ - (electrum+'lib/*.json', PYPKG), - (electrum+'lib/wordlist/english.txt', PYPKG + '/wordlist'), - (electrum+'lib/locale', PYPKG + '/locale'), - (electrum+'plugins', PYPKG + '_plugins'), -] -datas += collect_data_files('trezorlib') -datas += collect_data_files('btchip') -datas += collect_data_files('keepkeylib') - -# Add libusb so Trezor will work -binaries = [(electrum + "contrib/build-osx/libusb-1.0.dylib", ".")] -binaries += [(electrum + "contrib/build-osx/libsecp256k1.0.dylib", ".")] - -# Workaround for "Retro Look": -binaries += [b for b in collect_dynamic_libs('PyQt5') if 'macstyle' in b[0]] - -# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports -a = Analysis([electrum+MAIN_SCRIPT, - electrum+'gui/qt/main_window.py', - electrum+'gui/text.py', - electrum+'lib/util.py', - electrum+'lib/wallet.py', - electrum+'lib/simple_config.py', - electrum+'lib/bitcoin.py', - electrum+'lib/blockchain.py', - electrum+'lib/dnssec.py', - electrum+'lib/commands.py', - electrum+'plugins/cosigner_pool/qt.py', - electrum+'plugins/email_requests/qt.py', - electrum+'plugins/trezor/client.py', - electrum+'plugins/trezor/qt.py', - electrum+'plugins/keepkey/qt.py', - electrum+'plugins/ledger/qt.py', - ], - binaries=binaries, - datas=datas, - hiddenimports=hiddenimports, - hookspath=[]) - -# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal -for d in a.datas: - if 'pyconfig' in d[0]: - a.datas.remove(d) - break - -pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) - -exe = EXE(pyz, - a.scripts, - a.binaries, - a.datas, - name=PACKAGE, - debug=False, - strip=False, - upx=True, - icon=electrum+ICONS_FILE, - console=False) - -app = BUNDLE(exe, - version = VERSION, - name=PACKAGE + '.app', - icon=electrum+ICONS_FILE, - bundle_identifier=None, - info_plist={ - 'NSHighResolutionCapable': 'True', - 'NSSupportsAutomaticGraphicsSwitching': 'True' - } -) +# -*- mode: python -*- + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules, collect_dynamic_libs + +import sys +import os + +PACKAGE='Electrum-MONA' +PYPKG='electrum' +MAIN_SCRIPT='run_electrum' +ICONS_FILE='electrum.icns' + +for i, x in enumerate(sys.argv): + if x == '--name': + VERSION = sys.argv[i+1] + break +else: + raise Exception('no version') + +electrum = os.path.abspath(".") + "/" +block_cipher = None + +# see https://github.com/pyinstaller/pyinstaller/issues/2005 +hiddenimports = [] +hiddenimports += collect_submodules('trezorlib') +hiddenimports += collect_submodules('btchip') +hiddenimports += collect_submodules('keepkeylib') +hiddenimports += collect_submodules('websocket') + +datas = [ + (electrum+'electrum/*.json', PYPKG), + (electrum+'electrum/wordlist/english.txt', PYPKG + '/wordlist'), + (electrum+'electrum/locale', PYPKG + '/locale') +] +datas += collect_data_files('trezorlib') +datas += collect_data_files('btchip') +datas += collect_data_files('keepkeylib') + +# Add libusb so Trezor will work +binaries = [(electrum + "contrib/build-osx/libusb-1.0.dylib", ".")] +binaries += [(electrum + "contrib/build-osx/libsecp256k1.0.dylib", ".")] + +# Workaround for "Retro Look": +binaries += [b for b in collect_dynamic_libs('PyQt5') if 'macstyle' in b[0]] + +# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports +a = Analysis([electrum+ MAIN_SCRIPT, + electrum+'electrum/gui/qt/main_window.py', + electrum+'electrum/gui/text.py', + electrum+'electrum/util.py', + electrum+'electrum/wallet.py', + electrum+'electrum/simple_config.py', + electrum+'electrum/bitcoin.py', + electrum+'electrum/dnssec.py', + electrum+'electrum/commands.py', + electrum+'electrum/plugins/cosigner_pool/qt.py', + electrum+'electrum/plugins/email_requests/qt.py', + electrum+'electrum/plugins/trezor/client.py', + electrum+'electrum/plugins/trezor/qt.py', + electrum+'electrum/plugins/keepkey/qt.py', + electrum+'electrum/plugins/ledger/qt.py', + ], + binaries=binaries, + datas=datas, + hiddenimports=hiddenimports, + hookspath=[]) + +# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal +for d in a.datas: + if 'pyconfig' in d[0]: + a.datas.remove(d) + break + +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + +exe = EXE(pyz, + a.scripts, + a.binaries, + a.datas, + name=PACKAGE, + debug=False, + strip=False, + upx=True, + icon=electrum+ICONS_FILE, + console=False) + +app = BUNDLE(exe, + version = VERSION, + name=PACKAGE + '.app', + icon=electrum+ICONS_FILE, + bundle_identifier=None, + info_plist={ + 'NSHighResolutionCapable': 'True', + 'NSSupportsAutomaticGraphicsSwitching': 'True' + } +) diff --git a/contrib/build-wine/build-electrum-git-ja.sh b/contrib/build-wine/build-electrum-git-ja.sh index 6197949e7c8a..70e9fd2e7aec 100755 --- a/contrib/build-wine/build-electrum-git-ja.sh +++ b/contrib/build-wine/build-electrum-git-ja.sh @@ -1,7 +1,7 @@ #!/bin/bash NAME_ROOT=electrum-mona -PYTHON_VERSION=3.5.4 +PYTHON_VERSION=3.6.6 # These settings probably don't need any change export WINEPREFIX=/opt/wine64 @@ -19,23 +19,7 @@ set -e mkdir -p tmp cd tmp -if [ -d ./electrum-mona ]; then - rm ./electrum-mona -rf -fi - -git clone https://github.com/wakiyamap/electrum-mona -b master - -pushd electrum-mona -if [ ! -z "$1" ]; then - # a commit/tag/branch was specified - if ! git cat-file -e "$1" 2> /dev/null - then # can't find target - # try pull requests - git config --local --add remote.origin.fetch '+refs/pull/*/merge:refs/remotes/origin/pr/*' - git fetch --all - fi - git checkout $1 -fi +pushd $WINEPREFIX/drive_c/electrum-mona # Load electrum-icons and electrum-locale for this release git submodule init @@ -59,11 +43,9 @@ popd find -exec touch -d '2000-11-11T11:11:11+00:00' {} + popd -rm -rf $WINEPREFIX/drive_c/electrum-mona -cp -r electrum-mona $WINEPREFIX/drive_c/electrum-mona -cp electrum-mona/LICENCE . -cp -r ./electrum-mona/contrib/deterministic-build/electrum-locale/locale $WINEPREFIX/drive_c/electrum-mona/lib/ -cp ./electrum-mona/contrib/deterministic-build/electrum-icons/icons_rc.py $WINEPREFIX/drive_c/electrum-mona/gui/qt/ +cp $WINEPREFIX/drive_c/electrum-mona/LICENCE . +cp -r $WINEPREFIX/drive_c/electrum-mona/contrib/deterministic-build/electrum-locale/locale $WINEPREFIX/drive_c/electrum-mona/electrum/ +cp $WINEPREFIX/drive_c/electrum-mona/contrib/deterministic-build/electrum-icons/icons_rc.py $WINEPREFIX/drive_c/electrum-mona/electrum/gui/qt/ # build japanese version cp ../default-ja.patch $WINEPREFIX/drive_c/electrum-mona/gui/qt diff --git a/contrib/build-wine/build-electrum-git.sh b/contrib/build-wine/build-electrum-git.sh index 6e5cc166c271..777d8028e293 100755 --- a/contrib/build-wine/build-electrum-git.sh +++ b/contrib/build-wine/build-electrum-git.sh @@ -1,7 +1,7 @@ #!/bin/bash NAME_ROOT=electrum-mona -PYTHON_VERSION=3.5.4 +PYTHON_VERSION=3.6.6 # These settings probably don't need any change export WINEPREFIX=/opt/wine64 @@ -19,23 +19,7 @@ set -e mkdir -p tmp cd tmp -if [ -d ./electrum-mona ]; then - rm ./electrum-mona -rf -fi - -git clone https://github.com/wakiyamap/electrum-mona -b master - -pushd electrum-mona -if [ ! -z "$1" ]; then - # a commit/tag/branch was specified - if ! git cat-file -e "$1" 2> /dev/null - then # can't find target - # try pull requests - git config --local --add remote.origin.fetch '+refs/pull/*/merge:refs/remotes/origin/pr/*' - git fetch --all - fi - git checkout $1 -fi +pushd $WINEPREFIX/drive_c/electrum-mona # Load electrum-icons and electrum-locale for this release git submodule init @@ -59,11 +43,9 @@ popd find -exec touch -d '2000-11-11T11:11:11+00:00' {} + popd -rm -rf $WINEPREFIX/drive_c/electrum-mona -cp -r electrum-mona $WINEPREFIX/drive_c/electrum-mona -cp electrum-mona/LICENCE . -cp -r ./electrum-mona/contrib/deterministic-build/electrum-locale/locale $WINEPREFIX/drive_c/electrum-mona/lib/ -cp ./electrum-mona/contrib/deterministic-build/electrum-icons/icons_rc.py $WINEPREFIX/drive_c/electrum-mona/gui/qt/ +cp $WINEPREFIX/drive_c/electrum-mona/LICENCE . +cp -r $WINEPREFIX/drive_c/electrum-mona/contrib/deterministic-build/electrum-locale/locale $WINEPREFIX/drive_c/electrum-mona/electrum/ +cp $WINEPREFIX/drive_c/electrum-mona/contrib/deterministic-build/electrum-icons/icons_rc.py $WINEPREFIX/drive_c/electrum-mona/electrum/gui/qt/ # Install frozen dependencies $PYTHON -m pip install -r ../../deterministic-build/requirements.txt diff --git a/contrib/build-wine/build.sh b/contrib/build-wine/build.sh index 577ddd92099f..67beb4ee6611 100755 --- a/contrib/build-wine/build.sh +++ b/contrib/build-wine/build.sh @@ -2,10 +2,6 @@ # Lucky number export PYTHONHASHSEED=22 -if [ ! -z "$1" ]; then - to_build="$1" -fi - here=$(dirname "$0") test -n "$here" -a -d "$here" || exit @@ -28,5 +24,5 @@ find -exec touch -d '2000-11-11T11:11:11+00:00' {} + popd ls -l /opt/wine64/drive_c/python* -$here/build-electrum-git.sh $to_build && \ +$here/build-electrum-git.sh && \ echo "Done." diff --git a/contrib/build-wine/deterministic.spec b/contrib/build-wine/deterministic.spec index 9026fa8cb94b..f509a501c655 100644 --- a/contrib/build-wine/deterministic.spec +++ b/contrib/build-wine/deterministic.spec @@ -11,7 +11,7 @@ for i, x in enumerate(sys.argv): else: raise Exception('no name') -PYTHON_VERSION = '3.5.4' +PYTHON_VERSION = '3.6.6' PYHOME = 'c:/python' + PYTHON_VERSION home = 'C:\\electrum-mona\\' @@ -37,33 +37,31 @@ binaries += [b for b in collect_dynamic_libs('PyQt5') if 'qwindowsvista' in b[0] binaries += [('C:/tmp/libsecp256k1.dll', '.')] datas = [ - (home+'lib/*.json', 'electrum_mona'), - (home+'lib/wordlist/english.txt', 'electrum_mona/wordlist'), - (home+'lib/locale', 'electrum_mona/locale'), - (home+'plugins', 'electrum_mona_plugins'), - (zbardir+'ZBar\\bin\\', '.') + (home+'electrum/*.json', 'electrum'), + (home+'electrum/wordlist/english.txt', 'electrum/wordlist'), + (home+'electrum/locale', 'electrum/locale'), + ('C:\\Program Files (x86)\\ZBar\\bin\\', '.') ] datas += collect_data_files('trezorlib') datas += collect_data_files('btchip') datas += collect_data_files('keepkeylib') # We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports -a = Analysis([home+'electrum-mona', - home+'gui/qt/main_window.py', - home+'gui/text.py', - home+'lib/util.py', - home+'lib/wallet.py', - home+'lib/simple_config.py', - home+'lib/bitcoin.py', - home+'lib/blockchain.py', - home+'lib/dnssec.py', - home+'lib/commands.py', - home+'plugins/cosigner_pool/qt.py', - home+'plugins/email_requests/qt.py', - home+'plugins/trezor/client.py', - home+'plugins/trezor/qt.py', - home+'plugins/keepkey/qt.py', - home+'plugins/ledger/qt.py', +a = Analysis([home+'run_electrum', + home+'electrum/gui/qt/main_window.py', + home+'electrum/gui/text.py', + home+'electrum/util.py', + home+'electrum/wallet.py', + home+'electrum/simple_config.py', + home+'electrum/bitcoin.py', + home+'electrum/dnssec.py', + home+'electrum/commands.py', + home+'electrum/plugins/cosigner_pool/qt.py', + home+'electrum/plugins/email_requests/qt.py', + home+'electrum/plugins/trezor/client.py', + home+'electrum/plugins/trezor/qt.py', + home+'electrum/plugins/keepkey/qt.py', + home+'electrum/plugins/ledger/qt.py', #home+'packages/requests/utils.py' ], binaries=binaries, @@ -75,7 +73,7 @@ a = Analysis([home+'electrum-mona', # http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal for d in a.datas: - if 'pyconfig' in d[0]: + if 'pyconfig' in d[0]: a.datas.remove(d) break @@ -92,7 +90,7 @@ exe_standalone = EXE( pyz, a.scripts, a.binaries, - a.datas, + a.datas, name=os.path.join('build\\pyi.win32\\electrum-mona', cmdline_name + ".exe"), debug=False, strip=None, diff --git a/contrib/build-wine/docker/Dockerfile b/contrib/build-wine/docker/Dockerfile index cb801830b891..0d2a63b12347 100644 --- a/contrib/build-wine/docker/Dockerfile +++ b/contrib/build-wine/docker/Dockerfile @@ -3,8 +3,8 @@ FROM ubuntu:18.04@sha256:5f4bdc3467537cbbe563e80db2c3ec95d548a9145d64453b06939c4 ENV LC_ALL=C.UTF-8 LANG=C.UTF-8 RUN dpkg --add-architecture i386 && \ - apt-get update -qq && \ - apt-get install -qq \ + apt-get update -q && \ + apt-get install -qy \ wget=1.19.4-1ubuntu2.1 \ gnupg2=2.2.4-1ubuntu1.1 \ dirmngr=2.2.4-1ubuntu1.1 \ @@ -13,9 +13,12 @@ RUN dpkg --add-architecture i386 && \ wget -nc https://dl.winehq.org/wine-builds/Release.key && \ apt-key add Release.key && \ apt-add-repository https://dl.winehq.org/wine-builds/ubuntu/ && \ - apt-get update -qq && \ - apt-get install -qq \ - winehq-stable=3.0.1~bionic \ + apt-get update -q && \ + apt-get install -qy \ + wine-stable-amd64:amd64=3.0.1~bionic \ + wine-stable-i386:i386=3.0.1~bionic \ + wine-stable:amd64=3.0.1~bionic \ + winehq-stable:amd64=3.0.1~bionic \ git=1:2.17.1-1ubuntu0.1 \ p7zip-full=16.02+dfsg-6 \ make=4.1-9.1ubuntu1 \ diff --git a/contrib/build-wine/docker/README.md b/contrib/build-wine/docker/README.md index 2b3b65740e2f..47e2a0fd329c 100644 --- a/contrib/build-wine/docker/README.md +++ b/contrib/build-wine/docker/README.md @@ -2,7 +2,8 @@ Deterministic Windows binaries with Docker ========================================== This assumes an Ubuntu host, but it should not be too hard to adapt to another -similar system. +similar system. The docker commands should be executed in the project's root +folder. 1. Install Docker @@ -16,9 +17,7 @@ similar system. 2. Build image ``` - $ cd contrib/build-wine/docker - $ PROJECT_ROOT=$PWD/../../../ - $ sudo docker build --no-cache -t electrum-mona-wine-builder-img . + $ sudo docker build --no-cache -t electrum-mona-wine-builder-img contrib/build-wine/docker ``` Note: see [this](https://stackoverflow.com/a/40516974/7499128) if having dns problems @@ -26,16 +25,16 @@ similar system. 3. Build Windows binaries ``` - $ TARGET=master + $ git checkout $REV $ sudo docker run \ --name electrum-mona-wine-builder-cont \ - -v ${PROJECT_ROOT}:/opt/electrum-mona \ + -v $PWD:/opt/wine64/drive_c/electrum-mona \ --rm \ - --workdir /opt/electrum-mona/contrib/build-wine \ + --workdir /opt/wine64/drive_c/electrum-mona/contrib/build-wine \ electrum-mona-wine-builder-img \ - ./build.sh $TARGET + ./build.sh ``` -4. The generated binaries are in `$PROJECT_ROOT/contrib/build-wine/dist`. +4. The generated binaries are in `./contrib/build-wine/dist`. diff --git a/contrib/build-wine/electrum.nsi b/contrib/build-wine/electrum.nsi index bdb9d8fe067f..11d329623e2f 100644 --- a/contrib/build-wine/electrum.nsi +++ b/contrib/build-wine/electrum.nsi @@ -72,7 +72,7 @@ !define MUI_ABORTWARNING !define MUI_ABORTWARNING_TEXT "Are you sure you wish to abort the installation of ${PRODUCT_NAME}?" - !define MUI_ICON "tmp\electrum-mona\icons\electrum.ico" + !define MUI_ICON "c:\electrum-mona\icons\electrum.ico" ;-------------------------------- ;Pages @@ -111,7 +111,7 @@ Section ;Files to pack into the installer File /r "dist\electrum-mona\*.*" - File "..\..\icons\electrum.ico" + File "c:\electrum-mona\icons\electrum.ico" ;Store installation folder WriteRegStr HKCU "Software\${PRODUCT_NAME}" "" $INSTDIR diff --git a/contrib/build-wine/prepare-wine.sh b/contrib/build-wine/prepare-wine.sh index 56585ee1c751..cc169a5181b7 100755 --- a/contrib/build-wine/prepare-wine.sh +++ b/contrib/build-wine/prepare-wine.sh @@ -1,6 +1,6 @@ #!/bin/bash -PYTHON_VERSION=3.5.4 +PYTHON_VERSION=3.6.6 # Please update these links carefully, some versions won't work under Wine NSIS_FILENAME=nsis-3.03-setup.exe NSIS_URL=https://prdownloads.sourceforge.net/nsis/$NSIS_FILENAME?download @@ -85,13 +85,13 @@ retry() { here=$(dirname $(readlink -e $0)) set -e -# Clean up Wine environment -echo "Cleaning $WINEPREFIX" -rm -rf $WINEPREFIX -echo "done" - wine 'wineboot' +# HACK to work around https://bugs.winehq.org/show_bug.cgi?id=42474#c22 +# needed for python 3.6+ +rm -f /opt/wine-stable/lib/wine/fakedlls/api-ms-win-core-path-l1-1-0.dll +rm -f /opt/wine-stable/lib/wine/api-ms-win-core-path-l1-1-0.dll.so + cd /tmp/electrum-mona-build # Install Python diff --git a/contrib/build-wine/unsign.sh b/contrib/build-wine/unsign.sh index 67bbeeda2471..5fe31eb2023a 100755 --- a/contrib/build-wine/unsign.sh +++ b/contrib/build-wine/unsign.sh @@ -14,7 +14,7 @@ set -e mkdir -p signed >/dev/null 2>&1 mkdir -p signed/stripped >/dev/null 2>&1 -version=`python3 -c "import electrum_mona; print(electrum.version.ELECTRUM_VERSION)"` +version=`python3 -c "import electrum; print(electrum.version.ELECTRUM_VERSION)"` echo "Found $(ls dist/*.exe | wc -w) files to verify." diff --git a/contrib/deterministic-build/requirements-binaries.txt b/contrib/deterministic-build/requirements-binaries.txt index b17d0d709d6f..02561924b036 100644 --- a/contrib/deterministic-build/requirements-binaries.txt +++ b/contrib/deterministic-build/requirements-binaries.txt @@ -1,42 +1,43 @@ pip==10.0.1 \ --hash=sha256:717cdffb2833be8409433a93746744b59505f42146e8d37de6c62b430e25d6d7 \ --hash=sha256:f2bd08e0cd1b06e10218feaf6fef299f473ba706582eb3bd9d52203fdbd7ee68 -pycryptodomex==3.6.1 \ - --hash=sha256:1869d7735f445bbf1681afa2acce10ad829857cfb7a4a7b702e484f222021892 \ - --hash=sha256:24e054190d2b11ad3b8517d186c0b3df6f902a5f5a91be8e4bb6a3fcdc65b2cf \ - --hash=sha256:26967d31fabb0d80cb2b254a7c0f55f8dec9931e8676891edd24aa5aaeb0d021 \ - --hash=sha256:2a341b57bb5844d53b8f632f79277cd534762f502fb73bff5dc1a2f615ff91ed \ - --hash=sha256:43d6eb014aba7be354f3e8fe2693fe96446f6791da2b9570e8d54d481e3ab224 \ - --hash=sha256:4c271577f4f8c5cced55a60f4504b34545121c14facb8fc357f89c24089c81fc \ - --hash=sha256:59721f2853df9cf2265304d3b6d6d8cebe3a86b1fddc00f2bfbf18eb2a48fb78 \ - --hash=sha256:63a77a1b27d12ed1c42f4e539d9dbe588a88b70ec64b55271cdf1f56c1223bd6 \ - --hash=sha256:6d04640386c55b9f44015747496c3b6582360b5b3b4e42f9ce3fc7c6840f80d0 \ - --hash=sha256:730bd75d90e16975a112ea79863ce1faa7703d3b54f10d77656e7dadf6be0ef6 \ - --hash=sha256:75a300aa86c56e9c19a7b476c397cb22fda3be7af4cf2f105990fdd94c52f486 \ - --hash=sha256:7c6f67005c6e421f02fd7fe9d95876094307b31628d728adc6c2e038e2ed9c09 \ - --hash=sha256:82b758f870c8dd859f9b58bc9cff007403b68742f9e0376e2cbd8aa2ad3baa83 \ - --hash=sha256:8528a958b746c4da767bfba5ac370250dcb741f4c69e55873bd6efe89ac07291 \ - --hash=sha256:93582ea5bc3e8f95cb36d9dd752c01452085b54b396e3ed775ac1793b8dc486a \ - --hash=sha256:94e0105ad8d82d3bf5a032c92fc03b01e3bc9ea40b58308c2da42f8cf8c16c47 \ - --hash=sha256:a65889424bf10a884ff031e7f3fd12273dd5b420ee08ca8fcfd431a2f6cbabc1 \ - --hash=sha256:a8467982d26bfb90089f50c3c5d9ed541b7fe9f9df20803fede70d5046cd4ff1 \ - --hash=sha256:ab497d4e7361511ede562ed3cd4528f46c005781bc23b1b943612d27bfb078c3 \ - --hash=sha256:bb05caf3f6cf41d964c01e08dfaddfe48086c7b3e96708d50647f0a29ff33f56 \ - --hash=sha256:c4643647f5656855975b2aaf70fe3aa1e0c1558f8d1b5de0c9a8ccac65114c57 \ - --hash=sha256:c550e20834b679ed0b7608c345a816f97047d2297aab4f4599f95edee5d16e99 \ - --hash=sha256:cc797712add76cd658110585481c380833637b68df1404190777ba715a81c9b9 \ - --hash=sha256:dff0c883d495bf45d18acc74938d1de4d6a08b3345acb9177a46c6997a578c44 \ - --hash=sha256:e4f69af1f5b46255ec7b8116a853879a55e8e6b595a73c39f14ca430c410c469 \ - --hash=sha256:f61d0d83e9dd974849f9b0826ec20f49dbd9ed233fd90bf2592be1337231418e \ - --hash=sha256:f65f21d2b616c30ad4ba801504343eb768fd0a2894c5f587e784201320556543 +pycryptodomex==3.6.4 \ + --hash=sha256:0461e88a7199f9e88f9f90c2c1e109e9e1f7bbb94dc6192e5df52829d31510c1 \ + --hash=sha256:08d0aba5a72e8af5da118ac4b6a5d75befceca7dd92a031b040ed5ff4417cec2 \ + --hash=sha256:0e22d47935d5fa95f556d5f5857576bc6750233964de06a840d58459010c3889 \ + --hash=sha256:10ef21d1728ec0b8afc4f8e1d8d9ea66f317154ea18731a4a05bd996cdc33fdf \ + --hash=sha256:1962b81eef81bf5c42d625816904a22a0bd23d15ca5d49891a54e3c0d0189d84 \ + --hash=sha256:24aae88efe3cbcb4a9cf840b2c352e7de1d6c2c5b3df37ff99b5c7e271e8f3a8 \ + --hash=sha256:43ad6d1d7ca545d53360bf412ee70fcb9ede876b4376fc6db06fc7328f70588c \ + --hash=sha256:4daabe7c0404e673b9029aa43761c779b9b4df2cbe11ccd94daded6a0acd8808 \ + --hash=sha256:4e15af025e02b04b0d0728e8248e4384d3dc7a3a89a020f5bd4d04ef2c5d9d4c \ + --hash=sha256:5b4d3c4a069a05972e0ed7111071bbcb4727ac652b5d7e8f786e8ea2fe63306b \ + --hash=sha256:67ad8b2ad15a99ae70e287454a112f67d2abaf160ee9c97f9daebf2296066447 \ + --hash=sha256:6d7e6fb69d9fd2c57e177f8a9cdf6489a725da77568e3d0a226c7dd18504396a \ + --hash=sha256:7907d7a5adde7cd07d19f129a4afa892b68b0b52a07eaf989e48e2677040b4bf \ + --hash=sha256:88210edafd564c8ff4a68716aaf0627e3bc43e9c192a33d6f5616743f72c2d9b \ + --hash=sha256:8a6b14a90bdcbcdc268acae87126c33bf4250d3842803a93a548d7c10135893a \ + --hash=sha256:94a10446ad61965516aecd610a2dd28d79ab1dfd8723903e1bd19ffa985c208e \ + --hash=sha256:99bda900a0bf6f9e6c69bdeb6114f7f6730b9d36a47bc1fe144263ce85bfc403 \ + --hash=sha256:9dae2e738622bd35ba82fe0b06f773be137a14e6b28defb2e36efc2d809cd28a \ + --hash=sha256:a04cd6021ff2756c38135a95f81b980485507bccbff4d2b8f62e537552270471 \ + --hash=sha256:a3b61625b60dd5e72556520a77464e2ac568c20b8ad12ea1f4443bf5051dc624 \ + --hash=sha256:a9a91fd9e7967a5bad88d542c9fce09323e15d16cb6fa9b8978390e46e68cbdf \ + --hash=sha256:afc44f1b595bd736ec3762dd9a2d0ef276a6ac560c85f643acfc4c0bf0c73384 \ + --hash=sha256:b5f3c8912b36e6abb843a51eecb414a1161f80c0ca0b65066c23aa449b5f98db \ + --hash=sha256:cc07c8b7686dd7093f33067a02b92f4fed860d75ad2bcc4e60624f70fdb94576 \ + --hash=sha256:da646eddbe026306fd1cb2c392a9aee4ebea13f2a9add9af303bb3151786a5d8 \ + --hash=sha256:df93eaccd5c09e6380fab8f15c06a89944415e4bb9af64a94f467ce4c782ff8e \ + --hash=sha256:e667303019770834354c75022ab0324d5ae5bf7cd7015939678033a58f87ee70 \ + --hash=sha256:f921219040ce994c9118b7218b7f7b4e9394e507c97cfc869ce5358437fc26cd PyQt5==5.10.1 \ --hash=sha256:1e652910bd1ffd23a3a48c510ecad23a57a853ed26b782cd54b16658e6f271ac \ --hash=sha256:4db7113f464c733a99fcb66c4c093a47cf7204ad3f8b3bda502efcc0839ac14b \ --hash=sha256:9c17ab3974c1fc7bbb04cc1c9dae780522c0ebc158613f3025fccae82227b5f7 \ --hash=sha256:f6035baa009acf45e5f460cf88f73580ad5dc0e72330029acd99e477f20a5d61 -setuptools==39.2.0 \ - --hash=sha256:8fca9275c89964f13da985c3656cb00ba029d7f3916b37990927ffdf264e7926 \ - --hash=sha256:f7cddbb5f5c640311eb00eab6e849f7701fa70bf6a183fc8a2c33dd1d1672fb2 +setuptools==40.0.0 \ + --hash=sha256:012adb8e25fbfd64c652e99e7bab58799a3aaf05d39ab38561f69190a909015f \ + --hash=sha256:d68abee4eed409fbe8c302ac4d8429a1ffef912cd047a903b5701c024048dd49 SIP==4.19.8 \ --hash=sha256:09f9a4e6c28afd0bafedb26ffba43375b97fe7207bd1a0d3513f79b7d168b331 \ --hash=sha256:105edaaa1c8aa486662226360bd3999b4b89dd56de3e314d82b83ed0587d8783 \ diff --git a/contrib/deterministic-build/requirements-hw.txt b/contrib/deterministic-build/requirements-hw.txt index a49cb6001f77..29fae2fdd9bb 100644 --- a/contrib/deterministic-build/requirements-hw.txt +++ b/contrib/deterministic-build/requirements-hw.txt @@ -9,36 +9,35 @@ chardet==3.0.4 \ click==6.7 \ --hash=sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d \ --hash=sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b -Cython==0.28.3 \ - --hash=sha256:0344e9352b0915910e212c38403b63f902ce1cba75dde7a43a9112ff960eb2a5 \ - --hash=sha256:0a390c39e912fc5f82d5feae2d16ea061971407099e1efb0fecb255cb96fbeff \ - --hash=sha256:0f2b2e09f94c498f555935e732b7321b5f62f00e7a789238f6c5ddd66987a54d \ - --hash=sha256:15614592616b6dd5e919e158796350ebeba6cb6b5d2998cfff41b53f568c8355 \ - --hash=sha256:1aae6d6e9858888144cea147eb5e677830f45faaff3d305d77378c3cba55f526 \ - --hash=sha256:200583297f23e558744bc4688d8a2b2605ab6ad7d1494a9fd8c8094ad65ebf3c \ - --hash=sha256:295facc211a6b55db9979455b856180f2839be22ab767ffdea55986bee83ca9f \ - --hash=sha256:36c16bf39280fe857213d8da31c07a6179d3878c3dc2e435dce0974b9f8f0729 \ - --hash=sha256:3fef8dfa9cf86ab7814ca31369374ddd5b9524f54406aa83b53b5937965b8e88 \ - --hash=sha256:439d233d3214e3d69c033a9a93516758f2c8a03e83ea51ae14b6eed13687d224 \ - --hash=sha256:455ab39c6c0849a6c008fcdf2fae42475f18d0801a3be229e8f75367bbe3b325 \ - --hash=sha256:56821e3791209e6a11992e294afbf7e3dcda7d4fd54d06396dd521928d3d14fe \ - --hash=sha256:62b594584889b33bbea7e71f9d7c5c6539091b341334ef7ca1ae7e30a9dd3e15 \ - --hash=sha256:70f81a75fb25c1c3c61843e3a6fe771a76c4ebf4d154455a7eff0740ad47dff4 \ - --hash=sha256:8011090beb09251cb4ece1e14263e574b38eda696b788552b369ad343373d0e9 \ - --hash=sha256:80d6a0369333a162fc32a22637f5870f3e87fb038c7b58860bbe00b05b58aa62 \ - --hash=sha256:85b04e32af58a3c008c0ba8169017770aaa342a5972b748f81d043d66363e437 \ - --hash=sha256:9ed273d82116fa148c92901b9639030e087979d455982bd7bf727fb486c0bd17 \ - --hash=sha256:a1af59e6c9b4acc07c429d8495fc016a35e0a1270f28c57317352f512df7e214 \ - --hash=sha256:b894ff4daf8dfaf657bf2d5e7190a4de11b2400b1e0fb0902974d35c23a26dea \ - --hash=sha256:c2659981150b4de04397dcfd4bff64e384d3ba25af60d1b22820fdf108298cb2 \ - --hash=sha256:c981a750858f1727995acf861ab030b267d264ca6efda2f01104941187a3675f \ - --hash=sha256:cc4152b19ec168391f7815d24b70c8911829ba281bd5fcd98cab9dc21abe62ff \ - --hash=sha256:d0f5b1668e7f7f6fc9849f49a20c5db10562a0ab29cd66818894dfebbca7b304 \ - --hash=sha256:d7152006ed1a3adb8f978077b57d237ddafa188240af53cd72b5c79e4ed000e3 \ - --hash=sha256:e5f877472993474296125c22b84c334b550010815e513cccce73da854a132d64 \ - --hash=sha256:e7c2c87ff2f99ed4be1bb046d6eddfb388af627928037f9e0a420c05daaf14ed \ - --hash=sha256:edd7d499685655031be5b4d33005096b6345f81eeb7ab9d2dd415db0c7bcf64e \ - --hash=sha256:f99a777fda569a88deea863eac2722b5e88957c4d5f4413949740da791857ac9 +Cython==0.28.4 \ + --hash=sha256:01487236575df8f17b46982071438dce4f7eaf8acc8fb99fca3510d343cd7a28 \ + --hash=sha256:0671d17c7a27634d6819246e535241b951141ed0e3f6f2a6d618fd32344dae3e \ + --hash=sha256:0e6190d6971c46729f712dd7307a9c0a8c027bfa5b4d8f2edef106b01759926c \ + --hash=sha256:202587c754901d0678bd6ff89c707f099987928239049a528470c06c6c922cf8 \ + --hash=sha256:345197ba9278cf6a914cb7421dc665a0531a219b0072abf6b0cebfdf68e75725 \ + --hash=sha256:3a296b8d6b02f0e01ab04bedea658f43eef5ad2f8e586a820226ead1a677d9b1 \ + --hash=sha256:484572a2b22823a967be106137a93f7d634db116b3f7accb37dbd760eda2fa9f \ + --hash=sha256:4c67c9c803e50ceff32cc5e4769c50fc8ae8df9c4e5cc592ce8310b5a1076d23 \ + --hash=sha256:539038087c321911745fc2e77049209b1231300d481cb4d682b2f95c724814b3 \ + --hash=sha256:58113e0683c3688594c112103d7e9f2d0092fd2d8297a220240bea22e184dfdd \ + --hash=sha256:65cb25ca4284804293a2404d1be3b5a98818be21a72791649bacbcfa4e431d41 \ + --hash=sha256:699e765da2580e34b08473fc0acef3a2d7bcb7f13eb29401cd25236bcf000080 \ + --hash=sha256:6b54c3470810cea49a8be90814d05c5325ceb9c5bf429fd86c36fc1b32dfc157 \ + --hash=sha256:71ac1629e4eae2ed329be8caf45efea10bfe1af3d8767e12e64b83e4ea5a3250 \ + --hash=sha256:722c179d3df8677f3daf45b1a2764678ed4f0aaddbaa7211a8a08ebfd907c0db \ + --hash=sha256:76ac2b08d3d956d77b574bb43cbf1d37bd58b9d50c04ba281303e695854ebc46 \ + --hash=sha256:7eff1157be9e26bf7494288c89979ca69d593a009e2c7420a739e2cf1e0635f5 \ + --hash=sha256:99546c8696d27d0efa639c77b2f8af6e61dc3a5073caae4f27ffd991ca926f42 \ + --hash=sha256:a0c263b31d335f29c11f4a9e98fbcd908d0731d4ea99bfd27c1c47caaeb4ca2e \ + --hash=sha256:a29c66292605bff962adc26530c030607aa699206b12dfb84f131b0454e15df4 \ + --hash=sha256:a4d3724c5a1ddd86d7d830d8e02c40151839b833791dd4b6fe9e144380fa7d37 \ + --hash=sha256:aed9f33b19d542eea56c38ef3862ca56147f7903648156cd57eabb0fe47c35d6 \ + --hash=sha256:b57e733dd8871d2cc7358c2e0fe33027453afffbcd0ea6a537f54877cad5131c \ + --hash=sha256:d5bf4db62236e82955c40bafbaa18d54b20b5ceefa06fb57c7facc443929f4bd \ + --hash=sha256:d9272dd71ab78e87fa34a0a59bbd6acc9a9c0005c834a6fc8457ff9619dc6795 \ + --hash=sha256:e9d5671bcbb90a41b0832fcb3872fcbaca3d68ff11ea09724dd6cbdf31d947fb \ + --hash=sha256:ee54646afb2b73b293c94cf079682d18d404ebd6c01122dc3980f111aec2d8ae \ + --hash=sha256:f16a87197939977824609005b73f9ebb291b9653a14e5f27afc1c5d6f981ba39 ecdsa==0.13 \ --hash=sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c \ --hash=sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa @@ -95,15 +94,15 @@ pyblake2==1.1.2 \ requests==2.19.1 \ --hash=sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1 \ --hash=sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a -setuptools==39.2.0 \ - --hash=sha256:8fca9275c89964f13da985c3656cb00ba029d7f3916b37990927ffdf264e7926 \ - --hash=sha256:f7cddbb5f5c640311eb00eab6e849f7701fa70bf6a183fc8a2c33dd1d1672fb2 +setuptools==40.0.0 \ + --hash=sha256:012adb8e25fbfd64c652e99e7bab58799a3aaf05d39ab38561f69190a909015f \ + --hash=sha256:d68abee4eed409fbe8c302ac4d8429a1ffef912cd047a903b5701c024048dd49 six==1.11.0 \ --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \ --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb -trezor==0.10.1 \ - --hash=sha256:09b4edfa83b787975c6f30728c13bb413621d5bdf722231748758ba0181b8a60 \ - --hash=sha256:5bcad3e97129fccd6f8b4cf08f81862e423373617c857feb492cfa1b1807844e +trezor==0.10.2 \ + --hash=sha256:4dba4d5c53d3ca22884d79fb4aa68905fb8353a5da5f96c734645d8cf537138d \ + --hash=sha256:d2b32f25982ab403758d870df1d0de86d0751c106ef1cd1289f452880ce68b84 urllib3==1.23 \ --hash=sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf \ --hash=sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5 diff --git a/contrib/deterministic-build/requirements.txt b/contrib/deterministic-build/requirements.txt index a7dfb83a3931..8f0168ea087d 100644 --- a/contrib/deterministic-build/requirements.txt +++ b/contrib/deterministic-build/requirements.txt @@ -41,15 +41,18 @@ pyaes==1.6.1 \ --hash=sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f PySocks==1.6.8 \ --hash=sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672 +QDarkStyle==2.5.4 \ + --hash=sha256:3eb60922b8c4d9cedecb6897ca4c9f8a259d81bdefe5791976ccdf12432de1f0 \ + --hash=sha256:51331fc6490b38c376e6ba8d8c814320c8d2d1c2663055bc396321a7c28fa8be qrcode==6.0 \ --hash=sha256:037b0db4c93f44586e37f84c3da3f763874fcac85b2974a69a98e399ac78e1bf \ --hash=sha256:de4ffc15065e6ff20a551ad32b6b41264f3c75275675406ddfa8e3530d154be3 requests==2.19.1 \ --hash=sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1 \ --hash=sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a -setuptools==39.2.0 \ - --hash=sha256:8fca9275c89964f13da985c3656cb00ba029d7f3916b37990927ffdf264e7926 \ - --hash=sha256:f7cddbb5f5c640311eb00eab6e849f7701fa70bf6a183fc8a2c33dd1d1672fb2 +setuptools==40.0.0 \ + --hash=sha256:012adb8e25fbfd64c652e99e7bab58799a3aaf05d39ab38561f69190a909015f \ + --hash=sha256:d68abee4eed409fbe8c302ac4d8429a1ffef912cd047a903b5701c024048dd49 six==1.11.0 \ --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 \ --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb diff --git a/contrib/make_apk b/contrib/make_apk index d80ddc382269..773aeab548d2 100755 --- a/contrib/make_apk +++ b/contrib/make_apk @@ -1,6 +1,6 @@ #!/bin/bash -pushd ./gui/kivy/ +pushd ./electrum/gui/kivy/ if [[ -n "$1" && "$1" == "release" ]] ; then echo -n Keystore Password: diff --git a/contrib/make_download b/contrib/make_download index 8560ce7e9bbe..d06e4b73f471 100755 --- a/contrib/make_download +++ b/contrib/make_download @@ -3,7 +3,7 @@ import re import os import sys -from electrum_mona.version import ELECTRUM_VERSION, APK_VERSION +from electrum.version import ELECTRUM_VERSION, APK_VERSION print("version", ELECTRUM_VERSION) dirname = sys.argv[1] diff --git a/contrib/make_locale b/contrib/make_locale index 3ab4b21cf206..3c28d5702076 100755 --- a/contrib/make_locale +++ b/contrib/make_locale @@ -8,8 +8,7 @@ import requests os.chdir(os.path.dirname(os.path.realpath(__file__))) os.chdir('..') -code_directories = 'gui plugins lib' -cmd = "find {} -type f -name '*.py' -o -name '*.kv'".format(code_directories) +cmd = "find electrum -type f -name '*.py' -o -name '*.kv'" files = subprocess.check_output(cmd, shell=True) @@ -19,13 +18,13 @@ with open("app.fil", "wb") as f: print("Found {} files to translate".format(len(files.splitlines()))) # Generate fresh translation template -if not os.path.exists('lib/locale'): - os.mkdir('lib/locale') -cmd = 'xgettext -s --from-code UTF-8 --language Python --no-wrap -f app.fil --output=lib/locale/messages.pot' +if not os.path.exists('electrum/locale'): + os.mkdir('electrum/locale') +cmd = 'xgettext -s --from-code UTF-8 --language Python --no-wrap -f app.fil --output=electrum/locale/messages.pot' print('Generate template') os.system(cmd) -os.chdir('lib') +os.chdir('electrum') crowdin_identifier = 'electrum' crowdin_file_name = 'files[electrum-client/messages.pot]' @@ -55,7 +54,7 @@ if crowdin_api_key: # Download & unzip print('Download translations') -s = requests.request('GET', 'https://crowdin.com/download/project/' + crowdin_identifier + '.zip').content +s = requests.request('GET', 'https://crowdin.com/backend/download/project/' + crowdin_identifier + '.zip').content zfobj = zipfile.ZipFile(io.BytesIO(s)) print('Unzip translations') diff --git a/contrib/requirements/requirements-binaries.txt b/contrib/requirements/requirements-binaries.txt index 10a1c8d94910..9faf682e9696 100644 --- a/contrib/requirements/requirements-binaries.txt +++ b/contrib/requirements/requirements-binaries.txt @@ -1,2 +1,2 @@ -PyQt5 +PyQt5<5.11 pycryptodomex diff --git a/contrib/requirements/requirements.txt b/contrib/requirements/requirements.txt index 031379e048a0..b98fdb70ae2c 100644 --- a/contrib/requirements/requirements.txt +++ b/contrib/requirements/requirements.txt @@ -1,6 +1,5 @@ pyaes>=0.1a1 ecdsa>=0.9 -pbkdf2 requests qrcode protobuf diff --git a/electrum-env b/electrum-env index 5fb8de02399d..71dfd595837d 100755 --- a/electrum-env +++ b/electrum-env @@ -22,6 +22,6 @@ fi export PYTHONPATH="/usr/local/lib/python${PYTHON_VER}/site-packages:$PYTHONPATH" -./electrum-mona "$@" +./run_electrum "$@" deactivate diff --git a/lib/__init__.py b/electrum/__init__.py similarity index 87% rename from lib/__init__.py rename to electrum/__init__.py index 286e4b6af826..48a60c15c3f4 100644 --- a/lib/__init__.py +++ b/electrum/__init__.py @@ -1,6 +1,6 @@ from .version import ELECTRUM_VERSION from .util import format_satoshis, print_msg, print_error, set_verbosity -from .wallet import Synchronizer, Wallet +from .wallet import Wallet from .storage import WalletStorage from .coinchooser import COIN_CHOOSERS from .network import Network, pick_random_server @@ -10,5 +10,5 @@ from . import transaction from . import daemon from .transaction import Transaction -from .plugins import BasePlugin +from .plugin import BasePlugin from .commands import Commands, known_commands diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py new file mode 100644 index 000000000000..bbc8b0b2e412 --- /dev/null +++ b/electrum/address_synchronizer.py @@ -0,0 +1,494 @@ +# Electrum - lightweight Bitcoin client +# Copyright (C) 2018 The Electrum Developers +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import threading +import itertools +from collections import defaultdict + +from .util import PrintError, profiler +from .transaction import Transaction +from .synchronizer import Synchronizer +from .verifier import SPV + +TX_HEIGHT_LOCAL = -2 +TX_HEIGHT_UNCONF_PARENT = -1 +TX_HEIGHT_UNCONFIRMED = 0 + +class AddTransactionException(Exception): + pass + + +class UnrelatedTransactionException(AddTransactionException): + def __str__(self): + return _("Transaction is unrelated to this wallet.") + +class AddressSynchronizer(PrintError): + """ + inherited by wallet + """ + + def __init__(self, storage): + self.storage = storage + self.network = None + # verifier (SPV) and synchronizer are started in start_threads + self.synchronizer = None + self.verifier = None + # locks: if you need to take multiple ones, acquire them in the order they are defined here! + self.lock = threading.RLock() + self.transaction_lock = threading.RLock() + # address -> list(txid, height) + self.history = storage.get('addr_history',{}) + # Verified transactions. txid -> (height, timestamp, block_pos). Access with self.lock. + self.verified_tx = storage.get('verified_tx3', {}) + # Transactions pending verification. txid -> tx_height. Access with self.lock. + self.unverified_tx = defaultdict(int) + # true when synchronized + self.up_to_date = False + self.load_transactions() + self.load_local_history() + self.load_unverified_transactions() + self.remove_local_transactions_we_dont_have() + + def load_unverified_transactions(self): + # review transactions that are in the history + for addr, hist in self.history.items(): + for tx_hash, tx_height in hist: + # add it in case it was previously unconfirmed + self.add_unverified_tx(tx_hash, tx_height) + + def start_threads(self, network): + self.network = network + if self.network is not None: + self.verifier = SPV(self.network, self) + self.synchronizer = Synchronizer(self, network) + network.add_jobs([self.verifier, self.synchronizer]) + else: + self.verifier = None + self.synchronizer = None + + def stop_threads(self): + if self.network: + self.network.remove_jobs([self.synchronizer, self.verifier]) + self.synchronizer.release() + self.synchronizer = None + self.verifier = None + # Now no references to the synchronizer or verifier + # remain so they will be GC-ed + self.storage.put('stored_height', self.get_local_height()) + self.save_transactions() + self.save_verified_tx() + self.storage.write() + + def add_address(self, address): + if address not in self.history: + self.history[address] = [] + self.set_up_to_date(False) + if self.synchronizer: + self.synchronizer.add(address) + + def get_conflicting_transactions(self, tx): + """Returns a set of transaction hashes from the wallet history that are + directly conflicting with tx, i.e. they have common outpoints being + spent with tx. If the tx is already in wallet history, that will not be + reported as a conflict. + """ + conflicting_txns = set() + with self.transaction_lock: + for txin in tx.inputs(): + if txin['type'] == 'coinbase': + continue + prevout_hash = txin['prevout_hash'] + prevout_n = txin['prevout_n'] + spending_tx_hash = self.spent_outpoints[prevout_hash].get(prevout_n) + if spending_tx_hash is None: + continue + # this outpoint has already been spent, by spending_tx + assert spending_tx_hash in self.transactions + conflicting_txns |= {spending_tx_hash} + txid = tx.txid() + if txid in conflicting_txns: + # this tx is already in history, so it conflicts with itself + if len(conflicting_txns) > 1: + raise Exception('Found conflicting transactions already in wallet history.') + conflicting_txns -= {txid} + return conflicting_txns + + def add_transaction(self, tx_hash, tx, allow_unrelated=False): + assert tx_hash, tx_hash + assert tx, tx + assert tx.is_complete() + # we need self.transaction_lock but get_tx_height will take self.lock + # so we need to take that too here, to enforce order of locks + with self.lock, self.transaction_lock: + # NOTE: returning if tx in self.transactions might seem like a good idea + # BUT we track is_mine inputs in a txn, and during subsequent calls + # of add_transaction tx, we might learn of more-and-more inputs of + # being is_mine, as we roll the gap_limit forward + is_coinbase = tx.inputs()[0]['type'] == 'coinbase' + tx_height = self.get_tx_height(tx_hash)[0] + if not allow_unrelated: + # note that during sync, if the transactions are not properly sorted, + # it could happen that we think tx is unrelated but actually one of the inputs is is_mine. + # this is the main motivation for allow_unrelated + is_mine = any([self.is_mine(self.get_txin_address(txin)) for txin in tx.inputs()]) + is_for_me = any([self.is_mine(self.get_txout_address(txo)) for txo in tx.outputs()]) + if not is_mine and not is_for_me: + raise UnrelatedTransactionException() + # Find all conflicting transactions. + # In case of a conflict, + # 1. confirmed > mempool > local + # 2. this new txn has priority over existing ones + # When this method exits, there must NOT be any conflict, so + # either keep this txn and remove all conflicting (along with dependencies) + # or drop this txn + conflicting_txns = self.get_conflicting_transactions(tx) + if conflicting_txns: + existing_mempool_txn = any( + self.get_tx_height(tx_hash2)[0] in (TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT) + for tx_hash2 in conflicting_txns) + existing_confirmed_txn = any( + self.get_tx_height(tx_hash2)[0] > 0 + for tx_hash2 in conflicting_txns) + if existing_confirmed_txn and tx_height <= 0: + # this is a non-confirmed tx that conflicts with confirmed txns; drop. + return False + if existing_mempool_txn and tx_height == TX_HEIGHT_LOCAL: + # this is a local tx that conflicts with non-local txns; drop. + return False + # keep this txn and remove all conflicting + to_remove = set() + to_remove |= conflicting_txns + for conflicting_tx_hash in conflicting_txns: + to_remove |= self.get_depending_transactions(conflicting_tx_hash) + for tx_hash2 in to_remove: + self.remove_transaction(tx_hash2) + # add inputs + def add_value_from_prev_output(): + dd = self.txo.get(prevout_hash, {}) + # note: this nested loop takes linear time in num is_mine outputs of prev_tx + for addr, outputs in dd.items(): + # note: instead of [(n, v, is_cb), ...]; we could store: {n -> (v, is_cb)} + for n, v, is_cb in outputs: + if n == prevout_n: + if addr and self.is_mine(addr): + if d.get(addr) is None: + d[addr] = set() + d[addr].add((ser, v)) + return + self.txi[tx_hash] = d = {} + for txi in tx.inputs(): + if txi['type'] == 'coinbase': + continue + prevout_hash = txi['prevout_hash'] + prevout_n = txi['prevout_n'] + ser = prevout_hash + ':%d' % prevout_n + self.spent_outpoints[prevout_hash][prevout_n] = tx_hash + add_value_from_prev_output() + # add outputs + self.txo[tx_hash] = d = {} + for n, txo in enumerate(tx.outputs()): + v = txo[2] + ser = tx_hash + ':%d'%n + addr = self.get_txout_address(txo) + if addr and self.is_mine(addr): + if d.get(addr) is None: + d[addr] = [] + d[addr].append((n, v, is_coinbase)) + # give v to txi that spends me + next_tx = self.spent_outpoints[tx_hash].get(n) + if next_tx is not None: + dd = self.txi.get(next_tx, {}) + if dd.get(addr) is None: + dd[addr] = set() + if (ser, v) not in dd[addr]: + dd[addr].add((ser, v)) + self._add_tx_to_local_history(next_tx) + # add to local history + self._add_tx_to_local_history(tx_hash) + # save + self.transactions[tx_hash] = tx + return True + + def remove_transaction(self, tx_hash): + def remove_from_spent_outpoints(): + # undo spends in spent_outpoints + if tx is not None: # if we have the tx, this branch is faster + for txin in tx.inputs(): + if txin['type'] == 'coinbase': + continue + prevout_hash = txin['prevout_hash'] + prevout_n = txin['prevout_n'] + self.spent_outpoints[prevout_hash].pop(prevout_n, None) + if not self.spent_outpoints[prevout_hash]: + self.spent_outpoints.pop(prevout_hash) + else: # expensive but always works + for prevout_hash, d in list(self.spent_outpoints.items()): + for prevout_n, spending_txid in d.items(): + if spending_txid == tx_hash: + self.spent_outpoints[prevout_hash].pop(prevout_n, None) + if not self.spent_outpoints[prevout_hash]: + self.spent_outpoints.pop(prevout_hash) + # Remove this tx itself; if nothing spends from it. + # It is not so clear what to do if other txns spend from it, but it will be + # removed when those other txns are removed. + if not self.spent_outpoints[tx_hash]: + self.spent_outpoints.pop(tx_hash) + + with self.transaction_lock: + self.print_error("removing tx from history", tx_hash) + tx = self.transactions.pop(tx_hash, None) + remove_from_spent_outpoints() + self._remove_tx_from_local_history(tx_hash) + self.txi.pop(tx_hash, None) + self.txo.pop(tx_hash, None) + + def receive_tx_callback(self, tx_hash, tx, tx_height): + self.add_unverified_tx(tx_hash, tx_height) + self.add_transaction(tx_hash, tx, allow_unrelated=True) + + def receive_history_callback(self, addr, hist, tx_fees): + with self.lock: + old_hist = self.get_address_history(addr) + for tx_hash, height in old_hist: + if (tx_hash, height) not in hist: + # make tx local + self.unverified_tx.pop(tx_hash, None) + self.verified_tx.pop(tx_hash, None) + if self.verifier: + self.verifier.remove_spv_proof_for_tx(tx_hash) + self.history[addr] = hist + + for tx_hash, tx_height in hist: + # add it in case it was previously unconfirmed + self.add_unverified_tx(tx_hash, tx_height) + # if addr is new, we have to recompute txi and txo + tx = self.transactions.get(tx_hash) + if tx is None: + continue + self.add_transaction(tx_hash, tx, allow_unrelated=True) + + # Store fees + self.tx_fees.update(tx_fees) + + @profiler + def load_transactions(self): + # load txi, txo, tx_fees + self.txi = self.storage.get('txi', {}) + for txid, d in list(self.txi.items()): + for addr, lst in d.items(): + self.txi[txid][addr] = set([tuple(x) for x in lst]) + self.txo = self.storage.get('txo', {}) + self.tx_fees = self.storage.get('tx_fees', {}) + tx_list = self.storage.get('transactions', {}) + # load transactions + self.transactions = {} + for tx_hash, raw in tx_list.items(): + tx = Transaction(raw) + self.transactions[tx_hash] = tx + if self.txi.get(tx_hash) is None and self.txo.get(tx_hash) is None: + self.print_error("removing unreferenced tx", tx_hash) + self.transactions.pop(tx_hash) + # load spent_outpoints + _spent_outpoints = self.storage.get('spent_outpoints', {}) + self.spent_outpoints = defaultdict(dict) + for prevout_hash, d in _spent_outpoints.items(): + for prevout_n_str, spending_txid in d.items(): + prevout_n = int(prevout_n_str) + self.spent_outpoints[prevout_hash][prevout_n] = spending_txid + + @profiler + def load_local_history(self): + self._history_local = {} # address -> set(txid) + for txid in itertools.chain(self.txi, self.txo): + self._add_tx_to_local_history(txid) + + def remove_local_transactions_we_dont_have(self): + txid_set = set(self.txi) | set(self.txo) + for txid in txid_set: + tx_height = self.get_tx_height(txid)[0] + if tx_height == TX_HEIGHT_LOCAL and txid not in self.transactions: + self.remove_transaction(txid) + + @profiler + def save_transactions(self, write=False): + with self.transaction_lock: + tx = {} + for k,v in self.transactions.items(): + tx[k] = str(v) + self.storage.put('transactions', tx) + self.storage.put('txi', self.txi) + self.storage.put('txo', self.txo) + self.storage.put('tx_fees', self.tx_fees) + self.storage.put('addr_history', self.history) + self.storage.put('spent_outpoints', self.spent_outpoints) + if write: + self.storage.write() + + def save_verified_tx(self, write=False): + with self.lock: + self.storage.put('verified_tx3', self.verified_tx) + if write: + self.storage.write() + + def clear_history(self): + with self.lock: + with self.transaction_lock: + self.txi = {} + self.txo = {} + self.tx_fees = {} + self.spent_outpoints = defaultdict(dict) + self.history = {} + self.verified_tx = {} + self.transactions = {} + self.save_transactions() + + def get_history(self, domain=None): + # get domain + if domain is None: + domain = self.get_addresses() + domain = set(domain) + # 1. Get the history of each address in the domain, maintain the + # delta of a tx as the sum of its deltas on domain addresses + tx_deltas = defaultdict(int) + for addr in domain: + h = self.get_address_history(addr) + for tx_hash, height in h: + delta = self.get_tx_delta(tx_hash, addr) + if delta is None or tx_deltas[tx_hash] is None: + tx_deltas[tx_hash] = None + else: + tx_deltas[tx_hash] += delta + # 2. create sorted history + history = [] + for tx_hash in tx_deltas: + delta = tx_deltas[tx_hash] + height, conf, timestamp = self.get_tx_height(tx_hash) + history.append((tx_hash, height, conf, timestamp, delta)) + history.sort(key = lambda x: self.get_txpos(x[0])) + history.reverse() + # 3. add balance + c, u, x = self.get_balance(domain) + balance = c + u + x + h2 = [] + for tx_hash, height, conf, timestamp, delta in history: + h2.append((tx_hash, height, conf, timestamp, delta, balance)) + if balance is None or delta is None: + balance = None + else: + balance -= delta + h2.reverse() + # fixme: this may happen if history is incomplete + if balance not in [None, 0]: + self.print_error("Error: history not synchronized") + return [] + + return h2 + + def _add_tx_to_local_history(self, txid): + with self.transaction_lock: + for addr in itertools.chain(self.txi.get(txid, []), self.txo.get(txid, [])): + cur_hist = self._history_local.get(addr, set()) + cur_hist.add(txid) + self._history_local[addr] = cur_hist + + def _remove_tx_from_local_history(self, txid): + with self.transaction_lock: + for addr in itertools.chain(self.txi.get(txid, []), self.txo.get(txid, [])): + cur_hist = self._history_local.get(addr, set()) + try: + cur_hist.remove(txid) + except KeyError: + pass + else: + self._history_local[addr] = cur_hist + + def add_unverified_tx(self, tx_hash, tx_height): + if tx_height in (TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT) \ + and tx_hash in self.verified_tx: + with self.lock: + self.verified_tx.pop(tx_hash) + if self.verifier: + self.verifier.remove_spv_proof_for_tx(tx_hash) + + # tx will be verified only if height > 0 + if tx_hash not in self.verified_tx: + with self.lock: + self.unverified_tx[tx_hash] = tx_height + + def add_verified_tx(self, tx_hash, info): + # Remove from the unverified map and add to the verified map + with self.lock: + self.unverified_tx.pop(tx_hash, None) + self.verified_tx[tx_hash] = info # (tx_height, timestamp, pos) + height, conf, timestamp = self.get_tx_height(tx_hash) + self.network.trigger_callback('verified', tx_hash, height, conf, timestamp) + + def get_unverified_txs(self): + '''Returns a map from tx hash to transaction height''' + with self.lock: + return dict(self.unverified_tx) # copy + + def undo_verifications(self, blockchain, height): + '''Used by the verifier when a reorg has happened''' + txs = set() + with self.lock: + for tx_hash, item in list(self.verified_tx.items()): + tx_height, timestamp, pos = item + if tx_height >= height: + header = blockchain.read_header(tx_height) + # fixme: use block hash, not timestamp + if not header or header.get('timestamp') != timestamp: + self.verified_tx.pop(tx_hash, None) + txs.add(tx_hash) + return txs + + def get_local_height(self): + """ return last known height if we are offline """ + return self.network.get_local_height() if self.network else self.storage.get('stored_height', 0) + + def get_tx_height(self, tx_hash): + """ Given a transaction, returns (height, conf, timestamp) """ + with self.lock: + if tx_hash in self.verified_tx: + height, timestamp, pos = self.verified_tx[tx_hash] + conf = max(self.get_local_height() - height + 1, 0) + return height, conf, timestamp + elif tx_hash in self.unverified_tx: + height = self.unverified_tx[tx_hash] + return height, 0, None + else: + # local transaction + return TX_HEIGHT_LOCAL, 0, None + + def set_up_to_date(self, up_to_date): + with self.lock: + self.up_to_date = up_to_date + if up_to_date: + self.save_transactions(write=True) + # if the verifier is also up to date, persist that too; + # otherwise it will persist its results when it finishes + if self.verifier and self.verifier.is_up_to_date(): + self.save_verified_tx(write=True) + + def is_up_to_date(self): + with self.lock: return self.up_to_date diff --git a/lib/base_crash_reporter.py b/electrum/base_crash_reporter.py similarity index 98% rename from lib/base_crash_reporter.py rename to electrum/base_crash_reporter.py index 98d6d0a45355..ba3f77eb332b 100644 --- a/lib/base_crash_reporter.py +++ b/electrum/base_crash_reporter.py @@ -28,8 +28,9 @@ import requests -from electrum_mona import ELECTRUM_VERSION, constants -from electrum_mona.i18n import _ +from .version import ELECTRUM_VERSION +from .import constants +from .i18n import _ class BaseCrashReporter(object): diff --git a/lib/base_wizard.py b/electrum/base_wizard.py similarity index 98% rename from lib/base_wizard.py rename to electrum/base_wizard.py index 72ce5b9542e4..5d734071ea40 100644 --- a/lib/base_wizard.py +++ b/electrum/base_wizard.py @@ -348,7 +348,7 @@ def on_hw_derivation(self, name, device_info, derivation, xtype): k = hardware_keystore(d) self.on_keystore(k) - def passphrase_dialog(self, run_next): + def passphrase_dialog(self, run_next, is_restoring=False): title = _('Seed extension') message = '\n'.join([ _('You may extend your seed with custom words.'), @@ -358,7 +358,10 @@ def passphrase_dialog(self, run_next): _('Note that this is NOT your encryption password.'), _('If you do not know what this is, leave this field empty.'), ]) - self.line_dialog(title=title, message=message, warning=warning, default='', test=lambda x:True, run_next=run_next) + warn_issue4566 = is_restoring and self.seed_type == 'bip39' + self.line_dialog(title=title, message=message, warning=warning, + default='', test=lambda x:True, run_next=run_next, + warn_issue4566=warn_issue4566) def restore_from_seed(self): self.opt_bip39 = True @@ -371,10 +374,10 @@ def on_restore_seed(self, seed, is_bip39, is_ext): self.seed_type = 'bip39' if is_bip39 else bitcoin.seed_type(seed) if self.seed_type == 'bip39': f = lambda passphrase: self.on_restore_bip39(seed, passphrase) - self.passphrase_dialog(run_next=f) if is_ext else f('') + self.passphrase_dialog(run_next=f, is_restoring=True) if is_ext else f('') elif self.seed_type in ['standard', 'segwit']: f = lambda passphrase: self.run('create_keystore', seed, passphrase) - self.passphrase_dialog(run_next=f) if is_ext else f('') + self.passphrase_dialog(run_next=f, is_restoring=True) if is_ext else f('') elif self.seed_type == 'old': self.run('create_keystore', seed, '') elif self.seed_type == '2fa': diff --git a/lib/bitcoin.py b/electrum/bitcoin.py similarity index 100% rename from lib/bitcoin.py rename to electrum/bitcoin.py diff --git a/lib/blockchain.py b/electrum/blockchain.py similarity index 98% rename from lib/blockchain.py rename to electrum/blockchain.py index 9cdcab3df6ad..dc08e586c5ee 100644 --- a/lib/blockchain.py +++ b/electrum/blockchain.py @@ -42,6 +42,8 @@ class MissingHeader(Exception): pass +class InvalidHeader(Exception): + pass def serialize_header(res): s = int_to_hex(res.get('version'), 4) \ @@ -54,9 +56,9 @@ def serialize_header(res): def deserialize_header(s, height): if not s: - raise Exception('Invalid header: {}'.format(s)) + raise InvalidHeader('Invalid header: {}'.format(s)) if len(s) != 80: - raise Exception('Invalid header length: {}'.format(len(s))) + raise InvalidHeader('Invalid header length: {}'.format(len(s))) hex_to_int = lambda s: int('0x' + bh2u(s[::-1]), 16) h = {} h['version'] = hex_to_int(s[0:4]) diff --git a/lib/checkpoints.json b/electrum/checkpoints.json similarity index 100% rename from lib/checkpoints.json rename to electrum/checkpoints.json diff --git a/lib/checkpoints_testnet.json b/electrum/checkpoints_testnet.json similarity index 100% rename from lib/checkpoints_testnet.json rename to electrum/checkpoints_testnet.json diff --git a/lib/coinchooser.py b/electrum/coinchooser.py similarity index 100% rename from lib/coinchooser.py rename to electrum/coinchooser.py diff --git a/lib/commands.py b/electrum/commands.py similarity index 99% rename from lib/commands.py rename to electrum/commands.py index 8613f7bbeea7..c505b6a205f4 100644 --- a/lib/commands.py +++ b/electrum/commands.py @@ -35,12 +35,12 @@ from .import util, ecc from .util import bfh, bh2u, format_satoshis, json_decode, print_error, json_encode -from .import bitcoin +from . import bitcoin from .bitcoin import is_address, hash_160, COIN, TYPE_ADDRESS from .i18n import _ from .transaction import Transaction, multisig_script from .paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED -from .plugins import run_hook +from .plugin import run_hook known_commands = {} diff --git a/lib/constants.py b/electrum/constants.py similarity index 100% rename from lib/constants.py rename to electrum/constants.py diff --git a/lib/contacts.py b/electrum/contacts.py similarity index 100% rename from lib/contacts.py rename to electrum/contacts.py diff --git a/lib/crypto.py b/electrum/crypto.py similarity index 100% rename from lib/crypto.py rename to electrum/crypto.py diff --git a/lib/currencies.json b/electrum/currencies.json similarity index 100% rename from lib/currencies.json rename to electrum/currencies.json diff --git a/lib/daemon.py b/electrum/daemon.py similarity index 98% rename from lib/daemon.py rename to electrum/daemon.py index 71babd4c9c57..ccdce4a0a81c 100644 --- a/lib/daemon.py +++ b/electrum/daemon.py @@ -41,7 +41,7 @@ from .commands import known_commands, Commands from .simple_config import SimpleConfig from .exchange_rate import FxThread -from .plugins import run_hook +from .plugin import run_hook def get_lockfile(config): @@ -307,7 +307,7 @@ def init_gui(self, config, plugins): gui_name = config.get('gui', 'qt') if gui_name in ['lite', 'classic']: gui_name = 'qt' - gui = __import__('electrum_mona_gui.' + gui_name, fromlist=['electrum_mona_gui']) + gui = __import__('electrum.gui.' + gui_name, fromlist=['electrum']) self.gui = gui.ElectrumGui(config, self, plugins) try: self.gui.main() diff --git a/lib/dnssec.py b/electrum/dnssec.py similarity index 100% rename from lib/dnssec.py rename to electrum/dnssec.py diff --git a/lib/ecc.py b/electrum/ecc.py similarity index 100% rename from lib/ecc.py rename to electrum/ecc.py diff --git a/lib/ecc_fast.py b/electrum/ecc_fast.py similarity index 100% rename from lib/ecc_fast.py rename to electrum/ecc_fast.py diff --git a/electrum/electrum-mona b/electrum/electrum-mona new file mode 120000 index 000000000000..74bf81ab6819 --- /dev/null +++ b/electrum/electrum-mona @@ -0,0 +1 @@ +../run_electrum \ No newline at end of file diff --git a/lib/exchange_rate.py b/electrum/exchange_rate.py similarity index 100% rename from lib/exchange_rate.py rename to electrum/exchange_rate.py diff --git a/gui/__init__.py b/electrum/gui/__init__.py similarity index 100% rename from gui/__init__.py rename to electrum/gui/__init__.py diff --git a/gui/kivy/Makefile b/electrum/gui/kivy/Makefile similarity index 51% rename from gui/kivy/Makefile rename to electrum/gui/kivy/Makefile index 1838e9431e01..a8acc309a9bd 100644 --- a/gui/kivy/Makefile +++ b/electrum/gui/kivy/Makefile @@ -8,25 +8,25 @@ theming: $(PYTHON) -m kivy.atlas theming/light 1024 theming/light/*.png prepare: # running pre build setup - @cp tools/buildozer.spec ../../buildozer.spec - # copy electrum-mona to main.py - @cp ../../electrum-mona ../../main.py + @cp tools/buildozer.spec ../../../buildozer.spec + # copy electrum to main.py + @cp ../../../run_electrum ../../../main.py @-if [ ! -d "../../.buildozer" ];then \ - cd ../..; buildozer android debug;\ - cp -f gui/kivy/tools/blacklist.txt .buildozer/android/platform/python-for-android/src/blacklist.txt;\ + cd ../../..; buildozer android debug;\ + cp -f electrum/gui/kivy/tools/blacklist.txt .buildozer/android/platform/python-for-android/src/blacklist.txt;\ rm -rf ./.buildozer/android/platform/python-for-android/dist;\ fi apk: @make prepare - @-cd ../..; buildozer android debug deploy run + @-cd ../../..; buildozer android debug deploy run @make clean release: @make prepare - @-cd ../..; buildozer android release + @-cd ../../..; buildozer android release @make clean clean: # Cleaning up # rename main.py to electrum-mona - @-rm ../../main.py + @-rm ../../../main.py # remove buildozer.spec - @-rm ../../buildozer.spec + @-rm ../../../buildozer.spec diff --git a/gui/kivy/Readme.md b/electrum/gui/kivy/Readme.md similarity index 95% rename from gui/kivy/Readme.md rename to electrum/gui/kivy/Readme.md index f8d881ce6dc9..4c151acccda1 100644 --- a/gui/kivy/Readme.md +++ b/electrum/gui/kivy/Readme.md @@ -112,15 +112,7 @@ e.g. those needed in the next step. ~/.buildozer/android/platform/android-sdk-20/tools/android update sdk -u -t build-tools-27.0.3,android-19,extra-android-m2repository -## 9. Set apk version - -Create a file `contrib/versions.py` with contents similar to: -``` -version_apk = '3.1.999' -``` -This will be the version of the Android app. - -## 10. Build the APK +## 9. Build the APK ```sh contrib/make_apk diff --git a/gui/kivy/__init__.py b/electrum/gui/kivy/__init__.py similarity index 100% rename from gui/kivy/__init__.py rename to electrum/gui/kivy/__init__.py diff --git a/gui/kivy/data/background.png b/electrum/gui/kivy/data/background.png similarity index 100% rename from gui/kivy/data/background.png rename to electrum/gui/kivy/data/background.png diff --git a/gui/kivy/data/fonts/Roboto-Bold.ttf b/electrum/gui/kivy/data/fonts/Roboto-Bold.ttf similarity index 100% rename from gui/kivy/data/fonts/Roboto-Bold.ttf rename to electrum/gui/kivy/data/fonts/Roboto-Bold.ttf diff --git a/gui/kivy/data/fonts/Roboto-Condensed.ttf b/electrum/gui/kivy/data/fonts/Roboto-Condensed.ttf similarity index 100% rename from gui/kivy/data/fonts/Roboto-Condensed.ttf rename to electrum/gui/kivy/data/fonts/Roboto-Condensed.ttf diff --git a/gui/kivy/data/fonts/Roboto-Medium.ttf b/electrum/gui/kivy/data/fonts/Roboto-Medium.ttf similarity index 100% rename from gui/kivy/data/fonts/Roboto-Medium.ttf rename to electrum/gui/kivy/data/fonts/Roboto-Medium.ttf diff --git a/gui/kivy/data/fonts/Roboto.ttf b/electrum/gui/kivy/data/fonts/Roboto.ttf similarity index 100% rename from gui/kivy/data/fonts/Roboto.ttf rename to electrum/gui/kivy/data/fonts/Roboto.ttf diff --git a/gui/kivy/data/fonts/tron/License.txt b/electrum/gui/kivy/data/fonts/tron/License.txt similarity index 100% rename from gui/kivy/data/fonts/tron/License.txt rename to electrum/gui/kivy/data/fonts/tron/License.txt diff --git a/gui/kivy/data/fonts/tron/Readme.txt b/electrum/gui/kivy/data/fonts/tron/Readme.txt similarity index 100% rename from gui/kivy/data/fonts/tron/Readme.txt rename to electrum/gui/kivy/data/fonts/tron/Readme.txt diff --git a/gui/kivy/data/fonts/tron/Tr2n.ttf b/electrum/gui/kivy/data/fonts/tron/Tr2n.ttf similarity index 100% rename from gui/kivy/data/fonts/tron/Tr2n.ttf rename to electrum/gui/kivy/data/fonts/tron/Tr2n.ttf diff --git a/gui/kivy/data/glsl/default.fs b/electrum/gui/kivy/data/glsl/default.fs similarity index 100% rename from gui/kivy/data/glsl/default.fs rename to electrum/gui/kivy/data/glsl/default.fs diff --git a/gui/kivy/data/glsl/default.png b/electrum/gui/kivy/data/glsl/default.png similarity index 100% rename from gui/kivy/data/glsl/default.png rename to electrum/gui/kivy/data/glsl/default.png diff --git a/gui/kivy/data/glsl/default.vs b/electrum/gui/kivy/data/glsl/default.vs similarity index 100% rename from gui/kivy/data/glsl/default.vs rename to electrum/gui/kivy/data/glsl/default.vs diff --git a/gui/kivy/data/glsl/header.fs b/electrum/gui/kivy/data/glsl/header.fs similarity index 100% rename from gui/kivy/data/glsl/header.fs rename to electrum/gui/kivy/data/glsl/header.fs diff --git a/gui/kivy/data/glsl/header.vs b/electrum/gui/kivy/data/glsl/header.vs similarity index 100% rename from gui/kivy/data/glsl/header.vs rename to electrum/gui/kivy/data/glsl/header.vs diff --git a/gui/kivy/data/images/defaulttheme-0.png b/electrum/gui/kivy/data/images/defaulttheme-0.png similarity index 100% rename from gui/kivy/data/images/defaulttheme-0.png rename to electrum/gui/kivy/data/images/defaulttheme-0.png diff --git a/gui/kivy/data/images/defaulttheme.atlas b/electrum/gui/kivy/data/images/defaulttheme.atlas similarity index 100% rename from gui/kivy/data/images/defaulttheme.atlas rename to electrum/gui/kivy/data/images/defaulttheme.atlas diff --git a/gui/kivy/data/java-classes/org/electrum/qr/SimpleScannerActivity.java b/electrum/gui/kivy/data/java-classes/org/electrum-mona/qr/SimpleScannerActivity.java similarity index 93% rename from gui/kivy/data/java-classes/org/electrum/qr/SimpleScannerActivity.java rename to electrum/gui/kivy/data/java-classes/org/electrum-mona/qr/SimpleScannerActivity.java index 8f4714628770..9c7334f382a2 100644 --- a/gui/kivy/data/java-classes/org/electrum/qr/SimpleScannerActivity.java +++ b/electrum/gui/kivy/data/java-classes/org/electrum-mona/qr/SimpleScannerActivity.java @@ -1,4 +1,4 @@ -package org.electrum.qr; +package org.electrum-mona.qr; import android.app.Activity; import android.os.Bundle; @@ -14,7 +14,7 @@ public class SimpleScannerActivity extends Activity implements ZXingScannerView.ResultHandler { private ZXingScannerView mScannerView; - final String TAG = "org.electrum.SimpleScannerActivity"; + final String TAG = "org.electrum-mona.SimpleScannerActivity"; @Override public void onCreate(Bundle state) { diff --git a/gui/kivy/data/logo/kivy-icon-32.png b/electrum/gui/kivy/data/logo/kivy-icon-32.png similarity index 100% rename from gui/kivy/data/logo/kivy-icon-32.png rename to electrum/gui/kivy/data/logo/kivy-icon-32.png diff --git a/gui/kivy/data/style.kv b/electrum/gui/kivy/data/style.kv similarity index 100% rename from gui/kivy/data/style.kv rename to electrum/gui/kivy/data/style.kv diff --git a/gui/kivy/i18n.py b/electrum/gui/kivy/i18n.py similarity index 95% rename from gui/kivy/i18n.py rename to electrum/gui/kivy/i18n.py index 782c1fed37a5..733249d3ea38 100644 --- a/gui/kivy/i18n.py +++ b/electrum/gui/kivy/i18n.py @@ -36,7 +36,7 @@ def bind(label): @staticmethod def switch_lang(lang): # get the right locales directory, and instanciate a gettext - from electrum_mona.i18n import LOCALE_DIR + from electrum.i18n import LOCALE_DIR locales = gettext.translation('electrum', LOCALE_DIR, languages=[lang], fallback=True) _.lang = locales.gettext for label in _.observers: diff --git a/gui/kivy/main.kv b/electrum/gui/kivy/main.kv similarity index 95% rename from gui/kivy/main.kv rename to electrum/gui/kivy/main.kv index d14634e6b382..b4f05188e4c9 100644 --- a/gui/kivy/main.kv +++ b/electrum/gui/kivy/main.kv @@ -1,7 +1,7 @@ #:import Clock kivy.clock.Clock #:import Window kivy.core.window.Window #:import Factory kivy.factory.Factory -#:import _ electrum_mona_gui.kivy.i18n._ +#:import _ electrum.gui.kivy.i18n._ ########################### @@ -189,7 +189,7 @@ Color: rgba: 0.192, .498, 0.745, 1 BorderImage: - source: 'atlas://gui/kivy/theming/light/card_bottom' + source: 'atlas://electrum/gui/kivy/theming/light/card_bottom' size: self.size pos: self.pos @@ -203,7 +203,7 @@ Color: rgba: 0.192, .498, 0.745, 1 BorderImage: - source: 'atlas://gui/kivy/theming/light/card_bottom' + source: 'atlas://electrum/gui/kivy/theming/light/card_bottom' size: self.size pos: self.pos @@ -216,7 +216,7 @@ Color: rgba: 0.192, .498, 0.745, 1 BorderImage: - source: 'atlas://gui/kivy/theming/light/card_bottom' + source: 'atlas://electrum/gui/kivy/theming/light/card_bottom' size: self.size pos: self.pos @@ -326,8 +326,8 @@ valign: 'middle' bold: True font_size: '12.5sp' - background_normal: 'atlas://gui/kivy/theming/light/tab_btn' - background_down: 'atlas://gui/kivy/theming/light/tab_btn_pressed' + background_normal: 'atlas://electrum/gui/kivy/theming/light/tab_btn' + background_down: 'atlas://electrum/gui/kivy/theming/light/tab_btn_pressed' : @@ -416,14 +416,14 @@ BoxLayout: rgb: .6, .6, .6 Rectangle: size: self.size - source: 'gui/kivy/data/background.png' + source: 'electrum/gui/kivy/data/background.png' ActionBar: ActionView: id: av ActionPrevious: - app_icon: 'atlas://gui/kivy/theming/light/logo' + app_icon: 'atlas://electrum/gui/kivy/theming/light/logo' app_icon_width: '100dp' with_previous: False size_hint_x: None diff --git a/gui/kivy/main_window.py b/electrum/gui/kivy/main_window.py similarity index 92% rename from gui/kivy/main_window.py rename to electrum/gui/kivy/main_window.py index e1412006d16c..0c6c02a88844 100644 --- a/gui/kivy/main_window.py +++ b/electrum/gui/kivy/main_window.py @@ -7,14 +7,15 @@ from decimal import Decimal import threading -from electrum_mona.bitcoin import TYPE_ADDRESS -from electrum_mona import WalletStorage, Wallet -from electrum_mona_gui.kivy.i18n import _ -from electrum_mona.paymentrequest import InvoiceStore -from electrum_mona.util import profiler, InvalidPassword -from electrum_mona.plugins import run_hook -from electrum_mona.util import format_satoshis, format_satoshis_plain -from electrum_mona.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED +from electrum.bitcoin import TYPE_ADDRESS +from electrum.storage import WalletStorage +from electrum.wallet import Wallet +from electrum.i18n import _ +from electrum.paymentrequest import InvoiceStore +from electrum.util import profiler, InvalidPassword +from electrum.plugin import run_hook +from electrum.util import format_satoshis, format_satoshis_plain +from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED from kivy.app import App from kivy.core.window import Window @@ -29,10 +30,10 @@ from kivy.lang import Builder ## lazy imports for factory so that widgets can be used in kv -#Factory.register('InstallWizard', module='electrum_gui.kivy.uix.dialogs.installwizard') -#Factory.register('InfoBubble', module='electrum_gui.kivy.uix.dialogs') -#Factory.register('OutputList', module='electrum_gui.kivy.uix.dialogs') -#Factory.register('OutputItem', module='electrum_gui.kivy.uix.dialogs') +#Factory.register('InstallWizard', module='electrum.gui.kivy.uix.dialogs.installwizard') +#Factory.register('InfoBubble', module='electrum.gui.kivy.uix.dialogs') +#Factory.register('OutputList', module='electrum.gui.kivy.uix.dialogs') +#Factory.register('OutputItem', module='electrum.gui.kivy.uix.dialogs') from .uix.dialogs.installwizard import InstallWizard from .uix.dialogs import InfoBubble, crash_reporter @@ -48,26 +49,27 @@ # register widget cache for keeping memory down timeout to forever to cache # the data -Cache.register('electrum_mona_widgets', timeout=0) +Cache.register('electrum_widgets', timeout=0) from kivy.uix.screenmanager import Screen from kivy.uix.tabbedpanel import TabbedPanel from kivy.uix.label import Label from kivy.core.clipboard import Clipboard -Factory.register('TabbedCarousel', module='electrum_mona_gui.kivy.uix.screens') +Factory.register('TabbedCarousel', module='electrum.gui.kivy.uix.screens') # Register fonts without this you won't be able to use bold/italic... # inside markup. from kivy.core.text import Label Label.register('Roboto', - 'gui/kivy/data/fonts/Roboto.ttf', - 'gui/kivy/data/fonts/Roboto.ttf', - 'gui/kivy/data/fonts/Roboto-Bold.ttf', - 'gui/kivy/data/fonts/Roboto-Bold.ttf') + 'electrum/gui/kivy/data/fonts/Roboto.ttf', + 'electrum/gui/kivy/data/fonts/Roboto.ttf', + 'electrum/gui/kivy/data/fonts/Roboto-Bold.ttf', + 'electrum/gui/kivy/data/fonts/Roboto-Bold.ttf') -from electrum_mona.util import base_units, NoDynamicFeeEstimates +from electrum.util import (base_units, NoDynamicFeeEstimates, decimal_point_to_base_unit_name, + base_unit_name_to_decimal_point, NotEnoughFunds) class ElectrumWindow(App): @@ -99,7 +101,7 @@ def choose_server_dialog(self, popup): from .uix.dialogs.choice_dialog import ChoiceDialog protocol = 's' def cb2(host): - from electrum_mona import constants + from electrum import constants pp = servers.get(host, constants.net.DEFAULT_PORTS) port = pp.get(protocol, '') popup.ids.host.text = host @@ -158,11 +160,13 @@ def on_history(self, d): self._trigger_update_history() def _get_bu(self): - return self.electrum_config.get('base_unit', 'mBTC') + decimal_point = self.electrum_config.get('decimal_point', 5) + return decimal_point_to_base_unit_name(decimal_point) def _set_bu(self, value): assert value in base_units.keys() - self.electrum_config.set_key('base_unit', value, True) + decimal_point = base_unit_name_to_decimal_point(value) + self.electrum_config.set_key('decimal_point', decimal_point, True) self._trigger_update_status() self._trigger_update_history() @@ -284,6 +288,9 @@ def wallet_name(self): return os.path.basename(self.wallet.storage.path) if self.wallet else ' ' def on_pr(self, pr): + if not self.wallet: + self.show_error(_('No wallet loaded.')) + return if pr.verify(self.wallet.contacts): key = self.wallet.invoices.add(pr) if self.invoices_screen: @@ -303,7 +310,7 @@ def on_pr(self, pr): self.send_screen.do_clear() def on_qr(self, data): - from electrum_mona.bitcoin import base_decode, is_address + from electrum.bitcoin import base_decode, is_address data = data.strip() if is_address(data): self.set_URI(data) @@ -312,8 +319,8 @@ def on_qr(self, data): self.set_URI(data) return # try to decode transaction - from electrum_mona.transaction import Transaction - from electrum_mona.util import bh2u + from electrum.transaction import Transaction + from electrum.util import bh2u try: text = bh2u(base_decode(data, None, base=43)) tx = Transaction(text) @@ -350,13 +357,13 @@ def show_request(self, addr): self.receive_screen.screen.address = addr def show_pr_details(self, req, status, is_invoice): - from electrum_mona.util import format_time + from electrum.util import format_time requestor = req.get('requestor') exp = req.get('exp') memo = req.get('memo') amount = req.get('amount') fund = req.get('fund') - popup = Builder.load_file('gui/kivy/uix/ui_screens/invoice.kv') + popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/invoice.kv') popup.is_invoice = is_invoice popup.amount = amount popup.requestor = requestor if is_invoice else req.get('address') @@ -372,10 +379,10 @@ def show_pr_details(self, req, status, is_invoice): popup.open() def show_addr_details(self, req, status): - from electrum_mona.util import format_time + from electrum.util import format_time fund = req.get('fund') isaddr = 'y' - popup = Builder.load_file('gui/kivy/uix/ui_screens/invoice.kv') + popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/invoice.kv') popup.isaddr = isaddr popup.is_invoice = False popup.status = status @@ -395,7 +402,7 @@ def scan_qr(self, on_complete): from jnius import autoclass, cast from android import activity PythonActivity = autoclass('org.kivy.android.PythonActivity') - SimpleScannerActivity = autoclass("org.electrum.qr.SimpleScannerActivity") + SimpleScannerActivity = autoclass("org.electrum-mona.qr.SimpleScannerActivity") Intent = autoclass('android.content.Intent') intent = Intent(PythonActivity.mActivity, SimpleScannerActivity) @@ -428,7 +435,7 @@ def do_share(self, data, title): currentActivity.startActivity(it) def build(self): - return Builder.load_file('gui/kivy/main.kv') + return Builder.load_file('electrum/gui/kivy/main.kv') def _pause(self): if platform == 'android': @@ -585,7 +592,7 @@ def popup_dialog(self, name): d = WalletDialog() d.open() elif name == 'status': - popup = Builder.load_file('gui/kivy/uix/ui_screens/'+name+'.kv') + popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/'+name+'.kv') master_public_keys_layout = popup.ids.master_public_keys for xpub in self.wallet.get_master_public_keys()[1:]: master_public_keys_layout.add_widget(TopLabel(text=_('Master Public Key'))) @@ -595,7 +602,7 @@ def popup_dialog(self, name): master_public_keys_layout.add_widget(ref) popup.open() else: - popup = Builder.load_file('gui/kivy/uix/ui_screens/'+name+'.kv') + popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/'+name+'.kv') popup.open() @profiler @@ -611,13 +618,13 @@ def init_ui(self): #setup lazy imports for mainscreen Factory.register('AnimatedPopup', - module='electrum_mona_gui.kivy.uix.dialogs') + module='electrum.gui.kivy.uix.dialogs') Factory.register('QRCodeWidget', - module='electrum_mona_gui.kivy.uix.qrcodewidget') + module='electrum.gui.kivy.uix.qrcodewidget') # preload widgets. Remove this if you want to load the widgets on demand - #Cache.append('electrum_mona_widgets', 'AnimatedPopup', Factory.AnimatedPopup()) - #Cache.append('electrum_mona_widgets', 'QRCodeWidget', Factory.QRCodeWidget()) + #Cache.append('electrum_widgets', 'AnimatedPopup', Factory.AnimatedPopup()) + #Cache.append('electrum_widgets', 'QRCodeWidget', Factory.QRCodeWidget()) # load and focus the ui self.root.manager = self.root.ids['manager'] @@ -707,6 +714,8 @@ def get_max_amount(self): except NoDynamicFeeEstimates as e: Clock.schedule_once(lambda dt, bound_e=e: self.show_error(str(bound_e))) return '' + except NotEnoughFunds: + return '' amount = tx.output_value() __, x_fee_amount = run_hook('get_tx_extra_fee', self.wallet, tx) or (None, 0) amount_after_all_fees = amount - x_fee_amount @@ -768,7 +777,7 @@ def set_send(self, address, amount, label, message): self.send_payment(address, amount=amount, label=label, message=message) def show_error(self, error, width='200dp', pos=None, arrow_pos=None, - exit=False, icon='atlas://gui/kivy/theming/light/error', duration=0, + exit=False, icon='atlas://electrum/gui/kivy/theming/light/error', duration=0, modal=False): ''' Show an error Message Bubble. ''' @@ -780,7 +789,7 @@ def show_info(self, error, width='200dp', pos=None, arrow_pos=None, exit=False, duration=0, modal=False): ''' Show an Info Message Bubble. ''' - self.show_error(error, icon='atlas://gui/kivy/theming/light/important', + self.show_error(error, icon='atlas://electrum/gui/kivy/theming/light/important', duration=duration, modal=modal, exit=exit, pos=pos, arrow_pos=arrow_pos) @@ -820,7 +829,7 @@ def show_info_bubble(self, text=_('Hello World'), pos=None, duration=0, info_bubble.show_arrow = False img.allow_stretch = True info_bubble.dim_background = True - info_bubble.background_image = 'atlas://gui/kivy/theming/light/card' + info_bubble.background_image = 'atlas://electrum/gui/kivy/theming/light/card' else: info_bubble.fs = False info_bubble.icon = icon diff --git a/gui/kivy/nfc_scanner/__init__.py b/electrum/gui/kivy/nfc_scanner/__init__.py similarity index 98% rename from gui/kivy/nfc_scanner/__init__.py rename to electrum/gui/kivy/nfc_scanner/__init__.py index 41142c3e1b4d..c2dc9e278b19 100644 --- a/gui/kivy/nfc_scanner/__init__.py +++ b/electrum/gui/kivy/nfc_scanner/__init__.py @@ -41,4 +41,5 @@ def nfc_disable_exchange(self): NFCScanner = core_select_lib('nfc_manager', ( # keep the dummy implementation as the last one to make it the fallback provider.NFCScanner = core_select_lib('nfc_scanner', ( ('android', 'scanner_android', 'ScannerAndroid'), - ('dummy', 'scanner_dummy', 'ScannerDummy')), True, 'electrum_mona_gui.kivy') + ('dummy', 'scanner_dummy', 'ScannerDummy')), True, 'electrum.gui.kivy') + diff --git a/gui/kivy/nfc_scanner/scanner_android.py b/electrum/gui/kivy/nfc_scanner/scanner_android.py similarity index 97% rename from gui/kivy/nfc_scanner/scanner_android.py rename to electrum/gui/kivy/nfc_scanner/scanner_android.py index c85d9e752345..dc8a86308d85 100644 --- a/gui/kivy/nfc_scanner/scanner_android.py +++ b/electrum/gui/kivy/nfc_scanner/scanner_android.py @@ -10,7 +10,7 @@ raise ImportError import threading -from electrum_mona_gui.kivy.nfc_scanner import NFCBase +from . import NFCBase from jnius import autoclass, cast from android.runnable import run_on_ui_thread from android import activity @@ -165,20 +165,20 @@ def nfc_enable(self): def create_AAR(self): '''Create the record responsible for linking our application to the tag. ''' - return NdefRecord.createApplicationRecord(JString("org.electrum_mona.kivy")) + return NdefRecord.createApplicationRecord(JString("org.electrum-mona.kivy")) def create_TNF_EXTERNAL(self, data): '''Create our actual payload record. ''' if BUILDVERSION >= 14: - domain = "org.electrum_mona" + domain = "org.electrum-mona" stype = "externalType" extRecord = NdefRecord.createExternal(domain, stype, data) else: # Creating the NdefRecord manually: extRecord = NdefRecord( NdefRecord.TNF_EXTERNAL_TYPE, - "org.electrum_mona:externalType", + "org.electrum-mona:externalType", '', data) return extRecord @@ -213,7 +213,7 @@ def _nfc_enable_ndef_exchange(self, data): # Create record ndef_record = NdefRecord( NdefRecord.TNF_MIME_MEDIA, - 'org.electrum_mona.kivy', '', data) + 'org.electrum-mona.kivy', '', data) # Create message ndef_message = NdefMessage([ndef_record]) diff --git a/gui/kivy/nfc_scanner/scanner_dummy.py b/electrum/gui/kivy/nfc_scanner/scanner_dummy.py similarity index 96% rename from gui/kivy/nfc_scanner/scanner_dummy.py rename to electrum/gui/kivy/nfc_scanner/scanner_dummy.py index f09807a19d14..a0d3e2643ecf 100644 --- a/gui/kivy/nfc_scanner/scanner_dummy.py +++ b/electrum/gui/kivy/nfc_scanner/scanner_dummy.py @@ -1,6 +1,6 @@ ''' Dummy NFC Provider to be used on desktops in case no other provider is found ''' -from electrum_mona_gui.kivy.nfc_scanner import NFCBase +from . import NFCBase from kivy.clock import Clock from kivy.logger import Logger diff --git a/gui/kivy/theming/light/action_bar.png b/electrum/gui/kivy/theming/light/action_bar.png similarity index 100% rename from gui/kivy/theming/light/action_bar.png rename to electrum/gui/kivy/theming/light/action_bar.png diff --git a/gui/kivy/theming/light/action_button_group.png b/electrum/gui/kivy/theming/light/action_button_group.png similarity index 100% rename from gui/kivy/theming/light/action_button_group.png rename to electrum/gui/kivy/theming/light/action_button_group.png diff --git a/gui/kivy/theming/light/action_group_dark.png b/electrum/gui/kivy/theming/light/action_group_dark.png similarity index 100% rename from gui/kivy/theming/light/action_group_dark.png rename to electrum/gui/kivy/theming/light/action_group_dark.png diff --git a/gui/kivy/theming/light/action_group_light.png b/electrum/gui/kivy/theming/light/action_group_light.png similarity index 100% rename from gui/kivy/theming/light/action_group_light.png rename to electrum/gui/kivy/theming/light/action_group_light.png diff --git a/gui/kivy/theming/light/add_contact.png b/electrum/gui/kivy/theming/light/add_contact.png similarity index 100% rename from gui/kivy/theming/light/add_contact.png rename to electrum/gui/kivy/theming/light/add_contact.png diff --git a/gui/kivy/theming/light/arrow_back.png b/electrum/gui/kivy/theming/light/arrow_back.png similarity index 100% rename from gui/kivy/theming/light/arrow_back.png rename to electrum/gui/kivy/theming/light/arrow_back.png diff --git a/gui/kivy/theming/light/bit_logo.png b/electrum/gui/kivy/theming/light/bit_logo.png similarity index 100% rename from gui/kivy/theming/light/bit_logo.png rename to electrum/gui/kivy/theming/light/bit_logo.png diff --git a/gui/kivy/theming/light/blue_bg_round_rb.png b/electrum/gui/kivy/theming/light/blue_bg_round_rb.png similarity index 100% rename from gui/kivy/theming/light/blue_bg_round_rb.png rename to electrum/gui/kivy/theming/light/blue_bg_round_rb.png diff --git a/gui/kivy/theming/light/btn_create_account.png b/electrum/gui/kivy/theming/light/btn_create_account.png similarity index 100% rename from gui/kivy/theming/light/btn_create_account.png rename to electrum/gui/kivy/theming/light/btn_create_account.png diff --git a/gui/kivy/theming/light/btn_create_act_disabled.png b/electrum/gui/kivy/theming/light/btn_create_act_disabled.png similarity index 100% rename from gui/kivy/theming/light/btn_create_act_disabled.png rename to electrum/gui/kivy/theming/light/btn_create_act_disabled.png diff --git a/gui/kivy/theming/light/btn_nfc.png b/electrum/gui/kivy/theming/light/btn_nfc.png similarity index 100% rename from gui/kivy/theming/light/btn_nfc.png rename to electrum/gui/kivy/theming/light/btn_nfc.png diff --git a/gui/kivy/theming/light/btn_send_address.png b/electrum/gui/kivy/theming/light/btn_send_address.png similarity index 100% rename from gui/kivy/theming/light/btn_send_address.png rename to electrum/gui/kivy/theming/light/btn_send_address.png diff --git a/gui/kivy/theming/light/btn_send_nfc.png b/electrum/gui/kivy/theming/light/btn_send_nfc.png similarity index 100% rename from gui/kivy/theming/light/btn_send_nfc.png rename to electrum/gui/kivy/theming/light/btn_send_nfc.png diff --git a/gui/kivy/theming/light/calculator.png b/electrum/gui/kivy/theming/light/calculator.png similarity index 100% rename from gui/kivy/theming/light/calculator.png rename to electrum/gui/kivy/theming/light/calculator.png diff --git a/gui/kivy/theming/light/camera.png b/electrum/gui/kivy/theming/light/camera.png similarity index 100% rename from gui/kivy/theming/light/camera.png rename to electrum/gui/kivy/theming/light/camera.png diff --git a/gui/kivy/theming/light/card.png b/electrum/gui/kivy/theming/light/card.png similarity index 100% rename from gui/kivy/theming/light/card.png rename to electrum/gui/kivy/theming/light/card.png diff --git a/gui/kivy/theming/light/card_bottom.png b/electrum/gui/kivy/theming/light/card_bottom.png similarity index 100% rename from gui/kivy/theming/light/card_bottom.png rename to electrum/gui/kivy/theming/light/card_bottom.png diff --git a/gui/kivy/theming/light/card_btn.png b/electrum/gui/kivy/theming/light/card_btn.png similarity index 100% rename from gui/kivy/theming/light/card_btn.png rename to electrum/gui/kivy/theming/light/card_btn.png diff --git a/gui/kivy/theming/light/card_top.png b/electrum/gui/kivy/theming/light/card_top.png similarity index 100% rename from gui/kivy/theming/light/card_top.png rename to electrum/gui/kivy/theming/light/card_top.png diff --git a/gui/kivy/theming/light/carousel_deselected.png b/electrum/gui/kivy/theming/light/carousel_deselected.png similarity index 100% rename from gui/kivy/theming/light/carousel_deselected.png rename to electrum/gui/kivy/theming/light/carousel_deselected.png diff --git a/gui/kivy/theming/light/carousel_selected.png b/electrum/gui/kivy/theming/light/carousel_selected.png similarity index 100% rename from gui/kivy/theming/light/carousel_selected.png rename to electrum/gui/kivy/theming/light/carousel_selected.png diff --git a/gui/kivy/theming/light/clock1.png b/electrum/gui/kivy/theming/light/clock1.png similarity index 100% rename from gui/kivy/theming/light/clock1.png rename to electrum/gui/kivy/theming/light/clock1.png diff --git a/gui/kivy/theming/light/clock2.png b/electrum/gui/kivy/theming/light/clock2.png similarity index 100% rename from gui/kivy/theming/light/clock2.png rename to electrum/gui/kivy/theming/light/clock2.png diff --git a/gui/kivy/theming/light/clock3.png b/electrum/gui/kivy/theming/light/clock3.png similarity index 100% rename from gui/kivy/theming/light/clock3.png rename to electrum/gui/kivy/theming/light/clock3.png diff --git a/gui/kivy/theming/light/clock4.png b/electrum/gui/kivy/theming/light/clock4.png similarity index 100% rename from gui/kivy/theming/light/clock4.png rename to electrum/gui/kivy/theming/light/clock4.png diff --git a/gui/kivy/theming/light/clock5.png b/electrum/gui/kivy/theming/light/clock5.png similarity index 100% rename from gui/kivy/theming/light/clock5.png rename to electrum/gui/kivy/theming/light/clock5.png diff --git a/gui/kivy/theming/light/close.png b/electrum/gui/kivy/theming/light/close.png similarity index 100% rename from gui/kivy/theming/light/close.png rename to electrum/gui/kivy/theming/light/close.png diff --git a/gui/kivy/theming/light/closebutton.png b/electrum/gui/kivy/theming/light/closebutton.png similarity index 100% rename from gui/kivy/theming/light/closebutton.png rename to electrum/gui/kivy/theming/light/closebutton.png diff --git a/gui/kivy/theming/light/confirmed.png b/electrum/gui/kivy/theming/light/confirmed.png similarity index 100% rename from gui/kivy/theming/light/confirmed.png rename to electrum/gui/kivy/theming/light/confirmed.png diff --git a/gui/kivy/theming/light/contact.png b/electrum/gui/kivy/theming/light/contact.png similarity index 100% rename from gui/kivy/theming/light/contact.png rename to electrum/gui/kivy/theming/light/contact.png diff --git a/gui/kivy/theming/light/contact_overlay.png b/electrum/gui/kivy/theming/light/contact_overlay.png similarity index 100% rename from gui/kivy/theming/light/contact_overlay.png rename to electrum/gui/kivy/theming/light/contact_overlay.png diff --git a/gui/kivy/theming/light/create_act_text.png b/electrum/gui/kivy/theming/light/create_act_text.png similarity index 100% rename from gui/kivy/theming/light/create_act_text.png rename to electrum/gui/kivy/theming/light/create_act_text.png diff --git a/gui/kivy/theming/light/create_act_text_active.png b/electrum/gui/kivy/theming/light/create_act_text_active.png similarity index 100% rename from gui/kivy/theming/light/create_act_text_active.png rename to electrum/gui/kivy/theming/light/create_act_text_active.png diff --git a/gui/kivy/theming/light/dialog.png b/electrum/gui/kivy/theming/light/dialog.png similarity index 100% rename from gui/kivy/theming/light/dialog.png rename to electrum/gui/kivy/theming/light/dialog.png diff --git a/gui/kivy/theming/light/dropdown_background.png b/electrum/gui/kivy/theming/light/dropdown_background.png similarity index 100% rename from gui/kivy/theming/light/dropdown_background.png rename to electrum/gui/kivy/theming/light/dropdown_background.png diff --git a/gui/kivy/theming/light/electrum_icon640.png b/electrum/gui/kivy/theming/light/electrum_icon640.png similarity index 100% rename from gui/kivy/theming/light/electrum_icon640.png rename to electrum/gui/kivy/theming/light/electrum_icon640.png diff --git a/gui/kivy/theming/light/error.png b/electrum/gui/kivy/theming/light/error.png similarity index 100% rename from gui/kivy/theming/light/error.png rename to electrum/gui/kivy/theming/light/error.png diff --git a/gui/kivy/theming/light/gear.png b/electrum/gui/kivy/theming/light/gear.png similarity index 100% rename from gui/kivy/theming/light/gear.png rename to electrum/gui/kivy/theming/light/gear.png diff --git a/gui/kivy/theming/light/globe.png b/electrum/gui/kivy/theming/light/globe.png similarity index 100% rename from gui/kivy/theming/light/globe.png rename to electrum/gui/kivy/theming/light/globe.png diff --git a/gui/kivy/theming/light/icon_border.png b/electrum/gui/kivy/theming/light/icon_border.png similarity index 100% rename from gui/kivy/theming/light/icon_border.png rename to electrum/gui/kivy/theming/light/icon_border.png diff --git a/gui/kivy/theming/light/important.png b/electrum/gui/kivy/theming/light/important.png similarity index 100% rename from gui/kivy/theming/light/important.png rename to electrum/gui/kivy/theming/light/important.png diff --git a/gui/kivy/theming/light/info.png b/electrum/gui/kivy/theming/light/info.png similarity index 100% rename from gui/kivy/theming/light/info.png rename to electrum/gui/kivy/theming/light/info.png diff --git a/gui/kivy/theming/light/lightblue_bg_round_lb.png b/electrum/gui/kivy/theming/light/lightblue_bg_round_lb.png similarity index 100% rename from gui/kivy/theming/light/lightblue_bg_round_lb.png rename to electrum/gui/kivy/theming/light/lightblue_bg_round_lb.png diff --git a/gui/kivy/theming/light/logo.png b/electrum/gui/kivy/theming/light/logo.png similarity index 100% rename from gui/kivy/theming/light/logo.png rename to electrum/gui/kivy/theming/light/logo.png diff --git a/gui/kivy/theming/light/logo_atom_dull.png b/electrum/gui/kivy/theming/light/logo_atom_dull.png similarity index 100% rename from gui/kivy/theming/light/logo_atom_dull.png rename to electrum/gui/kivy/theming/light/logo_atom_dull.png diff --git a/gui/kivy/theming/light/mail_icon.png b/electrum/gui/kivy/theming/light/mail_icon.png similarity index 100% rename from gui/kivy/theming/light/mail_icon.png rename to electrum/gui/kivy/theming/light/mail_icon.png diff --git a/gui/kivy/theming/light/manualentry.png b/electrum/gui/kivy/theming/light/manualentry.png similarity index 100% rename from gui/kivy/theming/light/manualentry.png rename to electrum/gui/kivy/theming/light/manualentry.png diff --git a/gui/kivy/theming/light/network.png b/electrum/gui/kivy/theming/light/network.png similarity index 100% rename from gui/kivy/theming/light/network.png rename to electrum/gui/kivy/theming/light/network.png diff --git a/gui/kivy/theming/light/nfc.png b/electrum/gui/kivy/theming/light/nfc.png similarity index 100% rename from gui/kivy/theming/light/nfc.png rename to electrum/gui/kivy/theming/light/nfc.png diff --git a/gui/kivy/theming/light/nfc_clock.png b/electrum/gui/kivy/theming/light/nfc_clock.png similarity index 100% rename from gui/kivy/theming/light/nfc_clock.png rename to electrum/gui/kivy/theming/light/nfc_clock.png diff --git a/gui/kivy/theming/light/nfc_phone.png b/electrum/gui/kivy/theming/light/nfc_phone.png similarity index 100% rename from gui/kivy/theming/light/nfc_phone.png rename to electrum/gui/kivy/theming/light/nfc_phone.png diff --git a/gui/kivy/theming/light/nfc_stage_one.png b/electrum/gui/kivy/theming/light/nfc_stage_one.png similarity index 100% rename from gui/kivy/theming/light/nfc_stage_one.png rename to electrum/gui/kivy/theming/light/nfc_stage_one.png diff --git a/gui/kivy/theming/light/overflow_background.png b/electrum/gui/kivy/theming/light/overflow_background.png similarity index 100% rename from gui/kivy/theming/light/overflow_background.png rename to electrum/gui/kivy/theming/light/overflow_background.png diff --git a/gui/kivy/theming/light/overflow_btn_dn.png b/electrum/gui/kivy/theming/light/overflow_btn_dn.png similarity index 100% rename from gui/kivy/theming/light/overflow_btn_dn.png rename to electrum/gui/kivy/theming/light/overflow_btn_dn.png diff --git a/gui/kivy/theming/light/paste_icon.png b/electrum/gui/kivy/theming/light/paste_icon.png similarity index 100% rename from gui/kivy/theming/light/paste_icon.png rename to electrum/gui/kivy/theming/light/paste_icon.png diff --git a/gui/kivy/theming/light/pen.png b/electrum/gui/kivy/theming/light/pen.png similarity index 100% rename from gui/kivy/theming/light/pen.png rename to electrum/gui/kivy/theming/light/pen.png diff --git a/gui/kivy/theming/light/qrcode.png b/electrum/gui/kivy/theming/light/qrcode.png similarity index 100% rename from gui/kivy/theming/light/qrcode.png rename to electrum/gui/kivy/theming/light/qrcode.png diff --git a/gui/kivy/theming/light/save.png b/electrum/gui/kivy/theming/light/save.png similarity index 100% rename from gui/kivy/theming/light/save.png rename to electrum/gui/kivy/theming/light/save.png diff --git a/gui/kivy/theming/light/settings.png b/electrum/gui/kivy/theming/light/settings.png similarity index 100% rename from gui/kivy/theming/light/settings.png rename to electrum/gui/kivy/theming/light/settings.png diff --git a/gui/kivy/theming/light/shadow.png b/electrum/gui/kivy/theming/light/shadow.png similarity index 100% rename from gui/kivy/theming/light/shadow.png rename to electrum/gui/kivy/theming/light/shadow.png diff --git a/gui/kivy/theming/light/shadow_right.png b/electrum/gui/kivy/theming/light/shadow_right.png similarity index 100% rename from gui/kivy/theming/light/shadow_right.png rename to electrum/gui/kivy/theming/light/shadow_right.png diff --git a/gui/kivy/theming/light/share.png b/electrum/gui/kivy/theming/light/share.png similarity index 100% rename from gui/kivy/theming/light/share.png rename to electrum/gui/kivy/theming/light/share.png diff --git a/gui/kivy/theming/light/star_big_inactive.png b/electrum/gui/kivy/theming/light/star_big_inactive.png similarity index 100% rename from gui/kivy/theming/light/star_big_inactive.png rename to electrum/gui/kivy/theming/light/star_big_inactive.png diff --git a/gui/kivy/theming/light/stepper_full.png b/electrum/gui/kivy/theming/light/stepper_full.png similarity index 100% rename from gui/kivy/theming/light/stepper_full.png rename to electrum/gui/kivy/theming/light/stepper_full.png diff --git a/gui/kivy/theming/light/stepper_left.png b/electrum/gui/kivy/theming/light/stepper_left.png similarity index 100% rename from gui/kivy/theming/light/stepper_left.png rename to electrum/gui/kivy/theming/light/stepper_left.png diff --git a/gui/kivy/theming/light/stepper_restore_password.png b/electrum/gui/kivy/theming/light/stepper_restore_password.png similarity index 100% rename from gui/kivy/theming/light/stepper_restore_password.png rename to electrum/gui/kivy/theming/light/stepper_restore_password.png diff --git a/gui/kivy/theming/light/stepper_restore_seed.png b/electrum/gui/kivy/theming/light/stepper_restore_seed.png similarity index 100% rename from gui/kivy/theming/light/stepper_restore_seed.png rename to electrum/gui/kivy/theming/light/stepper_restore_seed.png diff --git a/gui/kivy/theming/light/tab.png b/electrum/gui/kivy/theming/light/tab.png similarity index 100% rename from gui/kivy/theming/light/tab.png rename to electrum/gui/kivy/theming/light/tab.png diff --git a/gui/kivy/theming/light/tab_btn.png b/electrum/gui/kivy/theming/light/tab_btn.png similarity index 100% rename from gui/kivy/theming/light/tab_btn.png rename to electrum/gui/kivy/theming/light/tab_btn.png diff --git a/gui/kivy/theming/light/tab_btn_disabled.png b/electrum/gui/kivy/theming/light/tab_btn_disabled.png similarity index 100% rename from gui/kivy/theming/light/tab_btn_disabled.png rename to electrum/gui/kivy/theming/light/tab_btn_disabled.png diff --git a/gui/kivy/theming/light/tab_btn_pressed.png b/electrum/gui/kivy/theming/light/tab_btn_pressed.png similarity index 100% rename from gui/kivy/theming/light/tab_btn_pressed.png rename to electrum/gui/kivy/theming/light/tab_btn_pressed.png diff --git a/gui/kivy/theming/light/tab_disabled.png b/electrum/gui/kivy/theming/light/tab_disabled.png similarity index 100% rename from gui/kivy/theming/light/tab_disabled.png rename to electrum/gui/kivy/theming/light/tab_disabled.png diff --git a/gui/kivy/theming/light/tab_strip.png b/electrum/gui/kivy/theming/light/tab_strip.png similarity index 100% rename from gui/kivy/theming/light/tab_strip.png rename to electrum/gui/kivy/theming/light/tab_strip.png diff --git a/gui/kivy/theming/light/textinput_active.png b/electrum/gui/kivy/theming/light/textinput_active.png similarity index 100% rename from gui/kivy/theming/light/textinput_active.png rename to electrum/gui/kivy/theming/light/textinput_active.png diff --git a/gui/kivy/theming/light/unconfirmed.png b/electrum/gui/kivy/theming/light/unconfirmed.png similarity index 100% rename from gui/kivy/theming/light/unconfirmed.png rename to electrum/gui/kivy/theming/light/unconfirmed.png diff --git a/gui/kivy/theming/light/wallet.png b/electrum/gui/kivy/theming/light/wallet.png similarity index 100% rename from gui/kivy/theming/light/wallet.png rename to electrum/gui/kivy/theming/light/wallet.png diff --git a/gui/kivy/theming/light/wallets.png b/electrum/gui/kivy/theming/light/wallets.png similarity index 100% rename from gui/kivy/theming/light/wallets.png rename to electrum/gui/kivy/theming/light/wallets.png diff --git a/gui/kivy/theming/light/white_bg_round_top.png b/electrum/gui/kivy/theming/light/white_bg_round_top.png similarity index 100% rename from gui/kivy/theming/light/white_bg_round_top.png rename to electrum/gui/kivy/theming/light/white_bg_round_top.png diff --git a/gui/kivy/tools/bitcoin_intent.xml b/electrum/gui/kivy/tools/bitcoin_intent.xml similarity index 100% rename from gui/kivy/tools/bitcoin_intent.xml rename to electrum/gui/kivy/tools/bitcoin_intent.xml diff --git a/gui/kivy/tools/blacklist.txt b/electrum/gui/kivy/tools/blacklist.txt similarity index 100% rename from gui/kivy/tools/blacklist.txt rename to electrum/gui/kivy/tools/blacklist.txt diff --git a/gui/kivy/tools/buildozer.spec b/electrum/gui/kivy/tools/buildozer.spec similarity index 92% rename from gui/kivy/tools/buildozer.spec rename to electrum/gui/kivy/tools/buildozer.spec index 5401112de2a4..903b02ded5dd 100644 --- a/gui/kivy/tools/buildozer.spec +++ b/electrum/gui/kivy/tools/buildozer.spec @@ -7,7 +7,7 @@ title = Electrum-MONA package.name = Electrum_MONA # (str) Package domain (needed for android/ios packaging) -package.domain = org.electrum_mona +package.domain = org.electrum-mona # (str) Source code where the main.py live source.dir = . @@ -19,13 +19,13 @@ source.include_exts = py,png,jpg,kv,atlas,ttf,txt,gif,pem,mo,vs,fs,json source.exclude_exts = spec # (list) List of directory to exclude (let empty to not exclude anything) -source.exclude_dirs = bin, build, dist, contrib, gui/qt, gui/kivy/tools, gui/kivy/theming/light +source.exclude_dirs = bin, build, dist, contrib, electrum/gui/qt, electrum/gui/kivy/tools, electrum/gui/kivy/theming/light # (list) List of exclusions using pattern matching source.exclude_patterns = Makefile,setup* # (str) Application versioning (method 1) version.regex = APK_VERSION = '(.*)' -version.filename = %(source.dir)s/lib/version.py +version.filename = %(source.dir)s/electrum/version.py # (str) Application versioning (method 2) #version = 1.9.8 @@ -87,11 +87,11 @@ android.ndk_path = /opt/crystax-ndk-10.3.2 # (list) List of Java files to add to the android project (can be java or a # directory containing the files) -android.add_src = gui/kivy/data/java-classes/ +android.add_src = electrum/gui/kivy/data/java-classes/ android.gradle_dependencies = me.dm7.barcodescanner:zxing:1.9.8 -android.add_activities = org.electrum.qr.SimpleScannerActivity +android.add_activities = org.electrum-mona.qr.SimpleScannerActivity # (str) python-for-android branch to use, if not master, useful to try # not yet merged features. @@ -105,7 +105,7 @@ android.add_activities = org.electrum.qr.SimpleScannerActivity #android.ouya.icon.filename = %(source.dir)s/data/ouya_icon.png # (str) XML file to include as an intent filters in tag -android.manifest.intent_filters = gui/kivy/tools/bitcoin_intent.xml +android.manifest.intent_filters = electrums/gui/kivy/tools/bitcoin_intent.xml # (str) launchMode to set for the main activity android.manifest.launch_mode = singleTask diff --git a/gui/kivy/uix/__init__.py b/electrum/gui/kivy/uix/__init__.py similarity index 100% rename from gui/kivy/uix/__init__.py rename to electrum/gui/kivy/uix/__init__.py diff --git a/gui/kivy/uix/combobox.py b/electrum/gui/kivy/uix/combobox.py similarity index 100% rename from gui/kivy/uix/combobox.py rename to electrum/gui/kivy/uix/combobox.py diff --git a/gui/kivy/uix/context_menu.py b/electrum/gui/kivy/uix/context_menu.py similarity index 96% rename from gui/kivy/uix/context_menu.py rename to electrum/gui/kivy/uix/context_menu.py index 38010acfb349..84d5ba64764e 100644 --- a/gui/kivy/uix/context_menu.py +++ b/electrum/gui/kivy/uix/context_menu.py @@ -8,7 +8,7 @@ from kivy.factory import Factory from kivy.clock import Clock -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ Builder.load_string(''' diff --git a/gui/kivy/uix/dialogs/__init__.py b/electrum/gui/kivy/uix/dialogs/__init__.py similarity index 99% rename from gui/kivy/uix/dialogs/__init__.py rename to electrum/gui/kivy/uix/dialogs/__init__.py index 81927498d76a..9f8f7f2e3bb9 100644 --- a/gui/kivy/uix/dialogs/__init__.py +++ b/electrum/gui/kivy/uix/dialogs/__init__.py @@ -6,7 +6,7 @@ from kivy.uix.recycleview import RecycleView from kivy.uix.boxlayout import BoxLayout -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ diff --git a/gui/kivy/uix/dialogs/addresses.py b/electrum/gui/kivy/uix/dialogs/addresses.py similarity index 98% rename from gui/kivy/uix/dialogs/addresses.py rename to electrum/gui/kivy/uix/dialogs/addresses.py index e67f9218c2f1..5b90f2f7aa3d 100644 --- a/gui/kivy/uix/dialogs/addresses.py +++ b/electrum/gui/kivy/uix/dialogs/addresses.py @@ -98,8 +98,8 @@ ''') -from electrum_mona_gui.kivy.i18n import _ -from electrum_mona_gui.kivy.uix.context_menu import ContextMenu +from electrum.gui.kivy.i18n import _ +from electrum.gui.kivy.uix.context_menu import ContextMenu class AddressesDialog(Factory.Popup): diff --git a/gui/kivy/uix/dialogs/amount_dialog.py b/electrum/gui/kivy/uix/dialogs/amount_dialog.py similarity index 100% rename from gui/kivy/uix/dialogs/amount_dialog.py rename to electrum/gui/kivy/uix/dialogs/amount_dialog.py diff --git a/gui/kivy/uix/dialogs/bump_fee_dialog.py b/electrum/gui/kivy/uix/dialogs/bump_fee_dialog.py similarity index 98% rename from gui/kivy/uix/dialogs/bump_fee_dialog.py rename to electrum/gui/kivy/uix/dialogs/bump_fee_dialog.py index f60e4e49f11b..854be26bd447 100644 --- a/gui/kivy/uix/dialogs/bump_fee_dialog.py +++ b/electrum/gui/kivy/uix/dialogs/bump_fee_dialog.py @@ -3,7 +3,7 @@ from kivy.properties import ObjectProperty from kivy.lang import Builder -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ Builder.load_string(''' diff --git a/gui/kivy/uix/dialogs/checkbox_dialog.py b/electrum/gui/kivy/uix/dialogs/checkbox_dialog.py similarity index 100% rename from gui/kivy/uix/dialogs/checkbox_dialog.py rename to electrum/gui/kivy/uix/dialogs/checkbox_dialog.py diff --git a/gui/kivy/uix/dialogs/choice_dialog.py b/electrum/gui/kivy/uix/dialogs/choice_dialog.py similarity index 100% rename from gui/kivy/uix/dialogs/choice_dialog.py rename to electrum/gui/kivy/uix/dialogs/choice_dialog.py diff --git a/gui/kivy/uix/dialogs/crash_reporter.py b/electrum/gui/kivy/uix/dialogs/crash_reporter.py similarity index 98% rename from gui/kivy/uix/dialogs/crash_reporter.py rename to electrum/gui/kivy/uix/dialogs/crash_reporter.py index a15f3f355fc0..8603d806b691 100644 --- a/gui/kivy/uix/dialogs/crash_reporter.py +++ b/electrum/gui/kivy/uix/dialogs/crash_reporter.py @@ -10,8 +10,8 @@ from kivy.utils import platform -from electrum_mona.base_crash_reporter import BaseCrashReporter -from electrum_mona.i18n import _ +from electrum.base_crash_reporter import BaseCrashReporter +from electrum.i18n import _ Builder.load_string(''' diff --git a/gui/kivy/uix/dialogs/fee_dialog.py b/electrum/gui/kivy/uix/dialogs/fee_dialog.py similarity index 99% rename from gui/kivy/uix/dialogs/fee_dialog.py rename to electrum/gui/kivy/uix/dialogs/fee_dialog.py index 82f4928169c5..7c6293973ad1 100644 --- a/gui/kivy/uix/dialogs/fee_dialog.py +++ b/electrum/gui/kivy/uix/dialogs/fee_dialog.py @@ -3,7 +3,7 @@ from kivy.properties import ObjectProperty from kivy.lang import Builder -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ Builder.load_string(''' diff --git a/gui/kivy/uix/dialogs/fx_dialog.py b/electrum/gui/kivy/uix/dialogs/fx_dialog.py similarity index 98% rename from gui/kivy/uix/dialogs/fx_dialog.py rename to electrum/gui/kivy/uix/dialogs/fx_dialog.py index 7b208c805040..fce8582902eb 100644 --- a/gui/kivy/uix/dialogs/fx_dialog.py +++ b/electrum/gui/kivy/uix/dialogs/fx_dialog.py @@ -66,7 +66,7 @@ from kivy.uix.widget import Widget from kivy.clock import Clock -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ from functools import partial class FxDialog(Factory.Popup): diff --git a/gui/kivy/uix/dialogs/installwizard.py b/electrum/gui/kivy/uix/dialogs/installwizard.py similarity index 97% rename from gui/kivy/uix/dialogs/installwizard.py rename to electrum/gui/kivy/uix/dialogs/installwizard.py index 4f0346435369..d5b51e07a187 100644 --- a/gui/kivy/uix/dialogs/installwizard.py +++ b/electrum/gui/kivy/uix/dialogs/installwizard.py @@ -15,8 +15,8 @@ from kivy.clock import Clock from kivy.utils import platform -from electrum_mona.base_wizard import BaseWizard -from electrum_mona.util import is_valid_email +from electrum.base_wizard import BaseWizard +from electrum.util import is_valid_email from . import EventsDialog @@ -31,7 +31,7 @@ Builder.load_string(''' #:import Window kivy.core.window.Window -#:import _ electrum_mona_gui.kivy.i18n._ +#:import _ electrum.gui.kivy.i18n._ @@ -41,8 +41,8 @@ background_color: (1, 1, 1, 1) if self.focus else (0.454, 0.698, 0.909, 1) foreground_color: (0.31, 0.31, 0.31, 1) if self.focus else (0.835, 0.909, 0.972, 1) hint_text_color: self.foreground_color - background_active: 'atlas://gui/kivy/theming/light/create_act_text_active' - background_normal: 'atlas://gui/kivy/theming/light/create_act_text_active' + background_active: 'atlas://electrum/gui/kivy/theming/light/create_act_text_active' + background_normal: 'atlas://electrum/gui/kivy/theming/light/create_act_text_active' size_hint_y: None height: '48sp' @@ -91,7 +91,7 @@ size_hint: 1, None height: self.texture_size[1] if self.opacity else 0 font_size: '33sp' - font_name: 'gui/kivy/data/fonts/tron/Tr2n.ttf' + font_name: 'electrum/gui/kivy/data/fonts/tron/Tr2n.ttf' GridLayout: cols: 1 id: crcontent @@ -300,7 +300,7 @@ font_size: '18dp' text_size: self.width - dp(24), self.height - dp(12) color: .1, .1, .1, 1 - background_normal: 'atlas://gui/kivy/theming/light/white_bg_round_top' + background_normal: 'atlas://electrum/gui/kivy/theming/light/white_bg_round_top' background_down: self.background_normal size_hint_y: None @@ -446,7 +446,7 @@ id: scan height: '48sp' on_release: root.scan_xpub() - icon: 'atlas://gui/kivy/theming/light/camera' + icon: 'atlas://electrum/gui/kivy/theming/light/camera' size_hint: 1, None WizardButton: text: _('Paste') @@ -759,8 +759,8 @@ class RestoreSeedDialog(WizardDialog): def __init__(self, wizard, **kwargs): super(RestoreSeedDialog, self).__init__(wizard, **kwargs) self._test = kwargs['test'] - from electrum_mona.mnemonic import Mnemonic - from electrum_mona.old_mnemonic import words as old_wordlist + from electrum.mnemonic import Mnemonic + from electrum.old_mnemonic import words as old_wordlist self.words = set(Mnemonic('en').wordlist).union(set(old_wordlist)) self.ids.text_input_seed.text = test_seed if is_test else '' self.message = _('Please type your seed phrase using the virtual keyboard.') @@ -961,7 +961,7 @@ def target(): app = App.get_running_app() app.show_info_bubble( - text=msg, icon='atlas://gui/kivy/theming/light/important', + text=msg, icon='atlas://electrum/gui/kivy/theming/light/important', pos=Window.center, width='200sp', arrow_pos=None, modal=True) t = threading.Thread(target = target) t.start() diff --git a/gui/kivy/uix/dialogs/invoices.py b/electrum/gui/kivy/uix/dialogs/invoices.py similarity index 88% rename from gui/kivy/uix/dialogs/invoices.py rename to electrum/gui/kivy/uix/dialogs/invoices.py index a077db6ef9fc..4fb986df1038 100644 --- a/gui/kivy/uix/dialogs/invoices.py +++ b/electrum/gui/kivy/uix/dialogs/invoices.py @@ -17,7 +17,7 @@ amount: '' status: '' date: '' - icon: 'atlas://gui/kivy/theming/light/important' + icon: 'atlas://electrum/gui/kivy/theming/light/important' Image: id: icon source: root.icon @@ -76,10 +76,10 @@ ''') from kivy.properties import BooleanProperty -from electrum_mona_gui.kivy.i18n import _ -from electrum_mona.util import format_time -from electrum_mona.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED -from electrum_mona_gui.kivy.uix.context_menu import ContextMenu +from electrum.gui.kivy.i18n import _ +from electrum.util import format_time +from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED +from electrum.gui.kivy.uix.context_menu import ContextMenu invoice_text = { PR_UNPAID:_('Pending'), @@ -88,10 +88,10 @@ PR_EXPIRED:_('Expired') } pr_icon = { - PR_UNPAID: 'atlas://gui/kivy/theming/light/important', - PR_UNKNOWN: 'atlas://gui/kivy/theming/light/important', - PR_PAID: 'atlas://gui/kivy/theming/light/confirmed', - PR_EXPIRED: 'atlas://gui/kivy/theming/light/close' + PR_UNPAID: 'atlas://electrum/gui/kivy/theming/light/important', + PR_UNKNOWN: 'atlas://electrum/gui/kivy/theming/light/important', + PR_PAID: 'atlas://electrum/gui/kivy/theming/light/confirmed', + PR_EXPIRED: 'atlas://electrum/gui/kivy/theming/light/close' } diff --git a/gui/kivy/uix/dialogs/label_dialog.py b/electrum/gui/kivy/uix/dialogs/label_dialog.py similarity index 89% rename from gui/kivy/uix/dialogs/label_dialog.py rename to electrum/gui/kivy/uix/dialogs/label_dialog.py index cf7aa2def5d9..974cd0667a8c 100644 --- a/gui/kivy/uix/dialogs/label_dialog.py +++ b/electrum/gui/kivy/uix/dialogs/label_dialog.py @@ -21,8 +21,8 @@ pos_hint: {'center_y':.5} text:'' multiline: False - background_normal: 'atlas://gui/kivy/theming/light/tab_btn' - background_active: 'atlas://gui/kivy/theming/light/textinput_active' + background_normal: 'atlas://electrum/gui/kivy/theming/light/tab_btn' + background_active: 'atlas://electrum/gui/kivy/theming/light/textinput_active' hint_text_color: self.foreground_color foreground_color: 1, 1, 1, 1 font_size: '16dp' diff --git a/gui/kivy/uix/dialogs/nfc_transaction.py b/electrum/gui/kivy/uix/dialogs/nfc_transaction.py similarity index 92% rename from gui/kivy/uix/dialogs/nfc_transaction.py rename to electrum/gui/kivy/uix/dialogs/nfc_transaction.py index 46b7839005a1..c37af3a85350 100644 --- a/gui/kivy/uix/dialogs/nfc_transaction.py +++ b/electrum/gui/kivy/uix/dialogs/nfc_transaction.py @@ -8,7 +8,7 @@ def __init__(self, **kwargs): # Delayed Init global NFCSCanner if NFCSCanner is None: - from electrum_mona_gui.kivy.nfc_scanner import NFCScanner + from electrum.gui.kivy.nfc_scanner import NFCScanner self.scanner = NFCSCanner super(NFCTransactionDialog, self).__init__(**kwargs) diff --git a/gui/kivy/uix/dialogs/password_dialog.py b/electrum/gui/kivy/uix/dialogs/password_dialog.py similarity index 95% rename from gui/kivy/uix/dialogs/password_dialog.py rename to electrum/gui/kivy/uix/dialogs/password_dialog.py index 0095f3ee3348..2fdcb3d9be20 100644 --- a/gui/kivy/uix/dialogs/password_dialog.py +++ b/electrum/gui/kivy/uix/dialogs/password_dialog.py @@ -5,14 +5,14 @@ from decimal import Decimal from kivy.clock import Clock -from electrum_mona.util import InvalidPassword -from electrum_mona_gui.kivy.i18n import _ +from electrum.util import InvalidPassword +from electrum.gui.kivy.i18n import _ Builder.load_string(''' id: popup - title: 'Electrum' + title: 'Electrum-MONA' message: '' BoxLayout: size_hint: 1, 1 @@ -82,7 +82,7 @@ def init(self, app, wallet, message, on_success, on_failure, is_change=0): self.is_change = is_change self.pw = None self.new_password = None - self.title = 'Electrum' + (' - ' + self.wallet.basename() if self.wallet else '') + self.title = 'Electrum-MONA' + (' - ' + self.wallet.basename() if self.wallet else '') def check_password(self, password): if self.is_change > 1: diff --git a/gui/kivy/uix/dialogs/qr_dialog.py b/electrum/gui/kivy/uix/dialogs/qr_dialog.py similarity index 100% rename from gui/kivy/uix/dialogs/qr_dialog.py rename to electrum/gui/kivy/uix/dialogs/qr_dialog.py diff --git a/gui/kivy/uix/dialogs/qr_scanner.py b/electrum/gui/kivy/uix/dialogs/qr_scanner.py similarity index 88% rename from gui/kivy/uix/dialogs/qr_scanner.py rename to electrum/gui/kivy/uix/dialogs/qr_scanner.py index 7d204b24e4da..8a565f0195fe 100644 --- a/gui/kivy/uix/dialogs/qr_scanner.py +++ b/electrum/gui/kivy/uix/dialogs/qr_scanner.py @@ -2,7 +2,7 @@ from kivy.factory import Factory from kivy.lang import Builder -Factory.register('QRScanner', module='electrum_mona_gui.kivy.qr_scanner') +Factory.register('QRScanner', module='electrum.gui.kivy.qr_scanner') class QrScannerDialog(Factory.AnimatedPopup): @@ -33,7 +33,7 @@ def on_complete(self, x): #separator_color: .89, .89, .89, 1 #separator_height: '1.2dp' #title_color: .437, .437, .437, 1 - #background: 'atlas://gui/kivy/theming/light/dialog' + #background: 'atlas://electrum/gui/kivy/theming/light/dialog' on_activate: qrscr.start() qrscr.size = self.size diff --git a/gui/kivy/uix/dialogs/question.py b/electrum/gui/kivy/uix/dialogs/question.py similarity index 96% rename from gui/kivy/uix/dialogs/question.py rename to electrum/gui/kivy/uix/dialogs/question.py index 94cecebabe89..4b5e085fa9af 100644 --- a/gui/kivy/uix/dialogs/question.py +++ b/electrum/gui/kivy/uix/dialogs/question.py @@ -6,7 +6,7 @@ from kivy.uix.label import Label from kivy.uix.widget import Widget -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ Builder.load_string(''' diff --git a/gui/kivy/uix/dialogs/requests.py b/electrum/gui/kivy/uix/dialogs/requests.py similarity index 88% rename from gui/kivy/uix/dialogs/requests.py rename to electrum/gui/kivy/uix/dialogs/requests.py index d153f49159fb..5aadae0d0f14 100644 --- a/gui/kivy/uix/dialogs/requests.py +++ b/electrum/gui/kivy/uix/dialogs/requests.py @@ -17,7 +17,7 @@ amount: '' status: '' date: '' - icon: 'atlas://gui/kivy/theming/light/important' + icon: 'atlas://electrum/gui/kivy/theming/light/important' Image: id: icon source: root.icon @@ -74,16 +74,16 @@ ''') from kivy.properties import BooleanProperty -from electrum_mona_gui.kivy.i18n import _ -from electrum_mona.util import format_time -from electrum_mona.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED -from electrum_mona_gui.kivy.uix.context_menu import ContextMenu +from electrum.gui.kivy.i18n import _ +from electrum.util import format_time +from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED +from electrum.gui.kivy.uix.context_menu import ContextMenu pr_icon = { - PR_UNPAID: 'atlas://gui/kivy/theming/light/important', - PR_UNKNOWN: 'atlas://gui/kivy/theming/light/important', - PR_PAID: 'atlas://gui/kivy/theming/light/confirmed', - PR_EXPIRED: 'atlas://gui/kivy/theming/light/close' + PR_UNPAID: 'atlas://electrum/gui/kivy/theming/light/important', + PR_UNKNOWN: 'atlas://electrum/gui/kivy/theming/light/important', + PR_PAID: 'atlas://electrum/gui/kivy/theming/light/confirmed', + PR_EXPIRED: 'atlas://electrum/gui/kivy/theming/light/close' } request_text = { PR_UNPAID: _('Pending'), diff --git a/gui/kivy/uix/dialogs/seed_options.py b/electrum/gui/kivy/uix/dialogs/seed_options.py similarity index 100% rename from gui/kivy/uix/dialogs/seed_options.py rename to electrum/gui/kivy/uix/dialogs/seed_options.py diff --git a/gui/kivy/uix/dialogs/settings.py b/electrum/gui/kivy/uix/dialogs/settings.py similarity index 96% rename from gui/kivy/uix/dialogs/settings.py rename to electrum/gui/kivy/uix/dialogs/settings.py index 2927f8a3e370..1a1d6051899f 100644 --- a/gui/kivy/uix/dialogs/settings.py +++ b/electrum/gui/kivy/uix/dialogs/settings.py @@ -3,17 +3,17 @@ from kivy.properties import ObjectProperty from kivy.lang import Builder -from electrum_mona.util import base_units_list -from electrum_mona.i18n import languages -from electrum_mona_gui.kivy.i18n import _ -from electrum_mona.plugins import run_hook -from electrum_mona import coinchooser +from electrum.util import base_units_list +from electrum.i18n import languages +from electrum.gui.kivy.i18n import _ +from electrum.plugin import run_hook +from electrum import coinchooser from .choice_dialog import ChoiceDialog Builder.load_string(''' #:import partial functools.partial -#:import _ electrum_mona_gui.kivy.i18n._ +#:import _ electrum.gui.kivy.i18n._ id: settings @@ -173,7 +173,7 @@ def callback(popup): proxy = None self.app.network.set_parameters(server, port, protocol, proxy, auto_connect) item.status = self.proxy_status() - popup = Builder.load_file('gui/kivy/uix/ui_screens/proxy.kv') + popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/proxy.kv') popup.ids.mode.text = proxy.get('mode') if proxy else 'None' popup.ids.host.text = proxy.get('host') if proxy else '' popup.ids.port.text = proxy.get('port') if proxy else '' diff --git a/gui/kivy/uix/dialogs/tx_dialog.py b/electrum/gui/kivy/uix/dialogs/tx_dialog.py similarity index 96% rename from gui/kivy/uix/dialogs/tx_dialog.py rename to electrum/gui/kivy/uix/dialogs/tx_dialog.py index d6d6f80149dc..e847072d7dd3 100644 --- a/gui/kivy/uix/dialogs/tx_dialog.py +++ b/electrum/gui/kivy/uix/dialogs/tx_dialog.py @@ -5,9 +5,9 @@ from kivy.clock import Clock from kivy.uix.label import Label -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ from datetime import datetime -from electrum_mona.util import InvalidPassword +from electrum.util import InvalidPassword Builder.load_string(''' @@ -85,7 +85,7 @@ IconButton: size_hint: 0.5, None height: '48dp' - icon: 'atlas://gui/kivy/theming/light/qrcode' + icon: 'atlas://electrum/gui/kivy/theming/light/qrcode' on_release: root.show_qr() Button: size_hint: 0.5, None @@ -178,7 +178,7 @@ def do_broadcast(self): self.app.broadcast(self.tx) def show_qr(self): - from electrum_mona.bitcoin import base_encode, bfh + from electrum.bitcoin import base_encode, bfh text = bfh(str(self.tx)) text = base_encode(text, base=43) self.app.qr_dialog(_("Raw Transaction"), text) diff --git a/gui/kivy/uix/dialogs/wallets.py b/electrum/gui/kivy/uix/dialogs/wallets.py similarity index 97% rename from gui/kivy/uix/dialogs/wallets.py rename to electrum/gui/kivy/uix/dialogs/wallets.py index 67510b76cb48..d7b0469bf551 100644 --- a/gui/kivy/uix/dialogs/wallets.py +++ b/electrum/gui/kivy/uix/dialogs/wallets.py @@ -5,7 +5,7 @@ from kivy.properties import ObjectProperty from kivy.lang import Builder -from electrum_mona.util import base_units +from electrum.util import base_units from ...i18n import _ from .label_dialog import LabelDialog diff --git a/gui/kivy/uix/drawer.py b/electrum/gui/kivy/uix/drawer.py similarity index 100% rename from gui/kivy/uix/drawer.py rename to electrum/gui/kivy/uix/drawer.py diff --git a/gui/kivy/uix/gridview.py b/electrum/gui/kivy/uix/gridview.py similarity index 100% rename from gui/kivy/uix/gridview.py rename to electrum/gui/kivy/uix/gridview.py diff --git a/gui/kivy/uix/menus.py b/electrum/gui/kivy/uix/menus.py similarity index 98% rename from gui/kivy/uix/menus.py rename to electrum/gui/kivy/uix/menus.py index 5c28993dc598..a7cdaefe24e6 100644 --- a/gui/kivy/uix/menus.py +++ b/electrum/gui/kivy/uix/menus.py @@ -7,7 +7,7 @@ from kivy.properties import ListProperty from kivy.uix.widget import Widget -from electrum_mona_gui.kivy.i18n import _ +from ..i18n import _ class ContextMenuItem(Widget): '''abstract class diff --git a/gui/kivy/uix/qrcodewidget.py b/electrum/gui/kivy/uix/qrcodewidget.py similarity index 100% rename from gui/kivy/uix/qrcodewidget.py rename to electrum/gui/kivy/uix/qrcodewidget.py diff --git a/gui/kivy/uix/screens.py b/electrum/gui/kivy/uix/screens.py similarity index 93% rename from gui/kivy/uix/screens.py rename to electrum/gui/kivy/uix/screens.py index fc757e835bb4..38a97c03ed83 100644 --- a/gui/kivy/uix/screens.py +++ b/electrum/gui/kivy/uix/screens.py @@ -18,16 +18,16 @@ from kivy.factory import Factory from kivy.utils import platform -from electrum_mona.util import profiler, parse_URI, format_time, InvalidPassword, NotEnoughFunds, Fiat -from electrum_mona import bitcoin -from electrum_mona.util import timestamp_to_datetime -from electrum_mona.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED -from electrum_mona.plugins import run_hook +from electrum.util import profiler, parse_URI, format_time, InvalidPassword, NotEnoughFunds, Fiat +from electrum import bitcoin +from electrum.util import timestamp_to_datetime +from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED +from electrum.plugin import run_hook from .context_menu import ContextMenu -from electrum_mona_gui.kivy.i18n import _ +from electrum.gui.kivy.i18n import _ class HistoryRecycleView(RecycleView): pass @@ -61,7 +61,7 @@ def update(self): @profiler def load_screen(self): - self.screen = Builder.load_file('gui/kivy/uix/ui_screens/' + self.kvname + '.kv') + self.screen = Builder.load_file('electrum/gui/kivy/uix/ui_screens/' + self.kvname + '.kv') self.add_widget(self.screen) self.loaded = True self.update() @@ -133,7 +133,7 @@ def callback(text): def get_card(self, tx_hash, height, conf, timestamp, value, balance): status, status_str = self.app.wallet.get_tx_status(tx_hash, height, conf, timestamp) - icon = "atlas://gui/kivy/theming/light/" + TX_ICONS[status] + icon = "atlas://electrum/gui/kivy/theming/light/" + TX_ICONS[status] label = self.app.wallet.get_label(tx_hash) if tx_hash else _('Pruned transaction outputs') ri = {} ri['screen'] = self @@ -166,13 +166,17 @@ class SendScreen(CScreen): kvname = 'send' payment_request = None + payment_request_queued = None def set_URI(self, text): - import electrum_mona as electrum + if not self.app.wallet: + self.payment_request_queued = text + return + import electrum try: - uri = electrum_mona.util.parse_URI(text, self.app.on_pr) + uri = electrum.util.parse_URI(text, self.app.on_pr) except: - self.app.show_info(_("Not a Bitcoin URI")) + self.app.show_info(_("Not a Monacoin URI")) return amount = uri.get('amount') self.screen.address = uri.get('address', '') @@ -182,7 +186,9 @@ def set_URI(self, text): self.screen.is_pr = False def update(self): - pass + if self.app.wallet and self.payment_request_queued: + self.set_URI(self.payment_request_queued) + self.payment_request_queued = None def do_clear(self): self.screen.amount = '' @@ -210,7 +216,7 @@ def do_save(self): # it should be already saved return # save address as invoice - from electrum_mona.paymentrequest import make_unsigned_request, PaymentRequest + from electrum.paymentrequest import make_unsigned_request, PaymentRequest req = {'address':self.screen.address, 'memo':self.screen.message} amount = self.app.get_amount(self.screen.amount) if self.screen.amount else 0 req['amount'] = amount @@ -351,7 +357,7 @@ def on_address(self, addr): Clock.schedule_once(lambda dt: self.update_qr()) def get_URI(self): - from electrum_mona.util import create_URI + from electrum.util import create_URI amount = self.screen.amount if amount: a, u = self.screen.amount.split() diff --git a/gui/kivy/uix/ui_screens/about.kv b/electrum/gui/kivy/uix/ui_screens/about.kv similarity index 96% rename from gui/kivy/uix/ui_screens/about.kv rename to electrum/gui/kivy/uix/ui_screens/about.kv index 4f16c77b47b9..8d3798379a3d 100644 --- a/gui/kivy/uix/ui_screens/about.kv +++ b/electrum/gui/kivy/uix/ui_screens/about.kv @@ -1,4 +1,4 @@ -#:import VERSION electrum_mona.version.ELECTRUM_VERSION +#:import VERSION electrum.version.ELECTRUM_VERSION Popup: title: _("About Electrum-MONA") diff --git a/gui/kivy/uix/ui_screens/history.kv b/electrum/gui/kivy/uix/ui_screens/history.kv similarity index 92% rename from gui/kivy/uix/ui_screens/history.kv rename to electrum/gui/kivy/uix/ui_screens/history.kv index 03b2f968b86d..04988a70fad9 100644 --- a/gui/kivy/uix/ui_screens/history.kv +++ b/electrum/gui/kivy/uix/ui_screens/history.kv @@ -1,6 +1,6 @@ -#:import _ electrum_mona_gui.kivy.i18n._ +#:import _ electrum.gui.kivy.i18n._ #:import Factory kivy.factory.Factory -#:set font_light 'gui/kivy/data/fonts/Roboto-Condensed.ttf' +#:set font_light 'electrum/gui/kivy/data/fonts/Roboto-Condensed.ttf' #:set btc_symbol chr(171) #:set mbtc_symbol chr(187) @@ -17,7 +17,7 @@ - icon: 'atlas://gui/kivy/theming/light/important' + icon: 'atlas://electrum/gui/kivy/theming/light/important' message: '' is_mine: True amount: '--' diff --git a/gui/kivy/uix/ui_screens/invoice.kv b/electrum/gui/kivy/uix/ui_screens/invoice.kv similarity index 100% rename from gui/kivy/uix/ui_screens/invoice.kv rename to electrum/gui/kivy/uix/ui_screens/invoice.kv diff --git a/gui/kivy/uix/ui_screens/network.kv b/electrum/gui/kivy/uix/ui_screens/network.kv similarity index 100% rename from gui/kivy/uix/ui_screens/network.kv rename to electrum/gui/kivy/uix/ui_screens/network.kv diff --git a/gui/kivy/uix/ui_screens/proxy.kv b/electrum/gui/kivy/uix/ui_screens/proxy.kv similarity index 100% rename from gui/kivy/uix/ui_screens/proxy.kv rename to electrum/gui/kivy/uix/ui_screens/proxy.kv diff --git a/gui/kivy/uix/ui_screens/receive.kv b/electrum/gui/kivy/uix/ui_screens/receive.kv similarity index 90% rename from gui/kivy/uix/ui_screens/receive.kv rename to electrum/gui/kivy/uix/ui_screens/receive.kv index ad42e2b96271..574e16c00e6d 100644 --- a/gui/kivy/uix/ui_screens/receive.kv +++ b/electrum/gui/kivy/uix/ui_screens/receive.kv @@ -1,8 +1,8 @@ -#:import _ electrum_mona_gui.kivy.i18n._ +#:import _ electrum.gui.kivy.i18n._ #:import Decimal decimal.Decimal #:set btc_symbol chr(171) #:set mbtc_symbol chr(187) -#:set font_light 'gui/kivy/data/fonts/Roboto-Condensed.ttf' +#:set font_light 'electrum/gui/kivy/data/fonts/Roboto-Condensed.ttf' @@ -62,7 +62,7 @@ ReceiveScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/globe' + source: 'atlas://electrum/gui/kivy/theming/light/globe' size_hint: None, None size: '22dp', '22dp' pos_hint: {'center_y': .5} @@ -79,7 +79,7 @@ ReceiveScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/calculator' + source: 'atlas://electrum/gui/kivy/theming/light/calculator' opacity: 0.7 size_hint: None, None size: '22dp', '22dp' @@ -99,7 +99,7 @@ ReceiveScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/pen' + source: 'atlas://electrum/gui/kivy/theming/light/pen' size_hint: None, None size: '22dp', '22dp' pos_hint: {'center_y': .5} @@ -111,7 +111,7 @@ ReceiveScreen: size_hint: 1, None height: '48dp' IconButton: - icon: 'atlas://gui/kivy/theming/light/save' + icon: 'atlas://electrum/gui/kivy/theming/light/save' size_hint: 0.6, None height: '48dp' on_release: s.parent.do_save() @@ -126,7 +126,7 @@ ReceiveScreen: height: '48dp' on_release: s.parent.do_copy() IconButton: - icon: 'atlas://gui/kivy/theming/light/share' + icon: 'atlas://electrum/gui/kivy/theming/light/share' size_hint: 0.6, None height: '48dp' on_release: s.parent.do_share() diff --git a/gui/kivy/uix/ui_screens/send.kv b/electrum/gui/kivy/uix/ui_screens/send.kv similarity index 88% rename from gui/kivy/uix/ui_screens/send.kv rename to electrum/gui/kivy/uix/ui_screens/send.kv index 1451d1a121e5..88cbcc3a988b 100644 --- a/gui/kivy/uix/ui_screens/send.kv +++ b/electrum/gui/kivy/uix/ui_screens/send.kv @@ -1,8 +1,8 @@ -#:import _ electrum_mona_gui.kivy.i18n._ +#:import _ electrum.gui.kivy.i18n._ #:import Decimal decimal.Decimal #:set btc_symbol chr(171) #:set mbtc_symbol chr(187) -#:set font_light 'gui/kivy/data/fonts/Roboto-Condensed.ttf' +#:set font_light 'electrum/gui/kivy/data/fonts/Roboto-Condensed.ttf' SendScreen: @@ -25,7 +25,7 @@ SendScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/globe' + source: 'atlas://electrum/gui/kivy/theming/light/globe' size_hint: None, None size: '22dp', '22dp' pos_hint: {'center_y': .5} @@ -43,7 +43,7 @@ SendScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/calculator' + source: 'atlas://electrum/gui/kivy/theming/light/calculator' opacity: 0.7 size_hint: None, None size: '22dp', '22dp' @@ -63,7 +63,7 @@ SendScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/pen' + source: 'atlas://electrum/gui/kivy/theming/light/pen' size_hint: None, None size: '22dp', '22dp' pos_hint: {'center_y': .5} @@ -80,7 +80,7 @@ SendScreen: height: blue_bottom.item_height spacing: '5dp' Image: - source: 'atlas://gui/kivy/theming/light/star_big_inactive' + source: 'atlas://electrum/gui/kivy/theming/light/star_big_inactive' opacity: 0.7 size_hint: None, None size: '22dp', '22dp' @@ -96,7 +96,7 @@ SendScreen: IconButton: size_hint: 0.6, 1 on_release: s.parent.do_save() - icon: 'atlas://gui/kivy/theming/light/save' + icon: 'atlas://electrum/gui/kivy/theming/light/save' Button: text: _('Invoices') size_hint: 1, 1 @@ -108,7 +108,7 @@ SendScreen: id: qr size_hint: 0.6, 1 on_release: Clock.schedule_once(lambda dt: app.scan_qr(on_complete=app.on_qr)) - icon: 'atlas://gui/kivy/theming/light/camera' + icon: 'atlas://electrum/gui/kivy/theming/light/camera' BoxLayout: size_hint: 1, None height: '48dp' diff --git a/gui/kivy/uix/ui_screens/server.kv b/electrum/gui/kivy/uix/ui_screens/server.kv similarity index 100% rename from gui/kivy/uix/ui_screens/server.kv rename to electrum/gui/kivy/uix/ui_screens/server.kv diff --git a/gui/kivy/uix/ui_screens/status.kv b/electrum/gui/kivy/uix/ui_screens/status.kv similarity index 100% rename from gui/kivy/uix/ui_screens/status.kv rename to electrum/gui/kivy/uix/ui_screens/status.kv diff --git a/gui/qt/__init__.py b/electrum/gui/qt/__init__.py similarity index 95% rename from gui/qt/__init__.py rename to electrum/gui/qt/__init__.py index 53ca995e2085..390b6c348478 100644 --- a/gui/qt/__init__.py +++ b/electrum/gui/qt/__init__.py @@ -38,16 +38,16 @@ from PyQt5.QtCore import * import PyQt5.QtCore as QtCore -from electrum_mona.i18n import _, set_language -from electrum_mona.plugins import run_hook -from electrum_mona import WalletStorage -from electrum_mona.base_wizard import GoBack -# from electrum_mona.synchronizer import Synchronizer -# from electrum_mona.verifier import SPV -# from electrum_mona.util import DebugMem -from electrum_mona.util import (UserCancelled, print_error, +from electrum.i18n import _, set_language +from electrum.plugin import run_hook +from electrum.storage import WalletStorage +from electrum.base_wizard import GoBack +# from electrum.synchronizer import Synchronizer +# from electrum.verifier import SPV +# from electrum.util import DebugMem +from electrum.util import (UserCancelled, print_error, WalletFileException, BitcoinException) -# from electrum_mona.wallet import Abstract_Wallet +# from electrum.wallet import Abstract_Wallet from .installwizard import InstallWizard @@ -57,7 +57,7 @@ except Exception as e: print(e) print("Error: Could not find icons file.") - print("Please run 'pyrcc5 icons.qrc -o gui/qt/icons_rc.py', and reinstall Electrum") + print("Please run 'pyrcc5 icons.qrc -o electrum/gui/qt/icons_rc.py'") sys.exit(1) from .util import * # * needed for plugins diff --git a/gui/qt/address_dialog.py b/electrum/gui/qt/address_dialog.py similarity index 99% rename from gui/qt/address_dialog.py rename to electrum/gui/qt/address_dialog.py index 32e14b3ba145..9afd50adcbe2 100644 --- a/gui/qt/address_dialog.py +++ b/electrum/gui/qt/address_dialog.py @@ -23,7 +23,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from electrum_mona.i18n import _ +from electrum.i18n import _ from PyQt5.QtCore import * from PyQt5.QtGui import * diff --git a/gui/qt/address_list.py b/electrum/gui/qt/address_list.py similarity index 97% rename from gui/qt/address_list.py rename to electrum/gui/qt/address_list.py index 2cc579964a68..7217940f6c03 100644 --- a/gui/qt/address_list.py +++ b/electrum/gui/qt/address_list.py @@ -24,10 +24,10 @@ # SOFTWARE. import webbrowser -from electrum_mona.i18n import _ -from electrum_mona.util import block_explorer_URL -from electrum_mona.plugins import run_hook -from electrum_mona.bitcoin import is_address +from electrum.i18n import _ +from electrum.util import block_explorer_URL +from electrum.plugin import run_hook +from electrum.bitcoin import is_address from .util import * @@ -140,7 +140,7 @@ def on_update(self): self.setCurrentItem(address_item) def create_menu(self, position): - from electrum_mona.wallet import Multisig_Wallet + from electrum.wallet import Multisig_Wallet is_multisig = isinstance(self.wallet, Multisig_Wallet) can_delete = self.wallet.can_delete_address() selected = self.selectedItems() diff --git a/gui/qt/amountedit.py b/electrum/gui/qt/amountedit.py similarity index 97% rename from gui/qt/amountedit.py rename to electrum/gui/qt/amountedit.py index 66e1106eceac..7d802a4b669e 100644 --- a/gui/qt/amountedit.py +++ b/electrum/gui/qt/amountedit.py @@ -6,7 +6,7 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import (QLineEdit, QStyle, QStyleOptionFrame) -from electrum_mona.util import (format_satoshis_plain, decimal_point_to_base_unit_name, +from electrum.util import (format_satoshis_plain, decimal_point_to_base_unit_name, FEERATE_PRECISION, quantize_feerate) diff --git a/gui/qt/completion_text_edit.py b/electrum/gui/qt/completion_text_edit.py similarity index 99% rename from gui/qt/completion_text_edit.py rename to electrum/gui/qt/completion_text_edit.py index a131712e617c..4709b03d8bde 100644 --- a/gui/qt/completion_text_edit.py +++ b/electrum/gui/qt/completion_text_edit.py @@ -117,4 +117,4 @@ def is_special_key(self, e): te = CompletionTextEdit() te.set_completer(completer) te.show() - app.exec_() \ No newline at end of file + app.exec_() diff --git a/gui/qt/console.py b/electrum/gui/qt/console.py similarity index 99% rename from gui/qt/console.py rename to electrum/gui/qt/console.py index 79604cea1f43..d0b10a30d7be 100644 --- a/gui/qt/console.py +++ b/electrum/gui/qt/console.py @@ -6,8 +6,8 @@ from PyQt5 import QtCore from PyQt5 import QtGui from PyQt5 import QtWidgets -from electrum_mona import util -from electrum_mona.i18n import _ +from electrum import util +from electrum.i18n import _ if platform.system() == 'Windows': diff --git a/gui/qt/contact_list.py b/electrum/gui/qt/contact_list.py similarity index 96% rename from gui/qt/contact_list.py rename to electrum/gui/qt/contact_list.py index 0ec993805217..b13ee9ecbd41 100644 --- a/gui/qt/contact_list.py +++ b/electrum/gui/qt/contact_list.py @@ -24,10 +24,10 @@ # SOFTWARE. import webbrowser -from electrum_mona.i18n import _ -from electrum_mona.bitcoin import is_address -from electrum_mona.util import block_explorer_URL -from electrum_mona.plugins import run_hook +from electrum.i18n import _ +from electrum.bitcoin import is_address +from electrum.util import block_explorer_URL +from electrum.plugin import run_hook from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import ( diff --git a/gui/qt/exception_window.py b/electrum/gui/qt/exception_window.py similarity index 98% rename from gui/qt/exception_window.py rename to electrum/gui/qt/exception_window.py index 185c785ec569..1774a043fb5d 100644 --- a/gui/qt/exception_window.py +++ b/electrum/gui/qt/exception_window.py @@ -30,8 +30,8 @@ from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import * -from electrum_mona.i18n import _ -from electrum_mona.base_crash_reporter import BaseCrashReporter +from electrum.i18n import _ +from electrum.base_crash_reporter import BaseCrashReporter from .util import MessageBoxMixin diff --git a/gui/qt/fee_slider.py b/electrum/gui/qt/fee_slider.py similarity index 98% rename from gui/qt/fee_slider.py rename to electrum/gui/qt/fee_slider.py index 36db14d09fc6..04911d878219 100644 --- a/gui/qt/fee_slider.py +++ b/electrum/gui/qt/fee_slider.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import QSlider, QToolTip diff --git a/gui/qt/history_list.py b/electrum/gui/qt/history_list.py similarity index 97% rename from gui/qt/history_list.py rename to electrum/gui/qt/history_list.py index cf8028e697a8..73bdf970af03 100644 --- a/gui/qt/history_list.py +++ b/electrum/gui/qt/history_list.py @@ -26,14 +26,15 @@ import webbrowser import datetime -from electrum_mona.wallet import AddTransactionException, TX_HEIGHT_LOCAL +from electrum.address_synchronizer import TX_HEIGHT_LOCAL from .util import * -from electrum_mona.i18n import _ -from electrum_mona.util import block_explorer_URL, profiler +from electrum.i18n import _ +from electrum.util import block_explorer_URL, profiler, print_error try: - from electrum_mona.plot import plot_history, NothingToPlotException + from electrum.plot import plot_history, NothingToPlotException except: + print_error("qt/history_list: could not import electrum.plot. This feature needs matplotlib to be installed.") plot_history = None # note: this list needs to be kept in sync with another in kivy @@ -427,5 +428,5 @@ def do_export_history(self, wallet, fileName, is_csv): for line in lines: transaction.writerow(line) else: - from electrum_mona.util import json_encode + from electrum.util import json_encode f.write(json_encode(history)) diff --git a/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py similarity index 95% rename from gui/qt/installwizard.py rename to electrum/gui/qt/installwizard.py index f9cdab6e5187..64daaa1edf9f 100644 --- a/gui/qt/installwizard.py +++ b/electrum/gui/qt/installwizard.py @@ -8,10 +8,11 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import * -from electrum_mona import Wallet, WalletStorage -from electrum_mona.util import UserCancelled, InvalidPassword -from electrum_mona.base_wizard import BaseWizard, HWD_SETUP_DECRYPT_WALLET, GoBack -from electrum_mona.i18n import _ +from electrum.wallet import Wallet +from electrum.storage import WalletStorage +from electrum.util import UserCancelled, InvalidPassword +from electrum.base_wizard import BaseWizard, HWD_SETUP_DECRYPT_WALLET, GoBack +from electrum.i18n import _ from .seed_dialog import SeedLayout, KeysLayout from .network_dialog import NetworkChoiceLayout @@ -31,6 +32,12 @@ 'p2wpkh-p2sh:KxZcY47uGp9a... \t-> 3NhNeZQXF...\n' + 'p2wpkh:KxZcY47uGp9a... \t-> bc1q3fjfk...') # note: full key is KxZcY47uGp9aVQAb6VVvuBs8SwHKgkSR2DbZUzjDzXf2N2GPhG9n +MSG_PASSPHRASE_WARN_ISSUE4566 = _("Warning") + ": "\ + + _("You have multiple consecutive whitespaces or leading/trailing " + "whitespaces in your passphrase.") + " " \ + + _("This is discouraged.") + " " \ + + _("Due to a bug, old versions of Electrum will NOT be creating the " + "same wallet as newer versions or other software.") class CosignWidget(QWidget): @@ -549,17 +556,24 @@ def on_text_change(text): @wizard_dialog def line_dialog(self, run_next, title, message, default, test, warning='', - presets=()): + presets=(), warn_issue4566=False): vbox = QVBoxLayout() vbox.addWidget(WWLabel(message)) line = QLineEdit() line.setText(default) def f(text): self.next_button.setEnabled(test(text)) + if warn_issue4566: + text_whitespace_normalised = ' '.join(text.split()) + warn_issue4566_label.setVisible(text != text_whitespace_normalised) line.textEdited.connect(f) vbox.addWidget(line) vbox.addWidget(WWLabel(warning)) + warn_issue4566_label = WWLabel(MSG_PASSPHRASE_WARN_ISSUE4566) + warn_issue4566_label.setVisible(False) + vbox.addWidget(warn_issue4566_label) + for preset in presets: button = QPushButton(preset[0]) button.clicked.connect(lambda __, text=preset[1]: line.setText(text)) @@ -569,7 +583,7 @@ def f(text): vbox.addLayout(hbox) self.exec_layout(vbox, title, next_enabled=test(default)) - return ' '.join(line.text().split()) + return line.text() @wizard_dialog def show_xpub_dialog(self, xpub, run_next): diff --git a/gui/qt/invoice_list.py b/electrum/gui/qt/invoice_list.py similarity index 97% rename from gui/qt/invoice_list.py rename to electrum/gui/qt/invoice_list.py index 9f6057195965..462aadd852c3 100644 --- a/gui/qt/invoice_list.py +++ b/electrum/gui/qt/invoice_list.py @@ -23,8 +23,8 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from electrum_mona.i18n import _ -from electrum_mona.util import format_time +from electrum.i18n import _ +from electrum.util import format_time from .util import * diff --git a/gui/qt/main_window.py b/electrum/gui/qt/main_window.py similarity index 99% rename from gui/qt/main_window.py rename to electrum/gui/qt/main_window.py index 5e81c188cf1e..9d42c83a7bb7 100644 --- a/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -39,21 +39,20 @@ from .exception_window import Exception_Hook from PyQt5.QtWidgets import * -from electrum_mona import keystore, simple_config, ecc -from electrum_mona.bitcoin import COIN, is_address, TYPE_ADDRESS -from electrum_mona import constants -from electrum_mona.plugins import run_hook -from electrum_mona.i18n import _ -from electrum_mona.util import (format_time, format_satoshis, format_fee_satoshis, +from electrum import (keystore, simple_config, ecc, constants, util, bitcoin, commands, + coinchooser, paymentrequest) +from electrum.bitcoin import COIN, is_address, TYPE_ADDRESS +from electrum.plugin import run_hook +from electrum.i18n import _ +from electrum.util import (format_time, format_satoshis, format_fee_satoshis, format_satoshis_plain, NotEnoughFunds, PrintError, UserCancelled, NoDynamicFeeEstimates, profiler, export_meta, import_meta, bh2u, bfh, InvalidPassword, base_units, base_units_list, base_unit_name_to_decimal_point, decimal_point_to_base_unit_name, quantize_feerate) -from electrum_mona import Transaction -from electrum_mona import util, bitcoin, commands, coinchooser -from electrum_mona import paymentrequest -from electrum_mona.wallet import Multisig_Wallet, AddTransactionException, CannotBumpFee +from electrum.transaction import Transaction +from electrum.address_synchronizer import AddTransactionException +from electrum.wallet import Multisig_Wallet, CannotBumpFee from .amountedit import AmountEdit, BTCAmountEdit, MyLineEdit, FeerateEdit from .qrcodewidget import QRCodeWidget, QRDialog @@ -82,7 +81,7 @@ def keyPressEvent(self, e): self.func() -from electrum_mona.paymentrequest import PR_PAID +from electrum.paymentrequest import PR_PAID class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): @@ -284,7 +283,10 @@ def bring_to_top(self): def on_error(self, exc_info): if not isinstance(exc_info[1], UserCancelled): - traceback.print_exception(*exc_info) + try: + traceback.print_exception(*exc_info) + except OSError: + pass # see #4418; try to at least show popup: self.show_error(str(exc_info[1])) def on_network(self, event, *args): @@ -1126,7 +1128,7 @@ def fee_cb(dyn, pos, fee_rate): def on_fee_or_feerate(edit_changed, editing_finished): edit_other = self.feerate_e if edit_changed == self.fee_e else self.fee_e if editing_finished: - if not edit_changed.get_amount(): + if edit_changed.get_amount() is None: # This is so that when the user blanks the fee and moves on, # we go back to auto-calculate mode and put a fee back. edit_changed.setModified(False) @@ -1346,7 +1348,7 @@ def do_update_fee(self): # actual fees often differ somewhat. if freeze_feerate or self.fee_slider.is_active(): displayed_feerate = self.feerate_e.get_amount() - if displayed_feerate: + if displayed_feerate is not None: displayed_feerate = quantize_feerate(displayed_feerate) else: # fallback to actual fee @@ -1965,7 +1967,7 @@ def update_buttons_on_seed(self): self.send_button.setVisible(not self.wallet.is_watching_only()) def change_password_dialog(self): - from electrum_mona.storage import STO_EV_XPUB_PW + from electrum.storage import STO_EV_XPUB_PW if self.wallet.get_available_storage_encryption_version() == STO_EV_XPUB_PW: from .password_dialog import ChangePasswordDialogForHW d = ChangePasswordDialogForHW(self, self.wallet) @@ -2308,7 +2310,7 @@ def password_dialog(self, msg=None, parent=None): return d.run() def tx_from_text(self, txt): - from electrum_mona.transaction import tx_from_str + from electrum.transaction import tx_from_str try: tx = tx_from_str(txt) return Transaction(tx) @@ -2317,7 +2319,7 @@ def tx_from_text(self, txt): return def read_tx_from_qrcode(self): - from electrum_mona import qrscanner + from electrum import qrscanner try: data = qrscanner.scan_barcode(self.config.get_video_device()) except BaseException as e: @@ -2366,7 +2368,7 @@ def do_process_from_file(self): self.show_transaction(tx) def do_process_from_txid(self): - from electrum_mona import transaction + from electrum import transaction txid, ok = QInputDialog.getText(self, _('Lookup transaction'), _('Transaction ID') + ':') if ok and txid: txid = str(txid).strip() @@ -2549,7 +2551,7 @@ def get_pk_old(): address_e.textChanged.connect(on_address) if not d.exec_(): return - from electrum_mona.wallet import sweep_preparations + from electrum.wallet import sweep_preparations try: self.do_clear() if get_pk() is not None: @@ -2627,7 +2629,7 @@ def settings_dialog(self): lang_help = _('Select which language is used in the GUI (after restart).') lang_label = HelpLabel(_('Language') + ':', lang_help) lang_combo = QComboBox() - from electrum_mona.i18n import languages + from electrum.i18n import languages lang_combo.addItems(list(languages.values())) lang_keys = list(languages.keys()) lang_cur_setting = self.config.get("language", '') @@ -2791,7 +2793,7 @@ def on_be(x): block_ex_combo.currentIndexChanged.connect(on_be) gui_widgets.append((block_ex_label, block_ex_combo)) - from electrum_mona import qrscanner + from electrum import qrscanner system_cameras = qrscanner._find_system_cameras() qr_combo = QComboBox() qr_combo.addItem("Default","default") @@ -3089,7 +3091,8 @@ def do_toggle(cb, name, i): run_hook('init_qt', self.gui_object) for i, descr in enumerate(plugins.descriptions.values()): - name = descr['__name__'] + full_name = descr['__name__'] + prefix, _separator, name = full_name.rpartition('.') p = plugins.get(name) if descr.get('registers_keystore'): continue diff --git a/gui/qt/network_dialog.py b/electrum/gui/qt/network_dialog.py similarity index 99% rename from gui/qt/network_dialog.py rename to electrum/gui/qt/network_dialog.py index d39e448ae81c..f9a1f7da7367 100644 --- a/gui/qt/network_dialog.py +++ b/electrum/gui/qt/network_dialog.py @@ -30,10 +30,10 @@ from PyQt5.QtWidgets import * import PyQt5.QtCore as QtCore -from electrum_mona.i18n import _ -from electrum_mona import constants -from electrum_mona.util import print_error -from electrum_mona.network import serialize_server, deserialize_server +from electrum.i18n import _ +from electrum import constants +from electrum.util import print_error +from electrum.network import serialize_server, deserialize_server from .util import * diff --git a/gui/qt/password_dialog.py b/electrum/gui/qt/password_dialog.py similarity index 99% rename from gui/qt/password_dialog.py rename to electrum/gui/qt/password_dialog.py index b1a07feb8c13..ecaf781c966b 100644 --- a/gui/qt/password_dialog.py +++ b/electrum/gui/qt/password_dialog.py @@ -26,12 +26,12 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import * from PyQt5.QtWidgets import * -from electrum_mona.i18n import _ +from electrum.i18n import _ from .util import * import re import math -from electrum_mona.plugins import run_hook +from electrum.plugin import run_hook def check_password_strength(password): diff --git a/gui/qt/paytoedit.py b/electrum/gui/qt/paytoedit.py similarity index 98% rename from gui/qt/paytoedit.py rename to electrum/gui/qt/paytoedit.py index 649b43c338da..5c9e2d53c12a 100644 --- a/gui/qt/paytoedit.py +++ b/electrum/gui/qt/paytoedit.py @@ -27,8 +27,8 @@ import re from decimal import Decimal -from electrum_mona import bitcoin -from electrum_mona.util import bfh +from electrum import bitcoin +from electrum.util import bfh from .qrtextedit import ScanQRTextEdit from .completion_text_edit import CompletionTextEdit @@ -89,7 +89,7 @@ def parse_output(self, x): return bitcoin.TYPE_SCRIPT, script def parse_script(self, x): - from electrum_mona.transaction import opcodes, push_script + from electrum.transaction import opcodes, push_script script = '' for word in x.split(): if word[0:3] == 'OP_': diff --git a/gui/qt/qrcodewidget.py b/electrum/gui/qt/qrcodewidget.py similarity index 97% rename from gui/qt/qrcodewidget.py rename to electrum/gui/qt/qrcodewidget.py index 8a7a78ffa75a..dc444d6a5fd3 100644 --- a/gui/qt/qrcodewidget.py +++ b/electrum/gui/qt/qrcodewidget.py @@ -8,8 +8,8 @@ import os import qrcode -import electrum_mona -from electrum_mona.i18n import _ +import electrum +from electrum.i18n import _ from .util import WindowModalDialog @@ -102,7 +102,7 @@ def __init__(self, data, parent=None, title = "", show_text=False): hbox = QHBoxLayout() hbox.addStretch(1) - config = electrum_mona.get_config() + config = electrum.get_config() if config: filename = os.path.join(config.path, "qrcode.png") diff --git a/gui/qt/qrtextedit.py b/electrum/gui/qt/qrtextedit.py similarity index 94% rename from gui/qt/qrtextedit.py rename to electrum/gui/qt/qrtextedit.py index 3d6490e99945..6f3d1e057bdd 100644 --- a/gui/qt/qrtextedit.py +++ b/electrum/gui/qt/qrtextedit.py @@ -1,6 +1,6 @@ -from electrum_mona.i18n import _ -from electrum_mona.plugins import run_hook +from electrum.i18n import _ +from electrum.plugin import run_hook from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import QFileDialog @@ -55,7 +55,7 @@ def file_input(self): self.setText(data) def qr_input(self): - from electrum_mona import qrscanner, get_config + from electrum import qrscanner, get_config try: data = qrscanner.scan_barcode(get_config().get_video_device()) except BaseException as e: diff --git a/gui/qt/qrwindow.py b/electrum/gui/qt/qrwindow.py similarity index 97% rename from gui/qt/qrwindow.py rename to electrum/gui/qt/qrwindow.py index 293c2be3caea..9abcc26f9b8b 100644 --- a/gui/qt/qrwindow.py +++ b/electrum/gui/qt/qrwindow.py @@ -29,8 +29,8 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QLabel, QWidget -from electrum_mona_gui.qt.qrcodewidget import QRCodeWidget -from electrum_mona.i18n import _ +from .qrcodewidget import QRCodeWidget +from electrum.i18n import _ if platform.system() == 'Windows': MONOSPACE_FONT = 'Lucida Console' diff --git a/gui/qt/request_list.py b/electrum/gui/qt/request_list.py similarity index 96% rename from gui/qt/request_list.py rename to electrum/gui/qt/request_list.py index d8e6ed8f1be1..7b55c5d8efe6 100644 --- a/gui/qt/request_list.py +++ b/electrum/gui/qt/request_list.py @@ -23,10 +23,10 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from electrum_mona.i18n import _ -from electrum_mona.util import format_time, age -from electrum_mona.plugins import run_hook -from electrum_mona.paymentrequest import PR_UNKNOWN +from electrum.i18n import _ +from electrum.util import format_time, age +from electrum.plugin import run_hook +from electrum.paymentrequest import PR_UNKNOWN from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import QTreeWidgetItem, QMenu diff --git a/gui/qt/seed_dialog.py b/electrum/gui/qt/seed_dialog.py similarity index 95% rename from gui/qt/seed_dialog.py rename to electrum/gui/qt/seed_dialog.py index 3e25ee837cab..3e6c79d75a8d 100644 --- a/gui/qt/seed_dialog.py +++ b/electrum/gui/qt/seed_dialog.py @@ -23,10 +23,10 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from electrum_mona.i18n import _ -from electrum_mona.mnemonic import Mnemonic -import electrum_mona.old_mnemonic -from electrum_mona.plugins import run_hook +from electrum.i18n import _ +from electrum.mnemonic import Mnemonic +import electrum.old_mnemonic +from electrum.plugin import run_hook from .util import * @@ -145,7 +145,7 @@ def __init__(self, seed=None, title=None, icon=True, msg=None, options=None, def initialize_completer(self): english_list = Mnemonic('en').wordlist - old_list = electrum_mona.old_mnemonic.words + old_list = electrum.old_mnemonic.words self.wordlist = english_list + list(set(old_list) - set(english_list)) #concat both lists self.wordlist.sort() self.completer = QCompleter(self.wordlist) @@ -156,14 +156,14 @@ def get_seed(self): return ' '.join(text.split()) def on_edit(self): - from electrum_mona.bitcoin import seed_type + from electrum.bitcoin import seed_type s = self.get_seed() b = self.is_seed(s) if not self.is_bip39: t = seed_type(s) label = _('Seed Type') + ': ' + t if t else '' else: - from electrum_mona.keystore import bip39_is_checksum_valid + from electrum.keystore import bip39_is_checksum_valid is_checksum, is_wordlist = bip39_is_checksum_valid(s) status = ('checksum: ' + ('ok' if is_checksum else 'failed')) if is_wordlist else 'unknown wordlist' label = 'BIP39' + ' (%s)'%status @@ -207,5 +207,6 @@ def __init__(self, parent, seed, passphrase): title = _("Your wallet generation seed is:") slayout = SeedLayout(title=title, seed=seed, msg=True, passphrase=passphrase) vbox.addLayout(slayout) - run_hook('set_seed', seed, slayout.seed_e) + has_extension = True if passphrase else False + run_hook('set_seed', seed, has_extension, slayout.seed_e) vbox.addLayout(Buttons(CloseButton(self))) diff --git a/gui/qt/transaction_dialog.py b/electrum/gui/qt/transaction_dialog.py similarity index 95% rename from gui/qt/transaction_dialog.py rename to electrum/gui/qt/transaction_dialog.py index db4f1f30d8e5..66d47f6f7c75 100644 --- a/gui/qt/transaction_dialog.py +++ b/electrum/gui/qt/transaction_dialog.py @@ -31,14 +31,13 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import * -from electrum_mona.bitcoin import base_encode -from electrum_mona.i18n import _ -from electrum_mona.plugins import run_hook -from electrum_mona import simple_config +from electrum.bitcoin import base_encode +from electrum.i18n import _ +from electrum.plugin import run_hook +from electrum import simple_config -from electrum_mona.util import bfh -from electrum_mona.wallet import AddTransactionException -from electrum_mona.transaction import SerializationError +from electrum.util import bfh +from electrum.transaction import SerializationError from .util import * @@ -278,10 +277,15 @@ def add_io(self, vbox): chg = QTextCharFormat() chg.setBackground(QBrush(ColorScheme.YELLOW.as_color(background=True))) chg.setToolTip(_("Wallet change address")) + twofactor = QTextCharFormat() + twofactor.setBackground(QBrush(ColorScheme.BLUE.as_color(background=True))) + twofactor.setToolTip(_("TrustedCoin (2FA) fee for the next batch of transactions")) def text_format(addr): if self.wallet.is_mine(addr): return chg if self.wallet.is_change(addr) else rec + elif self.wallet.is_billing_address(addr): + return twofactor return ext def format_amount(amt): diff --git a/gui/qt/util.py b/electrum/gui/qt/util.py similarity index 99% rename from gui/qt/util.py rename to electrum/gui/qt/util.py index 0a8a29045c9d..50ed0a5c34a2 100644 --- a/gui/qt/util.py +++ b/electrum/gui/qt/util.py @@ -10,9 +10,9 @@ from PyQt5.QtCore import * from PyQt5.QtWidgets import * -from electrum_mona.i18n import _ -from electrum_mona.util import FileImportFailed, FileExportFailed -from electrum_mona.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED +from electrum.i18n import _ +from electrum.util import FileImportFailed, FileExportFailed +from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_EXPIRED if platform.system() == 'Windows': diff --git a/gui/qt/utxo_list.py b/electrum/gui/qt/utxo_list.py similarity index 99% rename from gui/qt/utxo_list.py rename to electrum/gui/qt/utxo_list.py index e4fa18754b83..75831de60283 100644 --- a/gui/qt/utxo_list.py +++ b/electrum/gui/qt/utxo_list.py @@ -24,7 +24,7 @@ # SOFTWARE. from .util import * -from electrum_mona.i18n import _ +from electrum.i18n import _ class UTXOList(MyTreeWidget): diff --git a/gui/stdio.py b/electrum/gui/stdio.py similarity index 97% rename from gui/stdio.py rename to electrum/gui/stdio.py index 82d9f8868783..41bb5dde0675 100644 --- a/gui/stdio.py +++ b/electrum/gui/stdio.py @@ -1,9 +1,9 @@ from decimal import Decimal _ = lambda x:x #from i18n import _ -from electrum_mona import WalletStorage, Wallet -from electrum_mona.util import format_satoshis, set_verbosity -from electrum_mona.bitcoin import is_address, COIN, TYPE_ADDRESS +from electrum import WalletStorage, Wallet +from electrum.util import format_satoshis, set_verbosity +from electrum.bitcoin import is_address, COIN, TYPE_ADDRESS import getpass, datetime # minimal fdisk like gui for console usage diff --git a/gui/text.py b/electrum/gui/text.py similarity index 98% rename from gui/text.py rename to electrum/gui/text.py index cb3911dbbfd8..38fccd9277b9 100644 --- a/gui/text.py +++ b/electrum/gui/text.py @@ -3,10 +3,10 @@ from decimal import Decimal import getpass -import electrum_mona as electrum -from electrum_mona.util import format_satoshis, set_verbosity -from electrum_mona.bitcoin import is_address, COIN, TYPE_ADDRESS -from electrum_mona import Wallet, WalletStorage +import electrum +from electrum.util import format_satoshis, set_verbosity +from electrum.bitcoin import is_address, COIN, TYPE_ADDRESS +from .. import Wallet, WalletStorage _ = lambda x:x @@ -392,7 +392,7 @@ def network_dialog(self): self.show_message("Error:" + server + "\nIn doubt, type \"auto-connect\"") return False if out.get('server') or out.get('proxy'): - proxy = electrum_mona.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config + proxy = electrum.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config self.network.set_parameters(host, port, protocol, proxy, auto_connect) def settings_dialog(self): diff --git a/lib/i18n.py b/electrum/i18n.py similarity index 100% rename from lib/i18n.py rename to electrum/i18n.py diff --git a/lib/interface.py b/electrum/interface.py similarity index 100% rename from lib/interface.py rename to electrum/interface.py diff --git a/lib/jsonrpc.py b/electrum/jsonrpc.py similarity index 100% rename from lib/jsonrpc.py rename to electrum/jsonrpc.py diff --git a/lib/keystore.py b/electrum/keystore.py similarity index 98% rename from lib/keystore.py rename to electrum/keystore.py index 5b44e6702536..a36fb1f0b24c 100644 --- a/lib/keystore.py +++ b/electrum/keystore.py @@ -26,15 +26,14 @@ from unicodedata import normalize -from . import bitcoin, ecc +from . import bitcoin, ecc, constants from .bitcoin import * from .ecc import string_to_number, number_to_string from .crypto import pw_decode, pw_encode -from . import constants from .util import (PrintError, InvalidPassword, hfu, WalletFileException, BitcoinException) from .mnemonic import Mnemonic, load_wordlist -from .plugins import run_hook +from .plugin import run_hook class KeyStore(PrintError): @@ -553,13 +552,12 @@ def bip39_normalize_passphrase(passphrase): return normalize('NFKD', passphrase or '') def bip39_to_seed(mnemonic, passphrase): - import pbkdf2, hashlib, hmac + import hashlib, hmac PBKDF2_ROUNDS = 2048 mnemonic = normalize('NFKD', ' '.join(mnemonic.split())) passphrase = bip39_normalize_passphrase(passphrase) - return pbkdf2.PBKDF2(mnemonic, 'mnemonic' + passphrase, - iterations = PBKDF2_ROUNDS, macmodule = hmac, - digestmodule = hashlib.sha512).read(64) + return hashlib.pbkdf2_hmac('sha512', mnemonic.encode('utf-8'), + b'mnemonic' + passphrase.encode('utf-8'), iterations = PBKDF2_ROUNDS) # returns tuple (is_checksum_valid, is_wordlist_valid) def bip39_is_checksum_valid(mnemonic): @@ -666,7 +664,7 @@ def hardware_keystore(d): if hw_type in hw_keystores: constructor = hw_keystores[hw_type] return constructor(d) - raise WalletFileException('unknown hardware type: {}'.format(hw_type)) + raise WalletFileException('unknown hardware type: {}. hw_keystores: {}'.format(hw_type, list(hw_keystores.keys()))) def load_keystore(storage, name): d = storage.get(name, {}) diff --git a/lib/mnemonic.py b/electrum/mnemonic.py similarity index 97% rename from lib/mnemonic.py rename to electrum/mnemonic.py index 17c2cafca5d9..a22913ae3559 100644 --- a/lib/mnemonic.py +++ b/electrum/mnemonic.py @@ -30,7 +30,6 @@ import string import ecdsa -import pbkdf2 from .util import print_error from .bitcoin import is_old_seed, is_new_seed @@ -131,7 +130,7 @@ def mnemonic_to_seed(self, mnemonic, passphrase): PBKDF2_ROUNDS = 2048 mnemonic = normalize_text(mnemonic) passphrase = normalize_text(passphrase) - return pbkdf2.PBKDF2(mnemonic, 'electrum' + passphrase, iterations = PBKDF2_ROUNDS, macmodule = hmac, digestmodule = hashlib.sha512).read(64) + return hashlib.pbkdf2_hmac('sha512', mnemonic.encode('utf-8'), b'electrum' + passphrase.encode('utf-8'), iterations = PBKDF2_ROUNDS) def mnemonic_encode(self, i): n = len(self.wordlist) diff --git a/lib/msqr.py b/electrum/msqr.py similarity index 100% rename from lib/msqr.py rename to electrum/msqr.py diff --git a/lib/network.py b/electrum/network.py similarity index 97% rename from lib/network.py rename to electrum/network.py index 5eda9629fb7d..1fff4cfa7678 100644 --- a/lib/network.py +++ b/electrum/network.py @@ -47,6 +47,7 @@ from . import blockchain from .version import ELECTRUM_VERSION, PROTOCOL_VERSION from .i18n import _ +from .blockchain import InvalidHeader NODES_RETRY_INTERVAL = 60 @@ -78,6 +79,7 @@ def parse_servers(result): servers[host] = out return servers + def filter_version(servers): def is_recent(version): try: @@ -87,7 +89,7 @@ def is_recent(version): return {k: v for k, v in servers.items() if is_recent(v.get('version'))} -def filter_protocol(hostmap, protocol = 's'): +def filter_protocol(hostmap, protocol='s'): '''Filters the hostmap for those implementing protocol. The result is a list in serialized form.''' eligible = [] @@ -97,12 +99,14 @@ def filter_protocol(hostmap, protocol = 's'): eligible.append(serialize_server(host, port, protocol)) return eligible + def pick_random_server(hostmap = None, protocol = 's', exclude_set = set()): if hostmap is None: hostmap = constants.net.DEFAULT_SERVERS eligible = list(set(filter_protocol(hostmap, protocol)) - exclude_set) return random.choice(eligible) if eligible else None + from .simple_config import SimpleConfig proxy_modes = ['socks4', 'socks5', 'http'] @@ -199,7 +203,7 @@ def __init__(self, config=None): self.pending_sends = [] self.message_id = 0 self.debug = False - self.irc_servers = {} # returned by interface (list from irc) + self.irc_servers = {} # returned by interface (list from irc) self.recent_servers = self.read_recent_servers() # note: needs self.recent_servers_lock self.banner = '' @@ -211,7 +215,7 @@ def __init__(self, config=None): # callbacks set by the GUI self.callbacks = defaultdict(list) # note: needs self.callback_lock - dir_path = os.path.join( self.config.path, 'certs') + dir_path = os.path.join(self.config.path, 'certs') util.make_dir(dir_path) # subscriptions and requests @@ -310,9 +314,6 @@ def is_connected(self): def is_connecting(self): return self.connection_status == 'connecting' - def is_up_to_date(self): - return self.unanswered_requests == {} - @with_interface_lock def queue_request(self, method, params, interface=None): # If you want to queue a request on any interface it must go @@ -404,7 +405,7 @@ def get_servers(self): except: continue if host not in out: - out[host] = { protocol:port } + out[host] = {protocol: port} return out @with_interface_lock @@ -414,7 +415,7 @@ def start_interface(self, server): self.print_error("connecting to %s as new interface" % server) self.set_status('connecting') self.connecting.add(server) - c = Connection(server, self.socket_queue, self.config.path) + Connection(server, self.socket_queue, self.config.path) def start_random_interface(self): with self.interface_lock: @@ -527,9 +528,10 @@ def set_parameters(self, host, port, protocol, proxy, auto_connect): self.auto_connect = auto_connect if self.proxy != proxy or self.protocol != protocol: # Restart the network defaulting to the given server - self.stop_network() - self.default_server = server - self.start_network(protocol, proxy) + with self.interface_lock: + self.stop_network() + self.default_server = server + self.start_network(protocol, proxy) elif self.default_server != server: self.switch_to_interface(server) else: @@ -550,7 +552,7 @@ def switch_lagging_interface(self): if self.server_is_lagging() and self.auto_connect: # switch to one that has the correct header (not height) header = self.blockchain().read_header(self.get_local_height()) - filtered = list(map(lambda x:x[0], filter(lambda x: x[1].tip_header==header, self.interfaces.items()))) + filtered = list(map(lambda x: x[0], filter(lambda x: x[1].tip_header == header, self.interfaces.items()))) if filtered: choice = random.choice(filtered) self.switch_to_interface(choice) @@ -566,6 +568,7 @@ def switch_to_interface(self, server): self.interface = None self.start_interface(server) return + i = self.interfaces[server] if self.interface != i: self.print_error("switching to", server) @@ -598,7 +601,7 @@ def add_recent_server(self, server): def process_response(self, interface, response, callbacks): if self.debug: - self.print_error("<--", response) + self.print_error(interface.host, "<--", response) error = response.get('error') result = response.get('result') method = response.get('method') @@ -798,6 +801,7 @@ def maintain_sockets(self): server, socket = self.socket_queue.get() if server in self.connecting: self.connecting.remove(server) + if socket: self.new_interface(server, socket) else: @@ -1010,6 +1014,7 @@ def on_get_header(self, interface, response): interface.mode = 'default' interface.request = None self.notify('updated') + # refresh network dialog self.notify('interfaces') @@ -1068,8 +1073,17 @@ def run(self): self.on_stop() def on_notify_header(self, interface, header_dict): - header_hex, height = header_dict['hex'], header_dict['height'] - header = blockchain.deserialize_header(util.bfh(header_hex), height) + try: + header_hex, height = header_dict['hex'], header_dict['height'] + except KeyError: + # no point in keeping this connection without headers sub + self.connection_down(interface.server) + return + try: + header = blockchain.deserialize_header(util.bfh(header_hex), height) + except InvalidHeader: + self.connection_down(interface.server) + return if height < self.max_checkpoint(): self.connection_down(interface.server) return diff --git a/lib/old_mnemonic.py b/electrum/old_mnemonic.py similarity index 100% rename from lib/old_mnemonic.py rename to electrum/old_mnemonic.py diff --git a/lib/paymentrequest.proto b/electrum/paymentrequest.proto similarity index 100% rename from lib/paymentrequest.proto rename to electrum/paymentrequest.proto diff --git a/lib/paymentrequest.py b/electrum/paymentrequest.py similarity index 98% rename from lib/paymentrequest.py rename to electrum/paymentrequest.py index db7ffb58c733..1739ba28cd27 100644 --- a/lib/paymentrequest.py +++ b/electrum/paymentrequest.py @@ -35,16 +35,11 @@ try: from . import paymentrequest_pb2 as pb2 except ImportError: - sys.exit("Error: could not find paymentrequest_pb2.py. Create it with 'protoc --proto_path=lib/ --python_out=lib/ lib/paymentrequest.proto'") + sys.exit("Error: could not find paymentrequest_pb2.py. Create it with 'protoc --proto_path=electrum/ --python_out=electrum/ electrum/paymentrequest.proto'") -from . import bitcoin -from . import ecc -from . import util +from . import bitcoin, ecc, util, transaction, x509, rsakey from .util import print_error, bh2u, bfh from .util import export_meta, import_meta -from . import transaction -from . import x509 -from . import rsakey from .bitcoin import TYPE_ADDRESS diff --git a/lib/paymentrequest_pb2.py b/electrum/paymentrequest_pb2.py similarity index 100% rename from lib/paymentrequest_pb2.py rename to electrum/paymentrequest_pb2.py diff --git a/lib/pem.py b/electrum/pem.py similarity index 100% rename from lib/pem.py rename to electrum/pem.py diff --git a/lib/plot.py b/electrum/plot.py similarity index 100% rename from lib/plot.py rename to electrum/plot.py diff --git a/lib/plugins.py b/electrum/plugin.py similarity index 97% rename from lib/plugins.py rename to electrum/plugin.py index 0dca6bd4ca83..c5223dc3764c 100644 --- a/lib/plugins.py +++ b/electrum/plugin.py @@ -35,6 +35,7 @@ from .i18n import _ from .util import profiler, PrintError, DaemonThread, UserCancelled, ThreadJob from . import bitcoin +from . import plugins plugin_loaders = {} hook_names = set() @@ -46,11 +47,6 @@ class Plugins(DaemonThread): @profiler def __init__(self, config, is_local, gui_name): DaemonThread.__init__(self) - if is_local: - find = imp.find_module('plugins') - plugins = imp.load_module('electrum_mona_plugins', *find) - else: - import electrum_mona_plugins as plugins self.pkgpath = os.path.dirname(plugins.__file__) self.config = config self.hw_wallets = {} @@ -64,10 +60,8 @@ def __init__(self, config, is_local, gui_name): def load_plugins(self): for loader, name, ispkg in pkgutil.iter_modules([self.pkgpath]): - # do not load deprecated plugins - if name in ['plot', 'exchange_rate']: - continue - m = loader.find_module(name).load_module(name) + mod = pkgutil.find_loader('electrum.plugins.' + name) + m = mod.load_module() d = m.__dict__ gui_good = self.gui_name in d.get('available_for', []) if not gui_good: @@ -95,12 +89,12 @@ def count(self): def load_plugin(self, name): if name in self.plugins: return self.plugins[name] - full_name = 'electrum_mona_plugins.' + name + '.' + self.gui_name + full_name = 'electrum.plugins.' + name + '.' + self.gui_name loader = pkgutil.find_loader(full_name) if not loader: raise RuntimeError("%s implementation for %s plugin not found" % (self.gui_name, name)) - p = loader.load_module(full_name) + p = loader.load_module() plugin = p.Plugin(self, self.config, name) self.add_jobs(plugin.thread_jobs()) self.plugins[name] = plugin @@ -138,7 +132,8 @@ def is_available(self, name, w): for dep, s in deps: try: __import__(dep) - except ImportError: + except ImportError as e: + self.print_error('Plugin', name, 'unavailable:', type(e).__name__, ':', str(e)) return False requires = d.get('requires_wallet_type', []) return not requires or w.wallet_type in requires diff --git a/plugins/README b/electrum/plugins/README similarity index 100% rename from plugins/README rename to electrum/plugins/README diff --git a/plugins/__init__.py b/electrum/plugins/__init__.py similarity index 100% rename from plugins/__init__.py rename to electrum/plugins/__init__.py diff --git a/plugins/audio_modem/__init__.py b/electrum/plugins/audio_modem/__init__.py similarity index 84% rename from plugins/audio_modem/__init__.py rename to electrum/plugins/audio_modem/__init__.py index 62617a25c6fb..46c2d2091e00 100644 --- a/plugins/audio_modem/__init__.py +++ b/electrum/plugins/audio_modem/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = _('Audio MODEM') description = _('Provides support for air-gapped transaction signing.') diff --git a/plugins/audio_modem/qt.py b/electrum/plugins/audio_modem/qt.py similarity index 94% rename from plugins/audio_modem/qt.py rename to electrum/plugins/audio_modem/qt.py index abbafefb354c..2b88df88596b 100644 --- a/plugins/audio_modem/qt.py +++ b/electrum/plugins/audio_modem/qt.py @@ -5,10 +5,10 @@ import sys import platform -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona_gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog -from electrum_mona.util import print_msg, print_error -from electrum_mona.i18n import _ +from electrum.plugin import BasePlugin, hook +from electrum.gui.qt.util import WaitingDialog, EnterButton, WindowModalDialog +from electrum.util import print_msg, print_error +from electrum.i18n import _ from PyQt5.QtGui import * from PyQt5.QtCore import * diff --git a/plugins/cosigner_pool/__init__.py b/electrum/plugins/cosigner_pool/__init__.py similarity index 91% rename from plugins/cosigner_pool/__init__.py rename to electrum/plugins/cosigner_pool/__init__.py index 5240e1e607ee..085b5095bfb6 100644 --- a/plugins/cosigner_pool/__init__.py +++ b/electrum/plugins/cosigner_pool/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = _('Cosigner Pool') description = ' '.join([ _("This plugin facilitates the use of multi-signatures wallets."), diff --git a/plugins/cosigner_pool/qt.py b/electrum/plugins/cosigner_pool/qt.py similarity index 95% rename from plugins/cosigner_pool/qt.py rename to electrum/plugins/cosigner_pool/qt.py index 9e1a7263ef87..6efe73b5a162 100644 --- a/plugins/cosigner_pool/qt.py +++ b/electrum/plugins/cosigner_pool/qt.py @@ -30,14 +30,14 @@ from PyQt5.QtCore import * from PyQt5.QtWidgets import QPushButton -from electrum_mona import bitcoin, util, keystore, ecc -from electrum_mona import transaction -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.i18n import _ -from electrum_mona.wallet import Multisig_Wallet -from electrum_mona.util import bh2u, bfh +from electrum import bitcoin, util, keystore, ecc +from electrum import transaction +from electrum.plugin import BasePlugin, hook +from electrum.i18n import _ +from electrum.wallet import Multisig_Wallet +from electrum.util import bh2u, bfh -from electrum_mona_gui.qt.transaction_dialog import show_transaction +from electrum.gui.qt.transaction_dialog import show_transaction import sys import traceback @@ -160,7 +160,7 @@ def transaction_dialog_update(self, d): d.cosigner_send_button.hide() def cosigner_can_sign(self, tx, cosigner_xpub): - from electrum_mona.keystore import is_xpubkey, parse_xpubkey + from electrum.keystore import is_xpubkey, parse_xpubkey xpub_set = set([]) for txin in tx.inputs(): for x_pubkey in txin['x_pubkeys']: diff --git a/plugins/digitalbitbox/__init__.py b/electrum/plugins/digitalbitbox/__init__.py similarity index 86% rename from plugins/digitalbitbox/__init__.py rename to electrum/plugins/digitalbitbox/__init__.py index 57fe431c78d8..5653d6161282 100644 --- a/plugins/digitalbitbox/__init__.py +++ b/electrum/plugins/digitalbitbox/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = 'Digital Bitbox' description = _('Provides support for Digital Bitbox hardware wallet') diff --git a/plugins/digitalbitbox/cmdline.py b/electrum/plugins/digitalbitbox/cmdline.py similarity index 90% rename from plugins/digitalbitbox/cmdline.py rename to electrum/plugins/digitalbitbox/cmdline.py index 260496663bd0..cf5d4005a896 100644 --- a/plugins/digitalbitbox/cmdline.py +++ b/electrum/plugins/digitalbitbox/cmdline.py @@ -1,4 +1,4 @@ -from electrum_mona.plugins import hook +from electrum.plugin import hook from .digitalbitbox import DigitalBitboxPlugin from ..hw_wallet import CmdLineHandler diff --git a/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py similarity index 97% rename from plugins/digitalbitbox/digitalbitbox.py rename to electrum/plugins/digitalbitbox/digitalbitbox.py index 903844fac7d0..0daf4478e06a 100644 --- a/plugins/digitalbitbox/digitalbitbox.py +++ b/electrum/plugins/digitalbitbox/digitalbitbox.py @@ -4,20 +4,19 @@ # try: - import electrum_mona - from electrum_mona.crypto import Hash, EncodeAES, DecodeAES - from electrum_mona.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh, is_address, + from electrum.crypto import Hash, EncodeAES, DecodeAES + from electrum.bitcoin import (TYPE_ADDRESS, push_script, var_int, public_key_to_p2pkh, is_address, serialize_xpub, deserialize_xpub) - from electrum_mona import ecc - from electrum_mona.ecc import msg_magic - from electrum_mona.wallet import Standard_Wallet - from electrum_mona import constants - from electrum_mona.transaction import Transaction - from electrum_mona.i18n import _ - from electrum_mona.keystore import Hardware_KeyStore + from electrum import ecc + from electrum.ecc import msg_magic + from electrum.wallet import Standard_Wallet + from electrum import constants + from electrum.transaction import Transaction + from electrum.i18n import _ + from electrum.keystore import Hardware_KeyStore from ..hw_wallet import HW_PluginBase - from electrum_mona.util import print_error, to_string, UserCancelled - from electrum_mona.base_wizard import ScriptTypeNotSupported, HWD_SETUP_NEW_WALLET + from electrum.util import print_error, to_string, UserCancelled + from electrum.base_wizard import ScriptTypeNotSupported, HWD_SETUP_NEW_WALLET import time import hid @@ -121,8 +120,8 @@ def dbb_has_password(self): def stretch_key(self, key): - import pbkdf2, hmac - return to_hexstr(pbkdf2.PBKDF2(key, b'Digital Bitbox', iterations = 20480, macmodule = hmac, digestmodule = hashlib.sha512).read(64)) + import hmac + return to_hexstr(hashlib.pbkdf2_hmac('sha512', key.encode('utf-8'), b'Digital Bitbox', iterations = 20480)) def backup_password_dialog(self): diff --git a/plugins/digitalbitbox/qt.py b/electrum/plugins/digitalbitbox/qt.py similarity index 90% rename from plugins/digitalbitbox/qt.py rename to electrum/plugins/digitalbitbox/qt.py index b170e690dd3d..594756969c64 100644 --- a/plugins/digitalbitbox/qt.py +++ b/electrum/plugins/digitalbitbox/qt.py @@ -3,9 +3,10 @@ from ..hw_wallet.qt import QtHandlerBase, QtPluginBase from .digitalbitbox import DigitalBitboxPlugin -from electrum_mona.i18n import _ -from electrum_mona.plugins import hook -from electrum_mona.wallet import Standard_Wallet +from electrum.i18n import _ +from electrum.plugin import hook +from electrum.wallet import Standard_Wallet + class Plugin(DigitalBitboxPlugin, QtPluginBase): icon_unpaired = ":icons/digitalbitbox_unpaired.png" diff --git a/plugins/email_requests/__init__.py b/electrum/plugins/email_requests/__init__.py similarity index 78% rename from plugins/email_requests/__init__.py rename to electrum/plugins/email_requests/__init__.py index 269521b7f764..8c9e824725eb 100644 --- a/plugins/email_requests/__init__.py +++ b/electrum/plugins/email_requests/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = _('Email') description = _("Send and receive payment request with an email account") diff --git a/plugins/email_requests/qt.py b/electrum/plugins/email_requests/qt.py similarity index 96% rename from plugins/email_requests/qt.py rename to electrum/plugins/email_requests/qt.py index c6ccf252b4fb..c5e2a10e3a2a 100644 --- a/plugins/email_requests/qt.py +++ b/electrum/plugins/email_requests/qt.py @@ -42,11 +42,11 @@ from PyQt5.QtWidgets import (QVBoxLayout, QLabel, QGridLayout, QLineEdit, QInputDialog) -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.paymentrequest import PaymentRequest -from electrum_mona.i18n import _ -from electrum_mona.util import PrintError -from electrum_mona_gui.qt.util import (EnterButton, Buttons, CloseButton, OkButton, +from electrum.plugin import BasePlugin, hook +from electrum.paymentrequest import PaymentRequest +from electrum.i18n import _ +from electrum.util import PrintError +from ...gui.qt.util import (EnterButton, Buttons, CloseButton, OkButton, WindowModalDialog, get_parent_main_window) @@ -175,7 +175,7 @@ def receive_list_menu(self, menu, addr): menu.addAction(_("Send via e-mail"), lambda: self.send(window, addr)) def send(self, window, addr): - from electrum_mona import paymentrequest + from electrum import paymentrequest r = window.wallet.receive_requests.get(addr) message = r.get('memo', '') if r.get('signature'): diff --git a/plugins/greenaddress_instant/__init__.py b/electrum/plugins/greenaddress_instant/__init__.py similarity index 82% rename from plugins/greenaddress_instant/__init__.py rename to electrum/plugins/greenaddress_instant/__init__.py index 13cec5527743..d2b317854be9 100644 --- a/plugins/greenaddress_instant/__init__.py +++ b/electrum/plugins/greenaddress_instant/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = 'GreenAddress instant' description = _("Allows validating if your transactions have instant confirmations by GreenAddress") diff --git a/plugins/greenaddress_instant/qt.py b/electrum/plugins/greenaddress_instant/qt.py similarity index 97% rename from plugins/greenaddress_instant/qt.py rename to electrum/plugins/greenaddress_instant/qt.py index 5c406e90f685..81e6686e1fb9 100644 --- a/plugins/greenaddress_instant/qt.py +++ b/electrum/plugins/greenaddress_instant/qt.py @@ -30,8 +30,8 @@ from PyQt5.QtWidgets import QApplication, QPushButton -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.i18n import _ +from electrum.plugin import BasePlugin, hook +from electrum.i18n import _ diff --git a/plugins/hw_wallet/__init__.py b/electrum/plugins/hw_wallet/__init__.py similarity index 100% rename from plugins/hw_wallet/__init__.py rename to electrum/plugins/hw_wallet/__init__.py diff --git a/plugins/hw_wallet/cmdline.py b/electrum/plugins/hw_wallet/cmdline.py similarity index 94% rename from plugins/hw_wallet/cmdline.py rename to electrum/plugins/hw_wallet/cmdline.py index ba3486c97505..de29780c7abc 100644 --- a/plugins/hw_wallet/cmdline.py +++ b/electrum/plugins/hw_wallet/cmdline.py @@ -1,4 +1,4 @@ -from electrum_mona.util import print_msg, print_error, raw_input +from electrum.util import print_msg, print_error, raw_input class CmdLineHandler: diff --git a/plugins/hw_wallet/plugin.py b/electrum/plugins/hw_wallet/plugin.py similarity index 96% rename from plugins/hw_wallet/plugin.py rename to electrum/plugins/hw_wallet/plugin.py index f8ce996e2942..a7f1b76e2a95 100644 --- a/plugins/hw_wallet/plugin.py +++ b/electrum/plugins/hw_wallet/plugin.py @@ -24,9 +24,9 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.i18n import _ -from electrum_mona.bitcoin import is_address +from electrum.plugin import BasePlugin, hook +from electrum.i18n import _ +from electrum.bitcoin import is_address class HW_PluginBase(BasePlugin): diff --git a/plugins/hw_wallet/qt.py b/electrum/plugins/hw_wallet/qt.py similarity index 96% rename from plugins/hw_wallet/qt.py rename to electrum/plugins/hw_wallet/qt.py index c46a473d61d8..214ea2b55918 100644 --- a/plugins/hw_wallet/qt.py +++ b/electrum/plugins/hw_wallet/qt.py @@ -27,11 +27,11 @@ import threading from PyQt5.Qt import QVBoxLayout, QLabel -from electrum_mona_gui.qt.password_dialog import PasswordDialog, PW_PASSPHRASE -from electrum_mona_gui.qt.util import * +from electrum.gui.qt.password_dialog import PasswordDialog, PW_PASSPHRASE +from electrum.gui.qt.util import * -from electrum_mona.i18n import _ -from electrum_mona.util import PrintError +from electrum.i18n import _ +from electrum.util import PrintError # The trickiest thing about this handler was getting windows properly # parented on macOS. @@ -177,9 +177,9 @@ def win_yes_no_question(self, msg): -from electrum_mona.plugins import hook -from electrum_mona.util import UserCancelled -from electrum_mona_gui.qt.main_window import StatusBarButton +from electrum.plugin import hook +from electrum.util import UserCancelled +from electrum.gui.qt.main_window import StatusBarButton class QtPluginBase(object): diff --git a/plugins/keepkey/__init__.py b/electrum/plugins/keepkey/__init__.py similarity index 88% rename from plugins/keepkey/__init__.py rename to electrum/plugins/keepkey/__init__.py index 863135a18095..0b54bc4a0db5 100644 --- a/plugins/keepkey/__init__.py +++ b/electrum/plugins/keepkey/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = 'KeepKey' description = _('Provides support for KeepKey hardware wallet') diff --git a/plugins/keepkey/client.py b/electrum/plugins/keepkey/client.py similarity index 100% rename from plugins/keepkey/client.py rename to electrum/plugins/keepkey/client.py diff --git a/plugins/keepkey/clientbase.py b/electrum/plugins/keepkey/clientbase.py similarity index 97% rename from plugins/keepkey/clientbase.py rename to electrum/plugins/keepkey/clientbase.py index a91f85bf98cb..e1c7b2aa4e6c 100644 --- a/plugins/keepkey/clientbase.py +++ b/electrum/plugins/keepkey/clientbase.py @@ -1,10 +1,10 @@ import time from struct import pack -from electrum_mona.i18n import _ -from electrum_mona.util import PrintError, UserCancelled -from electrum_mona.keystore import bip39_normalize_passphrase -from electrum_mona.bitcoin import serialize_xpub +from electrum.i18n import _ +from electrum.util import PrintError, UserCancelled +from electrum.keystore import bip39_normalize_passphrase +from electrum.bitcoin import serialize_xpub class GuiMixin(object): diff --git a/plugins/keepkey/cmdline.py b/electrum/plugins/keepkey/cmdline.py similarity index 90% rename from plugins/keepkey/cmdline.py rename to electrum/plugins/keepkey/cmdline.py index c706ac910cd7..7cbad274e150 100644 --- a/plugins/keepkey/cmdline.py +++ b/electrum/plugins/keepkey/cmdline.py @@ -1,4 +1,4 @@ -from electrum_mona.plugins import hook +from electrum.plugin import hook from .keepkey import KeepKeyPlugin from ..hw_wallet import CmdLineHandler diff --git a/plugins/keepkey/keepkey.py b/electrum/plugins/keepkey/keepkey.py similarity index 97% rename from plugins/keepkey/keepkey.py rename to electrum/plugins/keepkey/keepkey.py index 11964bc796cd..e0f568b83a63 100644 --- a/plugins/keepkey/keepkey.py +++ b/electrum/plugins/keepkey/keepkey.py @@ -2,17 +2,17 @@ import traceback import sys -from electrum_mona.util import bfh, bh2u, UserCancelled -from electrum_mona.bitcoin import (b58_address_to_hash160, xpub_from_pubkey, +from electrum.util import bfh, bh2u, UserCancelled +from electrum.bitcoin import (b58_address_to_hash160, xpub_from_pubkey, TYPE_ADDRESS, TYPE_SCRIPT, is_segwit_address) -from electrum_mona import constants -from electrum_mona.i18n import _ -from electrum_mona.plugins import BasePlugin -from electrum_mona.transaction import deserialize, Transaction -from electrum_mona.keystore import Hardware_KeyStore, is_xpubkey, parse_xpubkey -from electrum_mona.wallet import Standard_Wallet -from electrum_mona.base_wizard import ScriptTypeNotSupported +from electrum import constants +from electrum.i18n import _ +from electrum.plugin import BasePlugin +from electrum.transaction import deserialize, Transaction +from electrum.keystore import Hardware_KeyStore, is_xpubkey, parse_xpubkey +from electrum.wallet import Standard_Wallet +from electrum.base_wizard import ScriptTypeNotSupported from ..hw_wallet import HW_PluginBase from ..hw_wallet.plugin import is_any_tx_output_on_change_branch @@ -288,7 +288,7 @@ def tx_inputs(self, tx, for_sig=False, segwit=False): for txin in tx.inputs(): txinputtype = self.types.TxInputType() if txin['type'] == 'coinbase': - prev_hash = "\0"*32 + prev_hash = b"\x00"*32 prev_index = 0xffffffff # signed int -1 else: if for_sig: diff --git a/plugins/keepkey/qt.py b/electrum/plugins/keepkey/qt.py similarity index 98% rename from plugins/keepkey/qt.py rename to electrum/plugins/keepkey/qt.py index b128ae222b03..cd61d1800dbc 100644 --- a/plugins/keepkey/qt.py +++ b/electrum/plugins/keepkey/qt.py @@ -5,11 +5,11 @@ from PyQt5.Qt import QGridLayout, QInputDialog, QPushButton from PyQt5.Qt import QVBoxLayout, QLabel -from electrum_mona_gui.qt.util import * -from electrum_mona.i18n import _ -from electrum_mona.plugins import hook, DeviceMgr -from electrum_mona.util import PrintError, UserCancelled, bh2u -from electrum_mona.wallet import Wallet, Standard_Wallet +from electrum.gui.qt.util import * +from electrum.i18n import _ +from electrum.plugin import hook, DeviceMgr +from electrum.util import PrintError, UserCancelled, bh2u +from electrum.wallet import Wallet, Standard_Wallet from ..hw_wallet.qt import QtHandlerBase, QtPluginBase from .keepkey import KeepKeyPlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC @@ -250,7 +250,7 @@ def clean_text(widget): else: msg = _("Enter the master private key beginning with xprv:") def set_enabled(): - from electrum_mona.keystore import is_xprv + from keystore import is_xprv wizard.next_button.setEnabled(is_xprv(clean_text(text))) text.textChanged.connect(set_enabled) next_enabled = False diff --git a/plugins/labels/__init__.py b/electrum/plugins/labels/__init__.py similarity index 90% rename from plugins/labels/__init__.py rename to electrum/plugins/labels/__init__.py index 9e22a960e01a..4596bcae42ed 100644 --- a/plugins/labels/__init__.py +++ b/electrum/plugins/labels/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = _('LabelSync') description = ' '.join([ diff --git a/plugins/labels/cmdline.py b/electrum/plugins/labels/cmdline.py similarity index 85% rename from plugins/labels/cmdline.py rename to electrum/plugins/labels/cmdline.py index d33f207bd4f7..2f9aaa069deb 100644 --- a/plugins/labels/cmdline.py +++ b/electrum/plugins/labels/cmdline.py @@ -1,5 +1,5 @@ from .labels import LabelsPlugin -from electrum_mona.plugins import hook +from electrum.plugin import hook class Plugin(LabelsPlugin): diff --git a/plugins/labels/kivy.py b/electrum/plugins/labels/kivy.py similarity index 88% rename from plugins/labels/kivy.py rename to electrum/plugins/labels/kivy.py index aff4e78942c8..56f1d079e08b 100644 --- a/plugins/labels/kivy.py +++ b/electrum/plugins/labels/kivy.py @@ -1,5 +1,5 @@ from .labels import LabelsPlugin -from electrum_mona.plugins import hook +from electrum.plugin import hook class Plugin(LabelsPlugin): diff --git a/plugins/labels/labels.py b/electrum/plugins/labels/labels.py similarity index 96% rename from plugins/labels/labels.py rename to electrum/plugins/labels/labels.py index 767a0c57ea1d..d5fa50b2c277 100644 --- a/plugins/labels/labels.py +++ b/electrum/plugins/labels/labels.py @@ -7,10 +7,9 @@ import base64 -import electrum_mona as electrum -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.crypto import aes_encrypt_with_iv, aes_decrypt_with_iv -from electrum_mona.i18n import _ +from electrum.plugin import BasePlugin, hook +from electrum.crypto import aes_encrypt_with_iv, aes_decrypt_with_iv +from electrum.i18n import _ class LabelsPlugin(BasePlugin): diff --git a/plugins/labels/qt.py b/electrum/plugins/labels/qt.py similarity index 91% rename from plugins/labels/qt.py rename to electrum/plugins/labels/qt.py index 149f6283a07e..df4ae55c2d62 100644 --- a/plugins/labels/qt.py +++ b/electrum/plugins/labels/qt.py @@ -6,11 +6,11 @@ from PyQt5.QtCore import * from PyQt5.QtWidgets import (QHBoxLayout, QLabel, QVBoxLayout) -from electrum_mona.plugins import hook -from electrum_mona.i18n import _ -from electrum_mona_gui.qt import EnterButton -from electrum_mona_gui.qt.util import ThreadedButton, Buttons -from electrum_mona_gui.qt.util import WindowModalDialog, OkButton +from electrum.plugin import hook +from electrum.i18n import _ +from electrum.gui.qt import EnterButton +from electrum.gui.qt.util import ThreadedButton, Buttons +from electrum.gui.qt.util import WindowModalDialog, OkButton from .labels import LabelsPlugin diff --git a/plugins/ledger/__init__.py b/electrum/plugins/ledger/__init__.py similarity index 88% rename from plugins/ledger/__init__.py rename to electrum/plugins/ledger/__init__.py index bdf337edebc8..b97f02335ca6 100644 --- a/plugins/ledger/__init__.py +++ b/electrum/plugins/ledger/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = 'Ledger Wallet' description = 'Provides support for Ledger hardware wallet' diff --git a/plugins/ledger/auth2fa.py b/electrum/plugins/ledger/auth2fa.py similarity index 98% rename from plugins/ledger/auth2fa.py rename to electrum/plugins/ledger/auth2fa.py index 122de91acb7e..f6ddeab01325 100644 --- a/plugins/ledger/auth2fa.py +++ b/electrum/plugins/ledger/auth2fa.py @@ -13,11 +13,11 @@ from btchip.btchip import * -from electrum_mona.i18n import _ -from electrum_mona_gui.qt.util import * -from electrum_mona.util import print_msg -from electrum_mona import constants, bitcoin -from electrum_mona_gui.qt.qrcodewidget import QRCodeWidget +from electrum.i18n import _ +from electrum.util import print_msg +from electrum import constants, bitcoin +from electrum.gui.qt.qrcodewidget import QRCodeWidget +from electrum.gui.qt.util import * DEBUG = False diff --git a/plugins/ledger/cmdline.py b/electrum/plugins/ledger/cmdline.py similarity index 90% rename from plugins/ledger/cmdline.py rename to electrum/plugins/ledger/cmdline.py index 5c35aab8f696..3e810169748f 100644 --- a/plugins/ledger/cmdline.py +++ b/electrum/plugins/ledger/cmdline.py @@ -1,4 +1,4 @@ -from electrum_mona.plugins import hook +from electrum.plugin import hook from .ledger import LedgerPlugin from ..hw_wallet import CmdLineHandler diff --git a/plugins/ledger/ledger.py b/electrum/plugins/ledger/ledger.py similarity index 98% rename from plugins/ledger/ledger.py rename to electrum/plugins/ledger/ledger.py index 0838c6e6b39b..3be79eecf775 100644 --- a/plugins/ledger/ledger.py +++ b/electrum/plugins/ledger/ledger.py @@ -3,17 +3,17 @@ import sys import traceback -from electrum_mona import bitcoin -from electrum_mona.bitcoin import TYPE_ADDRESS, int_to_hex, var_int -from electrum_mona.i18n import _ -from electrum_mona.plugins import BasePlugin -from electrum_mona.keystore import Hardware_KeyStore -from electrum_mona.transaction import Transaction -from electrum_mona.wallet import Standard_Wallet +from electrum import bitcoin +from electrum.bitcoin import TYPE_ADDRESS, int_to_hex, var_int +from electrum.i18n import _ +from electrum.plugin import BasePlugin +from electrum.keystore import Hardware_KeyStore +from electrum.transaction import Transaction +from electrum.wallet import Standard_Wallet from ..hw_wallet import HW_PluginBase from ..hw_wallet.plugin import is_any_tx_output_on_change_branch -from electrum_mona.util import print_error, is_verbose, bfh, bh2u, versiontuple -from electrum_mona.base_wizard import ScriptTypeNotSupported +from electrum.util import print_error, is_verbose, bfh, bh2u, versiontuple +from electrum.base_wizard import ScriptTypeNotSupported try: import hid diff --git a/plugins/ledger/qt.py b/electrum/plugins/ledger/qt.py similarity index 93% rename from plugins/ledger/qt.py rename to electrum/plugins/ledger/qt.py index 4bfbe5cc785a..d49bcb8d6bcb 100644 --- a/plugins/ledger/qt.py +++ b/electrum/plugins/ledger/qt.py @@ -1,9 +1,9 @@ #from btchip.btchipPersoWizard import StartBTChipPersoDialog -from electrum_mona.i18n import _ -from electrum_mona.plugins import hook -from electrum_mona.wallet import Standard_Wallet -from electrum_mona_gui.qt.util import * +from electrum.i18n import _ +from electrum.plugin import hook +from electrum.wallet import Standard_Wallet +from electrum.gui.qt.util import * from .ledger import LedgerPlugin from ..hw_wallet.qt import QtHandlerBase, QtPluginBase diff --git a/plugins/revealer/DejaVuSansMono-Bold.ttf b/electrum/plugins/revealer/DejaVuSansMono-Bold.ttf similarity index 100% rename from plugins/revealer/DejaVuSansMono-Bold.ttf rename to electrum/plugins/revealer/DejaVuSansMono-Bold.ttf diff --git a/plugins/revealer/LICENSE_DEJAVU.txt b/electrum/plugins/revealer/LICENSE_DEJAVU.txt similarity index 100% rename from plugins/revealer/LICENSE_DEJAVU.txt rename to electrum/plugins/revealer/LICENSE_DEJAVU.txt diff --git a/plugins/revealer/SIL Open Font License.txt b/electrum/plugins/revealer/SIL Open Font License.txt similarity index 100% rename from plugins/revealer/SIL Open Font License.txt rename to electrum/plugins/revealer/SIL Open Font License.txt diff --git a/plugins/revealer/SourceSansPro-Bold.otf b/electrum/plugins/revealer/SourceSansPro-Bold.otf similarity index 100% rename from plugins/revealer/SourceSansPro-Bold.otf rename to electrum/plugins/revealer/SourceSansPro-Bold.otf diff --git a/plugins/revealer/__init__.py b/electrum/plugins/revealer/__init__.py similarity index 96% rename from plugins/revealer/__init__.py rename to electrum/plugins/revealer/__init__.py index f8eb88d7edef..dcc8c31fdbfe 100644 --- a/plugins/revealer/__init__.py +++ b/electrum/plugins/revealer/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = _('Revealer') description = ''.join(["
", @@ -10,7 +10,6 @@ _("Once activated you can access the plug-in through the icon at the seed dialog."), '
', '
', _("For more information, visit"), " https://revealer.cc", '
', '
', - ]) available_for = ['qt'] diff --git a/plugins/revealer/qt.py b/electrum/plugins/revealer/qt.py similarity index 96% rename from plugins/revealer/qt.py rename to electrum/plugins/revealer/qt.py index 554fe92ed7ee..69c9fcd32964 100644 --- a/plugins/revealer/qt.py +++ b/electrum/plugins/revealer/qt.py @@ -1,6 +1,6 @@ ''' -Revealer +Revealer So you have something to hide? plug-in for the electrum wallet. @@ -10,7 +10,7 @@ - Safety - One time pad security - Redundancy - Trustless printing & distribution - Encrypt your seedphrase or any secret you want for your revealer - - Based on crypto by legendary cryptographers Naor and Shamir + - Based on crypto by legendary cryptographers Naor and Shamir Tiago Romagnani Silveira, 2017 @@ -25,11 +25,12 @@ from PyQt5.QtPrintSupport import QPrinter -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.i18n import _ -from electrum_mona_gui.qt.util import * -from electrum_mona_gui.qt.qrtextedit import ScanQRTextEdit -from electrum_mona.util import to_bytes, make_dir +from electrum.plugin import BasePlugin, hook +from electrum.i18n import _ +from electrum.util import to_bytes, make_dir + +from electrum.gui.qt.util import * +from electrum.gui.qt.qrtextedit import ScanQRTextEdit class Plugin(BasePlugin): @@ -56,8 +57,9 @@ def __init__(self, parent, config, name): make_dir(self.base_dir) @hook - def set_seed(self, seed, parent): + def set_seed(self, seed, has_extension, parent): self.cseed = seed.upper() + self.has_extension = has_extension parent.addButton(':icons/revealer.png', partial(self.setup_dialog, parent), "Revealer"+_(" secret backup utility")) def requires_settings(self): @@ -167,6 +169,10 @@ def bcrypt(self, dialog): "
","", self.base_dir+ self.filename+self.version+"_"+self.code_id,""])) dialog.close() + def ext_warning(self, dialog): + dialog.show_message(''.join(["",_("Warning: "), "", _("your seed extension will not be included in the encrypted backup.")])) + dialog.close() + def bdone(self, dialog): dialog.show_message(''.join([_("Digital Revealer ({}_{}) saved as PNG and PDF at:").format(self.version, self.code_id), "
","", self.base_dir + 'revealer_' +self.version + '_'+ self.code_id, ''])) @@ -239,12 +245,12 @@ def cypherseed_dialog(self, window): def update_wallet_name (self, name): self.wallet_name = str(name) self.base_name = self.base_dir + self.wallet_name - + def seed_img(self, is_seed = True): - + if not self.cseed and self.txt == False: return - + if is_seed: txt = self.cseed else: @@ -359,6 +365,9 @@ def make_cypherseed(self, img, rawnoise, calibration=False, is_seed = True): self.filename = self.wallet_name+'_'+ _('seed')+'_' self.was = self.wallet_name +' ' + _('seed') + if self.has_extension: + self.ext_warning(self.c_dialog) + if not calibration: self.toPdf(QImage(cypherseed)) QDesktopServices.openUrl (QUrl.fromLocalFile(os.path.abspath(self.base_dir+self.filename+self.version+'_'+self.code_id+'.pdf'))) @@ -374,8 +383,8 @@ def calibration(self): img = self.overlay_marks(self.calnoise.scaledToHeight(self.f_size.height()), False, True) self.calibration_pdf(img) QDesktopServices.openUrl (QUrl.fromLocalFile(os.path.abspath(self.base_dir+_('calibration')+'.pdf'))) - return img - + return img + def toPdf(self, image): printer = QPrinter() printer.setPaperSize(QSizeF(210, 297), QPrinter.Millimeter) @@ -385,13 +394,13 @@ def toPdf(self, image): printer.setPageMargins(0,0,0,0,6) painter = QPainter() painter.begin(printer) - + delta_h = round(image.width()/self.abstand_v) - delta_v = round(image.height()/self.abstand_h) + delta_v = round(image.height()/self.abstand_h) size_h = 2028+((int(self.calibration_h)*2028/(2028-(delta_h*2)+int(self.calibration_h)))/2) size_v = 1284+((int(self.calibration_v)*1284/(1284-(delta_v*2)+int(self.calibration_v)))/2) - + image = image.scaled(size_h, size_v) painter.drawImage(553,533, image) @@ -400,7 +409,7 @@ def toPdf(self, image): painter.setPen(QPen(Qt.black, 1)) painter.drawPath(wpath) painter.end() - + def calibration_pdf(self, image): printer = QPrinter() printer.setPaperSize(QSizeF(210, 297), QPrinter.Millimeter) @@ -426,7 +435,7 @@ def calibration_pdf(self, image): "match on the opposite sides. ")) painter.drawText(700, 2477, _("4. Type the numbers in the software")) painter.end() - + def pixelcode_2x2(self, img): result = QImage(img.width()*2, img.height()*2, QImage.Format_ARGB32 ) white = qRgba(255,255,255,0) @@ -441,7 +450,7 @@ def pixelcode_2x2(self, img): result.setPixel(x*2,y*2+1, white) result.setPixel(x*2+1,y*2, white) result.setPixel(x*2, y*2, black) - + else: result.setPixel(x*2+1,y*2+1, white) result.setPixel(x*2,y*2+1, black) @@ -481,13 +490,13 @@ def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): #border around img border_thick = 6 Rpath = QPainterPath() - Rpath.addRect(QRectF((total_distance_h)+(border_thick/2), - (total_distance_h)+(border_thick/2), + Rpath.addRect(QRectF((total_distance_h)+(border_thick/2), + (total_distance_h)+(border_thick/2), base_img.width()-((total_distance_h)*2)-((border_thick)-1), (base_img.height()-((total_distance_h))*2)-((border_thick)-1))) pen = QPen(Qt.black, border_thick) pen.setJoinStyle (Qt.MiterJoin) - + painter.setPen(pen) painter.drawPath(Rpath) @@ -497,12 +506,12 @@ def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawPath(Bpath) - + pen = QPen(Qt.black, 1) painter.setPen(pen) painter.drawLine(0, base_img.height()/2, total_distance_h, base_img.height()/2) painter.drawLine(base_img.width()/2, 0, base_img.width()/2, total_distance_h) - + painter.drawLine(base_img.width()-total_distance_h, base_img.height()/2, base_img.width(), base_img.height()/2) painter.drawLine(base_img.width()/2, base_img.height(), base_img.width()/2, base_img.height() - total_distance_h) @@ -524,15 +533,15 @@ def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): QImage(':icons/electrumb.png').scaledToWidth(2.1*(total_distance_h), Qt.SmoothTransformation)) painter.setPen(QPen(Qt.white, border_thick*8)) - painter.drawLine(base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2, - (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2, + painter.drawLine(base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2, + (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2, base_img.width()-((total_distance_h))-(border_thick*8)/2-(border_thick/2)-2 - 77, (base_img.height()-((total_distance_h)))-((border_thick*8)/2)-(border_thick/2)-2) painter.setPen(QColor(0,0,0,255)) painter.drawText(QRect(0, base_img.height()-107, base_img.width()-total_distance_h - border_thick - 11, base_img.height()-total_distance_h - border_thick), Qt.AlignRight, self.version + '_'+self.code_id) painter.end() - + else: # revealer painter.setPen(QPen(border_color, 17)) @@ -550,7 +559,7 @@ def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): painter.drawImage((total_distance_h)+ (border_thick), ((total_distance_h))+ (border_thick), logo, Qt.SmoothTransformation) #frame around logo - painter.setPen(QPen(Qt.black, border_thick)) + painter.setPen(QPen(Qt.black, border_thick)) painter.drawLine(total_distance_h+border_thick, total_distance_h+logo.height()+3*(border_thick/2), total_distance_h+logo.width()+border_thick, total_distance_h+logo.height()+3*(border_thick/2)) painter.drawLine(logo.width()+total_distance_h+3*(border_thick/2), total_distance_h+(border_thick), @@ -607,12 +616,12 @@ def overlay_marks(self, img, is_cseed=False, calibration_sheet=False): cal_img = QImage(self.f_size.width() + 100, self.f_size.height() + 100, QImage.Format_ARGB32) cal_img.fill(Qt.white) - + cal_painter = QPainter() cal_painter.begin(cal_img) cal_painter.drawImage(0,0, base_img) - #black lines in the middle of border top left only + #black lines in the middle of border top left only cal_painter.setPen(QPen(Qt.black, 1, Qt.DashDotDotLine)) cal_painter.drawLine(0, dist_v, base_img.width(), dist_v) cal_painter.drawLine(dist_h, 0, dist_h, base_img.height()) @@ -682,7 +691,7 @@ def paintQR(self, data): def calibration_dialog(self, window): d = WindowModalDialog(window, _("Revealer - Printer calibration settings")) - + d.setMinimumSize(100, 200) vbox = QVBoxLayout(d) @@ -709,7 +718,7 @@ def calibration_dialog(self, window): grid.addWidget(vertical, 1, 1) vbox.addStretch() - vbox.addSpacing(13) + vbox.addSpacing(13) vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): diff --git a/plugins/trezor/__init__.py b/electrum/plugins/trezor/__init__.py similarity index 88% rename from plugins/trezor/__init__.py rename to electrum/plugins/trezor/__init__.py index 80e08eb1ae94..e3b08ed65b85 100644 --- a/plugins/trezor/__init__.py +++ b/electrum/plugins/trezor/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = 'TREZOR Wallet' description = _('Provides support for TREZOR hardware wallet') diff --git a/plugins/trezor/client.py b/electrum/plugins/trezor/client.py similarity index 100% rename from plugins/trezor/client.py rename to electrum/plugins/trezor/client.py diff --git a/plugins/trezor/clientbase.py b/electrum/plugins/trezor/clientbase.py similarity index 98% rename from plugins/trezor/clientbase.py rename to electrum/plugins/trezor/clientbase.py index d82dbfe35904..b91e4af4a112 100644 --- a/plugins/trezor/clientbase.py +++ b/electrum/plugins/trezor/clientbase.py @@ -1,10 +1,10 @@ import time from struct import pack -from electrum_mona.i18n import _ -from electrum_mona.util import PrintError, UserCancelled -from electrum_mona.keystore import bip39_normalize_passphrase -from electrum_mona.bitcoin import serialize_xpub +from electrum.i18n import _ +from electrum.util import PrintError, UserCancelled +from electrum.keystore import bip39_normalize_passphrase +from electrum.bitcoin import serialize_xpub class GuiMixin(object): diff --git a/plugins/trezor/cmdline.py b/electrum/plugins/trezor/cmdline.py similarity index 90% rename from plugins/trezor/cmdline.py rename to electrum/plugins/trezor/cmdline.py index 4539f2fb0f8c..e435aad138f7 100644 --- a/plugins/trezor/cmdline.py +++ b/electrum/plugins/trezor/cmdline.py @@ -1,4 +1,4 @@ -from electrum_mona.plugins import hook +from electrum.plugin import hook from .trezor import TrezorPlugin from ..hw_wallet import CmdLineHandler diff --git a/plugins/trezor/qt.py b/electrum/plugins/trezor/qt.py similarity index 98% rename from plugins/trezor/qt.py rename to electrum/plugins/trezor/qt.py index fb1d8ad2ada3..53340b94d776 100644 --- a/plugins/trezor/qt.py +++ b/electrum/plugins/trezor/qt.py @@ -5,11 +5,11 @@ from PyQt5.Qt import QGridLayout, QInputDialog, QPushButton from PyQt5.Qt import QVBoxLayout, QLabel -from electrum_mona_gui.qt.util import * -from electrum_mona.i18n import _ -from electrum_mona.plugins import hook, DeviceMgr -from electrum_mona.util import PrintError, UserCancelled, bh2u -from electrum_mona.wallet import Wallet, Standard_Wallet +from electrum.gui.qt.util import * +from electrum.i18n import _ +from electrum.plugin import hook, DeviceMgr +from electrum.util import PrintError, UserCancelled, bh2u +from electrum.wallet import Wallet, Standard_Wallet from ..hw_wallet.qt import QtHandlerBase, QtPluginBase from .trezor import (TrezorPlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC, @@ -220,7 +220,7 @@ def clean_text(widget): else: msg = _("Enter the master private key beginning with xprv:") def set_enabled(): - from electrum_mona.keystore import is_xprv + from electrum.keystore import is_xprv wizard.next_button.setEnabled(is_xprv(clean_text(text))) text.textChanged.connect(set_enabled) next_enabled = False diff --git a/plugins/trezor/transport.py b/electrum/plugins/trezor/transport.py similarity index 98% rename from plugins/trezor/transport.py rename to electrum/plugins/trezor/transport.py index 1af4fed35f99..5ce686c69185 100644 --- a/plugins/trezor/transport.py +++ b/electrum/plugins/trezor/transport.py @@ -1,4 +1,4 @@ -from electrum_mona.util import PrintError +from electrum.util import PrintError class TrezorTransport(PrintError): diff --git a/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py similarity index 97% rename from plugins/trezor/trezor.py rename to electrum/plugins/trezor/trezor.py index 0063f0e141d5..ecc9f4320aa8 100644 --- a/plugins/trezor/trezor.py +++ b/electrum/plugins/trezor/trezor.py @@ -2,15 +2,15 @@ import traceback import sys -from electrum_mona.util import bfh, bh2u, versiontuple, UserCancelled -from electrum_mona.bitcoin import (b58_address_to_hash160, xpub_from_pubkey, deserialize_xpub, +from electrum.util import bfh, bh2u, versiontuple, UserCancelled +from electrum.bitcoin import (b58_address_to_hash160, xpub_from_pubkey, deserialize_xpub, TYPE_ADDRESS, TYPE_SCRIPT, is_address) -from electrum_mona import constants -from electrum_mona.i18n import _ -from electrum_mona.plugins import BasePlugin, Device -from electrum_mona.transaction import deserialize, Transaction -from electrum_mona.keystore import Hardware_KeyStore, is_xpubkey, parse_xpubkey, xtype_from_derivation -from electrum_mona.base_wizard import ScriptTypeNotSupported +from electrum import constants +from electrum.i18n import _ +from electrum.plugin import BasePlugin, Device +from electrum.transaction import deserialize, Transaction +from electrum.keystore import Hardware_KeyStore, is_xpubkey, parse_xpubkey, xtype_from_derivation +from electrum.base_wizard import ScriptTypeNotSupported from ..hw_wallet import HW_PluginBase from ..hw_wallet.plugin import is_any_tx_output_on_change_branch @@ -362,7 +362,7 @@ def tx_inputs(self, tx, for_sig=False, script_gen=SCRIPT_GEN_LEGACY): for txin in tx.inputs(): txinputtype = self.types.TxInputType() if txin['type'] == 'coinbase': - prev_hash = "\0"*32 + prev_hash = b"\x00"*32 prev_index = 0xffffffff # signed int -1 else: if for_sig: diff --git a/plugins/virtualkeyboard/__init__.py b/electrum/plugins/virtualkeyboard/__init__.py similarity index 86% rename from plugins/virtualkeyboard/__init__.py rename to electrum/plugins/virtualkeyboard/__init__.py index ca1b1367ecb8..c24f19b1a3cf 100644 --- a/plugins/virtualkeyboard/__init__.py +++ b/electrum/plugins/virtualkeyboard/__init__.py @@ -1,4 +1,4 @@ -from electrum_mona.i18n import _ +from electrum.i18n import _ fullname = 'Virtual Keyboard' description = '%s\n%s' % (_("Add an optional virtual keyboard to the password dialog."), _("Warning: do not use this if it makes you pick a weaker password.")) diff --git a/plugins/virtualkeyboard/qt.py b/electrum/plugins/virtualkeyboard/qt.py similarity index 95% rename from plugins/virtualkeyboard/qt.py rename to electrum/plugins/virtualkeyboard/qt.py index ad555f22a1c8..3ce78af33df8 100644 --- a/plugins/virtualkeyboard/qt.py +++ b/electrum/plugins/virtualkeyboard/qt.py @@ -1,7 +1,7 @@ from PyQt5.QtGui import * from PyQt5.QtWidgets import (QVBoxLayout, QGridLayout, QPushButton) -from electrum_mona.plugins import BasePlugin, hook -from electrum_mona.i18n import _ +from electrum.plugin import BasePlugin, hook +from electrum.i18n import _ import random diff --git a/lib/qrscanner.py b/electrum/qrscanner.py similarity index 100% rename from lib/qrscanner.py rename to electrum/qrscanner.py diff --git a/lib/ripemd.py b/electrum/ripemd.py similarity index 100% rename from lib/ripemd.py rename to electrum/ripemd.py diff --git a/lib/rsakey.py b/electrum/rsakey.py similarity index 99% rename from lib/rsakey.py rename to electrum/rsakey.py index d9079c304719..97efd65d0748 100644 --- a/lib/rsakey.py +++ b/electrum/rsakey.py @@ -25,7 +25,7 @@ # This module uses functions from TLSLite (public domain) # -# TLSLite Authors: +# TLSLite Authors: # Trevor Perrin # Martin von Loewis - python 3 port # Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 @@ -80,7 +80,7 @@ def numberToByteArray(n, howManyBytes=None): The returned bytearray may be smaller than howManyBytes, but will not be larger. The returned bytearray will contain a big-endian encoding of the input integer (n). - """ + """ if howManyBytes == None: howManyBytes = numBytes(n) b = bytearray(howManyBytes) @@ -331,7 +331,7 @@ def hashAndVerify(self, sigBytes, bytes): @return: Whether the signature matches the passed-in data. """ hashBytes = SHA1(bytearray(bytes)) - + # Try it with/without the embedded NULL prefixedHashBytes1 = self._addPKCS1SHA1Prefix(hashBytes, False) prefixedHashBytes2 = self._addPKCS1SHA1Prefix(hashBytes, True) @@ -445,21 +445,21 @@ def decrypt(self, encBytes): # ************************************************************************** def _addPKCS1SHA1Prefix(self, bytes, withNULL=True): - # There is a long history of confusion over whether the SHA1 - # algorithmIdentifier should be encoded with a NULL parameter or - # with the parameter omitted. While the original intention was + # There is a long history of confusion over whether the SHA1 + # algorithmIdentifier should be encoded with a NULL parameter or + # with the parameter omitted. While the original intention was # apparently to omit it, many toolkits went the other way. TLS 1.2 # specifies the NULL should be included, and this behavior is also # mandated in recent versions of PKCS #1, and is what tlslite has - # always implemented. Anyways, verification code should probably - # accept both. However, nothing uses this code yet, so this is + # always implemented. Anyways, verification code should probably + # accept both. However, nothing uses this code yet, so this is # all fairly moot. if not withNULL: prefixBytes = bytearray(\ - [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14]) + [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14]) else: prefixBytes = bytearray(\ - [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14]) + [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14]) prefixedBytes = prefixBytes + bytes return prefixedBytes diff --git a/scripts/bip70 b/electrum/scripts/bip70.py similarity index 85% rename from scripts/bip70 rename to electrum/scripts/bip70.py index d2197ec9bd75..2e04bfe76f03 100755 --- a/scripts/bip70 +++ b/electrum/scripts/bip70.py @@ -3,9 +3,9 @@ import tlslite -from electrum_mona.transaction import Transaction -from electrum_mona import paymentrequest -from electrum_mona import paymentrequest_pb2 as pb2 +from electrum.transaction import Transaction +from electrum import paymentrequest +from electrum import paymentrequest_pb2 as pb2 chain_file = 'mychain.pem' cert_file = 'mycert.pem' diff --git a/scripts/block_headers b/electrum/scripts/block_headers.py similarity index 83% rename from scripts/block_headers rename to electrum/scripts/block_headers.py index a7b4b63eda10..d3ecb7fdbc47 100755 --- a/scripts/block_headers +++ b/electrum/scripts/block_headers.py @@ -1,10 +1,10 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # A simple script that connects to a server and displays block headers import time -from electrum_mona import SimpleConfig, Network -from electrum_mona.util import print_msg, json_encode +from .. import SimpleConfig, Network +from electrum.util import print_msg, json_encode # start network c = SimpleConfig() diff --git a/electrum/scripts/estimate_fee.py b/electrum/scripts/estimate_fee.py new file mode 100755 index 000000000000..85f63cef0290 --- /dev/null +++ b/electrum/scripts/estimate_fee.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +from . import util +import json +from electrum.network import filter_protocol +peers = filter_protocol(util.get_peers()) +results = util.send_request(peers, 'blockchain.estimatefee', [2]) +print(json.dumps(results, indent=4)) diff --git a/scripts/get_history b/electrum/scripts/get_history.py similarity index 69% rename from scripts/get_history rename to electrum/scripts/get_history.py index ce5a9c0b50f7..c83f99d9147b 100755 --- a/scripts/get_history +++ b/electrum/scripts/get_history.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 import sys -from electrum_mona import Network -from electrum_mona.util import json_encode, print_msg -from electrum_mona import bitcoin +from .. import Network +from electrum.util import json_encode, print_msg +from electrum import bitcoin try: addr = sys.argv[1] diff --git a/scripts/peers b/electrum/scripts/peers.py similarity index 72% rename from scripts/peers rename to electrum/scripts/peers.py index 0b4450bc34fe..a887f07952f7 100755 --- a/scripts/peers +++ b/electrum/scripts/peers.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 -import util +from . import util -from electrum_mona.network import filter_protocol -from electrum_mona.blockchain import hash_header +from electrum.network import filter_protocol +from electrum.blockchain import hash_header peers = util.get_peers() peers = filter_protocol(peers, 's') diff --git a/scripts/servers b/electrum/scripts/servers.py similarity index 57% rename from scripts/servers rename to electrum/scripts/servers.py index ad594ab599d7..c7201bc382b9 100755 --- a/scripts/servers +++ b/electrum/scripts/servers.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 -from electrum_mona import set_verbosity -from electrum_mona.network import filter_version -import util, json +from .. import set_verbosity +from electrum.network import filter_version +from . import util +import json set_verbosity(False) servers = filter_version(util.get_peers()) diff --git a/scripts/txradar b/electrum/scripts/txradar.py similarity index 93% rename from scripts/txradar rename to electrum/scripts/txradar.py index 5c34c0d6c301..dda732274286 100755 --- a/scripts/txradar +++ b/electrum/scripts/txradar.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 -import util, sys +from . import util +import sys try: tx = sys.argv[1] except: diff --git a/scripts/util.py b/electrum/scripts/util.py similarity index 89% rename from scripts/util.py rename to electrum/scripts/util.py index 9e0e682f9672..266348f7599f 100644 --- a/scripts/util.py +++ b/electrum/scripts/util.py @@ -1,15 +1,16 @@ import select, time, queue -# import electrum_mona -from electrum_mona import Connection, Interface, SimpleConfig +# import electrum +from .. import Connection, Interface, SimpleConfig -from electrum_mona.network import parse_servers +from electrum.network import parse_servers from collections import defaultdict -# electrum_mona.util.set_verbosity(1) +# electrum.util.set_verbosity(1) def get_interfaces(servers, timeout=10): '''Returns a map of servers to connected interfaces. If any connections fail or timeout, they will be missing from the map. ''' + assert type(servers) is list socket_queue = queue.Queue() config = SimpleConfig() connecting = {} @@ -51,6 +52,9 @@ def get_peers(): peers = {} # 1. get connected interfaces server = config.get('server') + if server is None: + print("You need to set a secure server, for example (for mainnet): 'electrum setconfig server helicarrier.bauerj.eu:50002:s'") + return [] interfaces = get_interfaces([server]) if not interfaces: print("No connection to", server) diff --git a/scripts/watch_address b/electrum/scripts/watch_address.py similarity index 82% rename from scripts/watch_address rename to electrum/scripts/watch_address.py index c349a4ad45b3..8fd5d49141c7 100755 --- a/scripts/watch_address +++ b/electrum/scripts/watch_address.py @@ -2,9 +2,9 @@ import sys import time -from electrum_mona import bitcoin -from electrum_mona import SimpleConfig, Network -from electrum_mona.util import print_msg, json_encode +from electrum import bitcoin +from .. import SimpleConfig, Network +from electrum.util import print_msg, json_encode try: addr = sys.argv[1] diff --git a/lib/scrypt.py b/electrum/scrypt.py similarity index 100% rename from lib/scrypt.py rename to electrum/scrypt.py diff --git a/lib/segwit_addr.py b/electrum/segwit_addr.py similarity index 100% rename from lib/segwit_addr.py rename to electrum/segwit_addr.py diff --git a/lib/servers.json b/electrum/servers.json similarity index 100% rename from lib/servers.json rename to electrum/servers.json diff --git a/lib/servers_regtest.json b/electrum/servers_regtest.json similarity index 100% rename from lib/servers_regtest.json rename to electrum/servers_regtest.json diff --git a/lib/servers_testnet.json b/electrum/servers_testnet.json similarity index 100% rename from lib/servers_testnet.json rename to electrum/servers_testnet.json diff --git a/lib/simple_config.py b/electrum/simple_config.py similarity index 94% rename from lib/simple_config.py rename to electrum/simple_config.py index 4618896d4a74..47512ecb3550 100644 --- a/lib/simple_config.py +++ b/electrum/simple_config.py @@ -5,6 +5,7 @@ import stat from decimal import Decimal from typing import Union +from numbers import Real from copy import deepcopy @@ -37,7 +38,7 @@ def set_config(c): config = c -FINAL_CONFIG_VERSION = 2 +FINAL_CONFIG_VERSION = 3 class SimpleConfig(PrintError): @@ -164,6 +165,7 @@ def upgrade(self): self.print_error('upgrading config') self.convert_version_2() + self.convert_version_3() self.set_key('config_version', FINAL_CONFIG_VERSION, save=True) @@ -186,6 +188,19 @@ def convert_version_2(self): self.set_key('config_version', 2) + def convert_version_3(self): + if not self._is_upgrade_method_needed(2, 2): + return + + base_unit = self.user_config.get('base_unit') + if isinstance(base_unit, str): + self._set_key_in_user_config('base_unit', None) + map_ = {'btc':8, 'mbtc':5, 'ubtc':2, 'bits':2, 'sat':0} + decimal_point = map_.get(base_unit.lower()) + self._set_key_in_user_config('decimal_point', decimal_point) + + self.set_key('config_version', 3) + def _is_upgrade_method_needed(self, min_version, max_version): cur_version = self.get_config_version() if cur_version > max_version: @@ -296,20 +311,28 @@ def eta_to_fee(self, slider_pos) -> Union[int, None]: fee = int(fee) return fee - def fee_to_depth(self, target_fee): + def fee_to_depth(self, target_fee: Real) -> int: + """For a given sat/vbyte fee, returns an estimate of how deep + it would be in the current mempool in vbytes. + Pessimistic == overestimates the depth. + """ depth = 0 for fee, s in self.mempool_fees: depth += s if fee <= target_fee: break - else: - return 0 return depth - @impose_hard_limits_on_fee def depth_to_fee(self, slider_pos) -> int: """Returns fee in sat/kbyte.""" target = self.depth_target(slider_pos) + return self.depth_target_to_fee(target) + + @impose_hard_limits_on_fee + def depth_target_to_fee(self, target: int) -> int: + """Returns fee in sat/kbyte. + target: desired mempool depth in vbytes + """ depth = 0 for fee, s in self.mempool_fees: depth += s @@ -317,6 +340,10 @@ def depth_to_fee(self, slider_pos) -> int: break else: return 0 + # add one sat/byte as currently that is + # the max precision of the histogram + fee += 1 + # convert to sat/kbyte return fee * 1000 def depth_target(self, slider_pos): diff --git a/lib/storage.py b/electrum/storage.py similarity index 98% rename from lib/storage.py rename to electrum/storage.py index 69875e3f1b8c..0524cd23f5ae 100644 --- a/lib/storage.py +++ b/electrum/storage.py @@ -29,17 +29,15 @@ import copy import re import stat -import pbkdf2, hmac, hashlib +import hmac, hashlib import base64 import zlib from collections import defaultdict -from . import util +from . import util, bitcoin, ecc from .util import PrintError, profiler, InvalidPassword, WalletFileException, bfh -from .plugins import run_hook, plugin_loaders +from .plugin import run_hook, plugin_loaders from .keystore import bip44_derivation -from . import bitcoin -from . import ecc # seed_version is now used for the version of the wallet file @@ -167,7 +165,7 @@ def file_exists(self): @staticmethod def get_eckey_from_password(password): - secret = pbkdf2.PBKDF2(password, '', iterations=1024, macmodule=hmac, digestmodule=hashlib.sha512).read(64) + secret = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), b'', iterations=1024) ec_key = ecc.ECPrivkey.from_arbitrary_size_secret(secret) return ec_key @@ -639,7 +637,7 @@ def raise_unsupported_version(self, seed_version): # version 1.9.8 created v6 wallets when an incorrect seed was entered in the restore dialog msg += '\n\nThis file was created because of a bug in version 1.9.8.' if self.get('master_public_keys') is None and self.get('master_private_keys') is None and self.get('imported_keys') is None: - # pbkdf2 was not included with the binaries, and wallet creation aborted. + # pbkdf2 (at that time an additional dependency) was not included with the binaries, and wallet creation aborted. msg += "\nIt does not contain any keys, and can safely be removed." else: # creation was complete if electrum was run from source diff --git a/lib/synchronizer.py b/electrum/synchronizer.py similarity index 95% rename from lib/synchronizer.py rename to electrum/synchronizer.py index 3a8dc0bbaf47..48635df8152d 100644 --- a/lib/synchronizer.py +++ b/electrum/synchronizer.py @@ -124,11 +124,6 @@ def on_address_history(self, response): # tx_fees tx_fees = [(item['tx_hash'], item.get('fee')) for item in result] tx_fees = dict(filter(lambda x:x[1] is not None, tx_fees)) - # Note if the server hasn't been patched to sort the items properly - if hist != sorted(hist, key=lambda x:x[1]): - interface = self.network.interface - # note: we don't actually know which interface was used if it was *just* changed - if interface: interface.print_error("serving improperly sorted address histories") # Check that txids are unique if len(hashes) != len(result): self.print_error("error: server history has non-unique txids: %s"% addr) @@ -150,13 +145,16 @@ def on_tx_response(self, response): if not params: return tx_hash = params[0] - #assert tx_hash == hash_encode(Hash(bytes.fromhex(result))) tx = Transaction(result) try: tx.deserialize() except Exception: self.print_msg("cannot deserialize transaction, skipping", tx_hash) return + if tx_hash != tx.txid(): + self.print_error("received tx does not match expected txid ({} != {})" + .format(tx_hash, tx.txid())) + return tx_height = self.requested_tx.pop(tx_hash) self.wallet.receive_tx_callback(tx_hash, tx, tx_height) self.print_error("received tx %s height: %d bytes: %d" % diff --git a/lib/tests/__init__.py b/electrum/tests/__init__.py similarity index 96% rename from lib/tests/__init__.py rename to electrum/tests/__init__.py index f10adee508eb..7d1d336d385e 100644 --- a/lib/tests/__init__.py +++ b/electrum/tests/__init__.py @@ -1,7 +1,7 @@ import unittest import threading -from lib import constants +from electrum import constants # Set this locally to make the test suite run faster. diff --git a/lib/tests/test_bitcoin.py b/electrum/tests/test_bitcoin.py similarity index 99% rename from lib/tests/test_bitcoin.py rename to electrum/tests/test_bitcoin.py index 9c1deef932cd..3fd5f864753d 100644 --- a/lib/tests/test_bitcoin.py +++ b/electrum/tests/test_bitcoin.py @@ -2,8 +2,7 @@ import unittest import sys -from lib import bitcoin -from lib.bitcoin import ( +from electrum.bitcoin import ( public_key_to_p2pkh, bip32_root, bip32_public_derivation, bip32_private_derivation, Hash, address_from_private_key, @@ -14,13 +13,14 @@ xpub_type, is_xprv, is_bip32_derivation, seed_type, EncodeBase58Check, script_num_to_hex, push_script, add_number_to_script,int_to_hex, deserialize_privkey_old, is_private_key_old) -from lib import ecc, crypto, ecc_fast -from lib.ecc import number_to_string, string_to_number -from lib.transaction import opcodes -from lib.util import bfh, bh2u -from lib import constants -from lib.storage import WalletStorage -from lib.keystore import xtype_from_derivation +from electrum import ecc, crypto, constants +from electrum.ecc import number_to_string, string_to_number +from electrum.transaction import opcodes +from electrum.util import bfh, bh2u +from electrum.storage import WalletStorage +from electrum.keystore import xtype_from_derivation + +from electrum import ecc_fast from . import SequentialTestCase from . import TestCaseForTestnet diff --git a/lib/tests/test_commands.py b/electrum/tests/test_commands.py similarity index 97% rename from lib/tests/test_commands.py rename to electrum/tests/test_commands.py index f94a73968283..6aa0ba715e8d 100644 --- a/lib/tests/test_commands.py +++ b/electrum/tests/test_commands.py @@ -1,7 +1,7 @@ import unittest from decimal import Decimal -from lib.commands import Commands +from electrum.commands import Commands class TestCommands(unittest.TestCase): diff --git a/lib/tests/test_dnssec.py b/electrum/tests/test_dnssec.py similarity index 99% rename from lib/tests/test_dnssec.py rename to electrum/tests/test_dnssec.py index a7380225878d..e7e9ac4fb84a 100644 --- a/lib/tests/test_dnssec.py +++ b/electrum/tests/test_dnssec.py @@ -1,6 +1,6 @@ import dns -from lib import dnssec +from electrum import dnssec from . import SequentialTestCase from .test_bitcoin import needs_test_with_all_ecc_implementations diff --git a/lib/tests/test_interface.py b/electrum/tests/test_interface.py similarity index 97% rename from lib/tests/test_interface.py rename to electrum/tests/test_interface.py index 4f453a61ff6e..402588ca8b24 100644 --- a/lib/tests/test_interface.py +++ b/electrum/tests/test_interface.py @@ -1,6 +1,6 @@ import unittest -from lib import interface +from electrum import interface from . import SequentialTestCase diff --git a/lib/tests/test_mnemonic.py b/electrum/tests/test_mnemonic.py similarity index 92% rename from lib/tests/test_mnemonic.py rename to electrum/tests/test_mnemonic.py index e19168fabdb5..191ce90238ad 100644 --- a/lib/tests/test_mnemonic.py +++ b/electrum/tests/test_mnemonic.py @@ -1,8 +1,8 @@ import unittest -from lib import keystore -from lib import mnemonic -from lib import old_mnemonic -from lib.util import bh2u +from electrum import keystore +from electrum import mnemonic +from electrum import old_mnemonic +from electrum.util import bh2u from . import SequentialTestCase diff --git a/lib/tests/test_scrypt.py b/electrum/tests/test_scrypt.py similarity index 79% rename from lib/tests/test_scrypt.py rename to electrum/tests/test_scrypt.py index d8126dec22b4..756e4e032dc1 100644 --- a/lib/tests/test_scrypt.py +++ b/electrum/tests/test_scrypt.py @@ -1,10 +1,10 @@ import unittest import threading -from lib.scrypt import scrypt_1024_1_1_80 as scryptGetHash -from lib.util import bfh,bh2u -from lib.bitcoin import rev_hex,int_to_hex -from lib.blockchain import serialize_header +from electrum.scrypt import scrypt_1024_1_1_80 as scryptGetHash +from electrum.util import bfh,bh2u +from electrum.bitcoin import rev_hex,int_to_hex +from electrum.blockchain import serialize_header class Test_scrypt(unittest.TestCase): diff --git a/lib/tests/test_simple_config.py b/electrum/tests/test_simple_config.py similarity index 72% rename from lib/tests/test_simple_config.py rename to electrum/tests/test_simple_config.py index b62cb407f5e6..6a3dbd0238e4 100644 --- a/lib/tests/test_simple_config.py +++ b/electrum/tests/test_simple_config.py @@ -6,7 +6,7 @@ import shutil from io import StringIO -from lib.simple_config import (SimpleConfig, read_user_config) +from electrum.simple_config import (SimpleConfig, read_user_config) from . import SequentialTestCase @@ -110,6 +110,43 @@ def test_user_config_is_not_written_with_read_only_config(self): result.pop('config_version', None) self.assertEqual({"something": "a"}, result) + def test_depth_target_to_fee(self): + config = SimpleConfig(self.options) + config.mempool_fees = [[49, 100110], [10, 121301], [6, 153731], [5, 125872], [1, 36488810]] + self.assertEqual( 2 * 1000, config.depth_target_to_fee(1000000)) + self.assertEqual( 6 * 1000, config.depth_target_to_fee( 500000)) + self.assertEqual( 7 * 1000, config.depth_target_to_fee( 250000)) + self.assertEqual(11 * 1000, config.depth_target_to_fee( 200000)) + self.assertEqual(50 * 1000, config.depth_target_to_fee( 100000)) + config.mempool_fees = [] + self.assertEqual( 1 * 1000, config.depth_target_to_fee(10 ** 5)) + self.assertEqual( 1 * 1000, config.depth_target_to_fee(10 ** 6)) + self.assertEqual( 1 * 1000, config.depth_target_to_fee(10 ** 7)) + config.mempool_fees = [[1, 36488810]] + self.assertEqual( 2 * 1000, config.depth_target_to_fee(10 ** 5)) + self.assertEqual( 2 * 1000, config.depth_target_to_fee(10 ** 6)) + self.assertEqual( 2 * 1000, config.depth_target_to_fee(10 ** 7)) + self.assertEqual( 1 * 1000, config.depth_target_to_fee(10 ** 8)) + config.mempool_fees = [[5, 125872], [1, 36488810]] + self.assertEqual( 6 * 1000, config.depth_target_to_fee(10 ** 5)) + self.assertEqual( 2 * 1000, config.depth_target_to_fee(10 ** 6)) + self.assertEqual( 2 * 1000, config.depth_target_to_fee(10 ** 7)) + self.assertEqual( 1 * 1000, config.depth_target_to_fee(10 ** 8)) + + def test_fee_to_depth(self): + config = SimpleConfig(self.options) + config.mempool_fees = [[49, 100000], [10, 120000], [6, 150000], [5, 125000], [1, 36000000]] + self.assertEqual(100000, config.fee_to_depth(500)) + self.assertEqual(100000, config.fee_to_depth(50)) + self.assertEqual(100000, config.fee_to_depth(49)) + self.assertEqual(220000, config.fee_to_depth(48)) + self.assertEqual(220000, config.fee_to_depth(10)) + self.assertEqual(370000, config.fee_to_depth(9)) + self.assertEqual(370000, config.fee_to_depth(6.5)) + self.assertEqual(370000, config.fee_to_depth(6)) + self.assertEqual(495000, config.fee_to_depth(5.5)) + self.assertEqual(36495000, config.fee_to_depth(0.5)) + class TestUserConfig(SequentialTestCase): diff --git a/lib/tests/test_storage_upgrade.py b/electrum/tests/test_storage_upgrade.py similarity index 98% rename from lib/tests/test_storage_upgrade.py rename to electrum/tests/test_storage_upgrade.py index f6f66f10ec54..642b2179f16a 100644 --- a/lib/tests/test_storage_upgrade.py +++ b/electrum/tests/test_storage_upgrade.py @@ -1,10 +1,10 @@ import shutil import tempfile -from lib.storage import WalletStorage -from lib.wallet import Wallet +from electrum.storage import WalletStorage +from electrum.wallet import Wallet -from lib.tests.test_wallet import WalletTestCase +from .test_wallet import WalletTestCase from . import SequentialTestCase @@ -34,8 +34,8 @@ def test_upgrade_from_client_2_9_3_multisig(self): @classmethod def setUpClass(cls): super().setUpClass() - from lib.plugins import Plugins - from lib.simple_config import SimpleConfig + from electrum.plugin import Plugins + from electrum.simple_config import SimpleConfig cls.electrum_path = tempfile.mkdtemp() config = SimpleConfig({'electrum_path': cls.electrum_path}) diff --git a/lib/tests/test_transaction.py b/electrum/tests/test_transaction.py similarity index 99% rename from lib/tests/test_transaction.py rename to electrum/tests/test_transaction.py index e321ec5dcfc1..f4b8b0578243 100644 --- a/lib/tests/test_transaction.py +++ b/electrum/tests/test_transaction.py @@ -1,9 +1,9 @@ import unittest -from lib import transaction -from lib.bitcoin import TYPE_ADDRESS -from lib.keystore import xpubkey_to_address -from lib.util import bh2u, bfh +from electrum import transaction +from electrum.bitcoin import TYPE_ADDRESS +from electrum.keystore import xpubkey_to_address +from electrum.util import bh2u, bfh from . import SequentialTestCase, TestCaseForTestnet from .test_bitcoin import needs_test_with_all_ecc_implementations diff --git a/lib/tests/test_util.py b/electrum/tests/test_util.py similarity index 98% rename from lib/tests/test_util.py rename to electrum/tests/test_util.py index 9a19f11d18c0..f7af4925c50f 100644 --- a/lib/tests/test_util.py +++ b/electrum/tests/test_util.py @@ -1,5 +1,5 @@ import unittest -from lib.util import format_satoshis, parse_URI +from electrum.util import format_satoshis, parse_URI from . import SequentialTestCase diff --git a/lib/tests/test_wallet.py b/electrum/tests/test_wallet.py similarity index 96% rename from lib/tests/test_wallet.py rename to electrum/tests/test_wallet.py index 3780dc6e4bc6..a19970240a84 100644 --- a/lib/tests/test_wallet.py +++ b/electrum/tests/test_wallet.py @@ -6,7 +6,7 @@ import json from io import StringIO -from lib.storage import WalletStorage, FINAL_SEED_VERSION +from electrum.storage import WalletStorage, FINAL_SEED_VERSION from . import SequentialTestCase diff --git a/lib/tests/test_wallet_vertical.py b/electrum/tests/test_wallet_vertical.py similarity index 97% rename from lib/tests/test_wallet_vertical.py rename to electrum/tests/test_wallet_vertical.py index 5e8a510cc4cd..e22f5161ee6a 100644 --- a/lib/tests/test_wallet_vertical.py +++ b/electrum/tests/test_wallet_vertical.py @@ -4,20 +4,25 @@ import tempfile from typing import Sequence -import lib -from lib import storage, bitcoin, keystore, constants -from lib.transaction import Transaction -from lib.simple_config import SimpleConfig -from lib.wallet import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT, sweep -from lib.util import bfh, bh2u +from electrum import storage, bitcoin, keystore, constants +from electrum import Transaction +from electrum import SimpleConfig +from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT +from electrum.wallet import sweep, Multisig_Wallet, Standard_Wallet, Imported_Wallet +from electrum.util import bfh, bh2u -#from plugins.trustedcoin import trustedcoin +#from electrum.plugins.trustedcoin import trustedcoin from . import TestCaseForTestnet from . import SequentialTestCase from .test_bitcoin import needs_test_with_all_ecc_implementations +_UNICODE_HORROR_HEX = 'e282bf20f09f988020f09f98882020202020e3818620e38191e3819fe381be20e3828fe3828b2077cda2cda2cd9d68cda16fcda2cda120ccb8cda26bccb5cd9f6eccb4cd98c7ab77ccb8cc9b73cd9820cc80cc8177cd98cda2e1b8a9ccb561d289cca1cda27420cca7cc9568cc816fccb572cd8fccb5726f7273cca120ccb6cda1cda06cc4afccb665cd9fcd9f20ccb6cd9d696ecda220cd8f74cc9568ccb7cca1cd9f6520cd9fcd9f64cc9b61cd9c72cc95cda16bcca2cca820cda168ccb465cd8f61ccb7cca2cca17274cc81cd8f20ccb4ccb7cda0c3b2ccb5ccb666ccb82075cca7cd986ec3adcc9bcd9c63cda2cd8f6fccb7cd8f64ccb8cda265cca1cd9d3fcd9e' +UNICODE_HORROR = bfh(_UNICODE_HORROR_HEX).decode('utf-8') +# '₿ 😀 😈 う けたま わる w͢͢͝h͡o͢͡ ̸͢k̵͟n̴͘ǫw̸̛s͘ ̀́w͘͢ḩ̵a҉̡͢t ̧̕h́o̵r͏̵rors̡ ̶͡͠lį̶e͟͟ ̶͝in͢ ͏t̕h̷̡͟e ͟͟d̛a͜r̕͡k̢̨ ͡h̴e͏a̷̢̡rt́͏ ̴̷͠ò̵̶f̸ u̧͘ní̛͜c͢͏o̷͏d̸͢e̡͝?͞' + + class WalletIntegrityHelper: gap_limit = 1 # make tests run faster @@ -41,7 +46,7 @@ def create_standard_wallet(cls, ks, gap_limit=None): store = storage.WalletStorage('if_this_exists_mocking_failed_648151893') store.put('keystore', ks.dump()) store.put('gap_limit', gap_limit or cls.gap_limit) - w = lib.wallet.Standard_Wallet(store) + w = Standard_Wallet(store) w.synchronize() return w @@ -51,7 +56,7 @@ def create_imported_wallet(cls, privkeys=False): if privkeys: k = keystore.Imported_KeyStore({}) store.put('keystore', k.dump()) - w = lib.wallet.Imported_Wallet(store) + w = Imported_Wallet(store) return w @classmethod @@ -63,12 +68,11 @@ def create_multisig_wallet(cls, keystores: Sequence, multisig_type: str, gap_lim store.put('x%d/' % cosigner_index, ks.dump()) store.put('wallet_type', multisig_type) store.put('gap_limit', gap_limit or cls.gap_limit) - w = lib.wallet.Multisig_Wallet(store) + w = Multisig_Wallet(store) w.synchronize() return w -# TODO passphrase/seed_extension class TestWalletKeystoreAddressIntegrityForMainnet(SequentialTestCase): @needs_test_with_all_ecc_implementations @@ -111,6 +115,26 @@ def test_electrum_seed_segwit(self, mock_write): self.assertEqual(w.get_receiving_addresses()[0], 'mona1q3g5tmkmlvxryhh843v4dz026avatc0zz8fpnsg') self.assertEqual(w.get_change_addresses()[0], 'mona1qdy94n2q5qcp0kg7v9yzwe6wvfkhnvyzjad9y8q') + @needs_test_with_all_ecc_implementations + @mock.patch.object(storage.WalletStorage, '_write') + def test_electrum_seed_segwit_passphrase(self, mock_write): + seed_words = 'bitter grass shiver impose acquire brush forget axis eager alone wine silver' + self.assertEqual(bitcoin.seed_type(seed_words), 'segwit') + + ks = keystore.from_seed(seed_words, UNICODE_HORROR, False) + + WalletIntegrityHelper.check_seeded_keystore_sanity(self, ks) + self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) + + self.assertEqual(ks.xprv, 'zprvAZDmEQiCLUcZXPfrBXoksCD2R6RMAzAre7SUyBotibisy9c7vGhLYvHaP3d9rYU12DKAWdZfscPNA7qEPgTkCDqX5sE93ryAJAQvkDbfLxU') + self.assertEqual(ks.xpub, 'zpub6nD7dvF6ArArjskKHZLmEL9ky8FqaSti1LN5maDWGwFrqwwGTp1b6ic4EHwciFNaYDmCXcQYxXSiF9BjcLCMPcaYkVN2nQD6QjYQ8vpSR3Z') + + w = WalletIntegrityHelper.create_standard_wallet(ks) + self.assertEqual(w.txin_type, 'p2wpkh') + + self.assertEqual(w.get_receiving_addresses()[0], 'mona1qx94dutas7ysn2my645cyttujrms5d9p566vls6') + self.assertEqual(w.get_change_addresses()[0], 'mona1qcywwsy87sdp8vz5rfjh3sxdv6rt95kujfnkn2f') + @needs_test_with_all_ecc_implementations @mock.patch.object(storage.WalletStorage, '_write') def test_electrum_seed_old(self, mock_write): @@ -193,6 +217,25 @@ def test_bip39_seed_bip44_standard(self, mock_write): self.assertEqual(w.get_receiving_addresses()[0], 'MS5xvLi9MztCEBdct5TaGWBxgbxkbdKioY') self.assertEqual(w.get_change_addresses()[0], 'MU8uE2nH1pkVt7outQMjki68do5Pp6gzK7') + @needs_test_with_all_ecc_implementations + @mock.patch.object(storage.WalletStorage, '_write') + def test_bip39_seed_bip44_standard_passphrase(self, mock_write): + seed_words = 'treat dwarf wealth gasp brass outside high rent blood crowd make initial' + self.assertEqual(keystore.bip39_is_checksum_valid(seed_words), (True, True)) + + ks = keystore.from_bip39_seed(seed_words, UNICODE_HORROR, "m/44'/22'/0'") + + self.assertTrue(isinstance(ks, keystore.BIP32_KeyStore)) + + self.assertEqual(ks.xprv, 'xprv9yT9wTgHbNGsd8cUWegrXUmvGRWYnzhBVnKXBABGEydimfVe13zuCUYposYjqFE5rDc2jj1W9F5MFuA59AfbPmAX2Lp7nMVQ6XgbaZbx2YC') + self.assertEqual(ks.xpub, 'xpub6CSWLyDBRjqAqcgwcgDrtciepTM3CTR2s1F7yYasoKAheTpnYbK9kGsJfBPeBXjfHJsiEUs1vzto6JiK8MQTfFmXQgZSxFQSNbTsWExoBx7') + + w = WalletIntegrityHelper.create_standard_wallet(ks) + self.assertEqual(w.txin_type, 'p2pkh') + + self.assertEqual(w.get_receiving_addresses()[0], 'MPupn7dRc9tSpayLQrk6j6UGidRWbquccD') + self.assertEqual(w.get_change_addresses()[0], 'MR3eRFkFt9rFVPM6eFi9pkDprm4shTEEf6') + @needs_test_with_all_ecc_implementations @mock.patch.object(storage.WalletStorage, '_write') def test_bip39_seed_bip49_p2sh_segwit(self, mock_write): diff --git a/lib/transaction.py b/electrum/transaction.py similarity index 100% rename from lib/transaction.py rename to electrum/transaction.py diff --git a/lib/util.py b/electrum/util.py similarity index 99% rename from lib/util.py rename to electrum/util.py index 7e8ebffac336..f22774f0bd3b 100644 --- a/lib/util.py +++ b/electrum/util.py @@ -328,16 +328,19 @@ def android_data_dir(): return PythonActivity.mActivity.getFilesDir().getPath() + '/data' def android_headers_dir(): - d = android_ext_dir() + '/org.electrum_mona.electrum_mona' + d = android_ext_dir() + '/org.electrum-mona.electrum' if not os.path.exists(d): - os.mkdir(d) + try: + os.mkdir(d) + except FileExistsError: + pass # in case of race return d def android_check_data_dir(): """ if needed, move old directory to sandbox """ ext_dir = android_ext_dir() data_dir = android_data_dir() - old_electrum_dir = ext_dir + '/electrum_mona' + old_electrum_dir = ext_dir + '/electrum' if not os.path.exists(data_dir) and os.path.exists(old_electrum_dir): import shutil new_headers_path = android_headers_dir() + '/blockchain_headers' diff --git a/lib/verifier.py b/electrum/verifier.py similarity index 85% rename from lib/verifier.py rename to electrum/verifier.py index a5bec9f55142..16024eba68fa 100644 --- a/lib/verifier.py +++ b/electrum/verifier.py @@ -42,44 +42,46 @@ def run(self): interface = self.network.interface if not interface: return + blockchain = interface.blockchain if not blockchain: return - lh = self.network.get_local_height() + + local_height = self.network.get_local_height() unverified = self.wallet.get_unverified_txs() for tx_hash, tx_height in unverified.items(): tx_min_hash, tx_min_height = min(unverified.items(), key=lambda x: x[1]) index_min = tx_min_height // 2016 # do not request merkle branch before headers are available - if (tx_height > 0) and (tx_height <= lh): - header = blockchain.read_header(tx_height) - if header is None: - index = tx_height // 2016 - if index < len(blockchain.checkpoints): - self.network.request_chunk(interface, index) - else: - if (tx_hash not in self.requested_merkle - and tx_hash not in self.merkle_roots): - - self.network.get_merkle_for_transaction( - tx_hash, - tx_height, - self.verify_merkle) - self.print_error('requested merkle', tx_hash) - self.requested_merkle.add(tx_hash) + if tx_height <= 0 or tx_height > local_height: + continue + + header = blockchain.read_header(tx_height) + if header is None: + index = tx_height // 2016 + if index < len(blockchain.checkpoints): + self.network.request_chunk(interface, index) + elif (tx_hash not in self.requested_merkle + and tx_hash not in self.merkle_roots): + self.network.get_merkle_for_transaction( + tx_hash, + tx_height, + self.verify_merkle) + self.print_error('requested merkle', tx_hash) + self.requested_merkle.add(tx_hash) if self.network.blockchain() != self.blockchain: self.blockchain = self.network.blockchain() self.undo_verifications() - def verify_merkle(self, r): + def verify_merkle(self, response): if self.wallet.verifier is None: return # we have been killed, this was just an orphan callback - if r.get('error'): - self.print_error('received an error:', r) + if response.get('error'): + self.print_error('received an error:', response) return - params = r['params'] - merkle = r['result'] + params = response['params'] + merkle = response['result'] # Verify the hash of the server-provided merkle branch to a # transaction matches the merkle root of its block tx_hash = params[0] diff --git a/lib/version.py b/electrum/version.py similarity index 100% rename from lib/version.py rename to electrum/version.py diff --git a/lib/wallet.py b/electrum/wallet.py similarity index 77% rename from lib/wallet.py rename to electrum/wallet.py index 97de2e2b13b3..182c4ced411b 100644 --- a/lib/wallet.py +++ b/electrum/wallet.py @@ -28,7 +28,7 @@ import os -import threading +import sys import random import time import json @@ -36,12 +36,8 @@ import errno import traceback from functools import partial -from collections import defaultdict from numbers import Number from decimal import Decimal -import itertools - -import sys from .i18n import _ from .util import (NotEnoughFunds, PrintError, UserCancelled, profiler, @@ -54,15 +50,12 @@ from .keystore import load_keystore, Hardware_KeyStore from .storage import multisig_type, STO_EV_PLAINTEXT, STO_EV_USER_PW, STO_EV_XPUB_PW -from . import transaction +from . import transaction, bitcoin, coinchooser, paymentrequest, contacts from .transaction import Transaction -from .plugins import run_hook -from . import bitcoin -from . import coinchooser -from .synchronizer import Synchronizer -from .verifier import SPV +from .plugin import run_hook +from .address_synchronizer import (AddressSynchronizer, TX_HEIGHT_LOCAL, + TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED) -from . import paymentrequest from .paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED from .paymentrequest import InvoiceStore from .contacts import Contacts @@ -74,9 +67,6 @@ _('Local'), ] -TX_HEIGHT_LOCAL = -2 -TX_HEIGHT_UNCONF_PARENT = -1 -TX_HEIGHT_UNCONFIRMED = 0 def relayfee(network): @@ -178,68 +168,37 @@ def sweep(privkeys, network, config, recipient, fee=None, imax=100): return tx -class AddTransactionException(Exception): - pass +class CannotBumpFee(Exception): pass -class UnrelatedTransactionException(AddTransactionException): - def __str__(self): - return _("Transaction is unrelated to this wallet.") -class CannotBumpFee(Exception): pass - -class Abstract_Wallet(PrintError): +class Abstract_Wallet(AddressSynchronizer): """ Wallet classes are created to handle various address generation methods. Completion states (watching-only, single account, no seed, etc) are handled inside classes. """ max_change_outputs = 3 + gap_limit_for_change = 6 def __init__(self, storage): + AddressSynchronizer.__init__(self, storage) self.electrum_version = ELECTRUM_VERSION - self.storage = storage - self.network = None - # verifier (SPV) and synchronizer are started in start_threads - self.synchronizer = None - self.verifier = None - - self.gap_limit_for_change = 6 # constant - - # locks: if you need to take multiple ones, acquire them in the order they are defined here! - self.lock = threading.RLock() - self.transaction_lock = threading.RLock() - # saved fields self.use_change = storage.get('use_change', True) self.multiple_change = storage.get('multiple_change', False) self.labels = storage.get('labels', {}) self.frozen_addresses = set(storage.get('frozen_addresses',[])) - self.history = storage.get('addr_history',{}) # address -> list(txid, height) self.fiat_value = storage.get('fiat_value', {}) self.receive_requests = storage.get('payment_requests', {}) - # Verified transactions. txid -> (height, timestamp, block_pos). Access with self.lock. - self.verified_tx = storage.get('verified_tx3', {}) - # Transactions pending verification. txid -> tx_height. Access with self.lock. - self.unverified_tx = defaultdict(int) - self.load_keystore() self.load_addresses() self.test_addresses_sanity() - self.load_transactions() - self.load_local_history() - self.check_history() - self.load_unverified_transactions() - self.remove_local_transactions_we_dont_have() - # There is a difference between wallet.up_to_date and network.is_up_to_date(). - # network.is_up_to_date() returns true when all requests have been answered and processed - # wallet.up_to_date is true when the wallet is synchronized (stronger requirement) - # Neither of them considers the verifier. - self.up_to_date = False + self.check_history() # save wallet type the first time if self.storage.get('wallet_type') is None: @@ -251,7 +210,6 @@ def __init__(self, storage): self.coin_price_cache = {} - def diagnostic_name(self): return self.basename() @@ -261,92 +219,16 @@ def __str__(self): def get_master_public_key(self): return None - @profiler - def load_transactions(self): - # load txi, txo, tx_fees - self.txi = self.storage.get('txi', {}) - for txid, d in list(self.txi.items()): - for addr, lst in d.items(): - self.txi[txid][addr] = set([tuple(x) for x in lst]) - self.txo = self.storage.get('txo', {}) - self.tx_fees = self.storage.get('tx_fees', {}) - tx_list = self.storage.get('transactions', {}) - # load transactions - self.transactions = {} - for tx_hash, raw in tx_list.items(): - tx = Transaction(raw) - self.transactions[tx_hash] = tx - if self.txi.get(tx_hash) is None and self.txo.get(tx_hash) is None: - self.print_error("removing unreferenced tx", tx_hash) - self.transactions.pop(tx_hash) - # load spent_outpoints - _spent_outpoints = self.storage.get('spent_outpoints', {}) - self.spent_outpoints = defaultdict(dict) - for prevout_hash, d in _spent_outpoints.items(): - for prevout_n_str, spending_txid in d.items(): - prevout_n = int(prevout_n_str) - self.spent_outpoints[prevout_hash][prevout_n] = spending_txid - - @profiler - def load_local_history(self): - self._history_local = {} # address -> set(txid) - for txid in itertools.chain(self.txi, self.txo): - self._add_tx_to_local_history(txid) - - def remove_local_transactions_we_dont_have(self): - txid_set = set(self.txi) | set(self.txo) - for txid in txid_set: - tx_height = self.get_tx_height(txid)[0] - if tx_height == TX_HEIGHT_LOCAL and txid not in self.transactions: - self.remove_transaction(txid) - - @profiler - def save_transactions(self, write=False): - with self.transaction_lock: - tx = {} - for k,v in self.transactions.items(): - tx[k] = str(v) - self.storage.put('transactions', tx) - self.storage.put('txi', self.txi) - self.storage.put('txo', self.txo) - self.storage.put('tx_fees', self.tx_fees) - self.storage.put('addr_history', self.history) - self.storage.put('spent_outpoints', self.spent_outpoints) - if write: - self.storage.write() - - def save_verified_tx(self, write=False): - with self.lock: - self.storage.put('verified_tx3', self.verified_tx) - if write: - self.storage.write() - - def clear_history(self): - with self.lock: - with self.transaction_lock: - self.txi = {} - self.txo = {} - self.tx_fees = {} - self.spent_outpoints = defaultdict(dict) - self.history = {} - self.verified_tx = {} - self.transactions = {} - self.save_transactions() - @profiler def check_history(self): save = False - hist_addrs_mine = list(filter(lambda k: self.is_mine(k), self.history.keys())) hist_addrs_not_mine = list(filter(lambda k: not self.is_mine(k), self.history.keys())) - for addr in hist_addrs_not_mine: self.history.pop(addr) save = True - for addr in hist_addrs_mine: hist = self.history[addr] - for tx_hash, tx_height in hist: if self.txi.get(tx_hash) or self.txo.get(tx_hash): continue @@ -381,19 +263,6 @@ def synchronize(self): def is_deterministic(self): return self.keystore.is_deterministic() - def set_up_to_date(self, up_to_date): - with self.lock: - self.up_to_date = up_to_date - if up_to_date: - self.save_transactions(write=True) - # if the verifier is also up to date, persist that too; - # otherwise it will persist its results when it finishes - if self.verifier and self.verifier.is_up_to_date(): - self.save_verified_tx(write=True) - - def is_up_to_date(self): - with self.lock: return self.up_to_date - def set_label(self, name, text = None): changed = False old_text = self.labels.get(name) @@ -464,64 +333,6 @@ def export_private_key(self, address, password): def get_public_keys(self, address): return [self.get_public_key(address)] - def add_unverified_tx(self, tx_hash, tx_height): - if tx_height in (TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT) \ - and tx_hash in self.verified_tx: - with self.lock: - self.verified_tx.pop(tx_hash) - if self.verifier: - self.verifier.remove_spv_proof_for_tx(tx_hash) - - # tx will be verified only if height > 0 - if tx_hash not in self.verified_tx: - with self.lock: - self.unverified_tx[tx_hash] = tx_height - - def add_verified_tx(self, tx_hash, info): - # Remove from the unverified map and add to the verified map - with self.lock: - self.unverified_tx.pop(tx_hash, None) - self.verified_tx[tx_hash] = info # (tx_height, timestamp, pos) - height, conf, timestamp = self.get_tx_height(tx_hash) - self.network.trigger_callback('verified', tx_hash, height, conf, timestamp) - - def get_unverified_txs(self): - '''Returns a map from tx hash to transaction height''' - with self.lock: - return dict(self.unverified_tx) # copy - - def undo_verifications(self, blockchain, height): - '''Used by the verifier when a reorg has happened''' - txs = set() - with self.lock: - for tx_hash, item in list(self.verified_tx.items()): - tx_height, timestamp, pos = item - if tx_height >= height: - header = blockchain.read_header(tx_height) - # fixme: use block hash, not timestamp - if not header or header.get('timestamp') != timestamp: - self.verified_tx.pop(tx_hash, None) - txs.add(tx_hash) - return txs - - def get_local_height(self): - """ return last known height if we are offline """ - return self.network.get_local_height() if self.network else self.storage.get('stored_height', 0) - - def get_tx_height(self, tx_hash): - """ Given a transaction, returns (height, conf, timestamp) """ - with self.lock: - if tx_hash in self.verified_tx: - height, timestamp, pos = self.verified_tx[tx_hash] - conf = max(self.get_local_height() - height + 1, 0) - return height, conf, timestamp - elif tx_hash in self.unverified_tx: - height = self.unverified_tx[tx_hash] - return height, 0, None - else: - # local transaction - return TX_HEIGHT_LOCAL, 0, None - def get_txpos(self, tx_hash): "return position, even if the tx is unverified" with self.lock: @@ -780,24 +591,6 @@ def get_address_history(self, addr): h.append((tx_hash, tx_height)) return h - def _add_tx_to_local_history(self, txid): - with self.transaction_lock: - for addr in itertools.chain(self.txi.get(txid, []), self.txo.get(txid, [])): - cur_hist = self._history_local.get(addr, set()) - cur_hist.add(txid) - self._history_local[addr] = cur_hist - - def _remove_tx_from_local_history(self, txid): - with self.transaction_lock: - for addr in itertools.chain(self.txi.get(txid, []), self.txo.get(txid, [])): - cur_hist = self._history_local.get(addr, set()) - try: - cur_hist.remove(txid) - except KeyError: - pass - else: - self._history_local[addr] = cur_hist - def get_txin_address(self, txi): addr = txi.get('address') if addr and addr != "(pubkey)": @@ -821,235 +614,6 @@ def get_txout_address(self, txo): addr = None return addr - def get_conflicting_transactions(self, tx): - """Returns a set of transaction hashes from the wallet history that are - directly conflicting with tx, i.e. they have common outpoints being - spent with tx. If the tx is already in wallet history, that will not be - reported as a conflict. - """ - conflicting_txns = set() - with self.transaction_lock: - for txin in tx.inputs(): - if txin['type'] == 'coinbase': - continue - prevout_hash = txin['prevout_hash'] - prevout_n = txin['prevout_n'] - spending_tx_hash = self.spent_outpoints[prevout_hash].get(prevout_n) - if spending_tx_hash is None: - continue - # this outpoint has already been spent, by spending_tx - assert spending_tx_hash in self.transactions - conflicting_txns |= {spending_tx_hash} - txid = tx.txid() - if txid in conflicting_txns: - # this tx is already in history, so it conflicts with itself - if len(conflicting_txns) > 1: - raise Exception('Found conflicting transactions already in wallet history.') - conflicting_txns -= {txid} - return conflicting_txns - - def add_transaction(self, tx_hash, tx, allow_unrelated=False): - assert tx_hash, tx_hash - assert tx, tx - assert tx.is_complete() - # we need self.transaction_lock but get_tx_height will take self.lock - # so we need to take that too here, to enforce order of locks - with self.lock, self.transaction_lock: - # NOTE: returning if tx in self.transactions might seem like a good idea - # BUT we track is_mine inputs in a txn, and during subsequent calls - # of add_transaction tx, we might learn of more-and-more inputs of - # being is_mine, as we roll the gap_limit forward - is_coinbase = tx.inputs()[0]['type'] == 'coinbase' - tx_height = self.get_tx_height(tx_hash)[0] - if not allow_unrelated: - # note that during sync, if the transactions are not properly sorted, - # it could happen that we think tx is unrelated but actually one of the inputs is is_mine. - # this is the main motivation for allow_unrelated - is_mine = any([self.is_mine(self.get_txin_address(txin)) for txin in tx.inputs()]) - is_for_me = any([self.is_mine(self.get_txout_address(txo)) for txo in tx.outputs()]) - if not is_mine and not is_for_me: - raise UnrelatedTransactionException() - # Find all conflicting transactions. - # In case of a conflict, - # 1. confirmed > mempool > local - # 2. this new txn has priority over existing ones - # When this method exits, there must NOT be any conflict, so - # either keep this txn and remove all conflicting (along with dependencies) - # or drop this txn - conflicting_txns = self.get_conflicting_transactions(tx) - if conflicting_txns: - existing_mempool_txn = any( - self.get_tx_height(tx_hash2)[0] in (TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_UNCONF_PARENT) - for tx_hash2 in conflicting_txns) - existing_confirmed_txn = any( - self.get_tx_height(tx_hash2)[0] > 0 - for tx_hash2 in conflicting_txns) - if existing_confirmed_txn and tx_height <= 0: - # this is a non-confirmed tx that conflicts with confirmed txns; drop. - return False - if existing_mempool_txn and tx_height == TX_HEIGHT_LOCAL: - # this is a local tx that conflicts with non-local txns; drop. - return False - # keep this txn and remove all conflicting - to_remove = set() - to_remove |= conflicting_txns - for conflicting_tx_hash in conflicting_txns: - to_remove |= self.get_depending_transactions(conflicting_tx_hash) - for tx_hash2 in to_remove: - self.remove_transaction(tx_hash2) - # add inputs - def add_value_from_prev_output(): - dd = self.txo.get(prevout_hash, {}) - # note: this nested loop takes linear time in num is_mine outputs of prev_tx - for addr, outputs in dd.items(): - # note: instead of [(n, v, is_cb), ...]; we could store: {n -> (v, is_cb)} - for n, v, is_cb in outputs: - if n == prevout_n: - if addr and self.is_mine(addr): - if d.get(addr) is None: - d[addr] = set() - d[addr].add((ser, v)) - return - self.txi[tx_hash] = d = {} - for txi in tx.inputs(): - if txi['type'] == 'coinbase': - continue - prevout_hash = txi['prevout_hash'] - prevout_n = txi['prevout_n'] - ser = prevout_hash + ':%d' % prevout_n - self.spent_outpoints[prevout_hash][prevout_n] = tx_hash - add_value_from_prev_output() - # add outputs - self.txo[tx_hash] = d = {} - for n, txo in enumerate(tx.outputs()): - v = txo[2] - ser = tx_hash + ':%d'%n - addr = self.get_txout_address(txo) - if addr and self.is_mine(addr): - if d.get(addr) is None: - d[addr] = [] - d[addr].append((n, v, is_coinbase)) - # give v to txi that spends me - next_tx = self.spent_outpoints[tx_hash].get(n) - if next_tx is not None: - dd = self.txi.get(next_tx, {}) - if dd.get(addr) is None: - dd[addr] = set() - if (ser, v) not in dd[addr]: - dd[addr].add((ser, v)) - self._add_tx_to_local_history(next_tx) - # add to local history - self._add_tx_to_local_history(tx_hash) - # save - self.transactions[tx_hash] = tx - return True - - def remove_transaction(self, tx_hash): - def remove_from_spent_outpoints(): - # undo spends in spent_outpoints - if tx is not None: # if we have the tx, this branch is faster - for txin in tx.inputs(): - if txin['type'] == 'coinbase': - continue - prevout_hash = txin['prevout_hash'] - prevout_n = txin['prevout_n'] - self.spent_outpoints[prevout_hash].pop(prevout_n, None) - if not self.spent_outpoints[prevout_hash]: - self.spent_outpoints.pop(prevout_hash) - else: # expensive but always works - for prevout_hash, d in list(self.spent_outpoints.items()): - for prevout_n, spending_txid in d.items(): - if spending_txid == tx_hash: - self.spent_outpoints[prevout_hash].pop(prevout_n, None) - if not self.spent_outpoints[prevout_hash]: - self.spent_outpoints.pop(prevout_hash) - # Remove this tx itself; if nothing spends from it. - # It is not so clear what to do if other txns spend from it, but it will be - # removed when those other txns are removed. - if not self.spent_outpoints[tx_hash]: - self.spent_outpoints.pop(tx_hash) - - with self.transaction_lock: - self.print_error("removing tx from history", tx_hash) - tx = self.transactions.pop(tx_hash, None) - remove_from_spent_outpoints() - self._remove_tx_from_local_history(tx_hash) - self.txi.pop(tx_hash, None) - self.txo.pop(tx_hash, None) - - def receive_tx_callback(self, tx_hash, tx, tx_height): - self.add_unverified_tx(tx_hash, tx_height) - self.add_transaction(tx_hash, tx, allow_unrelated=True) - - def receive_history_callback(self, addr, hist, tx_fees): - with self.lock: - old_hist = self.get_address_history(addr) - for tx_hash, height in old_hist: - if (tx_hash, height) not in hist: - # make tx local - self.unverified_tx.pop(tx_hash, None) - self.verified_tx.pop(tx_hash, None) - if self.verifier: - self.verifier.remove_spv_proof_for_tx(tx_hash) - self.history[addr] = hist - - for tx_hash, tx_height in hist: - # add it in case it was previously unconfirmed - self.add_unverified_tx(tx_hash, tx_height) - # if addr is new, we have to recompute txi and txo - tx = self.transactions.get(tx_hash) - if tx is None: - continue - self.add_transaction(tx_hash, tx, allow_unrelated=True) - - # Store fees - self.tx_fees.update(tx_fees) - - def get_history(self, domain=None): - # get domain - if domain is None: - domain = self.get_addresses() - domain = set(domain) - # 1. Get the history of each address in the domain, maintain the - # delta of a tx as the sum of its deltas on domain addresses - tx_deltas = defaultdict(int) - for addr in domain: - h = self.get_address_history(addr) - for tx_hash, height in h: - delta = self.get_tx_delta(tx_hash, addr) - if delta is None or tx_deltas[tx_hash] is None: - tx_deltas[tx_hash] = None - else: - tx_deltas[tx_hash] += delta - - # 2. create sorted history - history = [] - for tx_hash in tx_deltas: - delta = tx_deltas[tx_hash] - height, conf, timestamp = self.get_tx_height(tx_hash) - history.append((tx_hash, height, conf, timestamp, delta)) - history.sort(key = lambda x: self.get_txpos(x[0])) - history.reverse() - - # 3. add balance - c, u, x = self.get_balance(domain) - balance = c + u + x - h2 = [] - for tx_hash, height, conf, timestamp, delta in history: - h2.append((tx_hash, height, conf, timestamp, delta, balance)) - if balance is None or delta is None: - balance = None - else: - balance -= delta - h2.reverse() - - # fixme: this may happen if history is incomplete - if balance not in [None, 0]: - self.print_error("Error: history not synchronized") - return [] - - return h2 - def balance_at_timestamp(self, domain, target_timestamp): h = self.get_history(domain) for tx_hash, height, conf, timestamp, value, balance in h: @@ -1308,36 +872,6 @@ def set_frozen_state(self, addrs, freeze): return True return False - def load_unverified_transactions(self): - # review transactions that are in the history - for addr, hist in self.history.items(): - for tx_hash, tx_height in hist: - # add it in case it was previously unconfirmed - self.add_unverified_tx(tx_hash, tx_height) - - def start_threads(self, network): - self.network = network - if self.network is not None: - self.verifier = SPV(self.network, self) - self.synchronizer = Synchronizer(self, network) - network.add_jobs([self.verifier, self.synchronizer]) - else: - self.verifier = None - self.synchronizer = None - - def stop_threads(self): - if self.network: - self.network.remove_jobs([self.synchronizer, self.verifier]) - self.synchronizer.release() - self.synchronizer = None - self.verifier = None - # Now no references to the synchronizer or verifier - # remain so they will be GC-ed - self.storage.put('stored_height', self.get_local_height()) - self.save_transactions() - self.save_verified_tx() - self.storage.write() - def wait_until_synchronized(self, callback=None): def wait_for_wallet(): self.set_up_to_date(False) @@ -1628,7 +1162,7 @@ def get_request_status(self, key): expiration = 0 conf = None if amount: - if self.up_to_date: + if self.is_up_to_date(): paid, conf = self.get_payment_status(address, amount) status = PR_PAID if paid else PR_UNPAID if status == PR_UNPAID and expiration is not None and time.time() > timestamp + expiration: @@ -1723,12 +1257,6 @@ def can_import_address(self): def can_delete_address(self): return False - def add_address(self, address): - if address not in self.history: - self.history[address] = [] - if self.synchronizer: - self.synchronizer.add(address) - def has_password(self): return self.has_keystore_encryption() or self.has_storage_encryption() @@ -1866,6 +1394,10 @@ def coin_price(self, txid, price_func, ccy, txin_value): p = self.price_at_timestamp(txid, price_func) return p * txin_value/Decimal(COIN) + def is_billing_address(self, addr): + # overloaded for TrustedCoin wallets + return False + class Simple_Wallet(Abstract_Wallet): # wallet with a single keystore diff --git a/lib/websockets.py b/electrum/websockets.py similarity index 100% rename from lib/websockets.py rename to electrum/websockets.py diff --git a/lib/wordlist/chinese_simplified.txt b/electrum/wordlist/chinese_simplified.txt similarity index 100% rename from lib/wordlist/chinese_simplified.txt rename to electrum/wordlist/chinese_simplified.txt diff --git a/lib/wordlist/english.txt b/electrum/wordlist/english.txt similarity index 100% rename from lib/wordlist/english.txt rename to electrum/wordlist/english.txt diff --git a/lib/wordlist/japanese.txt b/electrum/wordlist/japanese.txt similarity index 100% rename from lib/wordlist/japanese.txt rename to electrum/wordlist/japanese.txt diff --git a/lib/wordlist/portuguese.txt b/electrum/wordlist/portuguese.txt similarity index 100% rename from lib/wordlist/portuguese.txt rename to electrum/wordlist/portuguese.txt diff --git a/lib/wordlist/spanish.txt b/electrum/wordlist/spanish.txt similarity index 100% rename from lib/wordlist/spanish.txt rename to electrum/wordlist/spanish.txt diff --git a/lib/x509.py b/electrum/x509.py similarity index 100% rename from lib/x509.py rename to electrum/x509.py diff --git a/lib/setup.py b/lib/setup.py deleted file mode 100644 index d11615c8ba16..000000000000 --- a/lib/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -from distutils.core import setup -from Cython.Build import cythonize - -setup( - ext_modules = cythonize("target.pyx") -) diff --git a/pubkeys/sombernight.asc b/pubkeys/sombernight.asc deleted file mode 100644 index 336606856d9e..000000000000 --- a/pubkeys/sombernight.asc +++ /dev/null @@ -1,92 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFq/xaYBEADLjN4eABFUTJH0OGRE6mtfPz4J2WYU8B3VI0KSKnqSNwGKm6MP -dB394HIxpxO2aKW2IbxULQvbsaMYmqYYXzndlGgQIcqX6FSNfoOfmsTW9zzLI7CU -Ezsh4lvV5PIxCMaJdG1qwM4vEEQh2AZkqdGLCNjS1nDywDFUqC11R+XmbcpDh6pn -/T8f7oWBEBpfYKCPWSy35oRIxse9o6pc84JxGRv57eVMofApkZkhDVf+r+Z3mjbj -iDVmRo/cGTaEPod3332z5dh+Ee/7Tg8RiVpqrJXkDlL+VhHH3ARECw/PeQEVd7B7 -Rxv9Ss/At2Js0Ah6cQSc67+S2Fuk/c7CahItAEJO9Us8T5LhhBNkc8QD9VoFkHBz -T7S6Xhvq2MbRdbpIWLg32IqilARYUOSDOfa1GR//5lRW6Z9XX9GEjkKNAHbeQVTQ -kwTVjN34cHMv03PhNy3a3FVaHzcIW+NTS5d7yuyinmTR+a3DTH3Uoo2d1TEItb6J -NJsMaq4mC7XoXSg0JflqNU3sCjC22V/fFdGbdtLGJmv1pDX8g10XZ0REIZUX3vfl -zsUsS3P0MD8aHst6nQzsDiUSjouuMdyO66rSKUZSM54rUH4DIj9EKq+yA8qfq6jJ -UUvOo4AXpBsdQmNBj5FLksFKIEatC0ov+/U/Nj1G884UkWXJv9GqmcGvjQARAQAB -tClTb21iZXJOaWdodCA8c29tYmVyLm5pZ2h0QHByb3Rvbm1haWwuY29tPokCTgQT -AQgAOBYhBErWQznfoF4gs/atUee3SM2vXl7ZBQJav8WmAhsDBQsJCAcCBhUKCQgL -AgQWAgMBAh4BAheAAAoJEOe3SM2vXl7ZPp0P/3yPNOgatCImwQq3eoXBNOonXazI -7y4E/mcCNz0PJQmpxrzrbM/JEKx0ARXQuRw/ai22+tPM9XNkD1ewySs6iNMmeT4T -YDQajNCI7V+aXlvLdbRnSwHaXC1gT/LA65vraTRuzkiCGkPFEmvUFO8ax1pdMwz2 -jxpXLRo04NtQf1BHAi3iM0BAd0+MY5xd7Dcqzdp96Kg/KY89g09UscQ7O6HKfM5k -DQyOKfUgGJJ/rbON7OuFEJCrAbIPp+xOysIz+7ay602lpPnbNnmjgDcg3V4U3O7T -vZQqXD7AHUUA03PDUUtAfpgNzSFqbh0T3UDjQI/Yv/LOQmHqvD6XxEiIb42Ttj0C -hmWbamXV/Q2Fkt5QSvmXeTAEI8R9IW/Ui8+WvnHwxck51P5PnH/U2raBgU8nYpCv -L78m9GFsScgrf6MMWRfh4L53E7eS3Mb4YTUgIgCdb5PYlDLq9zlyQiDFf9tW9V6A -b7db/BVUWQ4wu9lulumnbooUY98DaodWL7TmAbOgqmMPX0KBOhf1vNXIuF8puIoK -jowV9FIYD0muVICHY4U0uMO9hqnvdRjQXssTY1u4io3bfG4l49wnCNup2rRMS172 -uef+xIl5rle0MsGBlcjf48Fuxi1FnFNzeRrVP8s8NEof4/men+3a0bnB0GywHtSr -D9HurGkl0mOJOt/piQEiBBABAgAMBQJav8wABQMAEnUAAAoJEJcQuJvKV618UgUI -AKi/tyFRSXqef3qUpdLG+2l6TTw8TMejQGtifKAKZ/sBWtIY3UruKVaKlHqb9vXR -/ZFMezQZoW+Z4mA79NS+T6yIH8AnaN6lIIbXEQ8lzJHV744Wp+vWlluqLD30534m -bfGRFmPj8jCCV5k/GHsSUL3GTFlfxOOI8wQu/xENqRX6HjhH1pKOQfYqOBbxhaOv -IrRYlL3Ia6CVJpHzJbQVKOwu8reij8MZ5hE1xr+Dj9i7GGYVlz2ZPRfOIzM7mIN8 -v8nMXsrb7sEMNga9tDD4/YV93rDodBk2bEk+yVR11/uX8BC1bpHoAncd7qbd42Ie -E1ZZ2scYrMPz7YBkTEh6Yum5Ag0EWr/FpgEQAKzVKZzXQ0lTXt+B9Y+wPiBfGlSu -NPFEf+jgMEiwjWFG/G47pDqUejTHovg/L6WA2MWW5sS9NfcSsq6FusnSRYoHH1Bj -er+HlIGJp102m1mdvMjV/2CwG7Vv/emzzguy153GFpmsP70aGqno2vXil2Z1/jKx -8eSEbHoW/n5nJGq9E3p50ZyRDy0ZQHlZgpoU0+0qbMQawo4DKTgfDEGwPLt+8+pR -4dF2T5Yxomf6k2NN6l2xuJrIl57tpanPBkwC9/qLLZpww/leX1g4GkQx7f7kic1F -jCPDpSYGXITkkT253lHXiy3ttJGT2zPwgvKxuktsj9Wb5vpc55NH9inKCnPXKbFm -34mOfmFGlZ2UJn4wG3OQgbMDtfUnJFo0L+thjg7SDDXra7NHshmslp0+YvBfVttn -0C33bFCUc26hUUrkcemAsZgphEOJ6aYMk2A3dcFjylt/wID4jHVhpdhdkbqBhA/2 -BJL6o9fpttE7+oBiM5ihSClkAppRk51oLis+Eev28KMllvXsDa7HRSkrp6AFYaHy -U2pnOAmTvOxN6+oEJGS1vKfCu4Oy64TQ3Cs7JXP4sgwF8pd5LoYPsO7hfbwGMN62 -fEil17cuA0Lz6xwFHBIdJFfSbJjv2AmZ7P/220bUW9jNh2Vol9Cm9JfTQsAY43mF -Qa4yMLdd3F3dvfCFABEBAAGJAjYEGAEIACAWIQRK1kM536BeILP2rVHnt0jNr15e -2QUCWr/FpgIbDAAKCRDnt0jNr15e2UR6EACR1qooneG5onL8sBhjVW7TRuMx5F02 -FJJ90KKcI+bOUpqSHFWAFLmjtMjqVIzFuz+Mfaer6KtCnLO7RAtCNxTvZ5N/qeG0 -RH2qQ/ETPAASEn6aCARDtXDG67T1GNaTo5QIYg6ipD1wb/ptkRqD0yK4Y99aKcy0 -uxMedc10XJDXfNeGMWQoHwn1PAlOGQTbt4JOQbH/VEC8/NDrPDAd2fw2oIC2gi0o -TSbIY4pKeFOt5F0UIkDzctR3sTyvLXuH7o0azRTIdvVogouON6DtizQf/i2qi/5/ -tCce8JksRzUf53lNDBj4gLMttv79VBtTf5F5e5mny5N5JmaTdkpdZtDwrQN1fAMm -sIFDND7fIdW/7uwA11yTeYoJGxcGHiDNVqdWcSzleL0uhOHZTvbsf6Hu743j3L/j -JMqllf7W4rPHx3OjLC4dCgUxA3gg2pylYSOldQGE4I1JJLW9La5f8yNvjXOic36O -rHKHZPO5aOGRqgLnJwDvPEyUSc4CClKDN0a/9gSgabSjoQZ12kPA73qTI45onMYI -o2c1y9KzvGVTrDbfFMNzjgSGfiSBSS6WYs9iIy0KqFry3UZWi+P59ea+cVPcOrcN -2p7zbJaPijJtvKeInT51inTjvJTx064nAB7dgFYklhzCumyOgVl4c+Zkn9Rl+h3e -LtctJR6oxIvVDrkCDQRav8ckARAAp+3ZGLyft2kClLJNYy9NTTOUZqbT4FokAqpz -39hRdt10GcV98TyWS+faOHf2rLXQ5OMMFlJdEnsvU4DDQNMY1qUmaThEbFupZza9 -qBuqafwecfQALIRssvDnSVmcRauQJOfVCkFiGjx9vYeRT7VgWycqHeh6NuHQ7wNB -i7TW1Pb1X1qX2xfdZPXTIeym5D2RhWJnCLz215PyxZ6ypwUmrKKBuMY/YRqca9VE -AExOcyYFbs8ujojqMHCHzidZYPQomCp4JoY6DgsXlp5Y7TxFQDjC411vrWEgXQl8 -sR2icRb/fWQpn7cn8EbNJgJvfAH7EH2957FbpZar2ql329GoNZQAQv6+NNKgEdzj -f1Bm0X+uVya9u3ZBshrnq/wzI2HHZ3UW43ZKdt544us+KjouRRLaFPDvKLhoFa+i -VFBe61+eebEkhWBtKXWvrRtRtgdnbWnUu7b1ooJYE/s9O1HtPkRNav6v6p0nWJCL -b/jhOiM3TraQ6D0nZxwNRaiplCjincXlP87laNjhmkiiyUYcepmM4X2Lj1gsmbWm -KTt7TIvj4iVLhzNj7YCPH69tACnN8D5GxvnYgbnWTj3ipB236i1tAITJBkbf91fM -xWI9Gul2zIf0cvelhoVE72zHRRNln5ytUvCNlBw8M5xUIx5+xsOpbp8xnxdfa2ba -27GLZfEAEQEAAYkEbAQYAQgAIBYhBErWQznfoF4gs/atUee3SM2vXl7ZBQJav8ck -AhsCAkAJEOe3SM2vXl7ZwXQgBBkBCAAdFiEEbXohFtqQngCsIRCLsztfIyxicekF -Alq/xyQACgkQsztfIyxicekF9Q//SvZcFhowYfQSBgXNl1Q1CZQwlapDmI2xmudC -hCmg3w4uRLMhLemoHae6OWair9kYGwhC1GXnOwK7qiYLpGKjCleNuvcErCZs6IUW -3FRoLaVaRDAMw5FXsvw83+oHm5duXLiCFSIIAdIgfcWrnkEGG8Oz6GwgZ9cgGRUK -satDtGapzUlNErMgmTJclmHHxwLwbD+quLiF1iZXHGk6aDtfMtLssPFa3XBiRkHu -6GZMio4z0FQVaW4XSAEMBWO9ch7mdOGM3AMQ8yPELxmWQBxrusuCSY1hMMXjEjU8 -DBleeBduHZrsphcDoAlE2wY8cIiZgl41K5yBCX5N++9qpwSCsuOK3suidzqCPLCU -y7eY0/4UorbmNHoCIPl5oOZCIL+zv81DTKGFGd9bB77ggVEGzT+sDNvrmeuvwGYw -e8V7TA9gaxh4P1+qLwN5USqSeu27AhrXw0Hgym3vLUBURLLPVxX6HPapJhYsPwPR -yFlyJLYVoBp4Y4k4YIeqiWPCc+a1nlTfvK/OJDvvCzNFZh5K26csvZnBrortmUau -2k4zIg/DMJn4FWwveQ1HNKmyCKbQWCehCr2qa+QOG6R+FO/TxFRCsWNabb7blkRV -1QNBOhVGp6g5vrJQLzc2kA9kEZRlHIepWucpxOBsOPuOQR5/gcM9RhQ80HuYGY+k -fkBcCiTqShAAr18KpfDmSMBng4DX2WJVr1aTZ3ntJeCY8F0T9nEN/rPPZ2R/4cEB -8obaoyKAYYzaFtRujJy+IvKfDE9t9qarGbvEauy97dU6cbhEyCGqfwwDo6WJvwx0 -kdl8IfNqYJ7EJiNtox1Z7OgidH0wmOHaxRmX4t5Pnny3FR5zCfAr8bf5e+v94OLW -SBV336PhXhZttoCzCpZTV55ZNV8xPy8AD0sTpOJ59w1FjZyGKOmtjzBqJFrFy+EN -JXW0k+fSb9ZLORlgJR3bxI2Q3LVo+C6Hl2vW3A9BgqXwT9cYPW+5Lpq1iS0WuGz3 -B3+jZSFkXYFYFpNPmi8u1exItKl331qxu8g5R4RCReQhmL0of+kMB90sKjg2gn/A -2dVORjVK2IbHy3ftFCiku5SiqK1Qs9U/ZawsBxfuJpE2bxMWSZ9qSr5Ef622wTfK -EeJqSBO4MH04JFD5ckiimg+4Kad1Hieg5LOgavonVV9xvVMgsxQNpfoPFYUTakN0 -abDMKxA1b6R2gxIvvp50M9J7t/BnqPqM148Q20Cgm1G1AK8z8N+2cX22hYcmyt2x -LEwfWaojVFp518+6GT8hmwgjROUGC3OWM6Daq/F/jej/sI7+Md40vI4Bn8t4gdEA -k4b8JKqEhlT/nyvlS5ynegosnLIMNlqO09El0wpRHTJoxb951/GPMM8= -=+v+2 ------END PGP PUBLIC KEY BLOCK----- diff --git a/electrum-mona b/run_electrum similarity index 92% rename from electrum-mona rename to run_electrum index f2b8132a4124..6737b07d4b00 100755 --- a/electrum-mona +++ b/run_electrum @@ -32,7 +32,7 @@ is_local = not is_bundle and os.path.exists(os.path.join(script_dir, "electrum-m is_android = 'ANDROID_DATA' in os.environ # move this back to gui/kivy/__init.py once plugins are moved -os.environ['KIVY_DATA_DIR'] = os.path.abspath(os.path.dirname(__file__)) + '/gui/kivy/data/' +os.environ['KIVY_DATA_DIR'] = os.path.abspath(os.path.dirname(__file__)) + '/electrum/gui/kivy/data/' if is_local or is_android: sys.path.insert(0, os.path.join(script_dir, 'packages')) @@ -46,7 +46,6 @@ def check_imports(): import ecdsa import requests import qrcode - import pbkdf2 import google.protobuf import jsonrpclib except ImportError as e: @@ -64,25 +63,19 @@ def check_imports(): if not is_android: check_imports() -# load local module as electrum -if is_local or is_android: - import imp - imp.load_module('electrum_mona', *imp.find_module('lib')) - imp.load_module('electrum_mona_gui', *imp.find_module('gui')) - - -from electrum_mona import bitcoin, util -from electrum_mona import constants -from electrum_mona import SimpleConfig, Network -from electrum_mona.wallet import Wallet, Imported_Wallet -from electrum_mona.storage import WalletStorage, get_derivation_used_for_hw_device_encryption -from electrum_mona.util import print_msg, print_stderr, json_encode, json_decode, UserCancelled -from electrum_mona.util import set_verbosity, InvalidPassword -from electrum_mona.commands import get_parser, known_commands, Commands, config_variables -from electrum_mona import daemon -from electrum_mona import keystore -from electrum_mona.mnemonic import Mnemonic +from electrum import bitcoin, util +from electrum import constants +from electrum import SimpleConfig, Network +from electrum.wallet import Wallet, Imported_Wallet +from electrum import bitcoin, util, constants +from electrum.storage import WalletStorage, get_derivation_used_for_hw_device_encryption +from electrum.util import print_msg, print_stderr, json_encode, json_decode, UserCancelled +from electrum.util import set_verbosity, InvalidPassword +from electrum.commands import get_parser, known_commands, Commands, config_variables +from electrum import daemon +from electrum import keystore +from electrum.mnemonic import Mnemonic # get password routine def prompt_password(prompt, confirm=True): @@ -176,7 +169,7 @@ def init_daemon(config_options): storage = WalletStorage(config.get_wallet_path()) if not storage.file_exists(): print_msg("Error: Wallet file not found.") - print_msg("Type 'electrum-mona create' to create a new wallet, or provide a path to a wallet with the -w option") + print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option") sys.exit(0) if storage.is_encrypted(): if storage.is_encrypted_with_hw_device(): @@ -214,7 +207,7 @@ def init_cmdline(config_options, server): if cmd.requires_wallet and not storage.file_exists(): print_msg("Error: Wallet file not found.") - print_msg("Type 'electrum-mona create' to create a new wallet, or provide a path to a wallet with the -w option") + print_msg("Type 'electrum create' to create a new wallet, or provide a path to a wallet with the -w option") sys.exit(0) # important warning @@ -327,9 +320,10 @@ def run_offline_command(config, config_options, plugins): return result def init_plugins(config, gui_name): - from electrum_mona.plugins import Plugins + from electrum.plugin import Plugins return Plugins(config, is_local or is_android, gui_name) + if __name__ == '__main__': # The hook will only be used in the Qt GUI right now util.setup_thread_excepthook() @@ -436,7 +430,7 @@ if __name__ == '__main__': d = daemon.Daemon(config, fd, False) d.start() if config.get('websocket_server'): - from electrum_mona import websockets + from electrum import websockets websockets.WebSocketServer(config, d.network).start() if config.get('requests_dir'): path = os.path.join(config.get('requests_dir'), 'index.html') @@ -464,7 +458,7 @@ if __name__ == '__main__': else: cmd = known_commands[cmdname] if cmd.requires_network: - print_msg("Daemon not running; try 'electrum-mona daemon start'") + print_msg("Daemon not running; try 'electrum daemon start'") sys.exit(1) else: plugins = init_plugins(config, 'cmdline') diff --git a/scripts/estimate_fee b/scripts/estimate_fee deleted file mode 100755 index a0581f5a8a93..000000000000 --- a/scripts/estimate_fee +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -import util, json -peers = util.get_peers() -results = util.send_request(peers, 'blockchain.estimatefee', [2]) -print(json.dumps(results, indent=4)) diff --git a/setup.py b/setup.py index 1ec16357e5dc..01f1bd993f93 100755 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ with open('contrib/requirements/requirements-hw.txt') as f: requirements_hw = f.read().splitlines() -version = imp.load_source('version', 'lib/version.py') +version = imp.load_source('version', 'electrum/version.py') if sys.version_info[:3] < (3, 4, 0): sys.exit("Error: Electrum requires Python version >= 3.4.0...") @@ -54,36 +54,34 @@ install_requires=requirements, extras_require=extras_require, packages=[ - 'electrum_mona', - 'electrum_mona_gui', - 'electrum_mona_gui.qt', - 'electrum_mona_plugins', - 'electrum_mona_plugins.audio_modem', - 'electrum_mona_plugins.cosigner_pool', - 'electrum_mona_plugins.email_requests', - 'electrum_mona_plugins.greenaddress_instant', - 'electrum_mona_plugins.hw_wallet', - 'electrum_mona_plugins.keepkey', - 'electrum_mona_plugins.labels', - 'electrum_mona_plugins.ledger', - 'electrum_mona_plugins.revealer', - 'electrum_mona_plugins.trezor', - 'electrum_mona_plugins.digitalbitbox', - 'electrum_mona_plugins.virtualkeyboard', + 'electrum', + 'electrum.gui', + 'electrum.gui.qt', + 'electrum.plugins', + 'electrum.plugins.audio_modem', + 'electrum.plugins.cosigner_pool', + 'electrum.plugins.email_requests', + 'electrum.plugins.greenaddress_instant', + 'electrum.plugins.hw_wallet', + 'electrum.plugins.keepkey', + 'electrum.plugins.labels', + 'electrum.plugins.ledger', + 'electrum.plugins.revealer', + 'electrum.plugins.trezor', + 'electrum.plugins.digitalbitbox', + 'electrum.plugins.virtualkeyboard', ], package_dir={ - 'electrum_mona': 'lib', - 'electrum_mona_gui': 'gui', - 'electrum_mona_plugins': 'plugins', + 'electrum': 'electrum' }, package_data={ '': ['*.txt', '*.json', '*.ttf', '*.otf'], - 'electrum_mona': [ - 'wordlist/*.txt', - 'locale/*/LC_MESSAGES/electrum.mo', + 'electrum': [ + 'electrum/wordlist/*.txt', + 'electrum/locale/*/LC_MESSAGES/electrum.mo', ], }, - scripts=['electrum-mona'], + scripts=['electrum/electrum-mona'], data_files=data_files, description="Lightweight Monacoin Wallet", author="Thomas Voegtlin", diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 08719f92b069..d5bade0d1899 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -19,5 +19,5 @@ parts: python-version: python3 stage-packages: [python3-pyqt5] build-packages: [pyqt5-dev-tools] - install: pyrcc5 icons.qrc -o $SNAPCRAFT_PART_INSTALL/lib/python3.5/site-packages/electrum_mona_gui/qt/icons_rc.py + install: pyrcc5 icons.qrc -o $SNAPCRAFT_PART_INSTALL/lib/python3.5/site-packages/electrum/gui/qt/icons_rc.py after: [desktop-qt5] diff --git a/testcode.sh b/testcode.sh index 25795fe82d41..c6ae57dfb000 100755 --- a/testcode.sh +++ b/testcode.sh @@ -1,11 +1,2 @@ #!/bin/bash - -if [ `grep -E -r "(import|from) electrum" ../electrum-mona | grep -v "electrum_mona" | grep -E -v -c "electrum-(locale|icons)"` -ge 1 ]; then - echo "NG!!" - grep -E -r "(import|from) electrum" ../electrum-mona | grep -v "electrum_mona" | grep -E -v "electrum-(locale|icons)" - echo "NG!!" -else - echo "OK!! electrum_ not found." -fi - -pytest lib/tests/ +pytest electrum/tests/ diff --git a/tox.ini b/tox.ini index 39fc02affda7..b00d29238a2b 100644 --- a/tox.ini +++ b/tox.ini @@ -6,7 +6,7 @@ deps= pytest coverage commands= - coverage run --source=lib -m py.test -v + coverage run --source=electrum '--omit=electrum/gui/*,electrum/plugins/*,electrum/scripts/*,electrum/tests/*' -m py.test -v coverage report extras= fast