[#1106] Zashi-iOS audit Issue G

- storedWallet is no longer held in memory
- unit tests fixed
This commit is contained in:
Lukas Korba 2024-03-06 16:12:23 +01:00
parent 6970b6ff60
commit b5a71c7bed
5 changed files with 36 additions and 56 deletions

View File

@ -240,15 +240,8 @@ extension RootReducer {
/// When initialization succeeds user is taken to the home screen.
case .initialization(.initializeSDK(let walletMode)):
do {
state.storedWallet = try walletStorage.exportWallet()
guard let storedWallet = state.storedWallet else {
state.appInitializationState = .failed
state.alert = AlertState.cantLoadSeedPhrase()
return .none
}
let birthday = state.storedWallet?.birthday?.value() ?? zcashSDKEnvironment.latestCheckpoint
let storedWallet = try walletStorage.exportWallet()
let birthday = storedWallet.birthday?.value() ?? zcashSDKEnvironment.latestCheckpoint
try mnemonic.isValid(storedWallet.seedPhrase.value())
let seedBytes = try mnemonic.toSeed(storedWallet.seedPhrase.value())
@ -273,35 +266,34 @@ extension RootReducer {
return .send(.initialization(.registerForSynchronizersUpdate))
case .initialization(.checkBackupPhraseValidation):
guard let storedWallet = state.storedWallet else {
state.appInitializationState = .failed
state.alert = AlertState.cantLoadSeedPhrase()
return .none
}
var landingDestination = RootReducer.DestinationState.Destination.tabs
if !storedWallet.hasUserPassedPhraseBackupTest {
let phraseWords = mnemonic.asWords(storedWallet.seedPhrase.value())
do {
let storedWallet = try walletStorage.exportWallet()
var landingDestination = RootReducer.DestinationState.Destination.tabs
let recoveryPhrase = RecoveryPhrase(words: phraseWords.map { $0.redacted })
state.phraseDisplayState.phrase = recoveryPhrase
state.phraseDisplayState.birthday = storedWallet.birthday
if let value = storedWallet.birthday?.value() {
let latestBlock = numberFormatter.string(NSDecimalNumber(value: value))
state.phraseDisplayState.birthdayValue = "\(String(describing: latestBlock ?? ""))"
if !storedWallet.hasUserPassedPhraseBackupTest {
let phraseWords = mnemonic.asWords(storedWallet.seedPhrase.value())
let recoveryPhrase = RecoveryPhrase(words: phraseWords.map { $0.redacted })
state.phraseDisplayState.phrase = recoveryPhrase
state.phraseDisplayState.birthday = storedWallet.birthday
if let value = storedWallet.birthday?.value() {
let latestBlock = numberFormatter.string(NSDecimalNumber(value: value))
state.phraseDisplayState.birthdayValue = "\(String(describing: latestBlock ?? ""))"
}
landingDestination = .phraseDisplay
}
landingDestination = .phraseDisplay
state.appInitializationState = .initialized
return .run { [landingDestination] send in
try await mainQueue.sleep(for: .seconds(2.5))
await send(.destination(.updateDestination(landingDestination)))
}
.cancellable(id: CancelId.timer, cancelInFlight: true)
} catch {
return Effect.send(.initialization(.initializationFailed(error.toZcashError())))
}
state.appInitializationState = .initialized
return .run { [landingDestination] send in
try await mainQueue.sleep(for: .seconds(2.5))
await send(.destination(.updateDestination(landingDestination)))
}
.cancellable(id: CancelId.timer, cancelInFlight: true)
case .initialization(.nukeWalletRequest):
state.alert = AlertState.wipeRequest()
return .none

View File

@ -46,7 +46,6 @@ public struct RootReducer: Reducer {
public var phraseDisplayState: RecoveryPhraseDisplay.State
public var sandboxState: SandboxReducer.State
public var splashAppeared = false
public var storedWallet: StoredWallet?
public var tabsState: TabsReducer.State
public var walletConfig: WalletConfig
public var welcomeState: WelcomeReducer.State
@ -62,7 +61,6 @@ public struct RootReducer: Reducer {
onboardingState: OnboardingFlowReducer.State,
phraseDisplayState: RecoveryPhraseDisplay.State,
sandboxState: SandboxReducer.State,
storedWallet: StoredWallet? = nil,
tabsState: TabsReducer.State,
walletConfig: WalletConfig,
welcomeState: WelcomeReducer.State
@ -77,7 +75,6 @@ public struct RootReducer: Reducer {
self.onboardingState = onboardingState
self.phraseDisplayState = phraseDisplayState
self.sandboxState = sandboxState
self.storedWallet = storedWallet
self.tabsState = tabsState
self.walletConfig = walletConfig
self.welcomeState = welcomeState

View File

@ -75,9 +75,7 @@ class AppInitializationTests: XCTestCase {
await testQueue.advance(by: 3.00)
await store.receive(.initialization(.initializeSDK(.existingWallet))) { state in
state.storedWallet = storedWallet
}
await store.receive(.initialization(.initializeSDK(.existingWallet)))
await store.receive(.initialization(.checkBackupPhraseValidation)) { state in
state.appInitializationState = .initialized
@ -151,9 +149,7 @@ class AppInitializationTests: XCTestCase {
await testQueue.advance(by: 3.00)
await store.receive(.initialization(.initializeSDK(.existingWallet))) { state in
state.storedWallet = storedWallet
}
await store.receive(.initialization(.initializeSDK(.existingWallet)))
let recoveryPhrase = RecoveryPhrase(words: try store.dependencies.mnemonic.randomMnemonicWords().map { $0.redacted })

View File

@ -35,9 +35,7 @@ final class RestoreWalletTests: XCTestCase {
state.isRestoringWallet = true
}
await store.receive(.initialization(.initializeSDK(.restoreWallet))) { state in
state.storedWallet = .placeholder
}
await store.receive(.initialization(.initializeSDK(.restoreWallet)))
await store.receive(.initialization(.initializationSuccessfullyDone(nil)))

View File

@ -165,11 +165,9 @@ class RootTests: XCTestCase {
state.alert = AlertState.initializationFailed(zcashError)
}
await store.receive(.initialization(.checkBackupPhraseValidation)) { state in
// failed is expected because environment is throwing errors
state.appInitializationState = .failed
state.alert = AlertState.cantLoadSeedPhrase()
}
await store.receive(.initialization(.checkBackupPhraseValidation))
await store.receive(.initialization(.initializationFailed(zcashError)))
await store.finish()
}
@ -191,16 +189,15 @@ class RootTests: XCTestCase {
await store.receive(.initialization(.initializeSDK(.existingWallet)))
await store.receive(.initialization(.checkBackupPhraseValidation)) { state in
// failed is expected because environment is throwing errors
state.appInitializationState = .failed
state.alert = AlertState.cantLoadSeedPhrase()
}
await store.receive(.initialization(.checkBackupPhraseValidation))
await store.receive(.initialization(.initializationFailed(zcashError))) { state in
state.appInitializationState = .failed
state.alert = AlertState.initializationFailed(zcashError)
}
await store.receive(.initialization(.initializationFailed(zcashError)))
await store.finish()
}