<p>This is a bit late, but I've been struggling with this myself so hopefully I can help out anyone who comes across this thread with a similar question:</p>

<p>Looks like the <code>chainstate</code> obfuscation key begins with an <code>08</code>, which probably refers to the length of the key. If you remove the <code>08</code>, you get an obfuscation key of (for the above example) <code>99b9c2314a85c9b6</code>, which you'll note is the reverse endian-ness of the beginning of <code>result_hex</code> (as it should, since the beginning of block hashes are zeros). </p>

<p>So to get these pieces of data to match endian-ness, you can reverse the key above and you'll get <code>b6c9854a31c2b999</code>. Per <a href="https://bitcoin.stackexchange.com/questions/51387/how-does-bitcoin-read-from-write-to-leveldb/52167#52167">this answer</a>, to de-obfuscate data you need to append the obfuscation key to itself until it matches the length of the data, leaving us with:</p>

<pre><code>result_hex = b6c9854a31c2b999b6da5ee266a8047f3c8c5fc82479ab03af9272a3a57372a2
xor_key    = b6c9854a31c2b999b6c9854a31c2b999b6c9854a31c2b999b6c9854a31c2b999
</code></pre>

<p>If you enter those two values on <a href="https://xor.pw/#" rel="nofollow noreferrer">https://xor.pw/#</a> (as the OP did) you get <code>13dba8576abde68a45da8215bb129a195bf7e994b1cb3b</code>, which you'll notice is quite a bit shorter than the inputs. This is because that site omits leading zeros. Add the missing zeros in and you get <code>00000000000000000013dba8576abde68a45da8215bb129a195bf7e994b1cb3b</code>, which <a href="https://blockstream.info/block/00000000000000000013dba8576abde68a45da8215bb129a195bf7e994b1cb3b" rel="nofollow noreferrer">is a block hash</a> from around the time this question was asked.</p>

CC BY-SA 4.0
2019-10-05T22:53:32.450Z
2019-10-05T22:53:32.450Z
henryperson
<p>Your logic of xoring obfuscation key with the key seems to be causing an issue. Key and level DB value should be first made the same length. The result block hash should start with zeros. Feel free to copy code from <a href="https://github.com/shivaenigma/bitcointools/commit/afb2f87b17492334235f6b61ad92491faca80cca" rel="nofollow noreferrer">this repo</a> which is in working state</p>

CC BY-SA 4.0
2019-10-07T12:26:07.207Z
2019-10-07T12:26:07.207Z
dark knight
<p>From this link <a href="https://bitcoin.stackexchange.com/questions/28168/what-are-the-keys-used-in-the-blockchain-leveldb-ie-what-are-the-keyvalue-pair">What are the keys used in the blockchain levelDB (ie what are the key:value pairs)?</a>,
to get the block hash I use the obfuscation key and xor it with the result I get from the db. So I look up the block hash I got on blockchain.com,
but the block hash doesn't exist. So I check if I'm xoring right by using the website <a href="http://xor.pw/#" rel="nofollow noreferrer">http://xor.pw/#</a>. My xored value matched the website.</p>

<p>Then I look back to the example on <a href="https://bitcoin.stackexchange.com/questions/51387/how-does-bitcoin-read-from-write-to-leveldb/52167#52167">How does Bitcoin read from/write to LevelDB</a> and xored their example
<code>26c326d7353661dc7005d274976f458691f24f0f05d141335f4ad5927e41</code> and <code>27c78118b731610527c78118b731610527c78118b731610527c78118b731</code> on <a href="http://xor.pw/#" rel="nofollow noreferrer">http://xor.pw/#</a>
and I got <code>104a7cf820700d957c2536c205e2483b635ce17b2e02036788d548ac970</code> not <code>01028820010b2a00367244680f6da18acd861a08f0a89cb3b49ab50e</code>.</p>

<p>Me and and the website can't get the same result and be wrong right? What am I missing?</p>

<pre><code>import plyvel

def get_xor_key(o_key, result):
    xor_key = ''
    while len(xor_key) &lt; len(result):
        if len(xor_key) + len(o_key) &lt;= len(result): xor_key += o_key
        else: xor_key += o_key[:len(result)-len(xor_key)]
    return xor_key
def xor_two_str(s, t): return hex(int(s, 16) ^ int(t, 16))

