Skip to content

Commit

Permalink
Run import keys genesis filter as non-worker (fixes FF < v41, breaks …
Browse files Browse the repository at this point in the history
…UI % complete reporting) #319
  • Loading branch information
James Calfee committed Oct 29, 2015
1 parent 085c300 commit 6ff8353
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 116 deletions.
79 changes: 79 additions & 0 deletions 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 {
Expand All @@ -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 }

Expand All @@ -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
Expand Down Expand Up @@ -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 })
}
}
})
}

}
102 changes: 61 additions & 41 deletions web/app/components/Wallet/ImportKeys.jsx
Expand Up @@ -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
Expand Down Expand Up @@ -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 })
})
})
}

/**
Expand Down
79 changes: 4 additions & 75 deletions web/app/workers/GenesisFilterWorker.js
@@ -1,87 +1,16 @@

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")
return
}
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 })
}
}
})
}
} catch( e ) { console.error("GenesisFilterWorker", e) } }

0 comments on commit 6ff8353

Please sign in to comment.