From a2abe1753f763b777a7d5e10d0d65d572442acb4 Mon Sep 17 00:00:00 2001
From: Diego Martinelli <martinelli.diego@gmail.com>
Date: Fri, 8 May 2009 10:33:20 +0200
Subject: [PATCH 1/4] Initial commit

---
 extra/hashcash/authors.txt     | 0
 extra/hashcash/hashcash.factor | 4 ++++
 2 files changed, 4 insertions(+)
 create mode 100755 extra/hashcash/authors.txt
 create mode 100755 extra/hashcash/hashcash.factor

diff --git a/extra/hashcash/authors.txt b/extra/hashcash/authors.txt
new file mode 100755
index 0000000000..e69de29bb2
diff --git a/extra/hashcash/hashcash.factor b/extra/hashcash/hashcash.factor
new file mode 100755
index 0000000000..fe7cf10bd3
--- /dev/null
+++ b/extra/hashcash/hashcash.factor
@@ -0,0 +1,4 @@
+! Copyright (C) 2009 Your name.
+! See http://factorcode.org/license.txt for BSD license.
+USING: ;
+IN: hashcash

From dedb1d753660d719bf9b3924179359b2458765f6 Mon Sep 17 00:00:00 2001
From: Diego Martinelli <martinelli.diego@gmail.com>
Date: Sat, 9 May 2009 17:23:41 +0200
Subject: [PATCH 2/4] Main implementation done. Need docs and tests.

---
 extra/hashcash/authors.txt     |  1 +
 extra/hashcash/hashcash.factor | 90 +++++++++++++++++++++++++++++++++-
 2 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/extra/hashcash/authors.txt b/extra/hashcash/authors.txt
index e69de29bb2..f6e3b59c4c 100755
--- a/extra/hashcash/authors.txt
+++ b/extra/hashcash/authors.txt
@@ -0,0 +1 @@
+Diego Martinelli
diff --git a/extra/hashcash/hashcash.factor b/extra/hashcash/hashcash.factor
index fe7cf10bd3..3e75aad94c 100755
--- a/extra/hashcash/hashcash.factor
+++ b/extra/hashcash/hashcash.factor
@@ -1,4 +1,90 @@
-! Copyright (C) 2009 Your name.
+! Copyright (C) 2009 Diego Martinelli.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: ;
+USING: accessors byte-arrays calendar calendar.format 
+checksums checksums.openssl classes.tuple 
+fry kernel make math math.functions math.parser math.ranges 
+present random sequences splitting strings syntax ;
 IN: hashcash
+
+! Hashcash implementation
+! Reference materials listed below:
+! 
+! http://hashcash.org
+! http://en.wikipedia.org/wiki/Hashcash
+! http://www.ibm.com/developerworks/linux/library/l-hashcash.html?ca=dgr-lnxw01HashCash
+! 
+! And the reference implementation (in python):
+! http://www.gnosis.cx/download/gnosis/util/hashcash.py
+
+<PRIVATE
+
+! Return a string with today's date in the form YYMMDD
+: get-date ( -- str )
+    now [ year>> 100 mod pad-00 ] 
+        [ month>> pad-00 ] 
+        [ day>> pad-00 ] tri 3append ;
+
+! Random salt is formed by ascii characters
+! between 33 and 126
+: available-chars ( -- seq )
+    33 126 [a,b] [ CHAR: : = not ] filter ;
+
+PRIVATE>
+
+! Generate a 'length' long random salt
+: salt ( length -- salted )
+    available-chars '[ _ random ] "" replicate-as ;
+
+TUPLE: hashcash version bits date resource ext salt suffix ;
+
+: <hashcash> ( -- tuple )
+    hashcash new
+        1 >>version
+        20 >>bits
+        get-date >>date
+        8 salt >>salt ;
+
+M: hashcash string>> 
+    tuple-slots [ present ] map ":" join ;
+
+<PRIVATE
+
+: sha1-checksum ( str -- bytes )
+    openssl-sha1 checksum-bytes ; inline
+
+: set-suffix ( tuple guess -- tuple )
+    >hex >>suffix ;
+
+: get-bits ( bytes -- str )
+    [ >bin 8 CHAR: 0 pad-head ] { } map-as concat ;
+
+: checksummed-bits ( tuple -- relevant-bits )
+    dup string>> sha1-checksum
+    swap bits>> 8 / ceiling head get-bits ;
+
+: all-char-zero? ( seq -- ? )
+    [ CHAR: 0 = ] all? ; inline
+
+: valid-guess? ( checksum tuple -- ? )
+    bits>> head all-char-zero? ;
+
+: (mint) ( tuple counter -- tuple ) 
+    2dup set-suffix checksummed-bits pick 
+    valid-guess? [ drop ] [ 1+ (mint) ] if ;
+
+PRIVATE>
+
+: mint* ( tuple -- str )
+    0 (mint) string>> ;
+
+: mint ( resource -- str )
+    <hashcash>
+        swap >>resource
+    mint* ;
+
+! One might wanna add check based on the date,
+! passing a 'good-until' duration param
+: check-stamp ( stamp -- ? )
+    dup ":" split [ sha1-checksum get-bits ] dip
+    second string>number head all-char-zero? ;
+

From ef5c9844e4fe34e207f6795605c44d05746d5e3c Mon Sep 17 00:00:00 2001
From: Diego Martinelli <martinelli.diego@gmail.com>
Date: Sun, 10 May 2009 14:20:23 +0200
Subject: [PATCH 3/4] Done with docs and unit tests.

