Skip to content
Open
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
10 changes: 10 additions & 0 deletions smite-ir/src/generators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@
mod channel_announcement;
mod channel_ready;
mod channel_update;
mod error;
mod funding_created;
mod funding_flow;
mod node_announcement;
mod open_channel;
mod warning;

pub use channel_announcement::ChannelAnnouncementGenerator;
pub use channel_ready::ChannelReadyGenerator;
pub use channel_update::ChannelUpdateGenerator;
pub use error::SendErrorGenerator;
pub use funding_created::FundingCreatedGenerator;
pub use funding_flow::FundingFlowGenerator;
pub use node_announcement::NodeAnnouncementGenerator;
pub use open_channel::OpenChannelGenerator;
pub use warning::SendWarningGenerator;

use rand::Rng;

Expand All @@ -42,6 +46,8 @@ pub enum AnyGenerator {
FundingCreated(FundingCreatedGenerator),
ChannelReady(ChannelReadyGenerator),
FundingFlow(FundingFlowGenerator),
SendError(SendErrorGenerator),
SendWarning(SendWarningGenerator),
}

impl AnyGenerator {
Expand All @@ -54,6 +60,8 @@ impl AnyGenerator {
Self::FundingCreated(FundingCreatedGenerator),
Self::ChannelReady(ChannelReadyGenerator),
Self::FundingFlow(FundingFlowGenerator),
Self::SendError(SendErrorGenerator),
Self::SendWarning(SendWarningGenerator),
];
}

Expand All @@ -67,6 +75,8 @@ impl Generator for AnyGenerator {
Self::FundingCreated(generator) => generator.generate(builder, rng),
Self::ChannelReady(generator) => generator.generate(builder, rng),
Self::FundingFlow(generator) => generator.generate(builder, rng),
Self::SendError(generator) => generator.generate(builder, rng),
Self::SendWarning(generator) => generator.generate(builder, rng),
}
}
}
30 changes: 30 additions & 0 deletions smite-ir/src/generators/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! Generator for the BOLT 1 `error` message.

use rand::{Rng, RngExt};
use smite::bolt::ChannelId;

use super::Generator;
use crate::builder::ProgramBuilder;
use crate::{Operation, VariableType};

/// Generates an unsolicited `error` send.
///
/// The target fails the referenced channel, so inserting this after a funding
/// flow exercises its force-close path.
#[derive(Clone, Copy)]
pub struct SendErrorGenerator;

impl Generator for SendErrorGenerator {
fn generate(&self, builder: &mut ProgramBuilder, rng: &mut impl Rng) {
// The all-zero id fails every channel at once (BOLT 1), a path the
// mutator rarely reaches by flipping bits in a real channel_id.
let channel_id = if rng.random_ratio(1, 4) {
builder.append(Operation::LoadChannelId(ChannelId::ALL.0), &[])
} else {
builder.pick_variable(VariableType::ChannelId, rng)
};
let data = builder.pick_variable(VariableType::Bytes, rng);

builder.append(Operation::SendError, &[channel_id, data]);
}
}
30 changes: 30 additions & 0 deletions smite-ir/src/generators/warning.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! Generator for the BOLT 1 `warning` message.

use rand::{Rng, RngExt};
use smite::bolt::ChannelId;

use super::Generator;
use crate::builder::ProgramBuilder;
use crate::{Operation, VariableType};

/// Generates an unsolicited `warning` send.
///
/// Targets only log warnings, so this mainly covers their parsing and logging
/// of untrusted `data` for both known and unknown channels.
#[derive(Clone, Copy)]
pub struct SendWarningGenerator;

impl Generator for SendWarningGenerator {
fn generate(&self, builder: &mut ProgramBuilder, rng: &mut impl Rng) {
// The all-zero id marks a warning as not channel-specific (BOLT 1), a
// path the mutator rarely reaches by flipping bits in a real channel_id.
let channel_id = if rng.random_ratio(1, 4) {
builder.append(Operation::LoadChannelId(ChannelId::ALL.0), &[])
} else {
builder.pick_variable(VariableType::ChannelId, rng)
};
let data = builder.pick_variable(VariableType::Bytes, rng);

builder.append(Operation::SendWarning, &[channel_id, data]);
}
}
2 changes: 2 additions & 0 deletions smite-ir/src/mutators/operation_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ fn mutate_operation(op: &mut Operation, rng: &mut impl Rng) -> bool {
| Operation::SendOpenChannel
| Operation::SendFundingCreated
| Operation::SendShutdown
| Operation::SendError
| Operation::SendWarning
| Operation::RecvAcceptChannel
| Operation::RecvFundingSigned
| Operation::RecvChannelReady
Expand Down
30 changes: 27 additions & 3 deletions smite-ir/src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,18 @@ pub enum Operation {
/// 0: `channel_id` (`ChannelId`)
/// 1: `scriptpubkey` (`Bytes`)
SendShutdown,
/// Build and send an `error` message (BOLT 1, type 17).
///
/// Inputs (2):
/// 0: `channel_id` (`ChannelId`, all zeros = all channels)
/// 1: `data` (`Bytes`)
SendError,
/// Build and send a `warning` message (BOLT 1, type 1).
///
/// Inputs (2):
/// 0: `channel_id` (`ChannelId`, all zeros = not channel-specific)
/// 1: `data` (`Bytes`)
SendWarning,
/// Receive and parse an `accept_channel` response.
/// Produces an `AcceptChannel` compound variable.
RecvAcceptChannel,
Expand Down Expand Up @@ -553,6 +565,8 @@ impl fmt::Display for Operation {
write!(f, "SendChannelReady{{include_alias={include_alias}}}")
}
Self::SendShutdown => write!(f, "SendShutdown"),
Self::SendError => write!(f, "SendError"),
Self::SendWarning => write!(f, "SendWarning"),
Self::RecvAcceptChannel => write!(f, "RecvAcceptChannel"),
Self::RecvFundingSigned => write!(f, "RecvFundingSigned"),
Self::RecvChannelReady => write!(f, "RecvChannelReady()"),
Expand Down Expand Up @@ -594,6 +608,8 @@ impl Operation {
| Self::BuildAnnouncementSignatures => Some(VariableType::Message),
Self::SendMessage
| Self::SendChannelReady { .. }
| Self::SendError
| Self::SendWarning
| Self::RecvChannelReady
| Self::MineBlocks(_)
| Self::BroadcastTransaction => None,
Expand Down Expand Up @@ -712,9 +728,9 @@ impl Operation {
VariableType::Point, // second_per_commitment_point
VariableType::ShortChannelId, // short_channel_id (alias)
],
Self::SendShutdown => vec![
Self::SendShutdown | Self::SendError | Self::SendWarning => vec![
VariableType::ChannelId, // channel_id
VariableType::Bytes, // scriptpubkey
VariableType::Bytes, // scriptpubkey (shutdown) or data (error, warning)
],
Self::RecvAcceptChannel => vec![VariableType::SentOpenChannel],
Self::RecvFundingSigned => vec![VariableType::SentFundingCreated],
Expand Down Expand Up @@ -761,6 +777,8 @@ impl Operation {
| Self::SendFundingCreated
| Self::SendChannelReady { .. }
| Self::SendShutdown
| Self::SendError
| Self::SendWarning
| Self::RecvFundingSigned
| Self::RecvChannelReady
| Self::MineBlocks(_)
Expand Down Expand Up @@ -809,6 +827,8 @@ impl Operation {
| Self::SendFundingCreated
| Self::SendChannelReady { .. }
| Self::SendShutdown
| Self::SendError
| Self::SendWarning
| Self::RecvAcceptChannel
| Self::RecvFundingSigned
| Self::RecvChannelReady
Expand Down Expand Up @@ -853,7 +873,9 @@ impl Operation {
| Self::SendMessage
| Self::SendOpenChannel
| Self::SendChannelReady { .. }
| Self::SendShutdown => true,
| Self::SendShutdown
| Self::SendError
| Self::SendWarning => true,
// `CreateFundingTransaction` selects coins from the wallet, whose
// contents change as transactions are created and broadcast.
// `SendFundingCreated` builds its message from the recorded
Expand Down Expand Up @@ -916,6 +938,8 @@ impl Operation {
| Self::SendOpenChannel
| Self::SendFundingCreated
| Self::SendShutdown
| Self::SendError
| Self::SendWarning
| Self::RecvAcceptChannel
| Self::RecvFundingSigned
| Self::RecvChannelReady
Expand Down
Loading