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
3 changes: 3 additions & 0 deletions smite-ir/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ impl ProgramBuilder {
VariableType::FundingTransaction => {
panic!("cannot generate fresh FundingTransaction: requires composed inputs")
}
VariableType::ChannelConfig => {
panic!("cannot generate fresh ChannelConfig: requires composed inputs")
}
}
}

Expand Down
1 change: 1 addition & 0 deletions smite-ir/src/mutators/operation_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ fn mutate_operation(op: &mut Operation, rng: &mut impl Rng) -> bool {
// match have drifted out of sync.
Operation::DerivePoint
| Operation::CreateFundingTransaction
| Operation::CreateChannelConfig
| Operation::LoadTargetPubkeyFromContext
| Operation::LoadChainHashFromContext
| Operation::BuildOpenChannel
Expand Down
41 changes: 41 additions & 0 deletions smite-ir/src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@ pub enum Operation {
/// 2: `funding_satoshis` (`Amount`)
/// 3: `feerate_per_kw` (`FeeratePerKw`)
CreateFundingTransaction,
/// Create a static channel configuration capturing the funding details and
/// the channel parameters for both parties.
///
/// Inputs (15):
/// 0: `funding_transaction` (`FundingTransaction`)
/// 1: `funding_satoshis` (`Amount`)
/// 2: `channel_type` (`Features`)
/// 3: `opener_funding_pubkey` (`Point`)
/// 4: `opener_payment_basepoint` (`Point`)
/// 5: `opener_revocation_basepoint` (`Point`)
/// 6: `opener_delayed_payment_basepoint` (`Point`)
/// 7: `opener_dust_limit_satoshis` (`Amount`)
/// 8: `opener_to_self_delay` (`U16`)
/// 9: `acceptor_funding_pubkey` (`Point`)
/// 10: `acceptor_payment_basepoint` (`Point`)
/// 11: `acceptor_revocation_basepoint` (`Point`)
/// 12: `acceptor_delayed_payment_basepoint` (`Point`)
/// 13: `acceptor_dust_limit_satoshis` (`Amount`)
/// 14: `acceptor_to_self_delay` (`U16`)
CreateChannelConfig,

// -- Build: construct a BOLT message from inputs --
/// Build an `open_channel` message (BOLT 2, type 32).
Expand Down Expand Up @@ -568,6 +588,7 @@ impl fmt::Display for Operation {
Self::DerivePoint => write!(f, "DerivePoint"),
Self::ExtractAcceptChannel(field) => write!(f, "Extract{field}"),
Self::CreateFundingTransaction => write!(f, "CreateFundingTransaction"),
Self::CreateChannelConfig => write!(f, "CreateChannelConfig"),
Self::BuildOpenChannel => write!(f, "BuildOpenChannel"),
Self::BuildNodeAnnouncement { rgb_color, alias } => write!(
f,
Expand Down Expand Up @@ -601,6 +622,7 @@ impl Operation {
Self::LoadChainHashFromContext => Some(VariableType::ChainHash),
Self::ExtractAcceptChannel(field) => Some(field.output_type()),
Self::CreateFundingTransaction => Some(VariableType::FundingTransaction),
Self::CreateChannelConfig => Some(VariableType::ChannelConfig),
Self::BuildOpenChannel | Self::BuildNodeAnnouncement { .. } => {
Some(VariableType::Message)
}
Expand Down Expand Up @@ -639,6 +661,23 @@ impl Operation {
VariableType::Amount, // funding_satoshis
VariableType::FeeratePerKw, // feerate_per_kw
],
Self::CreateChannelConfig => vec![
VariableType::FundingTransaction, // funding_transaction
VariableType::Amount, // funding_satoshis
VariableType::Features, // channel_type
VariableType::Point, // opener_funding_pubkey
VariableType::Point, // opener_payment_basepoint
VariableType::Point, // opener_revocation_basepoint
VariableType::Point, // opener_delayed_payment_basepoint
VariableType::Amount, // opener_dust_limit_satoshis
VariableType::U16, // opener_to_self_delay
VariableType::Point, // acceptor_funding_pubkey
VariableType::Point, // acceptor_payment_basepoint
VariableType::Point, // acceptor_revocation_basepoint
VariableType::Point, // acceptor_delayed_payment_basepoint
VariableType::Amount, // acceptor_dust_limit_satoshis
VariableType::U16, // acceptor_to_self_delay
],
Self::SendMessage => vec![VariableType::Message],
Self::BroadcastTransaction => vec![VariableType::FundingTransaction],

Expand Down Expand Up @@ -700,6 +739,7 @@ impl Operation {
| Self::DerivePoint
| Self::ExtractAcceptChannel(_)
| Self::CreateFundingTransaction
| Self::CreateChannelConfig
| Self::BuildOpenChannel
| Self::BuildNodeAnnouncement { .. }
| Self::SendMessage
Expand Down Expand Up @@ -739,6 +779,7 @@ impl Operation {
| Self::LoadChainHashFromContext
| Self::DerivePoint
| Self::CreateFundingTransaction
| Self::CreateChannelConfig
| Self::BuildOpenChannel
| Self::SendMessage
| Self::RecvAcceptChannel
Expand Down
130 changes: 130 additions & 0 deletions smite-ir/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,14 @@ fn postcard_roundtrip() {
operation: Operation::BroadcastTransaction,
inputs: vec![10],
},
Instruction {
operation: Operation::LoadU16(144),
inputs: vec![],
},
Instruction {
operation: Operation::CreateChannelConfig,
inputs: vec![10, 4, 5, 1, 1, 1, 1, 4, 12, 1, 1, 1, 1, 4, 12],
},
],
};

Expand Down Expand Up @@ -604,6 +612,120 @@ fn validate_rejects_broadcast_tx_with_wrong_input_type() {
);
}

fn create_channel_config_instructions() -> Vec<Instruction> {
vec![
Instruction {
operation: Operation::LoadPrivateKey(key(1)),
inputs: vec![],
},
Instruction {
operation: Operation::DerivePoint,
inputs: vec![0],
},
Instruction {
operation: Operation::LoadAmount(10_000_000),
inputs: vec![],
},
Instruction {
operation: Operation::LoadFeeratePerKw(15_000),
inputs: vec![],
},
Instruction {
operation: Operation::CreateFundingTransaction,
inputs: vec![1, 1, 2, 3],
},
Instruction {
operation: Operation::LoadFeatures(vec![0x01, 0x02]),
inputs: vec![],
},
Instruction {
operation: Operation::LoadPrivateKey(key(2)),
inputs: vec![],
},
Instruction {
operation: Operation::DerivePoint,
inputs: vec![6],
},
Instruction {
operation: Operation::LoadAmount(546),
inputs: vec![],
},
Instruction {
operation: Operation::LoadU16(144),
inputs: vec![],
},
Instruction {
operation: Operation::LoadPrivateKey(key(3)),
inputs: vec![],
},
Instruction {
operation: Operation::DerivePoint,
inputs: vec![10],
},
Instruction {
operation: Operation::CreateChannelConfig,
inputs: vec![4, 2, 5, 7, 7, 7, 7, 8, 9, 11, 11, 11, 11, 8, 9],
},
]
}

#[test]
fn displays_create_channel_config_program() {
let program = Program {
instructions: create_channel_config_instructions(),
};
let text = program.to_string();
let lines: Vec<&str> = text.lines().collect();

let z31 = "00".repeat(31);

let expected = vec![
format!("v0 = LoadPrivateKey(0x{z31}01)"),
"v1 = DerivePoint(v0)".into(),
"v2 = LoadAmount(10000000)".into(),
"v3 = LoadFeeratePerKw(15000)".into(),
"v4 = CreateFundingTransaction(v1, v1, v2, v3)".into(),
"v5 = LoadFeatures(0x0102)".into(),
format!("v6 = LoadPrivateKey(0x{z31}02)"),
"v7 = DerivePoint(v6)".into(),
"v8 = LoadAmount(546)".into(),
"v9 = LoadU16(144)".into(),
format!("v10 = LoadPrivateKey(0x{z31}03)"),
"v11 = DerivePoint(v10)".into(),
"v12 = CreateChannelConfig(v4, v2, v5, v7, v7, v7, v7, v8, v9, v11, v11, v11, v11, v8, v9)"
.into(),
];
assert_eq!(lines, expected);
}

#[test]
fn validate_accepts_create_channel_config() {
let program = Program {
instructions: create_channel_config_instructions(),
};
program
.validate()
.expect("CreateChannelConfig should validate");
}

#[test]
fn validate_rejects_create_channel_config_with_wrong_input_count() {
let program = Program {
instructions: vec![Instruction {
operation: Operation::CreateChannelConfig,
inputs: vec![],
}],
};
assert_eq!(
program.validate(),
Err(ValidateError::WrongInputCount {
instr: 0,
expected: 15,
got: 0,
}),
);
}

// Ensure AcceptChannelField and AcceptChannelField::ALL stay in sync. The
// exhaustive match in this test will fail to compile if a variant is added
// without updating it, and the assertion will fail if the match is updated
Expand Down Expand Up @@ -1055,6 +1177,14 @@ fn generate_fresh_funding_transaction_panics() {
builder.generate_fresh(VariableType::FundingTransaction, &mut rng);
}

#[test]
#[should_panic(expected = "cannot generate fresh ChannelConfig")]
fn generate_fresh_channel_config_panics() {
let mut rng = SmallRng::seed_from_u64(0);
let mut builder = ProgramBuilder::new();
builder.generate_fresh(VariableType::ChannelConfig, &mut rng);
}

#[test]
#[should_panic(expected = "expected 1 inputs, got 0")]
fn append_wrong_input_count_panics() {
Expand Down
6 changes: 5 additions & 1 deletion smite-ir/src/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use bitcoin::secp256k1::PublicKey;
use smite::bolt::{AcceptChannel, ChannelId, ShortChannelId};
use smite::channel_tx::FundingTransaction;
use smite::channel_tx::{ChannelConfig, FundingTransaction};

const CHAIN_HASH_SIZE: usize = 32;
const PRIVATE_KEY_SIZE: usize = 32;
Expand Down Expand Up @@ -47,6 +47,8 @@ pub enum Variable {
AcceptChannel(AcceptChannel),
/// Constructed funding transaction with funding output index.
FundingTransaction(FundingTransaction),
/// Static channel configuration (funding details and both parties).
ChannelConfig(ChannelConfig),
}

impl Variable {
Expand All @@ -70,6 +72,7 @@ impl Variable {
Self::Message(_) => VariableType::Message,
Self::AcceptChannel(_) => VariableType::AcceptChannel,
Self::FundingTransaction(_) => VariableType::FundingTransaction,
Self::ChannelConfig(_) => VariableType::ChannelConfig,
}
}
}
Expand All @@ -94,4 +97,5 @@ pub enum VariableType {
Message,
AcceptChannel,
FundingTransaction,
ChannelConfig,
}
Loading