Author

Topic: Bitcoin in Perl6 (Read 2222 times)

legendary
Activity: 1190
Merit: 1004
June 06, 2012, 10:53:03 AM
#7
You should note when making the cryptography code that there are some irregularities with OpenSSL which is what bitcoin-qt uses and your code should be compatible with these irregularities. Discussed here: http://bitcoinstats.com/irc/bitcoin-dev/logs/2012/06/05/2#l3670669 It's possible that if you have a client that does not take care of these OpenSSL irregularities then particular public keys and maybe signatures in transactions would be accepted by OpenSSL but not your code. This means bitcoin-qt would accept the transactions as valid but your code wont.

I'm no expert on that though.
legendary
Activity: 1288
Merit: 1076
June 06, 2012, 05:16:38 AM
#6


I found out that a really slow part was the elliptic curve exponentiation (this is needed when converting a private key to a bitcoin address).

So I wrote a wrapper to make it possible to compute this using BC.  It is used when the environment variable "PERL6_EC_METHOD" is set to "BC".   It's now about five times faster.

Here is the bc code:

Code:
/*
 *
 * A small library for elliptic curve arithmetics and cryptography with
 * bitcoin.
 *
 *
 */

scale=0;

/* secp256k1 parameters */
ibase=16;
p= FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F;
b= 7;
a= 0;
gx=79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;
gy=483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;
go=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
ibase=A;

/* A modulo function that behaves well with negative numbers */
define true_mod(n, m) {
    if (n >= 0) return n%m else return -n*(m-1)%m;
}

/* modular inverse function */
define inverse_mod ( n, m ) {
    auto c, tc, d, td, uc, tuc, vc, tvc, ud, vd, q;
    c = true_mod(n, m); d = m; uc=1; vc=0; ud=0; vd=1; q=0;
    while (c != 0) {
q = d / c;
tc = c;
c = true_mod(d, c);
d = tc;

tuc = uc;
tvc = vc;
uc = ud - q*uc;
vc = vd - q*vc;
ud = tuc;
vd = tvc;
    }
    return true_mod(ud, m);
}

/* This test function should print a long sequence of '1'. */
define test_inverse_mod () {
    auto n, i;
    n = 2017;
    for (i=1; i}

/*
 * Elliptic curve operations.
 *
 * For simplicity, we'll ignore the possibiliy of a
 * point at horizon.
 *
 * BC functions can not return multiple values,
 * so we'll use a base-p encoding for points.
 *
 */

define add( point_a, point_b ) {
    auto i, l, x, y, xa, ya, xb, yb;
    xa = point_a / p; ya = point_a % p;
    xb = point_b / p; yb = point_b % p;
    i = inverse_mod( xb - xa, p );
    l = true_mod((yb - ya) * i, p);
    x = l^2 - xa - xb;
    y = l*(xa - x) - ya;
    return true_mod(x, p) *p + true_mod(y, p);
}

define double( point ) {
    auto l, x, y, xout, yout;
    x = point / p; y = point % p;
    l = true_mod((3*x^2 + a) * inverse_mod( 2*y, p ), p);
    xout = true_mod(l^2 - 2*x, p);
    yout = true_mod(l*(x - xout) - y, p);
    return xout * p + yout;
}

define mult( k, point ) {
    if (k == 1) return point;
    if (k == 2) return double( point );
    if (k % 2 == 0) return double( mult( k/2, point ) );
    return add(point, double( mult( k/2, point ) ));
}

];

our sub compute(Str $expression) {
    return map {:16($_)},
    qqx[
    echo "{code}
    tmp = $expression;
    obase=16;
    tmp / p
    tmp % p
    quit" |
    bc -q
    ].comb: /+/;
}
legendary
Activity: 1288
Merit: 1076
May 25, 2012, 10:16:48 AM
#5
Lots of improvements.  The Bitcoin::DataStream class is now implemented.  This allows me to create a block object from a hexdump and check its proof-of-work.

However, it requires a customed version of rakudo with more complete pack/unpack functions.  They can be found on my fork of rakudo: http://github.com/grondilu/rakudo

It's still pretty slow, though.  But I love the syntax of the whole thing, for instance for creating a new, random bitcoin address:

Code:
use Bitcoin;
say my $k = Bitcoin::Key.new;
say $k.address;


What is really missing now is a decent database library.  If someone would like to port BerkeleyDB on perl6, it would be awesome.
legendary
Activity: 1222
Merit: 1016
Live and Let Live
May 16, 2012, 08:52:30 AM
#4
This is still the most basic stuff and it is awefully slow but there is a begin to everything, right?

This is a very long term project anyway.

Yes!  Perl 6 is shaping to be the best thing since sliced bread!  Smiley

I wish I had more time to help this project... However all my time is going to Open Transactions.
legendary
Activity: 1288
Merit: 1076
May 16, 2012, 04:41:41 AM
#3
I created two github repositories:


You can now create addresses in Perl6:

Code:
use Bitcoin; my Bitcoin::Key $key .= new;  .say for $key, $key.address;

Or check an existing key or address:

Code:
use Bitcoin; say Bitcoin::Address.new: "1SomeSi11yAddressToCheckXXXXX";

This is still the most basic stuff and it is awefully slow but there is a begin to everything, right?

This is a very long term project anyway.
legendary
Activity: 1288
Merit: 1076
February 28, 2012, 06:29:00 AM
#2
I wrote a Crypto module.  Only Sha256 and rmd160 so far.

Sha256 seems to work fine but rmd160 returns wrong result FIXED

http://s0.barwen.ch/~grondilu/Crypto.pm6
legendary
Activity: 1288
Merit: 1076
January 26, 2012, 06:14:21 AM
#1
I'd like to help implementing Bitcoin in Perl6, one of the most awesome programming language of the future.

Here is the beginning, the Base58 encoding:

Code:
#!/usr/local/bin/perl6
module Bitcoin::Base58;

my @b58 = <
      1 2 3 4 5 6 7 8 9
    A B C D E F G H   J K L M N   P Q R S T U V W X Y Z
    a b c d e f g h i j k   m n o p q r s t u v w x y z
>;
my %b58 = @b58 Z ^58;

our sub decode(Str $x) returns Int { $x ~~ /.$/ ?? %b58{$/} + 58*&?ROUTINE($/.prematch) !! 0 }
our sub encode(Int $n) returns Str { $n < 58 ?? @b58[$n] !! &?ROUTINE($n div 58) ~ @b58[$n%58] }

More will come.
Jump to: