From dd6d3aba46ad7562028d20424d3980eb5ccc8653 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Mon, 20 May 2019 16:43:03 -0700 Subject: [PATCH 01/15] Refactor Docker operation --- ZKPlayground.xcodeproj/project.pbxproj | 18 +++----- ZKPlayground/AppDelegate.swift | 33 +++++++------- ZKPlayground/BuildPhase.swift | 2 +- .../Docker Operations/RemoteDockerAPI.swift | 20 --------- .../EditorWindowController.swift | 10 ++--- .../ShellOperation.swift} | 44 +++++++++---------- 6 files changed, 51 insertions(+), 76 deletions(-) delete mode 100644 ZKPlayground/Docker Operations/RemoteDockerAPI.swift rename ZKPlayground/{Docker Operations/Docker.swift => Shell Operations/ShellOperation.swift} (82%) diff --git a/ZKPlayground.xcodeproj/project.pbxproj b/ZKPlayground.xcodeproj/project.pbxproj index e21c396..f450b4c 100644 --- a/ZKPlayground.xcodeproj/project.pbxproj +++ b/ZKPlayground.xcodeproj/project.pbxproj @@ -24,7 +24,6 @@ C76F0A8E2251943F002B275B /* BuildPhase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76F0A8D2251943F002B275B /* BuildPhase.swift */; }; C76F0A902252D167002B275B /* BuildPhaseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C76F0A8F2252D167002B275B /* BuildPhaseView.xib */; }; C76F0A922252D8A0002B275B /* BuildPhaseStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76F0A912252D8A0002B275B /* BuildPhaseStackView.swift */; }; - C78A91C22246F7720033233E /* RemoteDockerAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78A91C12246F7720033233E /* RemoteDockerAPI.swift */; }; C78A91CA22488BA00033233E /* NSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78A91C922488BA00033233E /* NSColor.swift */; }; C78A92442248ADD60033233E /* CompilerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78A92432248ADD60033233E /* CompilerError.swift */; }; C78A92462248AF3A0033233E /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78A92452248AF3A0033233E /* String.swift */; }; @@ -41,7 +40,7 @@ C7AE8A9222442EE6001EC64A /* EditorWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AE8A9122442EE6001EC64A /* EditorWindowController.swift */; }; C7AE8A94224430B0001EC64A /* SplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AE8A93224430B0001EC64A /* SplitViewController.swift */; }; C7AE8A9622443135001EC64A /* InspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AE8A9522443135001EC64A /* InspectorViewController.swift */; }; - C7AE8A9A22445986001EC64A /* Docker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AE8A97224443BA001EC64A /* Docker.swift */; }; + C7AE8A9A22445986001EC64A /* ShellOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7AE8A97224443BA001EC64A /* ShellOperation.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -74,7 +73,6 @@ C76F0A8D2251943F002B275B /* BuildPhase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildPhase.swift; sourceTree = ""; }; C76F0A8F2252D167002B275B /* BuildPhaseView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BuildPhaseView.xib; sourceTree = ""; }; C76F0A912252D8A0002B275B /* BuildPhaseStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildPhaseStackView.swift; sourceTree = ""; }; - C78A91C12246F7720033233E /* RemoteDockerAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteDockerAPI.swift; sourceTree = ""; }; C78A91C922488BA00033233E /* NSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSColor.swift; sourceTree = ""; }; C78A92432248ADD60033233E /* CompilerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompilerError.swift; sourceTree = ""; }; C78A92452248AF3A0033233E /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = ""; }; @@ -97,7 +95,7 @@ C7AE8A9122442EE6001EC64A /* EditorWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorWindowController.swift; sourceTree = ""; }; C7AE8A93224430B0001EC64A /* SplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitViewController.swift; sourceTree = ""; }; C7AE8A9522443135001EC64A /* InspectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorViewController.swift; sourceTree = ""; }; - C7AE8A97224443BA001EC64A /* Docker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Docker.swift; sourceTree = ""; }; + C7AE8A97224443BA001EC64A /* ShellOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellOperation.swift; sourceTree = ""; }; CD92BEDFC397D6BE20E8D2FE /* Pods-ZKPlaygroundTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZKPlaygroundTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ZKPlaygroundTests/Pods-ZKPlaygroundTests.release.xcconfig"; sourceTree = ""; }; DF75002819B65626EA81721D /* Pods-ZKPlayground.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZKPlayground.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ZKPlayground/Pods-ZKPlayground.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -161,13 +159,12 @@ path = Inspector; sourceTree = ""; }; - C78A91C3224718390033233E /* Docker Operations */ = { + C78A91C3224718390033233E /* Shell Operations */ = { isa = PBXGroup; children = ( - C7AE8A97224443BA001EC64A /* Docker.swift */, - C78A91C12246F7720033233E /* RemoteDockerAPI.swift */, + C7AE8A97224443BA001EC64A /* ShellOperation.swift */, ); - path = "Docker Operations"; + path = "Shell Operations"; sourceTree = ""; }; C78A91C822488B970033233E /* Extensions */ = { @@ -207,7 +204,7 @@ C764DC5D2257B3B80042B122 /* Template Window */, C7AE8A8122436470001EC64A /* Editor Window */, C7AE8A5F22434E55001EC64A /* AppDelegate.swift */, - C78A91C3224718390033233E /* Docker Operations */, + C78A91C3224718390033233E /* Shell Operations */, C7AE8A6122434E55001EC64A /* ViewController.swift */, C7AE8A6322434E55001EC64A /* Document.swift */, C7AE8A8F22436B37001EC64A /* ZKError.swift */, @@ -450,7 +447,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C78A91C22246F7720033233E /* RemoteDockerAPI.swift in Sources */, C76F0A8C22518043002B275B /* TimeInterval.swift in Sources */, C764DC64225C73250042B122 /* ZokratesInterface.swift in Sources */, C7AE8A9222442EE6001EC64A /* EditorWindowController.swift in Sources */, @@ -465,7 +461,7 @@ C7AE8A9022436B37001EC64A /* ZKError.swift in Sources */, C764DC68225C742E0042B122 /* InterfaceProtocol.swift in Sources */, C7AE8A6022434E55001EC64A /* AppDelegate.swift in Sources */, - C7AE8A9A22445986001EC64A /* Docker.swift in Sources */, + C7AE8A9A22445986001EC64A /* ShellOperation.swift in Sources */, C7AE8A6422434E55001EC64A /* Document.swift in Sources */, C76F0A922252D8A0002B275B /* BuildPhaseStackView.swift in Sources */, C764DC612257B3F60042B122 /* TemplatesViewController.swift in Sources */, diff --git a/ZKPlayground/AppDelegate.swift b/ZKPlayground/AppDelegate.swift index b07f8b7..b9fd451 100644 --- a/ZKPlayground/AppDelegate.swift +++ b/ZKPlayground/AppDelegate.swift @@ -15,7 +15,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { - dockerInstall() + verifyZokratesInstall() // If no document is restored, show template chooser // if NSDocumentController.shared.documents.isEmpty { @@ -31,21 +31,22 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool { return false } - - private func dockerInstall() { - - if FileManager.default.isExecutableFile(atPath: "//usr//local//bin//docker") { return } - - let alert = NSAlert() - alert.messageText = "Docker is not installed" - alert.informativeText = "ZK Playground requires Docker" - alert.addButton(withTitle: "Download Docker") - alert.addButton(withTitle: "Continue anyway") - let response = alert.runModal() - if response == .alertFirstButtonReturn, - let url = URL(string: "https://docs.docker.com/docker-for-mac/install") { - NSWorkspace.shared.open(url) - } + + private func verifyZokratesInstall() { + + let zokratesPath = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".zokrates/bin/zokrates").path + + print(zokratesPath) + + if FileManager.default.isExecutableFile(atPath: zokratesPath) { return } + + // Zokrates is not installed + + // Run: + // curl -LSfs get.zokrat.es | sh + // export PATH=$PATH:$HOME/.zokrates/bin + // export ZOKRATES_HOME=$HOME/.zokrates/stdlib + } @IBAction func showTemplates(_ sender: AnyObject?) { diff --git a/ZKPlayground/BuildPhase.swift b/ZKPlayground/BuildPhase.swift index 0a9ff3b..9c8f6c3 100644 --- a/ZKPlayground/BuildPhase.swift +++ b/ZKPlayground/BuildPhase.swift @@ -31,7 +31,7 @@ class BuildPhase: NSObject { self.errorMessage = errorMessage self.urls = phase.filenames.map{ - URL(fileURLWithPath: workDirectory).appendingPathComponent(Docker.buildDirectory).appendingPathComponent($0).path + URL(fileURLWithPath: workDirectory).appendingPathComponent(ShellOperation.buildDirectory).appendingPathComponent($0).path } if let urls = self.urls { self.successful = urls.filter{ FileManager.default.fileExists(atPath: $0) }.count == urls.count } else { self.successful = false } diff --git a/ZKPlayground/Docker Operations/RemoteDockerAPI.swift b/ZKPlayground/Docker Operations/RemoteDockerAPI.swift deleted file mode 100644 index cd4fda5..0000000 --- a/ZKPlayground/Docker Operations/RemoteDockerAPI.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// RemoteDockerAPI.swift -// ZKPlayground -// -// Created by Ronald "Danger" Mannak on 3/23/19. -// Copyright © 2019 A Puzzle A Day. All rights reserved. -// - -import Foundation - -/// Just leaving this here in case we want to control Docker remotely -/// Source: https://github.com/docker/for-mac/issues/770 -/// https://github.com/valeriomazzeo/docker-client-swift -/// https://docs.docker.com/develop/sdk/examples/ -class RemoteDockerAPI: Operation { - - let command = "docker run -d -v /var/run/docker.sock:/var/run/docker.sock -p 127.0.0.1:1234:1234 bobrik/socat TCP-LISTEN:1234,fork UNIX-CONNECT:/var/run/docker.sock; export DOCKER_HOST=tcp://localhost:1234" - // curl 127.0.0.1:1234/containers/json - -} diff --git a/ZKPlayground/Editor Window/EditorWindowController.swift b/ZKPlayground/Editor Window/EditorWindowController.swift index 1bec750..5520e59 100644 --- a/ZKPlayground/Editor Window/EditorWindowController.swift +++ b/ZKPlayground/Editor Window/EditorWindowController.swift @@ -82,7 +82,7 @@ extension EditorWindowController { // 4. Build directory let fileManager = FileManager.default - let buildDirectory = URL(string: workDirectory)!.appendingPathComponent(Docker.buildDirectory) + let buildDirectory = URL(string: workDirectory)!.appendingPathComponent(ShellOperation.buildDirectory) var isDirectory: ObjCBool = false if fileManager.fileExists(atPath: buildDirectory.path, isDirectory: &isDirectory) == false || isDirectory.boolValue == false { @@ -161,12 +161,12 @@ extension EditorWindowController { } // Docker delegate -extension EditorWindowController: DockerProtocol { - func docker(_ docker: Docker, didReceiveStdout string: String) { +extension EditorWindowController: ShellProtocol { + func shell(_ docker: ShellOperation, didReceiveStdout string: String) { self.logViewController.stdout(string) } - func docker(_ docker: Docker, didReceiveStderr string: String) { + func shell(_ docker: ShellOperation, didReceiveStderr string: String) { // Open log pane DispatchQueue.main.async { @@ -181,7 +181,7 @@ extension EditorWindowController: DockerProtocol { self.logViewController.stderr(string) } - func docker(_ docker: Docker, didReceiveStdin string: String) { + func shell(_ docker: ShellOperation, didReceiveStdin string: String) { self.logViewController.stdin(string) } diff --git a/ZKPlayground/Docker Operations/Docker.swift b/ZKPlayground/Shell Operations/ShellOperation.swift similarity index 82% rename from ZKPlayground/Docker Operations/Docker.swift rename to ZKPlayground/Shell Operations/ShellOperation.swift index 8a866be..a1a49ee 100644 --- a/ZKPlayground/Docker Operations/Docker.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -8,23 +8,21 @@ import Foundation -protocol DockerProtocol: class { +protocol ShellProtocol: class { - // Docker received data from the docker image - func docker(_ docker: Docker, didReceiveStdout string: String) + // Received data from shell + func shell(_ shell: ShellOperation, didReceiveStdout string: String) - // Docker received an error from the docker image - func docker(_ docker: Docker, didReceiveStderr string: String) + // Received error from shell + func shell(_ shell: ShellOperation, didReceiveStderr string: String) - // Docker sent stdin to the docker image from the app - func docker(_ docker: Docker, didReceiveStdin string: String) + // App sent stdin to shell + func shell(_ shell: ShellOperation, didReceiveStdin string: String) } -/// TODO: explore Docker Remote API http://blog.arungupta.me/enable-docker-remote-api-mac-osx-machine/ -/// https://github.com/docker/for-mac/issues/770 -class Docker: Operation { +class ShellOperation: Operation { - weak var delegate: DockerProtocol? + weak var delegate: ShellProtocol? /// If any of the commands in the script returns non-zero, /// the script will cancel and forward the exit code @@ -51,10 +49,10 @@ class Docker: Operation { /// the name of the directory mapped to workDirectoryPath fileprivate static let dockerDirectoryPath = "/home/zokrates/playground" static let buildDirectory = "build" - fileprivate static var dockerBuildPath = { return URL(fileURLWithPath: dockerDirectoryPath).appendingPathComponent(Docker.buildDirectory).path }() + fileprivate static var dockerBuildPath = { return URL(fileURLWithPath: dockerDirectoryPath).appendingPathComponent(ShellOperation.buildDirectory).path }() fileprivate var dockerFilename: String { - return URL(fileURLWithPath: Docker.dockerDirectoryPath).appendingPathComponent(self.filename).path + return URL(fileURLWithPath: ShellOperation.dockerDirectoryPath).appendingPathComponent(self.filename).path } /// Arguments used to start Docker (e.g. docker run -v ....) @@ -64,7 +62,7 @@ class Docker: Operation { self.filename = filename self.workDirectory = workDirectory - self.dockerArguments = ["run", "-v", workDirectory + ":" + Docker.dockerDirectoryPath, "-i", "zokrates/zokrates", "/bin/bash"] + self.dockerArguments = ["run", "-v", workDirectory + ":" + ShellOperation.dockerDirectoryPath, "-i", "zokrates/zokrates", "/bin/bash"] self.logOutput = logOutput super.init() @@ -96,15 +94,15 @@ class Docker: Operation { // Print to log let command: String = task.launchPath ?? "" let arguments: String = task.arguments?.joined(separator: " ") ?? "" - self.delegate?.docker(self, didReceiveStdin: "\n$ " + command + " " + arguments + "\n") + self.delegate?.shell(self, didReceiveStdin: "\n$ " + command + " " + arguments + "\n") // Set exitStatus at exit self.task.terminationHandler = { task in self.exitStatus = Int(task.terminationStatus) if self.exitStatus == 0 { - self.delegate?.docker(self, didReceiveStdout: "\nTask exited with exit status 0\n") + self.delegate?.shell(self, didReceiveStdout: "\nTask exited with exit status 0\n") } else { - self.delegate?.docker(self, didReceiveStderr: "\nTask exited with exit status \(self.exitStatus!)\n") + self.delegate?.shell(self, didReceiveStderr: "\nTask exited with exit status \(self.exitStatus!)\n") } _ = self.notifications.map { NotificationCenter.default.removeObserver($0) } } @@ -116,7 +114,7 @@ class Docker: Operation { self.capture(self.stdoutPipe) { stdout in - self.delegate?.docker(self, didReceiveStdout: stdout) + self.delegate?.shell(self, didReceiveStdout: stdout) if self.logOutput == true { self.output += stdout } // print utf8 values @@ -127,7 +125,7 @@ class Docker: Operation { self.capture(self.stderrPipe) { stderr in - self.delegate?.docker(self, didReceiveStderr: stderr) + self.delegate?.shell(self, didReceiveStderr: stderr) if self.logOutput == true { self.output += stderr } } @@ -160,7 +158,7 @@ class Docker: Operation { let string = string + "\n" guard task.isRunning == true, let data = (string).data(using: .utf8) else { return assertionFailure() } - self.delegate?.docker(self, didReceiveStdin: "\n" + string) + self.delegate?.shell(self, didReceiveStdin: "\n" + string) self.stdinPipe.fileHandleForWriting.write(data) if wait == true { self.stdinPipe.fileHandleForWriting.waitForDataInBackgroundAndNotify() } } @@ -178,13 +176,13 @@ class Docker: Operation { fileprivate func copy(file: String) { //} -> Bool { - self.write("cp " + file + " " + Docker.dockerBuildPath) + self.write("cp " + file + " " + ShellOperation.dockerBuildPath) } } /// Compiles code, returns warnings and errors /// ./zokrates compile -i playground/root.code -class Lint: Docker { +class Lint: ShellOperation { override func main() { @@ -197,7 +195,7 @@ class Lint: Docker { } /// Compiles and builds product and proofs -class Compile: Docker { +class Compile: ShellOperation { let arguments: [String]? From 524cdc6c49dc2a1a743ba1b81c4c829d1b1902a0 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Tue, 21 May 2019 11:58:33 -0700 Subject: [PATCH 02/15] Add export Zokrates path --- ZKPlayground/Shell Operations/ShellOperation.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index a1a49ee..549b617 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -85,8 +85,16 @@ class ShellOperation: Operation { guard isCancelled == false else { return } // Set up task + + // Exporting Zokrates paths + // export PATH=$PATH:$HOME/.zokrates/bin + // export ZOKRATES_HOME=$HOME/.zokrates/stdlib + let zokratesDirectory = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".zokrates") + let zokratesBinPath = zokratesDirectory.appendingPathComponent("bin").path + let zokratesHomePath = zokratesDirectory.appendingPathComponent("stdlib").path + self.task.environment = ProcessInfo().environment - self.task.environment?.updateValue("/usr/local/bin/:/usr/bin:/bin:/usr/sbin:/sbin", forKey: "PATH") + self.task.environment?.updateValue("/usr/local/bin/:/usr/bin:/bin:/usr/sbin:/sbin:\(zokratesBinPath):\(zokratesHomePath)", forKey: "PATH") task.launchPath = "/usr/local/bin/docker" // TODO: use which path task.arguments = self.dockerArguments task.currentDirectoryPath = Bundle.main.bundlePath From be6e23e315496dc75c4ecf32dac7f7f4c4d5fb7e Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Tue, 21 May 2019 17:39:49 -0700 Subject: [PATCH 03/15] Refactor Linting --- ZKPlayground.xcodeproj/project.pbxproj | 2 - ZKPlayground/BuildPhase.swift | 2 +- .../Editor Window/EditorViewController.swift | 2 +- .../EditorWindowController.swift | 33 +--- .../Shell Operations/ShellOperation.swift | 151 +++++++++++------- ZKPlayground/ViewController.swift | 27 ---- 6 files changed, 99 insertions(+), 118 deletions(-) delete mode 100644 ZKPlayground/ViewController.swift diff --git a/ZKPlayground.xcodeproj/project.pbxproj b/ZKPlayground.xcodeproj/project.pbxproj index f450b4c..1768c32 100644 --- a/ZKPlayground.xcodeproj/project.pbxproj +++ b/ZKPlayground.xcodeproj/project.pbxproj @@ -79,7 +79,6 @@ C79BE65C2255765C00325471 /* slice1_512@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "slice1_512@2x.png"; sourceTree = ""; }; C7AE8A5C22434E55001EC64A /* ZKPlayground.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZKPlayground.app; sourceTree = BUILT_PRODUCTS_DIR; }; C7AE8A5F22434E55001EC64A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - C7AE8A6122434E55001EC64A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; C7AE8A6322434E55001EC64A /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = ""; }; C7AE8A6522434E59001EC64A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; C7AE8A6822434E59001EC64A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -205,7 +204,6 @@ C7AE8A8122436470001EC64A /* Editor Window */, C7AE8A5F22434E55001EC64A /* AppDelegate.swift */, C78A91C3224718390033233E /* Shell Operations */, - C7AE8A6122434E55001EC64A /* ViewController.swift */, C7AE8A6322434E55001EC64A /* Document.swift */, C7AE8A8F22436B37001EC64A /* ZKError.swift */, C78A92432248ADD60033233E /* CompilerError.swift */, diff --git a/ZKPlayground/BuildPhase.swift b/ZKPlayground/BuildPhase.swift index 9c8f6c3..17ee973 100644 --- a/ZKPlayground/BuildPhase.swift +++ b/ZKPlayground/BuildPhase.swift @@ -31,7 +31,7 @@ class BuildPhase: NSObject { self.errorMessage = errorMessage self.urls = phase.filenames.map{ - URL(fileURLWithPath: workDirectory).appendingPathComponent(ShellOperation.buildDirectory).appendingPathComponent($0).path + URL(fileURLWithPath: workDirectory).appendingPathComponent("build").appendingPathComponent($0).path } if let urls = self.urls { self.successful = urls.filter{ FileManager.default.fileExists(atPath: $0) }.count == urls.count } else { self.successful = false } diff --git a/ZKPlayground/Editor Window/EditorViewController.swift b/ZKPlayground/Editor Window/EditorViewController.swift index 4768215..4106f46 100644 --- a/ZKPlayground/Editor Window/EditorViewController.swift +++ b/ZKPlayground/Editor Window/EditorViewController.swift @@ -44,7 +44,7 @@ class EditorViewController: NSViewController { document.save(nil) - let lint = Lint(workDirectory: workDirectory, filename: filename) + let lint = Lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: true) lint.completionBlock = { if lint.output.contains("Compilation failed:") { diff --git a/ZKPlayground/Editor Window/EditorWindowController.swift b/ZKPlayground/Editor Window/EditorWindowController.swift index 5520e59..c8da240 100644 --- a/ZKPlayground/Editor Window/EditorWindowController.swift +++ b/ZKPlayground/Editor Window/EditorWindowController.swift @@ -60,7 +60,7 @@ class EditorWindowController: NSWindowController { extension EditorWindowController { @IBAction func compile(_ sender: Any?) { - + /* // 1. Sanity check guard let document = document as? Document else { return assertionFailure() } @@ -79,35 +79,6 @@ extension EditorWindowController { // 3. Save document and reset buildphases document.save(self) document.buildPhases = nil - - // 4. Build directory - let fileManager = FileManager.default - let buildDirectory = URL(string: workDirectory)!.appendingPathComponent(ShellOperation.buildDirectory) - var isDirectory: ObjCBool = false - if fileManager.fileExists(atPath: buildDirectory.path, isDirectory: &isDirectory) == false || isDirectory.boolValue == false { - - // 5.a Build directory does not exist. Create it - do { - try fileManager.createDirectory(atPath: buildDirectory.path, withIntermediateDirectories: false, attributes: nil) - } catch { - NSAlert(error: error).beginSheetModal(for: self.window!) - inspectorViewController.progressIndicator.stopAnimation(self) - return - } - } else { - - // 5.b Delete all files in the build directory - let enumerator = fileManager.enumerator(at: buildDirectory, includingPropertiesForKeys: nil) - while let file = enumerator?.nextObject() as? URL { - do { - try fileManager.removeItem(at: file) - } catch { - NSAlert(error: error).beginSheetModal(for: self.window!) - inspectorViewController.progressIndicator.stopAnimation(self) - return - } - } - } // 6. Create and queue compile operation let compile = Compile(workDirectory: workDirectory, filename: filename, arguments: self.inspectorViewController.arguments) @@ -152,7 +123,7 @@ extension EditorWindowController { document.buildPhases = phases } - compileQueue.addOperation(compile) + compileQueue.addOperation(compile) */ } @IBAction func stop(_ sender: Any?) { diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index 549b617..8eef323 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -7,6 +7,7 @@ // import Foundation +import Cocoa protocol ShellProtocol: class { @@ -43,66 +44,66 @@ class ShellOperation: Operation { private var notifications = [NSObjectProtocol]() /// Name of the .code file, e.g. "HelloWorld.code" - private let filename: String - private let workDirectory: String + fileprivate let sourceFilename: String + fileprivate let workDirectory: String + var buildDirectory: String { return URL(fileURLWithPath: self.workDirectory).appendingPathComponent("build").path } - /// the name of the directory mapped to workDirectoryPath - fileprivate static let dockerDirectoryPath = "/home/zokrates/playground" - static let buildDirectory = "build" - fileprivate static var dockerBuildPath = { return URL(fileURLWithPath: dockerDirectoryPath).appendingPathComponent(ShellOperation.buildDirectory).path }() - - fileprivate var dockerFilename: String { - return URL(fileURLWithPath: ShellOperation.dockerDirectoryPath).appendingPathComponent(self.filename).path - } - - /// Arguments used to start Docker (e.g. docker run -v ....) - private let dockerArguments: [String] - - init(workDirectory: String, filename: String, logOutput: Bool = true) { + init(workDirectory: String, sourceFilename: String, logOutput: Bool = true) { - self.filename = filename + self.sourceFilename = sourceFilename self.workDirectory = workDirectory - self.dockerArguments = ["run", "-v", workDirectory + ":" + ShellOperation.dockerDirectoryPath, "-i", "zokrates/zokrates", "/bin/bash"] self.logOutput = logOutput super.init() } - override init() { - - self.filename = "" - self.workDirectory = "" - self.logOutput = true - self.dockerArguments = ["run", "hello-world"] - - super.init() - } +// override init() { +// +// self.sourceFilename = "" +// self.workDirectory = "" +// self.arguments = "" +// self.logOutput = true +// +// super.init() +// } - /// Runs (and if needed, installs) Zokrates in a Docker image - /// Format is: docker run -v /Users/davidhasselhoff/Code/:/home/zokrates/playground -i zokrates/zokrates /bin/bash + /// Runs Zokrates override func main() { guard isCancelled == false else { return } + // Create build directory + if self.createBuildDirectory() == false { + assertionFailure() + return + } + // Set up task - // Exporting Zokrates paths - // export PATH=$PATH:$HOME/.zokrates/bin - // export ZOKRATES_HOME=$HOME/.zokrates/stdlib + // Exporting Zokrates paths in environment. May not be necessary let zokratesDirectory = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".zokrates") let zokratesBinPath = zokratesDirectory.appendingPathComponent("bin").path - let zokratesHomePath = zokratesDirectory.appendingPathComponent("stdlib").path +// let zokratesHomePath = zokratesDirectory.appendingPathComponent("stdlib").path +// self.task.environment = ProcessInfo().environment +// self.task.environment?.updateValue("/usr/local/bin/:/usr/bin:/bin:/usr/sbin:/sbin:\(zokratesBinPath)", forKey: "PATH") +// self.task.environment?.updateValue(zokratesHomePath, forKey: "ZOKRATES_HOME") - self.task.environment = ProcessInfo().environment - self.task.environment?.updateValue("/usr/local/bin/:/usr/bin:/bin:/usr/sbin:/sbin:\(zokratesBinPath):\(zokratesHomePath)", forKey: "PATH") - task.launchPath = "/usr/local/bin/docker" // TODO: use which path - task.arguments = self.dockerArguments - task.currentDirectoryPath = Bundle.main.bundlePath + // Set executable to Zokrates + self.task.executableURL = URL(fileURLWithPath: zokratesBinPath, isDirectory: true).appendingPathComponent("zokrates") - // Print to log - let command: String = task.launchPath ?? "" - let arguments: String = task.arguments?.joined(separator: " ") ?? "" - self.delegate?.shell(self, didReceiveStdin: "\n$ " + command + " " + arguments + "\n") + // currentDirectoryPath is the starting point for any relative path speficied. + // Set to the buildDirectory. + self.task.currentDirectoryPath = self.buildDirectory + + if self.logOutput { + + // Print to log + let path = task.currentDirectoryPath + let command: String = task.executableURL?.path ?? "" + let arguments: String = task.arguments?.joined(separator: " ") ?? "" + self.delegate?.shell(self, didReceiveStdin: "\n\(path)$ " + command + " " + arguments + "\n") + print("\n\(path)$ " + command + " " + arguments + "\n") + } // Set exitStatus at exit self.task.terminationHandler = { task in @@ -123,22 +124,28 @@ class ShellOperation: Operation { self.capture(self.stdoutPipe) { stdout in self.delegate?.shell(self, didReceiveStdout: stdout) - if self.logOutput == true { self.output += stdout } - - // print utf8 values + if self.logOutput == true { + self.output += stdout + print(stdout) + } + + // uncomment to print utf8 values // var s = "" // _ = stdout.utf8.map{ s.append("\($0), ") } -// self.delegate?.docker(self, didReceiveStdin: s) +// self.delegate?.shell(self, didReceiveStdin: s) } self.capture(self.stderrPipe) { stderr in self.delegate?.shell(self, didReceiveStderr: stderr) - if self.logOutput == true { self.output += stderr } + if self.logOutput == true { + self.output += stderr + print(stderr) + } } task.launch() -// self.task.waitUntilExit() // uncomment when testing Hello-world + self.task.waitUntilExit() // uncomment when testing Hello-world } private func capture(_ pipe: Pipe, dataReceived: @escaping (String) -> Void) { @@ -171,10 +178,8 @@ class ShellOperation: Operation { if wait == true { self.stdinPipe.fileHandleForWriting.waitForDataInBackgroundAndNotify() } } - /// Exits Docker override func cancel() { - // Send 'exit' command to docker if task.isRunning { task.interrupt() } self.stdinPipe.fileHandleForReading.closeFile() self.stderrPipe.fileHandleForReading.closeFile() @@ -182,9 +187,35 @@ class ShellOperation: Operation { super.cancel() } - fileprivate func copy(file: String) { //} -> Bool { + fileprivate func createBuildDirectory() -> Bool { + + // 1. Check if build directory exists + let manager = FileManager.default + var isDirectory: ObjCBool = false + if manager.fileExists(atPath: self.buildDirectory, isDirectory: &isDirectory) == false || isDirectory.boolValue == false { + + // Build directory does not exist. Create it + do { + try + manager.createDirectory(atPath: self.buildDirectory, withIntermediateDirectories: false, attributes: nil) + } catch { + NSAlert(error: error).runModal() + return false + } + } - self.write("cp " + file + " " + ShellOperation.dockerBuildPath) + // 2. Delete all files in the build directory + let enumerator = manager.enumerator(at: URL(fileURLWithPath: self.buildDirectory, isDirectory: true), includingPropertiesForKeys: nil) + while let file = enumerator?.nextObject() as? URL { + do { + try manager.removeItem(at: file) + } catch { + NSAlert(error: error).runModal() + return false + } + } + + return true } } @@ -194,16 +225,17 @@ class Lint: ShellOperation { override func main() { + self.task.arguments = ["compile", "-i", "../" + self.sourceFilename] super.main() - let command = "./zokrates compile -i " + self.dockerFilename + "; exit" - self.write(command) - self.task.waitUntilExit() +// let command = "cd " + self.buildDirectory + "; " + self.zokratesBinPath + "/zokrates compile -i ../" + self.filename +// self.write(command) +// self.task.waitUntilExit() } } /// Compiles and builds product and proofs -class Compile: ShellOperation { +/*class Compile: ShellOperation { let arguments: [String]? @@ -211,13 +243,19 @@ class Compile: ShellOperation { self.arguments = arguments - super.init(workDirectory: workDirectory, filename: filename) + super.init(workDirectory: workDirectory, sourceFilename: filename) } override func main() { super.main() + // 1. Create build directory + if self.createBuildDirectory() == false { + assertionFailure() + return + } + // 1. Set time format self.write("TIMEFORMAT='Elapsed time: %3R'") @@ -253,3 +291,4 @@ class Compile: ShellOperation { self.task.waitUntilExit() } } +*/ diff --git a/ZKPlayground/ViewController.swift b/ZKPlayground/ViewController.swift deleted file mode 100644 index ba5bf78..0000000 --- a/ZKPlayground/ViewController.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// ViewController.swift -// ZKPlayground -// -// Created by Ronald "Danger" Mannak on 3/20/19. -// Copyright © 2019 A Puzzle A Day. All rights reserved. -// - -import Cocoa - -class ViewController: NSViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - override var representedObject: Any? { - didSet { - // Update the view, if already loaded. - } - } - - -} - From ff04bfdf14669744aa6358fc22f0b8b64f650fa0 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Tue, 21 May 2019 17:54:44 -0700 Subject: [PATCH 04/15] Add zokrates is not installed warning --- ZKPlayground/AppDelegate.swift | 10 ++++------ ZKPlayground/ZKError.swift | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ZKPlayground/AppDelegate.swift b/ZKPlayground/AppDelegate.swift index b9fd451..187c05c 100644 --- a/ZKPlayground/AppDelegate.swift +++ b/ZKPlayground/AppDelegate.swift @@ -41,12 +41,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { if FileManager.default.isExecutableFile(atPath: zokratesPath) { return } // Zokrates is not installed - - // Run: - // curl -LSfs get.zokrat.es | sh - // export PATH=$PATH:$HOME/.zokrates/bin - // export ZOKRATES_HOME=$HOME/.zokrates/stdlib - + let alert = NSAlert() + alert.messageText = "Zokrates is not installed" + alert.informativeText = "run 'curl -LSfs get.zokrat.es | sh' in the terminal to install Zokrates" + alert.runModal() } @IBAction func showTemplates(_ sender: AnyObject?) { diff --git a/ZKPlayground/ZKError.swift b/ZKPlayground/ZKError.swift index c795ec9..a2b0a6e 100644 --- a/ZKPlayground/ZKError.swift +++ b/ZKPlayground/ZKError.swift @@ -8,7 +8,7 @@ import Foundation -enum ZKError: Error { +enum ZKError:LocalizedError { case fileNotFound(String) case directoryNotFound(String) case cannotOpenFile(String) @@ -18,4 +18,5 @@ enum ZKError: Error { case bashScriptFailed(String) case initError(String) case internalError(String) + } From 1d77b14fa7ff1e065165973689af68eb8d17841b Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Tue, 21 May 2019 23:06:32 -0700 Subject: [PATCH 05/15] Move lint to static function --- .../Editor Window/EditorViewController.swift | 2 +- .../Shell Operations/ShellOperation.swift | 28 ++++++------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/ZKPlayground/Editor Window/EditorViewController.swift b/ZKPlayground/Editor Window/EditorViewController.swift index 4106f46..349a3c6 100644 --- a/ZKPlayground/Editor Window/EditorViewController.swift +++ b/ZKPlayground/Editor Window/EditorViewController.swift @@ -44,7 +44,7 @@ class EditorViewController: NSViewController { document.save(nil) - let lint = Lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: true) + let lint = ShellOperation.lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: true) lint.completionBlock = { if lint.output.contains("Compilation failed:") { diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index 8eef323..b56b9c8 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -57,16 +57,6 @@ class ShellOperation: Operation { super.init() } -// override init() { -// -// self.sourceFilename = "" -// self.workDirectory = "" -// self.arguments = "" -// self.logOutput = true -// -// super.init() -// } - /// Runs Zokrates override func main() { @@ -219,19 +209,17 @@ class ShellOperation: Operation { } } -/// Compiles code, returns warnings and errors -/// ./zokrates compile -i playground/root.code -class Lint: ShellOperation { +// Convenience inits +extension ShellOperation { - override func main() { + /// Compiles code, returns warnings and errors + static func lint(workDirectory: String, sourceFilename: String, logOutput: Bool = true) -> ShellOperation { - self.task.arguments = ["compile", "-i", "../" + self.sourceFilename] - super.main() - -// let command = "cd " + self.buildDirectory + "; " + self.zokratesBinPath + "/zokrates compile -i ../" + self.filename -// self.write(command) -// self.task.waitUntilExit() + let operation = ShellOperation(workDirectory: workDirectory, sourceFilename: sourceFilename, logOutput: logOutput) + operation.task.arguments = ["compile", "-i", "../" + operation.sourceFilename] + return operation } + } /// Compiles and builds product and proofs From 355c0d93dc7a55d3d9a87644c134073efcf07fa1 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Tue, 21 May 2019 23:51:21 -0700 Subject: [PATCH 06/15] Refactor compile operations --- .../Shell Operations/ShellOperation.swift | 107 +++++++++--------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index b56b9c8..6cc5a89 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -43,14 +43,11 @@ class ShellOperation: Operation { private let stdinPipe = Pipe() private var notifications = [NSObjectProtocol]() - /// Name of the .code file, e.g. "HelloWorld.code" - fileprivate let sourceFilename: String fileprivate let workDirectory: String var buildDirectory: String { return URL(fileURLWithPath: self.workDirectory).appendingPathComponent("build").path } - init(workDirectory: String, sourceFilename: String, logOutput: Bool = true) { + init(workDirectory: String, logOutput: Bool = true) { - self.sourceFilename = sourceFilename self.workDirectory = workDirectory self.logOutput = logOutput @@ -212,71 +209,75 @@ class ShellOperation: Operation { // Convenience inits extension ShellOperation { - /// Compiles code, returns warnings and errors - static func lint(workDirectory: String, sourceFilename: String, logOutput: Bool = true) -> ShellOperation { + private static func assemble(arguments: [String], workDirectory: String, logOutput: Bool = true) -> ShellOperation { - let operation = ShellOperation(workDirectory: workDirectory, sourceFilename: sourceFilename, logOutput: logOutput) - operation.task.arguments = ["compile", "-i", "../" + operation.sourceFilename] + let operation = ShellOperation(workDirectory: workDirectory, logOutput: logOutput) + operation.task.arguments = arguments return operation } -} - -/// Compiles and builds product and proofs -/*class Compile: ShellOperation { - - let arguments: [String]? - - init(workDirectory: String, filename: String, arguments: [String]?) { + /// Compiles code, returns warnings and errors + static func lint(workDirectory: String, sourceFilename: String, logOutput: Bool = false) -> ShellOperation { - self.arguments = arguments + // TODO: don't delete the other files in the build directory - super.init(workDirectory: workDirectory, sourceFilename: filename) + return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, logOutput: logOutput) } - override func main() { + static func build(workDirectory: String, arguments: [String]?, sourceFilename: String, logOutput: Bool = true) -> [ShellOperation] { - super.main() + let compileOperation = compile(workDirectory: workDirectory, sourceFilename: sourceFilename, logOutput: logOutput) + let witnessOperation = witness(arguments: arguments, workDirectory: workDirectory, logOutput: logOutput) + let setupOperation = setup(workDirectory: workDirectory, logOutput: logOutput) + let verifierOperation = verifier(workDirectory: workDirectory, logOutput: logOutput) + let proofOperation = proof(workDirectory: workDirectory, logOutput: logOutput) - // 1. Create build directory - if self.createBuildDirectory() == false { - assertionFailure() - return - } + // Add dependencies, so operations are executed in the right order + proofOperation.addDependency(verifierOperation) + verifierOperation.addDependency(setupOperation) + setupOperation.addDependency(witnessOperation) + witnessOperation.addDependency(compileOperation) - // 1. Set time format - self.write("TIMEFORMAT='Elapsed time: %3R'") + return [compileOperation, witnessOperation, setupOperation, verifierOperation, proofOperation] + } + + /// Compiles code + static func compile(workDirectory: String, sourceFilename: String, logOutput: Bool = true) -> ShellOperation { - // 2. Compile - self.write("time ./zokrates compile -i " + self.dockerFilename) - copy(file: "out") - copy(file: "out.code") + // TODO: don't delete the other files in the build directory - // 3. Setup - self.write("time ./zokrates setup") - copy(file: "proving.key") - copy(file: "variables.inf") - copy(file: "verification.key") + return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, logOutput: logOutput) + } + + /// Computes a witness for the compiled program found at ./out.code and arguments to the program. + static func witness(arguments: [String]? = nil, workDirectory: String, logOutput: Bool = true) -> ShellOperation { - // 4. Compute witness - var command = "time ./zokrates compute-witness" - if let arguments = self.arguments { - command += " -a " - _ = arguments.map{ command.append($0 + " ") } + var args = ["compute-witness"] + if let arguments = arguments { + args.append("-a") + args.append(contentsOf: arguments) } - self.write(command) - copy(file: "witness") - - // 5. Generate proof - self.write("time ./zokrates generate-proof") - copy(file: "proof.json") - // copy verifier - self.write("time ./zokrates export-verifier") - copy(file: "verifier.sol") + return assemble(arguments: args, workDirectory: workDirectory, logOutput: logOutput) + } + + /// Generates a trusted setup for the compiled program found at ./out.code + /// Creates a proving key and a verifying key at ./proving.key and ./verifying.key. These keys are derived from a source of randomness, commonly referred to as “toxic waste”. Anyone having access to the source of randomness can produce fake proofs that will be accepted by a verifier following the protocol. + static func setup(workDirectory: String, logOutput: Bool = true) -> ShellOperation { + + return assemble(arguments: ["setup"], workDirectory: workDirectory, logOutput: logOutput) + } + + /// Using the verifying key at ./verifying.key, generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program at ./out.code. + /// Creates a verifier contract at ./verifier.sol. + static func verifier(workDirectory: String, logOutput: Bool = true) -> ShellOperation { + + return assemble(arguments: ["export-verifier"], workDirectory: workDirectory, logOutput: logOutput) + } + + /// Using the proving key at ./proving.key, generates a proof for a computation of the compiled program ./out.code resulting in ./witness. + static func proof(workDirectory: String, logOutput: Bool = true) -> ShellOperation { - self.write("exit") - self.task.waitUntilExit() + return assemble(arguments: ["generate-proof"], workDirectory: workDirectory, logOutput: logOutput) } } -*/ From 5d031940e11a4c0bbe7ab626cd4328654c465d82 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Thu, 23 May 2019 11:48:20 -0700 Subject: [PATCH 07/15] Fix build phases --- .../EditorWindowController.swift | 58 +++++-------------- ZKPlayground/Extensions/TimeInterval.swift | 4 +- .../Shell Operations/ShellOperation.swift | 31 +++++----- 3 files changed, 33 insertions(+), 60 deletions(-) diff --git a/ZKPlayground/Editor Window/EditorWindowController.swift b/ZKPlayground/Editor Window/EditorWindowController.swift index c8da240..9072122 100644 --- a/ZKPlayground/Editor Window/EditorWindowController.swift +++ b/ZKPlayground/Editor Window/EditorWindowController.swift @@ -60,7 +60,7 @@ class EditorWindowController: NSWindowController { extension EditorWindowController { @IBAction func compile(_ sender: Any?) { - /* + // 1. Sanity check guard let document = document as? Document else { return assertionFailure() } @@ -78,56 +78,24 @@ extension EditorWindowController { // 3. Save document and reset buildphases document.save(self) - document.buildPhases = nil + document.buildPhases = [BuildPhase]() - // 6. Create and queue compile operation - let compile = Compile(workDirectory: workDirectory, filename: filename, arguments: self.inspectorViewController.arguments) - compile.delegate = self - compile.completionBlock = { - - // 5.a Fetch time measurements - let times = TimeInterval.parse(compile.output) - - // 5.b Set BuildPhases - var phases = [BuildPhase]() - for index in 0 ..< 5 { - - var phase: BuildPhaseType { - switch index { - case 0: - return .compile - case 1: - return .setup - case 2: - return .witness - case 3: - return .proof - case 4: - return .verifier - default: - assertionFailure() - return .verifier - } - } - - let buildPhase: BuildPhase - if times.count > index { - // Phase completed successfully - buildPhase = BuildPhase(phase: phase, workDirectory: workDirectory, elapsedTime: times[index]) - } else { - // Error - buildPhase = BuildPhase(phase: phase, workDirectory: workDirectory, elapsedTime: nil, errorMessage: "Error") - } - phases.append(buildPhase) + // 6. Create and queue compile operations + let compileOperations = ShellOperation.build(workDirectory: workDirectory, arguments: self.inspectorViewController.arguments, sourceFilename: filename) + + for operation in compileOperations { + operation.delegate = self + operation.completionBlock = { + let buildPhase = BuildPhase(phase: operation.buildPhaseType, workDirectory: workDirectory, elapsedTime: operation.executionTime , errorMessage: operation.exitStatus == 0 ? nil : "Error") + document.buildPhases!.append(buildPhase) } - - document.buildPhases = phases } - compileQueue.addOperation(compile) */ + compileQueue.addOperations(compileOperations, waitUntilFinished: false) + } @IBAction func stop(_ sender: Any?) { - + print("Not implemented") } } diff --git a/ZKPlayground/Extensions/TimeInterval.swift b/ZKPlayground/Extensions/TimeInterval.swift index 4626e99..2fcb0ac 100644 --- a/ZKPlayground/Extensions/TimeInterval.swift +++ b/ZKPlayground/Extensions/TimeInterval.swift @@ -18,7 +18,7 @@ extension TimeInterval { /// Bash time format set to: TIMEFORMAT='Elapsed time: %3R' /// Example: "Elapsed time: 0.003" /// - Returns: Array of timeintervals - static func parse(_ string: String) -> [TimeInterval] { +/* static func parse(_ string: String) -> [TimeInterval] { let regex = try! NSRegularExpression(pattern: "(?<=Elapsed time\\:\\s)[0-9]{1,2}+\\.[0-9]{1,3}", options: []) @@ -27,5 +27,5 @@ extension TimeInterval { return matches.compactMap{ return TimeInterval(String(string.substring(with: $0.range(at: 0)) ?? "")) ?? nil } - } + } */ } diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index 6cc5a89..c9e6f7f 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -31,10 +31,14 @@ class ShellOperation: Operation { /// http://www.tldp.org/LDP/abs/html/exitcodes.html private (set) var exitStatus: Int? + private (set) var executionTime: TimeInterval? + // If true, output will be stored in output property private let logOutput: Bool private (set) var output = "" + let buildPhaseType: BuildPhaseType + fileprivate let task = Process() @@ -46,9 +50,10 @@ class ShellOperation: Operation { fileprivate let workDirectory: String var buildDirectory: String { return URL(fileURLWithPath: self.workDirectory).appendingPathComponent("build").path } - init(workDirectory: String, logOutput: Bool = true) { + init(workDirectory: String, buildPhase: BuildPhaseType, logOutput: Bool = true) { self.workDirectory = workDirectory + self.buildPhaseType = buildPhase self.logOutput = logOutput super.init() @@ -59,6 +64,8 @@ class ShellOperation: Operation { guard isCancelled == false else { return } + let startTime = DispatchTime.now() + // Create build directory if self.createBuildDirectory() == false { assertionFailure() @@ -70,10 +77,6 @@ class ShellOperation: Operation { // Exporting Zokrates paths in environment. May not be necessary let zokratesDirectory = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".zokrates") let zokratesBinPath = zokratesDirectory.appendingPathComponent("bin").path -// let zokratesHomePath = zokratesDirectory.appendingPathComponent("stdlib").path -// self.task.environment = ProcessInfo().environment -// self.task.environment?.updateValue("/usr/local/bin/:/usr/bin:/bin:/usr/sbin:/sbin:\(zokratesBinPath)", forKey: "PATH") -// self.task.environment?.updateValue(zokratesHomePath, forKey: "ZOKRATES_HOME") // Set executable to Zokrates self.task.executableURL = URL(fileURLWithPath: zokratesBinPath, isDirectory: true).appendingPathComponent("zokrates") @@ -133,6 +136,8 @@ class ShellOperation: Operation { task.launch() self.task.waitUntilExit() // uncomment when testing Hello-world + let endTime = DispatchTime.now() + self.executionTime = TimeInterval(endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) } private func capture(_ pipe: Pipe, dataReceived: @escaping (String) -> Void) { @@ -209,9 +214,9 @@ class ShellOperation: Operation { // Convenience inits extension ShellOperation { - private static func assemble(arguments: [String], workDirectory: String, logOutput: Bool = true) -> ShellOperation { + private static func assemble(arguments: [String], workDirectory: String, buildPhase: BuildPhaseType, logOutput: Bool = true) -> ShellOperation { - let operation = ShellOperation(workDirectory: workDirectory, logOutput: logOutput) + let operation = ShellOperation(workDirectory: workDirectory, buildPhase: buildPhase, logOutput: logOutput) operation.task.arguments = arguments return operation } @@ -221,7 +226,7 @@ extension ShellOperation { // TODO: don't delete the other files in the build directory - return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, logOutput: logOutput) + return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, buildPhase: .compile, logOutput: logOutput) } static func build(workDirectory: String, arguments: [String]?, sourceFilename: String, logOutput: Bool = true) -> [ShellOperation] { @@ -246,7 +251,7 @@ extension ShellOperation { // TODO: don't delete the other files in the build directory - return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, logOutput: logOutput) + return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, buildPhase: .compile, logOutput: logOutput) } /// Computes a witness for the compiled program found at ./out.code and arguments to the program. @@ -258,26 +263,26 @@ extension ShellOperation { args.append(contentsOf: arguments) } - return assemble(arguments: args, workDirectory: workDirectory, logOutput: logOutput) + return assemble(arguments: args, workDirectory: workDirectory, buildPhase: .witness, logOutput: logOutput) } /// Generates a trusted setup for the compiled program found at ./out.code /// Creates a proving key and a verifying key at ./proving.key and ./verifying.key. These keys are derived from a source of randomness, commonly referred to as “toxic waste”. Anyone having access to the source of randomness can produce fake proofs that will be accepted by a verifier following the protocol. static func setup(workDirectory: String, logOutput: Bool = true) -> ShellOperation { - return assemble(arguments: ["setup"], workDirectory: workDirectory, logOutput: logOutput) + return assemble(arguments: ["setup"], workDirectory: workDirectory, buildPhase: .setup, logOutput: logOutput) } /// Using the verifying key at ./verifying.key, generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program at ./out.code. /// Creates a verifier contract at ./verifier.sol. static func verifier(workDirectory: String, logOutput: Bool = true) -> ShellOperation { - return assemble(arguments: ["export-verifier"], workDirectory: workDirectory, logOutput: logOutput) + return assemble(arguments: ["export-verifier"], workDirectory: workDirectory, buildPhase: .verifier, logOutput: logOutput) } /// Using the proving key at ./proving.key, generates a proof for a computation of the compiled program ./out.code resulting in ./witness. static func proof(workDirectory: String, logOutput: Bool = true) -> ShellOperation { - return assemble(arguments: ["generate-proof"], workDirectory: workDirectory, logOutput: logOutput) + return assemble(arguments: ["generate-proof"], workDirectory: workDirectory, buildPhase: .proof, logOutput: logOutput) } } From 724b029fe05ad582eff4d305e0acbaef91ce7779 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Thu, 23 May 2019 12:05:07 -0700 Subject: [PATCH 08/15] Fix execution time --- .../Shell Operations/ShellOperation.swift | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index c9e6f7f..0dbe483 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -64,13 +64,7 @@ class ShellOperation: Operation { guard isCancelled == false else { return } - let startTime = DispatchTime.now() - - // Create build directory - if self.createBuildDirectory() == false { - assertionFailure() - return - } + let startTime = Date() // Set up task @@ -135,9 +129,8 @@ class ShellOperation: Operation { } task.launch() - self.task.waitUntilExit() // uncomment when testing Hello-world - let endTime = DispatchTime.now() - self.executionTime = TimeInterval(endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) + self.task.waitUntilExit() // uncomment when testing Hello-world + self.executionTime = Date().timeIntervalSince(startTime) } private func capture(_ pipe: Pipe, dataReceived: @escaping (String) -> Void) { @@ -218,6 +211,12 @@ extension ShellOperation { let operation = ShellOperation(workDirectory: workDirectory, buildPhase: buildPhase, logOutput: logOutput) operation.task.arguments = arguments + + // Create build directory + if operation.createBuildDirectory() == false { + assertionFailure() + } + return operation } From c7d20e7e5bebaa9a408c45ab963fea551980473b Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Thu, 23 May 2019 12:50:09 -0700 Subject: [PATCH 09/15] Fix operation order --- ZKPlayground/BuildPhase.swift | 2 +- .../EditorWindowController.swift | 2 ++ .../Inspector/InspectorViewController.swift | 2 +- .../Shell Operations/ShellOperation.swift | 20 +++++++++---------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ZKPlayground/BuildPhase.swift b/ZKPlayground/BuildPhase.swift index 17ee973..b4ad2e0 100644 --- a/ZKPlayground/BuildPhase.swift +++ b/ZKPlayground/BuildPhase.swift @@ -85,7 +85,7 @@ enum BuildPhaseType: String { case .compile: return ["out", "out.code"] case .setup: - return ["proving.key", "variables.inf", "verification.key"] + return ["proving.key", "verification.key"] // "variables.inf" case .witness: return ["witness"] case .proof: diff --git a/ZKPlayground/Editor Window/EditorWindowController.swift b/ZKPlayground/Editor Window/EditorWindowController.swift index 9072122..f43520c 100644 --- a/ZKPlayground/Editor Window/EditorWindowController.swift +++ b/ZKPlayground/Editor Window/EditorWindowController.swift @@ -86,7 +86,9 @@ extension EditorWindowController { for operation in compileOperations { operation.delegate = self operation.completionBlock = { + let buildPhase = BuildPhase(phase: operation.buildPhaseType, workDirectory: workDirectory, elapsedTime: operation.executionTime , errorMessage: operation.exitStatus == 0 ? nil : "Error") + print(buildPhase) document.buildPhases!.append(buildPhase) } } diff --git a/ZKPlayground/Editor Window/Inspector/InspectorViewController.swift b/ZKPlayground/Editor Window/Inspector/InspectorViewController.swift index ac73ea0..0e8e019 100644 --- a/ZKPlayground/Editor Window/Inspector/InspectorViewController.swift +++ b/ZKPlayground/Editor Window/Inspector/InspectorViewController.swift @@ -117,7 +117,7 @@ class InspectorViewController: NSViewController { // Phase was successful buildPhaseView.titleLabel.stringValue = "✅ " + phase.name - buildPhaseView.timeLabel.stringValue = phase.elapsedTime == nil ? " " : "\(phase.elapsedTime!)s" + buildPhaseView.timeLabel.stringValue = phase.elapsedTime == nil ? " " : String(format: "%.2fs", phase.elapsedTime!) if let result = phase.fetchCompilerResult() { buildPhaseView.textField.stringValue = result buildPhaseView.textField.isHidden = false diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index 0dbe483..be79f6f 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -129,7 +129,7 @@ class ShellOperation: Operation { } task.launch() - self.task.waitUntilExit() // uncomment when testing Hello-world + self.task.waitUntilExit() // uncomment when testing Hello-world self.executionTime = Date().timeIntervalSince(startTime) } @@ -212,11 +212,6 @@ extension ShellOperation { let operation = ShellOperation(workDirectory: workDirectory, buildPhase: buildPhase, logOutput: logOutput) operation.task.arguments = arguments - // Create build directory - if operation.createBuildDirectory() == false { - assertionFailure() - } - return operation } @@ -237,12 +232,17 @@ extension ShellOperation { let proofOperation = proof(workDirectory: workDirectory, logOutput: logOutput) // Add dependencies, so operations are executed in the right order + setupOperation.addDependency(compileOperation) + witnessOperation.addDependency(setupOperation) + verifierOperation.addDependency(witnessOperation) proofOperation.addDependency(verifierOperation) - verifierOperation.addDependency(setupOperation) - setupOperation.addDependency(witnessOperation) - witnessOperation.addDependency(compileOperation) - return [compileOperation, witnessOperation, setupOperation, verifierOperation, proofOperation] + // Create build directory + if compileOperation.createBuildDirectory() == false { + assertionFailure() + } + + return [compileOperation, setupOperation, witnessOperation, verifierOperation, proofOperation] } /// Compiles code From 82adc956a68512683e74d9ff68fc4e48c9935b22 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Fri, 24 May 2019 10:34:12 -0700 Subject: [PATCH 10/15] Added as to lexer --- ZKPlayground/Editor Window/ZokratesLexer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZKPlayground/Editor Window/ZokratesLexer.swift b/ZKPlayground/Editor Window/ZokratesLexer.swift index 3524547..dd68d09 100644 --- a/ZKPlayground/Editor Window/ZokratesLexer.swift +++ b/ZKPlayground/Editor Window/ZokratesLexer.swift @@ -26,7 +26,7 @@ public class ZokratesLexer: SourceCodeRegexLexer { generators.append(regexGenerator("\\.\\w+", tokenType: .identifier)) - let keywords = "import def return for in endfor if fi".components(separatedBy: " ") + let keywords = "import def return for in endfor if fi as".components(separatedBy: " ") generators.append(keywordGenerator(keywords, tokenType: .keyword)) From 43f0774eff78a0f3839f541395211fcf9aebffd3 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Fri, 24 May 2019 10:54:31 -0700 Subject: [PATCH 11/15] Add home path, fix log output to background thread --- .../EditorWindowController.swift | 24 ++++++++++++------- .../Shell Operations/ShellOperation.swift | 6 ++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ZKPlayground/Editor Window/EditorWindowController.swift b/ZKPlayground/Editor Window/EditorWindowController.swift index f43520c..bea871a 100644 --- a/ZKPlayground/Editor Window/EditorWindowController.swift +++ b/ZKPlayground/Editor Window/EditorWindowController.swift @@ -86,10 +86,11 @@ extension EditorWindowController { for operation in compileOperations { operation.delegate = self operation.completionBlock = { - - let buildPhase = BuildPhase(phase: operation.buildPhaseType, workDirectory: workDirectory, elapsedTime: operation.executionTime , errorMessage: operation.exitStatus == 0 ? nil : "Error") - print(buildPhase) - document.buildPhases!.append(buildPhase) + DispatchQueue.main.sync { + let buildPhase = BuildPhase(phase: operation.buildPhaseType, workDirectory: workDirectory, elapsedTime: operation.executionTime , errorMessage: operation.exitStatus == 0 ? nil : "Error") + print(buildPhase) + document.buildPhases!.append(buildPhase) + } } } compileQueue.addOperations(compileOperations, waitUntilFinished: false) @@ -104,26 +105,31 @@ extension EditorWindowController { // Docker delegate extension EditorWindowController: ShellProtocol { func shell(_ docker: ShellOperation, didReceiveStdout string: String) { - self.logViewController.stdout(string) + + DispatchQueue.main.sync { + self.logViewController.stdout(string) + } } func shell(_ docker: ShellOperation, didReceiveStderr string: String) { // Open log pane - DispatchQueue.main.async { + DispatchQueue.main.sync { let item = (self.contentViewController as! NSSplitViewController).splitViewItems[2] if item.isCollapsed { self.statusViewController.disclosureClicked(self) self.statusViewController.disclosureButton.state = .on } + self.logViewController.stderr(string) } - - self.logViewController.stderr(string) } func shell(_ docker: ShellOperation, didReceiveStdin string: String) { - self.logViewController.stdin(string) + + DispatchQueue.main.sync { + self.logViewController.stdin(string) + } } } diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index be79f6f..799402c 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -68,9 +68,13 @@ class ShellOperation: Operation { // Set up task - // Exporting Zokrates paths in environment. May not be necessary + // Exporting Zokrates paths in environment. let zokratesDirectory = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".zokrates") let zokratesBinPath = zokratesDirectory.appendingPathComponent("bin").path + self.task.environment = ProcessInfo().environment + self.task.environment?.updateValue("/usr/local/bin/:/usr/bin:/bin:/usr/sbin:/sbin:\(zokratesBinPath)", forKey: "PATH") + let zokratesHomePath = zokratesDirectory.appendingPathComponent("stdlib").path + self.task.environment?.updateValue(zokratesHomePath, forKey: "ZOKRATES_HOME") // Set executable to Zokrates self.task.executableURL = URL(fileURLWithPath: zokratesBinPath, isDirectory: true).appendingPathComponent("zokrates") From 8ba89bff5fbac82fbaa79d4b86be7a345189d458 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Fri, 24 May 2019 11:28:01 -0700 Subject: [PATCH 12/15] Optimized output for large outputs --- .../Editor Window/EditorViewController.swift | 4 +- .../EditorWindowController.swift | 2 +- .../Shell Operations/ShellOperation.swift | 43 +++++++++++-------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/ZKPlayground/Editor Window/EditorViewController.swift b/ZKPlayground/Editor Window/EditorViewController.swift index 349a3c6..755c495 100644 --- a/ZKPlayground/Editor Window/EditorViewController.swift +++ b/ZKPlayground/Editor Window/EditorViewController.swift @@ -36,7 +36,7 @@ class EditorViewController: NSViewController { } @objc fileprivate func lint(_ sender: Any?) { - + return // ***REMOVE guard let document = representedObject as? Document, let filename = document.fileURL?.lastPathComponent, let workDirectory = document.fileURL?.deletingLastPathComponent().path @@ -44,7 +44,7 @@ class EditorViewController: NSViewController { document.save(nil) - let lint = ShellOperation.lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: true) + let lint = ShellOperation.lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: .none) lint.completionBlock = { if lint.output.contains("Compilation failed:") { diff --git a/ZKPlayground/Editor Window/EditorWindowController.swift b/ZKPlayground/Editor Window/EditorWindowController.swift index bea871a..0d33a01 100644 --- a/ZKPlayground/Editor Window/EditorWindowController.swift +++ b/ZKPlayground/Editor Window/EditorWindowController.swift @@ -81,7 +81,7 @@ extension EditorWindowController { document.buildPhases = [BuildPhase]() // 6. Create and queue compile operations - let compileOperations = ShellOperation.build(workDirectory: workDirectory, arguments: self.inspectorViewController.arguments, sourceFilename: filename) + let compileOperations = ShellOperation.build(workDirectory: workDirectory, arguments: self.inspectorViewController.arguments, sourceFilename: filename, logOutput: .inputOnly) for operation in compileOperations { operation.delegate = self diff --git a/ZKPlayground/Shell Operations/ShellOperation.swift b/ZKPlayground/Shell Operations/ShellOperation.swift index 799402c..5116122 100644 --- a/ZKPlayground/Shell Operations/ShellOperation.swift +++ b/ZKPlayground/Shell Operations/ShellOperation.swift @@ -21,6 +21,13 @@ protocol ShellProtocol: class { func shell(_ shell: ShellOperation, didReceiveStdin string: String) } +enum LogLevel { + + case none // Nothing will be logged + case inputOnly // Only input (e.g. commands) will be logged + case all // Everything will be logged +} + class ShellOperation: Operation { weak var delegate: ShellProtocol? @@ -33,13 +40,11 @@ class ShellOperation: Operation { private (set) var executionTime: TimeInterval? - // If true, output will be stored in output property - private let logOutput: Bool + private let logOutput: LogLevel private (set) var output = "" let buildPhaseType: BuildPhaseType - fileprivate let task = Process() private let stdoutPipe = Pipe() @@ -50,7 +55,7 @@ class ShellOperation: Operation { fileprivate let workDirectory: String var buildDirectory: String { return URL(fileURLWithPath: self.workDirectory).appendingPathComponent("build").path } - init(workDirectory: String, buildPhase: BuildPhaseType, logOutput: Bool = true) { + init(workDirectory: String, buildPhase: BuildPhaseType, logOutput: LogLevel = .all) { self.workDirectory = workDirectory self.buildPhaseType = buildPhase @@ -83,7 +88,7 @@ class ShellOperation: Operation { // Set to the buildDirectory. self.task.currentDirectoryPath = self.buildDirectory - if self.logOutput { + if self.logOutput != .none { // Print to log let path = task.currentDirectoryPath @@ -111,8 +116,8 @@ class ShellOperation: Operation { self.capture(self.stdoutPipe) { stdout in - self.delegate?.shell(self, didReceiveStdout: stdout) - if self.logOutput == true { + if self.logOutput == .all { + self.delegate?.shell(self, didReceiveStdout: stdout) self.output += stdout print(stdout) } @@ -125,11 +130,11 @@ class ShellOperation: Operation { self.capture(self.stderrPipe) { stderr in + guard self.logOutput != .none else { return } + self.delegate?.shell(self, didReceiveStderr: stderr) - if self.logOutput == true { - self.output += stderr - print(stderr) - } + self.output += stderr + print(stderr) } task.launch() @@ -211,7 +216,7 @@ class ShellOperation: Operation { // Convenience inits extension ShellOperation { - private static func assemble(arguments: [String], workDirectory: String, buildPhase: BuildPhaseType, logOutput: Bool = true) -> ShellOperation { + private static func assemble(arguments: [String], workDirectory: String, buildPhase: BuildPhaseType, logOutput: LogLevel = .all) -> ShellOperation { let operation = ShellOperation(workDirectory: workDirectory, buildPhase: buildPhase, logOutput: logOutput) operation.task.arguments = arguments @@ -220,14 +225,14 @@ extension ShellOperation { } /// Compiles code, returns warnings and errors - static func lint(workDirectory: String, sourceFilename: String, logOutput: Bool = false) -> ShellOperation { + static func lint(workDirectory: String, sourceFilename: String, logOutput: LogLevel = .all) -> ShellOperation { // TODO: don't delete the other files in the build directory return assemble(arguments: ["compile", "-i", "../" + sourceFilename], workDirectory: workDirectory, buildPhase: .compile, logOutput: logOutput) } - static func build(workDirectory: String, arguments: [String]?, sourceFilename: String, logOutput: Bool = true) -> [ShellOperation] { + static func build(workDirectory: String, arguments: [String]?, sourceFilename: String, logOutput: LogLevel = .all) -> [ShellOperation] { let compileOperation = compile(workDirectory: workDirectory, sourceFilename: sourceFilename, logOutput: logOutput) let witnessOperation = witness(arguments: arguments, workDirectory: workDirectory, logOutput: logOutput) @@ -250,7 +255,7 @@ extension ShellOperation { } /// Compiles code - static func compile(workDirectory: String, sourceFilename: String, logOutput: Bool = true) -> ShellOperation { + static func compile(workDirectory: String, sourceFilename: String, logOutput: LogLevel = .all) -> ShellOperation { // TODO: don't delete the other files in the build directory @@ -258,7 +263,7 @@ extension ShellOperation { } /// Computes a witness for the compiled program found at ./out.code and arguments to the program. - static func witness(arguments: [String]? = nil, workDirectory: String, logOutput: Bool = true) -> ShellOperation { + static func witness(arguments: [String]? = nil, workDirectory: String, logOutput: LogLevel = .all) -> ShellOperation { var args = ["compute-witness"] if let arguments = arguments { @@ -271,20 +276,20 @@ extension ShellOperation { /// Generates a trusted setup for the compiled program found at ./out.code /// Creates a proving key and a verifying key at ./proving.key and ./verifying.key. These keys are derived from a source of randomness, commonly referred to as “toxic waste”. Anyone having access to the source of randomness can produce fake proofs that will be accepted by a verifier following the protocol. - static func setup(workDirectory: String, logOutput: Bool = true) -> ShellOperation { + static func setup(workDirectory: String, logOutput: LogLevel = .all) -> ShellOperation { return assemble(arguments: ["setup"], workDirectory: workDirectory, buildPhase: .setup, logOutput: logOutput) } /// Using the verifying key at ./verifying.key, generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program at ./out.code. /// Creates a verifier contract at ./verifier.sol. - static func verifier(workDirectory: String, logOutput: Bool = true) -> ShellOperation { + static func verifier(workDirectory: String, logOutput: LogLevel = .all) -> ShellOperation { return assemble(arguments: ["export-verifier"], workDirectory: workDirectory, buildPhase: .verifier, logOutput: logOutput) } /// Using the proving key at ./proving.key, generates a proof for a computation of the compiled program ./out.code resulting in ./witness. - static func proof(workDirectory: String, logOutput: Bool = true) -> ShellOperation { + static func proof(workDirectory: String, logOutput: LogLevel = .all) -> ShellOperation { return assemble(arguments: ["generate-proof"], workDirectory: workDirectory, buildPhase: .proof, logOutput: logOutput) } From 8fd6136ce134bc3a4ca2e256754be6a8c7421bda Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Fri, 24 May 2019 12:51:23 -0700 Subject: [PATCH 13/15] Reenable auto-linting --- ZKPlayground/Editor Window/EditorViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZKPlayground/Editor Window/EditorViewController.swift b/ZKPlayground/Editor Window/EditorViewController.swift index 755c495..70d460a 100644 --- a/ZKPlayground/Editor Window/EditorViewController.swift +++ b/ZKPlayground/Editor Window/EditorViewController.swift @@ -36,7 +36,7 @@ class EditorViewController: NSViewController { } @objc fileprivate func lint(_ sender: Any?) { - return // ***REMOVE + guard let document = representedObject as? Document, let filename = document.fileURL?.lastPathComponent, let workDirectory = document.fileURL?.deletingLastPathComponent().path From f782d2e041e39e5dcc4e405dc20fea3aa2433810 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Fri, 24 May 2019 14:21:42 -0700 Subject: [PATCH 14/15] Update lint --- ZKPlayground/Editor Window/EditorViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ZKPlayground/Editor Window/EditorViewController.swift b/ZKPlayground/Editor Window/EditorViewController.swift index 70d460a..119acfa 100644 --- a/ZKPlayground/Editor Window/EditorViewController.swift +++ b/ZKPlayground/Editor Window/EditorViewController.swift @@ -44,7 +44,7 @@ class EditorViewController: NSViewController { document.save(nil) - let lint = ShellOperation.lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: .none) + let lint = ShellOperation.lint(workDirectory: workDirectory, sourceFilename: filename, logOutput: .all) lint.completionBlock = { if lint.output.contains("Compilation failed:") { From 2497d981717ecdc32e0d3afa645a89ac337af752 Mon Sep 17 00:00:00 2001 From: Ronald Mannak Date: Fri, 24 May 2019 14:40:24 -0700 Subject: [PATCH 15/15] Update version number to 0.14 --- ZKPlayground/Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ZKPlayground/Info.plist b/ZKPlayground/Info.plist index ce1e2cf..49c1422 100644 --- a/ZKPlayground/Info.plist +++ b/ZKPlayground/Info.plist @@ -38,9 +38,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.13 + 0.14 CFBundleVersion - 4 + 5 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion