Merge pull request #537 from LukasKorba/487_shieldFunds_to_async_await

[#487] shieldFunds to async/await
This commit is contained in:
Francisco Gindre 2022-09-23 12:08:07 -07:00 committed by GitHub
commit c834b13f29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 94 additions and 99 deletions

View File

@ -46,25 +46,17 @@ class GetUTXOsViewController: UIViewController {
KRProgressHUD.showMessage("🛡 Shielding 🛡") KRProgressHUD.showMessage("🛡 Shielding 🛡")
AppDelegate.shared.sharedSynchronizer.shieldFunds( Task { @MainActor in
spendingKey: spendingKey, let transaction = try await AppDelegate.shared.sharedSynchronizer.shieldFunds(
transparentSecretKey: transparentSecretKey, spendingKey: spendingKey,
memo: "shielding is fun!", transparentSecretKey: transparentSecretKey,
from: 0, memo: "shielding is fun!",
resultBlock: { result in from: 0)
DispatchQueue.main.async { KRProgressHUD.dismiss()
KRProgressHUD.dismiss() self.messageLabel.text = "funds shielded \(transaction)"
switch result { }
case .success(let transaction):
self.messageLabel.text = "funds shielded \(transaction)"
case .failure(let error):
self.messageLabel.text = "Shielding failed: \(error)"
}
}
}
)
} catch { } catch {
self.messageLabel.text = "Error \(error)" self.messageLabel.text = "Shielding failed \(error)"
} }
} }
} }

View File

@ -142,7 +142,7 @@ public protocol Synchronizer {
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void
) )
/// Sends zatoshi. /// Shields zatoshi.
/// - Parameter spendingKey: the key that allows spends to occur. /// - Parameter spendingKey: the key that allows spends to occur.
/// - Parameter transparentSecretKey: the key that allows to spend transaprent funds /// - Parameter transparentSecretKey: the key that allows to spend transaprent funds
/// - Parameter memo: the optional memo to include as part of the transaction. /// - Parameter memo: the optional memo to include as part of the transaction.
@ -151,9 +151,8 @@ public protocol Synchronizer {
spendingKey: String, spendingKey: String,
transparentSecretKey: String, transparentSecretKey: String,
memo: String?, memo: String?,
from accountIndex: Int, from accountIndex: Int
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void ) async throws -> PendingTransactionEntity
)
/// Attempts to cancel a transaction that is about to be sent. Typically, cancellation is only /// Attempts to cancel a transaction that is about to be sent. Typically, cancellation is only
/// an option if the transaction has not yet been submitted to the server. /// an option if the transaction has not yet been submitted to the server.

View File

@ -507,9 +507,8 @@ public class SDKSynchronizer: Synchronizer {
spendingKey: String, spendingKey: String,
transparentSecretKey: String, transparentSecretKey: String,
memo: String?, memo: String?,
from accountIndex: Int, from accountIndex: Int
resultBlock: @escaping (Result<PendingTransactionEntity, Error>) -> Void ) async throws -> PendingTransactionEntity {
) {
// let's see if there are funds to shield // let's see if there are funds to shield
let derivationTool = DerivationTool(networkType: self.network.networkType) let derivationTool = DerivationTool(networkType: self.network.networkType)
@ -519,32 +518,22 @@ public class SDKSynchronizer: Synchronizer {
// Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet. // Verify that at least there are funds for the fee. Ideally this logic will be improved by the shielding wallet.
guard tBalance.verified >= self.network.constants.defaultFee(for: self.latestScannedHeight) else { guard tBalance.verified >= self.network.constants.defaultFee(for: self.latestScannedHeight) else {
resultBlock(.failure(ShieldFundsError.insuficientTransparentFunds)) throw ShieldFundsError.insuficientTransparentFunds
return
} }
let viewingKey = try derivationTool.deriveViewingKey(spendingKey: spendingKey) let viewingKey = try derivationTool.deriveViewingKey(spendingKey: spendingKey)
let zAddr = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey) let zAddr = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey)
let shieldingSpend = try transactionManager.initSpend(zatoshi: tBalance.verified, toAddress: zAddr, memo: memo, from: 0) let shieldingSpend = try transactionManager.initSpend(zatoshi: tBalance.verified, toAddress: zAddr, memo: memo, from: 0)
// TODO: Task will be removed when this method is changed to async, issue 487, https://github.com/zcash/ZcashLightClientKit/issues/487 let transaction = try await transactionManager.encodeShieldingTransaction(
Task { spendingKey: spendingKey,
do { tsk: transparentSecretKey,
let transaction = try await transactionManager.encodeShieldingTransaction( pendingTransaction: shieldingSpend
spendingKey: spendingKey, )
tsk: transparentSecretKey,
pendingTransaction: shieldingSpend return try await transactionManager.submit(pendingTransaction: transaction)
)
let submittedTx = try await transactionManager.submit(pendingTransaction: transaction)
resultBlock(.success(submittedTx))
} catch {
resultBlock(.failure(error))
}
}
} catch { } catch {
resultBlock(.failure(error)) throw error
return
} }
} }

View File

