Skip to content

Commit

Permalink
[#174576563] Add ZNS support to swift resolution library
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Merenkov committed Sep 10, 2020
1 parent 686c340 commit 17a0811
Show file tree
Hide file tree
Showing 11 changed files with 334 additions and 13 deletions.
22 changes: 21 additions & 1 deletion Resolution.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
3EE4DA1424E367720097540B /* resolution.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EE4DA0624E367720097540B /* resolution.h */; settings = {ATTRIBUTES = (Public, ); }; };
3EE4DA1E24E367D40097540B /* Resolution.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE4DA1D24E367D40097540B /* Resolution.swift */; };
3EF4D83524F77E300022B33C /* AbiCoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF4D83424F77E300022B33C /* AbiCoderTests.swift */; };
8402F708250935FE0007F01D /* ContractZNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8402F707250935FD0007F01D /* ContractZNS.swift */; };
848E21092507890A008707D2 /* ZNS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848E21082507890A008707D2 /* ZNS.swift */; };
848E210C25079D61008707D2 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848E210B25079D61008707D2 /* Types.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -58,7 +61,10 @@
3EE4DA1324E367720097540B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3EE4DA1D24E367D40097540B /* Resolution.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Resolution.swift; sourceTree = "<group>"; };
3EF4D83424F77E300022B33C /* AbiCoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbiCoderTests.swift; sourceTree = "<group>"; };
8402F707250935FD0007F01D /* ContractZNS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContractZNS.swift; sourceTree = "<group>"; };
8425AED824FFBADF00BBCBBA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
848E21082507890A008707D2 /* ZNS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZNS.swift; sourceTree = "<group>"; };
848E210B25079D61008707D2 /* Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -85,6 +91,7 @@
isa = PBXGroup;
children = (
3E2AC91B24E4FA28008EBC39 /* CNS.swift */,
848E21082507890A008707D2 /* ZNS.swift */,
3EAFA40324EE32B2008791E9 /* CommonNamingService.swift */,
);
path = NamingServices;
Expand Down Expand Up @@ -140,15 +147,16 @@
3EE4DA0524E367720097540B /* Resolution */ = {
isa = PBXGroup;
children = (
848E210A25079D43008707D2 /* Helpers */,
3E2AC92024E4FA3E008EBC39 /* ABI */,
3E2AC91D24E4FA35008EBC39 /* Protocols */,
3E2AC91A24E4FA28008EBC39 /* NamingServices */,
3EE4DA0624E367720097540B /* resolution.h */,
3EE4DA1D24E367D40097540B /* Resolution.swift */,
3E65912724E381E900D7EC35 /* Errors.swift */,
3E65913024E4ADAC00D7EC35 /* Contract.swift */,
8402F707250935FD0007F01D /* ContractZNS.swift */,
3EAFA3FF24EE0CFD008791E9 /* APIRequest.swift */,
3EAFA40124EE312A008791E9 /* Utilities.swift */,
);
name = Resolution;
path = Sources/Resolution;
Expand All @@ -173,6 +181,15 @@
path = Sources;
sourceTree = "<group>";
};
848E210A25079D43008707D2 /* Helpers */ = {
isa = PBXGroup;
children = (
3EAFA40124EE312A008791E9 /* Utilities.swift */,
848E210B25079D61008707D2 /* Types.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
849E07CB24F946CA00A793D3 /* Tests */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -324,14 +341,17 @@
3E2AC91C24E4FA28008EBC39 /* CNS.swift in Sources */,
3EAFA40424EE32B2008791E9 /* CommonNamingService.swift in Sources */,
3E2AC91F24E4FA35008EBC39 /* NamingService.swift in Sources */,
848E21092507890A008707D2 /* ZNS.swift in Sources */,
3E2AC94124E5EE9A008EBC39 /* ABIElement.swift in Sources */,
3E65912824E381E900D7EC35 /* Errors.swift in Sources */,
3EAFA3F724EB59DA008791E9 /* ABICoder.swift in Sources */,
3EE4DA1E24E367D40097540B /* Resolution.swift in Sources */,
848E210C25079D61008707D2 /* Types.swift in Sources */,
3E65913124E4ADAC00D7EC35 /* Contract.swift in Sources */,
3EAFA40024EE0CFD008791E9 /* APIRequest.swift in Sources */,
3EAFA40224EE312A008791E9 /* Utilities.swift in Sources */,
3EAFA3FE24EE03E0008791E9 /* JSON_RPC.swift in Sources */,
8402F708250935FE0007F01D /* ContractZNS.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
29 changes: 27 additions & 2 deletions Sources/Resolution/ABI/JSON_RPC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,20 @@ import Foundation
struct JSON_RPC_REQUEST: Codable {
let jsonrpc, id, method: String
let params: [ParamElement]

enum CodingKeys: String, CodingKey {
case jsonrpc
case id
case method
case params
}
}

enum ParamElement: Codable {
case paramClass(ParamClass)
case string(String)
case array([ParamElement])
case dictionary([String: ParamElement])

init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
Expand All @@ -28,6 +37,15 @@ enum ParamElement: Codable {
self = .paramClass(elem)
return
}
if let elem = try? container.decode(Array<ParamElement>.self) {
self = .array(elem)
return
}
if let elem = try? container.decode([String: ParamElement].self) {
self = .dictionary(elem)
return
}

throw DecodingError.typeMismatch(ParamElement.self,
DecodingError.Context(
codingPath: decoder.codingPath,
Expand All @@ -42,14 +60,21 @@ enum ParamElement: Codable {
try container.encode(elem)
case .string(let elem):
try container.encode(elem)
case .array(let array):
try container.encode(array)
case .dictionary(let dict):
try container.encode(dict)
}
}
}

struct ParamClass: Codable {
let data, to: String
let data: String
let to: String
}

struct JSON_RPC_RESPONSE: Codable {
let jsonrpc, id, result: String
let jsonrpc: String
let id: String
let result: ParamElement
}
7 changes: 6 additions & 1 deletion Sources/Resolution/Contract.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ internal class Contract {
guard err == nil else {
throw err!
}
return resp?.result
switch resp?.result {
case .string(let result):
return result
default:
return nil
}
}
}
97 changes: 97 additions & 0 deletions Sources/Resolution/ContractZNS.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//
// Contract.swift
// resolution
//
// Created by Johnny Good on 8/12/20.
// Copyright © 2020 Johnny Good. All rights reserved.
//

import Foundation

internal class ContractZNS {
let address: String
let providerUrl: String

init(providerUrl: String, address: String) {
self.address = address
self.providerUrl = providerUrl
}

func fetchSubState(field: String, keys: [String]) throws -> Any {

let body: JSON_RPC_REQUEST = JSON_RPC_REQUEST(
jsonrpc: "2.0",
id: "1",
method: "GetSmartContractSubState",
params: [
ParamElement.string(self.address),
ParamElement.string(field),
ParamElement.array(keys.map { ParamElement.string($0) })
]
)
let response = try postRequest(body)!

guard case let ParamElement.dictionary(dict) = response,
let results = self.reduce(dict: dict)[field] as? [String: Any] else {
print("Invalid response, can't process")
return response
}

return results
}

private func postRequest(_ body: JSON_RPC_REQUEST) throws -> Any? {
let postRequest = APIRequest(providerUrl)
var resp: JSON_RPC_RESPONSE?
var err: Error?
let semaphore = DispatchSemaphore(value: 0)
postRequest.post(body, completion: {result in
switch result {
case .success(let response):
resp = response
case .failure(let error):
err = error
}
semaphore.signal()
})
semaphore.wait()
guard err == nil else {
throw err!
}
return resp?.result
}

// MARK: - PRIVATE Helper functions

private func reduce(dict: [String: ParamElement]) -> [String: Any] {
return dict.reduce(into: [String: Any]()) { dict, pair in
let (key, value) = pair

switch value {
case .paramClass(let elem):
dict[key] = elem
case .string(let elem):
dict[key] = elem
case .array(let array):
dict[key] = self.map(array: array)
case .dictionary(let dictionary):
dict[key] = self.reduce(dict: dictionary)
}
}
}

private func map(array: [ParamElement]) -> [Any] {
return array.map { (value) -> Any in
switch value {
case .paramClass(let elem):
return elem
case .string(let elem):
return elem
case .array(let array):
return self.map(array: array)
case .dictionary(let dictionary):
return self.reduce(dict: dictionary)
}
}
}
}
1 change: 1 addition & 0 deletions Sources/Resolution/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ public enum ResolutionError: Error {
case unconfiguredDomain
case recordNotFound
case unsupportedNetwork
case unspecifiedResolver
case unknownError(Error)
}
12 changes: 12 additions & 0 deletions Sources/Resolution/Helpers/Types.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Types.swift
// Resolution
//
// Created by Admin on 08.09.20.
// Copyright © 2020 Johnny Good. All rights reserved.
//

import Foundation

public typealias StringResult = (Result<String, ResolutionError>) -> Void
public typealias DictionaryResult = (Result<[String: String], ResolutionError>) -> Void
File renamed without changes.
9 changes: 7 additions & 2 deletions Sources/Resolution/NamingServices/CommonNamingService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,15 @@ class CommonNamingService {
var node = [UInt8].init(repeating: 0x0, count: 32)
if domain.count > 0 {
node = domain.split(separator: ".")
.map { Array($0.utf8).sha3(.keccak256) }
.map { Array($0.utf8)}
.reversed()
.reduce(node) { return ($0 + $1).sha3(.keccak256) }
.reduce(node) { return self.childHash(parent: $0, label: $1)}
}
return "0x" + node.toHexString()
}

func childHash(parent: [UInt8], label: [UInt8]) -> [UInt8] {
let childHash = label.sha3(.keccak256)
return (parent + childHash).sha3(.keccak256)
}
}
Loading

0 comments on commit 17a0811

Please sign in to comment.