---
 extra/hashcash/hashcash.factor | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/extra/hashcash/hashcash.factor b/extra/hashcash/hashcash.factor
index 3e75aad94c..1eb690b20f 100755
--- a/extra/hashcash/hashcash.factor
+++ b/extra/hashcash/hashcash.factor
@@ -74,10 +74,10 @@ M: hashcash string>>
 
 PRIVATE>
 
-: mint* ( tuple -- str )
+: mint* ( tuple -- stamp )
     0 (mint) string>> ;
 
-: mint ( resource -- str )
+: mint ( resource -- stamp )
     <hashcash>
         swap >>resource
     mint* ;

From 85facc27d6c610fabc142cc1476c44d5f59b2ec0 Mon Sep 17 00:00:00 2001
From: Diego Martinelli <martinelli.diego@gmail.com>
Date: Sun, 10 May 2009 14:27:35 +0200
Subject: [PATCH 4/4] Ops.

---
 extra/hashcash/hashcash-docs.factor  | 60 ++++++++++++++++++++++++++++
 extra/hashcash/hashcash-tests.factor | 15 +++++++
 extra/hashcash/summary.txt           |  1 +
 3 files changed, 76 insertions(+)
 create mode 100644 extra/hashcash/hashcash-docs.factor
 create mode 100644 extra/hashcash/hashcash-tests.factor
 create mode 100644 extra/hashcash/summary.txt

diff --git a/extra/hashcash/hashcash-docs.factor b/extra/hashcash/hashcash-docs.factor
new file mode 100644
index 0000000000..2cfe0bb68e
--- /dev/null
+++ b/extra/hashcash/hashcash-docs.factor
@@ -0,0 +1,60 @@
+USING: help.markup help.syntax kernel math ;
+IN: hashcash
+
+ARTICLE: "hashcash" "Hashcash"
+"Hashcash is a denial-of-service counter measure tool."
+$nl
+"A hashcash stamp constitutes a proof-of-work which takes a parameterizable amount of work to compute for the sender. The recipient can verify received hashcash stamps efficiently."
+$nl
+"More info on hashcash:"
+$nl
+{ $url "http://www.hashcash.org/" } $nl
+{ $url "http://en.wikipedia.org/wiki/Hashcash" } $nl
+{ $url "http://www.ibm.com/developerworks/linux/library/l-hashcash.html?ca=dgr-lnxw01HashCash" } $nl
+"This library provide basic utilities for hashcash creation and validation."
+$nl
+"Creating stamps:"
+{ $subsection mint }
+{ $subsection mint* }
+"Validation:"
+{ $subsection check-stamp }
+"Hashcash tuple and constructor:"
+{ $subsection hashcash }
+{ $subsection <hashcash> }
+"Utilities:"
+{ $subsection salt } ;
+
+{ mint mint* <hashcash> check-stamp salt } related-words
+
+HELP: mint
+{ $values { "resource" "a string" } { "stamp" "generated stamp" } }
+{ $description "This word generate a valid stamp with default parameters and the specified resource." } ;
+
+HELP: mint*
+{ $values { "tuple" "a tuple" } { "stamp" "generated stamp" } }
+{ $description "As " { $snippet "mint" } " but it takes an hashcash tuple as a parameter." } ;
+
+HELP: check-stamp
+{ $values { "stamp" "a string" } { "?" boolean } }
+{ $description "Check for stamp's validity. Only supports hashcash version 1." } ;
+
+HELP: salt
+{ $values { "length" integer } { "salted" "a string" } }
+{ $description "It generates a random string of " { $snippet "length" } " characters." } ;
+
+HELP: <hashcash>
+{ $values { "tuple" object } }
+{ $description "It fill an hashcash tuple with the default values: 1 as hashcash version, 20 as bits, today's date as date and a random 8 character long salt" } ;
+
+HELP: hashcash
+{ $class-description "An hashcash object. An hashcash have the following slots:"
+    { $table
+        { { $slot "version" } "The version number. Only version 1 is supported." }
+        { { $slot "bits" } "The claimed bit value." }
+        { { $slot "date" } "The date a stamp was minted." }
+        { { $slot "resource" } "The resource for which a stamp is minted." }
+        { { $slot "ext" } "Extensions that a specialized application may want." }
+        { { $slot "salt" } "A random salt." }
+        { { $slot "suffix" } "The computed suffix. This is supposed to be manipulated by the library." }
+    }
+} ;
diff --git a/extra/hashcash/hashcash-tests.factor b/extra/hashcash/hashcash-tests.factor
new file mode 100644
index 0000000000..efef40acfa
--- /dev/null
+++ b/extra/hashcash/hashcash-tests.factor
@@ -0,0 +1,15 @@
+USING: accessors sequences tools.test hashcash ;
+
+[ t ] [ "foo@bar.com" mint check-stamp ] unit-test
+
+[ t ] [ 
+    <hashcash> 
+        "foo@bar.com" >>resource 
+        16 >>bits 
+    mint* check-stamp ] unit-test
+
+[ t ] [ 
+    "1:20:040927:mertz@gnosis.cx::odVZhQMP:7ca28" check-stamp
+] unit-test
+
+[ 8 ] [ 8 salt length ] unit-test
diff --git a/extra/hashcash/summary.txt b/extra/hashcash/summary.txt
new file mode 100644
index 0000000000..e5ec1d4064
--- /dev/null
+++ b/extra/hashcash/summary.txt
@@ -0,0 +1 @@
+Hashcash implementation