db = plyvel.DB('/home/chris/.bitcoin/chainstate')
o_key = db.get(b'\x0e\x00obfuscate_key')
print('o_key', o_key.encode('hex')) # my o_key is 0899b9c2314a85c9b6

result = db.get(b'B')
result_hex = result.encode('hex')
print('result_hex', result_hex) # b6c9854a31c2b999b6da5ee266a8047f3c8c5fc82479ab03af9272a3a57372a2
xor_key = get_xor_key(o_key, result)
xored = xor_two_str(xor_key.encode('hex'), result_hex)
block_hash = xored[2:-1].decode('hex')[::-1].encode('hex')
print(block_hash) # 870b3cd33974701cfceb9c5bffa0b2b6b9c66e0a9de0a3b56617389267caebaa
</code></pre>

CC BY-SA 4.0
2019-06-14T01:01:51.283Z
Can you explain to me why in the answer for https://bitcoin.stackexchange.com/questions/51387/how-does-bitcoin-read-from-write-to-leveldb/52167#52167 it says `26c326d7353661dc7005d274976f458691f24f0f05d141335f4ad5927e41` xor `27c78118b731610527c78118b731610527c78118b731610527c78118b731` is equal to `104a7cf820700d957c2536c205e2483b635ce17b2e02036788d548ac970` and not `01028820010b2a00367244680f6da18acd861a08f0a89cb3b49ab50e`?
guest1234312
CC BY-SA 4.0
2019-06-14T01:57:52.363Z
Oh, I see what's going on.  Your answer is mathematically right, but you have dropped a leading zero so it is harder to see.  It's more clear if written as `0104a7cf820700d957c2536c205e2483b635ce17b2e02036788d548ac970`.  However, I don't understand either where the `010288...` answer comes from.  It's not even the right number of bytes.
Nate Eldredge
CC BY-SA 4.0
2019-06-14T19:16:53.303Z
The author of https://bitcoin.stackexchange.com/questions/51387/how-does-bitcoin-read-from-write-to-leveldb/52167#52167 has acknowledged that their result seems to be in error.
Nate Eldredge
CC BY-SA 4.0
2019-06-15T07:33:31.130Z
Hmm. Then I wonder what I'm doing wrong.
guest1234312
CC BY-SA 4.0
2019-06-15T13:00:31.200Z
What information you trying to get from blockchain that you need to work with 'leveldb'?
Denis Leonov
CC BY-SA 4.0
2019-06-15T18:49:02.107Z
Just trying to understand how it works.
guest1234312
CC BY-SA 4.0
2019-06-15T21:17:36.683Z
The decoded block hash ought to start with zeros, and I'm noticing that the beginning of the database value looks like the end of the obfuscation key, reversed.  So this is probably a big/little-endian issue.  Try reversing the bytes in one of the values before xor'ing.
Nate Eldredge
CC BY-SA 4.0
2019-06-16T02:01:49.330Z
Tried it. That is not the case.
guest1234312
<python><leveldb><block-hash>
How to get the block hash in the chainstate leveldb?
guest1234312
# How to get the block hash in the chainstate leveldb?

(Asked by: username_0 on 2019-06-13)

From this link What are the keys used in the blockchain levelDB (ie what are the key:value pairs)?,
to get the block hash I use the obfuscation key and xor it with the result I get from the db. So I look up the block hash I got on blockchain.com,
but the block hash doesn't exist. So I check if I'm xoring right by using the website http://xor.pw/#. My xored value matched the website.
Then I look back to the example on How does Bitcoin read from/write to LevelDB and xored their example
26c326d7353661dc7005d274976f458691f24f0f05d141335f4ad5927e41 and 27c78118b731610527c78118b731610527c78118b731610527c78118b731 on http://xor.pw/#
and I got 104a7cf820700d957c2536c205e2483b635ce17b2e02036788d548ac970 not 01028820010b2a00367244680f6da18acd861a08f0a89cb3b49ab50e.
Me and and the website can't get the same result and be wrong right? What am I missing?
import plyvel

def get_xor_key(o_key, result):
    xor_key = ''
    while len(xor_key) < len(result):
        if len(xor_key) + len(o_key) <= len(result): xor_key += o_key
        else: xor_key += o_key[:len(result)-len(xor_key)]
    return xor_key
