From 6ff83537f4ba31503e6a3266e86b2f497937a7bf Mon Sep 17 00:00:00 2001 From: James Calfee Date: Thu, 29 Oct 2015 10:42:48 -0500 Subject: [PATCH] Run import keys genesis filter as non-worker (fixes FF < v41, breaks UI % complete reporting) #319 --- dl/src/chain/GenesisFilter.js | 79 ++++++++++++++++++ web/app/components/Wallet/ImportKeys.jsx | 102 ++++++++++++++--------- web/app/workers/GenesisFilterWorker.js | 79 +----------------- 3 files changed, 144 insertions(+), 116 deletions(-) diff --git a/dl/src/chain/GenesisFilter.js b/dl/src/chain/GenesisFilter.js index 18408361a..a73a2eaae 100644 --- a/dl/src/chain/GenesisFilter.js +++ b/dl/src/chain/GenesisFilter.js @@ -1,4 +1,6 @@ import h from "common/hash" +import config from "chain/config" +import key_utils from "common/key_utils" var bts_genesiskeys_bloom_url = undefined try { @@ -20,6 +22,13 @@ try { */ export default class GenesisFilter { + /** or call this.init */ + constructor(bloom_buffer) { + if( ! bloom_buffer ) return + this.bloom_buffer = bloom_buffer + this.bits_in_filter = bloom_buffer.length * 8 // 8388608 (test data) + } + /** Was a bloom file deployed? This does not try to load it from the server. */ isAvailable() { return bts_genesiskeys_bloom_url !== undefined } @@ -29,6 +38,7 @@ export default class GenesisFilter { throw new Error("Genesis bloom file was not deployed") var xhr = new XMLHttpRequest + // firefox 40 did not allow the blob url but ff 41.0.2 did xhr.responseType = "blob" xhr.onload = ()=> { if (xhr.status === 404) return @@ -65,4 +75,73 @@ export default class GenesisFilter { return true } + filter( account_keys, status ) { + if( ! this.isAvailable() ) { + console.log("WARN: Missing bloom filter for BTS 0.9.x wallets") + status({ error: "missing_bloom" }) + return + } + var initalizing = true + status({ initalizing }) + this.init(()=> { + var previous_address_prefix = config.address_prefix + config.address_prefix = "BTS" + try { + initalizing = false + status({ initalizing }) + var running_count_progress = 1 + for(var a = 0; a < account_keys.length; a++) { + var removed_count = 0, count = 0 + var keys = account_keys[a] + var total = keys.encrypted_private_keys.length + status({ importing: true, account_name: keys.account_name, count, total }) + for(var k = keys.encrypted_private_keys.length - 1; k >= 0; k--) { + count++ + if( count % running_count_progress === 0 ) { + running_count_progress = 47 + status({ importing: true, account_name: keys.account_name, count, total }) + } + if( ! keys.public_keys) { + // un-released format, just for testing + status({ error: "missing_public_keys" }) + return + } + var key = keys.public_keys[k] + if( /^GPH/.test(key) ) key = "BTS" + key.substring(3) + if(this.inGenesis( key )) continue + var addresses = key_utils.addresses(key) + var addy_found = false + for(var i = 0; i < addresses.length; i++) { + if(this.inGenesis( addresses[i] )) { + addy_found = true + break + } + } + if( addy_found ) continue + delete keys.encrypted_private_keys[k] + delete keys.public_keys[k] + removed_count++ + } + var encrypted_private_keys = [], public_keys = [] + for(var k = keys.encrypted_private_keys.length - 1; k >= 0; k--) { + if( ! keys.encrypted_private_keys[k]) continue + encrypted_private_keys.push( keys.encrypted_private_keys[k] ) + public_keys.push( keys.public_keys[k] ) + } + keys.encrypted_private_keys = encrypted_private_keys + status({ importing: false, account_name: keys.account_name, + count: count - removed_count, total }) + keys.public_keys = public_keys + } + status({ success: true, }) + } finally { + config.address_prefix = previous_address_prefix + if( initalizing ) { + initalizing = false + status({ initalizing }) + } + } + }) + } + } \ No newline at end of file diff --git a/web/app/components/Wallet/ImportKeys.jsx b/web/app/components/Wallet/ImportKeys.jsx index 8399a1696..b6537298e 100644 --- a/web/app/components/Wallet/ImportKeys.jsx +++ b/web/app/components/Wallet/ImportKeys.jsx @@ -22,6 +22,8 @@ import WalletDb from "stores/WalletDb"; import ImportKeysStore from "stores/ImportKeysStore" import PublicKey from "ecc/key_public"; +import GenesisFilter from "chain/GenesisFilter" + require("./ImportKeys.scss"); var import_keys_assert_checking = false @@ -312,49 +314,67 @@ export default class ImportKeys extends Component { // BTS 1.0 wallets may have a lot of generated but unused keys or spent TITAN addresses making // wallets so large it is was not possible to use the JavaScript wallets with them. - var GenesisFilterWorker = require("worker!workers/GenesisFilterWorker") - var worker = new GenesisFilterWorker - var filter_status = this.state.genesis_filter_status - worker.postMessage({ account_keys: unfiltered_account_keys }) - worker.onmessage = event => { try { - var { account_keys, status } = event.data - if( status.error === "missing_public_keys" || status.error === "missing_bloom" ) { - if( status.error === "missing_public_keys" ) - console.error("un-released format, just for testing") - update_state({ password_checksum, account_keys: unfiltered_account_keys, - genesis_filter_finished: true, genesis_filtering: false }) - return - } - if( status.success ) { - update_state({ password_checksum, account_keys, - genesis_filter_finished: true, genesis_filtering: false }) - return - } - if( status.initalizing !== undefined ) { - update_state({ genesis_filter_initalizing: status.initalizing, genesis_filtering: true }) - return - } - if( status.importing === undefined ) { - // programmer error - console.error('unknown status', status) - return - } + + var genesis_filter = new GenesisFilter + if( ! genesis_filter.isAvailable() ) { + update_state({ password_checksum, account_keys: unfiltered_account_keys, + genesis_filter_finished: true, genesis_filtering: false }) + return + } + genesis_filter.init(()=> { + var filter_status = this.state.genesis_filter_status - if( ! filter_status.length ) - // first account - filter_status.push( status ) - else { - var last_account_name = filter_status[filter_status.length - 1].account_name - if( last_account_name === status.account_name ) - // update same account - filter_status[filter_status.length - 1] = status - else - // new account - filter_status.push( status ) - } - update_state({ genesis_filter_status: filter_status }) + // FF < version 41 does not support worker threads internals (like blob urls) + // var GenesisFilterWorker = require("worker!workers/GenesisFilterWorker") + // var worker = new GenesisFilterWorker + // worker.postMessage({ + // account_keys: unfiltered_account_keys, + // bloom_filter: genesis_filter.bloom_filter + // }) + // worker.onmessage = event => { try { + // var { status, account_keys } = event.data + // // ... + // } catch( e ) { console.error('GenesisFilterWorker', e) }} - } catch( e ) { console.error('GenesisFilterWorker', e) }} + var account_keys = unfiltered_account_keys + genesis_filter.filter( account_keys, status => { + console.log("import filter", status) + if( status.error === "missing_public_keys" ) { + console.error("un-released format, just for testing") + update_state({ password_checksum, account_keys: unfiltered_account_keys, + genesis_filter_finished: true, genesis_filtering: false }) + return + } + if( status.success ) { + // var { account_keys } = event.data // if using worker thread + update_state({ password_checksum, account_keys, + genesis_filter_finished: true, genesis_filtering: false }) + return + } + if( status.initalizing !== undefined ) { + update_state({ genesis_filter_initalizing: status.initalizing, genesis_filtering: true }) + return + } + if( status.importing === undefined ) { + // programmer error + console.error('unknown status', status) + return + } + if( ! filter_status.length ) + // first account + filter_status.push( status ) + else { + var last_account_name = filter_status[filter_status.length - 1].account_name + if( last_account_name === status.account_name ) + // update same account + filter_status[filter_status.length - 1] = status + else + // new account + filter_status.push( status ) + } + update_state({ genesis_filter_status: filter_status }) + }) + }) } /** diff --git a/web/app/workers/GenesisFilterWorker.js b/web/app/workers/GenesisFilterWorker.js index cf395f7ff..b279e34bb 100644 --- a/web/app/workers/GenesisFilterWorker.js +++ b/web/app/workers/GenesisFilterWorker.js @@ -1,13 +1,11 @@ -var config = require( "chain/config" ) -var key_utils = require( "common/key_utils" ) var GenesisFilter = require( "chain/GenesisFilter" ) -var genesis_filter = new GenesisFilter onmessage = function(event) { try { console.log("GenesisFilterWorker start"); - var { account_keys } = event.data - filter( account_keys, status => { + var { account_keys, bloom_filter } = event.data + var genesis_filter = new GenesisFilter( bloom_filter ) + genesis_filter.filter( account_keys, status => { if( status.success ) { postMessage({ account_keys, status }) console.log("GenesisFilterWorker done") @@ -15,73 +13,4 @@ onmessage = function(event) { try { } postMessage({ status }) }) -} catch( e ) { console.error("GenesisFilterWorker", e) } } - -var filter = function( account_keys, status ) { - if( ! genesis_filter.isAvailable() ) { - console.log("WARN: Missing bloom filter for BTS 0.9.x wallets") - status({ error: "missing_bloom" }) - return - } - var initalizing = true - status({ initalizing }) - genesis_filter.init(()=> { - var previous_address_prefix = config.address_prefix - config.address_prefix = "BTS" - try { - initalizing = false - status({ initalizing }) - var running_count_progress = 1 - for(var a = 0; a < account_keys.length; a++) { - var removed_count = 0, count = 0 - var keys = account_keys[a] - var total = keys.encrypted_private_keys.length - status({ importing: true, account_name: keys.account_name, count, total }) - for(var k = keys.encrypted_private_keys.length - 1; k >= 0; k--) { - count++ - if( count % running_count_progress === 0 ) { - running_count_progress = 47 - status({ importing: true, account_name: keys.account_name, count, total }) - } - if( ! keys.public_keys) { - // un-released format, just for testing - status({ error: "missing_public_keys" }) - return - } - var key = keys.public_keys[k] - if( /^GPH/.test(key) ) key = "BTS" + key.substring(3) - if(genesis_filter.inGenesis( key )) continue - var addresses = key_utils.addresses(key) - var addy_found = false - for(var i = 0; i < addresses.length; i++) { - if(genesis_filter.inGenesis( addresses[i] )) { - addy_found = true - break - } - } - if( addy_found ) continue - delete keys.encrypted_private_keys[k] - delete keys.public_keys[k] - removed_count++ - } - var encrypted_private_keys = [], public_keys = [] - for(var k = keys.encrypted_private_keys.length - 1; k >= 0; k--) { - if( ! keys.encrypted_private_keys[k]) continue - encrypted_private_keys.push( keys.encrypted_private_keys[k] ) - public_keys.push( keys.public_keys[k] ) - } - keys.encrypted_private_keys = encrypted_private_keys - status({ importing: false, account_name: keys.account_name, - count: count - removed_count, total }) - keys.public_keys = public_keys - } - status({ success: true }) - } finally { - config.address_prefix = previous_address_prefix - if( initalizing ) { - initalizing = false - status({ initalizing }) - } - } - }) -} \ No newline at end of file +} catch( e ) { console.error("GenesisFilterWorker", e) } } \ No newline at end of file