Pages:
Author

Topic: A full shell script implementation of bitcoin ? - page 2. (Read 14288 times)

legendary
Activity: 1288
Merit: 1080
Code:
$ openssl dgst -sha256 -hex <<< "hello, world"
853ff93762a06ddbf722c4ebe9ddd66d8f63ddaea97f521c3ecc20da7c976020
$

Cheers,

different version of openssl I guess.

$ openssl version
OpenSSL 1.0.0c 2 Dec 2010
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
Well, when I run openssl dgst -sha1 -hex <<<"hello, world", I get an annoying:

(stdin)= cd50d19784897085a8d0e3e413f8612b097c03f1


I wish there was an option not to display this "(...)= " before my result.  Anyway that's why I had to add a 'sed "s/^.* //"'.

Ah, this doesn't happen here — I only see that SHA256 digest:

Code:
$ openssl dgst -sha256 -hex <<< "hello, world"
853ff93762a06ddbf722c4ebe9ddd66d8f63ddaea97f521c3ecc20da7c976020
$

Cheers,
legendary
Activity: 1288
Merit: 1080
But you have to get rid of the annoying 'std(...)= ':

Huh?  I don't get you…

Well, when I run openssl dgst -sha1 -hex <<<"hello, world", I get an annoying:

(stdin)= cd50d19784897085a8d0e3e413f8612b097c03f1


I wish there was an option not to display this "(...)= " before my result.  Anyway that's why I had to add a 'sed "s/^.* //"'.
hero member
Activity: 616
Merit: 500
Firstbits.com/1fg4i :)
(just subscribing to the thread)
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
But you have to get rid of the annoying 'std(...)= ':

Huh?  I don't get you…

Quote
I didn't know that there were actually 2 sha256 passes, just like for the hash of the block itself.

Neither did I, but it was worth a try.

Quote
(also, you can use '|' at the end of line without using '\')

(I know, but I think explicit line continuations are more legible.)

Quote
Now how to deal with blocks with a number of transactions that are not a power of 2?

You tell me. Wink

Cheers,
legendary
Activity: 1288
Merit: 1080
How about

Code:
{ bigEndianHex2littleEndianHex <<<"$a" | xxd -p -r ;
   bigEndianHex2littleEndianHex <<<"$b" | xxd -p -r ; } \
   | openssl dgst -sha256 -binary \
   | openssl dgst -sha256 -hex \
   | bigEndianHex2littleEndianHex

That would give the third hash, wouldn't it?

It does indeed!   But you have to get rid of the annoying 'std(...)= ':

I didn't know that there were actually 2 sha256 passes, just like for the hash of the block itself.

Code:
{ bigEndianHex2littleEndianHex <<<"$a" | xxd -p -r ;
   bigEndianHex2littleEndianHex <<<"$b" | xxd -p -r ; }  |
   openssl dgst -sha256 -binary |
   openssl dgst -sha256 -hex |
   sed 's/.* //' |
   bigEndianHex2littleEndianHex

(also, you can use '|' at the end of line without using '\')

Now how to deal with blocks with a number of transactions that are not a power of 2?
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
Code:
{ bigEndianHex2littleEndianHex <<<"$a" |xxd -p -r ; bigEndianHex2littleEndianHex <<<"$b" |xxd -p -r ; } |openssl dgst -sha256 -hex

How about

Code:
{ bigEndianHex2littleEndianHex <<<"$a" | xxd -p -r ;
   bigEndianHex2littleEndianHex <<<"$b" | xxd -p -r ; } \
   | openssl dgst -sha256 -binary \
   | openssl dgst -sha256 -hex \
   | bigEndianHex2littleEndianHex

That would give the third hash, wouldn't it?

Cheers,
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better

I'm pretty sure it doesn't matter, since xxd does only read hexadecimal characters.

Code:
echo "A 1" |xxd -p -r |xxd -p 
a1
echo -n "A 1" |xxd -p -r |xxd -p
a1

Oh, great, I should have checked that, of course…

Cheers,
legendary
Activity: 1288
Merit: 1080
You are aware that the bashism <<< appends a LF (ASCII 10) to its argument, right?

Code:
$ sha256sum e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  -
$ sha256sum <<< ''
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b  -
$ printf '\n' | sha256sum
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b  -
$ hexdump -C <<< a
00000000  61 0a                                             |a.|
00000002
$

In the same vein: perhaps bigEndianHex2littleEndianHex() should use echo -n or printf instead of just echo

I'm pretty sure it doesn't matter, since xxd -p -r does only read hexadecimal characters.


echo "A 1" |xxd -p -r |xxd -p
a1
echo -n "A 1" |xxd -p -r |xxd -p
a1
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
My first attempt is this code:

Code:
{ bigEndianHex2littleEndianHex <<<"$a" |xxd -p -r ; bigEndianHex2littleEndianHex <<<"$b" |xxd -p -r ; } |openssl dgst -sha256 -hex

Needless to say, the version without bigEndianHex2littleEndianHex didn't work either.

You are aware that the bashism <<< appends a LF (ASCII 10) to its argument, right?

Code:
$ sha256sum e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  -
$ sha256sum <<< ''
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b  -
$ printf '\n' | sha256sum
01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b  -
$ hexdump -C <<< a
00000000  61 0a                                             |a.|
00000002
$

In the same vein: perhaps bigEndianHex2littleEndianHex() should use echo -n or printf instead of just echo

Cheers,
legendary
Activity: 1288
Merit: 1080

Ok now, let's try to make the Merkle tree.

The first block with more than one transaction is the block 170.  It has two transactions and its Merkle tree is:

{
"b1fea52486ce0c62bb442b530a3f0132b826c74e473d1f2c220bfa78111c5082",
"f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
"7dac2c5666815c17a3b36427de37bb9d2e2c5ccec3f8633eb91a4205cb4c10ff"
}

The third is the Merkle root.

My first attempt is this code:

Code:
{ bigEndianHex2littleEndianHex <<<"$a" |xxd -p -r ; bigEndianHex2littleEndianHex <<<"$b" |xxd -p -r ; } |openssl dgst -sha256 -hex

Needless to say, the version without bigEndianHex2littleEndianHex didn't work either.
legendary
Activity: 3920
Merit: 2349
Eadem mutata resurgo
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.

I agree that a Busybox dependency limitation would be a good place to put some boundaries to begin with.
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
(we actually don't need tr either, by the way)

(You're right, I suppose we can always take for granted that the strings are 64 characters wide…)

Cheers,
legendary
Activity: 1288
Merit: 1080
yep, I've edited (we actually don't need tr either, by the way).

I also tested on the second block.  I worked fine.
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
Thanks, that helped!

Cool!  Smiley

The following patch might make the script a tad more computationally efficient:

Code:
diff --git a/bashhash.sh b/bashhash.sh
index a99bf9d..1bddd92 100644
--- a/bashhash.sh
+++ b/bashhash.sh
@@ -24,8 +24,8 @@ time=1231006505
 bits=486604799
 nonce=2083236893
 
-printf "%8x%8x%8x%64s%64s%8x" $nonce $bits $time $mrkl_root $prev_block $ver |
-sed 's/ /0/g' |
+printf "%08x%08x%08x%64s%64s%08x" $nonce $bits $time $mrkl_root $prev_block $ver |
+tr ' ' '0' |
 bigEndianHex2littleEndianHex |
 xxd -r -p |
 openssl dgst -sha256 -binary |

If basically uses printf to format the numbers, and uses tr instead of sed.

Cheers,
legendary
Activity: 1288
Merit: 1080
Thanks, that helped!

Code:
#{
#  "hash":"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
#  "ver":1,
#  "prev_block":"0000000000000000000000000000000000000000000000000000000000000000",
#  "mrkl_root":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
#  "time":1231006505,
#  "bits":486604799,
#  "nonce":2083236893,

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

ver=1
prev_block=0000000000000000000000000000000000000000000000000000000000000000
mrkl_root=4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
time=1231006505
bits=486604799
nonce=2083236893

printf "%08x%08x%08x%064s%064s%08x" $nonce $bits $time $mrkl_root $prev_block $ver |
bigEndianHex2littleEndianHex |
xxd -r -p |
openssl dgst -sha256 -binary |
openssl dgst -sha256 -hex |
sed 's/^.* //' |
bigEndianHex2littleEndianHex

I can't really give the bounty since the solution was not complete.  But thanks again.
hero member
Activity: 566
Merit: 500
Unselfish actions pay back better
Code:
  xxd -pr

Am I right when I assume that xxd is supposed to produce a binary block that corresponds to the hex stream?  If so, then ‘xxd -p -r’ might be what you're looking for.  E.g.

Code:
# A=0x41, B=0x42, C=0x43
$ echo 414243 | xxd -r -p && echo
ABC
$

Not that it helps much in the actual situation…

Cheers,
full member
Activity: 144
Merit: 100
Perhaps this will help:

printf "%s%s%s%s%s%s" 01000000 0000000000000000000000000000000000000000000000000000000000000000 3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a 29ab5f49 ffff001d 1dac2b7c | xxd -r -p | openssl dgst -sha256 -binary | openssl dgst -sha256 -hex

6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000

A key thing you were missing is byte swapping.  I manually byte-swapped all the inputs.  You'll have to figure out how to script that.
legendary
Activity: 1288
Merit: 1080

I know this is a poor programming method, but I've tried a whole bunch of combinations for the size of each value:

Code:
#{
#  "hash":"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
#  "ver":1,
#  "prev_block":"0000000000000000000000000000000000000000000000000000000000000000",
#  "mrkl_root":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
#  "time":1231006505,
#  "bits":486604799,
#  "nonce":2083236893,

ver=1
prev_block=0000000000000000000000000000000000000000000000000000000000000000
 mrkl_root=4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
time=1231006505
bits=486604799
nonce=2083236893

for s in - ''
do for a in 2 4
do for b in 64 128
do for c in 16 24 32
do
    printf "%$s${a}x%$s${b}s%$s${b}s%$s${c}x%$s${c}x%$s${c}x" $ver $prev_block $mrkl_root $time $bits $nonce |
    sed 's/ /0/g' |
    xxd -pr |
    openssl dgst -sha256 -binary |
    openssl dgst -sha256 -hex |
    sed 's/^.* //'
done
done
done
done

None of them works.


I pledge 5 BTC to whoever finds the correct way.
legendary
Activity: 3920
Merit: 2349
Eadem mutata resurgo

Would that be a bash hash or a hash bash?

Bang hash bash

Hash bang boom!
Pages:
Jump to: