Skip to content

Commit a4ad39a

Browse files
committed
Initial commit
0 parents  commit a4ad39a

39 files changed

+5274
-0
lines changed

.github/workflows/lint.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Lint
2+
on:
3+
push:
4+
branches:
5+
- "master"
6+
pull_request:
7+
paths:
8+
- ".github/workflows/server-unit-tests.yml"
9+
- "**.go"
10+
- "go.mod"
11+
- "go.sum"
12+
13+
jobs:
14+
server:
15+
name: Lint
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Run revive linter
23+
uses: docker://morphy/revive-action:v2
24+
25+
go-mod-tidy:
26+
name: Go mod tidy
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
32+
- name: Set up Go
33+
uses: actions/setup-go@v4
34+
with:
35+
go-version-file: go.mod
36+
37+
- name: Run go mod tidy
38+
run: go mod tidy
39+
40+
- name: Ensure clean git state
41+
run: git diff-index --quiet HEAD -- || (echo "Please run 'go mod tidy' and commit changes." && exit 1)

.github/workflows/release.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0
20+
21+
- name: Setup Go
22+
uses: actions/setup-go@v4
23+
with:
24+
go-version-file: go.mod
25+
26+
- name: Run GoReleaser
27+
uses: goreleaser/goreleaser-action@v5
28+
with:
29+
distribution: goreleaser
30+
version: latest
31+
args: release --clean
32+
env:
33+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Test
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- "master"
8+
pull_request:
9+
paths:
10+
- ".github/workflows/test.yml"
11+
- "**.go"
12+
- "go.mod"
13+
- "go.sum"
14+
15+
jobs:
16+
tests:
17+
name: Tests
18+
runs-on: ubuntu-latest
19+
strategy:
20+
fail-fast: false
21+
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Go
27+
uses: actions/setup-go@v4
28+
with:
29+
go-version-file: go.mod
30+
31+
- name: Run tests
32+
run: go test ./...

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
acceptlnd.yaml
2+
acceptlnd.yml
3+
*.cert
4+
*.macaroon

.goreleaser.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
project_name: acceptlnd
2+
before:
3+
hooks:
4+
- go mod download
5+
- go mod tidy
6+
builds:
7+
-
8+
ldflags: -s -w -X main.version={{.Version}}
9+
env:
10+
- CGO_ENABLED=0
11+
goos:
12+
- darwin
13+
- linux
14+
- windows
15+
- freebsd
16+
- openbsd
17+
goarch:
18+
- 386
19+
- amd64
20+
- arm
21+
- arm64
22+
archives:
23+
-
24+
name_template: '{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}-{{ .Tag }}'
25+
format: tar.gz
26+
format_overrides:
27+
- goos: windows
28+
format: zip
29+
checksum:
30+
name_template: checksums.txt
31+
changelog:
32+
sort: asc
33+
filters:
34+
exclude:
35+
- '^docs:'
36+
- '^test:'
37+
- 'typo'

Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM golang:1.21-alpine3.18 as builder
2+
3+
WORKDIR /app
4+
5+
COPY go.mod .
6+
7+
RUN go mod download && go mod verify
8+
9+
COPY . .
10+
11+
RUN CGO_ENABLED=0 go build -o acceptlnd -ldflags="-s -w" .
12+
13+
# ---
14+
15+
FROM scratch
16+
17+
COPY --from=builder /app/acceptlnd /acceptlnd
18+
19+
ENTRYPOINT ["/acceptlnd"]

README.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
## AcceptLND
2+
3+
AcceptLND is a channel requests management tool based on policies for LND.
4+
5+
## Usage
6+
7+
```bash
8+
acceptlnd [-config CONFIG] [-debug] [-version]
9+
10+
Parameters:
11+
-config Path to the configuration file (default: "acceptlnd.yml")
12+
-debug Enable debug level logging
13+
-version Print the current version
14+
```
15+
16+
## Installation
17+
18+
Download the binary from the [Releases](https://github.com/aftermath2/acceptlnd/releases) page, use docker or compile it yourself.
19+
20+
<details><summary>Docker</summary>
21+
22+
```console
23+
docker build -t acceptlnd .
24+
# The configuration, certificate and macaroon must be mounted into the container.
25+
# The paths specified in the configuration file can be absolute or relative to the mount path.
26+
docker run --network=host -v <config_files_mount> acceptlnd <flags>
27+
```
28+
29+
</details>
30+
31+
<details><summary>Build from source</summary>
32+
33+
> Requires Go 1.18+ installed
34+
35+
```console
36+
git clone https://github.com/aftermath2/acceptlnd
37+
cd acceptlnd
38+
go build -o acceptlnd -ldflags="-s -w" .
39+
```
40+
41+
</details>
42+
43+
## Configuration
44+
45+
The configuration file can be passed as a flag (`-config="<path>"`) when executing the binary, the default value is `acceptlnd.yml`.
46+
47+
Configuration schema:
48+
49+
| Key | Type | Required | Description |
50+
| -- | -- | -- | -- |
51+
| **rpc_address** | string || LND GRPC address (`host:port`) |
52+
| **certificate_path** | string || Path to LND's TLS certificate |
53+
| **macaroon_path** | string || Path to the macaroon file. See [macaroon](#macaroon) |
54+
| **policies** | [][Policy](#policy) || Set of policies to enforce |
55+
56+
### Macaroon
57+
58+
AcceptLND needs a macaroon to communicate with the LND instance to manage channel requests.
59+
60+
Although `admin.macaroon` can be used, it is recommended baking a fine-grained macaroon that gives AcceptLND access just to the RPC methods it uses. To bake it, execute:
61+
62+
```
63+
lncli bakemacaroon uri:/lnrpc.Lightning/ChannelAcceptor uri:/lnrpc.Lightning/GetInfo uri:/lnrpc.Lightning/GetNodeInfo --save_to acceptlnd.macaroon
64+
```
65+
66+
Once created, specify its path in the `macaroon_path` field of the configuration file, it can be relative or absolute.
67+
68+
## Policy
69+
70+
Policies define a set of requirements that must be met for a request to be accepted. A configuration may have an unlimited number of policies, they are evaluated from top to bottom.
71+
72+
A policy would only be enforced if its conditions are satisfied, or if it has no conditions.
73+
74+
| Name | Type | Description |
75+
| -- | -- | -- |
76+
| **conditions** | [Conditions](#conditions) | Set of conditions that must be met to enforce the policies |
77+
| **reject_all** | boolean | Reject all channel requests |
78+
| **whitelist** | []string | List of nodes public keys whose requests will be accepted |
79+
| **blacklist** | []string | List of nodes public keys whose requests will be rejected |
80+
| **reject_private_channels** | boolean | Whether private channels should be rejected |
81+
| **reject_zero_conf_channels** | boolean | Whether to reject zero confirmation channels |
82+
| **request** | [Request](#request) | Parameters related to the channel opening request |
83+
| **node** | [Node](#node) | Parameters related to the channel initiator |
84+
85+
Here's a simple example:
86+
87+
```yml
88+
policies:
89+
-
90+
conditions:
91+
is_private: true
92+
request:
93+
channel_capacity:
94+
min: 2_000_000
95+
```
96+
97+
This policy only applies to private channels and will reject those that have a capacity lower than 2 million sats.
98+
99+
> [!Note]
100+
> The denomination used in all the numbers is **satoshis**.
101+
>
102+
> More examples can be found at [/examples](./examples/).
103+
104+
### Conditions
105+
106+
Conditions are used to evaluate policies conditionally. When used, all of them must resolve to true or the policy is skipped.
107+
108+
They are defined in the configuration exactly the same way policies are, only a few fields change.
109+
110+
| Name | Type | Description |
111+
| -- | -- | -- |
112+
| **whitelist** | []string | List of nodes public keys to which policies should be applied |
113+
| **blacklist** | []string | List of nodes public keys to which policies should not be applied |
114+
| **is_private** | boolean | Match private channels |
115+
| **wants_zero_conf** | boolean | Match zero confirmation channels |
116+
| **request** | [Request](#request) | Parameters related to the channel opening request |
117+
| **node** | [Node](#node) | Parameters related to the initiator node |
118+
119+
### Request
120+
121+
Parameters related to the channel opening request.
122+
123+
| Name | Type | Description |
124+
| -- | -- | -- |
125+
| **channel_capacity** | range | Requested channel size |
126+
| **channel_reserve** | range | Requested channel reserve |
127+
| **push_amount** | range | Pushed amount of sats |
128+
| **csv_delay** | range | Requested CSV delay |
129+
| **max_accepted_htlcs** | range | The total number of incoming HTLC's that the initiator will accept |
130+
| **min_htlc** | range | The smallest HTLC in millisatoshis that the initiator will accept |
131+
| **max_value_in_flight** | range | The maximum amount of coins in millisatoshis that can be pending in the channel |
132+
| **dust_limit** | range | The dust limit of the initiator's commitment transaction |
133+
| **commitment_types** | []int | Accepted channel commitment types. See [lnrpc.CommitmentTypes](https://lightning.engineering/api-docs/api/lnd/lightning/channel-acceptor/index.html#lnrpccommitmenttype) |
134+
135+
### Node
136+
137+
Parameters related to the node that is initiating the channel.
138+
139+
| Name | Type | Description |
140+
| -- | -- | -- |
141+
| **capacity** | range | Peer's node capacity |
142+
| **hybrid** | boolean | Whether the peer will be required to be hybrid |
143+
| **feature_flags** | []int | Feature flags the peer node must know. Check out [lnrpc.FeatureBit](https://lightning.engineering/api-docs/api/lnd/lightning/query-routes#lnrpcfeaturebit) |
144+
| **Channels** | [Channels](#Channels) | Initiator node channels |
145+
146+
### Channels
147+
148+
Parameters related to the initiator node's channels.
149+
150+
| Name | Type | Description |
151+
| -- | -- | -- |
152+
| **number** | range | Peer's number of channels |
153+
| **zero_base_fees** | boolean | Whether the peer's channels must all have zero base fees |
154+
| **capacity** | stat_range | Channels size |
155+
| **block_height** | stat_range | Channels block height |
156+
| **time_lock_delta** | stat_range | Channels time lock delta |
157+
| **min_htlc** | stat_range | Channels minimum HTLC |
158+
| **max_htlc** | stat_range | Channels maximum HTLC |
159+
| **last_update_diff** | stat_range | Channels last update difference to the time of the request (seconds) |
160+
| **together** | range | Number of channels that the host node and initiator node have together |
161+
| **incoming_fee_rates** | stat_range | Channels incoming fee rates |
162+
| **outgoing_fee_rates** | stat_range | Channels outgoing fee rates |
163+
| **incoming_base_fees** | stat_range | Channels incoming base fees |
164+
| **outgoing_base_fees** | stat_range | Channels outgoing base fees |
165+
| **outgoing_disabled** | stat_range | Number of outgoing disabled channels. The value type is float and should be between 0 and 1 |
166+
| **incoming_disabled** | stat_range | Number of incoming disabled channels. The value type is float and should be between 0 and 1 |
167+
168+
> [!Note]
169+
> **Outgoing** refers to the channel value from the initiator's node side, **incoming** to the value corresponding to the initiator node peer side.
170+
>
171+
> For instance, let's say Bob wants to open a channel with us and he already has one with Charlie. Bob has a base fee of 0 sats and Charlie has a base fee of 1 sat. In this case, the outgoing base fee is 0 sats (Bob's side) and the incoming base fee is 1 sat (Charlie's side).
172+
173+
#### Range
174+
175+
A range may have a minimum value, a maximum value or both defined. All values are in **satoshis**.
176+
177+
> `Min` and `Max` are inclusive, they include the value assigned: `[Min, Max]`.
178+
179+
##### Example
180+
181+
```yml
182+
request:
183+
channel_capacity:
184+
min: 2_000_000
185+
max: 50_000_000
186+
```
187+
188+
#### Statistic range (stat_range)
189+
190+
Statistic ranges work just like ranges but they compare values against the node's data set after being aggregated using an operation.
191+
192+
##### Example
193+
194+
```yml
195+
node:
196+
channels:
197+
outgoing_fee_rates:
198+
operation: median
199+
min: 0
200+
max: 100
201+
```
202+
203+
#### Operations
204+
205+
- **mean** (default): average of a list of numbers.
206+
- **median**: middle value in a list ordered from smallest to largest.
207+
- **mode**: most frequently occurring value on a list.
208+
- **range**: difference between the biggest and the smallest number.

0 commit comments

Comments
 (0)