Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created January 18, 2026 14:20
Show Gist options
  • Select an option

  • Save rust-play/87a47ecc26e26be1c44699d0309f1091 to your computer and use it in GitHub Desktop.

Select an option

Save rust-play/87a47ecc26e26be1c44699d0309f1091 to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
/// A verbose example of Bitcoin's two variable integer types.
fn main() {
let value: u64 = 515;
// 1. CompactSize (Little-Endian) - Used in P2P/Transactions
let compact = encode_compact_size(value);
println!("Value: {}", value);
println!("CompactSize (LE-based) hex: {:02x?}", compact);
// 2. VarInt (Base-128 Big-Endian) - Used in LevelDB/Disk
let varint = encode_varint(value);
println!("Internal VarInt (BE-based) hex: {:02x?}", varint);
}
/// CompactSize: The standard "P2P" encoding (Little-Endian bytes after prefix)
fn encode_compact_size(v: u64) -> Vec<u8> {
if v < 253 {
vec![v as u8]
} else if v <= 0xFFFF {
let mut b = vec![0xfd];
b.extend_from_slice(&(v as u16).to_le_bytes());
b
} else if v <= 0xFFFFFFFF {
let mut b = vec![0xfe];
b.extend_from_slice(&(v as u32).to_le_bytes());
b
} else {
let mut b = vec![0xff];
b.extend_from_slice(&v.to_le_bytes());
b
}
}
/// VarInt: Internal Base-128 encoding (Big-Endian)
/// Logic from Bitcoin Core's `serialize.h` / `WriteVarInt`
fn encode_varint(mut n: u64) -> Vec<u8> {
let mut res = Vec::new();
let mut tmp = Vec::new();
loop {
// The last byte has MSB 0, others have MSB 1
let mask = if tmp.is_empty() { 0x00 } else { 0x80 };
tmp.push((n & 0x7F) as u8 | mask);
if n <= 0x7F { break; }
n = (n >> 7) - 1; // The "minus one" prevents redundant zero-padding
}
// Reverse because we calculated from least-significant to most-significant
// but the format is Big-Endian.
res.extend(tmp.into_iter().rev());
res
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment