Skip to content

Commit 6e0f62b

Browse files
authored
Merge pull request #65 from BANKEX/develop
Fix BIP 32 derivation in release build (with optimization)
2 parents 6d840cb + 621ea9c commit 6e0f62b

File tree

2 files changed

+58
-29
lines changed

2 files changed

+58
-29
lines changed

web3swift/Convenience/Classes/LibSecp256k1Extension.swift

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,44 +53,44 @@ extension SECP256K1 {
5353
static func combineSerializedPublicKeys(keys: [Data], outputCompressed: Bool = false) -> Data? {
5454
let numToCombine = keys.count
5555
guard numToCombine >= 1 else { return nil}
56-
var publicKeys = [UnsafePointer<secp256k1_pubkey>?]()
57-
var result:Int32
58-
for i in 0..<numToCombine {
59-
var publicKey = secp256k1_pubkey()
56+
var storage = ContiguousArray<secp256k1_pubkey>()
57+
let arrayOfPointers = UnsafeMutablePointer< UnsafePointer<secp256k1_pubkey>? >.allocate(capacity: numToCombine)
58+
defer {
59+
arrayOfPointers.deinitialize(count: numToCombine)
60+
arrayOfPointers.deallocate()
61+
}
62+
for i in 0 ..< numToCombine {
6063
let key = keys[i]
61-
let keyLen = key.count
62-
result = key.withUnsafeBytes { (publicKeyPointer:UnsafePointer<UInt8>) -> Int32 in
63-
let res = secp256k1_ec_pubkey_parse(context!, UnsafeMutablePointer<secp256k1_pubkey>(&publicKey), publicKeyPointer, keyLen)
64-
return res
65-
}
66-
if result == 0 {
67-
return nil
64+
guard let pubkey = SECP256K1.parsePublicKey(serializedKey: key) else {return nil}
65+
storage.append(pubkey)
66+
}
67+
for i in 0 ..< numToCombine {
68+
withUnsafePointer(to: &storage[i]) { (ptr) -> Void in
69+
arrayOfPointers.advanced(by: i).pointee = ptr
6870
}
69-
let pointer = UnsafePointer<secp256k1_pubkey>(UnsafeMutablePointer<secp256k1_pubkey>(&publicKey))
70-
publicKeys.append(pointer)
7171
}
72-
72+
let immutablePointer = UnsafePointer(arrayOfPointers)
7373
var publicKey: secp256k1_pubkey = secp256k1_pubkey()
74-
let arrayPointer = UnsafePointer(publicKeys)
75-
result = secp256k1_ec_pubkey_combine(context!, UnsafeMutablePointer<secp256k1_pubkey>(&publicKey), arrayPointer, numToCombine)
74+
75+
// let bufferPointer = UnsafeBufferPointer(start: immutablePointer, count: numToCombine)
76+
// for (index, value) in bufferPointer.enumerated() {
77+
// print("pointer value \(index): \(value!)")
78+
// let val = value?.pointee
79+
// print("value \(index): \(val!)")
80+
// }
81+
//
82+
let result = withUnsafeMutablePointer(to: &publicKey) { (pubKeyPtr: UnsafeMutablePointer<secp256k1_pubkey>) -> Int32 in
83+
let res = secp256k1_ec_pubkey_combine(context!, pubKeyPtr, immutablePointer, numToCombine)
84+
return res
85+
}
7686
if result == 0 {
7787
return nil
7888
}
79-
80-
var keyLength = outputCompressed ? 33 : 65
81-
var serializedPubkey = Data(repeating: 0x00, count: keyLength)
82-
83-
result = serializedPubkey.withUnsafeMutableBytes { (serializedPubkeyPointer:UnsafeMutablePointer<UInt8>) -> Int32 in
84-
let res = secp256k1_ec_pubkey_serialize(context!,
85-
serializedPubkeyPointer,
86-
UnsafeMutablePointer<Int>(&keyLength),
87-
UnsafeMutablePointer<secp256k1_pubkey>(&publicKey),
88-
UInt32(outputCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED))
89-
return res
90-
}
91-
return Data(serializedPubkey)
89+
let serializedKey = SECP256K1.serializePublicKey(publicKey: &publicKey, compressed: outputCompressed)
90+
return serializedKey
9291
}
9392

93+
9494
static func recoverPublicKey(hash: Data, recoverableSignature: inout secp256k1_ecdsa_recoverable_signature) -> secp256k1_pubkey? {
9595
guard hash.count == 32 else {return nil}
9696
var publicKey: secp256k1_pubkey = secp256k1_pubkey()

web3swiftTests/web3swiftTests.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@ class web3swiftTests: XCTestCase {
8888
XCTAssert(first4bits == 0x0f)
8989
}
9090

91+
func testCombiningPublicKeys() {
92+
let priv1 = Data.randomBytes(length: 32)!
93+
let pub1 = Web3.Utils.privateToPublic(priv1, compressed: true)!
94+
let priv2 = Data.randomBytes(length: 32)!
95+
let pub2 = Web3.Utils.privateToPublic(priv2, compressed: true)!
96+
let combined = SECP256K1.combineSerializedPublicKeys(keys: [pub1, pub2], outputCompressed: true)
97+
XCTAssert(combined != nil)
98+
}
99+
91100
func testBIP39 () {
92101
var entropy = Data.fromHex("00000000000000000000000000000000")!
93102
var phrase = BIP39.generateMnemonicsFromEntropy(entropy: entropy)
@@ -1991,6 +2000,26 @@ class web3swiftTests: XCTestCase {
19912000
}
19922001
}
19932002

2003+
func testPersonalSignature() {
2004+
let web3 = Web3.InfuraRinkebyWeb3()
2005+
let tempKeystore = try! EthereumKeystoreV3(password: "")
2006+
let keystoreManager = KeystoreManager([tempKeystore!])
2007+
web3.addKeystoreManager(keystoreManager)
2008+
let message = "Hello World"
2009+
let expectedAddress = keystoreManager.addresses![0]
2010+
print(expectedAddress)
2011+
let signRes = web3.personal.signPersonalMessage(message: message.data(using: .utf8)!, from: expectedAddress, password: "")
2012+
guard case .success(let signature) = signRes else {return XCTFail()}
2013+
let unmarshalledSignature = SECP256K1.unmarshalSignature(signatureData: signature)!
2014+
print("V = " + String(unmarshalledSignature.v))
2015+
print("R = " + Data(unmarshalledSignature.r).toHexString())
2016+
print("S = " + Data(unmarshalledSignature.s).toHexString())
2017+
print("Personal hash = " + Web3.Utils.hashPersonalMessage(message.data(using: .utf8)!)!.toHexString())
2018+
let recoveredSigner = web3.personal.ecrecover(personalMessage: message.data(using: .utf8)!, signature: signature)
2019+
guard case .success(let signer) = recoveredSigner else {return XCTFail()}
2020+
XCTAssert(expectedAddress == signer, "Failed to sign personal message")
2021+
}
2022+
19942023
func testPerformanceExample() {
19952024
// This is an example of a performance test case.
19962025
self.measure {

0 commit comments

Comments
 (0)