diff --git a/web3swift/Convenience/Classes/LibSecp256k1Extension.swift b/web3swift/Convenience/Classes/LibSecp256k1Extension.swift index 2ce1c99..dbd8919 100644 --- a/web3swift/Convenience/Classes/LibSecp256k1Extension.swift +++ b/web3swift/Convenience/Classes/LibSecp256k1Extension.swift @@ -53,44 +53,44 @@ extension SECP256K1 { static func combineSerializedPublicKeys(keys: [Data], outputCompressed: Bool = false) -> Data? { let numToCombine = keys.count guard numToCombine >= 1 else { return nil} - var publicKeys = [UnsafePointer?]() - var result:Int32 - for i in 0..() + let arrayOfPointers = UnsafeMutablePointer< UnsafePointer? >.allocate(capacity: numToCombine) + defer { + arrayOfPointers.deinitialize(count: numToCombine) + arrayOfPointers.deallocate() + } + for i in 0 ..< numToCombine { let key = keys[i] - let keyLen = key.count - result = key.withUnsafeBytes { (publicKeyPointer:UnsafePointer) -> Int32 in - let res = secp256k1_ec_pubkey_parse(context!, UnsafeMutablePointer(&publicKey), publicKeyPointer, keyLen) - return res - } - if result == 0 { - return nil + guard let pubkey = SECP256K1.parsePublicKey(serializedKey: key) else {return nil} + storage.append(pubkey) + } + for i in 0 ..< numToCombine { + withUnsafePointer(to: &storage[i]) { (ptr) -> Void in + arrayOfPointers.advanced(by: i).pointee = ptr } - let pointer = UnsafePointer(UnsafeMutablePointer(&publicKey)) - publicKeys.append(pointer) } - + let immutablePointer = UnsafePointer(arrayOfPointers) var publicKey: secp256k1_pubkey = secp256k1_pubkey() - let arrayPointer = UnsafePointer(publicKeys) - result = secp256k1_ec_pubkey_combine(context!, UnsafeMutablePointer(&publicKey), arrayPointer, numToCombine) + +// let bufferPointer = UnsafeBufferPointer(start: immutablePointer, count: numToCombine) +// for (index, value) in bufferPointer.enumerated() { +// print("pointer value \(index): \(value!)") +// let val = value?.pointee +// print("value \(index): \(val!)") +// } +// + let result = withUnsafeMutablePointer(to: &publicKey) { (pubKeyPtr: UnsafeMutablePointer) -> Int32 in + let res = secp256k1_ec_pubkey_combine(context!, pubKeyPtr, immutablePointer, numToCombine) + return res + } if result == 0 { return nil } - - var keyLength = outputCompressed ? 33 : 65 - var serializedPubkey = Data(repeating: 0x00, count: keyLength) - - result = serializedPubkey.withUnsafeMutableBytes { (serializedPubkeyPointer:UnsafeMutablePointer) -> Int32 in - let res = secp256k1_ec_pubkey_serialize(context!, - serializedPubkeyPointer, - UnsafeMutablePointer(&keyLength), - UnsafeMutablePointer(&publicKey), - UInt32(outputCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)) - return res - } - return Data(serializedPubkey) + let serializedKey = SECP256K1.serializePublicKey(publicKey: &publicKey, compressed: outputCompressed) + return serializedKey } + static func recoverPublicKey(hash: Data, recoverableSignature: inout secp256k1_ecdsa_recoverable_signature) -> secp256k1_pubkey? { guard hash.count == 32 else {return nil} var publicKey: secp256k1_pubkey = secp256k1_pubkey() diff --git a/web3swiftTests/web3swiftTests.swift b/web3swiftTests/web3swiftTests.swift index 0251224..0652d25 100644 --- a/web3swiftTests/web3swiftTests.swift +++ b/web3swiftTests/web3swiftTests.swift @@ -88,6 +88,15 @@ class web3swiftTests: XCTestCase { XCTAssert(first4bits == 0x0f) } + func testCombiningPublicKeys() { + let priv1 = Data.randomBytes(length: 32)! + let pub1 = Web3.Utils.privateToPublic(priv1, compressed: true)! + let priv2 = Data.randomBytes(length: 32)! + let pub2 = Web3.Utils.privateToPublic(priv2, compressed: true)! + let combined = SECP256K1.combineSerializedPublicKeys(keys: [pub1, pub2], outputCompressed: true) + XCTAssert(combined != nil) + } + func testBIP39 () { var entropy = Data.fromHex("00000000000000000000000000000000")! var phrase = BIP39.generateMnemonicsFromEntropy(entropy: entropy) @@ -1991,6 +2000,26 @@ class web3swiftTests: XCTestCase { } } + func testPersonalSignature() { + let web3 = Web3.InfuraRinkebyWeb3() + let tempKeystore = try! EthereumKeystoreV3(password: "") + let keystoreManager = KeystoreManager([tempKeystore!]) + web3.addKeystoreManager(keystoreManager) + let message = "Hello World" + let expectedAddress = keystoreManager.addresses![0] + print(expectedAddress) + let signRes = web3.personal.signPersonalMessage(message: message.data(using: .utf8)!, from: expectedAddress, password: "") + guard case .success(let signature) = signRes else {return XCTFail()} + let unmarshalledSignature = SECP256K1.unmarshalSignature(signatureData: signature)! + print("V = " + String(unmarshalledSignature.v)) + print("R = " + Data(unmarshalledSignature.r).toHexString()) + print("S = " + Data(unmarshalledSignature.s).toHexString()) + print("Personal hash = " + Web3.Utils.hashPersonalMessage(message.data(using: .utf8)!)!.toHexString()) + let recoveredSigner = web3.personal.ecrecover(personalMessage: message.data(using: .utf8)!, signature: signature) + guard case .success(let signer) = recoveredSigner else {return XCTFail()} + XCTAssert(expectedAddress == signer, "Failed to sign personal message") + } + func testPerformanceExample() { // This is an example of a performance test case. self.measure {