Pages:
Author

Topic: [BOUNTY] Pushpool question (Read 7875 times)

newbie
Activity: 37
Merit: 0
February 06, 2014, 12:53:35 PM
#37
Deleted... I figured it out.
legendary
Activity: 910
Merit: 1000
November 29, 2013, 01:03:00 PM
#36
I came across this thread after looking for info to convert the solution that pushpoold reports into the blockhash.  It anyone is interested, I've written  php code for this.
full member
Activity: 175
Merit: 102
July 25, 2011, 11:59:23 AM
#35
Speaking of which, where might I find code to do this in C/C++?
Baiscally, any C miner has this code.

EDIT : Here -> http://pastebin.com/Ya3604J0

= awesome. Thanks!
hero member
Activity: 731
Merit: 503
Libertas a calumnia
July 25, 2011, 03:13:36 AM
#34
btw: I can't find any documentation about the extraNonce: where is it recorded?
why I can't see it on blockexplorer and such?
legendary
Activity: 1372
Merit: 1008
1davout
July 25, 2011, 01:53:52 AM
#33
Speaking of which, where might I find code to do this in C/C++?
Baiscally, any C miner has this code.

EDIT : Here -> http://pastebin.com/Ya3604J0
full member
Activity: 175
Merit: 102
July 23, 2011, 04:13:31 AM
#32
Speaking of which, where might I find code to do this in C/C++?

Thinking about adding this to my version of pushpool.
legendary
Activity: 1372
Merit: 1008
1davout
July 21, 2011, 03:06:19 AM
#31
The only TOS I was able to find was "This server is up more than 99% of the time, but anything that pulls data from here should still be prepared for failure." on the real time stats page.  Is there another TOS I've missed?
IIRC theymos stated something around the lines of this, I might be completely wrong here though.

The link you provided to the "getblockbyhash" patch went to a rails bitcoin-pool.  Is the patch here or at another location?
I found it on Jeff Garzik's github bitcoin fork, it's funny, I went to check on the repo and I can't find the branch I used to compile bitcoin with the getblock RPC call built-in, maybe it's been included upstream. You might want to look this up because it's a pretty convenient and reliable way to get info about blocks Smiley

Ok, found it, it's on the "getblockbycount" branch and hasn't been merged upstream.
https://github.com/jgarzik/bitcoin/tree/getblockbycount
newbie
Activity: 42
Merit: 0
July 20, 2011, 02:03:04 PM
#30
Perhaps he is talking about this post?

I am looking for help if anybody can tell me how to perform that patch :S (Never patched anything before!)
newbie
Activity: 10
Merit: 0
July 20, 2011, 01:22:56 PM
#29
Davout:
I appreciate the heads-up about blockexplorer.  It's a great service and I do not want to end up spamming it.  The only TOS I was able to find was "This server is up more than 99% of the time, but anything that pulls data from here should still be prepared for failure." on the real time stats page.  Is there another TOS I've missed?

