Author

Topic: [BOUNTY] Mathematica fcns for RIPEMD-160 and base58 coding (0.05 BTC each) (Read 2961 times)

legendary
Activity: 1162
Merit: 1007
I'm with CaeZar on this one.  Peter R did just ask for base58 encode and decode, nothing about formatting it for bitcoin addresses.

Thanks for moderating Tysat.  I've paid out the bounty 0.075 BTC bounty to 19t2j4ZHfaNf1hX7YEDLZpdURcwvGywBhc:

https://blockchain.info/tx/9d003c3b4ca172d0d177480570b72fb683542a959c67f924e5c7c76ff5832a73

I learned from this experience that clarity in expectations is very important, and that one should include a cut-off date.  The debate in this thread cost me in time than the small bounty lol. 


newbie
Activity: 9
Merit: 0
0.075BTC payment acknowledged. Thank you.
legendary
Activity: 966
Merit: 1004
Keep it real
I'm with CaeZar on this one.  Peter R did just ask for base58 encode and decode, nothing about formatting it for bitcoin addresses.
newbie
Activity: 9
Merit: 0
While I agree with your statement that
Quote
we can't have a Jobs Market where the person posting the job needs to know more about the technical details than the person filling the job,
I still maintain that it is the responsibility of the person posting the bounty to clearly outline what is to be done. In this case, you said Base58Encode and Base58Decode, and that is what I did according to the common definition of the bitcoin community (that is why I quoted point 4 in the article you later stated as authoritative on the definitions.) This doesn't mean you need to be more technically aware than the person filling the job, but it does mean that you need to understand and be clear about the job requirements. When there was a disagreement, I offered up documentation of a common held view, you returned with: well, that was not what I was wanting
Quote
in my mind...
I'm sorry, but that is unfair as you can keep changing your mind and the requirements as the job progresses, which is what you have been doing. Originally it was base58encode, then base58encode plus '1s' character addition and in your latest post you again add more work, stating I should also do whatever is needed to prepend the base58 string with the requirements of p2sh. To be fair, you should pay the bounty for the work that has been done and negotiate a price with the worker for additional work. As it is, you are holding me hostage to continue doing more work to receive the pay due me for the work I've already done.

Never-the-less, regarding 1, that the added work of encoding the '1s' characters is still not done, you must have overlooked my post from May 21, 3:43:13. Note the addition to the front half of the code that counts the number of zero-bytes and adds the appropriate number of '1' characters and the corresponding test and output. I did the extra work anyway so that we could move on.

Please pay.

And by all means, contact a moderator if you think I'm being unfair.
legendary
Activity: 1162
Merit: 1007
This is not good.  This was an experiment that I hope succeeded because it would be useful to be able to submit small jobs and have people do them.  I take responsibility for not posting a closing date (and solving the problem myself in the meantime and posting part of the code in another thread); however, we can't have a Jobs Market where the person posting the job needs to know more about the technical details than the person filling the job.  If there was ambiguity, the job filler should ask a question.  In my mind it was obvious that I wanted to the base58 encode/decode functions used by bitcoin seeing how this is a bitcoin forum.  I can't think of any bitcoin related use for these functions without properly dealing with the version byte. 

However, I do see your point and I wish to resolve this issue.  It is difficult for me to pay you the full amount based on what you've done because that would set a bad precedent I think.  However, you have done something and it would be wrong for me to pay you nothing.  Here is my new proposal:

1.  I will pay the full bounty (0.075 BTC) if you complete Base58Encode[] and Base58Decode[] as per the bitcoin wiki I linked (deal with the version byte properly).  It should work for private keys, P2SH addresses and regular addresses. 

2.  I will pay you half the bounty for what you've done so far. 

