Michael Mächtel před 8 roky
rodič
revize
af624bb813
3 změnil soubory, kde provedl 281 přidání a 0 odebrání
  1. 123
    0
      hw7/task1/README.md
  2. 106
    0
      hw7/task1/hasher_sha256.rs
  3. 52
    0
      hw7/task1/unit_tests.rs

+ 123
- 0
hw7/task1/README.md Zobrazit soubor

@@ -0,0 +1,123 @@
1
+# Homework hw7 task1
2
+
3
+- ['Proof-of-Work'](#proof-of-work)
4
+- [Implementierung](#implementierung)
5
+    - [Modul `hash256`](#modul-hash256)
6
+    - [Parsen der Argumente](#parsen-der-argumente)
7
+    - [Subcommand 'timings'](#subcommand-timings)
8
+    - [Tests](#tests)
9
+    - [Optimierung](#optimierung)
10
+    - [Laufzeit Messungen](#laufzeit-messungen)
11
+
12
+## 'Proof-of-Work'
13
+Zur Vorbereitung einer Multithreading Anwendung beschäftigen wir uns mit dem Mining von Kryptowährungen.
14
+
15
+Das Grundprinzip bei dem sogenannten 'Proof-of-Work' basiert auf der Idee, dass Miner im Netzwerk nachweisen müssen, dass sie einen gewissen Aufwand erbracht haben.
16
+
17
+Das Durchführen eines Proof-of-Work Mechanismus bzw. das Berechnen der Ergebnisse bezeichnet man im Kontext von Blockchains als „Mining“. Die Miner versuchen dabei, durch milliardenfache Ausführung von Rechenoperationen, ein Ergebnis mit bestimmten Eigenschaften zu finden. Haben die Miner ein solches Ergebnis gefunden, werden Sie vergütet.
18
+
19
+Die Basis dieser Berechnung stellt das Multiplizieren zweier Zahlen und Hashen des Ergebnisses dar. Gesucht wird dabei ein Hashwert, der eine besondere Eigenschaft hat, z.B. indem er ein bestimmtes Muster enthält.
20
+
21
+Dieses zu findende Muster ist die sogenannte 'Difficulty'. Umso mehr Teilnehmer in einem Netzwerk aktiv sind und umso mehr Rechenkapazität somit im Netzwerk vorhanden ist, umso schwieriger wird die Difficulty.
22
+
23
+Beispiel:
24
+
25
+Gesucht ist die Zahl x, die multipliziert mit 21 (BASE) einen Hash ergibt, der am Ende das Muster "12345" hat. Eine Lösung ist die Zahl 567621, denn der Hash von 21*567621 ergibt "b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345".
26
+
27
+## Implementierung
28
+
29
+### Modul `hash256`
30
+
31
+Schreiben Sie im Modul die Funktion *verify_product(base, number, difficulty) -> Option<Solution>*. Die Funnktion bildet den Hashwert des Produkts aus *base* und *number* (beide Typ `usize`)und überprüft, ob am Ende des Musters die *difficulty* steht. Stimmt das Muster nicht, so gibt die Funktion 'None' zurück. Im Erfolgsfall gibt die Funktion ein Tuple Struct zurück. `usize` im Tuple Struct (.0) ist die Zahl, die bei der Multiplikation den gesuchten Hash ergibt und der Hash (.1) selbst ist der `String`
32
+
33
+Benutzen Sie dazu die hash Methode aus der Datei `hasher_sha256.rs`, die wiederum das externe [Crate sha2][] dafür benutzt.
34
+
35
+Schreiben Sie ein Display Trait für Solution, welche die `Solution` folgendermaßen ausgibt:
36
+
37
+```text
38
+Number: 110918 --> hash: 0e5e21f9f25b01c820a68025f2cffeb44df1649dbc3c8c1f4932518080651234
39
+```
40
+
41
+Suchen Sie mit Hilfe der *verify_product()* Funktion in *main()* solange nach der Zahl, bis diese das gewünschte Muster im Hash liefert.
42
+
43
+### Parsen der Argumente
44
+
45
+Um die Parameter beim Aufruf des Programms auszuwerten, benutzen Sie das externe [Crate clap][]. Halten Sie aber die Funktion *main()* so übersichtlich wie möglich. Lagern Sie dazu die benutzte Funktionalität des Crates clap in einer eigenen Funktion aus.
46
+
47
+Die folgende Beispielausgabe von **cargo run -- --help** soll Ihnen nur als Richtlinie dienen:
48
+
49
+```text
50
+Running `target/debug/task1 --help`
51
+Proof of Work Mechanism 0.1
52
+Satoshi Nakamoto
53
+now the basics in Rust, no C anymore
54
+
55
+USAGE:
56
+    task1 [FLAGS] <base> <difficulty> [SUBCOMMAND]
57
+
58
+FLAGS:
59
+    -h, --help       Prints help information
60
+    -v               Sets the level of verbosity
61
+    -V, --version    Prints version information
62
+
63
+ARGS:
64
+    <base>          Sets the base to use
65
+    <difficulty>    Sets the difficulty to use
66
+
67
+SUBCOMMANDS:
68
+    help       Prints this message or the help of the given subcommand(s)
69
+    timings    controls timing features
70
+```
71
+
72
+Der `-v` Parameter ist optional, muss somit nicht implementiert werden.
73
+
74
+Beim Aufruf **cargo run -- 42 12345** erhalten Sie als Ausgabe:
75
+
76
+```text
77
+Using base: 42
78
+Using difficulty: 12345
79
+Please wait ...
80
+Number: 567621 --> hash: b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345
81
+
82
+```
83
+
84
+### Subcommand 'timings'
85
+
86
+Das Subcommand 'timings' soll die Zeit ausgeben, die für das Suchen des Hashwertes benötigt wurde. Nutzen Sie dazu das [Crate time][]. Nur wenn beim Aufruf des Programms zusätzlich das Subcommand timings angegeben wird, wird eine Zeitmessung ausgeführt, welche als Ergebnis die Laufzeit der Suche ausgibt. Achten Sie darauf, wirklich nur die 'Suche' zu vermessen.
87
+
88
+Beim Aufruf **cargo run -- 42 12345 timings** erhalten Sie als Ausgabe:
89
+
90
+```text
91
+Using base: 42
92
+Using difficulty: 12345
93
+Please wait ...
94
+Number: 567621 --> hash: b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345
95
+(Duration: 9s / 9871ms / 9871841us)
96
+```
97
+
98
+Geben Sie das erhaltene Ergebnis jeweils in ganzen
99
+
100
+- Sekunden
101
+- Millisekunden und
102
+- Mikrosekunden
103
+
104
+aus.
105
+
106
+### Tests
107
+
108
+Binden Sie die `unit_tests.rs` ein. Ebenfalls befindet sich ein Test in der Datei `hasher_sha256.rs`
109
+
110
+### Optimierung
111
+
112
+Nutzen Sie das Unix Tool **time**, um zusätzliche Ausgaben über die Laufzeit Ihres Programms zu erhalten (Antworten in die Datei `ANSWERS.md`):
113
+
114
+- Wie ist die Ausgabe von **time** zu interpretieren?
115
+- Welche Laufzeiten erhalten Sie, wenn Sie `--release` benutzen?
116
+
117
+### Laufzeit Messungen
118
+
119
+Welche (ungefähre) Abhängigkeit der Laufzeit von der Difficulty können Sie im --release Mode bestimmen? Nutzen Sie für Ihre Messungen unterschiedliche base und difficulties (Diskussion Ihrer Ergebnisse in `ANSWERS.md`)
120
+
121
+[Crate clap]: https://docs.rs/clap/
122
+[Crate sha2]: https://docs.rs/sha2/
123
+[Crate time]: https://docs.rs/time/

+ 106
- 0
hw7/task1/hasher_sha256.rs Zobrazit soubor

@@ -0,0 +1,106 @@
1
+extern crate sha2;
2
+#[cfg(feature = "SHA2")]
3
+use self::sha2::Sha256;
4
+
5
+
6
+pub struct Sha256;
7
+
8
+pub trait Hasher {
9
+    type Output: HashResult;
10
+    fn hash(input: &[u8]) -> Self::Output;
11
+}
12
+
13
+pub trait HashResult {
14
+    /// Get the output in hex notation.
15
+    fn hex(&self) -> String;
16
+    /// Size of the output in bytes.
17
+    fn size() -> usize;
18
+}
19
+
20
+
21
+impl Hasher for Sha256 {
22
+    type Output = [u8; 32];
23
+
24
+    fn hash(input: &[u8]) -> Self::Output {
25
+        use self::sha2::*;
26
+        let mut tmp = Sha256::new();
27
+        tmp.input(input);
28
+        let r = tmp.result().as_slice().to_vec();
29
+        [
30
+            r[0],
31
+            r[1],
32
+            r[2],
33
+            r[3],
34
+            r[4],
35
+            r[5],
36
+            r[6],
37
+            r[7],
38
+            r[8],
39
+            r[9],
40
+            r[10],
41
+            r[11],
42
+            r[12],
43
+            r[13],
44
+            r[14],
45
+            r[15],
46
+            r[16],
47
+            r[17],
48
+            r[18],
49
+            r[19],
50
+            r[20],
51
+            r[21],
52
+            r[22],
53
+            r[23],
54
+            r[24],
55
+            r[25],
56
+            r[26],
57
+            r[27],
58
+            r[28],
59
+            r[29],
60
+            r[30],
61
+            r[31],
62
+        ]
63
+    }
64
+}
65
+
66
+impl HashResult for [u8; 32] {
67
+    fn hex(&self) -> String {
68
+        const HEX: [char; 16] = [
69
+            '0',
70
+            '1',
71
+            '2',
72
+            '3',
73
+            '4',
74
+            '5',
75
+            '6',
76
+            '7',
77
+            '8',
78
+            '9',
79
+            'a',
80
+            'b',
81
+            'c',
82
+            'd',
83
+            'e',
84
+            'f',
85
+        ];
86
+        let mut tmp = String::with_capacity(32 * 2);
87
+        for byte in self.iter() {
88
+            tmp.push(HEX[*byte as usize / 16]);
89
+            tmp.push(HEX[*byte as usize % 16]);
90
+        }
91
+        tmp
92
+    }
93
+
94
+    fn size() -> usize {
95
+        32
96
+    }
97
+}
98
+
99
+
100
+#[test]
101
+fn test_hash() {
102
+    assert_eq!(
103
+        Sha256::hash("test".as_bytes()).hex(),
104
+        "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
105
+    );
106
+}

+ 52
- 0
hw7/task1/unit_tests.rs Zobrazit soubor

@@ -0,0 +1,52 @@
1
+#[cfg(test)]
2
+mod tests {
3
+    use hash256;
4
+
5
+    #[test]
6
+    fn test_verify1() {
7
+        assert_eq!(
8
+            hash256::verify_product(42, 567621, "12345"),
9
+            Some(hash256::Solution(
10
+                567621,
11
+                "b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345"
12
+                    .to_string(),
13
+            ))
14
+        );
15
+    }
16
+
17
+    #[test]
18
+    #[should_panic]
19
+    fn test_verify2() {
20
+        assert_eq!(
21
+            hash256::verify_product(41, 567621, "12345"),
22
+            Some(hash256::Solution(
23
+                567621,
24
+                "b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345"
25
+                    .to_string(),
26
+            ))
27
+        );
28
+    }
29
+
30
+    #[test]
31
+    #[should_panic]
32
+    fn test_verify3() {
33
+        assert_eq!(
34
+            hash256::verify_product(42, 567620, "12345"),
35
+            Some(hash256::Solution(
36
+                567621,
37
+                "b6bea2a40ed1bd6d9999b2232072092f3df0e02c4b507aa3ad947367b9712345"
38
+                    .to_string(),
39
+            ))
40
+        );
41
+    }
42
+
43
+    #[test]
44
+    fn test_verify4() {
45
+        assert_eq!(hash256::verify_product(41, 567621, "12345"), None);
46
+    }
47
+
48
+    #[test]
49
+    fn test_verify5() {
50
+        assert_eq!(hash256::verify_product(42, 567622, "12345"), None);
51
+    }
52
+}

Loading…
Zrušit
Uložit