Pages:
Author

Topic: A full shell script implementation of bitcoin ? (Read 14308 times)

legendary
Activity: 1288
Merit: 1080
February 18, 2022, 04:49:42 PM
#66
Sorry for necro-posting, but a github user pointed me to that thread so I felt like updating subscribers.


This project is still alive, though updates are rare.

Feel free to check it out : https://github.com/grondilu/bitcoin-bash-tools/
full member
Activity: 158
Merit: 100
aquí dice algo personal.
All of this is very impressive. Someone made a wiki?
legendary
Activity: 1288
Merit: 1080
I see on your github only a small subset of the things discussed in this thread.  How is this going?  Have you put it up somewhere?  I want to see it!

Sorry but I haven't got used to github as I basically don't like using it.  Also I don't have a permanent internet access, and I don't think about updating it when I connect.

Sorry but you'll have to extract the code from this thread.
newbie
Activity: 34
Merit: 0
I see on your github only a small subset of the things discussed in this thread.  How is this going?  Have you put it up somewhere?  I want to see it!
bji
member
Activity: 112
Merit: 10
I've been rediscovering Perl recently.  It's the coolest programming language I know.

Do I like Perl?  No, I hate perl.  It is sometimes acceptable when used in a very limited way for short-lived scripts intended to accomplish an immediate goal.  Perl code should be written, used once or twice, and then thrown away.
legendary
Activity: 1288
Merit: 1080
I've been rediscovering Perl recently.  It's the coolest programming language I know.

Code:
#!/usr/bin/perl
use strict;
use warnings;

use Digest::SHA qw(sha256);

my @base58 = (1 .. 9, 'A' .. 'H', 'J' .. 'N', 'P' .. 'Z', 'a' .. 'k', 'm' .. 'z');
my $base58 = join '', @base58;

sub decodeBase58($) {
    my $_ = shift;
    die "wrong format" if not m{^[$base58]+$};
    for my $c (0..57) { s/$base58[$c]/ $c/g }
    s/ /+58*/g;
    return qx{dc -e "16o0d$_+n"};
}

sub encodeBase58($) {
    my $_ = uc shift;
    open my $bc, qq[echo "ibase=16; n=$_; while(n>0) { n%3A; n/=3A }" | bc |];
    return join '', map { $base58[$_] } (reverse <$bc>);
}

sub checksum($) { return uc unpack 'H8', sha256 sha256 pack 'H*', shift }

sub checkBitcoinAddress($) {
    my $address = shift;
    die "wrong format" if $address !~ qr(^[$base58]{34,35}$);
    (my $h = sprintf "%50s", decodeBase58 $address) =~ tr/ /0/;

    (checksum substr $h, 0, -8) eq substr $h, -8;
}

sub hash160($) {
    # I have to use the shell here for there is no rmd160 in Digest:: :-(
    my $h = shift;
    open my $sh, qq{
    echo -n "$h" |
    openssl dgst -sha256 -binary |
    openssl dgst -rmd160 -binary |
    };
    return uc unpack 'H*', <$sh>;
}

sub hash160ToAddress($) {
    my $_ = shift;
    my $checksum = checksum "00$_";
    $_ = sprintf "%34s", encodeBase58 "00$_$checksum";
    tr/ /1/;
    return $_;
}

sub publicKeyToAddress($) {
    # Couldn't find a Perl library for ECDSA,
    # so I use the shell here.
    my $_ = shift;
    return hash160ToAddress hash160 qx{
    echo "$_" |
    openssl ec -pubin -pubout -outform DER 2>&- |
    tail -c 65
    }
}
legendary
Activity: 1288
Merit: 1080

Could someone write a C/C++ program that could allow me to test this portion of code in irc.cpp ?

Code:
#pragma pack(push, 1)
struct ircaddr
{
    int ip;
    short port;
};
#pragma pack(pop)

string EncodeAddress(const CAddress& addr)
{
    struct ircaddr tmp;
tmp.ip    = addr.ip;
    tmp.port  = addr.port;

    vector vch(UBEGIN(tmp), UEND(tmp));
    return string("u") + EncodeBase58Check(vch);
}

I need to do some trial and error testing of the bash equivalent.
legendary
Activity: 3920
Merit: 2349
Eadem mutata resurgo
Post #35 in this thread.

Quote
grondilu:
Quote
I also wonder if all communications could not be done using HTTP.  Blocks would be published via http GET method (giving the hash of the preceding block), and transactions could be sent via POST method.

One advantage of using http would be that it would be very hard for governments to forbid.

Where did you get to with the network connection side of this, netcat could be an option.
legendary
Activity: 1288
Merit: 1080
You should use the wildly available "netcat" ("nc") to connect to the IRC server !

