 So, today's next speaker will tell us more about the glorious future where machine-checked proofs will be used in everyday software all the way down to our redevelopment. We have Adam Cipalla. Ja, und damit auch herzlich willkommen aus der Übersetzer-Kabine, du hörst gleich bald verfügbar, maschinell geprüfte, mathematische Beweise in der tagtäglichen Software und Hardware-Entwicklung Übersetzung von Pink Dispatcher und Tribut. Ja, also von den ersten Anfängen von Programmierung haben Leute festgestellt, dass es eine relativ kurze Menge der Zeit ist, die sie verbringen, den tatsächlich einen Code zu schreiben. Hier ist ein Zitat von jemandem, einem Pionier der Computerwissenschaften, als er festgestellt hat, dass ein großer Teil seines Tages damit verbracht werden wird, den Code zu korrigieren, und ein wichtiger Teil von Arbeit ist jetzt, den Code, die Zeit zu reduzieren, die man braucht, um fehlerhaften Code zu regieren. Und ich will jetzt erzählen über Technologien, die letztendlich einen großen Einfluss haben werden, hier Zeit zu sparen, beim Versuch korrekte Systeme zu bauen. Und ich denke, die sind jetzt gerade so weit fertig, dass wenn man ganz vorne mit dabei sein will, dann kann man jetzt anfangen, die zu benutzen. Also eine kurze Perspektive darauf, was Programmierer machen, um sicher zu sein, dass ihr Code korrekt ist. Da gibt es klassisches Debugging, man macht also quasi Detektivarbeit, führt das Programm mehrfach aus, ändert eine Kleinigkeit, sieht, was sich ändert, und ich werde es hier auf einem kleinen Graf auf zwei Achsen mal darstellen, wo es also darum geht, wie intensiv auf der X-Achse und mit Vollständigkeit, also wie vollständig, wie viele verschiedene Szenarien hat man, um da Garantien zu bekommen. Und beim Debuggen, da kriegt man also quasi nur über die Szenarien, die wir tatsächlich ausführen, Sicherheit, also wenig kommt Vollständigkeit, aber man weiß eben sehr viel genau. Und wenn man jetzt ein Programm schreibt, dann muss man über sehr viele Dinge nachdenken, alle diese Dinge, die passieren können, oder man muss eben an zusätzlichen Koten zufügen, um darauf vorbereitet sein, was alles passieren kann. Und durch diesen Designprozess kriegt man also hohe Grad an Vollständigkeit, aber es ist sehr unsicher. Testen, das ist sowas ganz ähnlich wie Debuggen. Eine Alternative ist das Programm mit ganz vielen Kommentaren zu versehen, um die Erwartungen aufzuschreiben, die man erwartet, wenn das Programm an dieser Stelle ankommt. Und dann liest man sich das durch und prüft diese ganzen Erwartungen. Und das kann jetzt natürlich zu einer großen Level von Vollständigkeit führen, aber die Genauigkeit leidet darunter, weil es den tatsächlichen Ausführungsprozess, das Codes gar nicht beeinflusst. Und dann gibt es natürlich noch Auditing. Man kann das billig machen, wenn man viel Code liest, aber nicht großartig drüber nachdenkt, oder man kann sehr viel intensiver drüber nachdenken. Und da muss man dann wahrscheinlich ein kleinere Menge an Code lesen, aber man kann genauer sein, um die Eigenschaften dieses Codes zu prüfen. Und bei den Techniken, die es mir heute darum geht, da soll es darum gehen, das Beste beider Welten hier zu bekommen, in beiden Achsen große Werte zu erreichen. Im Gegensatz zu den bisherigen Methoden. Ich bin ein Professor an der Universität, ihr kennt wahrscheinlich das Leute, die da aus dem Elfenbeinturm griechische Buchstaben rauswerfen und dann von allen Methoden benutzen und sagen hier, das ist ein sehr interessantes Forschungsfeld, wurde aber sehr lange in der Industrie und in der Open Source Welt nicht benutzt, aber vielleicht gibt es ja Hoffnung. Viele Leute kennen quasi dieses Szenario in diesen Welten. Es ist wirklich das Richtige, das zu machen, willst du nicht die richtige Sache machen, das Programm zu beweisen. Dann nicken die Programmierer und grinsenfreundlich, aber sie müssen dann zurückgehen, ihre Arbeit machen, denn nächste Woche ist ja Deadline. Und ich will zeigen, dass die Methoden mittlerweile soweit sind, dass sie sehr nah dran sind, tatsächlich Zeit sparen zu können, wo es speziell darum geht, wenn die Fehler sehr teuer sind. Also den Vorschlag, den ich jetzt machen will, ist in der Geschichte von Computern, haben wir immer mehr Abstraktionen eingeführt, die die Kosten von bestimmter Funktionalität reduziert haben. Und wir haben mal sicher verschiedene Reden eingeführt, die weitere abstraktionsmethoden eingefügt haben, die dazu geführt haben, dass wir in der Lage waren, bestimmte weitere Möglichkeiten für große Programme zu benutzen, die wir auch besser verstehen können. Und was ich behaupte, dass es möglich sein sollte in etwa zehn Jahren, von heute aus, komplett ausgerollte Computersysteme, die komplett geprüft sind, von der Hardware bis hoch zur Anwendung, und die Beweise sind algorithmisch überprüft. Das heißt, wir müssen uns da keine Gedanken dazu machen. Also es müssen keine Menschen lange mathematische Dokumente lesen. Und es sorgt dafür, also wir kommen dann zu dem Punkt, dass wir keinen bestimmten Code vertrauen müssen, um am Ende die Eigenschaften zu kriegen, die wir erwarten haben wollen. Und das wird also auch auf Hardware-Design anzuwenden sein, nicht nur in Software. Und dieser Ansatz sollte in der Lage sein, die Kosten für die Entwicklung zu reduzieren, indem insbesondere auch zeitintensive Aktivitäten, wie Debugging und Testing und Code Review ersetzt werden. Und ich wollte jetzt also noch ein bisschen darüber reden, was für Techniken ich hier besprechen will. Ich werde dann noch kurz zusammenfassen, wie dieser Ansatz die bisherigen Ansätze ersetzen kann. Also wie man das Debugging von einem konkreten System ersetzen kann. Anstatt von Tests können wir Spezifikationen schreiben, die allgemeine vorderer Liste auflisten. Und anstatt dass wir uns den Code genau auditen, können wir die Spezifikationen für Audits aufschreiben. Das ist sehr viel kürzer, da sind insbesondere Optimierungen nicht mit drin, die häufig am schwierigsten zu verstehen sind beim Code. Also um das nochmal zusammenzufassen, ich werde die zentrale Technologie Proof Assistance vorstellen. Ich werde da ein paar häufige Gegenpunkte mit aufführen. Und ich werde sagen, warum wir also der Meinung sind, dass es tatsächlich auf echte Systeme angewendet werden kann und auch kosteneffizient angewendet werden kann. Und warum auch bestimmte andere Technologie angewendet werden kann. Und auch ich werde über spezielle Anwendungsfeile von kryptografischer Software sprechen. Und am Ende wird es noch ein paar Ressourcen geben, wo ihr weiterlesen könnt. So, eine der ersten Fragen, die Leute bei formalen Methoden haben, ist hier aus einem Paper von 1979. Das heißt, soziale Prozesse und Beweise von Beweisen und Programmen. Und die handen eine ganze Menge Aussagen darin, aber ich würde das zusammenfassen und sie sagen, echte Systeme sind so komplex, die ändern sich so häufig, dass es jenseits der Macht von, dass man sich gar nicht genug konzentrieren kann, um Beweise über diese Systeme tatsächlich zu lesen. Und das ist nicht nur ein Beweis, sondern jede neue Version des Systems braucht einen neuen Beweis, um die Korrektheit des Systems zu beweisen. Und ich würde sagen, heute haben wir gelernt, dass sie sowohl Recht haben als auch Unrecht haben. Also es ist sicher so, dass Menschen keine Beweise über echte Systeme lesen können. Aber sie haben implizit angenommen, dass wir eben Menschen brauchen, um diese Beweise zu lesen. Und heute können wir eben Algorithmen benutzen, um diese Beweise zu lesen. Und hier ist jetzt, wie man das auf ein echtes Problem hochskalieren kann. Hier ist ein Ingenieur, der so einen Beweis entwirft. Er muss das nicht selber machen. Also es gibt ein ganzes Ökosystem an Bibliotheken, wo Techniken und Teile von Beweisen eingebaut sind. Der Beweis ist tatsächlich auch Quelltext, der wird auch in die Versionskontrolle eingecheckt. Das heißt, da können auch mehrere Entwickler daran zusammenarbeiten, die verschiedene Sätze und Beweise da mit einbauen. Wir können das in CI Systeme, also Continuous Integration Systeme einbauen, so dass, also jedes Mal, wenn eine Änderung passiert, wird der Beweis automatisch nochmal überprüft. Das heißt, er liest den Quelltext und wendet ein paar einfache Regeln an, um dann sicherzustellen, dass der Quelltext tatsächlich noch den Beweis entspricht. Einige dieser Entwickler haben möglicherweise falsche Behauptungen aufgestellt und das kann also wieder zurückgehen. Und dann muss man, dann können die anderen Entwickler, die Behauptungen der anderen, die die Sätze, die bewiesen werden sollen, auch gegenprüfen und ändern. Es ist sicher so, dass wir diese ganzen Werkzeuge schon haben aus Systemen für die es eben Korrektheitsbeweise gibt. Und ich denke, ich werde das im Rest des Talks auch zeigen. Es gibt sicher noch einige schwierige, also ein paar schwierige Ecken. Aber das zentrale System, hier ist der Proof Assistant. Also es ist im Wesentlichen eine Entwicklungsumgebung, wo man mathematische Bätze beweisen kann. Das heißt, man muss quasi als ASCII Quelltext den mathematischen Aussage umschreiben, aber dann werden sie eben automatisch geprüft. Und es gibt eine ganze Menge Proof Assistant, die in den letzten Dekaten entwickelt wurden. Eine davon heißt Isabelle Holl, da ist die Großteil der Entwicklung an der TU München hier in Deutschland passiert. Und das Interessant, dass der Ergebnis hier ist, ist sicher dieses, dass sie ein Micro-Colonel komplett bewiesen haben. Und anderes ist Coq aus Frankreich. Und deren wichtigste Anwendung ist ein, es kommt zärt ein C-Compiler, den sie komplett beweisen können, dem Bionärcode, den er erzeugt. Und ich werde mich hier auf Coq präsentieren, denn das habe ich für meine Arbeit im Wesentlichen benutzt. Es gibt so eine Zusammenarbeit zwischen Mensch und Maschine. Und der Mensch macht Vorschläge an die automatische Engine und sagt im Wesentliche, diese Strategie sollte funktionieren für den nächsten Beweisschritt. Und die Engine rotiert ein bisschen und sagt dann, okay, das habe ich gemacht. Und hier ist das, was noch zu beweisen übrig bleibt. Und dann gibt es eine Bibliothek von Schritten. Und die ist nicht fest, sondern man kann andere hinzufügen und Abstraktion auf immer höheren Ebenen machen, was ein echtes Argument darstellt, ein gültiges Argument. Und am Schluss haben wir den Zyklus beendet und es gibt nichts mehr, was noch zu beweisen ist. Und dann kommt aus der Technic Engine ein kleines Programm raus mit nur einigen wesentlichen, wenigen Folgerungsschritten. Und das ist dann entrusted, im Sinne einer trusted Codebase von Security aus. Und das Einzige, was wir noch behaupten, ist ein kleiner Proofchecker, den wir vertrauen müssen. Der guckt, ob diese Beweise wirklich richtig sind. Und was sind die einfachen Folgerungsschritte, die wir machen können? Als Beispiel zum Beispiel ein ganz bekanntes, was im Code zum Beispiel eingebaut ist, das ist der Modus Ponens. Wenn man weiß, dass aus P, Q folgt und P annimmt, dann kann man daraus Q folgern. Und es gibt etwa zehn Regeln, die wir in ASCII aufschreiben können. Und das ist eine Programmiersprache, eine Sprache, die aussieht wie eine funktionale Programmiersprache, wie Camel. Und das wurde benutzt, um Coke zu entwickeln in den 80er-Jahren. Und wir haben Zeilen wie diese, um zum Beispiel Modus Ponens hier aufzuschreiben. Und das ist die Folgerungsregel, die Deduktionsregel. Und diese Schritte sind genug, um alle Ergebnisse aus Mathematik und Informatik und anderen logikbasierten Feldern Bereichen aufzuschreiben. Und man braucht nur einen vertrauenswürdigen Checker, um diese Regeln anzuwenden und zu überprüfen. Und ich mache das mal etwas konkreter und habe hier ein kleines Beispiel von einem Beweis in Coke. Und ich habe hier einen Emacs offen. Und es gibt ein Emacs-Mode für Coke. Und Coke basiert auf einer funktionellen Programmiersprache. Das ist wie Haskell oder Camel, wenn ihr die kennt. Wir können sowas machen hier. Das ist eine Liste von natürlichen Zahlen, 5, 13, 89. Und ihr könnt es prüfen und einige Tasten drücken. Und dann gibt es dieses Highlighting. Und das heißt, soweit ist der Profisisten gekommen in seiner Verarbeitung. Jetzt habe ich eine Liste von natürlichen Zahlen am Gebulien Ausdrücke. Und dann habe ich diese Alternative Ausdrücke für Alternative Ausdrucksformen. Und kann ein neues Element vorne an die Liste anfügen. Und am Schluss eine Lehreliste. Das bedeutet das Gleiche wie die Liste oben. Und ich habe eine recursive Funktion. Die leiste Length nimmt eine Liste. Und man kriegt eine natürliche Zahl zurück und hat dann einen Pattern-Matching. Die Lehreliste bedeutet Null, wird auf Null gemappt. Und hier kann ich jetzt nicht alle Ideen von Funktionalprogrammierung hier erklären, wie in Haskell. Aber ich hoffe, dass das auch für Leute, die das nicht schon kennen, dass das einigermaßen Sinn ergibt hier. Jetzt beweisen wir den Satz. Okay, die Länge ist 3. Gut, jetzt haben wir eine Funktion, die 2-Liste macht aus 2-Listen eine Macht. Erst die von der ersten Liste und dann die Elemente der zweiten Liste. Und das kann man mit Plus machen, zum Beispiel in Python. Und hier gibt es Append. 2-Listen mit jeweils einigen Elementen. Und man kann schon sehen, dass einige der Elemente, das ist hier wie ein IDE. Und so wie in Eclipse eine rote Schlangenlinie. So kann man das sehen. Dann machen wir eine Beweisversuche und bekommt dann dieses Feedback. Das heißt, hier ist ein Satz für alle A-Listen von dem Typ A. Und die Länge der Liste, der kombinierten Liste, ist dasselbe wie die Liste der Länge der ersten Liste plus die Länge der zweiten Liste. Und das ist ein Fakt, den wir noch nicht bewiesen haben. Aber gucken, ob wir das machen können. Weil der erste Induktionsschritt ist, der erste Schritt, ich beweise es durch Induktion auf der einen Liste, LS1. Und hier ist das Beweißziel hier unten. Es ist nur noch mal hingeschrieben. Und jetzt haben wir zwei weitere Unterziele. Ein Basisfall und ein Induktionsfall. Das erste ist, die Liste wird durch die leere Liste ersetzt. Und LS1 wird durch eine beliebige nicht leere Liste ersetzt. Und dann die alten Listen als das zweite Argument. Und der Basisfall ist der Induktionsstart. Und ich nehme mit, was das heißt, Intro. Und statt Fall haben wir jetzt die lokale Variable LS2. Und es ist hier. Und dies sieht offensichtlich aus. Einfach nur durch die Definition von der PANNED. Und wir gehen zur Kompallzeit durch einige Teile des Programms. Und auf beiden Seiten. So, und dieser Teil ist damit dann bewiesen. Jetzt kommt der Induktionsschritt. Wieder ein Intro. Und ich ersetze das For All unten und sage Simplify. Und jetzt sehe ich, es gibt hier einen Term hier, die Länge von Append, bla, bla, bla. Und das ist auch, sieht man auch da oben, genau das Gleiche. Was jetzt passiert ist, unter dem Doppelstrich sind Hypothesen. Und hier haben wir eine Induktionshypothese. Und das ist im Wesentlichen schon der Satz, den wir haben. Ich kann das umschreiben. Und wir bilden dieses auf das ab. Und ersetzen das dann durch dieses. Und jetzt haben wir wieder Flexivität. Und wir sind fertig. Und am Ende von einem Coq-Proof schreibt nur noch QED. Der Beweis ist fertig. Und wenn das System sich nicht beschwert, dann ist es auch gut. Und dann ist der Beweis überprüft. Und Coq ist überzeugt, dass der Beweis richtig ist. Thank you. Noch ein kleines Beispiel, um zu zeigen, wie wir Lemmas wiederverwenden können. Dies ist eine Reverse Funktion aus dieser Liste. Und macht daraus dann eine neue Liste mit der Appendfunktion. Und Elemente, die vorne waren, kommen dann ans Ende. Und dann macht nur wieder einen schnellen Beweis. Ich mache wieder das mit Induktion. Und die Länge ändert sich nicht, wenn man die Liste umkehrt. Und wir haben Algebraische Vereinfachungen, können wir benutzen. Und das ist dann offensichtlich wahr. Und was passiert in diesem Fall? Hier kann ich sehen, ich habe die Länge eines Append. Das stimmt aber nicht genau mit der Hypothese überein. Aber zum Glück habe ich schon was anderes bewiesen. Nämlich die Länge von Append, was ersetzt wird durch das Length von Append, ersetzen wir durch was anderes. Und jetzt haben wir die Länge der invertierten Liste und die Länge vom Rest. Und jetzt können wir das nur schreiben mit hls. Das ist die plus eins Funktion. Das ist der Nachfolge-Element. Und das ist offensichtlich wahr. Aber es ist nicht als plus eins definiert. Aber jetzt habe ich eine Prozedur, die heißt Omega. Das ist noch ein Solver. Und der kann alle möglichen numerischen Sachen beweisen. Und das war auch ein Beweis. Und wir haben einen Fakt benutzt, den wir schon bewiesen haben, um einem größeren Beweis zu machen. Und das sind jetzt Probeweise, die auch für große Systeme noch verwendbar sind. Und noch ein weiteres Beispiel, was ich nicht im Detail erkläre. Aber zum Beispiel, wenn man hat eine Seite Code geschrieben, der ist nicht naiv und offensichtlich, wie das geht. Zum Beispiel hat man große Syntax-Trees mit plus und times, die mehrere Variablen benutzen. Ich habe eine rekursive Funktion, um das auszuwerten. Und habe Werte allen Variablen zugewiesen hier. Und ich habe so ein Optimizer mit mittlerer Komplexität, der das zur Compile-Zeit vereinfacht. Und das ist eine Optimierungstechnik, die Custom Folding heißt. Und hier habe ich angefangen, das zu beweisen. Und der Custom Fold wird interpretiert. Und das ist dasselbe, als ob man das ursprüngliche Programm interpretiert. Und dann habe ich einen Induktionsbeweis angefangen. Der erste Fall war einfach. Der zweite Fall war einfach. Und dann musste ich eine Fallunterscheidung machen, welcher Konstruktor benutzt wurde. Und ich habe noch eine Fallunterscheidung machen müssen. Und noch eine Fallunterscheidung. Und mehrfach geschachtelt. Und es passiert ganz viel. Aber es ist sehr viel Wiederholung. Und irgendwann habe ich einfach aufgegeben und habe hingeschrieben, das ist hier zu kompliziert. Und das müssen wir von Hand machen. Und ja, man sollte es skeptisch sein, dass das auf Vollscale funktioniert mit ganz komplizierten Programmen. Und selbst von einem, was nur auf eine Seite passt. Aber da komme ich später nochmal drauf zurück. Und wenn man das schon mal benutzen will, gibt es einige Fragen. Und ich hoffe, dass der jetzt was beantworten kann. Also es ist schwer, einem korrekten Code zu schreiben, obwohl man ganz viele Techniken hat. Und es ist sehr teuer, wenn man Bugs erst in der Anwendung findet. Für viele Systeme haben wir Schwierigkeiten, uns vorzustellen, dass eine eindeutige Spezifikation wäre. Viel einfacher als der tatsächliche Code. Und viel kürzer. Und ich baubte die Verifikation dieser Art. Die meisten Wert, wenn man das am häufigsten benutzt System benutzt, das heißt Beweis, das heißt Prozessoren, Kompiler, Betriebssysteme und so. Das heißt, das ist die Basis für alles, was wir machen. Und zweitens haben die auch tatsächlich kürzere Spezifikation als Implementation. Das heißt, ein Kompil zum Beispiel, kann der Kompiler gar nichts, sagt vielleicht nichts über Optimierung. Obwohl das die komplexesten Teile im Kompiler sind und die, wo am meisten Fehler auftauchen können. Der am meisten Fehler produzieren kann, auch in meiner Erfahrung nach. Und wenn wir darüber machen, was macht die Spezifikation kürzer als das Programm? Wenn wir nur die funktionale Verhaltensweise von dem Programm beschreiben und dann die Optimierung haben, um das System schneller zu machen, dann haben wir die Implementation. Das heißt, es gibt ganz viele Optimierung in einem System. Und hier ist eine Möglichkeit, gibt es die Möglichkeit, Spezifikationen zu schreiben, die viel kürzer sind als das System. Aber trotzdem ist es im Wesentlichen programmieren, nur in einer anderen Sprache. Und es ist immer noch schwierig, das korrekt hinzukriegen. Lass uns über so ein Beispiel nachdenken, was sind die größten Herausforderungen? Wir haben einen Kompiler. Und der Kailer ist die Überbrückung zwischen dem Source Code und die Zielsprache, zum Beispiel Maschinsprache. Und diese Semantik, das heißt, wenn ihr wissen wollt, was Semantik genau bedeutet, dann ... Ich habe den Kompiler nur geschrieben, weil ich eine Anwendung übersetzen will. Und jede Anwendung hat eine eigene Spezifikation. Und die Applikationssätze passen zusammen, wie die Kompiler-Theoreme. Und darunter habe ich meinen Prozessor, der die Maschinsprachsemmantik implementiert, zum Beispiel in VHTL oder wie auch immer der beschrieben ist. Und das Ganze ist hier eine bewiesene, nachgewiesene, verifizierte Einheit. Und die arbeiten alle zusammen, um diese Abstraktion zu erzeugen, die auf einer Platine sitzt und sich auf eine ganz bestimmte spezifizierte Weise verhält. Und das Nette an diesem Stil von Development, von Entwicklung, ist, dass kein einziges Stück von dem Code muss vertrauenswürdig sein. Es sind alles Details in diesem großen Block, aber alles ist durch die Beweise abgedeckt. Und zweitens, selbst die internen Spezifikationen sind jetzt nicht mehr trusted. Und man muss denen nicht mehr vertrauen. Sie sind Teil von dem bewiesenen Besamtsystem. Das heißt, die Semantik der C-Programmelsprache könnte vielleicht ganz einfach sein, aber man muss vorsichtig sein, dass man nicht irgendwelche Fälle vergisst. Aber es kann nicht mehr passieren, dass man incorrecte Systeme akzeptiert, wenn diese Spezifikationen innerhalb der Gesamtspezifikation ist, die man baut. Und das vergleichen mit dem, was wir bisher machen, was der Standard ist. Wir müssen nicht nur Unitests macht auf den Libraries, sondern volle Systemintegrationstests. Das heißt, wenn wir Libraries zusammenbauen und Module, der Zustandsraum explodiert, und es ist viel einfacher, eine vollständige Abdeckung haben für Funktionen als für Systeme, für ganze Systeme. Und wenn man den Beweisansatz nimmt, dann beweisen wir immer alle Komponenten innerhalb von dieser Black Box. Und wir wissen, dass wir alles haben, was wir brauchen, damit es funktioniert. Und wir brauchen eigentlich nicht so was wie Unitests, jedenfalls nicht in der zentralen Rolle wie bisher. In dem alten Verfahren müssen wir ausführlichen Code Review machen, weil ein einzelner kleiner Fehler an irgendeiner Stelle alles komplett zerstören kann. Und wenn man das mit beweisen macht, dann muss man nur Code Review machen an den äußeren Interfaces. Man kann im Prinzip theoretisch eine Komponente von deinem schlimmsten Feind akzeptieren, wenn die beweisen ist. Und man kann das einfach benutzen, ohne das auch irgendwie nur zu untersuchen. Und potenziell ist das eine Möglichkeit, Applikationen runterzulassen und dann Proof Checking zu machen, um sicherzustellen, dass die Security Policies erfüllt sind. Also ein weiteres Problem ist, wenn ich versuche, hier für so ein kleines Programm den Beweis hinzuschreiben, dann wird das also sehr schnell auch sehr groß. Wir kennen also das Szenario. Wenn wir uns vorstellen, wir sind in den 1950ern, schreibt ein Programm in Maschinencode. Das ist viel Arbeit und wird nie sehr populär sein. Wir haben heutzutage sehr viel höhere Level von Abstraktionen und Bibliotheken, die wir benutzen können, an jedem Level dieser Sprachen, die wir benutzen können für die meisten Teil der Arbeit. Das heißt, wir müssen mit einem populären Framework quasi nur noch das Programm zusammenstecken. Wir müssen also nicht alles neu schreiben jedes Mal. Und hier bei den maschinengeprüften Beweisen ist es ganz ähnlich. Wir können auf diesen Beweisgeneratoren aufbauen und die Bibliotheken von Lemmas benutzen. Und das ist das Geheimnis, ein Ökosystem von Werkzeugen zu erzeugen, was es billiger macht. Einen Beweis zu erzeugen, der sehr ähnlich ist zu dem, was man vorher gemacht hat. Und wenn wir jetzt, genau, wir gehen jetzt noch mal zurück in diese Beweise, die ich da geschrieben habe, um noch ein bisschen Werbung dafür zu machen. Also ich habe diesen Beweis hier hingeschrieben mit einem sehr, also ich habe das sehr von Hand gemacht. Ich kann jetzt hier aber stattdessen einfach, wir benutzen jetzt hier ein Semikolon, ich führe diesen Schritt aus, es wird also ein paar neue Ziele geben und jetzt führe ich das auf alle Ziele aus. Und dann gibt es hier einen ganz witzigen Namen, der heißt Intuition, also Intuition, und das ist ein Begriff aus der Logik, aber die Leute erleben das zuerst anders, aber das bedeutet das hier gar nicht. Und jetzt schauen wir mal, ob wir mit derselben Methode Glück haben können bei dem nächsten Beweis. Ja, fast, das hat fast funktioniert, das Einzige, was jetzt noch fehlt ist, also denkt dran, ich habe hier unten ein Lämmer wieder benutzt, das ich schon mal bewiesen hatte und das hatte hier jetzt gar nicht versucht. Also ich muss jetzt hier noch das Lämmer, das wir schon besucht haben, den Längther Pen, und jetzt sage ich, hier erinnert ich daran, dieses Lämmer haben wir doch vorhin bewiesen, benutzt es doch mal für Umschreibeaufgaben und jetzt wird es hier tatsächlich angewandt, jetzt immer fast fertig, ich muss nur noch sagen, diese Schritte müssen jetzt immer und immer wieder wiederholt werden und das ist ein Beispiel für eine Schleife, das ist tatsächlich eine Touring vollständige Skripsprache, das ist also ganz unterschiedlich, wenn man sich, also die ganz primitive Beweissprache, wo nur die zehn Schritte drin sind, also wir können hier Datenstrukturen und Schleifen und so was implementieren und wir schreiben jetzt Skripte, die dafür sorgen, dass die für uns die Beweise finden, aber nur weil du dieses Skript lesen kannst, heißt es nicht, dass du jedes Detail, was dahinter steht, auch verstehen kannst und das Schöne daran ist, wenn man solches Skript schreibt, dann wenn man das System ändert, was man verifiziert, dann funktionieren die Beweise häufig weiterhin, das ist also eine schöne Eigenschaft, das ist ganz ähnlich wie wenn man Bibliotheken entwickelt, wir wollen gute Beweise, die für viele ähnliche Situationen können. Wir müssen es also nicht häufig umschreiben, wenn wir das ordentlich machen. Also ich wollte hier nochmal einen anderen Beweis angucken, ich habe ein paar andere Beweise noch bewiesen, die brauchen wir hier gar nicht, also wir wollen eine Induktion über E machen, ein paar Fälle bleiben hier noch übrig und wenn sich hier sehe, ist das Programm hat einen Pattern-Match über dieses Ding hier, das ist quasi eine Fallunterscheidung, die machen wir jetzt auch in dem Beweis, also wir matchen jetzt das Goal und was ich jetzt mache ist, ich suche jetzt einen Pattern-Match, also mit dieser Sündtags kann man Pattern-Matchen und ich werde da jetzt eine Fallunterscheidung machen und danach vereinfachen und werde wieder sagen, hier macht das immer und immer wieder für alle Unterziele, die hier generiert werden und was wir jetzt hier haben, sind nur noch ein paar Fakten aus der Arithmetik, hier gibt es ein Konst Null, das kann vereinfach werden, also ich sage jetzt nicht nur unterhalb der Linie vereinfachen, sondern überall und dann sind die auch weg und jetzt habe ich ein paar Sachen, die identisch sind zu einem E-Wall-Result, also einem Ergebnis von diesem E-Wall-Aufruf und das wollen wir jetzt auch wiederholen, wir suchen nach Fällen mit der Hypothesen, wo irgendwas ist gleich E-Wall, steht und das wollen wir umschreiben und dann entfernen wir das und jetzt sind die alle weg, also wir haben ganz einfache Sachen, wie ich das hier mit dem E-Wall-Aufruf und das mit dem N-Aufruf und ich habe wie viele habe ich jetzt, 53 solche Fakten, ein paar nicht so interessante Sachen, also mit Nullen und Plus und so weiter und das stellt sich raus, dass viele Sachen aus einer algebraischen Struktur einen Halb-Ring rausfallen und da kann ich jetzt also das Befehl Ring benutzen und das reicht schon für diesen Beweis. Aber ich habe jetzt eine komplett neue Hinweis für meinen Sündachs hinzugefügt, also sagen wir mal, ich habe zum Beispiel so etwas wie Subtraktion hinzugefügt, dann kann der selbe Beweis immer noch funktionieren, ohne den überhaupt anzufassen und tatsächlich sogar Änderungen an der Sprache oder der Optimierung könnten auch zu einem ähnlichen Resultat führen und das sind dann eben Beweise für große Systeme mit einem schnell endernden System. Das ist die Technologie, die da bei vielen Dingen als Basis dient, die wir mit Proofassistance benutzen können. Klassischerweise hat der Mathematiker irgendwie einen Satz im Kopf und schreibt einen Beweis auf und stellt sicher, dass der überzeugend ist. Bei Programmen ist das ganz ähnlich, wir haben eine Implementierung, wir schreiben eine Spezifikation dazu und die Beweisrichtig ist und die andere Variante ist, wir haben gar keinen Artifakt, also wir haben gar keine Programmen, sondern wir haben nur eine Wunschliste. Also ich hätte gerne einen FUBAR, was das machen würde und wir werfen das jetzt in ein System mit rein, das eine Implementierung und den Beweis der Implementierung gleichzeitig erzeugt, ohne dass wir die Software schreiben mussten und beide können praktisch sein und basieren auch auf derselben Technologie. Deswegen habe ich also nur Programme in dieser funktionalen Sprache, die in diesem COC-Beweissystem eingebaut ist, gezeigt, aber man kann das erweitern für alle möglichen Sprachen mit verschiedenen Syntaxen und auch anderer Semantik. Also hier sind ein paar Beispiele, die in diesem, wo Leute mit COC gearbeitet haben, das sind High-Level wie diese SQL-Abfrage-Sprache bis runter zu C. Und wir können auch eine ganze Menge von Werkzeugen benutzen, um unsere Programme und Beweise zu machen. Wir können Compiler benutzen, Zwischensprachen und wir können Programme schreiben in COC, die auch direkt die Beweise erzeugen. Und das Interessante ist jedes Tool, was wir in diesem Ökosystem hier mit hinzufügen, wie in jedem anderen Software-Ökosystem auch, brauchen wir jetzt ein gemeinsames, üblicherweise brauchen wir ein gemeinsames Binärformat, hier brauchen wir ein gemeinsames Beweisformat. Und in dem Fall sagen wir, okay, es gibt jetzt hier irgendwo ein Pfeil, der übersetzt es irgendwie und dann beweisen wir, dass diese Übersetzung korrekt ist. Und eine andere Variante ist ein Beweis erzeugen, das Beispiel Teil zu bauen. Das heißt, das erzeugt nicht nur eine Ausgabe, sondern auch gleich den Beweis für die Korrektateausgabe. Und für beide Methoden kann auch derselbe Beweis-Checker, also Proof-Checker benutzt werden. Also hier ein erstes Beispiel, das heißt, Kami, es geht um Unterstützung für Beweisen für digitale Hardware, wurde am MIT von den Leuten, die hier unten aufgelistet sind, entwickelt. Und jetzt wollen wir uns vorstellen, dass wir schnelle Open-Source-Entwicklungen für neue digitale Hardware-Systeme, indem wir Komponenten aus verschiedenen Bibliotheken zusammenbauen. Also zum Beispiel haben wir hier eine Bibliothek, zum Beispiel für das cache-koherente Speichersystem. Und dann gibt es einen Beschleuniger und einen anderen Beschleuniger für einen anderen Zweck. Und alle diese Systeme haben ihren eigenen Beweis. Und wir können die Beweise der Teile benutzen, um zu beweisen, dass das gesamte System korrekt ist. Wir kriegen hier potenziell Beweis für die Korrektheit, ohne irgendwelches Debugging. Wenn die Sätze, die da bewiesen werden sollten, korrekt aufgeschrieben worden sind. Und was meine ich hier eigentlich mit Korrektheit? Also stellen wir uns vor, wir haben eine hochoptimierte Implementierung eines Hardware-Komponente. Und wir haben auch eine Spezifikation, das ist die einfachste Art und Weise, der Funktionalität dieser Box darzustellen. Wir wissen nicht, wie das implementiert ist. Das könnte man auch Referenzimplementierungen nennen. Also nicht nur Spezifikation. Und dann wollen wir sowas haben, eine kontextbasierte Verfeinerungseigenschaften. Und was das bedeutet, es gibt einen, jemanden, der da sehr genau prüft und sich beide Boxen anguckt und sucht nach irgendwelchen unterschiedenden Verhalten dieser beiden Boxen. Und wenn dieser Richter eine Unterschied findet, der zum Beispiel eine Ausgabe erzeugt aus der Implementierung, die die Spezifikation überhaupt nicht erzeugen kann, dann verliert das System. Aber grundsätzlich, wenn der herausfindet, dass alles, was auf der linken Seite gemacht werden kann, auch rechts gemacht werden kann, dann sagen wir, das ist eine korrekte Implementierung dieser Spezifikation. Und wir schreiben das in der BlueSpec-Sprache. Das macht es besonders einfach zu sagen, was die korrekten Art und Weise sind, wie man mit dem System interagieren kann. Und alle internen Implementierungsdetails kann man sich gar nicht genau angucken. Und es ist wichtig, die Optimierung machen zu können, ohne dass man eben die Details in der Spezifikation kennen muss. Und ein paar Worte über diese Sprache. Es ist objektorientiert. Programme sind Objekte, die haben privaten Zustand. Und das gibt Funktionen, die sind die einzigen, die zugreifen können auf diesen privaten Zustand. Und Funktionsaufrufe passieren automat, ohne dass es da Dinge dazwischen gibt. Und wir können jeden Atomahnaufruf charakterisieren durch die Aufrufe, die innerhalb dieser Funktionen passieren. Und die Eigenschaft, die die Implementierung mit der Spezifikation verbindet, ist zu sagen, jeder von diesen Traces, der meine Implementierung generieren kann, die muss auch die Spec generieren können. Und man kann verschiedene Module und Objekte zusammenbauen. Das sorgt dafür, dass bestimmte Aufrufe in diesen Traces nicht mehr auftauchen. Man kann so die Details der Implementierung verstecken. Also schauen wir uns mal ein kleines Beispiel von Code in dieser Sprache an. Hier ist etwas Code, der ist ein Producer-Konsumer-Modell. Das ist die Produktproduzersite. Es gibt ein Modul mit einem speziellen Register und eine Regel, die an einem bestimmten Zyklus vom der CPU laufen muss und so weiter. Und Coke hat einen erweiterbaren Pasa. Und wir haben jetzt quasi diese Hardware-Beschreibungssprache mit eingebaut. Also es gibt keine Register-Regel oder so was. Wir haben diese Semantik, diese Hardware-Sprache komplett definiert. Und das bedeutet, wir können sie jetzt auch benutzen, um Systeme zu definieren und Beweise darauf auszuführen. Und die Definition, die ist sehr viel kürzer. Hier ist eine Spezifikation, die den Producer und den Konsumer zusammenbaut. Und mit weniger als 100 Zeilen in der Datei können wir hier unten beweisen, dass die Implementierung eine Verfeinerung der Spezifikation ist. Und ihr müsst mit es einfach glauben, wir können es hochskalieren, auf cache-coherenten Speichersysteme, Pipeline-Prozessoren und so weiter. Wir können diese Dinge spezifizieren und die Beweise gleichzeitig bauen. Das ist ein sehr generisches System. Ich wollte auch noch eine Anwendung zeigen. Ihr habt vielleicht von Risk5 schon gehört. Das ist ein Instruktionsset. Da gab es, glaube ich, am ersten Tag schon ein Talk dazu. Und ich habe ein Risk5-T-Shirt hier. Auf der Rückseite steht Instruktionssets, wollen frei sein. Das ist so ein bisschen wie das Linux, der Hardware-Instruktionsset. Wenn ihr euch Linux im Stand von 1995 vorstellt oder so, es ist ein offenes Instruktionenset, wird von einer Non-Profit, also einer gemeinnützigen Firma unterstützt. Und es gibt viele Möglichkeiten, sich hier mit einzubringen, auch was formale Methoden bedeutet. Und innerhalb dieser Jahre, dieses Vereins, wurde ursprünglich dieses Instruktionsset spezifiziert und wir arbeiten daran, dass wir die Korrektzeit von Risk5-Maschinencode sicherstellen können durch Beweise. Und es gibt ein paar nette Konsequenzen von diesem offenen Modell. Das passt echt gut zu formalen Methoden. Denn die Hersteller von Prozessoren haben das Copyright auf die Befehle, die das Instruktionsset eines Prozessors aufbauen. Aber wenn man sich stattdessen das offene Modell von Risk5 anschaut, dann können wir die formalen Semantik hinschreiben. Und jeder kann grundsätzlich eine geklonte Version dieses Prozessors bauen. Die können auch alle eigene Beweise haben. Und man kann verschiedene komponenten zusammenbauen. Und das kann dazu führen, dass man die Kosten hier in Hardware-Entwicklung reinzukommen, extrem reduziert. Und die zweite Case-Studie und das zweite Beispiel ist Elliptic Curve Cryptography, das zum Beispiel in TLS benutzt wird und auch eine Kollaboration mit anderen MIT-Bitarbeitern. Und die Geschichte ist diese. Cryptografie ist sehr wichtig, so wie wir es kennen. Und die meisten Abdeckationen nehmen einfach Bibliotheken, die schon fertig sind, die von einigen Editären, Implementärern gemacht wurden. Und das alles zusammen. Es gibt nur eine mittelgroße Anzahl von cryptografischen Algorithmen. Und die meisten brauchen dazu große Primzahlen. Und es gibt einige, eine mittlere Größe, eine mittlere Menge von Hardware-Architekturen. Und in der Praktis muss er für jede Auswahl aus diesen Blasen muss man braucht man mehrere Tage, braucht ein Experte mehrere Tage, um das zu machen, möglicherweise in Assembler. Und das ist kein sehr zuverlässiger Prozess. Und natürlich ist es sehr wahrscheinlich, dass da Bugs drin sein können mit schwerwiegenden Folgen. Das heißt, wäre das nicht schön, wenn wir das automatisch machen könnte, nicht nur schnellen Low-Level-Code macht, sondern auch einen Maschinen überprüfbaren Beweis, dass die Low-Level-Mathematik überprüft. Das heißt, wir machen Kryptografie, Verifikation. Und was zum Beispiel oft bewiesen wird, ist eine High-Level-Property. Wenn man den Schlüssel nicht kennt, dann braucht man mehr als polynomial Zeit, um den zu finden. Und es gibt bestimmte Algorithmen, dass ein bestimmter Algorithmus diese Vorsitzung erfüllt. Können wir beweisen und dann können wir zum Beispiel einen effizienten Low-Level-Code machen, der diese Mathematik implementiert. Und das ist eine sehr interessante Anwendung. Unser System ist zum Beispiel jetzt in Chrome eingebaut in der BoringSSL Bibliothek manuell geschriebenen Elliptic-Code zu ersetzen, der da bisher drin war. Und man kann diese Imklimitation der Kurve 2559 in Chrome 64 in der aktuellen Bitter-Version die folgenden Versionen wird das in Chrome in Version 65 wird es drin sein. Und eine ganz kurze Demo nochmal und dieser Generation-Prozess was wir gemacht haben wir haben eine Bibliothek von funktionellen Programmen die ganz generell diese Mathematik beschreiben in diesem Bereich und diese Zahlen sind viel zu groß um die Hardware-Register zu tun das heißt, wir müssen die auf mehrere Register aufteilen und dann einfach Grundschul-Mathematik benutzen und wir haben hier Faltungen und Abbildungen und hier sind Flatmaps und andere Teile der Repräsentation das ist eine feindfachtige Version für Demonstrationszwecke und wir gucken das alles und gehen hier nach unten und da steht im Wesentlichen das Ziel nämlich zum Beispiel haben wir 10 Integer-Tupel und für die Kurve 2559 wollen wir aus jeder Zahl 10 Tupels um mit 10 Zahlen machen und deswegen haben wir 10 Tupel mit richtigen Antworten und dann multiplizieren wir das mit 52 und wir haben hier noch eine Geschritte die ich nicht im Detail eingehe symbolisch Manipulation und der ist wichtig ist hier das läuft jetzt ungefähr 10 Sekunden glaub ich und wir fragen eine correct by construction Code erzeugen kann und wir kriegen dann Ausgaben wie diese das ist die letzte Stelle von der Antwort und es sind sehr viele redundante Teile drin also nehmen wir die Ringalgebra um das weiter zu vereinfachen und dies rein braucht einige Zehntel Sekunden einiges kreativ normalerweise wurde der von Hand geschrieben dieser Code für diese kryptografischen Primitive und dieses baut nicht nur den Code sondern das erzeugt auch den Beweis für die die Whiteboard Implementation und das muss gleich fertig sein und es wird dann nicht mehr diese Konstanten drin haben sondern es wird etwas schöner hingeschrieben und das was dann hier kommt ist noch nicht das Ende, wir haben noch spätere Phasen und dann sieht das eher aus wie C Code und dann macht der Bounce Analysen und das passiert auch automatisch wenn man in die richtigen Parameter übergibt und hier haben wir ein Beispiel der Ausgabe und dies hier sieht, wenn Leute schon mal 25519 Kurve implementiert haben, dann sieht das vielleicht bekannt aus und temporäre Variablen haben wir hier und wir müssen aber noch von daraus finden was die zum Beispiel sind hier noch einige Konstanten drin zum Beispiel 19 und 38 hier und es gibt noch andere Parameter und dann bekommt man ein Standard Code für die anderen Kurven und für verschiedene Hardware-Architekturen aber das sieht so ähnlich aus wie dies hier um das zu Ende zu kommen die Implementierung hat automatisch den Code geschrieben in einem einfachen Art zum Beispiel als einfache Produkte von Potentchen von zwei wir haben dann diese auf der Elliptic Curve Mailing Liste geguckt um alle Prim-Zahlen zu gucken aus den Archiven und die alle zu suchen für automatisch generierten Code und es gibt nur ganz selbe die sehr ineffizient sind zum Beispiel von Neulingen aber wir haben die auch ausprobiert und manchmal das auch und wir haben automatisch Code erzeugt für alle diese Fälle gegen die GNU Multi-Precision Library getestet das ist eine ganz normale verbreitete Library für ratmetischen großen Zahlen und dann haben wir diese auf einem Telefon mit einem ARM Prozessor und malerweise die GNU Multi-Precision Bibliothek braucht 10 bis 20 mal so lange für diese Elliptic Curve und diese Operation viel länger als unser Code der Automatik erzeugt war und ja und es ist hier noch einige Sachen die ihr euch weiterhin angucken könnt um darüber was zu lesen das erste ist Software Foundations ein Online-Buch und das ist eine Einführung Koch und wenn man einfach was Erfahrung was im Studium hat dann kann man das schon lesen und da gibt es eine Science of Deep Specification oder auch Deep Spec und im Sommer 2018 gibt es eine Summer School wo man das alles lernen kann mit Workshops und Hardware Verifikationen und C-Programm Verifikationen mit Koch bis in New Jersey und man kann die Mailing Liste abonnieren um Updates zu bekommen und dann gibt es noch weitere einige von meinen Projekten hier auf GitHub und es gibt noch weitere Dinge zu denen ich Beiträge geliefert habe die man sich angucken kann vielen Dank wir haben noch ein paar Minuten für Fragen und Antworten Mikrofon 1 ja, vielen Dank und ich habe noch eine Frage was für eine Strategie habt ihr die richtigen Theoreme, die richtigen Sätze zu finden denn ich glaube, das ist so das schwierigste mit und wie gesagt ihr macht Reviews davon und vielleicht ist das nicht ausreichend zum Beispiel wenn man diese Reverse Funktion hat und eine Sortierfunktion dann kann man zum Beispiel ein Theorem haben als Invariante das ist ausgeführt wird aber das ist vielleicht nicht genug für das heißt, was für Strategien habt ihr da vielleicht eine Kombination von konkreten Beispiel-Tests und Theoreme sind vielleicht nicht genug und was denkt ihr darüber? ja, das hängt mit einer Frage zusammen, die ganz häufig gestellt wird und häufig gegen Mitte des Talks habe ich da schon drüber gesprochen wir versuchen Programme zu schreiben und Programme haben häufig naheliegendere Spezifikationen als die Systemen und die Strukturen darunter das heißt, wenn wir die Infrastruktur die Sätze für die Infrastruktur schon falsch gemacht haben dann können wir die Applikationen nicht beweisen und eine übliche Technik ist, wenn man eine Komponente baut dann benutzt man die in möglichst vielen Kontexten und schaut nicht nochmal in die Implementierung sondern benutzt nur die Spezifikation und da kann man dann schon die Fehler in der Spezifikation ausbügeln in den Komponenten, die man benutzt und es kann möglicherweise praktisch sein, ein paar Testfälle zu haben für eine Komponente das kann auch eine gute Strategie sein aber es ist in gewisser Weise schon abgedeckt, wenn man Komponenten Kontexten benutzt und man muss dann eben sicherstellen, dass diese einzelne Funktion schon korrekt sein muss um das damit das gesamte System korrekt ist Ja, Mikrofon 3, vielen Dank für den Vortrag die Spezifikation von vielen Problemen beinhalten auch Zeit also man hat nicht nur die richtige man muss nicht nur die richtige Antwort haben sondern auch die richtige Antwort bevor man ein Timeout hat oder bevor der benutzer sich langweil oder die Maschine wieder bootet oder bevor die Deadline zu Ende ist wie schreibt man Zeitspezifikationen auf in Coq zum Beispiel dieses wird den maximalen so und zu viele Millisekunden brauchen Also ich denke ich werde jetzt erstmal darauf verzichten zu beweisen, dass Benutzer nicht gelangweilt werden aber was ein Timeout betrifft denke ich, wir arbeiten hier in einem sehr generischen mathematischen Framework also man kann alles abbilden, was man auch in ein Mathelehrbuch findet und es ist relativ einfach zu definieren was Zeit ist von der Ausführung eines Programms her und es gibt Projekte, die zum Beispiel beweisen dass ein C-Compiler die Laufzeit erhält zwischen dem Quelltext und dem Assembly Code das ist ein relativ naives Modell erstmal aber ich habe jetzt kein eigenes Projekt wo das benutzt wird und ich denke meine zentrale Antwort ist es ist ein sehr flexibles Framework ihr könnt da programmieren, was ihr wollt ihr könnt beweisen, was ihr wollt und wir werden da mit der Zeit einfach auch bessere Abstraktionen finden für solche Dinge Das ist eine Frage vom Signal-Hangle Das letzte könnt ihr Side-Channel-Attacks behandeln und ein wesentlicher Punkt von manuellen Implimationen die Automatischen Implementierungen die ich hier gezeigt habe die sind in einer sehr restriktiven Sprache geschrieben die konstante Zeit einfach durch die Sprache schon fordert also ja durch die Konstruktion schon erzeugt das Code der in konstanter Zeit läuft was andere Projekte gemacht haben ist automatische Analyse von Programmen um konstant Zeit zu beweisen das ist, denke ich, sehr wichtig aber es ist was formale Methoden angeht das ist eine der einfachen und das ist ziemlich super einfach deswegen, weil es sehr wichtig ist Mikrofon 4 Ja, so über Skalierung bis zu welchen Größen wie guckt ihr das hängt davon ab also wenn wir über die Leute sprechen die die Beweise schreiben dann das sind ja wir und wir machen uns da viele Gedanken wir hoffen, wir werden besser indem wir auch die Werkzeuge verbessern oder sprichst du jetzt über die Benutzer von Hardware oder Software also in welchem Umfang wenn ihr über volle Systems-Spezifikation redet dann ist das wirklich eine Frage Ihr meint ob wir den Nutzer in den Sätzen mitmodellieren also was wir machen ist wie der oberste Satz der wird modelliert als Ein- und Ausgabe wer wissen nicht was auf der anderen Seite ist nur die Spezifikation sagt wenn dieser Eingabe passiert dann wird dieser Ausgabe erwartet ich weiß nicht ob jemand schon mal auf die Idee gekommen ist aber es ist ja nicht so dass man die Spezifikation mit dem Nutzer kognitiv zu simulieren also zu erwarten wie die handeln ich denke da wird es auch viele Probleme geben so wie man diese Sätze überhaupt aufschreiben soll im wesentlichen stimm ich dem völlig zu aber im wesentlichen stimm ich dem völlig zu aber im wesentlichen stimm ich dem völlig zu aber im wesentlichen stimm ich dem völlig zu aber im wesentlichen stimm ich dem völlig zu vor zehn Jahren haben Forscher vorabs gesagt dass alle versprechen von formalen Methoden die die Verfügbarkeit in Zufallsigkeit zu erhöhen und hat dann und das war das traurigste was ich hier gehört hab und die die Probleme die wir eigentlich lösen wollen sind gar nicht so schlimm wie wir wie wir dachten. Okay, und warum denkst du, dass... Warum glaubt ihr, dass Programmiere das jetzt akzeptieren werden, wenn sie es bisher nicht getan haben? Also in meiner Erfahrung war es zumindest einige isolierte Communitys betrifft, Krypto-Bibliotheken und so was. Die interessieren sich sehr wohl für Korrektheit und die wollen sich diese Techniken auf jeden Fall anschauen. Und das ist eine Antwort in einem Bereich, wo die Leute besonders interessiert sind, wo es auch sehr teuer wird, wenn die Korrektheit nicht gegeben ist. Und der andere Fall ist, wenn es darum geht, die Benutzbarkeit zu verbessern, indem wir also viele Komponenten-Bibliotheken erzeugen, wo man also nicht anfangen muss von Punkt 0. Und ich denke, wir sind jetzt einem Punkt, wo das Ökosystem gerade groß genug ist, dass es eine zentrale Änderung gibt in den Kosten, die es bedeutet, diese Tools anzuwenden. Ja, verstehe ich, aber zum Beispiel in meinem Beispiel ist keine Referenz in alles, was man braucht, um diese Sprachen, diese parametrischen Polymorphismus. Und die Leute sagen immer noch, ja, das funktioniert auch so, ich mache solche Fehler ja sowieso nicht. Ich denke, das können wir dann vielleicht später weiterdiskutieren. Es gibt da noch eine Frage. Wie hat das Halteproblem Anwendung hier vorhin? Also das Halteproblem trifft auf liebege Teile von Code an, aber den Code, den wir analysieren wollen, ist geschrieben von Menschen, die da schon eine gewisse Intention mit drin haben. Und ich denke, der Autor des Codes ist verantwortlich, den Beweis mitzuliefern. Und die echte Problem ist dann zu entscheiden, ob dieser Beweis überzeugend ist. Ja, Mikrofon 3, die kleinen Beispiele, die du gezeigt hast, und die Beweise waren trotzdem immer noch sehr aufwendig und sehr lang, und die Beispiele waren sehr einfach. Aber gibt es größere Automatisierung möglich und machen Leute das? Es gibt eine große Menge an Ansätzen, die was Automatisierung angeht. Ich denke, die Beweise sind relativ kurz, sind auf jeden Fall sehr viel kürzer, als die Programme, auf die sie angewendet werden sollen, vielleicht ein Fünftel so groß etwa. Und vor 20 Jahren, also im Gegensatz zu 20 Jahren, ist das schon echt ein riesen Fortschritt. Und da können wir vielleicht auch Hoffnung für die Zukunft haben, dass da ganz im Schluss noch Mikrofon 3 in den Semantik von Blue Spec da was automat ausgeführt wird. Was passiert, wenn es ein Failure gibt? Also, was Hardware betrifft, ist einfach jede Methode, die ausgeführt wird, nur Leitungen und Signale, die über Leitungen weitergeleitet werden. Und am Anfang schaut man sich da einfach gar nicht an, was entlang der Schaltung durchliest. Danke.