[](https://travis-ci.org/akaalias/blockchain-toy)
[Full Github Repo here](https://github.com/akaalias/blockchain-toy)
Yesterday I watched [Anders Brownworth's awesome Blockchain demo](https://github.com/anders94/blockchain-demo) and got inspired to follow along in Clojure.
I _had_ to play around with implementing a toy (read: unoptimized!) algorithm to "mine" for nonces that, when added to the hashing input, produces n zeros at the beginning of the hash:
I came up with `make-nonce-for-zeros-finder`, a function which takes the numbers of zeros you want to have at the beginning and a maximum search-depth and returns a function that will calculate the right nonce for your inputs.
What I personally enjoyed about this little exercise was to express an iterative process in a simple recursive function. And to make a function-maker once I wanted to play around with different types of hashes/nonces I wanted to find.
```clojure
(with-test
(defn make-nonce-for-zeros-finder [z-count]
(fn
([num data]
((make-nonce-for-zeros-finder z-count) num data 0))
([num data nonce]
(cond (= (generate-zeros-string z-count) (subs (generate-hash num data nonce) 0 z-count)) nonce
:else (recur num data (inc nonce))))))
(is (= ((make-nonce-for-zeros-finder 1) nil nil) 39))
(is (= ((make-nonce-for-zeros-finder 1) 1 nil) 25))
(is (= ((make-nonce-for-zeros-finder 1) 1 1) 11))
(is (= ((make-nonce-for-zeros-finder 1) "foo" "bar" 0) 20))
(is (= ((make-nonce-for-zeros-finder 2) nil nil) 286))
(is (= ((make-nonce-for-zeros-finder 4) nil nil) 88484))
(is (= ((make-nonce-for-zeros-finder 4) 1 1) 64840))
(is (= ((make-nonce-for-zeros-finder 4) "foo" "bar") 42515)))
```
With it, I can quickly create finders for different lengths of zero paddings:
```clojure
(def find-nonce-for-one-zero-padded-hash
(make-nonce-for-zeros-finder 1))
(def find-nonce-for-two-zeros-padded-hash
(make-nonce-for-zeros-finder 2))
(def find-nonce-for-three-zeros-padded-hash
(make-nonce-for-zeros-finder 3))
(def find-nonce-for-four-zeros-padded-hash
(make-nonce-for-zeros-finder 4))
(def find-nonce-for-five-zeros-padded-hash
(make-nonce-for-zeros-finder 5))
(def find-nonce-for-six-zeros-padded-hash
(make-nonce-for-zeros-finder 6))
;; and so on...
```
With these guys set up, we can now calculate the nonce for hashes with 1, 2, 3, 4 and 5 zeros padded. Let's see how that looks:
```clojure
(find-nonce-for-one-zero-padded-hash "foo" "bar")
;; => 20
;; takes less than a millisecond
;; we can verify that the hash has one zero at the beginning:
(generate-hash "foo" "bar" 20)
;; => "0fdc57809f5917eba08907d2805e43ce83f4c933a090b4a2b2549923a35e43d7"
(find-nonce-for-two-zeros-padded-hash "foo" "bar")
;; => 102
;; takes less than a millisecond
;; we can verify that the hash has two zeros at the beginning:
(generate-hash "foo" "bar" 102)
;; => "006668bba91b7e2d5b5357b56600784edb77a72ecf86dc09d515853a841485f6"
(find-nonce-for-three-zeros-padded-hash "foo" "bar")
;; => 4663
;; takes less than a millisecond
;; we can verify that the hash has three zeros at the beginning:
(generate-hash "foo" "bar" 4663)
;; => "0005d9cd6c13fe6bf56e169fd2a7008003fc3a4c6539f8a1cf7d82975d00210e"
```
And that's really all there is to it. Once you cross 6 padded zeros, you'll notice an increase in time it takes to compute.
## How to test
I've been a huge fan of the `with-test` macro. Because of that, you'll find all test-coverage in core.clj instead of a separate "\_test.clj" file.
To run all tests, use `lein test`
## Related
- [[Thinking And Sleeping Better With Clojure]]