Skip to content

Commit 90d2e53

Browse files
authored
Merge pull request lightningdevkit#10 from grizznaut/blog-v1-infra-notes
add blog post on payjoin v1 infrastructure
2 parents e0e0bc5 + b788b7a commit 90d2e53

File tree

3 files changed

+192
-2
lines changed

3 files changed

+192
-2
lines changed

docs/.vuepress/config.js

+26
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,32 @@ module.exports = {
6666
themeColor,
6767
tags: ['Bitcoin', 'Payjoin', 'PDK', 'Payjoin Dev Kit', 'Documentation']
6868
}),
69+
plugins: [
70+
[
71+
'@vuepress/blog',
72+
{
73+
directories: [
74+
{
75+
id: 'blog',
76+
dirname: '_blog',
77+
path: '/blog/',
78+
},
79+
],
80+
frontmatters: [
81+
{
82+
id: 'tag',
83+
keys: ['tag', 'tags'],
84+
path: '/blog/tags/',
85+
},
86+
{
87+
id: 'author',
88+
keys: ['author', 'authors'],
89+
path: '/blog/author/',
90+
}
91+
]
92+
},
93+
],
94+
],
6995
themeConfig: {
7096
domain: baseUrl,
7197
logo: '/img/logo.svg',
+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
---
2+
title: "Notes on payjoin v1 infrastructure"
3+
description: "A guide on setting up a payjoin receiver on signet"
4+
date: "2024-05-22"
5+
authors:
6+
- spacebear
7+
tags:
8+
- PDK
9+
- Infrastructure
10+
---
11+
12+
<br/>
13+
14+
Payjoin v1 coordinates payjoins over a public server endpoint secured by either TLS or Tor hidden service hosted by the receiver. This requires setting up either a HTTPS proxy or a Tor proxy when testing payjoins across different implementations.
15+
16+
## Setting up a HTTPS payjoin server with nginx
17+
18+
This guide requires a dedicated server that you can `ssh` into, with the ability to `sudo`, and a domain name pointing to that server.
19+
20+
### Configure a nginx proxy
21+
22+
First, ensure nginx is installed on the server or [install nginx](https://nginx.org/en/docs/install.html).
23+
24+
Then, we'll edit `/etc/nginx/nginx.conf` to proxy traffic to the payjoin server (more on that later) by adding the following block:
25+
26+
```
27+
# nginx.conf
28+
server {
29+
server_name pj.example.com; # Replace this with your domain name
30+
31+
location / {
32+
proxy_pass http://localhost:3000; # This is the port on which we'll run the payjoin server
33+
34+
proxy_set_header Host $host;
35+
proxy_set_header X-Real-IP $remote_addr;
36+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
37+
proxy_set_header X-Forwarded-Proto $scheme;
38+
}
39+
}
40+
```
41+
42+
Note that the above configuration uses the `pj` subdomain to avoid conflicts with anything that may already be running on the root domain.
43+
44+
### Get a certificate
45+
46+
Next, we'll need to obtain a valid TLS certificate from a Certificate Authority. There are many ways to do this, but one free and relatively easy option is to use [certbot](https://certbot.eff.org/instructions), an open-source tool by [letsencrypt.org](https://letsencrypt.org).
47+
48+
Once certbot is installed, we can obtain a certificate and automatically update the nginx configuration:
49+
50+
```sudo certbot -d <server_name from the nginx.conf above> --nginx```
51+
52+
`/etc/nginx/nginx.conf` should now look something like this:
53+
54+
```
55+
# nginx.conf
56+
server {
57+
server_name pj.example.com;
58+
59+
location / {
60+
proxy_pass http://localhost:3000;
61+
62+
proxy_set_header Host $host;
63+
proxy_set_header X-Real-IP $remote_addr;
64+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
65+
proxy_set_header X-Forwarded-Proto $scheme;
66+
}
67+
68+
listen 443 ssl; # managed by Certbot
69+
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
70+
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
71+
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
72+
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
73+
}
74+
```
75+
76+
Verify the installation with `curl`:
77+
78+
```
79+
[ec2-user@ip-172-31-94-70 ~]$ curl -v https://<server_name>
80+
* Host pj.example.com:443 was resolved.
81+
* IPv6: (none)
82+
* IPv4: 54.156.128.153
83+
* Trying 54.156.128.153:443...
84+
* Connected to pj.example.com (54.156.128.153) port 443
85+
* ALPN: curl offers h2,http/1.1
86+
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
87+
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
88+
* CApath: none
89+
* TLSv1.3 (IN), TLS handshake, Server hello (2):
90+
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
91+
* TLSv1.3 (IN), TLS handshake, Certificate (11):
92+
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
93+
* TLSv1.3 (IN), TLS handshake, Finished (20):
94+
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
95+
* TLSv1.3 (OUT), TLS handshake, Finished (20):
96+
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / id-ecPublicKey
97+
* ALPN: server accepted http/1.1
98+
* Server certificate:
99+
* subject: CN=spacebear.dev
100+
* start date: Apr 18 01:37:16 2024 GMT
101+
* expire date: Jul 17 01:37:15 2024 GMT
102+
* subjectAltName: host "pj.example.com" matched cert's "pj.example.com"
103+
* issuer: C=US; O=Let's Encrypt; CN=R3
104+
* SSL certificate verify ok.
105+
106+
...
107+
108+
<html>
109+
<head><title>502 Bad Gateway</title></head>
110+
<body>
111+
<center><h1>502 Bad Gateway</h1></center>
112+
<hr><center>nginx/1.25.0</center>
113+
</body>
114+
</html>
115+
```
116+
117+
If everything worked, we should see "SSL certificate verify ok."! We now have a legit HTTPS server proxying traffic to port 3000, but as indicated by the 502 error there is nothing running there. The next step is to setup a payjoin receiver to run on that port.
118+
119+
#### (Optional) Make a cronjob to auto-renew the certificate on a schedule
120+
121+
```
122+
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
123+
```
124+
125+
### Set up Bitcoin Core on signet
126+
127+
Because we're testing between wallets on different machines, regtest won't work (at least not trivially). We need a "real" Bitcoin network like signet. [Install Bitcoin Core](https://bitcoincore.org/) and edit `~/.bitcoin/bitcoin.conf`:
128+
129+
```
130+
# bitcoin.conf
131+
chain=signet
132+
server=1
133+
rpcuser=payjoin
134+
rpcpassword=payjoin
135+
```
136+
137+
`bitcoind` will take a few minutes to sync. In the meantime, let's create `sender` and `receiver` wallets and fund them. Use a signet faucet like https://signetfaucet.com/ if you don't have any signet coins on hand.
138+
139+
### Install and run payjoin-cli receiver
140+
141+
Finally, we'll install (or build from source) [payjoin-cli](https://github.com/payjoin/rust-payjoin/tree/master/payjoin-cli#install-payjoin-cli) and make a `config.toml` in the directory we plan on running payjoin-cli from:
142+
143+
```
144+
# config.toml
145+
bitcoind_rpcuser = "payjoin"
146+
bitcoind_rpcpass = "payjoin"
147+
bitcoind_rpchost = "http://localhost:38332/wallet/receiver"
148+
```
149+
150+
We can now run the receiver:
151+
152+
```
153+
$ payjoin-cli receive 10000
154+
Listening at 0.0.0.0:3000. Configured to accept payjoin at BIP 21 Payjoin Uri:
155+
bitcoin:tb1q9e5qgztf6w4zz2m3ts3w2zp3psdqpgmtdkf7y0?amount=0.0001&pj=https://localhost:3000/&pjos=0
156+
```
157+
158+
### Send payjoin!
159+
160+
Send a payjoin to the BIP21 Uri generated above, taking care to replace `localhost:3000` in the `pj=` parameter with the domain name where your server is running. This should work from any wallet that implements payjoin support, from any machine.
161+
162+
E.g. sending from joinmarket:
163+
164+
```
165+
(jmvenv) $ sendpayment.py -m 0 wallet.jmdat "bitcoin:tb1q9e5qgztf6w4zz2m3ts3w2zp3psdqpgmtdkf7y0?amount=0.0001&pj=https://pj.example.com/&pjos=0"
166+
```

docs/_blog/pdk-an-sdk-for-payjoin-transactions.md

-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ tags:
99
- PDK
1010
---
1111

12-
<br/>
13-
<br/>
1412
<br/>
1513

1614
PDK is here to make Payjoin a drop in upgrade for all software touching Bitcoin. I cover the project's history, why you should consider it to add Payjoin to your stack, and some of the project's priorities moving forward. The PDK team will be updating this new blog with development updates, feature forecasts and the details of releases.

0 commit comments

Comments
 (0)