def xor_two_str(s, t): return hex(int(s, 16) ^ int(t, 16))

db = plyvel.DB('/home/chris/.bitcoin/chainstate')
o_key = db.get(b'\x0e\x00obfuscate_key')
print('o_key', o_key.encode('hex')) # my o_key is 0899b9c2314a85c9b6

result = db.get(b'B')
result_hex = result.encode('hex')
print('result_hex', result_hex) # b6c9854a31c2b999b6da5ee266a8047f3c8c5fc82479ab03af9272a3a57372a2
xor_key = get_xor_key(o_key, result)
xored = xor_two_str(xor_key.encode('hex'), result_hex)
block_hash = xored[2:-1].decode('hex')[::-1].encode('hex')
print(block_hash) # 870b3cd33974701cfceb9c5bffa0b2b6b9c66e0a9de0a3b56617389267caebaa

**Tags:** python, leveldb, block-hash

> **Comments:**
> **username_0**: Can you explain to me why in the answer for https://bitcoin.stackexchange.com/questions/51387/how-does-bitcoin-read-from-write-to-leveldb/52167#52167 it says `26c326d7353661dc7005d274976f458691f24f0f05d141335f4ad5927e41` xor `27c78118b731610527c78118b731610527c78118b731610527c78118b731` is equal to `104a7cf820700d957c2536c205e2483b635ce17b2e02036788d548ac970` and not `01028820010b2a00367244680f6da18acd861a08f0a89cb3b49ab50e`?  
> **username_1**: Oh, I see what's going on.  Your answer is mathematically right, but you have dropped a leading zero so it is harder to see.  It's more clear if written as `0104a7cf820700d957c2536c205e2483b635ce17b2e02036788d548ac970`.  However, I don't understand either where the `010288...` answer comes from.  It's not even the right number of bytes.  
> **username_1**: The author of https://bitcoin.stackexchange.com/questions/51387/how-does-bitcoin-read-from-write-to-leveldb/52167#52167 has acknowledged that their result seems to be in error.  
> **username_0**: Hmm. Then I wonder what I'm doing wrong.  
> **username_2**: What information you trying to get from blockchain that you need to work with 'leveldb'?  
> **username_0**: Just trying to understand how it works.  
> **username_1**: The decoded block hash ought to start with zeros, and I'm noticing that the beginning of the database value looks like the end of the obfuscation key, reversed.  So this is probably a big/little-endian issue.  Try reversing the bytes in one of the values before xor'ing.  
> **username_0**: Tried it. That is not the case.  

---

## 2 answers

### Answer by username_3 on 2019-10-05. Score: 1

This is a bit late, but I've been struggling with this myself so hopefully I can help out anyone who comes across this thread with a similar question:
Looks like the chainstate obfuscation key begins with an 08, which probably refers to the length of the key. If you remove the 08, you get an obfuscation key of (for the above example) 99b9c2314a85c9b6, which you'll note is the reverse endian-ness of the beginning of result_hex (as it should, since the beginning of block hashes are zeros). 
So to get these pieces of data to match endian-ness, you can reverse the key above and you'll get b6c9854a31c2b999. Per this answer, to de-obfuscate data you need to append the obfuscation key to itself until it matches the length of the data, leaving us with:
result_hex = b6c9854a31c2b999b6da5ee266a8047f3c8c5fc82479ab03af9272a3a57372a2
xor_key    = b6c9854a31c2b999b6c9854a31c2b999b6c9854a31c2b999b6c9854a31c2b999

If you enter those two values on https://xor.pw/# (as the OP did) you get 13dba8576abde68a45da8215bb129a195bf7e994b1cb3b, which you'll notice is quite a bit shorter than the inputs. This is because that site omits leading zeros. Add the missing zeros in and you get 00000000000000000013dba8576abde68a45da8215bb129a195bf7e994b1cb3b, which is a block hash from around the time this question was asked.


---

### Answer by username_4 on 2019-10-07. Score: 0

Your logic of xoring obfuscation key with the key seems to be causing an issue. Key and level DB value should be first made the same length. The result block hash should start with zeros. Feel free to copy code from [this repo](https://github.com/shivaenigma/bitcointools/commit/afb2f87b17492334235f6b61ad92491faca80cca) which is in working state


---

