Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 13 additions & 17 deletions smite-scenarios/src/executor/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1662,21 +1662,20 @@ fn execute_recv_channel_ready_unexpected_message() {

#[test]
fn execute_recv_channel_ready_rejects_reused_our_pubkey() {
// The target's `channel_ready` reuses a pubkey we revealed in an
// `open_channel` of a different negotiation.
let mut oc = SampleOpenChannel::new(PointSource::Secret([0x11; 32]));
oc.message.temporary_channel_id = SECOND_TEMPORARY_CHANNEL_ID;
// The target's `channel_ready` reuses a pubkey we revealed in our
// `open_channel`.
let oc = funded_open_channel();
let reused = oc.message.funding_pubkey;

let mut b = ProgramBuilder::new();
let sent_open_channel = send_open_channel(&mut b, &oc);
let negotiated = negotiate_channel(&mut b, &oc);
let funding_created = send_funding_created(&mut b);
b.append(Operation::RecvFundingSigned, &[funding_created.sent]);
b.append(Operation::MineBlocks(6), &[]);
b.append(Operation::RecvChannelReady, &[]);

let err = Fixture::new()
.with_negotiation(sample_funding_negotiation())
.queue(&Message::AcceptChannel(funded_accept_channel()))
.queue(&funding_signed_reply(funding_channel_id()))
.queue(&channel_ready_reply(reused))
.run_err(&b.build());
Expand All @@ -1687,32 +1686,29 @@ fn execute_recv_channel_ready_rejects_reused_our_pubkey() {
assert_eq!(*id, funding_channel_id());
assert!(reason.contains(&format!(
"second_per_commitment_point {reused} reuses our key from instruction {}",
sent_open_channel.sent,
negotiated.open_channel.sent,
)));
}

#[test]
fn execute_recv_channel_ready_rejects_reused_target_static_pubkey() {
let mut oc = announced_open_channel();
oc.message.temporary_channel_id = SECOND_TEMPORARY_CHANNEL_ID;

// The target's `channel_ready` reuses a static pubkey it revealed in an
// `accept_channel` of a different negotiation.
// The target's `channel_ready` reuses a static pubkey it revealed in its
// `accept_channel`. A distinct key in a non-first field shows every static
// pubkey is recorded, not just `funding_pubkey`.
let accept_channel = AcceptChannel {
temporary_channel_id: SECOND_TEMPORARY_CHANNEL_ID,
..sample_accept_channel()
delayed_payment_basepoint: sample_pubkey(11),
..funded_accept_channel()
};
let reused = accept_channel.delayed_payment_basepoint;

Comment on lines +1695 to 1703

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

These changes made this mutant alive:

diff --git a/smite-scenarios/src/executor.rs b/smite-scenarios/src/executor.rs
--- a/smite-scenarios/src/executor.rs
+++ b/smite-scenarios/src/executor.rs
@@ -1444,7 +1444,7 @@ fn record_recv_accept_channel(

     let channel = accept_channel.temporary_channel_id;
     // Static pubkeys may recur across channels, so keep the first origin.
-    for (field, pubkey) in accept_channel.static_pubkeys() {
+    for (field, pubkey) in accept_channel.static_pubkeys().into_iter().take(1) {
         revealed_pubkeys
             .entry(pubkey)
             .or_insert(KeyOrigin::TargetStatic { channel, field });
Suggested change
// The target's `channel_ready` reuses a static pubkey it revealed in its
// `accept_channel`.
let accept_channel = funded_accept_channel();
let reused = accept_channel.funding_pubkey;
// The target's `channel_ready` reuses a static pubkey it revealed in its
// `accept_channel`. A distinct key in a non-first field shows every static
// pubkey is recorded, not just `funding_pubkey`.
let accept_channel = AcceptChannel {
delayed_payment_basepoint: sample_pubkey(11),
..funded_accept_channel()
};
let reused = accept_channel.delayed_payment_basepoint;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied.

let mut b = ProgramBuilder::new();
negotiate_channel(&mut b, &oc);
negotiate_channel(&mut b, &funded_open_channel());
let funding_created = send_funding_created(&mut b);
b.append(Operation::RecvFundingSigned, &[funding_created.sent]);
b.append(Operation::MineBlocks(6), &[]);
b.append(Operation::RecvChannelReady, &[]);

let err = Fixture::new()
.with_negotiation(sample_funding_negotiation())
.queue(&Message::AcceptChannel(accept_channel))
.queue(&funding_signed_reply(funding_channel_id()))
.queue(&channel_ready_reply(reused))
Expand All @@ -1723,7 +1719,7 @@ fn execute_recv_channel_ready_rejects_reused_target_static_pubkey() {
};
assert_eq!(*id, funding_channel_id());
assert!(reason.contains(&format!(
"second_per_commitment_point {reused} reuses target's delayed_payment_basepoint on channel {SECOND_TEMPORARY_CHANNEL_ID}"
"second_per_commitment_point {reused} reuses target's delayed_payment_basepoint on channel {TEMPORARY_CHANNEL_ID}"
)));
}

Expand Down
87 changes: 44 additions & 43 deletions smite-scenarios/src/executor/tests/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,51 +473,52 @@ pub fn recv_channel_ready_fixture() -> (Fixture, PublicKey) {
(fx, target_pcp)
}

#[allow(clippy::similar_names)]
pub fn sample_funding_negotiation() -> PendingChannel {
let secp = Secp256k1::new();
let opener_pk = PublicKey::from_secret_key(&secp, &opener_funding_sk());
let acceptor_pk = PublicKey::from_secret_key(&secp, &acceptor_funding_sk());
/// The `open_channel` of the funding flow, with all six pubkeys derived from
/// [`opener_funding_sk`].
pub fn funded_open_channel() -> SampleOpenChannel {
let mut oc = SampleOpenChannel::new(PointSource::Secret(opener_funding_sk().secret_bytes()));
oc.message.funding_satoshis = 10_000_000;
oc.message.push_msat = 3_000_000_000;
oc.message.feerate_per_kw = 15_000;
oc.message.tlvs.channel_type = Some(ChannelTypeVariant::StaticRemoteKey.encode());

oc
}

PendingChannel {
open_channel: OpenChannel {
chain_hash: REGTEST_CHAIN_HASH,
temporary_channel_id: TEMPORARY_CHANNEL_ID,
funding_satoshis: 10_000_000,
push_msat: 3_000_000_000,
dust_limit_satoshis: 546,
max_htlc_value_in_flight_msat: 100_000_000,
channel_reserve_satoshis: 10_000,
htlc_minimum_msat: 1_000,
feerate_per_kw: 15_000,
to_self_delay: 144,
max_accepted_htlcs: 483,
funding_pubkey: opener_pk,
revocation_basepoint: opener_pk,
payment_basepoint: opener_pk,
delayed_payment_basepoint: opener_pk,
htlc_basepoint: opener_pk,
first_per_commitment_point: opener_pk,
channel_flags: 1,
tlvs: OpenChannelTlvs::default(),
/// The target's `accept_channel` for [`funded_open_channel`], with all five
/// static pubkeys derived from [`acceptor_funding_sk`].
pub fn funded_accept_channel() -> AcceptChannel {
let acceptor_pk = PublicKey::from_secret_key(&Secp256k1::new(), &acceptor_funding_sk());

AcceptChannel {
temporary_channel_id: TEMPORARY_CHANNEL_ID,
dust_limit_satoshis: 546,
max_htlc_value_in_flight_msat: 100_000_000,
channel_reserve_satoshis: 10_000,
htlc_minimum_msat: 1_000,
minimum_depth: 6,
to_self_delay: 144,
max_accepted_htlcs: 483,
funding_pubkey: acceptor_pk,
revocation_basepoint: acceptor_pk,
payment_basepoint: acceptor_pk,
delayed_payment_basepoint: acceptor_pk,
htlc_basepoint: acceptor_pk,
// Distinct from the static pubkeys and every other sample pubkey the
// tests use, as required by `AcceptChannelOracle`.
first_per_commitment_point: sample_pubkey(10),
tlvs: AcceptChannelTlvs {
upfront_shutdown_script: None,
channel_type: Some(ChannelTypeVariant::StaticRemoteKey.encode()),
},
accept_channel: Some(AcceptChannel {
temporary_channel_id: TEMPORARY_CHANNEL_ID,
dust_limit_satoshis: 546,
max_htlc_value_in_flight_msat: 100_000_000,
channel_reserve_satoshis: 10_000,
htlc_minimum_msat: 1_000,
minimum_depth: 6,
to_self_delay: 144,
max_accepted_htlcs: 483,
funding_pubkey: acceptor_pk,
revocation_basepoint: acceptor_pk,
payment_basepoint: acceptor_pk,
delayed_payment_basepoint: acceptor_pk,
htlc_basepoint: acceptor_pk,
first_per_commitment_point: acceptor_pk,
tlvs: AcceptChannelTlvs::default(),
}),
}
}

/// The negotiation of [`funded_open_channel`] and [`funded_accept_channel`].
pub fn sample_funding_negotiation() -> PendingChannel {
PendingChannel {
open_channel: funded_open_channel().message,
accept_channel: Some(funded_accept_channel()),
funding_built: false,
}
}
Expand Down
12 changes: 6 additions & 6 deletions smite-scenarios/src/executor/tests/programs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
//! purpose is to create malformed program.

use super::harness::{
PointSource, SampleOpenChannel, TEMPORARY_CHANNEL_ID, acceptor_funding_sk, opener_funding_sk,
second_funding_negotiation,
PointSource, SampleOpenChannel, TEMPORARY_CHANNEL_ID, acceptor_funding_sk, funded_open_channel,
opener_funding_sk, second_funding_negotiation,
};
use crate::executor::*;
use smite_ir::Instruction;
Expand Down Expand Up @@ -182,8 +182,7 @@ pub fn negotiate_channel_program(oc: &SampleOpenChannel) -> Program {

// -- Funding transaction --

/// The funding amount and feerate the funding-flow programs negotiate.
const FUNDING_SATOSHIS: u64 = 10_000_000;
/// The funding transaction feerate used by the funding-flow programs.
const FUNDING_FEERATE_PER_KW: u32 = 15_000;

/// The variables a funding transaction fragment produces.
Expand All @@ -199,10 +198,11 @@ pub struct FundingTxVars {
pub tx: usize,
}

/// Emits a `CreateFundingTransaction` for [`FUNDING_SATOSHIS`] at
/// Emits a `CreateFundingTransaction` for [`funded_open_channel`], at
/// [`FUNDING_FEERATE_PER_KW`].
pub fn create_funding_tx(b: &mut ProgramBuilder) -> FundingTxVars {
create_funding_tx_with(b, FUNDING_SATOSHIS, FUNDING_FEERATE_PER_KW)
let funding_satoshis = funded_open_channel().message.funding_satoshis;
create_funding_tx_with(b, funding_satoshis, FUNDING_FEERATE_PER_KW)
}

/// Emits a `CreateFundingTransaction` between the opener and acceptor funding
Expand Down
Loading