#[cfg(test)]
mod tests {
use crate::channel::ChannelId;
use bitcoin;
use bitcoin::bip32::DerivationPath;
use bitcoin::hashes::hex::FromHex;
use bitcoin::secp256k1::SecretKey;
use bitcoin::ScriptBuf;
use lightning::ln::chan_utils::ChannelPublicKeys;
use test_log::test;
use vls_common::to_derivation_path;
use crate::util::status::{Code, Status};
use crate::util::test_utils::*;
macro_rules! hex (($hex:expr) => (Vec::from_hex($hex).unwrap()));
macro_rules! hex_script (($hex:expr) => (ScriptBuf::from(hex!($hex))));
fn check_basepoints(basepoints: &ChannelPublicKeys) {
let points = [
basepoints.funding_pubkey,
basepoints.revocation_basepoint.to_public_key(),
basepoints.payment_point,
basepoints.delayed_payment_basepoint.to_public_key(),
basepoints.htlc_basepoint.to_public_key(),
]
.iter()
.map(|p| hex::encode(p.serialize().to_vec()))
.collect::<Vec<_>>();
assert_eq!(
points,
vec![
"038ad68f4825b5b9db24e274d79b26887b46a70b8a16a720d69e363c858cd7907e",
"02662e5e76a56a9dca49130bfd6990d9fc71501c4b7d799d253bbd365b72ac72d8",
"03ee671ff5bf6450b8b3cad584b49a68265978f9b2bd5f7ff144eb6972dd6bd35a",
"022e399383d20b0157178d8927a102829ddedd12cea977527afce1d374dbedd553",
"02e25506cc6c4b9f888d682487d3b8d969a56e13b623da743d9c9d56c763931c49"
]
);
}
#[test]
fn setup_channel_test() {
let (node, channel_id) =
init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], make_test_channel_setup());
node.with_channel(&channel_id, |c| {
let params = c.keys.get_channel_parameters().unwrap();
assert!(params.is_outbound_from_holder);
assert_eq!(params.holder_selected_contest_delay, 6);
Ok(())
})
.unwrap();
}
#[test]
fn setup_channel_not_exist_test() {
let node = init_node(TEST_NODE_CONFIG, TEST_SEED[1]);
let channel_id_x = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[1]).unwrap());
let status: Result<_, Status> = node.setup_channel(
channel_id_x.clone(),
None,
make_test_channel_setup(),
&DerivationPath::master(),
);
assert!(status.is_err());
let err = status.unwrap_err();
assert_eq!(err.code(), Code::InvalidArgument);
assert_eq!(err.message(), format!("channel does not exist: {}", &channel_id_x));
}
#[test]
fn get_channel_basepoints_test() {
let (node, channel_id) =
init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], make_test_channel_setup());
let basepoints =
node.with_channel_base(&channel_id, |base| Ok(base.get_channel_basepoints())).unwrap();
check_basepoints(&basepoints);
}
#[test]
fn setup_channel_dual_channelid_test() {
let node = init_node(TEST_NODE_CONFIG, TEST_SEED[1]);
let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
node.new_channel_with_id(channel_id.clone(), &node).expect("new_channel");
let channel_id_x = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[1]).unwrap());
node.setup_channel(
channel_id.clone(),
Some(channel_id_x.clone()),
make_test_channel_setup(),
&DerivationPath::master(),
)
.expect("setup_channel");
let val = node.with_channel(&channel_id, |_chan| Ok(42)).expect("u32");
assert_eq!(val, 42);
let val_x = node.with_channel(&channel_id_x, |_chan| Ok(43)).expect("u32");
assert_eq!(val_x, 43);
}
#[test]
fn with_channel_not_exist_test() {
let (node, _channel_id) =
init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], make_test_channel_setup());
let channel_id_x = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[1]).unwrap());
let status: Result<(), Status> = node.with_channel(&channel_id_x, |_chan| Ok(()));
assert!(status.is_err());
let err = status.unwrap_err();
assert_eq!(err.code(), Code::InvalidArgument);
assert_eq!(
err.message(),
"no such channel: 0200000000000000000000000000000000000000000000000000000000000000"
);
}
#[test]
fn channel_stub_test() {
let node = init_node(TEST_NODE_CONFIG, TEST_SEED[1]);
let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
node.new_channel_with_id(channel_id.clone(), &node).expect("new_channel");
let result: Result<(), Status> = node.with_channel(&channel_id, |_chan| {
assert!(false); Ok(())
});
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code(), Code::InvalidArgument);
assert_eq!(err.message(), format!("channel not ready: {}", TEST_CHANNEL_ID[0]),);
let _: Result<(), Status> = node.with_channel_base(&channel_id, |base| {
let result = base.get_per_commitment_point(0);
assert!(result.is_ok());
let result = base.get_per_commitment_point(1);
assert!(result.is_ok());
assert_failed_precondition_err!(
base.get_per_commitment_point(2),
"policy failure: channel stub can only return point for commitment number zero or one"
);
assert_failed_precondition_err!(
base.get_per_commitment_secret(0),
"policy failure: channel stub cannot release commitment secret"
);
assert_eq!(base.get_per_commitment_secret_or_none(0), None);
Ok(())
});
let basepoints =
node.with_channel_base(&channel_id, |base| Ok(base.get_channel_basepoints())).unwrap();
check_basepoints(&basepoints);
let n: u64 = 10;
let suggested = SecretKey::from_slice(
hex_decode("2f87fef68f2bafdb3c6425921894af44da9a984075c70c7ba31ccd551b3585db")
.unwrap()
.as_slice(),
)
.unwrap();
let correct = node
.with_channel_base(&channel_id, |base| base.check_future_secret(n, &suggested))
.unwrap();
assert_eq!(correct, true);
let notcorrect = node
.with_channel_base(&channel_id, |base| base.check_future_secret(n + 1, &suggested))
.unwrap();
assert_eq!(notcorrect, false);
}
#[ignore] #[test]
fn node_new_channel_already_exists_test() {
let (node, _channel_id) =
init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], make_test_channel_setup());
let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
let result = node.new_channel_with_id(channel_id, &node);
let err = result.err().unwrap();
assert_eq!(err.code(), Code::InvalidArgument);
assert_eq!(err.message(), format!("channel already exists: {}", TEST_CHANNEL_ID[0]));
}
#[test]
fn setup_channel_already_setup_test() {
let (node, channel_id) =
init_node_and_channel(TEST_NODE_CONFIG, TEST_SEED[1], make_test_channel_setup());
let mut setup1 = make_test_channel_setup();
setup1.channel_value_sat += 1;
let result = node.setup_channel(channel_id, None, setup1, &DerivationPath::master());
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.code(), Code::InvalidArgument);
assert_eq!(
err.message(),
format!("channel already ready with different setup: {}", TEST_CHANNEL_ID[0])
);
}
#[test]
fn setup_channel_unknown_holder_shutdown_script() {
let node = init_node(TEST_NODE_CONFIG, TEST_SEED[1]);
let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
node.new_channel_with_id(channel_id.clone(), &node).expect("new_channel");
let mut setup = make_test_channel_setup();
setup.holder_shutdown_script =
Some(hex_script!("0014be56df7de366ad8ee9ccdad54e9a9993e99ef565"));
let holder_shutdown_key_path = DerivationPath::master();
let result = node.setup_channel(channel_id, None, setup.clone(), &holder_shutdown_key_path);
assert_failed_precondition_err!(
result,
"policy failure: validate_setup_channel: \
holder_shutdown_script is not in wallet or allowlist"
);
}
#[test]
fn setup_channel_holder_shutdown_script_in_allowlist() {
let node = init_node(TEST_NODE_CONFIG, TEST_SEED[1]);
let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
node.new_channel_with_id(channel_id.clone(), &node).expect("new_channel");
let mut setup = make_test_channel_setup();
setup.holder_shutdown_script =
Some(hex_script!("0014be56df7de366ad8ee9ccdad54e9a9993e99ef565"));
node.add_allowlist(&vec!["tb1qhetd7l0rv6kca6wvmt25ax5ej05eaat9q29z7z".to_string()])
.expect("added allowlist");
let holder_shutdown_key_path = DerivationPath::master();
let result = node.setup_channel(channel_id, None, setup.clone(), &holder_shutdown_key_path);
assert_status_ok!(result);
}
#[test]
fn setup_channel_holder_shutdown_script_in_wallet() {
let node = init_node(TEST_NODE_CONFIG, TEST_SEED[1]);
let channel_id = ChannelId::new(&hex_decode(TEST_CHANNEL_ID[0]).unwrap());
node.new_channel_with_id(channel_id.clone(), &node).expect("new_channel");
let mut setup = make_test_channel_setup();
setup.holder_shutdown_script =
Some(hex_script!("0014b76dd61e41b5ef052af21cda3260888c070bb9af"));
let holder_shutdown_key_path = to_derivation_path(&[7u32]);
let result = node.setup_channel(channel_id, None, setup.clone(), &holder_shutdown_key_path);
assert_status_ok!(result);
}
}