3.  If you don't like either 1 or 2, we could ask for a second/third opinion from other senior members here regarding what they think is the best way to deal with this. 
legendary
Activity: 1162
Merit: 1007
This is not good.  This was an experiment that I hope succeeded because it would be useful to be able to submit small jobs and have people do them.  I take responsibility for not posting a closing date (and solving the problem myself in the meantime and posting part of the code in another thread); however, we can't have a Jobs Market where the person posting the job needs to know more about the technical details than the person filling the job.  If there was ambiguity, the job filler should ask a question.  In my mind it was obvious that I wanted to the base58 encode/decode functions used by bitcoin seeing how this is a bitcoin forum.  I can't think of any bitcoin related use for these functions without properly dealing with the version byte. 

However, I do see your point and I wish to resolve this issue.  It is difficult for me to pay you the full amount based on what you've done because that would set a bad precedent I think.  However, you have done something and it would be wrong for me to pay you nothing.  Here is my new proposal:

1.  I will pay the full bounty (0.075 BTC) if you complete Base58Encode[] and Base58Decode[] as per the bitcoin wiki I linked (at least deal with the version byte properly).  It should work for private keys, P2SH addresses and regular addresses. 

2.  I will pay you half the bounty for what you've done so far. 

3.  If you don't like either 1 or 2, we could ask for a second/third opinion from other senior members here regarding what they think is the best way to deal with this. 
newbie
Activity: 9
Merit: 0
For the sake of thorough code, here is some Mathematica that prepends the correct number of leading '1s' according to the Base58Check criteria when you put in the n->25 optional argument.
Code:
Options[Base58Encode] = {n -> None}; 
Base58Encode[x_Integer, OptionsPattern[]] :=
 StringJoin[
  If[OptionValue[n] === None, "",
   ConstantArray["1",
    Quotient[
     Length[TakeWhile[
       IntegerDigits[x, 16, 2*OptionValue[n]], # == 0 &]], 2]]],
  StringTake[
   "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
   Partition[1 + IntegerDigits[x, 58], 1]]]
It produces the correct result with the number you give:
Code:
In[55]:= Base58Encode[\
4265945407764313278158431948729033804705681414470582224586, n -> 25]

Out[55]= "1Grv3aiTr82o1kEgYV2QZD8UtLmhqHoBKX"
About your other comments, I don't agree that you have the right to refuse pay based on 4 and 6 as the added work of performing the Base58Check was never part of the bounty described in the OP, and I went beyond the requirements of the bounty to provide you with the additions to the code you wanted.

newbie
Activity: 9
Merit: 0
According to the OP, on which the bounty is detailed, the bounty hunter was to do a base58 decode and encode:
Quote
Base58Encode[x_Integer]    (returns Mathematica string)
Base58Decode[x_String]     (returns Mathematica integer)
There is no mention in the OP as to the number or nature of leading '1s' to include.
However, according to the document, https://en.bitcoin.it/wiki/Base58Check_encoding, which is the one you encouraged me to read, it defines what is meant by a normalized base-58 encoding in point 4:
Quote
Treating the results of step 3 - a series of bytes - as a single big-endian bignumber, convert to base-58 using normal mathematical steps (bignumber division) and the base-58 alphabet described below. The result should be normalized to not have any leading base-58 zeroes (character '1').
I refer your attention to the last sentence, that the result should have no leading base-58 zeroes (character '1').
This is precisely the functionality provided to you on May 20 at 4:22pm when you use the default function without specifying n, the base-58 encoding with no leading '1s'.
What you have been asking for since is the next step, which is the Base58Check, and beyond the scope of the bounty as described.
I am open to discuss this further if you wish; however --- respectfully --- I submit that the bounty is already completed and that no more work is required on my part.
Please send 0.075BTC the bounty to: 19t2j4ZHfaNf1hX7YEDLZpdURcwvGywBhc
legendary
Activity: 1162
Merit: 1007
This code doesn't appear to encode the version byte correctly in general.  The same function for Base58Check encoding for bitcoin addresses should work for private keys and P2SH address:  https://en.bitcoin.it/wiki/Base58Check_encoding
legendary
Activity: 1162
Merit: 1007
This code is still note dealing with the leading "1"s properly.  Here is proof:

Code:
In[83]:= 
addr
IntegerDigits[addr, 256, 25]
Base58Encode[addr, n->24]
Base58Encode[addr, n->25]
Base58Encode[addr, n->26]

Out[83]= 4265945407764313278158431948729033804705681414470582224586
Out[84]= {0,173,250,140,87,79,52,104,141,119,77,20,47,92,96,5,77,223,21,9,70,89,193,70,202}
Out[85]= Grv3aiTr82o1kEgYV2QZD8UtLmhqHoBKX
Out[86]= 11Grv3aiTr82o1kEgYV2QZD8UtLmhqHoBKX
Out[87]= 111Grv3aiTr82o1kEgYV2QZD8UtLmhqHoBKX

Output 86 and 87 both have one too many "1"s. 

As one of the conditions was:

4.  It must not make any mistakes on valid inputs.

and because this is the third re-submission I think you this now constitutes more than "a minor oversight" such that:

6.  I reserve the right to not pay the bounty if you break these rules, but I promise to be reasonable if there is a minor oversight.


However, despite the coincidence with the when I posted the (partial) code in another thread, I think you were working on this in good faith and it clearly is almost right.  I propose that we settle on half the bounty which works out to 0.0375 BTC (no resubmission required).  If this is acceptable to you, please post a bitcoin address. 
newbie
Activity: 9
Merit: 0
If you know the byte length you want encoded, you could do this instead:
Code:
Options[Base58Encode] = {n -> None}; 
Base58Encode[x_Integer, OptionsPattern[]] :=
 StringJoin[
  StringTake[
   "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
   Partition[
    1 + If[OptionValue[n] === None, IntegerDigits[x, 58],
      IntegerDigits[x, 58, Ceiling[OptionValue[n]*8/Log[2, 58]]]],
    1]]]
and test with
Code:
byteLength = 16;
i = RandomInteger[2^(8*byteLength), 100];
i = Join[i, {0, 2^(8*byteLength) - 1}];
{Base58Encode[#], Base58Encode[#, n -> byteLength]} & /@
  Sort[i] // TableForm
The first column doesn't define a byte length and the second does. In the second column, you always get the "right" amount of leading '1s', even if you get a value that would normally result in too few '1s'

BTW, this is the only thread I have been reading. I found my own mistake this morning when I was doing the RIPEMD-160 in Mathematica. I started that before I saw your post above. My code is very similar to yours, with minor differences:
Code:
f[j_Integer /; 0 < j <= 16, x_Integer, y_Integer, z_Integer] := 
  BitXor[x, y, z];
f[j_Integer /; 16 < j <= 32, x_Integer, y_Integer, z_Integer] :=
  BitOr[BitAnd[x, y], BitAnd[BitNot[x], z]];
f[j_Integer /; 32 < j <= 48, x_Integer, y_Integer, z_Integer] :=
  BitXor[BitOr[x, BitNot[y]], z];
f[j_Integer /; 48 < j <= 64, x_Integer, y_Integer, z_Integer] :=
  BitOr[BitAnd[x, z], BitAnd[y, BitNot[z]]];
f[j_Integer /; 64 < j <= 80, x_Integer, y_Integer, z_Integer] :=
  BitXor[x, BitOr[y, BitNot[z]]];

k = Flatten[
   ConstantArray[#, 16] & /@
    Floor@{0, 2^30 Sqrt[2], 2^30 Sqrt[3], 2^30 Sqrt[5], 2^30 Sqrt[7]}];
kp = Flatten[
   ConstantArray[#, 16] & /@
    Floor@{2^30 Surd[2, 3], 2^30 Surd[3, 3], 2^30 Surd[5, 3], 2^30 Surd[7, 3],
       0}];
I prefer putting j ranges on the LHS of the function rather than with an If on the RHS. Other than that, things seemed quite similar. I also defined my Rotate function in a slightly different way then you:
Code:
Rol[x_Integer, n_Integer] := 
 Mod[BitOr[BitShiftLeft[x, n], BitShiftRight[x, 32 - n]], 2^32]
legendary
Activity: 1162
Merit: 1007
I realize I botched this when I caught that after z should come 21 not 11 (all the leading unprinted digits are 1s), so here is the fixed version:
Code:
Options[Base58Encode] = {n -> None}; 
Base58Encode[x_Integer, OptionsPattern[]] :=
 StringJoin[
  StringTake[
   "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
   Partition[
    1 + If[OptionValue[n] === None, IntegerDigits[x, 58],
      IntegerDigits[x, 58, OptionValue[n]]], 1]]]
You can call it with a single parameter and get the shortest version of the number, or specify the number of digits (n) as an option.
Code:
i = RandomInteger[2^256]
Base58Encode[i]
Base58Encode[i, n -> 50]
I'll fix the decode in the next post, as it is wrong too. Sorry about that.


Hello CaeZar.  I like the way you tested the encode/decode functions using the random list.  That's what I do too. 

Your encode function is not quite correct, however.  It is still not dealing with the leading "1"s properly.  I think the option value "n" needs to be the amount of bytes to assume the number being encoded is composed of.  And then add a "1" for every byte that is zero.  The encoding for bitcoin is strange.  It is documented here and we were discussing it here

Like I said in the OP, you can fix this and resubmit to claim the bounty.
legendary
Activity: 1162
Merit: 1007
I guess I technically have to claim my own bounty for ripemd160 Smiley

Here is working code for ripemd160 adapted nearly verbatim from here. Sorry about the formatting, but it should paste back into Mathematica nicely. 

Code:
(*
   This function finds the RIPEMD160 hash of a list of bytes expressed as integers.
Integers greater than 255 and less than 0 are truncated to 8 bits.
This code was adapted from: http://www.win.tue.nl/~berry/2WC01/CryptographicHash-Collisions.nb

 *)

ripemd160[bytelist_List/;Or[And@@IntegerQ/@bytelist, Length[bytelist]==0]]:=Module[{f,y,z,s,h1,h2,h3,h4,h5,a,b,c,d,e,t,m,X,r,xx,i,j,k, x, BitRotateLeft, convert},

x = Flatten[IntegerDigits[bytelist, 2, 8]];

BitRotateLeft[x_,n_] := FromDigits[ RotateLeft[IntegerDigits[x,2,32],n],2];
convert[x_] := FromDigits[Reverse[IntegerDigits[x,256,4]],256];

f[j_,u_,v_,w_]:=
If[j<=16, BitXor[u,v,w],
If[j<=32,  BitOr[BitAnd[u,v],BitAnd[BitNot[u],w]], 
If[j<=48,  BitXor[BitOr[u,BitNot[v]],w],
If[j<=64, BitOr[BitAnd[u,w],BitAnd[v,BitNot[w]]],
BitXor[u,BitOr[v,BitNot[w]]]
]]]];
y[0,j_] := y[0,j] =If[j<=16, 0, If[j<=32, 16^^5a827999, If[j<=48, 16^^6ed9eba1, If[j<=64,16^^8f1bbcdc,16^^a953fd4e]] ]];
y[1,j_] := y[1,j] =If[j<=16, 16^^50a28be6, If[j<=32, 16^^5c4dd124, If[j<=48, 16^^6d703ef3, If[j<=64,16^^7a6d76e9,0]] ]];
z[0]=Flatten[{{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},{7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8},
{3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12},{1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2},{4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13}}];
z[1]=Flatten[{{5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12},{6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2},{15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13},{8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14},{12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11}}];
s[0]=Flatten[{{11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8},{7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12},{11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5},{11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12},{9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6}}];
s[1]=Flatten[{{8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6},{9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11},{9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5},{15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8},{8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11}}];
m=Ceiling[(Length[x]+65)/512];
r = 512m-Length[x]-64;
xx =  Join[x,{1},Table[0,{r-1}],Flatten[IntegerDigits[Reverse[IntegerDigits[Mod[Length[x],2^64],256,8]],2,8]]];
{h1,h2,h3,h4,h5} = {16^^67452301,16^^efcdab89,16^^98badcfe,16^^10325476,16^^c3d2e1f0};
For[i=0, iFor[j=0, j<16, j++, X[j]=FromDigits[Take[xx,512i+32j+{1,32}],2];];
For[k=0,k<=1,k++,
{a[k],b[k],c[k],d[k],e[k]} = {h1,h2,h3,h4,h5};
For[j=1, j<=80, j++, t = Mod[a[k] + f[(1-k) j+k(81-j),b[k],c[k],d[k]] +convert[ X[z[k][[j]]]] + y[k,j],2^32];
{a[k],b[k],c[k],d[k],e[k]} = {e[k],Mod[e[k]+BitRotateLeft[t,s[k][[j]]],2^32],b[k],BitRotateLeft[c[k],10],d[k]};
];
];
{h1,h2,h3,h4,h5}=Mod[{h2+c[0]+d[1],h3+d[0]+e[1],h4+e[0]+a[1],h5+a[0]+b[1],h1+b[0]+c[1]},2^32];
];
FromDigits[convert/@{h1,h2,h3,h4,h5},2^32]
];


If you want to add ripemd160 to the default Mathematica fuction Hash[], here's how for the most useful pattern types:

Code:
Unprotect[Hash];
Hash[x_List , "RIPEMD160"] := ripemd160[x]
Hash[x_String, "RIPEMD160"] := ripemd160[ToCharacterCode[x]]
Hash[x_Integer, "RIPEMD160"] := ripemd160[IntegerDigits[x, 256, 20]] (*160 bit integer assumed*)

Here is the correct output to the test vectors from http://homes.esat.kuleuven.be/~bosselae/ripemd160.html

Code:
In[63]:= 
Hash["", "RIPEMD160"]//IntegerString[#, 16]&
Hash["a", "RIPEMD160"]//IntegerString[#, 16]&
Hash["abc", "RIPEMD160"]//IntegerString[#, 16]&
Hash["message digest", "RIPEMD160"]//IntegerString[#, 16]&
Hash["abcdefghijklmnopqrstuvwxyz", "RIPEMD160"]//IntegerString[#, 16]&
Hash["abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "RIPEMD160"]//IntegerString[#, 16]&
Hash["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "RIPEMD160"]//IntegerString[#, 16]&
Hash[StringJoin@@Table["1234567890", {8}], "RIPEMD160"]//IntegerString[#, 16]&
Hash[StringJoin@@Table["a", {10^6}], "RIPEMD160"]//IntegerString[#, 16]&

Out[63]= 9c1185a5c5e9fc54612808977ee8f548b2258d31
Out[64]= bdc9d2d256b3ee9daae347be6f4dc835a467ffe
Out[65]= 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
Out[66]= 5d0689ef49d2fae572b881b123a85ffa21595f36
Out[67]= f71c27109c692c1b56bbdceb5b9d2865b3708dbc
Out[68]= 12a053384a9c0c88e405a06c27dcf49ada62eb2b
Out[69]= b0e20b6e3116640286ed3a87a5713079b21f5189
Out[70]= 9b752e45573d4b39f4dbd3323cab82bf63326bfb
Out[71]= 52783243c1697bdbe16d37f97f68f08325dc1528
legendary
Activity: 1162
Merit: 1007
Bounty for ripemd160[] is now terminated.  I have the solution for that too Smiley
legendary
Activity: 1162
Merit: 1007
This is actually pretty funny! I originally posted this bounty as an experiment to see how liquid the jobs market is around here.  No one responded, I forgot, and then I ended up doing this myself as documented here: https://bitcointalksearch.org/topic/question-about-base58-encoding-613068

I was thinking in the shower today "hmm, I think I forgot to put an expiry date on that bounty." 

Anyways, a deal's a deal as clearly I didn't specify a deadline, so I'll confirm the code and send you the bounty. 

But I am curious about the timing here.  The timestamp in this thread is May 17 @ 3:12 pm, but I didn't post the (partial) solution till May 17 @ 7:43 pm.  But then the leading "1"s problem wasn't fixed till today, after we had the discussion I linked to above specifically about the leading "1"s.  Coincidence I guess.


newbie
Activity: 9
Merit: 0
Here is the fixed decode:
Code:
Base58Decode[x_String] := 
 FromDigits[
  First[First[
      StringPosition[
        "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", \
#] - 1]] & /@ Characters[x], 58]
You can test these functions with:
Code:
ParallelDo[i = RandomInteger[2^256]; 
 If[i != Base58Decode[Base58Encode[i]], Print[False]], {100000}]
and
Code:
Table[{i, Base58Encode[i, n -> 5], Base58Decode[Base58Encode[i]]}, {i,
    0, 100}] // TableForm
newbie
Activity: 9
Merit: 0
I realize I botched this when I caught that after z should come 21 not 11 (all the leading unprinted digits are 1s), so here is the fixed version:
Code:
Options[Base58Encode] = {n -> None}; 
Base58Encode[x_Integer, OptionsPattern[]] :=
 StringJoin[
  StringTake[
   "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
   Partition[
    1 + If[OptionValue[n] === None, IntegerDigits[x, 58],
      IntegerDigits[x, 58, OptionValue[n]]], 1]]]
You can call it with a single parameter and get the shortest version of the number, or specify the number of digits (n) as an option.
Code:
i = RandomInteger[2^256]
Base58Encode[i]
Base58Encode[i, n -> 50]
I'll fix the decode in the next post, as it is wrong too. Sorry about that.
legendary
Activity: 3472
Merit: 1724
Since I trashed your redirection thread, I will re-post CaeZaR's post here:

Base58Encode
The Mod...NestWhileList...Quotient portion of the code breaks the string down into base-58, then the StringTake finds the appropriate symbol to encode it with from the dictionary.
Code:
Base58Encode[x_Integer] := 
 StringJoin[
  StringTake[
   "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
   Partition[
    Mod[Reverse[NestWhileList[Quotient[#, 58, 1] &, x + 1, # > 58 &]],
      58, 1], 1]]]
Base58Decode
The StringPosition...Characters portion is the dictionary conversion from characters to numbers, then the fold takes care of putting the numbers into the powers of 58.
Code:
Base58Decode[x_String] := 
 Fold[58 #1 + #2 &, 0,
   First[First[
       StringPosition[
        "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", \
#]]] & /@ Characters[x]] - 1
Please send the 0.075BTC bounty to 19t2j4ZHfaNf1hX7YEDLZpdURcwvGywBhc
I'll do the other shortly if I get this bounty. Thanks.
legendary
Activity: 1162
Merit: 1007
Bounty increased to 0.075 BTC each.
legendary
Activity: 1162
Merit: 1007
***This is posted in Auctions so that people cannot modify their posts to falsely claim the bounty***


I am looking for someone to deliver the following functions that will run in Mathematica 9.0:

Hash[x_, "RIPEMD160"]      (returns Mathematica integer)
Base58Encode[x_Integer]    (returns Mathematica string)
Base58Decode[x_String]     (returns Mathematica integer)

Mathematica currently support Hash[x_, "SHA256"] but not RIPEMD160.  There is a 0.05 BTC bounty to write a function that adds this support.  This function should behave exactly the same as the standard Hash[] function, just using RIPEMD160 instead. 

Mathematica currently does not support bitcoin base58 encoding and decoding.  There is a 0.05 BTC bounty if you deliver both encode/decode functions. 

Rules:

0.  Post your function(s) in this thread.  I will pay out the bounty to the first person who delivers. 
1.  Each function must be a single integrated function (i.e., it can only call standard Mathematica functions).
2.  Each function must be fairly concise (i.e., it cannot have piles of extraneous code--it must be clean). 
3.  It must not generate any warnings on valid inputs.
4.  It must not make any mistakes on valid inputs.
5.  You cannot post C code and tell me to "just change this or that," I will simply cut&paste the code and execute it in Mathematica and it will either work or not work. 
6.  I reserve the right to not pay the bounty if you break these rules, but I promise to be reasonable if there is a minor oversight. 
7.  I reserve the right to defer payment of the bounty for up to 48 hours to allow me time to test your functions.


***This is posted in Auctions so that people cannot modify their posts to falsely claim the bounty***
Jump to: