Skip to content

Commit

Permalink
testNotifySubscriptionChanged stability
Browse files Browse the repository at this point in the history
  • Loading branch information
flypaper0 committed Oct 27, 2023
1 parent e74d770 commit 7fe66a2
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 51 deletions.
14 changes: 8 additions & 6 deletions Example/IntegrationTests/Push/NotifyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,22 @@ final class NotifyTests: XCTestCase {
let expectation = expectation(description: "expects client B to receive subscription after both clients are registered and client A creates one")
expectation.assertForOverFulfill = false

var subscription: NotifySubscription!

let clientB = makeWalletClient(prefix: "👐🏼 Wallet B: ")
clientB.subscriptionChangedPublisher.sink { subscriptions in
guard let subscription = subscriptions.first else { return }
Task(priority: .high) {
try await clientB.deleteSubscription(topic: subscription.topic)
expectation.fulfill()
}
clientB.subscriptionsPublisher.sink { subscriptions in
guard let newSubscription = subscriptions.first else { return }
subscription = newSubscription
expectation.fulfill()
}.store(in: &publishers)

try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign)
try! await clientB.register(account: account, domain: gmDappDomain, onSign: sign)
try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account)

wait(for: [expectation], timeout: InputConfig.defaultTimeout)

try await clientB.deleteSubscription(topic: subscription.topic)
}

func testWalletCreatesAndUpdatesSubscription() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,21 @@ final class NotifyWebDidResolver {
private static var subscribeKey = "wc-notify-subscribe-key"
private static var authenticationKey = "wc-notify-authentication-key"

func resolveAgreementKey(domain: String) async throws -> AgreementPublicKey {
let didDoc = try await resolveDidDoc(domainUrl: domain)
let subscribeKeyPath = "\(didDoc.id)#\(Self.subscribeKey)"
guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == subscribeKeyPath }) else { throw Errors.noVerificationMethodForKey }
guard verificationMethod.publicKeyJwk.crv == .X25519 else { throw Errors.unsupportedCurve}
let pubKeyBase64Url = verificationMethod.publicKeyJwk.x
return try AgreementPublicKey(base64url: pubKeyBase64Url)
func resolveDidDoc(appDomain: String) async throws -> WebDidDoc {
guard let didDocUrl = URL(string: "https://\(appDomain)/.well-known/did.json") else { throw Errors.invalidUrl }
let (data, _) = try await URLSession.shared.data(from: didDocUrl)
return try JSONDecoder().decode(WebDidDoc.self, from: data)
}

// TODO - Add cache for diddocs
func resolveAgreementKey(didDoc: WebDidDoc) throws -> AgreementPublicKey {
let keypath = "\(didDoc.id)#\(Self.subscribeKey)"
let pubKeyBase64Url = try resolveKey(didDoc: didDoc, curve: .X25519, keyPath: keypath)
return try AgreementPublicKey(base64url: pubKeyBase64Url)
}

func resolveAuthenticationKey(domain: String) async throws -> Data {
let didDoc = try await resolveDidDoc(domainUrl: domain)
let authenticationKeyPath = "\(didDoc.id)#\(Self.authenticationKey)"
guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == authenticationKeyPath }) else { throw Errors.noVerificationMethodForKey }
guard verificationMethod.publicKeyJwk.crv == .Ed25519 else { throw Errors.unsupportedCurve}
let pubKeyBase64Url = verificationMethod.publicKeyJwk.x
func resolveAuthenticationKey(didDoc: WebDidDoc) throws -> Data {
let keyPath = "\(didDoc.id)#\(Self.authenticationKey)"
let pubKeyBase64Url = try resolveKey(didDoc: didDoc, curve: .Ed25519, keyPath: keyPath)
guard let raw = Data(base64url: pubKeyBase64Url) else { throw Errors.invalidBase64urlString }
return raw
}
Expand All @@ -36,9 +34,9 @@ private extension NotifyWebDidResolver {
case unsupportedCurve
}

func resolveDidDoc(domainUrl: String) async throws -> WebDidDoc {
guard let didDocUrl = URL(string: "https://\(domainUrl)/.well-known/did.json") else { throw Errors.invalidUrl }
let (data, _) = try await URLSession.shared.data(from: didDocUrl)
return try JSONDecoder().decode(WebDidDoc.self, from: data)
func resolveKey(didDoc: WebDidDoc, curve: WebDidDoc.PublicKeyJwk.Curve, keyPath: String) throws -> String {
guard let verificationMethod = didDoc.verificationMethod.first(where: { verificationMethod in verificationMethod.id == keyPath }) else { throw Errors.noVerificationMethodForKey }
guard verificationMethod.publicKeyJwk.crv == curve else { throw Errors.unsupportedCurve }
return verificationMethod.publicKeyJwk.x
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,7 @@ class DeleteNotifySubscriptionRequester {
logger.debug("Subscription removed, topic: \(topic)")

kms.deleteSymmetricKey(for: topic)
}




}
}

