<p>I have no idea if this is correct but a quick glance at the references gives me</p>
<pre><code>$ ./leveldb
Version       250000
Block height  83373
Status        1d
Tx count      4
Header        008fdaec0a81fac8420100000093fc79c5606493fc6051e334231bc7b6e765bae097a5a6a82d960500000000006ed298fa7ccd23916490edb1d8dadf981ffb6a6cf99b518677a30cbae04767a1b118a94ca3b2311b110468f0
</code></pre>
<p>from writing and running this code:</p>
<pre class="lang-go prettyprint-override"><code>package main

import (
    &quot;encoding/hex&quot;
    &quot;fmt&quot;
    &quot;log&quot;
)

func main() {
    const valueHex = &quot;8EA010848A2D1D04008FDAEC0A81FAC8&quot; +
            &quot;420100000093FC79C5606493FC6051E3&quot; +
            &quot;34231BC7B6E765BAE097A5A6A82D9605&quot; +
            &quot;00000000006ED298FA7CCD23916490ED&quot; +
            &quot;B1D8DADF981FFB6A6CF99B518677A30C&quot; +
            &quot;BAE04767A1B118A94CA3B2311B110468&quot; +
            &quot;F0&quot;
    value, err := hex.DecodeString(valueHex)
    if err != nil {
        log.Fatal(err)
    }
    
    version, pos := varInt(value, 0)
    fmt.Printf(&quot;Version       %d\n&quot;, version)

    blockHeight, pos := varInt(value, pos)
    fmt.Printf(&quot;Block height  %d\n&quot;, blockHeight)

    status, pos := varInt(value, pos)
    fmt.Printf(&quot;Status        %x\n&quot;, status)

    txCount, pos := varInt(value, pos)
    fmt.Printf(&quot;Tx count      %x\n&quot;, txCount)

    fileNum := 0
    if (status &amp; 0x80 &gt; 0) || (status &amp; 0x8000 &gt; 0) {
        fileNum, pos = varInt(value, pos)
        fmt.Printf(&quot;File number   %d\n&quot;, fileNum)
    }

    offsetDat := 0
    if (status &amp; 0x80 &gt; 0) {
        offsetDat, pos = varInt(value, pos)
        fmt.Printf(&quot;Offset Data   %d\n&quot;, offsetDat)
    }

    offsetRev := 0
    if (status &amp; 0x8000 &gt; 0) {
        offsetRev, pos = varInt(value, pos)
        fmt.Printf(&quot;Offset Rev   %d\n&quot;, offsetRev)
    }

    header := value[pos:]
    fmt.Printf(&quot;Header        %x\n&quot;, header)

}

// Extracts a Bitcoin core style of variable length integer (varint)
func varInt(data []byte, offset int) (int, int) {
    var result, i int
    for i = offset; i&lt; len(data); i++ {
        result = result&lt;&lt;7 | int(data[i] &amp; 0x7F)
        if data[i] &amp; 0x80 &gt; 0 { // high bit if more bytes in varint
            result++ // weird thing Bitcoin core does.
        } else {
            break
        }
    }
    return result, i+1
}
</code></pre>
<p>Needs some sanity checking of offset in varInt() etc etc.
May be wrong but, if so, a wrong answer sometimes elicits a less wrong one.</p>

CC BY-SA 4.0
2024-09-04T21:46:58.920Z
2024-09-04T21:53:42.207Z
2024-09-04T21:53:42.207Z
RedGrittyBrick
<p>I'm trying to understand the format of key/value pairs in LevelDB for Bitcoin data storage.</p>
<p>Given the following raw key and value:</p>
<pre><code>Raw Key: 6200005BD1B034B80F7C08EA312BBCDBCFDB647E366B85EC6B206F0D0000000000
Raw Value: 8EA010848A2D1D04008FDAEC0A81FAC8420100000093FC79C5606493FC6051E334231BC7B6E765BAE097A5A6A82D960500000000006ED298FA7CCD23916490EDB1D8DADF981FFB6A6CF99B518677A30CBAE04767A1B118A94CA3B2311B110468F0
</code></pre>
<p><a href="https://bitcoin.stackexchange.com/a/67569/157164">https://bitcoin.stackexchange.com/a/67569/157164</a> <br />
<a href="https://bitcoin.stackexchange.com/a/29418/157164">https://bitcoin.stackexchange.com/a/29418/157164</a></p>
<p>From my understanding based on these two comments, I expected the value to contain, in this order:</p>
<pre><code>Block header
Block height
Transaction count
Validation status
Data file
Data offset
Undo file
Undo offset
</code></pre>
<p>However, it appears the block header is at the end of the value instead of the beginning. After stripping the header bytes, I'm left with: <code>8EA010848A2D1D04008FDAEC0A81FAC842</code></p>
<p>I expected to extract block height, transaction count, validation status, etc., from this, but I can't seem to do so, regardless of the endian format used.</p>
<p>Could someone clarify the correct structure of this value? Are these elements encoded as Varint or CompactSize? Any insight would be greatly appreciated!</p>

