Skip to content

nepet/btlv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

btlv

Crates.io Documentation License: MIT

A Rust library for encoding and decoding Lightning Network TLV (Type-Length-Value) streams, compliant with BOLT #1.

Features

  • BOLT-compliant bigsize and TLV encoding with canonical-form validation
  • TlvStream container with sorted, deduplicated records and typed accessors
  • tlv_struct! macro for declarative struct-to-TLV mapping
  • tu64 truncated unsigned integer encoding/decoding
  • Serde support (feature-gated) — serialize/deserialize TlvStream as hex strings
  • Spec test vectors from BOLT #1 appendices A and B

Installation

Add to your Cargo.toml:

[dependencies]
btlv = "0.2"

Serde support is enabled by default. To disable it:

[dependencies]
btlv = { version = "0.2", default-features = false }

To enable standalone BigSize encode/decode (e.g. for custom wire protocols):

[dependencies]
btlv = { version = "0.2", features = ["bigsize"] }
use btlv::bigsize;

let encoded = bigsize::encode(253);
let (value, bytes_read) = bigsize::decode(&encoded).unwrap();
assert_eq!(value, 253);

With serde enabled, tlv_struct! structs are directly serializable (they delegate to TlvStream's hex-string encoding):

let payload = OnionPayload {
    amt_to_forward: 1000,
    outgoing_cltv_value: 800_000,
    short_channel_id: None,
};

let json = serde_json::to_string(&payload).unwrap();
let decoded: OnionPayload = serde_json::from_str(&json).unwrap();

Usage

Working with TlvStream directly

use btlv::TlvStream;

// Build a stream
let mut stream = TlvStream::default();
stream.set_tu64(2, 1000);       // tu64-encoded amount
stream.set_tu64(4, 800_000);    // tu64-encoded CLTV
stream.insert(6, vec![0x00, 0x73, 0x00, 0x0f, 0x2c, 0x00, 0x07, 0x00]);

// Serialize to wire format
let bytes = stream.to_bytes().unwrap();

// Parse back
let decoded = TlvStream::from_bytes(&bytes).unwrap();
assert_eq!(decoded.get_tu64(2).unwrap(), Some(1000));

Declarative struct mapping with tlv_struct!

btlv::tlv_struct! {
    pub struct OnionPayload {
        #[tlv(2, tu64)]
        pub amt_to_forward: u64,
        #[tlv(4, tu64)]
        pub outgoing_cltv_value: u32,
        #[tlv(6, bytes)]
        pub short_channel_id: Option<[u8; 8]>,
    }
}

let payload = OnionPayload {
    amt_to_forward: 1000,
    outgoing_cltv_value: 800_000,
    short_channel_id: None,
};

// Serialize to TLV bytes and back
let bytes = payload.to_tlv_bytes().unwrap();
let decoded = OnionPayload::from_tlv_bytes(&bytes).unwrap();
assert_eq!(decoded.amt_to_forward, 1000);

The macro supports three encoding tags:

Tag Wire format Rust types
tu64 Variable-length minimal big-endian int u64, u32
u64 Fixed 8-byte big-endian u64
bytes Raw bytes Vec<u8>, [u8; N]

Fields wrapped in Option<T> are automatically optional — omitted when None, decoded as None when absent.

Core types

Type Description
TlvStream Sorted, deduplicated record container with typed get/set accessors
TlvRecord A single type-value pair
TlvError Error enum covering duplicate types, ordering, truncation, overflow

Bigsize encoding

Implements the BOLT #1 variable-length integer format:

Value range Wire encoding
0 to 252 1 byte
253 to 65535 0xfd + 2 bytes
65536 to 4294967295 0xfe + 4 bytes
4294967296 to 2^64 - 1 0xff + 8 bytes

Contributing

Contributions are welcome! Please feel free to submit a Pull Request or open an issue.

cargo test

The test suite includes BOLT #1 specification test vectors for bigsize, tu64, and TLV stream encoding.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A Rust library for encoding and decoding Lightning Network TLV (Type-Length-Value) streams, compliant with BOLT #1

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages