/** * Updates the Key detailed table for this account and key, with the passed addres * * @param hierarchyAccountId * @param ecKey * @param cryptoAddress * @param blockchainNetworkType */ public void updateKeyDetailedStatsWithNewAddress( int hierarchyAccountId, ECKey ecKey, CryptoAddress cryptoAddress, BlockchainNetworkType blockchainNetworkType) throws CantExecuteDatabaseOperationException, UnexpectedResultReturnedFromDatabaseException { /** If we are not allowed to save detailed information then we will exit */ if (!VaultKeyMaintenanceParameters.STORE_DETAILED_KEY_INFORMATION) return; DatabaseTable databaseTable = database.getTable( AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_DETAIL_TABLE_NAME); databaseTable.addStringFilter( AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_DETAIL_ACCOUNT_ID_COLUMN_NAME, String.valueOf(hierarchyAccountId), DatabaseFilterType.EQUAL); databaseTable.addStringFilter( AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_DETAIL_PUBLIC_KEY_COLUMN_NAME, ecKey.getPublicKeyAsHex(), DatabaseFilterType.EQUAL); try { databaseTable.loadToMemory(); } catch (CantLoadTableToMemoryException e) { throwLoadToMemoryException(e, databaseTable.getTableName()); } if (databaseTable.getRecords().size() == 0) { StringBuilder output = new StringBuilder("The key " + ecKey.toString()); output.append(System.lineSeparator()); output.append("which generated the address " + cryptoAddress.getAddress()); output.append(System.lineSeparator()); output.append("is not a key derived from the vault."); throw new UnexpectedResultReturnedFromDatabaseException( null, output.toString(), "Vault derivation miss match"); } DatabaseTableRecord record = databaseTable.getRecords().get(0); record.setStringValue( AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_DETAIL_ADDRESS_COLUMN_NAME, cryptoAddress.getAddress()); record.setStringValue( AssetsOverBitcoinCryptoVaultDatabaseConstants .KEY_MAINTENANCE_DETAIL_BLOCKCHAIN_NETWORK_TYPE_COLUMN_NAME, blockchainNetworkType.getCode()); try { databaseTable.updateRecord(record); } catch (CantUpdateRecordException e) { throw new CantExecuteDatabaseOperationException( CantExecuteDatabaseOperationException.DEFAULT_MESSAGE, e, "error updating record", "database issue"); } }
/** * Insert new public keys into the detailed monitor table * * @param accountId * @param keys * @throws CantExecuteDatabaseOperationException */ public void updateDetailMaintainerStats(int accountId, List<ECKey> keys, int currentGeneratedKeys) throws CantExecuteDatabaseOperationException { /** If we are not allowed to save detailed information then we will exit. */ if (!VaultKeyMaintenanceParameters.STORE_DETAILED_KEY_INFORMATION) return; DatabaseTable databaseTable = database.getTable( AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_DETAIL_TABLE_NAME); DatabaseTransaction transaction = database.newTransaction(); /** * I will insert each key. Since I don't want to repeat inserting keys, I will only insert the * keys which position is after currentGeneratedKeys value */ int i = 1; for (ECKey key : keys) { if (i >= currentGeneratedKeys) { DatabaseTableRecord record = databaseTable.getEmptyRecord(); record.setIntegerValue( AssetsOverBitcoinCryptoVaultDatabaseConstants .KEY_MAINTENANCE_DETAIL_ACCOUNT_ID_COLUMN_NAME, accountId); record.setIntegerValue( AssetsOverBitcoinCryptoVaultDatabaseConstants .KEY_MAINTENANCE_DETAIL_KEY_DEPTH_COLUMN_NAME, i); record.setStringValue( AssetsOverBitcoinCryptoVaultDatabaseConstants .KEY_MAINTENANCE_DETAIL_PUBLIC_KEY_COLUMN_NAME, key.getPublicKeyAsHex()); transaction.addRecordToInsert(databaseTable, record); } i++; } /** once I collected all records, I will insert them in a single transaction */ try { database.executeTransaction(transaction); } catch (DatabaseTransactionFailedException e) { throw new CantExecuteDatabaseOperationException( CantExecuteDatabaseOperationException.DEFAULT_MESSAGE, e, "error inserting records in transaction.", null); } }
private void doMigrateFrom_v1_0_262(Context context, NetworkParameters migrationParams) throws IOException { Log.d(TAG, "********* MIGRATION FROM v1.0.262 - " + migrationParams.getId() + "*********"); final File rootDir = context.getFilesDir(); final File storageDir; final File archiveDir = new File(rootDir, "archive_" + System.currentTimeMillis()); final File walletFile; final File chainFile; final File newWalletFile; final File newChainFile; if (ClientUtils.isMainNet(migrationParams)) { String walletFilesPrefix = AppConfig.MainNetConfig.get().getWalletFilesPrefix(); storageDir = new File(rootDir, "mainnet_wallet__uuid_object_storage"); walletFile = new File(rootDir, "mainnet_wallet_.wallet"); newWalletFile = new File(rootDir, walletFilesPrefix + ".wallet"); chainFile = new File(rootDir, "mainnet_wallet_.spvchain"); newChainFile = new File(rootDir, walletFilesPrefix + ".spvchain"); } else if (ClientUtils.isTestNet(migrationParams)) { String walletFilesPrefix = AppConfig.TestNetConfig.get().getWalletFilesPrefix(); storageDir = new File(rootDir, "testnet_wallet__uuid_object_storage"); walletFile = new File(rootDir, "testnet_wallet_.wallet"); newWalletFile = new File(rootDir, walletFilesPrefix + ".wallet"); chainFile = new File(rootDir, "testnet_wallet_.spvchain"); newChainFile = new File(rootDir, walletFilesPrefix + ".spvchain"); } else { throw new RuntimeException( "Network params not supported (unknown): " + migrationParams.toString()); } final File keyFile = new File(storageDir, "ECKeyWrapper.json"); if (keyFile.exists() && walletFile.exists()) { // Keys: stored in ECKeyWrapper.json /* Key format (JSON): { "...uuid1...": { "isPublicOnly": true, "keyPayload": [...bytes (integers)...], "name": "remote_server_public_key", "uuid": "...uuid1..." }, "...uuid2...": { "isPublicOnly": false, "keyPayload": [...bytes (integers)...], "name": "remote_client_public_key", "uuid": "...uuid2..." } } */ Log.d(TAG, "Key file found: " + keyFile); String keyFileJson = FileUtils.readFileToString(keyFile); Type type = new TypeToken<Map<String, ECKeyWrapper>>() {}.getType(); // Note: do not use gson from serializeutils (key is not stored in base64). Map<String, ECKeyWrapper> keys = new Gson().fromJson(keyFileJson, type); ECKey serverKey = null; ECKey clientKey = null; for (ECKeyWrapper key : keys.values()) { if (key.isPublicOnly && key.name.equals("remote_server_public_key")) { serverKey = ECKey.fromPublicOnly(key.keyPayload); } else if (!key.isPublicOnly && key.name.equals("remote_client_public_key")) { clientKey = ECKey.fromPrivate(key.keyPayload); } else { Log.d(TAG, "Unknown key name: " + key.name); } } if (clientKey != null && serverKey != null) { Log.d(TAG, "Found client and server keys - store in shared preferences."); try { /** ******** Actual Migration Code ********* */ SharedPrefUtils.setClientKey(context, migrationParams, clientKey); SharedPrefUtils.setServerKey(context, migrationParams, serverKey, "n/a - migration"); Log.d( TAG, "Migrated keys:" + " clientPubKey=" + clientKey.getPublicKeyAsHex() + ", serverPubKey=" + serverKey.getPublicKeyAsHex()); // move wallet file Log.d( TAG, "Migrate wallet file: " + walletFile.toString() + " -> " + newWalletFile.toString()); FileUtils.copyFile(walletFile, newWalletFile); Log.d( TAG, "Migrate chain file: " + chainFile.toString() + " -> " + newChainFile.toString()); FileUtils.copyFile(chainFile, newChainFile); SharedPrefUtils.enableMultisig2of2ToCltvForwarder(context); // move everything to an archive file. Log.d(TAG, "Move old files to archive dir: " + archiveDir.toString()); FileUtils.moveToDirectory(storageDir, archiveDir, true); FileUtils.moveToDirectory(walletFile, archiveDir, true); FileUtils.moveToDirectory(chainFile, archiveDir, true); } catch (Exception e) { Log.d(TAG, "Exception: ", e); // clear the changes made. SharedPrefUtils.setClientKey(context, migrationParams, null); SharedPrefUtils.setServerKey(context, migrationParams, null, ""); if (newWalletFile.exists()) { newWalletFile.delete(); } } } } else { Log.d( TAG, "Key file or wallet file not found - no migration required - " + String.format( "keyFile: %s (exists: %s), walletFile: %s (exists: %s)", keyFile.toString(), keyFile.exists(), walletFile.toString(), walletFile.exists())); } Log.d(TAG, "********* MIGRATION FROM v1.0.262 FINISHED *********"); }