<p>You are correct <code>dev-sign-last-tx</code> is indeed the command you want, but be careful, it is a dev command because it is used in integration tests to test a cheating party. Having an old fully signer commitment TX is very dangerous.</p>
<p>As you noticed <code>dev-sign-last-tx</code> is a bit racy, i.e., if there is a commmitment inbetween, you will end up with an old on. The other way of producing a commitment TX is to unilaterally close the channel, and in that case the commitment TX is guaranteed to be the latest agreed upon state.</p>
<p>You can likely compare the <code>dev-sign-last-tx</code> with the <code>scratch_txid</code> in <code>listpeers</code> and <code>listpeerchannels</code> to see if there have been changes inbetween.</p>
<p>Now for the lack of a 3rd output: the HTLC is only temporarily added, and then removed refunding the sender on failure and crediting the recipient on succcess. The HTLC output willl only be present for a brief period, and so you'd have to be rather fast to catch it with <code>dev-sign-last-tx</code>. If you want to cheat (in a test scenario) with an HTLC in the commitment you'll likely need to hold on to the incoming HTLC on the recipient side with the <code>htlc_accepted</code> hook, ensuring that you can call <code>dev-sign-last-tx</code> after adding, but before removing it again.</p>
<p>Also notice that for HTLCs that would be considered dust, they will not be materialized, since we'd spend more on creating and cleaning up the UTXO than the value that is actually being transferred.</p>