The link you provided to the "getblockbyhash" patch went to a rails bitcoin-pool.  Is the patch here or at another location?
legendary
Activity: 1372
Merit: 1008
1davout
July 20, 2011, 10:05:08 AM
#28
go to block explorer (via something like mechanize) to find information about the block (specifically the txid)
better, trust your local data (and abide by block explorer's ToS), use the getblockbyhash patch to pull the generation tx id in order to track confirmations for the block and possible orphan status, see https://github.com/davout/bitcoin-pool for the complete implementation
newbie
Activity: 10
Merit: 0
July 20, 2011, 09:50:40 AM
#27
For testnet solution "000000010b362ab3ec365c55dce00249fb087cb90ebf2208c4e97aa60022678a00000000616eb86 4ec5d0265277b564b916219818bad92cce0d52af9e3e748306af986384e206c1a1c00824f2a78f6 a600000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000"

Download the ruby code from http://pastebin.com/y0sMZSbi and save it as 'block_header.rb'
make sure ruby and irb (interactive ruby shell) are installed. 

Code:
irb
irb(main):001:0> load "./block_header.rb"
=> true
irb(main):003:0> b = BlockHeader.new("000000010b362ab3ec365c55dce00249fb087cb90ebf2208c4e97aa60022678a00000000616eb864ec5d0265277b564b916219818bad92cce0d52af9e3e748306af986384e206c1a1c00824f2a78f6a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
=> #
irb(main):006:0> b.block_hash
=> "00000000001b2ff1c57142a9d90592ea3be28fe747da10a889c90afc03ab6e7b"

I've found ruby mechanize (http://mechanize.rubyforge.org/) to be a good way to access web pages (such as block explorer)  your block info will be at http://blockexplorer.com/testnet/block/00000000001b2ff1c57142a9d90592ea3be28fe747da10a889c90afc03ab6e7b

scRUBYt! (http://www.justinspradlin.com/programming/ruby-screen-scraping-with-scrubyt/) makes a good screen scraper for pulling transaction info (txid) from block explorer.

Lastly, you will need a json-rpc library (such as http://json-rpc.rubyforge.org/ - see the client side section) to pull transaction data from bitcoind.

Now you have all of the pieces!
  • generate a solution that gets logged into the pushpool shares table
  • have ruby search the shares table to find a solution
  • use block_header.rb in your code to convert your solution into a valid block_hash
  • go to block explorer (via something like mechanize) to find information about the block (specifically the txid)
  • use json-rpc to pull information from bitcoind to find a matching transaction number
  • find useful things out about your block such as confirmations, amount generated, invalid
  • use this information to transfer bitcoins where needed
full member
Activity: 175
Merit: 102
July 19, 2011, 04:57:21 PM
#26
And a port to C#, for anyone who may want/need it.  

This isn't exactly the most efficient way to do it but will serve the purpose. I've also done a couple of things to make the returned values slightly more convenient for consumption purposes.

A .NET pushpool will need this, which is why I bothered to take the time...

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

    public class Block
    {
        private static DateTime UTC_ORIGIN = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        private static HashAlgorithm SHA256provider = Environment.OSVersion.Version.Major >= 6 ? new SHA256CryptoServiceProvider() : SHA256.Create();

        public string Solution { get; private set; }
        public long Version { get; private set; }
        public long Header { get; private set; }
        public string PreviousBlockHash { get; private set; }
        public string MerkleRoot { get; private set; }
        public DateTime TimeStamp { get; private set; }
        public long Bits { get; private set; }
        public long Nonce { get; private set; }

        private string computedBlockHash = string.Empty;
        public string BlockHash
        {
            get
            {
                // Lazy-load this when required since this is a CPU-intensive operation
                if (string.IsNullOrEmpty(this.computedBlockHash))
                {
                    this.computedBlockHash = ComputeBlockHash(this.GenerateHashableString());
                }

                return this.computedBlockHash;
            }
        }

        public Block(string solution)
        {
            this.Solution = solution;
            this.Construct();
        }

        private void Construct()
        {
            string raw = this.Solution.Substring(0, 160);

            Version = Convert.ToInt64(raw.Substring(0, 8), 16);                         // @version ||= @raw[0, 8].hex
            PreviousBlockHash = SwitchHexStringEndianness(raw.Substring(8, 64));        // @previous_block ||= switch_endianness(@raw[8, 64])
            MerkleRoot = SwitchHexStringEndianness(raw.Substring(72, 64));              // @merkle_root ||= switch_endianness(@raw[72, 64])
            TimeStamp = FromUnixTimestamp(Convert.ToInt64(raw.Substring(136, 8), 16));  // @timestamp ||= @raw[136, 8].hex
            Bits = Convert.ToInt64(raw.Substring(144, 8), 16);                          // @bits ||= @raw[144, 8].hex
            Nonce = Convert.ToInt64(raw.Substring(152, 8), 16);                         // @nonce ||= @raw[152, 8].hex
        }

        public override string ToString()
        {
            StringBuilder retBldr = new StringBuilder("Block:" + Environment.NewLine);
            retBldr.AppendFormat("Solution={0}{1}", this.Solution, Environment.NewLine);
            retBldr.AppendFormat("Version={0}{1}", this.Version, Environment.NewLine);
            retBldr.AppendFormat("PreviousBlockHash={0}{1}", this.PreviousBlockHash, Environment.NewLine);
            retBldr.AppendFormat("MerkleRoot={0}{1}", this.MerkleRoot, Environment.NewLine);
            retBldr.AppendFormat("TimeStamp={0}{1}", this.TimeStamp, Environment.NewLine);
            retBldr.AppendFormat("Bits={0}{1}", this.Bits, Environment.NewLine);
            retBldr.AppendFormat("Nonce={0}{1}", this.Nonce, Environment.NewLine);
            retBldr.AppendLine();
            retBldr.AppendFormat("BlockHash={0}{1}", this.BlockHash, Environment.NewLine);

            return retBldr.ToString();
        }

        private string GenerateHashableString()
        {
            return ReverseBytesInBinaryString(string.Format("{0:X8}", this.Version))
                    + ReverseBytesInBinaryString(this.PreviousBlockHash)
                    + ReverseBytesInBinaryString(this.MerkleRoot)
                    + ReverseBytesInBinaryString(string.Format("{0:X8}", ConvertToUnixTimestamp(this.TimeStamp)))
                    + ReverseBytesInBinaryString(string.Format("{0:X8}", this.Bits))
                    + ReverseBytesInBinaryString(string.Format("{0:X8}", this.Nonce));
        }


        private static string SwitchHexStringEndianness(string str)
        {
            string result = "";
            while (str.Length > 0)
            {
                result += str.Substring(str.Length - 8);
                str = str.Substring(0, str.Length - 8);
            }
            return result;
        }

        private static string ComputeBlockHash(string hashableString)
        {
            byte[] bytes = ConvertHexStringToBinary(hashableString);

            string hex = BytesToHexString(SHA256provider.ComputeHash(SHA256provider.ComputeHash(bytes)));
            return ReverseBytesInBinaryString(hex);
        }

        private static string BytesToHexString(byte[] a)
        {
            StringBuilder sb = new StringBuilder(a.Length * 2 + 2);
            foreach (byte b in a)
            {
                sb.AppendFormat("{0:X2}", b);
            }
            return sb.ToString().ToLower();
        }

        private static string ReverseBytesInBinaryString(string str)
        {
            return ConvertBinaryToHexString(ConvertHexStringToBinary(str));
        }

        private static string ConvertBinaryToHexString(byte[] bytes)
        {
            // Reverse the endianness of the byte array
            Array.Reverse(bytes);
            return BytesToHexString(bytes);
        }

        private static byte[] ConvertHexStringToBinary(string str)
        {
            List items = new List();
            for (int i = 0; i < str.Length / 2; i++)
            {
                items.Add(Convert.ToByte(str.Substring(i * 2, 2), 16));
            }
            return items.ToArray();
        }
        
        private static DateTime FromUnixTimestamp(long timestamp)
        {
            return UTC_ORIGIN.AddSeconds((double)timestamp);
        }

        private static long ConvertToUnixTimestamp(DateTime date)
        {
            TimeSpan diff = date - UTC_ORIGIN;
            return (long)diff.TotalSeconds; // Reminder: will truncate fractional seconds
        }
    }

Using is easy:

Code:
                Block b = new Block("solution string");
                Console.WriteLine(b.ToString());
sr. member
Activity: 448
Merit: 250
July 04, 2011, 12:01:18 PM
#25
Here's a Java port of the ruby code, for anyone who may need it.

Quote
/*
 * Java code to Parse Solution
 */

package com.kokade.utils;

import java.util.Date;

/**
 *
 * @author Andrew P Ross - apr at kent.ac.uk
 */
public class Block {
    public Block(String solution) {
        //Creates a block from a solution; not sure if i'll make this an entity soon
        this.solution = solution;
        construct();
    }
    
    
    public static void main(String args[]) {
        Block b= new Block(args[0]);
        System.out.println(b);
    }
    private String solution;
    private long version;
    private String header;
    private String previousBlockHash;
    private String merkleRoot;
    private Date timeStamp; //To change to date pl0iz.
    private long bits;
    private long nonce;
    
    private void construct() {
        String raw         = solution.substring(0,160);
        
        
        version           = Long.parseLong( raw.substring(0,8), 16);// @version ||= @raw[0, 8].hex
        previousBlockHash = switchEnd(raw.substring(8,8+64)); // @previous_block ||= switch_endianness(@raw[8, 64])
        merkleRoot        = switchEnd(raw.substring(72,72+64)); //@merkle_root ||= switch_endianness(@raw[72, 64])
        timeStamp         = new Date(Long.parseLong( raw.substring(136,136+8),16 ));  // @timestamp ||= @raw[136, 8].hex
        bits              = Long.parseLong( raw.substring(144,144+8), 16); //  @bits ||= @raw[144, 8].hex
        nonce             = Long.parseLong(raw.substring(152,152+8), 16); // @nonce ||= @raw[152, 8].hex

        
    }
    
    private String switchEnd(String string) {
        String str = string;
        String result = "";
        
        while(str.length() > 0) {
            
            result += str.substring(str.length()-8, str.length());
            str = str.substring(0, str.length() - 8 );
        }
        return result;
    }

  
    @Override
    public String toString() {
        return String.format("Block [solution=%s, version=%s, header=%s, previousBlockHash=%s, merkleRoot=%s, timeStamp=%s, bits=%s, nonce=%s]",
                solution, version, header, previousBlockHash, merkleRoot, ((timeStamp==null)?"null":timeStamp.getTime()), bits, nonce);
    }

    public long getBits() {
        return bits;
    }

    public String getHeader() {
        return header;
    }

    public String getMerkleRoot() {
        return merkleRoot;
    }

    public long getNonce() {
        return nonce;
    }

    public String getPreviousBlockHash() {
        return previousBlockHash;
    }

    public String getSolution() {
        return solution;
    }

    public Date getTimeStamp() {
        return timeStamp;
    }

    public long getVersion() {
        return version;
    }
    
    
  
}


Quote
java Block 00000001d219003dfd0ec774541ac59c6b566c2b11a64e99d745a2e70028f3e100000000fc415a3 869208702e88db306d9473f116b0412fd76739780b29953fea82d83d24e11de451c00824f8c5b32 da00000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000
Block [solution=00000001d219003dfd0ec774541ac59c6b566c2b11a64e99d745a2e70028f3e100000000fc415a3869208702e88db306d9473f116b0412fd76739780b29953fea82d83d24e11de451c00824f8c5b32da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, version=1, header=null, previousBlockHash=000000000028f3e1d745a2e711a64e996b566c2b541ac59cfd0ec774d219003d, merkleRoot=a82d83d2b29953fe767397806b0412fdd9473f11e88db30669208702fc415a38, timeStamp=1309793861, bits=469795407, nonce=2354787034]

http://blockexplorer.com/testnet/block/00000000005784f943f091bb8383aebd97333f129510f6327c084f58de25a1e9


Obviously, remove the "main" to use it in other code as a bean or whatnot.
legendary
Activity: 1372
Merit: 1008
1davout
June 21, 2011, 03:18:44 PM
#24
Thanks a lot  Cheesy
I'm happy it helps you !
newbie
Activity: 44
Merit: 0
June 21, 2011, 03:13:38 PM
#23
Thanks a lot  Cheesy
legendary
Activity: 1372
Merit: 1008
1davout
June 21, 2011, 12:30:01 PM
#22
Hope this helps, don't hesitate.

Code:
irb(main):005:0> bh = BlockHeader.new('0000000150c549978a44e3ef671a4ed3f5b922195ebde0fbbccfdb5900e6827000000000c8a03dfb42fa04d47e9fbfd3e6afcb3d0df2b516eb86f4e64d09fe53cc397b6c4de61f4c1c069652a228e13d000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000')
=> #           
irb(main):008:0> bh.hash
=> "000000000055825d01acc3dcc80d02671c2e75ab5b692940446e9b8615ea3824"
irb(main):009:0> bh.previous_block
=> "0000000000e68270bccfdb595ebde0fbf5b92219671a4ed38a44e3ef50c54997"
irb(main):010:0> bh.nonce
=> 2720588093
irb(main):011:0> bh.timestamp
=> 1306926924
irb(main):012:0> bh.version
=> 1
irb(main):013:0> bh.merkle_root
=> "cc397b6c4d09fe53eb86f4e60df2b516e6afcb3d7e9fbfd342fa04d4c8a03dfb"
irb(main):014:0> bh.bits
=> 470193746
newbie
Activity: 44
Merit: 0
June 21, 2011, 11:57:30 AM
#21
Hi,

Sadly I have no idea of ruby, but is no problem runnind it in shell.
My question exactly is: what command do I have to use, in order to retrieve the (previous)blokchash.
I tried already 

bh = BlockHeader.new(shareValue)
bh.inspect
puts bh

I get everytime a new hexvalue.

thank you
legendary
Activity: 1372
Merit: 1008
1davout
June 21, 2011, 11:40:45 AM
#20
thats sad :/
What is your question exactly ? If you need someone to feed you an already made PHP solution I think you're out of luck :

If what you want is use my code you just need a ruby interpreter
newbie
Activity: 44
Merit: 0
June 21, 2011, 11:32:41 AM
#19
thats sad :/
newbie
Activity: 44
Merit: 0
June 19, 2011, 11:25:24 AM
#18
Hello,

could some please provide a php solution to this problem, or tell where i need to put the
share result in the ruby programm.
I couldn't figure it out.

regards, redshark1802
Pages:
Jump to: