Skip to content
This repository was archived by the owner on Dec 19, 2025. It is now read-only.

Commit de8afec

Browse files
authored
Merge pull request #185 from Vib-UX/wire_shutdown
Wire shutdown, closes #179
2 parents a95e7d5 + 47f73f2 commit de8afec

4 files changed

Lines changed: 105 additions & 1 deletion

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { ChannelId } from "@node-lightning/core";
2+
import { expect } from "chai";
3+
import { ShutdownMessage } from "../../lib/messages/ShutdownMessage";
4+
5+
describe("ShutdownChannelMessage", () => {
6+
describe(".deserialize", () => {
7+
it("should deserialize without error", () => {
8+
const input = Buffer.from(
9+
"0026"+ // type
10+
"0000000000000000000000000000000000000000000000000000000000000000" + // Channel ID
11+
"0015" + //len
12+
"00a41a8527eab06efc0a8df57045d247784a071e23" //p2wpkh
13+
,"hex"); // prettier-ignore
14+
const result = ShutdownMessage.deserialize(input);
15+
expect(result.type).to.equal(38);
16+
expect(result.channelId.toString()).to.equal("0000000000000000000000000000000000000000000000000000000000000000"); // prettier-ignore
17+
expect(result.scriptPubKey.toString("hex")).to.equal("00a41a8527eab06efc0a8df57045d247784a071e23"); // prettier-ignore
18+
});
19+
});
20+
describe(".serialize", () => {
21+
it("should serialize a message", () => {
22+
const instance = new ShutdownMessage();
23+
instance.channelId = new ChannelId(Buffer.from("0000000000000000000000000000000000000000000000000000000000000000", "hex")); // prettier-ignore
24+
instance.scriptPubKey = Buffer.from("00a41a8527eab06efc0a8df57045d247784a071e23", "hex"); // prettier-ignore
25+
26+
const result = instance.serialize();
27+
expect(result.toString("hex")).to.equal(
28+
"0026" +
29+
"0000000000000000000000000000000000000000000000000000000000000000" +
30+
"0015" +
31+
"00a41a8527eab06efc0a8df57045d247784a071e23",
32+
);
33+
});
34+
});
35+
});

packages/wire/lib/MessageFactory.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { QueryChannelRangeMessage } from "./messages/QueryChannelRangeMessage";
1313
import { QueryShortChannelIdsMessage } from "./messages/QueryShortChannelIdsMessage";
1414
import { ReplyChannelRangeMessage } from "./messages/ReplyChannelRangeMessage";
1515
import { ReplyShortChannelIdsEndMessage } from "./messages/ReplyShortChannelIdsEndMessage";
16+
import { ShutdownMessage } from "./messages/ShutdownMessage";
1617
import { MessageType } from "./MessageType";
1718

1819
export function deserialize(buffer: Buffer): IWireMessage {
@@ -34,6 +35,8 @@ export function deserialize(buffer: Buffer): IWireMessage {
3435
return OpenChannelMessage.deserialize(buffer);
3536
case MessageType.AcceptChannel:
3637
return AcceptChannelMessage.deserialize(buffer);
38+
case MessageType.Shutdown:
39+
return ShutdownMessage.deserialize(buffer);
3740

3841
// gossip messages
3942
case MessageType.NodeAnnouncement:

packages/wire/lib/MessageType.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export enum MessageType {
1414
FundingCreated = 34,
1515
FundingSigned = 35,
1616
FundingLocked = 36,
17-
CloseChannel = 38,
17+
Shutdown = 38,
1818
ClosingSigned = 39,
1919

2020
// Commitment (128-255)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { BufferReader, BufferWriter } from "@node-lightning/bufio";
2+
import { MessageType } from "../MessageType";
3+
import { ChannelId } from "@node-lightning/core";
4+
import { IWireMessage } from "./IWireMessage";
5+
6+
/**
7+
* ShutdownMessage represents the `shutdown` message defined in BOLT #2 of the Lightning
8+
* Specification. This message can be sent by either node. The scriptPubKey must be a valid P2WPKH,
9+
* P2WSH, P2SH-P2WPKH, P2SH-P2WSH, or any valid witness script if option_shutdown_anysegwit is
10+
* negotiated and it should be same as `shutdown_scriptpubkey` value if it was sent during
11+
* `'open/accept' channel message`. Therefore, if both conditions hold true resulting transaction
12+
* will propagate to miners. If shutdown is sent by either node, corresponding node should send
13+
* commitment_signed to commit any outstanding changes before replying shutdown. Once shutdown is
14+
* sent by both nodes no new HTLCs should be added or accepted by the channel. After successful
15+
* handshake of shutdown message, fee negotiation and signature sending can begin with
16+
* `closing_signed` message.
17+
*/
18+
export class ShutdownMessage implements IWireMessage {
19+
public static type = MessageType.Shutdown;
20+
21+
/**
22+
* Deserializes a shutdown message
23+
* @param buf
24+
*/
25+
public static deserialize(buf: Buffer): ShutdownMessage {
26+
const instance = new ShutdownMessage();
27+
const reader = new BufferReader(buf);
28+
29+
reader.readUInt16BE(); // read type
30+
instance.channelId = new ChannelId(reader.readBytes(32));
31+
const len = reader.readUInt16BE();
32+
instance.scriptPubKey = reader.readBytes(len);
33+
34+
return instance;
35+
}
36+
37+
/**
38+
* The type for message. Shutdown = 38
39+
*/
40+
public readonly type: MessageType = ShutdownMessage.type;
41+
42+
/**
43+
* ChannelId generated from the funding transactions outpoint.
44+
*/
45+
public channelId: ChannelId;
46+
47+
/**
48+
* scriptPubKey is used by the sender to get paid, it must be a valid P2WPKH, P2WSH, P2SH-P2WPKH,
49+
* P2SH-P2WSH, or any valid witness script if option_shutdown_anysegwit is negotiated and it
50+
* should be same as `shutdown_scriptpubkey` value if it was sent during `'open/accept' channel
51+
* message`.
52+
*/
53+
public scriptPubKey: Buffer;
54+
55+
/**
56+
* Serializes the message into a Buffer
57+
*/
58+
public serialize(): Buffer {
59+
const writer = new BufferWriter();
60+
writer.writeUInt16BE(this.type);
61+
writer.writeBytes(this.channelId.toBuffer());
62+
writer.writeUInt16BE(this.scriptPubKey.length);
63+
writer.writeBytes(this.scriptPubKey);
64+
return writer.toBuffer();
65+
}
66+
}

0 commit comments

Comments
 (0)