CC BY-SA 4.0
2023-06-15T06:50:20.653Z
I can see that the txid obtained from `dev-sign-last-tx` does not correspond to the `scratch_txid` I get with `listpeerchannels`. Why wasn't this command implemented to get me the actual latest transaction? Would it make sense to write a plugin to do so?
Lagrang3
CC BY-SA 4.0
2023-06-15T06:54:38.983Z
So there is a refund mechanism for failed attempts? Then situations like this would no longer happen https://bitcoin.stackexchange.com/questions/86228/is-there-a-way-to-abort-a-stuck-lightning-network-payment
Lagrang3
CC BY-SA 4.0
2023-06-15T07:32:12.070Z
So you're saying that if the amount is below the dust limit there won't be an HTLC output in the commitment transaction that represents the state of the channel? How would two nodes agree on the state of the channel if not through that commitment tx?
Lagrang3
CC BY-SA 4.0
2023-06-24T14:10:52.933Z
Re: refund mechanism preventing stuck payment: refunding requires interaction by the endpoints. So if either endpoint is faulty and doesn't sign the refund it'll still get stuck.
cdecker
CC BY-SA 4.0
2023-06-24T14:12:19.607Z
Even for dust HTLCs we have a state transition, and regole the old state (the sender might have dropped by a sat, or the recipient might have accumulated another sat (Dunst doesn't matter individually but it does in aggregate)
cdecker
CC BY-SA 4.0
2023-06-24T14:13:39.240Z
As for why we can't guarantee the latest signed commitment is the current state is because we can't stop the channel from proceeding concurrently so this is inherently racy
cdecker
CC BY-SA 4.0
2023-06-14T12:40:03.997Z
2023-06-14T12:40:03.997Z
cdecker
<p>Playing with <code>c-lightning</code> on regtest I would like to see the last valid transaction for a channel. The closest related developer command I found to do that was <code>dev-sign-last-tx</code>.
It seems to produce what I want, for example if I have 4 nodes connected like this:</p>
<pre><code>l1 -- l2 -- l3 -- l4
</code></pre>
<p>At a certain state of the channel <code>l1-l2</code> I can do</p>
<pre><code>$ l1-cli dev-sign-last-tx `l2-cli getinfo | jq -r .id` | jq -r .tx | xargs bitcoin-cli -datadir=$PATH_TO_BITCOIN -regtest decoderawtransaction
{
  &quot;txid&quot;: &quot;df1e3ce314fe9b79c1a5f5152c09cb7deac8ade5e75ebf20db0da8d66276cf6d&quot;,
  &quot;hash&quot;: &quot;7fd1536fdb32e6353236fb9e535e6c7baf0e29c8f2f29fc08721f1248c0df929&quot;,
  &quot;version&quot;: 2,
  &quot;size&quot;: 345,
  &quot;vsize&quot;: 180,
  &quot;weight&quot;: 720,
  &quot;locktime&quot;: 544766664,
  &quot;vin&quot;: [
    {
      &quot;txid&quot;: &quot;67ebfe5b79d7d92e199e80f93b9ca01ac287490749981a6f7649309b645f3eaf&quot;,
      &quot;vout&quot;: 0,
      &quot;scriptSig&quot;: {
        &quot;asm&quot;: &quot;&quot;,
        &quot;hex&quot;: &quot;&quot;
      },
      &quot;txinwitness&quot;: [
        &quot;&quot;,
        &quot;3044022056f488bd90ea49da9c5c09092f2a864b9529f92aecc596625a551c327a37838c02207f50b1701d5d74de0b1bf4e777274d76d0cffbf131254b02858d6e8bd0eadc2701&quot;,
        &quot;304402203d0a0a022c9c228e62a1b724e07e3b2caf76f3771ef967f9d86f0df2dccc1a21022018414477c5b806e322636d52b7cec771d5b0368bf843d87fd44fa6b77874a36401&quot;,
        &quot;5221032f30452ef442c5af3c6c37a3d14b8afaad9f991e2adbfb2340b3316949f719112103d0ce37acee074edfaebaa35ff3306c0f56168185bb89e956228357a913e31c5a52ae&quot;
      ],
      &quot;sequence&quot;: 2152692867
    }
  ],
  &quot;vout&quot;: [
    {
      &quot;value&quot;: 0.00001000,
      &quot;n&quot;: 0,
      &quot;scriptPubKey&quot;: {
        &quot;asm&quot;: &quot;0 1a3be66bacb918f02df8b927fabd1569902d1360&quot;,
        &quot;desc&quot;: &quot;addr(bcrt1qrga7v6avhyv0qt0chynl40g4dxgz6ymq9dyffw)#85alm0m9&quot;,
        &quot;hex&quot;: &quot;00141a3be66bacb918f02df8b927fabd1569902d1360&quot;,
        &quot;address&quot;: &quot;bcrt1qrga7v6avhyv0qt0chynl40g4dxgz6ymq9dyffw&quot;,
        &quot;type&quot;: &quot;witness_v0_keyhash&quot;
      }
    },
    {
      &quot;value&quot;: 0.00998816,
      &quot;n&quot;: 1,
      &quot;scriptPubKey&quot;: {
        &quot;asm&quot;: &quot;0 f0ddefa68335b3b84dd93cebcbb298fe88a9c7472f1ce1b2a25ae1106de776a0&quot;,
        &quot;desc&quot;: &quot;addr(bcrt1q7rw7lf5rxkemsnwe8n4uhv5cl6y2n3689uwwrv4ztts3qm08w6sqjchzpw)#c83sshvg&quot;,
        &quot;hex&quot;: &quot;0020f0ddefa68335b3b84dd93cebcbb298fe88a9c7472f1ce1b2a25ae1106de776a0&quot;,
        &quot;address&quot;: &quot;bcrt1q7rw7lf5rxkemsnwe8n4uhv5cl6y2n3689uwwrv4ztts3qm08w6sqjchzpw&quot;,
        &quot;type&quot;: &quot;witness_v0_scripthash&quot;
      }
    }
  ]
}

</code></pre>
<p>and I can see the contents of some state transaction, with two outputs that must correspond to the balance of the channel: some of the sats go to <code>l1</code> and some to <code>l2</code>.
The commitment transaction on <code>l2</code>'s side is different, which is expected. It would be interesting to verify which are the locking scripts for the outputs. I don't see how they can be extracted from the command line interface; maybe using <code>l1-cli sql ...</code> somehow?</p>
<p>However, I am not convinced the command <code>dev-sign-last-tx</code> is giving me the last valid state of the channel. If I try to make a payment through this channel and the payment succeeds I can see with <code>dev-sign-last-tx</code> a new distribution of liquidity in the outputs.
But if I try to make a payment that fails, for instance by disconnecting the recipient and using a single trial with the primitive <code>sendpay</code> rpc instead of using the more complex <code>pay</code> plugin, I know there will have to a pending HTLC in the channel but it's not reflected with the <code>dev-sign-last-tx</code>; if I try that experiment I still see 2 outputs in the transaction, when there should be 3 or even more depending on how many HTLCs are pending.</p>
<p>To me this probably means that <code>dev-sign-last-tx</code> shows the last commitment transaction that didn't have HTLCs. How can I see the actual last valid transaction that gives me the state of the channel?</p>

<core-lightning><hash-time-locked-contract>
How to check the last commited transaction in c-lightning?
Lagrang3
# How to check the last commited transaction in c-lightning?

(Asked by: username_0 on 2023-06-14)

Playing with `c-lightning` on regtest I would like to see the last valid transaction for a channel. The closest related developer command I found to do that was `dev-sign-last-tx`.
It seems to produce what I want, for example if I have 4 nodes connected like this:

```
l1 -- l2 -- l3 -- l4

```

At a certain state of the channel `l1-l2` I can do

```
$ l1-cli dev-sign-last-tx `l2-cli getinfo | jq -r .id` | jq -r .tx | xargs bitcoin-cli -datadir=$PATH_TO_BITCOIN -regtest decoderawtransaction
{
  "txid": "df1e3ce314fe9b79c1a5f5152c09cb7deac8ade5e75ebf20db0da8d66276cf6d",
  "hash": "7fd1536fdb32e6353236fb9e535e6c7baf0e29c8f2f29fc08721f1248c0df929",
  "version": 2,
  "size": 345,
  "vsize": 180,
  "weight": 720,
  "locktime": 544766664,
  "vin": [
    {
      "txid": "67ebfe5b79d7d92e199e80f93b9ca01ac287490749981a6f7649309b645f3eaf",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "txinwitness": [
        "",
        "3044022056f488bd90ea49da9c5c09092f2a864b9529f92aecc596625a551c327a37838c02207f50b1701d5d74de0b1bf4e777274d76d0cffbf131254b02858d6e8bd0eadc2701",
        "304402203d0a0a022c9c228e62a1b724e07e3b2caf76f3771ef967f9d86f0df2dccc1a21022018414477c5b806e322636d52b7cec771d5b0368bf843d87fd44fa6b77874a36401",
        "5221032f30452ef442c5af3c6c37a3d14b8afaad9f991e2adbfb2340b3316949f719112103d0ce37acee074edfaebaa35ff3306c0f56168185bb89e956228357a913e31c5a52ae"
      ],
      "sequence": 2152692867
    }
  ],
  "vout": [
    {
      "value": 0.00001000,
      "n": 0,
      "scriptPubKey": {
        "asm": "0 1a3be66bacb918f02df8b927fabd1569902d1360",
        "desc": "addr(bcrt1qrga7v6avhyv0qt0chynl40g4dxgz6ymq9dyffw)#85alm0m9",
        "hex": "00141a3be66bacb918f02df8b927fabd1569902d1360",
        "address": "bcrt1qrga7v6avhyv0qt0chynl40g4dxgz6ymq9dyffw",
        "type": "witness_v0_keyhash"
      }
    },
    {
      "value": 0.00998816,
      "n": 1,
      "scriptPubKey": {
        "asm": "0 f0ddefa68335b3b84dd93cebcbb298fe88a9c7472f1ce1b2a25ae1106de776a0",
        "desc": "addr(bcrt1q7rw7lf5rxkemsnwe8n4uhv5cl6y2n3689uwwrv4ztts3qm08w6sqjchzpw)#c83sshvg",
        "hex": "0020f0ddefa68335b3b84dd93cebcbb298fe88a9c7472f1ce1b2a25ae1106de776a0",
        "address": "bcrt1q7rw7lf5rxkemsnwe8n4uhv5cl6y2n3689uwwrv4ztts3qm08w6sqjchzpw",
        "type": "witness_v0_scripthash"
      }
    }
  ]
}

```

and I can see the contents of some state transaction, with two outputs that must correspond to the balance of the channel: some of the sats go to `l1` and some to `l2`.
The commitment transaction on `l2`'s side is different, which is expected. It would be interesting to verify which are the locking scripts for the outputs. I don't see how they can be extracted from the command line interface; maybe using `l1-cli sql ...` somehow?

However, I am not convinced the command `dev-sign-last-tx` is giving me the last valid state of the channel. If I try to make a payment through this channel and the payment succeeds I can see with `dev-sign-last-tx` a new distribution of liquidity in the outputs.
But if I try to make a payment that fails, for instance by disconnecting the recipient and using a single trial with the primitive `sendpay` rpc instead of using the more complex `pay` plugin, I know there will have to a pending HTLC in the channel but it's not reflected with the `dev-sign-last-tx`; if I try that experiment I still see 2 outputs in the transaction, when there should be 3 or even more depending on how many HTLCs are pending.

To me this probably means that `dev-sign-last-tx` shows the last commitment transaction that didn't have HTLCs. How can I see the actual last valid transaction that gives me the state of the channel?

**Tags:** core-lightning, hash-time-locked-contract


---

## 1 answers

### Answer by username_1 on 2023-06-14. Score: 1 | Accepted answer

You are correct `dev-sign-last-tx` is indeed the command you want, but be careful, it is a dev command because it is used in integration tests to test a cheating party. Having an old fully signer commitment TX is very dangerous.

As you noticed `dev-sign-last-tx` is a bit racy, i.e., if there is a commmitment inbetween, you will end up with an old on. The other way of producing a commitment TX is to unilaterally close the channel, and in that case the commitment TX is guaranteed to be the latest agreed upon state.

You can likely compare the `dev-sign-last-tx` with the `scratch_txid` in `listpeers` and `listpeerchannels` to see if there have been changes inbetween.

Now for the lack of a 3rd output: the HTLC is only temporarily added, and then removed refunding the sender on failure and crediting the recipient on succcess. The HTLC output willl only be present for a brief period, and so you'd have to be rather fast to catch it with `dev-sign-last-tx`. If you want to cheat (in a test scenario) with an HTLC in the commitment you'll likely need to hold on to the incoming HTLC on the recipient side with the `htlc_accepted` hook, ensuring that you can call `dev-sign-last-tx` after adding, but before removing it again.

Also notice that for HTLCs that would be considered dust, they will not be materialized, since we'd spend more on creating and cleaning up the UTXO than the value that is actually being transferred.

> **Comments:**
> **username_0**: I can see that the txid obtained from `dev-sign-last-tx` does not correspond to the `scratch_txid` I get with `listpeerchannels`. Why wasn't this command implemented to get me the actual latest transaction? Would it make sense to write a plugin to do so?  
> **username_0**: So there is a refund mechanism for failed attempts? Then situations like this would no longer happen https://bitcoin.stackexchange.com/questions/86228/is-there-a-way-to-abort-a-stuck-lightning-network-payment  
> **username_0**: So you're saying that if the amount is below the dust limit there won't be an HTLC output in the commitment transaction that represents the state of the channel? How would two nodes agree on the state of the channel if not through that commitment tx?  
> **username_1**: Re: refund mechanism preventing stuck payment: refunding requires interaction by the endpoints. So if either endpoint is faulty and doesn't sign the refund it'll still get stuck.  
> **username_1**: Even for dust HTLCs we have a state transition, and regole the old state (the sender might have dropped by a sat, or the recipient might have accumulated another sat (Dunst doesn't matter individually but it does in aggregate)  
> **username_1**: As for why we can't guarantee the latest signed commitment is the current state is because we can't stop the channel from proceeding concurrently so this is inherently racy  

---

