0

RPC does not return the raw transaction for the genesis block. I need to get this data for other coins to be able to add them to ABE.

https://github.com/bitcoin-abe/bitcoin-abe/blob/master/Abe/genesis_tx.py

As the RPC does not return it I presume that I need to somehow parse the actual blockchain files to extract it but have no idea how.

Any advice on getting the raw hex TX for any coin?

3 Answers 3

0
  1. take genesis block
  2. skip first 80 bytes
  3. convert rest bytes to hex
  4. that's all
3
  • I'm interested to know if "headers first" changes this. I'll report back Commented Mar 5, 2015 at 14:59
  • 1
    You need to skip more than 80 bites, 81 actually, because there is a variable length integer representing the number of transactions. You could also add the command to get the genesis block info.
    – morsecoder
    Commented May 6, 2015 at 17:24
  • Headers first does not change this. Commented Sep 5, 2015 at 14:15
1

Of course you can :) Bitcoin full node keeps a blockchain database in local machine.
Here is a step-by-step instruction to get the genesis transaction information.

  • Find block data file.s In mac, it locates at "~/Library/Application Support/Bitcoin/blocks/blkxxxxx.dat"
  • Use the given following code to decode the genesis block
  • Now got every detail about the genesis block and the coinbase transaction in genesis block, including tx_version, tx_input_num, tx_prev_output, script_length, scriptsig, sequence, tx_output_num ...
  • import struct # make conversation between Python values and C structsrepresented as Python strings
    import StringIO # Reads and writes a string buffer
    import mmap # mutable string
    
    class BCDataStream(object):
      def __init__(self):
        self.input = None
        self.read_cursor = 0
    
      def clear(self):
        self.input = None
        self.read_cursor = 0
    
      def write(self, bytes):  # Initialize with string of bytes
        if self.input is None:
          self.input = bytes
        else:
          self.input += bytes
    
      def map_file(self, file, start):  # Initialize with bytes from file
        self.input = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
        self.read_cursor = start
      def seek_file(self, position):
        self.read_cursor = position
      def close_file(self):
        self.input.close()
    
      def read_string(self):
        # Strings are encoded depending on length:
        # 0 to 252 :  1-byte-length followed by bytes (if any)
        # 253 to 65,535 : byte'253' 2-byte-length followed by bytes
        # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by bytes
        # ... and the Bitcoin client is coded to understand:
        # greater than 4,294,967,295 : byte '255' 8-byte-length followed by bytes of string
        # ... but I don't think it actually handles any strings that big.
        if self.input is None:
          raise SerializationError("call write(bytes) before trying to deserialize")
    
        try:
          length = self.read_compact_size()
        except IndexError:
          raise SerializationError("attempt to read past end of buffer")
    
        return self.read_bytes(length)
    
      def write_string(self, string):
        # Length-encoded as with read-string
        self.write_compact_size(len(string))
        self.write(string)
    
      def read_bytes(self, length):
        try:
          result = self.input[self.read_cursor:self.read_cursor+length]
          self.read_cursor += length
          return result
        except IndexError:
          raise SerializationError("attempt to read past end of buffer")
    
        return ''
    
      def read_boolean(self): return self.read_bytes(1)[0] != chr(0)
      def read_int16  (self): return self._read_num('<h')
      def read_uint16 (self): return self._read_num('<H')
      def read_int32  (self): return self._read_num('<i')
      def read_uint32 (self): return self._read_num('<I')
      def read_int64  (self): return self._read_num('<q')
      def read_uint64 (self): return self._read_num('<Q')
    
      def write_boolean(self, val): return self.write(chr(1) if val else chr(0))
      def write_int16  (self, val): return self._write_num('<h', val)
      def write_uint16 (self, val): return self._write_num('<H', val)
      def write_int32  (self, val): return self._write_num('<i', val)
      def write_uint32 (self, val): return self._write_num('<I', val)
      def write_int64  (self, val): return self._write_num('<q', val)
      def write_uint64 (self, val): return self._write_num('<Q', val)
    
      def read_compact_size(self):
        size = ord(self.input[self.read_cursor])
        self.read_cursor += 1
        if size == 253:
          size = self._read_num('<H')
        elif size == 254:
          size = self._read_num('<I')
        elif size == 255:
          size = self._read_num('<Q')
        return size
    
      def write_compact_size(self, size):
        if size < 0:
          raise SerializationError("attempt to write size < 0")
        elif size < 253:
           self.write(chr(size))
        elif size < 2**16:
          self.write('\xfd')
          self._write_num('<H', size)
        elif size < 2**32:
          self.write('\xfe')
          self._write_num('<I', size)
        elif size < 2**64:
          self.write('\xff')
          self._write_num('<Q', size)
    
      def _read_num(self, format):
        (i,) = struct.unpack_from(format, self.input, self.read_cursor)
        self.read_cursor += struct.calcsize(format)
        return i
    
      def _write_num(self, format, num):
        s = struct.pack(format, num)
        self.write(s)
    
    
    def import_blkdat():
        pass
    
    
    
    ds = BCDataStream()
    file = open("/Users/junton/Library/Application Support/Bitcoin/blocks/blk00000.dat", "rb")
    ds.map_file(file, 0)
    
    # Read file
    # https://bitcoin.org/en/developer-reference#block-headers
    # https://en.bitcoin.it/wiki/Protocol_specification#block
    magic            = ds.read_bytes(4).encode('hex')
    block_size       = int(ds.read_bytes(4).encode('hex'), 16)
    version          = ds.read_bytes(4).encode('hex')
    prev_header_hash = ds.read_bytes(32).encode('hex')
    merkle_root_hash = ds.read_bytes(32).encode('hex')
    timestamp        = ds.read_bytes(4).encode('hex')
    nBits            = ds.read_bytes(4).encode('hex')
    nonce            = ds.read_bytes(4).encode('hex')
    
    num_of_transaction = ds.read_bytes(1).encode('hex')
    tx_version         = ds.read_bytes(4).encode('hex')
    tx_input           = ds.read_bytes(1).encode('hex')
    tx_prev_output     = ds.read_bytes(36).encode('hex')
    script_length      = ds.read_bytes(1).encode('hex')
    scriptsig          = ds.read_bytes(int((script_length), 16)).encode('hex')
    sequence           = ds.read_bytes(4).encode('hex')
    tx_output          = ds.read_bytes(1).encode('hex')
    BTC_num            = ds.read_bytes(8).encode('hex')
    pk_script_len      = ds.read_bytes(1).encode('hex')
    pk_script          = ds.read_bytes(int(pk_script_len, 16)).encode('hex')
    lock_time          = ds.read_bytes(4).encode('hex')
    
    
    print 'magic: '       + magic
    print 'block_size: '  + str(block_size)
    print 'version: '     + version
    print 'prevHash: '    + prev_header_hash
    print 'merkle_root: ' + merkle_root_hash
    print 'timestamp: '   + timestamp
    print 'nBits: '       + nBits
    print 'nonce: '       + nonce
    
    print '--------------------- Transaction Details: ---------------------'
    print 'num_of_transaction: ' + num_of_transaction
    print 'tx_version: ' + tx_version
    print 'tx_input_num: ' + tx_input
    print 'tx_prev_output: ' + tx_prev_output
    print 'script_length: ' + script_length
    print 'scriptsig: ' + scriptsig
    print 'sequence: ' + sequence
    print 'tx_ouput_num: ' + tx_output
    print 'BTC_num: ' + BTC_num
    print 'pk_script_len: ' + pk_script_len
    print 'pk_script: ' + pk_script
    print 'lock_time: ' + lock_time
    
    ds.close_file()
    
    0

    The Genesis Block and it's related transaction are generated by the Bitcoin Core client using this section of code. I do not know if it is actually stored on disk.

    I also have it recreated in JSON form on Github

    /**
     * Build the genesis block. Note that the output of its generation
     * transaction cannot be spent since it did not originally exist in the
     * database.
     *
     * CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
     *   CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
     *     CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
     *     CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
     *   vMerkleTree: 4a5e1e
     */
    const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
    CMutableTransaction txNew;
    txNew.vin.resize(1);
    txNew.vout.resize(1);
    txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
    txNew.vout[0].nValue = 50 * COIN;
    txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
    genesis.vtx.push_back(txNew);
    genesis.hashPrevBlock.SetNull();
    genesis.hashMerkleRoot = genesis.BuildMerkleTree();
    genesis.nVersion = 1;
    genesis.nTime    = 1231006505;
    genesis.nBits    = 0x1d00ffff;
    genesis.nNonce   = 2083236893;
    
    consensus.hashGenesisBlock = genesis.GetHash();
    assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
    assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
    
    1
    • 1
      It is stored on disk when you first open the client. Commented Sep 5, 2015 at 14:16

    Your Answer

    By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

    Not the answer you're looking for? Browse other questions tagged or ask your own question.