Blockchain
May 29, 2018
We represent a block as a four-slot vector:
(define (index block) (vector-ref block 0)) (define (datum block) (vector-ref block 1)) (define (phash block) (vector-ref block 2)) (define (chash block) (vector-ref block 3))
The Pearson hash is computed by concatenating the index
, datum
and phash
elements of a block, converting to strings as necessary:
(define (hash index datum phash) (pearson8 (string-append (number->string index) datum (number->string phash))))
We use the 8-bit version of the Pearson hash, but you could use the 16-bit version if you prefer. The genesis block has index 0, datum “Genesis Block”, and previous hash 0:
(define genesis (vector 0 "Genesis Block" 0 (hash 0 "Genesis Block" 0)))
Now it is easy to add a new block to a blockchain:
(define (adjoin chain datum) (let ((index (+ (index (car chain)) 1)) (phash (chash (car chain)))) (cons (vector index datum phash (hash index datum phash)) chain)))
Validating a blockchain is a little bit more work, because we have to visit every block in the chain:
(define (validate? chain) (define (valid? curr prev) (and (= (index curr) (+ (index prev) 1)) (= (phash curr) (chash prev)) (= (hash (index curr) (datum curr) (phash curr)) (chash curr)))) (if (null? (cdr chain)) (equal? (car chain) genesis) (and (valid? (car chain) (cadr chain)) (validate? (cdr chain)))))
And that’s it: blockchain in seventeen lines of code, not counting four lines from the previous exercise. Here is an example blockchain based on the titles of the five most recent exercises in this blog:
> (define b (list genesis)) > (set! b (adjoin b "Pearson Hashing")) > (set! b (adjoin b "Floyd's Triangle")) > (set! b (adjoin b "Billing Period")) > (set! b (adjoin b "Sum Embedded Numbers")) > (set! b (adjoin b "Help Wanted: Report Generator")) > (validate? b) #t > b (#(5 "Help Wanted: Report Generator" 192 216) #(4 "Sum Embedded Numbers" 70 192) #(3 "Billing Period" 59 70) #(2 "Floyd's Triangle" 106 59) #(1 "Pearson Hashing" 108 106) #(0 "Genesis Block" 0 108)) > (set! b (cons (car b) (cddr b))) > (validate? b) #f > b (#(5 "Help Wanted: Report Generator" 192 216) #(3 "Billing Period" 59 70) #(2 "Floyd's Triangle" 106 59) #(1 "Pearson Hashing" 108 106) #(0 "Genesis Block" 0 108))
The blockchain used by Bitcoin and other cryptocurrencies is only a little bit more complicated than this. It uses a proper hashing function, of course, it adds a timestamp to the block, and it includes a provision for merging chains when more than one person adds a block at the same time. The data is a series of accounting transactions — John Smith pays 3.7 bitcoin to Programming Praxis in exchange for programming services — and hundreds or thousands of accounting transactions are aggregated in each datum; the idea is that anyone can run back through the chain and determine who has how many bitcoin. There is also a proof of work that makes it costly (in terms of computer time) to add a transaction; thus, “miners” do the work of aggregating transactions and adding them to the blockchain, in exchange for micropayments of bitcoin deducted from each transaction they aggregate. But at its heart, Bitcoin is little more that what we have done here.
You can run the program at https://ideone.com/GozM0B.
[…] Blockchain […]
Here’s a solution in C using an XOR-based Pearson hashing (with the same table from the corresponding paper).
Output:
Here’s an updated hash function that fixes a memory leak (phash_str is now free’d).