Skip to content

Commit 4174883

Browse files
committed
add fallback addresses getter
1 parent 56146e7 commit 4174883

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

lightning-invoice/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ num-traits = { version = "0.2.8", default-features = false }
2727
bitcoin_hashes = { version = "0.11", default-features = false }
2828
hashbrown = { version = "0.8", optional = true }
2929
serde = { version = "1.0.118", optional = true }
30+
bitcoin = { version = "0.29.0", default-features = false }
3031

3132
[dev-dependencies]
3233
lightning = { version = "0.0.113", path = "../lightning", default-features = false, features = ["_test_utils"] }

lightning-invoice/src/de.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,36 @@ mod test {
907907
}
908908
}
909909

910+
#[test]
911+
fn test_fallback_to_address() {
912+
use crate::Fallback;
913+
use crate::Currency;
914+
use crate::utils::address_from_fallback;
915+
use bech32::FromBase32;
916+
use bitcoin::Address;
917+
use core::str::FromStr;
918+
919+
let cases = vec![
920+
(
921+
from_bech32("3x9et2e20v6pu37c5d9vax37wxq72un98".as_bytes()),
922+
Address::from_str("15WTXVVv4JHN992HjbRxMwmekcppRpzJrK").unwrap()
923+
),
924+
(
925+
from_bech32("j3a24vwu6r8ejrss3axul8rxldph2q7z9".as_bytes()),
926+
Address::from_str("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX").unwrap()
927+
),
928+
(
929+
from_bech32("qw508d6qejxtdg4y5r3zarvary0c5xw7k".as_bytes()),
930+
Address::from_str("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4").unwrap()
931+
),
932+
];
933+
934+
for (input, expected) in cases.into_iter() {
935+
let address = address_from_fallback(&Fallback::from_base32(&input).unwrap(), Currency::Bitcoin);
936+
assert_eq!(address, expected);
937+
}
938+
}
939+
910940
#[test]
911941
fn test_parse_route() {
912942
use lightning::routing::gossip::RoutingFees;

lightning-invoice/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ extern crate serde;
4545
use std::time::SystemTime;
4646

4747
use bech32::u5;
48+
use bitcoin::Address;
4849
use bitcoin_hashes::Hash;
4950
use bitcoin_hashes::sha256;
5051
use lightning::ln::PaymentSecret;
@@ -1258,6 +1259,13 @@ impl Invoice {
12581259
self.signed_invoice.fallbacks()
12591260
}
12601261

1262+
/// Returns a list of all fallback addresses as `bitcoin::Address`es
1263+
pub fn fallback_addresses(&self) -> Vec<Address> {
1264+
self.fallbacks().iter().map(|fallback| {
1265+
utils::address_from_fallback(fallback, self.currency())
1266+
}).collect()
1267+
}
1268+
12611269
/// Returns a list of all routes included in the invoice
12621270
pub fn private_routes(&self) -> Vec<&PrivateRoute> {
12631271
self.signed_invoice.private_routes()

lightning-invoice/src/utils.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! Convenient utilities to create an invoice.
22
3-
use crate::{CreationError, Currency, Invoice, InvoiceBuilder, SignOrCreationError};
3+
use crate::{CreationError, Currency, Invoice, InvoiceBuilder, SignOrCreationError, Fallback};
44

55
use crate::{prelude::*, Description, InvoiceDescription, Sha256};
66
use bech32::ToBase32;
7+
use bitcoin::util::address::WitnessVersion;
8+
use bitcoin::{Network, Address, Script, PubkeyHash, ScriptHash};
79
use bitcoin_hashes::Hash;
810
use lightning::chain;
911
use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
@@ -16,6 +18,7 @@ use lightning::routing::gossip::RoutingFees;
1618
use lightning::routing::router::{RouteHint, RouteHintHop, Router};
1719
use lightning::util::logger::Logger;
1820
use secp256k1::PublicKey;
21+
use core::convert::TryFrom;
1922
use core::ops::Deref;
2023
use core::time::Duration;
2124

@@ -633,6 +636,33 @@ fn filter_channels<L: Deref>(
633636
.collect::<Vec<RouteHint>>()
634637
}
635638

639+
pub(crate) fn address_from_fallback(fallback: &Fallback, currency: Currency) -> Address {
640+
let network = match currency {
641+
Currency::Bitcoin => Network::Bitcoin,
642+
Currency::BitcoinTestnet => Network::Testnet,
643+
Currency::Regtest => Network::Regtest,
644+
Currency::Simnet => Network::Regtest,
645+
Currency::Signet => Network::Signet,
646+
};
647+
648+
let script = match fallback {
649+
Fallback::SegWitProgram { version, program } => {
650+
let version = WitnessVersion::try_from(*version).unwrap();
651+
Script::new_witness_program(version, program.as_slice())
652+
}
653+
Fallback::PubKeyHash(pkh) => {
654+
let pkh = PubkeyHash::from_slice(pkh).unwrap();
655+
Script::new_p2pkh(&pkh)
656+
}
657+
Fallback::ScriptHash(sh) => {
658+
let sh = ScriptHash::from_slice(sh).unwrap();
659+
Script::new_p2sh(&sh)
660+
}
661+
};
662+
663+
Address::from_script(&script, network).unwrap()
664+
}
665+
636666
#[cfg(test)]
637667
mod test {
638668
use core::time::Duration;

0 commit comments

Comments
 (0)