CC BY-SA 4.0
2024-09-02T19:15:58.260Z
A quick look suggests to me that the the structure, encoding, order etc are shown in the code referred to in John Ratcliffe's answer to the first question you referenced. Does something there need clarification?
RedGrittyBrick
CC BY-SA 4.0
2024-09-03T08:08:16.207Z
@RedGrittyBrick, I'm unable to decode the height from the remaining bytes string (after stripping the header bytes), and thus, I'm unable to decode all the other values (such as datafile, data offset, etc.). I've tried both 'classic VarInts' and VarInt128 in both endianness formats, but it seems I'm missing something.
Shakarhan
<blockchain><raw-data><database><leveldb>
levelDB : How does the key/values pairs work for datadir/blocks/index/
Shakarhan
# levelDB : How does the key/values pairs work for datadir/blocks/index/

(Asked by: username_0 on 2024-09-02)

I'm trying to understand the format of key/value pairs in LevelDB for Bitcoin data storage.
Given the following raw key and value:
Raw Key: 6200005BD1B034B80F7C08EA312BBCDBCFDB647E366B85EC6B206F0D0000000000
Raw Value: 8EA010848A2D1D04008FDAEC0A81FAC8420100000093FC79C5606493FC6051E334231BC7B6E765BAE097A5A6A82D960500000000006ED298FA7CCD23916490EDB1D8DADF981FFB6A6CF99B518677A30CBAE04767A1B118A94CA3B2311B110468F0

https://bitcoin.stackexchange.com/a/67569/157164 
https://bitcoin.stackexchange.com/a/29418/157164
From my understanding based on these two comments, I expected the value to contain, in this order:
Block header
Block height
Transaction count
Validation status
Data file
Data offset
Undo file
Undo offset

However, it appears the block header is at the end of the value instead of the beginning. After stripping the header bytes, I'm left with: 8EA010848A2D1D04008FDAEC0A81FAC842
I expected to extract block height, transaction count, validation status, etc., from this, but I can't seem to do so, regardless of the endian format used.
Could someone clarify the correct structure of this value? Are these elements encoded as Varint or CompactSize? Any insight would be greatly appreciated!

**Tags:** blockchain, raw-data, database, leveldb

> **Comments:**
> **username_1**: A quick look suggests to me that the the structure, encoding, order etc are shown in the code referred to in John Ratcliffe's answer to the first question you referenced. Does something there need clarification?  
> **username_0**: @username_1, I'm unable to decode the height from the remaining bytes string (after stripping the header bytes), and thus, I'm unable to decode all the other values (such as datafile, data offset, etc.). I've tried both 'classic VarInts' and VarInt128 in both endianness formats, but it seems I'm missing something.  

---

## 1 answers

### Answer by username_1 on 2024-09-04. Score: 1

I have no idea if this is correct but a quick glance at the references gives me
$ ./leveldb
Version       250000
Block height  83373
Status        1d
Tx count      4
Header        008fdaec0a81fac8420100000093fc79c5606493fc6051e334231bc7b6e765bae097a5a6a82d960500000000006ed298fa7ccd23916490edb1d8dadf981ffb6a6cf99b518677a30cbae04767a1b118a94ca3b2311b110468f0

from writing and running this code:
package main

import (
    "encoding/hex"
    "fmt"
    "log"
)

func main() {
    const valueHex = "8EA010848A2D1D04008FDAEC0A81FAC8" +
            "420100000093FC79C5606493FC6051E3" +
            "34231BC7B6E765BAE097A5A6A82D9605" +
            "00000000006ED298FA7CCD23916490ED" +
            "B1D8DADF981FFB6A6CF99B518677A30C" +
            "BAE04767A1B118A94CA3B2311B110468" +
            "F0"
    value, err := hex.DecodeString(valueHex)
    if err != nil {
        log.Fatal(err)
    }
    
    version, pos := varInt(value, 0)
    fmt.Printf("Version       %d\n", version)

    blockHeight, pos := varInt(value, pos)
    fmt.Printf("Block height  %d\n", blockHeight)

    status, pos := varInt(value, pos)
    fmt.Printf("Status        %x\n", status)

    txCount, pos := varInt(value, pos)
    fmt.Printf("Tx count      %x\n", txCount)

    fileNum := 0
    if (status & 0x80 > 0) || (status & 0x8000 > 0) {
        fileNum, pos = varInt(value, pos)
        fmt.Printf("File number   %d\n", fileNum)
    }

    offsetDat := 0
    if (status & 0x80 > 0) {
        offsetDat, pos = varInt(value, pos)
        fmt.Printf("Offset Data   %d\n", offsetDat)
    }

    offsetRev := 0
    if (status & 0x8000 > 0) {
        offsetRev, pos = varInt(value, pos)
        fmt.Printf("Offset Rev   %d\n", offsetRev)
    }

    header := value[pos:]
    fmt.Printf("Header        %x\n", header)

}

// Extracts a Bitcoin core style of variable length integer (varint)
func varInt(data []byte, offset int) (int, int) {
    var result, i int
    for i = offset; i< len(data); i++ {
        result = result<<7 | int(data[i] & 0x7F)
        if data[i] & 0x80 > 0 { // high bit if more bytes in varint
            result++ // weird thing Bitcoin core does.
        } else {
            break
        }
    }
    return result, i+1
}

Needs some sanity checking of offset in varInt() etc etc.
May be wrong but, if so, a wrong answer sometimes elicits a less wrong one.


---

