Sunday, July 27, 2025
HomeBitcoinbitcoin core - Decoding chainstate UTXOs: TXID, block top, and stability misalignment

bitcoin core – Decoding chainstate UTXOs: TXID, block top, and stability misalignment

I’m making an attempt to make a rust toolset for studying UTXOs straight from chain state. I’m following bitcoin supply nearly to the letter (not less than I feel I’m).

I’ve a decode_varint

pub fn decode_varint(knowledge: &[u8]) -> Choice<(u32, usize)> {
    let mut n: u32 = 0;
    let mut shift = 0;

    for (i, &byte) in knowledge.iter().enumerate().take(5) {
        let half = (byte & 0x7F) as u32;
        n |= half << shift;

        if byte & 0x80 == 0 {
            return Some((n, i + 1));
        }

        // Bitcoin provides this quirk:
        n = n.wrapping_add(1 << shift);
        shift += 7;
    }

    None
}

I’ve a decompress_amount

pub fn decompress_amount(x: u64) -> u64 {
    if x == 0 {
        return 0;
    }
    let mut x = x - 1;
    let e = x % 10;
    x /= 10;
    let mut n;
    if e < 9 {
        let d = (x % 9) + 1;
        x /= 9;
        n = x * 10 + d;
    } else {
        n = x + 1;
    }
    for _ in 0..e {
        n *= 10;
    }
    n
}

I’m ensuring to solely get UTXO entries

pub fn decode_utxo_key(mut key: &[u8]) -> Choice<(Vec, u32)> {
    if key.is_empty() || key[0] != b'C' {
        return None;
    }
    key = &key[1..];
    let txid = key.get(..32)?.to_vec();
    key = &key[32..];
    let (vout, _) = decode_varint(key)?;
    Some((txid, vout as u32))
}

But for some cause my keys are exhibiting completely different txids than the block top.

key: `BytesKey([67, 0, 0, 0, 0, 1, 236, 58, 152, 94, 229, 61, 50, 239, 22, 75, 88, 246, 154, 181, 7, 146, 209, 249, 113, 25, 180, 120, 10, 150, 212, 118, 209, 0]), worth: [60, 114, 185, 97, 43, 211, 164, 127, 45, 124, 28, 164, 166, 210, 240, 182, 238, 220, 41, 24, 211, 153, 185, 205, 199])

txid: f349b3a497e29738638c27654d3125deb8d90702dc51ab3bc993370900000000

thats txid at block 684,608

I get the XOR obfuscation key:

    let read_opts = ReadOptions::new();
    let xor_iter = db.iter(read_opts);
    let mut obfuscation_key: Vec = Vec::new();

    for (key, worth) in xor_iter {
        if key.0.starts_with(&[0x0e]) {
            obfuscation_key = worth;
            break;
        }
    }

This returns worth bytes decoded as: [52, 148, 23, 67, 104 , 115, 134, 222, 130, 10, 78, 153, 93, 115, 228, 159, 196, 86, 17, 179, 224, 72, 222, 228, 185, 255, 26, 46, 229, 73, 140, 125, 129, 241, 246, 106, 170, 3, 94, 35]

But 52, is clearly not the right byte for block 684,608.

What am I lacking?

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments