use std::collections::{BTreeMap, BTreeSet};
use std::str::FromStr;
use std::sync::Arc;
use bdk_chain::bdk_core::{BlockId, ConfirmationBlockTime};
use bdk_chain::indexer::keychain_txout::ChangeSet as BdkIndexerChangeSet;
use bdk_chain::local_chain::ChangeSet as BdkLocalChainChangeSet;
use bdk_chain::tx_graph::ChangeSet as BdkTxGraphChangeSet;
use bdk_chain::DescriptorId;
use bdk_wallet::descriptor::Descriptor;
use bdk_wallet::keys::DescriptorPublicKey;
use bitcoin::hashes::sha256::Hash as Sha256Hash;
use bitcoin::p2p::Magic;
use bitcoin::{BlockHash, Network, OutPoint, Transaction, TxOut, Txid};
use lightning::ln::msgs::DecodeError;
use lightning::util::ser::{BigSize, Readable, RequiredWrapper, Writeable, Writer};
use lightning::{decode_tlv_stream, encode_tlv_stream, read_tlv_fields, write_tlv_fields};
const CHANGESET_SERIALIZATION_VERSION: u8 = 1;
pub(crate) struct ChangeSetSerWrapper<'a, T>(pub &'a T);
pub(crate) struct ChangeSetDeserWrapper<T>(pub T);
impl<'a> Writeable for ChangeSetSerWrapper<'a, Descriptor<DescriptorPublicKey>> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
CHANGESET_SERIALIZATION_VERSION.write(writer)?;
self.0.to_string().write(writer)
}
}
impl Readable for ChangeSetDeserWrapper<Descriptor<DescriptorPublicKey>> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let version: u8 = Readable::read(reader)?;
if version != CHANGESET_SERIALIZATION_VERSION {
return Err(DecodeError::UnknownVersion);
}
let descriptor_str: String = Readable::read(reader)?;
let descriptor = Descriptor::<DescriptorPublicKey>::from_str(&descriptor_str)
.map_err(|_| DecodeError::InvalidValue)?;
Ok(Self(descriptor))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, Network> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
CHANGESET_SERIALIZATION_VERSION.write(writer)?;
self.0.magic().to_bytes().write(writer)
}
}
impl Readable for ChangeSetDeserWrapper<Network> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let version: u8 = Readable::read(reader)?;
if version != CHANGESET_SERIALIZATION_VERSION {
return Err(DecodeError::UnknownVersion);
}
let buf: [u8; 4] = Readable::read(reader)?;
let magic = Magic::from_bytes(buf);
let network = Network::from_magic(magic).ok_or(DecodeError::InvalidValue)?;
Ok(Self(network))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BdkLocalChainChangeSet> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
CHANGESET_SERIALIZATION_VERSION.write(writer)?;
encode_tlv_stream!(writer, {
(0, self.0.blocks, required),
});
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BdkLocalChainChangeSet> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let version: u8 = Readable::read(reader)?;
if version != CHANGESET_SERIALIZATION_VERSION {
return Err(DecodeError::UnknownVersion);
}
let mut blocks = RequiredWrapper(None);
decode_tlv_stream!(reader, {
(0, blocks, required),
});
Ok(Self(BdkLocalChainChangeSet { blocks: blocks.0.unwrap() }))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BdkTxGraphChangeSet<ConfirmationBlockTime>> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
CHANGESET_SERIALIZATION_VERSION.write(writer)?;
encode_tlv_stream!(writer, {
(0, ChangeSetSerWrapper(&self.0.txs), required),
(1, Some(&self.0.first_seen), option),
(2, self.0.txouts, required),
(3, Some(&self.0.last_evicted), option),
(4, ChangeSetSerWrapper(&self.0.anchors), required),
(6, self.0.last_seen, required),
});
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BdkTxGraphChangeSet<ConfirmationBlockTime>> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let version: u8 = Readable::read(reader)?;
if version != CHANGESET_SERIALIZATION_VERSION {
return Err(DecodeError::UnknownVersion);
}
let mut txs: RequiredWrapper<ChangeSetDeserWrapper<BTreeSet<Arc<Transaction>>>> =
RequiredWrapper(None);
let mut txouts: RequiredWrapper<BTreeMap<OutPoint, TxOut>> = RequiredWrapper(None);
let mut anchors: RequiredWrapper<
ChangeSetDeserWrapper<BTreeSet<(ConfirmationBlockTime, Txid)>>,
> = RequiredWrapper(None);
let mut last_seen: RequiredWrapper<BTreeMap<Txid, u64>> = RequiredWrapper(None);
let mut first_seen = None;
let mut last_evicted = None;
decode_tlv_stream!(reader, {
(0, txs, required),
(1, first_seen, option),
(2, txouts, required),
(3, last_evicted, option),
(4, anchors, required),
(6, last_seen, required),
});
Ok(Self(BdkTxGraphChangeSet {
txs: txs.0.unwrap().0,
txouts: txouts.0.unwrap(),
anchors: anchors.0.unwrap().0,
last_seen: last_seen.0.unwrap(),
first_seen: first_seen.unwrap_or_default(),
last_evicted: last_evicted.unwrap_or_default(),
}))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BTreeSet<(ConfirmationBlockTime, Txid)>> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
let len = BigSize(self.0.len() as u64);
len.write(writer)?;
for (time, txid) in self.0.iter() {
write_tlv_fields!(writer, {
(0, ChangeSetSerWrapper(time), required),
(2, txid, required),
});
}
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BTreeSet<(ConfirmationBlockTime, Txid)>> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let len: BigSize = Readable::read(reader)?;
let mut set = BTreeSet::new();
for _ in 0..len.0 {
let mut time: RequiredWrapper<ChangeSetDeserWrapper<ConfirmationBlockTime>> =
RequiredWrapper(None);
let mut txid: RequiredWrapper<Txid> = RequiredWrapper(None);
read_tlv_fields!(reader, {
(0, time, required),
(2, txid, required),
});
set.insert((time.0.unwrap().0, txid.0.unwrap()));
}
Ok(Self(set))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BTreeSet<Arc<Transaction>>> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
let len = BigSize(self.0.len() as u64);
len.write(writer)?;
for tx in self.0.iter() {
write_tlv_fields!(writer, {
(0, tx, required),
});
}
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BTreeSet<Arc<Transaction>>> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let len: BigSize = Readable::read(reader)?;
let mut set = BTreeSet::new();
for _ in 0..len.0 {
let mut tx: RequiredWrapper<Transaction> = RequiredWrapper(None);
read_tlv_fields!(reader, {
(0, tx, required),
});
set.insert(Arc::new(tx.0.unwrap()));
}
Ok(Self(set))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, ConfirmationBlockTime> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
encode_tlv_stream!(writer, {
(0, ChangeSetSerWrapper(&self.0.block_id), required),
(2, self.0.confirmation_time, required),
});
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<ConfirmationBlockTime> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let mut block_id: RequiredWrapper<ChangeSetDeserWrapper<BlockId>> = RequiredWrapper(None);
let mut confirmation_time: RequiredWrapper<u64> = RequiredWrapper(None);
decode_tlv_stream!(reader, {
(0, block_id, required),
(2, confirmation_time, required),
});
Ok(Self(ConfirmationBlockTime {
block_id: block_id.0.unwrap().0,
confirmation_time: confirmation_time.0.unwrap(),
}))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BlockId> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
encode_tlv_stream!(writer, {
(0, self.0.height, required),
(2, self.0.hash, required),
});
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BlockId> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let mut height: RequiredWrapper<u32> = RequiredWrapper(None);
let mut hash: RequiredWrapper<BlockHash> = RequiredWrapper(None);
decode_tlv_stream!(reader, {
(0, height, required),
(2, hash, required),
});
Ok(Self(BlockId { height: height.0.unwrap(), hash: hash.0.unwrap() }))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BdkIndexerChangeSet> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
CHANGESET_SERIALIZATION_VERSION.write(writer)?;
encode_tlv_stream!(writer, { (0, ChangeSetSerWrapper(&self.0.last_revealed), required) });
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BdkIndexerChangeSet> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let version: u8 = Readable::read(reader)?;
if version != CHANGESET_SERIALIZATION_VERSION {
return Err(DecodeError::UnknownVersion);
}
let mut last_revealed: RequiredWrapper<ChangeSetDeserWrapper<BTreeMap<DescriptorId, u32>>> =
RequiredWrapper(None);
decode_tlv_stream!(reader, { (0, last_revealed, required) });
Ok(Self(BdkIndexerChangeSet {
last_revealed: last_revealed.0.unwrap().0,
spk_cache: Default::default(),
}))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, BTreeMap<DescriptorId, u32>> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
let len = BigSize(self.0.len() as u64);
len.write(writer)?;
for (descriptor_id, last_index) in self.0.iter() {
write_tlv_fields!(writer, {
(0, ChangeSetSerWrapper(descriptor_id), required),
(2, last_index, required),
});
}
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<BTreeMap<DescriptorId, u32>> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let len: BigSize = Readable::read(reader)?;
let mut set = BTreeMap::new();
for _ in 0..len.0 {
let mut descriptor_id: RequiredWrapper<ChangeSetDeserWrapper<DescriptorId>> =
RequiredWrapper(None);
let mut last_index: RequiredWrapper<u32> = RequiredWrapper(None);
read_tlv_fields!(reader, {
(0, descriptor_id, required),
(2, last_index, required),
});
set.insert(descriptor_id.0.unwrap().0, last_index.0.unwrap());
}
Ok(Self(set))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, DescriptorId> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
encode_tlv_stream!(writer, { (0, ChangeSetSerWrapper(&self.0 .0), required) });
Ok(())
}
}
impl Readable for ChangeSetDeserWrapper<DescriptorId> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let mut hash: RequiredWrapper<ChangeSetDeserWrapper<Sha256Hash>> = RequiredWrapper(None);
decode_tlv_stream!(reader, { (0, hash, required) });
Ok(Self(DescriptorId(hash.0.unwrap().0)))
}
}
impl<'a> Writeable for ChangeSetSerWrapper<'a, Sha256Hash> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
writer.write_all(&self.0[..])
}
}
impl Readable for ChangeSetDeserWrapper<Sha256Hash> {
fn read<R: lightning::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
use bitcoin::hashes::Hash;
let buf: [u8; 32] = Readable::read(reader)?;
Ok(Self(Sha256Hash::from_slice(&buf[..]).unwrap()))
}
}