@@ -68,9 +68,9 @@ userConfig.setChannelHandshakeConfig(val: channelConfig)
68
68
69
69
let createChannelResults = channelManager.createChannel (
70
70
theirNetworkKey : pubKey,
71
- channelValueSatoshis : amount,
72
- pushMsat : pushMsat,
73
- userChannelId : userId,
71
+ channelValueSatoshis : amount,
72
+ pushMsat : pushMsat,
73
+ userChannelId : userId,
74
74
overrideConfig : userConfig
75
75
)
76
76
```
@@ -81,49 +81,40 @@ let createChannelResults = channelManager.createChannel(
81
81
82
82
# FundingGenerationReady Event Handling
83
83
84
- At this point, an outbound channel has been initiated with your peer and it will appear in ` ChannelManager::list_channels ` . However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a ` FundingGenerationReady ` event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.
84
+ At this point, an outbound channel has been initiated with your peer and it will appear in ` ChannelManager::list_channels ` . However, the channel is not yet funded. Once your peer accepts the channel, you will be notified with a ` FundingGenerationReady ` event. It's then your responsibility to construct the funding transaction and pass it to ChannelManager, which will broadcast it once it receives your channel counterparty's signature.
85
85
86
86
::: tip Note
87
87
88
- Remember that the funding transaction must only spend SegWit inputs.
88
+ Remember that the funding transaction must only spend [ SegWit] ( https://bitcoinops.org/en/topics/segregated-witness/ ) inputs.
89
89
90
90
:::
91
91
92
92
<CodeSwitcher :languages =" {rust:'Rust', kotlin:'Kotlin', swift:'Swift'} " >
93
93
<template v-slot:rust >
94
94
95
95
``` rust
96
- // In the event handler passed to BackgroundProcessor::start
96
+ // After the peer responds with an `accept_channel` message, an
97
+ // Event.FundingGenerationReady event will be generated.
97
98
match event {
98
99
Event :: FundingGenerationReady {
99
100
temporary_channel_id ,
100
101
channel_value_satoshis ,
101
102
output_script ,
102
103
user_channel_id ,
103
104
} => {
104
- // This is the same channel created earler.
105
- assert_eq! (event . user_channel_id, 42 );
106
-
107
- // Construct the raw transaction with one output, that is paid the amount of the
108
- // channel.
109
- let network = bitcoin_bech32 :: constants :: Network :: Testnet ;
110
- let address = WitnessProgram :: from_scriptpubkey (& output_script [.. ], network )
111
- . unwrap (). to_address;
112
- let mut outputs = vec! [HashMap :: with_capacity (1 )];
113
- outputs [0 ]. insert (address , channel_value_satoshis as f64 / 100_000_000.0 );
114
- let raw_tx = bitcoind_client . create_raw_transaction (outputs ). await ;
115
-
116
- // Have your wallet put the inputs into the transaction such that the output is
117
- // satisfied.
118
- let funded_tx = bitcoind_client . fund_raw_transaction (raw_tx ). await ;
119
- assert! (funded_tx . changepos == 0 || funded_tx . changepos == 1 );
120
-
121
- // Sign the funding transaction and give it to ChannelManager to broadcast.
122
- let signed_tx = bitcoind_client . sign_raw_transaction_with_wallet (funded_tx . hex). await ;
123
- assert_eq! (signed_tx . complete, true );
124
- let final_tx : Transaction =
125
- encode :: deserialize (& hex_utils :: to_vec (& signed_tx . hex). unwrap ()). unwrap ();
126
- channel_manager . funding_transaction_generated (& temporary_channel_id , final_tx ). unwrap ();
105
+ // Generate the funding transaction for the channel based on the channel amount
106
+ // The following uses BDK (Bitcoin Dev Kit) for on-chain logic
107
+ let (psbt , _ ) = {
108
+ let mut builder = wallet . build_tx ();
109
+ builder
110
+ . add_recipient (output_script , channel_value_satoshis )
111
+ . fee_rate (fee_rate )
112
+ . enable_rbf ()
113
+ builder . finish ()?
114
+ };
115
+ let finalized = wallet . sign (& mut psbt , SignOptions :: default ())? ;
116
+ let raw_tx = finalized . extract_tx ()
117
+
127
118
}
128
119
// ...
129
120
}
@@ -136,13 +127,10 @@ match event {
136
127
``` java
137
128
// After the peer responds with an `accept_channel` message, an
138
129
// Event.FundingGenerationReady event will be generated.
139
-
140
130
if (event is Event . FundingGenerationReady ) {
141
- val funding_spk = event. output_script
131
+ val fundingSpk = event. output_script
142
132
143
- if (funding_spk. size == 34 && funding_spk[0 ]. toInt() == 0 && funding_spk[1 ]. toInt() == 32 ) {
144
- // Generate the funding transaction for the channel based on the channel amount
145
- // The following uses BDK (Bitcoin Dev Kit) for on-chain logic
133
+ if (fundingSpk. size == 34 && fundingSpk[0 ]. toInt() == 0 && fundingSpk[1 ]. toInt() == 32 ) {
146
134
val rawTx = buildFundingTx(event. channel_value_satoshis, event. output_script)
147
135
148
136
channelManager. funding_transaction_generated(
@@ -153,6 +141,8 @@ if (event is Event.FundingGenerationReady) {
153
141
}
154
142
}
155
143
144
+ // Generate the funding transaction for the channel based on the channel amount
145
+ // The following uses BDK (Bitcoin Dev Kit) for on-chain logic
156
146
fun buildFundingTx(value: Long , script: ByteArray ): Transaction {
157
147
val scriptListUByte: List<UByte > = script. toUByteArray(). asList()
158
148
val outputScript = Script(scriptListUByte)
@@ -173,21 +163,21 @@ fun buildFundingTx(value: Long, script: ByteArray): Transaction {
173
163
``` Swift
174
164
// After the peer responds with an `accept_channel` message, an
175
165
// Event.FundingGenerationReady event will be generated.
176
-
177
166
if let event = event.getValueAsFundingGenerationReady () {
178
167
let script = Script (rawOutputScript : event.getOutputScript ())
179
168
let channelValue = event.getChannelValueSatoshis ()
180
169
let rawTx = buildFundingTx (script : script, amount : channelValue)
181
170
if let rawTx = rawTx {
182
171
channelManager.fundingTransactionGenerated (
183
- temporaryChannelId : event.getTemporaryChannelId (),
184
- counterpartyNodeId : event.getCounterpartyNodeId (),
172
+ temporaryChannelId : event.getTemporaryChannelId (),
173
+ counterpartyNodeId : event.getCounterpartyNodeId (),
185
174
fundingTransaction : rawTx.serialize ()
186
175
)
187
176
}
188
177
}
189
178
190
- // Building transaction using BDK
179
+ // Generate the funding transaction for the channel based on the channel amount
180
+ // The following uses BDK (Bitcoin Dev Kit) for on-chain logic
191
181
func buildFundingTx (script : Script, amount : UInt64 ) -> Transaction? {
192
182
do {
193
183
let transaction = try TxBuilder ().addRecipient (
@@ -208,6 +198,7 @@ func buildFundingTx(script: Script, amount: UInt64) -> Transaction? {
208
198
</CodeSwitcher >
209
199
210
200
** References:** [ Rust ` FundingGenerationReady ` docs] ( https://docs.rs/lightning/*/lightning/util/events/enum.Event.html#variant.FundingGenerationReady ) , [ Java ` FundingGenerationReady ` bindings] ( https://github.com/lightningdevkit/ldk-garbagecollected/blob/main/src/main/java/org/ldk/structs/Event.java#L95 )
201
+
211
202
# Broadcasting the Funding Transaction
212
203
213
204
After crafting the funding transaction you'll need to send it to the Bitcoin network where it will hopefully be mined and added to the blockchain. You'll need to watch this transaction and wait for a minimum of 6 confirmations before the channel is ready to use.
@@ -218,18 +209,18 @@ After crafting the funding transaction you'll need to send it to the Bitcoin net
218
209
``` rust
219
210
// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client
220
211
impl BroadcasterInterface for YourTxBroadcaster {
221
- fn broadcast_transaction (& self , tx : & Transaction ) {
222
- let locked_runtime = self . tokio_runtime . read () . unwrap ();
223
- if locked_runtime . as_ref () . is_none () {
224
- log_error! ( self . logger, " Failed to broadcast transaction: No runtime. " );
225
- return ;
226
- }
212
+ fn broadcast_transactions (& self , txs : & [ & Transaction ] ) {
213
+ let server_url = DEFAULT_ESPLORA_SERVER_URL . to_string ();
214
+ let tx_sync = Arc :: new ( EsploraSyncClient :: new ( server_url , Arc :: clone ( & logger )));
215
+ let blockchain = EsploraBlockchain :: from_client ( tx_sync . client () . clone (), BDK_CLIENT_STOP_GAP )
216
+ . with_concurrency ( BDK_CLIENT_CONCURRENCY ) ;
217
+ ( blockchain , tx_sync )
227
218
228
219
let res = tokio :: task :: block_in_place (move || {
229
220
locked_runtime
230
221
. as_ref ()
231
222
. unwrap ()
232
- . block_on (async move { self . blockchain. broadcast (tx ). await })
223
+ . block_on (async move { blockchain . broadcast (tx ). await })
233
224
});
234
225
235
226
match res {
@@ -251,20 +242,22 @@ impl BroadcasterInterface for YourTxBroadcaster {
251
242
252
243
// Using BDK (Bitcoin Dev Kit) to broadcast a transaction via the esplora client
253
244
object YourTxBroadcaster : BroadcasterInterface . BroadcasterInterfaceInterface {
254
- override fun broadcast_transaction(tx : ByteArray ? ) {
255
- val esploraURL = " esploraUrl "
245
+ override fun broadcast_transactions(txs : Array<out ByteArray > ? ? ) {
246
+ val esploraURL = " esplora url "
256
247
val blockchainConfig = BlockchainConfig . Esplora(EsploraConfig(esploraURL, null , 5u, 20u, null ))
257
- val blockchain = Blockchain(blockchainConfig)
248
+ val blockchain = Blockchain(blockchainConfig)
258
249
259
- val uByteArray = UByteArray(tx. size) { tx[it]. toUByte() }
260
- val transaction = Transaction(uByteArray. toList())
250
+ txs? . let { transactions - >
251
+ CoroutineScope(Dispatchers . IO ). launch {
252
+ transactions. forEach { txByteArray - >
253
+ val uByteArray = txByteArray. toUByteArray()
254
+ val transaction = Transaction(uByteArray. toList())
261
255
262
- tx ? . let {
263
- CoroutineScope( Dispatchers . IO ) . launch {
264
- blockchain . broadcast(transaction)
265
- }
256
+ blockchain . broadcast(transaction)
257
+ Log . i( LDKTAG , " The raw transaction broadcast is: ${txByteArray.toHex()} " )
258
+ }
259
+ }
266
260
} ?: throw (IllegalStateException(" Broadcaster attempted to broadcast a null transaction" ))
267
-
268
261
}
269
262
}
270
263
0 commit comments