Skip to content

Commit efba907

Browse files
committed
Merge branch 'develop' into pr/2
2 parents d8dd9a2 + 915bcd9 commit efba907

21 files changed

+510
-274
lines changed

Sources/Core/EthereumABI/ABIElements.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ extension ABI.Element.Function {
325325
// set a flag to detect the request succeeded
326326
}
327327

328-
if returnArray.isEmpty {
328+
if returnArray.isEmpty && !outputs.isEmpty && data.isEmpty{
329329
return nil
330330
}
331331

Sources/Core/EthereumNetwork/Request/APIRequest+ComputedProperties.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ import Foundation
99

1010
extension APIRequest {
1111
var method: REST {
12-
switch self {
13-
default: return .POST
14-
}
12+
.POST
1513
}
1614

1715
public var encodedBody: Data {
18-
let request = RequestBody(method: self.call, params: self.parameters)
16+
let request = RequestBody(method: call, params: parameters)
1917
// this is safe to force try this here
2018
// Because request must failed to compile if it not conformable with `Encodable` protocol
2119
return try! JSONEncoder().encode(request)

Sources/Core/KeystoreManager/BIP32HDNode.swift

Lines changed: 119 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// web3swift
12
//
23
// Created by Alex Vlasov.
34
// Copyright © 2018 Alex Vlasov. All rights reserved.
@@ -23,12 +24,11 @@ extension UInt32 {
2324
}
2425

2526
public class HDNode {
26-
public struct HDversion {
27-
public var privatePrefix: Data = Data.fromHex("0x0488ADE4")!
28-
public var publicPrefix: Data = Data.fromHex("0x0488B21E")!
29-
public init() {
3027

31-
}
28+
private struct HDversion{
29+
public static var privatePrefix: Data? = Data.fromHex("0x0488ADE4")
30+
public static var publicPrefix: Data? = Data.fromHex("0x0488B21E")
31+
3232
}
3333
public var path: String? = "m"
3434
public var privateKey: Data?
@@ -51,11 +51,6 @@ public class HDNode {
5151
}
5252
}
5353
}
54-
public var hasPrivate: Bool {
55-
get {
56-
return privateKey != nil
57-
}
58-
}
5954

6055
init() {
6156
publicKey = Data()
@@ -72,7 +67,7 @@ public class HDNode {
7267
guard data.count == 82 else {return nil}
7368
let header = data[0..<4]
7469
var serializePrivate = false
75-
if header == HDNode.HDversion().privatePrefix {
70+
if header == HDversion.privatePrefix {
7671
serializePrivate = true
7772
}
7873
depth = data[4..<5].bytes[0]
@@ -94,8 +89,10 @@ public class HDNode {
9489

9590
public init?(seed: Data) {
9691
guard seed.count >= 16 else {return nil}
97-
let hmacKey = "Bitcoin seed".data(using: .ascii)!
98-
let hmac: Authenticator = HMAC(key: hmacKey.bytes, variant: HMAC.Variant.sha2(.sha512))
92+
93+
guard let hmacKey = "Bitcoin seed".data(using: .ascii) else {return nil}
94+
let hmac:Authenticator = HMAC(key: hmacKey.bytes, variant: HMAC.Variant.sha2(.sha512))
95+
9996
guard let entropy = try? hmac.authenticate(seed.bytes) else {return nil}
10097
guard entropy.count == 64 else { return nil}
10198
let I_L = entropy[0..<32]
@@ -104,7 +101,7 @@ public class HDNode {
104101
let privKeyCandidate = Data(I_L)
105102
guard SECP256K1.verifyPrivateKey(privateKey: privKeyCandidate) else {return nil}
106103
guard let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: privKeyCandidate, compressed: true) else {return nil}
107-
guard pubKeyCandidate.bytes[0] == 0x02 || pubKeyCandidate.bytes[0] == 0x03 else {return nil}
104+
guard pubKeyCandidate.bytes.first == 0x02 || pubKeyCandidate.bytes.first == 0x03 else {return nil}
108105
publicKey = pubKeyCandidate
109106
privateKey = privKeyCandidate
110107
depth = 0x00
@@ -120,91 +117,99 @@ public class HDNode {
120117
}
121118

122119
extension HDNode {
123-
public func derive (index: UInt32, derivePrivateKey: Bool, hardened: Bool = false) -> HDNode? {
124-
if derivePrivateKey {
125-
if self.hasPrivate { // derive private key when is itself extended private key
126-
var entropy: [UInt8]
127-
var trueIndex: UInt32
128-
if index >= (UInt32(1) << 31) || hardened {
129-
trueIndex = index
130-
if trueIndex < (UInt32(1) << 31) {
131-
trueIndex = trueIndex + (UInt32(1) << 31)
132-
}
133-
let hmac: Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
134-
var inputForHMAC = Data()
135-
inputForHMAC.append(Data([UInt8(0x00)]))
136-
inputForHMAC.append(self.privateKey!)
137-
inputForHMAC.append(trueIndex.serialize32())
138-
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else {return nil }
139-
guard ent.count == 64 else { return nil }
140-
entropy = ent
141-
} else {
142-
trueIndex = index
143-
let hmac: Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
144-
var inputForHMAC = Data()
145-
inputForHMAC.append(self.publicKey)
146-
inputForHMAC.append(trueIndex.serialize32())
147-
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else {return nil }
148-
guard ent.count == 64 else { return nil }
149-
entropy = ent
150-
}
151-
let I_L = entropy[0..<32]
152-
let I_R = entropy[32..<64]
153-
let cc = Data(I_R)
154-
let bn = BigUInt(Data(I_L))
155-
if bn > HDNode.curveOrder {
156-
if trueIndex < UInt32.max {
157-
return self.derive(index: index+1, derivePrivateKey: derivePrivateKey, hardened: hardened)
158-
}
159-
return nil
160-
}
161-
let newPK = (bn + BigUInt(self.privateKey!)) % HDNode.curveOrder
162-
if newPK == BigUInt(0) {
163-
if trueIndex < UInt32.max {
164-
return self.derive(index: index+1, derivePrivateKey: derivePrivateKey, hardened: hardened)
165-
}
166-
return nil
167-
}
168-
guard let privKeyCandidate = newPK.serialize().setLengthLeft(32) else {return nil}
169-
guard SECP256K1.verifyPrivateKey(privateKey: privKeyCandidate) else {return nil }
170-
guard let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: privKeyCandidate, compressed: true) else {return nil}
171-
guard pubKeyCandidate.bytes[0] == 0x02 || pubKeyCandidate.bytes[0] == 0x03 else {return nil}
172-
guard self.depth < UInt8.max else {return nil}
173-
let newNode = HDNode()
174-
newNode.chaincode = cc
175-
newNode.depth = self.depth + 1
176-
newNode.publicKey = pubKeyCandidate
177-
newNode.privateKey = privKeyCandidate
178-
newNode.childNumber = trueIndex
179-
guard let fprint = try? RIPEMD160.hash(message: self.publicKey.sha256())[0..<4] else {
180-
return nil
181-
}
182-
newNode.parentFingerprint = fprint
183-
var newPath = String()
184-
if newNode.isHardened {
185-
newPath = self.path! + "/"
186-
newPath += String(newNode.index % HDNode.hardenedIndexPrefix) + "'"
187-
} else {
188-
newPath = self.path! + "/" + String(newNode.index)
189-
}
190-
newNode.path = newPath
191-
return newNode
192-
} else {
193-
return nil // derive private key when is itself extended public key (impossible)
120+
public func derive(index: UInt32, derivePrivateKey:Bool, hardened: Bool = false) -> HDNode? {
121+
derivePrivateKey ?
122+
deriveAlongPrivateKey(index: index, derivePrivateKey: derivePrivateKey, hardened: hardened)
123+
:
124+
deriveWithoutPrivateKey(index: index, derivePrivateKey: derivePrivateKey, hardened: hardened)
125+
}
126+
public func deriveAlongPrivateKey(index: UInt32, derivePrivateKey:Bool, hardened: Bool = false) -> HDNode? {
127+
guard let privateKey = self.privateKey else {
128+
return nil
129+
}// derive private key when is itself extended private key
130+
var entropy:Array<UInt8>
131+
var trueIndex: UInt32
132+
if index >= (UInt32(1) << 31) || hardened {
133+
trueIndex = index
134+
if trueIndex < (UInt32(1) << 31) {
135+
trueIndex = trueIndex + (UInt32(1) << 31)
194136
}
195-
} else { // deriving only the public key
196-
var entropy: [UInt8] // derive public key when is itself public key
197-
if index >= (UInt32(1) << 31) || hardened {
198-
return nil // no derivation of hardened public key from extended public key
199-
} else {
200-
let hmac: Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
201-
var inputForHMAC = Data()
202-
inputForHMAC.append(self.publicKey)
203-
inputForHMAC.append(index.serialize32())
204-
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else {return nil }
205-
guard ent.count == 64 else { return nil }
206-
entropy = ent
137+
let hmac:Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
138+
var inputForHMAC = Data()
139+
inputForHMAC.append(Data([UInt8(0x00)]))
140+
inputForHMAC.append(privateKey)
141+
inputForHMAC.append(trueIndex.serialize32())
142+
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else {return nil }
143+
guard ent.count == 64 else { return nil }
144+
entropy = ent
145+
} else {
146+
trueIndex = index
147+
let hmac:Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
148+
var inputForHMAC = Data()
149+
inputForHMAC.append(self.publicKey)
150+
inputForHMAC.append(trueIndex.serialize32())
151+
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else {return nil }
152+
guard ent.count == 64 else { return nil }
153+
entropy = ent
154+
}
155+
let I_L = entropy[0..<32]
156+
let I_R = entropy[32..<64]
157+
let cc = Data(I_R)
158+
let bn = BigUInt(Data(I_L))
159+
if bn > HDNode.curveOrder {
160+
if trueIndex < UInt32.max {
161+
return self.derive(index:index+1, derivePrivateKey: derivePrivateKey, hardened:hardened)
207162
}
163+
return nil
164+
}
165+
let newPK = (bn + BigUInt(privateKey)) % HDNode.curveOrder
166+
if newPK == BigUInt(0) {
167+
if trueIndex < UInt32.max {
168+
return self.derive(index:index+1, derivePrivateKey: derivePrivateKey, hardened:hardened)
169+
}
170+
return nil
171+
}
172+
guard let privKeyCandidate = newPK.serialize().setLengthLeft(32) else {return nil}
173+
guard SECP256K1.verifyPrivateKey(privateKey: privKeyCandidate) else {return nil }
174+
guard let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: privKeyCandidate, compressed: true) else {return nil}
175+
guard pubKeyCandidate.bytes.first == 0x02 || pubKeyCandidate.bytes.first == 0x03 else {return nil}
176+
guard self.depth < UInt8.max else {return nil}
177+
let newNode = HDNode()
178+
newNode.chaincode = cc
179+
newNode.depth = self.depth + 1
180+
newNode.publicKey = pubKeyCandidate
181+
newNode.privateKey = privKeyCandidate
182+
newNode.childNumber = trueIndex
183+
guard let fprint = try? RIPEMD160.hash(message: self.publicKey.sha256())[0..<4] else {
184+
return nil
185+
}
186+
newNode.parentFingerprint = fprint
187+
var newPath = String()
188+
if newNode.isHardened {
189+
newPath = (self.path ?? "") + "/"
190+
newPath += String(newNode.index % HDNode.hardenedIndexPrefix) + "'"
191+
} else {
192+
newPath = (self.path ?? "") + "/" + String(newNode.index)
193+
}
194+
newNode.path = newPath
195+
return newNode
196+
}
197+
198+
public func deriveWithoutPrivateKey(index: UInt32, derivePrivateKey:Bool, hardened: Bool = false) -> HDNode? {
199+
// deriving only the public key
200+
var entropy:Array<UInt8> // derive public key when is itself public key
201+
guard !hardened && index < (UInt32(1) << 31) else {
202+
return nil // no derivation of hardened public key from extended public key
203+
}
204+
205+
let hmac:Authenticator = HMAC(key: self.chaincode.bytes, variant: .sha2(.sha512))
206+
var inputForHMAC = Data()
207+
inputForHMAC.append(self.publicKey)
208+
inputForHMAC.append(index.serialize32())
209+
guard let ent = try? hmac.authenticate(inputForHMAC.bytes) else {return nil }
210+
guard ent.count == 64 else { return nil }
211+
entropy = ent
212+
208213
let I_L = entropy[0..<32]
209214
let I_R = entropy[32..<64]
210215
let cc = Data(I_R)
@@ -218,9 +223,9 @@ extension HDNode {
218223
guard let tempKey = bn.serialize().setLengthLeft(32) else {return nil}
219224
guard SECP256K1.verifyPrivateKey(privateKey: tempKey) else {return nil }
220225
guard let pubKeyCandidate = SECP256K1.privateToPublic(privateKey: tempKey, compressed: true) else {return nil}
221-
guard pubKeyCandidate.bytes[0] == 0x02 || pubKeyCandidate.bytes[0] == 0x03 else {return nil}
226+
guard pubKeyCandidate.bytes.first == 0x02 || pubKeyCandidate.bytes.first == 0x03 else {return nil}
222227
guard let newPublicKey = SECP256K1.combineSerializedPublicKeys(keys: [self.publicKey, pubKeyCandidate], outputCompressed: true) else {return nil}
223-
guard newPublicKey.bytes[0] == 0x02 || newPublicKey.bytes[0] == 0x03 else {return nil}
228+
guard newPublicKey.bytes.first == 0x02 || newPublicKey.bytes.first == 0x03 else {return nil}
224229
guard self.depth < UInt8.max else {return nil}
225230
let newNode = HDNode()
226231
newNode.chaincode = cc
@@ -233,17 +238,17 @@ extension HDNode {
233238
newNode.parentFingerprint = fprint
234239
var newPath = String()
235240
if newNode.isHardened {
236-
newPath = self.path! + "/"
241+
newPath = (self.path ?? "") + "/"
237242
newPath += String(newNode.index % HDNode.hardenedIndexPrefix) + "'"
238243
} else {
239-
newPath = self.path! + "/" + String(newNode.index)
244+
newPath = (self.path ?? "") + "/" + String(newNode.index)
240245
}
241246
newNode.path = newPath
242247
return newNode
243-
}
244248
}
245249

246-
public func derive (path: String, derivePrivateKey: Bool = true) -> HDNode? {
250+
public func derive(path: String, derivePrivateKey: Bool = true) -> HDNode? {
251+
247252
let components = path.components(separatedBy: "/")
248253
var currentNode: HDNode = self
249254
var firstComponent = 0
@@ -262,19 +267,24 @@ extension HDNode {
262267
return currentNode
263268
}
264269

265-
public func serializeToString(serializePublic: Bool = true, version: HDversion = HDversion()) -> String? {
266-
guard let data = self.serialize(serializePublic: serializePublic, version: version) else {return nil}
270+
public func serializeToString(serializePublic: Bool = true) -> String? {
271+
guard let data = self.serialize(serializePublic: serializePublic) else {return nil}
267272
let encoded = Base58.base58FromBytes(data.bytes)
268273
return encoded
269274
}
270275

271-
public func serialize(serializePublic: Bool = true, version: HDversion = HDversion()) -> Data? {
276+
public func serialize(serializePublic: Bool = true) -> Data? {
277+
272278
var data = Data()
273-
if !serializePublic && !self.hasPrivate {return nil}
279+
280+
guard serializePublic || privateKey != nil else {
281+
return nil
282+
}
283+
274284
if serializePublic {
275-
data.append(version.publicPrefix)
285+
data.append(HDversion.publicPrefix!)
276286
} else {
277-
data.append(version.privatePrefix)
287+
data.append(HDversion.privatePrefix!)
278288
}
279289
data.append(contentsOf: [self.depth])
280290
data.append(self.parentFingerprint)

0 commit comments

Comments
 (0)