Thanks for the tip about netcat, I didn't know about it.  So many things to
know and only one life ;(
hero member
Activity: 826
Merit: 500
nice development. cant wait to see all the tools finished
member
Activity: 83
Merit: 10
The French Pool
Hi,

Warning ! "/dev/tcp/" is not available everywhere !
Disabled on some new Linux OS (Debian 6, ...) for more security.

You should use the wildly available "netcat" ("nc") to connect to the IRC server !

By the way, your script is very interesting !

(Sorry for my English, I'm french)

macman31
full member
Activity: 182
Merit: 100
Subscribing, very interesting Wink
legendary
Activity: 1288
Merit: 1080

Connecting to IRC is actually much easier than I thought.  I still have to request my IP and format my nick, though.

Code:
#!/bin/bash
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
#

################################################################################
#
#                                 BASE 58 encoding/decoding
#
# Requires bc, dc, openssl, xxd
################################################################################

base58=({1..9} {A..H} {J..N} {P..Z} {a..k} {m..z})
bitcoinregex="^[$(printf "%s" "${base58[@]}")]{34}$"

decodeBase58() {
    local s=$1
    for i in {0..57}
    do s="${s//${base58[i]}/ $i}"
    done
    dc <<< "16o0d${s// /+58*}+f"
}

encodeBase58() {
    # 58 = 0x3A
    bc <<<"ibase=16; n=${1^^}; while(n>0) { n%3A ; n/=3A }" |
    tac |
    while read n
    do echo -n ${base58[n]}
    done
}

checksum() {
    xxd -p -r <<<"$1" |
    openssl dgst -sha256 -binary |
    openssl dgst -sha256 -binary |
    xxd -p -c 80 |
    head -c 8
}

checkBitcoinAddress() {
    if [[ "$1" =~ $bitcoinregex ]]
    then
        h=$(decodeBase58 "$1")
        checksum "00${h::${#h}-8}" |
        grep -qi "^${h: -8}$"
    else return 2
    fi
}

hash160() {
    # binary data expected on stdin
    openssl dgst -sha256 -binary |
    openssl dgst -rmd160 -binary |
    xxd -p -c 80
}

hash160ToAddress() {
    printf "%34s\n" "$(encodeBase58 "00$1$(checksum "00$1")")" |
    sed "y/ /1/"
}

publicKeyToAddress() {
    hash160ToAddress $(
    openssl ec -pubin -pubout -outform DER 2>/dev/null |
    tail -c 65 |
    hash160
    )
}

bigEndianHex2littleEndianHex() {
    local s
    while read -n 2 c
    do s=$c$s
    done
    echo $s
}

bitcoinHash() {
    bigEndianHex2littleEndianHex |
    xxd -p -r |
    openssl dgst -sha256 -binary |
    openssl dgst -sha256 -binary |
    xxd -p -c 80 |
    bigEndianHex2littleEndianHex
}

################################################################################
#
#                                 IRC communication
#
# most of this comes from http://shudder.daemonette.org/source/BashNP-Guide.txt
################################################################################

host="irc.lfnet.org" port=6667 channel="#bitcoinTEST" mode="+i"

nick="$USER$$"
name="$USER's bitcoin bot script"

if
    # try to connect
    ! exec 3<> /dev/tcp/$host/$port
then
    echo "$(basename $0): unable to connect to $host:$port" 1>&2
    exit 1
else
    # duplicate standard input and output with the newly created socket
    exec 0<&3 1>&3-

    # register to the server
    echo "USER $nick ${mode:-+iw} $nick :$name"
    echo "NICK $nick"
    # join channel
    echo "JOIN $channel"

    while read
    do
set -- ${REPLY//$'\r'/}

# answer the critical ping request
# otherwise the server will disconnect us
[[ "$1" == "PING" ]] && echo "PONG $2"

echo $REPLY >&2

    done

    exec 1<&-
fi
legendary
Activity: 1288
Merit: 1080
how far are we from a total implementation?

Very far.
hero member
Activity: 616
Merit: 500
Firstbits.com/1fg4i :)
how far are we from a total implementation?
legendary
Activity: 1288
Merit: 1080
The last hash is doubled.

Indeed.  I thought I had tried that but I guess I did it wrong.

Thanks.
administrator
Activity: 5222
Merit: 13032
The last hash is doubled.
legendary
Activity: 1288
Merit: 1080
Here is the Merkle tree for block 95002, which had three transactions:

Code:
"mrkl_tree":[
"4fa598026d9be1ca0c2bff1b531e566b7ea7f90b72e75fda0c1795bc2dfa375c",
"186640daf908156e2616790d7c816235b0c43f668c3c38351b348c08ca44d457",
"ef3928700309b4deceac9a992a19a7481b4e520cbc0b1ab74e2645eee39c8da0",
"688c53517f62f7a65c0e87519c18a4de98f2ccafbf389b269d0bb867f88d166a",
"01889506f7fe9210045f588361881e2d16a034a62bc48ebd7b6b0a3edeaf5a6d",
"74f3a7df861d6a58957b84a3e425a8cf57e1e2e3a3def046dd200baeb8714f00"
]

I rewrote the two bash functions:

Code:
bigEndianHex2littleEndianHex() {
    local s=''
    while read -n 2 char
        do s=$char$s
    done
    echo $s
}

bitcoinHash() {
    bigEndianHex2littleEndianHex |
    xxd -p -r |
    openssl dgst -sha256 -binary |
    openssl dgst -sha256 -binary |
    xxd -p -c 80 |
    bigEndianHex2littleEndianHex
}


The fourth entry of the Merkle tree is easy to reconstitute.  It's obviously made out of the first two.

bitcoinHash <<<"186640daf908156e2616790d7c816235b0c43f668c3c38351b348c08ca44d457
4fa598026d9be1ca0c2bff1b531e566b7ea7f90b72e75fda0c1795bc2dfa375c"


But then, I don't know how to get the fith out of the third.
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
different version of openssl I guess.

$ openssl version
OpenSSL 1.0.0c 2 Dec 2010

Yes, I'm running OpenSSL 0.9.8k 25 Mar 2009 (from Ubuntu Lucid).

Cheers,
Pages:
Jump to: