Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sentry for error logging and information. #107

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@
"version" : "4.13.2"
}
},
{
"identity" : "sentry-cocoa",
"kind" : "remoteSourceControl",
"location" : "https://github.com/getsentry/sentry-cocoa",
"state" : {
"revision" : "5575af93efb776414f243e93d6af9f6258dc539a",
"version" : "8.36.0"
}
},
{
"identity" : "swift-crypto",
"kind" : "remoteSourceControl",
Expand Down
2 changes: 2 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ let package = Package(
.package(url: "https://github.com/torusresearch/fetch-node-details-swift", from: "6.0.3"),
// NB: jwt-kit may only be a dependency in tests or it will break cocoapod support
.package(url: "https://github.com/vapor/jwt-kit.git", from: "4.0.0"),
.package(url: "https://github.com/getsentry/sentry-cocoa", from: "8.36.0"),
],
targets: [
.target(
name: "TorusUtils",
dependencies: [
.product(name: "FetchNodeDetails", package: "fetch-node-details-swift"),
.product(name: "curveSecp256k1", package: "curvelib.swift"),
.product(name: "Sentry", package: "sentry-cocoa"),
]),
.testTarget(
name: "TorusUtilsTests",
Expand Down
4 changes: 3 additions & 1 deletion Sources/TorusUtils/Helpers/Common.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ internal func thresholdSame<T: Encodable>(arr: [T], threshold: Int) throws -> T?
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .sortedKeys
for (_, value) in arr.enumerated() {
guard let jsonString = String(data: try jsonEncoder.encode(value), encoding: .utf8) else { throw TorusUtilError.encodingFailed("thresholdSame")
guard let jsonString = String(data: try jsonEncoder.encode(value), encoding: .utf8) else {
SentryUtils.captureException("thresholdSame for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.encodingFailed("thresholdSame")
}
if let _ = hashmap[jsonString] {
hashmap[jsonString]! += 1
Expand Down
7 changes: 6 additions & 1 deletion Sources/TorusUtils/Helpers/KeyUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ enum TorusKeyType: String, Equatable, Hashable, Codable {

public class KeyUtils {
public static func keccak256Data(_ input: String) throws -> String {
guard let data = input.data(using: .utf8) else { throw TorusUtilError.invalidInput }
guard let data = input.data(using: .utf8) else {
SentryUtils.captureException("\(TorusUtilError.invalidInput) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidInput
}
return try keccak256(data: data).toHexString()
}

Expand Down Expand Up @@ -68,6 +71,7 @@ public class KeyUtils {
if (publicKeyUnprefixed.count <= 128) {
publicKeyUnprefixed = publicKeyUnprefixed.addLeading0sForLength128()
} else {
SentryUtils.captureException("\(TorusUtilError.invalidPubKeySize) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidPubKeySize
}

Expand Down Expand Up @@ -148,6 +152,7 @@ public class KeyUtils {

internal static func generateShares(keyType: TorusKeyType = .secp256k1, serverTimeOffset: Int, nodeIndexes: [BigUInt], nodePubKeys: [INodePub], privateKey: String) throws -> [ImportedShare] {
if keyType != TorusKeyType.secp256k1 {
SentryUtils.captureException("Unsupported key type for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("Unsupported key type")
}

Expand Down
4 changes: 4 additions & 0 deletions Sources/TorusUtils/Helpers/LangrangeInterpolatePoly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ internal class Lagrange {
let indexList: [BigInt] = nodeIndex.map({ BigInt($0) })

if sharesList.count != indexList.count {
SentryUtils.captureException("sharesList not equal to indexList length in lagrangeInterpolation for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("sharesList not equal to indexList length in lagrangeInterpolation")
}

Expand All @@ -112,6 +113,7 @@ internal class Lagrange {
guard
let inv = lower.inverse(KeyUtils.getOrderOfCurve())
else {
SentryUtils.captureException("\(TorusUtilError.decryptionFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.decryptionFailed
}
var delta = (upper * inv).modulus(KeyUtils.getOrderOfCurve())
Expand All @@ -121,13 +123,15 @@ internal class Lagrange {
}

if secret == BigUInt(0) {
SentryUtils.captureException("\(TorusUtilError.interpolationFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.interpolationFailed
}

let secretString = secret.serialize().hexString.addLeading0sForLength64()
if sharesDecrypt == sharesList.count {
return secretString
} else {
SentryUtils.captureException("\(TorusUtilError.interpolationFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.interpolationFailed
}
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/TorusUtils/Helpers/MetadataUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ internal class MetadataUtils {
guard
let url = URL(string: url)
else {
SentryUtils.captureException("Invalid Url \(url) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("Invalid Url \(url)")
}
var rq = URLRequest(url: url)
Expand Down Expand Up @@ -103,6 +104,7 @@ internal class MetadataUtils {
if case .sapphire = network {
return try await getOrSetNonce(legacyMetadataHost: metadataHost, serverTimeOffset: serverTimeOffset ?? Int(trunc(Double(0 + Int(Date().timeIntervalSince1970)))), X: X, Y: Y, privateKey: privateKey, getOnly: getOnly, keyType: keyType)
} else {
SentryUtils.captureException("\(TorusUtilError.metadataNonceMissing) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.metadataNonceMissing
}
}
Expand Down
18 changes: 17 additions & 1 deletion Sources/TorusUtils/Helpers/NodeUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ internal class NodeUtils {
var importedShareCount = 0
if importedShares != nil && importedShares!.count > 0 {
if importedShares!.count != endpoints.count {
SentryUtils.captureException("\(TorusUtilError.importShareFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.importShareFailed
}
isImportShareReq = true
Expand Down Expand Up @@ -214,6 +215,7 @@ internal class NodeUtils {
}

if importedShareCount > 0 && !(nodeSigs.count == endpoints.count) {
SentryUtils.captureException("\(TorusUtilError.commitmentRequestFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.commitmentRequestFailed
}

Expand Down Expand Up @@ -286,6 +288,7 @@ internal class NodeUtils {
}

if isImportShareReq && !shareImportSuccess {
SentryUtils.captureException("\(TorusUtilError.importShareFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.importShareFailed
}

Expand Down Expand Up @@ -364,6 +367,7 @@ internal class NodeUtils {
}

if thresholdPublicKey == nil {
SentryUtils.captureException("\(TorusUtilError.retrieveOrImportShareError) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.retrieveOrImportShareError
}

Expand Down Expand Up @@ -395,6 +399,7 @@ internal class NodeUtils {

// Invert comparision to return error early
if !(shareResponses.count >= thresholdReqCount && thresholdPublicKey != nil && (thresholdNonceData != nil || verifierParams.extended_verifier_id != nil || TorusUtils.isLegacyNetworkRouteMap(network: network))) {
SentryUtils.captureException("\(TorusUtilError.retrieveOrImportShareError) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.retrieveOrImportShareError
}

Expand Down Expand Up @@ -434,9 +439,11 @@ internal class NodeUtils {
let latestKey = item.keys[0]
nodeIndexes.append(latestKey.nodeIndex)
guard let cipherData = Data(base64Encoded: latestKey.share) else {
SentryUtils.captureException("cipher is not base64 encoded for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.decodingFailed("cipher is not base64 encoded")
}
guard let cipherTextHex = String(data: cipherData, encoding: .utf8) else {
SentryUtils.captureException("cipher is not base64 encoded for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.decodingFailed("cipherData is not utf8")
}
let decrypted = try MetadataUtils.decryptNodeData(eciesData: latestKey.shareMetadata, ciphertextHex: cipherTextHex, privKey: sessionAuthKeySerialized)
Expand All @@ -450,12 +457,14 @@ internal class NodeUtils {
let validSigs = sessionTokenSigs.filter({ $0 != nil }).map({ $0! })

if verifierParams.extended_verifier_id == nil && validSigs.count < threshold {
SentryUtils.captureException("\(TorusUtilError.retrieveOrImportShareError) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.retrieveOrImportShareError
}

let validTokens = sessionTokens.filter({ $0 != nil }).map({ $0! })

if verifierParams.extended_verifier_id == nil && validTokens.count < threshold {
SentryUtils.captureException("Insufficient number of signatures from nodes for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("Insufficient number of signatures from nodes")
}

Expand Down Expand Up @@ -503,6 +512,7 @@ internal class NodeUtils {
}

if privateKey == nil {
SentryUtils.captureException("\(TorusUtilError.privateKeyDeriveFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.privateKeyDeriveFailed
}

Expand Down Expand Up @@ -555,11 +565,13 @@ internal class NodeUtils {
finalPubKey = try KeyUtils.combinePublicKeys(keys: [oAuthPubKey, publicNonce])
pubNonce = PubNonce(x: thresholdNonceData!.pubNonce!.x, y: thresholdNonceData!.pubNonce!.y)
} else {
SentryUtils.captureException("\(TorusUtilError.pubNonceMissing) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.pubNonceMissing
}
}

if finalPubKey == nil {
SentryUtils.captureException("\(TorusUtilError.retrieveOrImportShareError) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.retrieveOrImportShareError
}

Expand All @@ -577,8 +589,10 @@ internal class NodeUtils {
// This is a sanity check to make doubly sure we are returning the correct private key after importing a share
if isImportShareReq {
if newPrivateKey == nil {
SentryUtils.captureException("\(TorusUtilError.importShareFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.importShareFailed
} else if (!(finalPrivKey == newPrivateKey!.addLeading0sForLength64())) {
SentryUtils.captureException("\(TorusUtilError.importShareFailed) for client id: \(TorusUtils.getClientId())")
grvgoel81 marked this conversation as resolved.
Show resolved Hide resolved
throw TorusUtilError.importShareFailed
}
}
Expand All @@ -587,7 +601,9 @@ internal class NodeUtils {
if typeOfUser == .v2 {
isUpgraded = metadataNonce == BigInt(0)
}


SentryUtils.logInformation(clientId: TorusUtils.getClientId(), finalEvmAddress: finalEvmAddress, platform: "torus-utils-swift")

return TorusKey(
finalKeyData: TorusKey.FinalKeyData(
evmAddress: finalEvmAddress,
Expand Down
2 changes: 2 additions & 0 deletions Sources/TorusUtils/Point.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ internal struct Point: Codable {
if let xCoord = BigInt(x, radix: 16) {
self.x = xCoord
} else {
SentryUtils.captureException("\(TorusUtilError.invalidInput) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidInput
}

if let yCoord = BigInt(y, radix: 16) {
self.y = yCoord
} else {
SentryUtils.captureException("\(TorusUtilError.invalidInput) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidInput
}
}
Expand Down
2 changes: 2 additions & 0 deletions Sources/TorusUtils/Share.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ internal class Share: Codable {
if let si = BigInt(shareIndex, radix: 16) {
self.shareIndex = si
} else {
SentryUtils.captureException("\(TorusUtilError.invalidInput) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidInput
}

if let s = BigInt(share, radix: 16) {
self.share = s
} else {
SentryUtils.captureException("\(TorusUtilError.invalidInput) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidInput
}
}
Expand Down
19 changes: 19 additions & 0 deletions Sources/TorusUtils/TorusUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BigInt
import FetchNodeDetails
import Foundation
import OSLog
import Sentry
#if canImport(curveSecp256k1)
import curveSecp256k1
#endif
Expand All @@ -26,6 +27,8 @@ public class TorusUtils {
var legacyMetadataHost: String

var apiKey: String = "torus-default"

public static var clientId: String = ""

/// Initializes TorusUtils with the provided options
///
Expand All @@ -37,6 +40,8 @@ public class TorusUtils {
///
/// - Throws: `TorusUtilError.invalidInput`
public init(params: TorusOptions, loglevel: OSLogType = .default) throws {
SentryUtils.initSentry()
TorusUtils.clientId = params.clientId
var defaultHost = ""
if params.legacyMetadataHost == nil {
if case let .legacy(urlHost) = params.network {
Expand All @@ -50,6 +55,7 @@ public class TorusUtils {
defaultHost = "https://node-1.dev-node.web3auth.io/metadata"
}
} else {
SentryUtils.captureException("\(TorusUtilError.invalidInput) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.invalidInput
}
}
Expand All @@ -73,6 +79,10 @@ public class TorusUtils {
}
return false
}

public static func getClientId() -> String {
return clientId
}

/// Sets the apiKey
///
Expand Down Expand Up @@ -176,6 +186,7 @@ public class TorusUtils {
) async throws -> TorusKey {
let nodePubs = TorusNodePubModelToINodePub(nodes: nodePubKeys)
if endpoints.count != nodeIndexes.count {
SentryUtils.captureException("Length of endpoints must be the same as length of nodeIndexes for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("Length of endpoints must be the same as length of nodeIndexes")
}

Expand Down Expand Up @@ -214,17 +225,21 @@ public class TorusUtils {
if keyAssignResult.errorResult != nil {
let error = keyAssignResult.errorResult!.message
if error.lowercased().contains("verifier not supported") {
SentryUtils.captureException("Verifier not supported. Check if you: 1. Are on the right network (Torus testnet/mainnet) 2. Have setup a verifier on dashboard.web3auth.io? for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("Verifier not supported. Check if you: 1. Are on the right network (Torus testnet/mainnet) 2. Have setup a verifier on dashboard.web3auth.io?")
} else {
SentryUtils.captureException(error)
throw TorusUtilError.runtime(error)
}
}

if keyAssignResult.keyResult == nil || keyAssignResult.keyResult?.keys.count == 0 {
SentryUtils.captureException("node results do not match at final lookup for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("node results do not match at final lookup")
}

if keyAssignResult.nonceResult == nil && extendedVerifierId == nil && !TorusUtils.isLegacyNetworkRouteMap(network: network) {
SentryUtils.captureException("metadata nonce is missing in share response for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.runtime("metadata nonce is missing in share response")
}

Expand Down Expand Up @@ -257,11 +272,13 @@ public class TorusUtils {
finalPubKey = try KeyUtils.combinePublicKeys(keys: [oAuthPubKey!, pubNonceKey])
pubNonce = pubNonceResult
} else {
SentryUtils.captureException("\(TorusUtilError.pubNonceMissing) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.pubNonceMissing
}
}

if oAuthPubKey == nil || finalPubKey == nil {
SentryUtils.captureException("\(TorusUtilError.privateKeyDeriveFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.privateKeyDeriveFailed
}

Expand Down Expand Up @@ -329,6 +346,7 @@ public class TorusUtils {
finalPubKey = try KeyUtils.combinePublicKeys(keys: [oAuthPubKey, pubNonceKey])
pubNonce = nonceResult!.pubNonce!
} else {
SentryUtils.captureException("\(TorusUtilError.metadataNonceMissing) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.metadataNonceMissing
}
} else {
Expand All @@ -346,6 +364,7 @@ public class TorusUtils {
let oAuthAddress = try KeyUtils.generateAddressFromPubKey(publicKeyX: X, publicKeyY: Y)

if typeOfUser == .v2 && finalPubKey == nil {
SentryUtils.captureException("\(TorusUtilError.privateKeyDeriveFailed) for client id: \(TorusUtils.getClientId())")
throw TorusUtilError.privateKeyDeriveFailed
}

Expand Down
Loading