@ -9,6 +9,7 @@
import XCTest import XCTest
@testable import TestUtils @testable import TestUtils
@testable import ZcashLightClientKit @testable import ZcashLightClientKit
class ShieldFundsTests: XCTestCase { class ShieldFundsTests: XCTestCase {
// TODO: Parameterize this from environment? // TODO: Parameterize this from environment?
// swiftlint:disable:next line_length // swiftlint:disable:next line_length
@ -82,7 +83,7 @@ class ShieldFundsTests: XCTestCase {
/// 15. sync up to the new chain tip /// 15. sync up to the new chain tip
/// verify that the shielded transactions are confirmed /// verify that the shielded transactions are confirmed
/// ///
func testShieldFunds() throws { func testShieldFunds() async throws {
// 1. load the dataset // 1. load the dataset
try coordinator.service.useDataset(from: "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/shielding-dataset/shield-funds/1631000.txt") try coordinator.service.useDataset(from: "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/shielding-dataset/shield-funds/1631000.txt")
@ -110,15 +111,19 @@ class ShieldFundsTests: XCTestCase {
let preTxExpectation = XCTestExpectation(description: "pre receive") let preTxExpectation = XCTestExpectation(description: "pre receive")
// 3. sync up to that height // 3. sync up to that height
try coordinator.sync( try await withCheckedThrowingContinuation { continuation in
completion: { synchro in do {
initialVerifiedBalance = synchro.initializer.getVerifiedBalance() try coordinator.sync(completion: { synchronizer in
initialTotalBalance = synchro.initializer.getBalance() initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
preTxExpectation.fulfill() initialTotalBalance = synchronizer.initializer.getBalance()
shouldContinue = true preTxExpectation.fulfill()
}, shouldContinue = true
error: self.handleError continuation.resume()
) }, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [preTxExpectation], timeout: 10) wait(for: [preTxExpectation], timeout: 10)
@ -149,14 +154,17 @@ class ShieldFundsTests: XCTestCase {
shouldContinue = false shouldContinue = false
// 6. Sync and find the UXTO on chain. // 6. Sync and find the UXTO on chain.
try coordinator.sync( try await withCheckedThrowingContinuation { continuation in
completion: { synchro in do {
tFundsDetectionExpectation.fulfill() try coordinator.sync(completion: { synchronizer in
shouldContinue = true shouldContinue = true
}, tFundsDetectionExpectation.fulfill()
error: self.handleError continuation.resume()
) }, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [tFundsDetectionExpectation], timeout: 2) wait(for: [tFundsDetectionExpectation], timeout: 2)
// at this point the balance should be zero for shielded, then zero verified transparent funds // at this point the balance should be zero for shielded, then zero verified transparent funds
@ -176,13 +184,17 @@ class ShieldFundsTests: XCTestCase {
sleep(2) sleep(2)
// 8. sync up to chain tip. // 8. sync up to chain tip.
try coordinator.sync( try await withCheckedThrowingContinuation { continuation in
completion: { synchro in do {
tFundsConfirmationSyncExpectation.fulfill() try coordinator.sync(completion: { synchronizer in
shouldContinue = true shouldContinue = true
}, tFundsConfirmationSyncExpectation.fulfill()
error: self.handleError continuation.resume()
) }, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [tFundsConfirmationSyncExpectation], timeout: 5) wait(for: [tFundsConfirmationSyncExpectation], timeout: 5)
@ -209,22 +221,18 @@ class ShieldFundsTests: XCTestCase {
var shieldingPendingTx: PendingTransactionEntity? var shieldingPendingTx: PendingTransactionEntity?
// shield the funds // shield the funds
coordinator.synchronizer.shieldFunds( do {
spendingKey: coordinator.spendingKey, let pendingTx = try await coordinator.synchronizer.shieldFunds(
transparentSecretKey: transparentSecretKey, spendingKey: coordinator.spendingKey,
memo: "shield funds", transparentSecretKey: transparentSecretKey,
from: 0 memo: "shield funds",
) { result in from: 0)
switch result { shouldContinue = true
case .failure(let error): XCTAssertEqual(pendingTx.value, Zatoshi(10000))
XCTFail("Failed With error: \(error.localizedDescription)") shieldingPendingTx = pendingTx
case .success(let pendingTx):
shouldContinue = true
XCTAssertEqual(pendingTx.value, Zatoshi(10000))
shieldingPendingTx = pendingTx
}
shieldFundsExpectation.fulfill() shieldFundsExpectation.fulfill()
} catch {
XCTFail("Failed With error: \(error.localizedDescription)")
} }
wait(for: [shieldFundsExpectation], timeout: 30) wait(for: [shieldFundsExpectation], timeout: 30)
@ -264,14 +272,17 @@ class ShieldFundsTests: XCTestCase {
// 13. sync up to chain tip // 13. sync up to chain tip
let postShieldSyncExpectation = XCTestExpectation(description: "sync Post shield") let postShieldSyncExpectation = XCTestExpectation(description: "sync Post shield")
shouldContinue = false shouldContinue = false
try coordinator.sync( try await withCheckedThrowingContinuation { continuation in
completion: { synchro in do {
postShieldSyncExpectation.fulfill() try coordinator.sync(completion: { synchronizer in
shouldContinue = true shouldContinue = true
}, postShieldSyncExpectation.fulfill()
error: self.handleError continuation.resume()
) }, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [postShieldSyncExpectation], timeout: 3) wait(for: [postShieldSyncExpectation], timeout: 3)
guard shouldContinue else { return } guard shouldContinue else { return }
@ -294,13 +305,17 @@ class ShieldFundsTests: XCTestCase {
shouldContinue = false shouldContinue = false
// 15. sync up to the new chain tip // 15. sync up to the new chain tip
try coordinator.sync( try await withCheckedThrowingContinuation { continuation in
completion: { synchro in do {
confirmationExpectation.fulfill() try coordinator.sync(completion: { synchronizer in
shouldContinue = true shouldContinue = true
}, confirmationExpectation.fulfill()
error: self.handleError continuation.resume()
) }, error: self.handleError)
} catch {
continuation.resume(throwing: error)
}
}
wait(for: [confirmationExpectation], timeout: 5) wait(for: [confirmationExpectation], timeout: 5)