private extension DeleteNotifySubscriptionRequester {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ class NotifySubscriptionsChangedRequestSubscriber {

let oldSubscriptions = notifyStorage.getSubscriptions(account: account)
let newSubscriptions = try await notifySubscriptionsBuilder.buildSubscriptions(jwtPayload.subscriptions)


subscriptionChangedSubject.send(newSubscriptions)

try Task.checkCancellation()

let subscriptions = oldSubscriptions.difference(from: newSubscriptions)

logger.debug("Received: \(newSubscriptions.count), changed: \(subscriptions.count)")

if subscriptions.count > 0 {
subscriptionChangedSubject.send(newSubscriptions)
notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account)

for subscription in newSubscriptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ class NotifyWatchSubscriptionsRequester: NotifyWatchSubscriptionsRequesting {

logger.debug("Watching subscriptions")

let notifyServerPublicKey = try await webDidResolver.resolveAgreementKey(domain: notifyHost)
let notifyServerAuthenticationKey = try await webDidResolver.resolveAuthenticationKey(domain: notifyHost)
let didDoc = try await webDidResolver.resolveDidDoc(appDomain: notifyHost)
let notifyServerPublicKey = try webDidResolver.resolveAgreementKey(didDoc: didDoc)
let notifyServerAuthenticationKey = try webDidResolver.resolveAuthenticationKey(didDoc: didDoc)

let notifyServerAuthenticationDidKey = DIDKey(rawData: notifyServerAuthenticationKey)
let watchSubscriptionsTopic = notifyServerPublicKey.rawRepresentation.sha256().toHexString()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,28 @@ class NotifyWatchSubscriptionsResponseSubscriber {

logger.debug("Received: \(newSubscriptions.count), changed: \(subscriptions.count)")

guard subscriptions.count > 0 else { return }
// TODO: unsubscribe for oldSubscriptions topics that are not included in new subscriptions
notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account)

for subscription in newSubscriptions {
let symKey = try SymmetricKey(hex: subscription.symKey)
try groupKeychainStorage.add(symKey, forKey: subscription.topic)
try kms.setSymmetricKey(symKey, for: subscription.topic)
}
if subscriptions.count > 0 {
// TODO: unsubscribe for oldSubscriptions topics that are not included in new subscriptions
notifyStorage.replaceAllSubscriptions(newSubscriptions, account: account)

try await networkingInteractor.batchSubscribe(topics: newSubscriptions.map { $0.topic })
for subscription in newSubscriptions {
let symKey = try SymmetricKey(hex: subscription.symKey)
try groupKeychainStorage.add(symKey, forKey: subscription.topic)
try kms.setSymmetricKey(symKey, for: subscription.topic)
}

try Task.checkCancellation()
try await networkingInteractor.batchSubscribe(topics: newSubscriptions.map { $0.topic })

var logProperties = [String: String]()
for (index, subscription) in newSubscriptions.enumerated() {
let key = "subscription_\(index + 1)"
logProperties[key] = subscription.topic
}
try Task.checkCancellation()

logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(newSubscriptions.count)", properties: logProperties)
var logProperties = [String: String]()
for (index, subscription) in newSubscriptions.enumerated() {
let key = "subscription_\(index + 1)"
logProperties[key] = subscription.topic
}

logger.debug("Updated Subscriptions with Watch Subscriptions Update, number of subscriptions: \(newSubscriptions.count)", properties: logProperties)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class NotifySubscribeRequester {

let config = await notifyConfigProvider.resolveNotifyConfig(appDomain: appDomain)

let peerPublicKey = try await webDidResolver.resolveAgreementKey(domain: appDomain)
let didDoc = try await webDidResolver.resolveDidDoc(appDomain: appDomain)
let peerPublicKey = try webDidResolver.resolveAgreementKey(didDoc: didDoc)
let subscribeTopic = peerPublicKey.rawRepresentation.sha256().toHexString()

let keysY = try generateAgreementKeys(peerPublicKey: peerPublicKey)
Expand Down

0 comments on commit 7fe66a2

Please sign in to comment.