Lightning Networkで支払いから認証までやっちゃう激アツ技術LSAT実装「Aperture」について
はじめに
これはno plan inc.の Advent Calendar 2022の14日目の記事です。
こちら の記事に引き続き、
LSAT実装の「Aperture」について説明しようと思います!
この記事では実際にAperuteを用いて、HTTP status code 402 レスポンスの再現と、satoshi支払いによりコンテンツが見られるようになるところまで手順書こうかと思います。
LSAT とは
lsat(「ルサット」?「エルサット」? 僕は「エルサット」派)って何? もっと知りたい。という方は、
こちら の記事を読んでもらえれば、Lightning Networkの基礎含めて概要が掴めるかと思います。
要は、
有料コンテンツ(有料API,ひみつの画像、アダルトなやつ、ひみつの文章)等々の前に設置される、HTTPの認証入リバースプロキシです。
web上の有料コンテンツへアクセスしたい時に、あるLightning Network ノードが発行する請求書に対して支払いを行ったかどうか判別し、払っていればがコンテンツが見られる、そうでなければHTTPのStatus Code 402が返され、コンテンツへアクセスができません。
Apertureとは
LSATを実装しているOSS projectです。
ドキュメントに書かれてある内容が不十分なところがあるので、この記事ではハマリポイントも押さえながら説明していきます。
Prerequisite(前提条件)
Golang
バージョンは 1.13以上
btcd
ビットコインのノードを立てるのに必要
lnd
ライトニングネットワークのノードを立てるのに必要
初心者の方は下記の記事の通りにインストール・セットアップしました。
事前にこれやっとくことおすすめします。 これやってること前提に進めていきます。
etcd
分散型の一貫したキーバリューストア
ネットワーク
ローカルで試すので、simnetを使います。
※面倒なのでdocker でやってみたいという方はこのレポジトリ参考にしてください。(DYOR)
1. 準備
btcdを起動
ターミナル上で、
$ btcd --simnet --rpcuser=kek --rpcpass=kek
2022-12-19 06:19:36.891 [INF] BTCD: Version 0.23.1-beta
2022-12-19 06:19:36.891 [INF] BTCD: Loading block database from '/Users/soma/Library/Application Support/Btcd/data/simnet/blocks_ffldb'
2022-12-19 06:19:36.974 [INF] BTCD: Block database loaded
2022-12-19 06:19:36.978 [INF] INDX: Committed filter index is enabled
2022-12-19 06:19:36.979 [INF] CHAN: Loading block index...
2022-12-19 06:19:36.983 [INF] CHAN: Chain state (height 1293, hash 12fe9d93a59d0bb800d0de20ba01485c1f6183747aecb599b23a3b6d722e33aa, totaltx 1299, work 2588)
2022-12-19 06:19:36.990 [INF] RPCS: RPC server listening on [::1]:18556
2022-12-19 06:19:36.990 [INF] RPCS: RPC server listening on 127.0.0.1:18556
2022-12-19 06:19:36.990 [INF] AMGR: Loaded 0 addresses from file '/Users/soma/Library/Application Support/Btcd/data/simnet/peers.json'
2022-12-19 06:19:36.990 [INF] CMGR: Server listening on 0.0.0.0:18555
2022-12-19 06:19:36.990 [INF] CMGR: Server listening on [::]:18555
lnd 起動
別タブを開き、
開発用のディレクトリを作成
$ mkdir dev
$ cd dev
$ mkdir alice bob
アリスのノード
$ cd $GOPATH/dev/alice
$ lnd --rpclisten=localhost:10001 --listen=localhost:10011 --restlisten=localhost:8001 --datadir=data --logdir=log --debuglevel=info --bitcoin.simnet --bitcoin.active --bitcoin.node=btcd --btcd.rpcuser=kek --btcd.rpcpass=kek
2022-12-19 06:56:42.692 [INF] LTND: Version: 0.15.99-beta commit=tor/v1.1.0-195-g7274cf40d-dirty, build=production, logging=default, debuglevel=info
2022-12-19 06:56:42.693 [INF] LTND: Active chain: Bitcoin (network=simnet)
2022-12-19 06:56:42.694 [INF] RPCS: RPC server listening on 127.0.0.1:10001
2022-12-19 06:56:42.696 [INF] RPCS: gRPC proxy started at 127.0.0.1:8001
2022-12-19 06:56:42.696 [INF] LTND: Opening the main database, this might take a few minutes...
2022-12-19 06:56:42.696 [INF] LTND: Opening bbolt database, sync_freelist=false, auto_compact=false
2022-12-19 06:56:42.702 [INF] LTND: Creating local graph and channel state DB instances
2022-12-19 06:56:42.762 [INF] CHDB: Checking for schema update: latest_version=29, db_version=29
2022-12-19 06:56:42.762 [INF] CHDB: Checking for optional update: prune_revocation_log=false, db_version=empty
2022-12-19 06:56:42.762 [INF] LTND: Database(s) now open (time_to_open=66.812083ms)!
2022-12-19 06:56:42.763 [INF] LTND: We're not running within systemd or the service type is not 'notify'
2022-12-19 06:56:42.763 [INF] LTND: Waiting for wallet encryption password. Use `lncli create` to create a wallet, `lncli unlock` to unlock an existing wallet, or `lncli changepassword` to change the password of an existing wallet and unlock it.
# 別タブにて
$ cd $GOPATH/dev/alice
# macaroonとwalletの作成
$ lncli --rpcserver=localhost:10001 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon create
$ ls -a data/chain/bitcoin/simnet/
. .. admin.macaroon invoice.macaroon macaroons.db readonly.macaroon router.macaroon wallet.db
# wallet の unlock
$ lncli --rpcserver=localhost:10001 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon unlock
ボブのノード
$ cd $GOPATH/dev/bob
$ lnd --rpclisten=localhost:10002 --listen=localhost:10012 --restlisten=localhost:8002 --datadir=data --logdir=log --debuglevel=info --bitcoin.simnet --bitcoin.active --bitcoin.node=btcd --btcd.rpcuser=kek --btcd.rpcpass=kek
2022-12-19 06:57:51.361 [INF] LTND: Version: 0.15.99-beta commit=tor/v1.1.0-195-g7274cf40d-dirty, build=production, logging=default, debuglevel=info
2022-12-19 06:57:51.361 [INF] LTND: Active chain: Bitcoin (network=simnet)
2022-12-19 06:57:51.362 [INF] RPCS: RPC server listening on 127.0.0.1:10002
2022-12-19 06:57:51.363 [INF] RPCS: gRPC proxy started at 127.0.0.1:8002
2022-12-19 06:57:51.363 [INF] LTND: Opening the main database, this might take a few minutes...
2022-12-19 06:57:51.363 [INF] LTND: Opening bbolt database, sync_freelist=false, auto_compact=false
2022-12-19 06:57:51.368 [INF] LTND: Creating local graph and channel state DB instances
2022-12-19 06:57:51.431 [INF] CHDB: Checking for schema update: latest_version=29, db_version=29
2022-12-19 06:57:51.431 [INF] CHDB: Checking for optional update: prune_revocation_log=false, db_version=empty
2022-12-19 06:57:51.432 [INF] LTND: Database(s) now open (time_to_open=68.7485ms)!
2022-12-19 06:57:51.432 [INF] LTND: We're not running within systemd or the service type is not 'notify'
2022-12-19 06:57:51.432 [INF] LTND: Waiting for wallet encryption password. Use `lncli create` to create a wallet, `lncli unlock` to unlock an existing wallet, or `lncli changepassword` to change the password of an existing wallet and unlock it.
# 別タブにて
$ cd $GOPATH/dev/bob
# macaroonとwalletの作成
$ lncli --rpcserver=localhost:10002 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon create
$ ls -a data/chain/bitcoin/simnet/
. .. admin.macaroon invoice.macaroon macaroons.db readonly.macaroon router.macaroon wallet.db
# wallet の unlock
$ lncli --rpcserver=localhost:10002 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon unlock
長いのでエイリアス登録しておきます
alias lncli-alice="lncli --rpcserver=localhost:10001 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon"
alias lncli-bob="lncli --rpcserver=localhost:10002 --macaroonpath=data/chain/bitcoin/simnet/admin.macaroon"
etcd
$ etcd
{"level":"info","ts":"2022-12-19T07:51:24.531+0900","caller":"etcdmain/etcd.go:73","msg":"Running: ","args":["etcd"]}
{"level":"info","ts":"2022-12-19T07:51:24.531+0900","caller":"etcdmain/etcd.go:100","msg":"failed to detect default host","error":"default host not supported on darwin_arm64"}
{"level":"warn","ts":"2022-12-19T07:51:24.531+0900","caller":"etcdmain/etcd.go:105","msg":"'data-dir' was empty; using default","data-dir":"default.etcd"}
{"level":"info","ts":"2022-12-19T07:51:24.531+0900","caller":"embed/etcd.go:124","msg":"configuring peer listeners","listen-peer-urls":["http://localhost:2380"]}
{"level":"info","ts":"2022-12-19T07:51:24.532+0900","caller":"embed/etcd.go:132","msg":"configuring client listeners","listen-client-urls":["http://localhost:2379"]}
{"level":"info","ts":"2022-12-19T07:51:24.532+0900","caller":"embed/etcd.go:306","msg":"starting an etcd server","etcd-version":"3.5.5","git-sha":"19002cfc6","go-version":"go1.16.15","go-os":"darwin","go-arch":"arm64","max-cpu-set":8,"max-cpu-available":8,"member-initialized":false,"name":"default","data-dir":"default.etcd","wal-dir":"","wal-dir-dedicated":"","member-dir":"default.etcd/member","force-new-cluster":false,"heartbeat-interval":"100ms","election-timeout":"1s","initial-election-tick-advance":true,"snapshot-count":100000,"snapshot-catchup-entries":5000,"initial-advertise-peer-urls":["http://localhost:2380"],"listen-peer-urls":["http://localhost:2380"],"advertise-client-urls":["http://localhost:2379"],"listen-client-urls":["http://localhost:2379"],"listen-metrics-urls":[],"cors":["*"],"host-whitelist":["*"],"initial-cluster":"default=http://localhost:2380","initial-cluster-state":"new","initial-cluster-token":"etcd-cluster","quota-backend-bytes":2147483648,"max-request-bytes":1572864,"max-concurrent-streams":4294967295,"pre-vote":true,"initial-corrupt-check":false,"corrupt-check-time-interval":"0s","compact-check-time-enabled":false,"compact-check-time-interval":"1m0s","auto-compaction-mode":"periodic","auto-compaction-retention":"0s","auto-compaction-interval":"0s","discovery-url":"","discovery-proxy":"","downgrade-check-interval":"5s"}
{"level":"info","ts":"2022-12-19T07:51:24.557+0900","caller":"etcdserver/backend.go:81","msg":"opened backend db","path":"default.etcd/member/snap......
ウォレットの残高補充
# wallet アドレスの確認
$ lncli-alice newaddress np2wkh
{
"address": "rZRRSo2f9hHVTMVo2VXUxop4Z6zKWA7tp2"
}
$ lncli-bob newaddress np2wkh
{
"address": "rXVbXGPiDuZNBtkamddQDH38Vt5h1xb7hJ"
}
# 一旦btcdノードをストップさせたのち、
# aliceへの補充
$ btcd --simnet --txindex --rpcuser=kek --rpcpass=kek --miningaddr=rZRRSo2f9hHVTMVo2VXUxop4Z6zKWA7tp2
# bobへの補充
$ btcd --simnet --txindex --rpcuser=kek --rpcpass=kek --miningaddr=rXVbXGPiDuZNBtkamddQDH38Vt5h1xb7hJ
チャネルの開設
# aliceノードのアドレスを調べる
$ lncli-alice getinfo
{
"version": "0.15.99-beta commit=tor/v1.1.0-195-g7274cf40d-dirty",
"commit_hash": "7274cf40d02ca96a39c1521e79cd7d1277518fee",
"identity_pubkey": "03195ae574334bd5c673372cd7a7e416c901a3bc3709c20403df0a3a5a5d3d32f5",
"alias": "03195ae574334bd5c673",
.....
# aliceノードとP2P接続
$ lncli-bob connect 03195ae574334bd5c673372cd7a7e416c901a3bc3709c20403df0a3a5a5d3d32f5@localhost:10011
{
}
# aliceノードとチャネル開設
$ lncli-bob openchannel --node_key=03d329c0c19c78e7c5507e4c1a17e9f5b4df3f38584ff25227f0a2ab043b6ba29e --local_amt=1000000
{
"funding_txid": "485df6d619d30a5b92e588d39ff4b9226416ff943e77f4f96224c8adbdf7a6cb"
}
チャネル開設のtxをブロックにブロードキャストするため、btcチェーンを3ブロック進める
$ btcctl --simnet --rpcuser=kek --rpcpass=kek generate 3
[
"586d1cf7e803256bb38c229448e157837e00ab56fd31424f1df6d48d684897ed",
"622651f8881651df54e9608e94e7b12ed0dfc123840d904cae66d9a04e41b46f",
"6bbfcd329c91ce8347e6f0cff48fb74182baf3792f57d03de71d1ab37d7b9b37"
]
2. HTTP 402レスポンスを体験する
apertureをクローン
$ git clone git@github.com:lightninglabs/aperture.git
$ cd aperture
apertureの設定
READMEに従うと、、
$ make build && make install
go build -v github.com/lightninglabs/aperture/cmd/aperture
golang.org/x/net/html/atom
golang.org/x/text/encoding/internal/identifier
golang.org/x/crypto/salsa20
golang.org/x/text/internal/utf8internal
github.com/beorn7/perks/quantile...........
サンプルのyamlファイルを複製
$ cp sample-confg.yaml config.yaml
yamlファイルの中身は以下のように設定します。なるべくサンプルから変えないようにしました。
# The address which the proxy can be reached at.
listenaddr: "localhost:8081"
# The root path of static content to serve upon receiving a request the proxy
# cannot handle.
staticroot: "./static"
# Should the static file server be enabled that serves files from the directory
# specified in `staticroot`?
servestatic: false
# The log level that should be used for the proxy.
#
# Valid options include: trace, debug, info, warn, error, critical, off.
debuglevel: "debug"
# Whether the proxy should create a valid certificate through Let's Encrypt for
# the fully qualifying domain name.
autocert: false
servername: aperture.example.com
# The port on which the pprof profile will be served. If no port is provided,
# the profile will not be served.
profile: 9999
# Settings for the lnd node used to generate payment requests. All of these
# options are required.
authenticator:
# The host:port which lnd's RPC can be reached at.
lndhost: "127.0.0.1:10001"
# The path to lnd's TLS certificate.
tlspath: "~/Library/Application\ Support/Lnd/tls.cert"
# The path to lnd's macaroon directory.
macdir: "/Users/soma/gocode/dev/alice/data/chain/bitcoin/simnet"
# The chain network the lnd is active on.
network: "simnet"
# Settings for the etcd instance which the proxy will use to reliably store and
# retrieve token information.
etcd:
# The client host:port which the etcd instance can be reached at.
host: "localhost:2379"
# If authentication is enabled, the user and password required to access the
# etcd instance.
# user: "user"
# password: "password"
# List of services that should be reachable behind the proxy. Requests will be
# matched to the services in order, picking the first that satisfies hostregexp
# and (if set) pathregexp. So order is important!
#
# Use single quotes for regular expressions with special characters in them to
# avoid YAML parsing errors!
services:
# The identifying name of the service. This will also be used to identify
# which capabilities caveat (if any) corresponds to the service.
- name: "service1"
# The regular expression used to match the service host.
hostregexp: '^service1.com:3000$'
# The regular expression used to match the path of the URL.
pathregexp: '^/.*$'
# The host:port which the service can be reached at.
address: "127.0.0.1:3000"
# The HTTP protocol that should be used to connect to the service. Valid
# options include: http, https.
protocol: http
# If required, a path to the service's TLS certificate to successfully
# establish a secure connection.
# tlscertpath: "path-to-optional-tls-cert/tls.cert"
# A comma-delimited list of capabilities that will be granted for tokens of
# the service at the base tier.
# capabilities: "add,subtract"
# The set of constraints that are applied to tokens of the service at the
# base tier.
constraints:
"valid_until": "2023-01-01"
# The LSAT value in satoshis for the service. It is ignored if
# dynamicprice.enabled is set to true.
price: 10
# Options to use for connection to the price serving gRPC server.
# dynamicprice:
# Whether or not a gRPC server is available to query price data from. If
# this option is set to true then the 'price' option is ignored.
# enabled: true
# The address of the gRPC pricer server.
# grpcaddress: "127.0.0.1:10010"
# Whether or not TLS encryption should be used for communications with the
# gRPC server.
# insecure: false
# The path to the pricer server's tls.cert. If the 'insecure' option is
# set to true then this path must be set.
# tlscertpath: "path-to-pricer-server-tls-cert/tls.cert"
# - name: "service2"
# hostregexp: "service2.com:8083"
# pathregexp: '^/.*$'
# address: "123.456.789:8082"
# protocol: https
# constraints:
# "valid_until": "2020-01-01"
# price: 1
# - name: "service3"
# hostregexp: "service3.com:8083"
# pathregexp: '^/.*$'
# address: "123.456.789:8082"
# protocol: https
# constraints:
# "valid_until": "2020-01-01"
# dynamicprice:
# enbled: true
# grpcaddress: 123.456.789:8083
# insecure: false
# tlscertpath: "path-to-pricer-server-tls-cert/tls.cert"
# Settings for a Tor instance to allow requests over Tor as onion services.
# Configuring Tor is optional.
# tor:
# The host:port which Tor's control can be reached at.
# control: "localhost:9051"
# The internal port we should listen on for client requests over Tor. Note
# that this port should not be exposed to the outside world, it is only
# intended to be reached by clients through the onion service.
# listenport: 8082
# The port through which the onion services to be created can be reached at.
# virtualport: 8082
# Whether a v2 onion service should be created to handle requests.
# v2: false
# Whether a v3 onion service should be created to handle requests.
# v3: false
# Enable the Lightning Node Connect hashmail server, allowing up to 1k messages
# per burst and a new message every 20 milliseconds.
# hashmail:
# enabled: true
# messagerate: 20ms
# messageburstallowance: 1000
# Enable the prometheus metrics exporter so that a prometheus server can scrape
# the metrics.
# prometheus:
# enabled: true
# listenaddr: "localhost:9000"
上の設定をざっくり要約すると、
- Aperture自身のサーバーはlocalhost:8081
- 認証がないと見られないコンテンツのホストは、service1.com:3000
- 支払いの有無を検証したり、invoice(請求書)を発行したりするlndのアドレスは、127.0.0.1:10001(aliceノード)
- コンテンツを閲覧するには10satoshi払う必要がある
これに合わせてホスト名を追記します
$ sudo vim /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost service1.com <----これを追記
255.255.255.255 broadcasthost
::1 localhost
# Added by Docker Desktop
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
# End of section
コンテンツ用のローカルサーバーをstatic下で立てます
$ cd static
$ python3 -m http.server 3000
apertureの起動
$ ./aperture --configfile=config.yaml
rpcserver.go -> addinvoices.go -> invoices.go
ヘッダー内にアクセスしたいコンテンツのホストを指定して、apertureにリクエストを送ると、'payment required'とLSATが返ってくる!!
$ curl -ki -H 'Host:service1.com:3000' https://localhost:8081
HTTP/2 402
accept: */*
access-control-allow-headers: Authorization, Grpc-Metadata-macaroon, WWW-Authenticate
access-control-allow-methods: GET, POST, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: WWW-Authenticate
content-type: text/plain; charset=utf-8
user-agent: curl/7.79.1
www-authenticate: LSAT macaroon="AgEEbHNhdAJCAACRU66KpxK3tevMpkzdRypkgyPn2KfV92NPD99+M1JUyn+hVF59TItFv8g7O+R4mHCWoLQmi/erLUPmN5tmtQv2AAITc2VydmljZXM9c2VydmljZTE6MAACFnNlcnZpY2UxX2NhcGFiaWxpdGllcz0AAhZ2YWxpZF91bnRpbD0yMDIzLTAxLTAxAAAGIB0hCEA+mbtIaB0N9bz8B00Fpd6aALXCQpktXjeH4vlt", invoice="lnsb100n1p36ghdrpp5j9f6az48z2mmt67v5exd63e2vjpj8e7c5l2lwc60pl0huv6j2n9qdq8f3f5z4qcqzpgxqyz5vqsp5g7ueyychjnwdew48cr8ufcr2996cju0gccy0yqghc3tyh8pkuhlq9qyyssq3m2qx8cmd6rkk6ef5mv2n58ukun54qg7vuvlkggak2g04v3yvtjrxrlk3yllxwzzvd4xh56ednnqztfs0ylpnzkpjywg9cl6wffvhzcp8g8c8u"
x-content-type-options: nosniff
content-length: 17
date: Tue, 13 Dec 2022 13:37:39 GMT
payment required
これは、Apertureに対して、「service1.com:3000のコンテンツを見せてくれ」とリクエストして、「お前はお金(10 satoshi)払ってないから無理、この請求書(invoice)に支払いしてくれ」と言われているということです。
3.LNで支払いをしてみる
invoiceの支払いを行う
$ lncli-bob sendpayment --pay_req=lnsb100n1p36ghdrpp5j9f6az48z2mmt67v5exd63e2vjpj8e7c5l2lwc60pl0huv6j2n9qdq8f3f5z4qcqzpgxqyz5vqsp5g7ueyychjnwdew48cr8ufcr2996cju0gccy0yqghc3tyh8pkuhlq9qyyssq3m2qx8cmd6rkk6ef5mv2n58ukun54qg7vuvlkggak2g04v3yvtjrxrlk3yllxwzzvd4xh56ednnqztfs0ylpnzkpjywg9cl6wffvhzcp8g8c8u
Payment hash: 9153ae8aa712b7b5ebcca64cdd472a648323e7d8a7d5f7634f0fdf7e335254ca
Description: LSAT
Amount (in satoshis): 10
Fee limit (in satoshis): 10
Destination: 03195ae574334bd5c673372cd7a7e416c901a3bc3709c20403df0a3a5a5d3d32f5
Confirm payment (yes/no): yes
+------------+--------------+--------------+--------------+-----+----------+------------------+-------+
| HTLC_STATE | ATTEMPT_TIME | RESOLVE_TIME | RECEIVER_AMT | FEE | TIMELOCK | CHAN_OUT | ROUTE |
+------------+--------------+--------------+--------------+-----+----------+------------------+-------+
| SUCCEEDED | 0.089 | 0.915 | 10 | 0 | 2158 | 2323268069556224 | |
+------------+--------------+--------------+--------------+-----+----------+------------------+-------+
Amount + fee: 10 + 0 sat
Payment hash: 9153ae8aa712b7b5ebcca64cdd472a648323e7d8a7d5f7634f0fdf7e335254ca
Payment status: SUCCEEDED, preimage: f25b3af74803787c6ff364341829ecacf0c7e55a35738c403f08ad19d2e7576a <--この値をコピー
invoiceの支払いが成功すると、preimageというレシートのような支払いの証明書がレスポンスで返ってくる
4.コンテンツが見られるようになる
macaroonとpreimageをリクエストヘッダAuthorizationに設定する
$ curl -ki -H 'Host:service1.com:3000' -H "Authorization: LSAT AgEEbHNhdAJCAACRU66KpxK3tevMpkzdRypkgyPn2KfV92NPD99+M1JUyn+hVF59TItFv8g7O+R4mHCWoLQmi/erLUPmN5tmtQv2AAITc2VydmljZXM9c2VydmljZTE6MAACFnNlcnZpY2UxX2NhcGFiaWxpdGllcz0AAhZ2YWxpZF91bnRpbD0yMDIzLTAxLTAxAAAGIB0hCEA+mbtIaB0N9bz8B00Fpd6aALXCQpktXjeH4vlt:f25b3af74803787c6ff364341829ecacf0c7e55a35738c403f08ad19d2e7576a" https://localhost:8081
HTTP/2 200
access-control-allow-headers: Authorization, Grpc-Metadata-macaroon, WWW-Authenticate
access-control-allow-methods: GET, POST, OPTIONS
access-control-allow-origin: *
access-control-expose-headers: WWW-Authenticate
content-type: text/html
date: Thu, 22 Dec 2022 14:54:39 GMT
last-modified: Sun, 18 Dec 2022 22:08:56 GMT
server: SimpleHTTP/0.6 Python/3.10.8
content-length: 3560
<html>
<head>
<title>LSAT proxy demo page</title>
<style>
.row:after {
content: "";
display: table;
clear: both;
}
......
コンテンツが見られるようになりました。
ハマりポイント
1. apertureからのレスポンスが一向に返ってこない
以下のことができていないと、aperture内の処理が終わらずレスポンスが返ってこないことがあります。注意しましょう。
Apertureを起動する前に、必要なlndやetcdを起動しているか
apertureの起動時に設定したノードとも接続するので起動の順番は大事。btcd->lnd(2つ)->etcd->apertureの順に起動させれば問題ないはず。
リクエストを送る際は、ヘッダーに正しいホスト名を記述しているか
ヘッダー情報を記述しないと、404 Page not found が返ってきたりします。
2. walletに資金補充したはずが、FAILURE_REASON_INSUFFICIENT_BALANCEが出る
$ lncli-bob sendpayment --pay_req=lnsb100n1p36ghdrpp5j9f6az48z2mmt67v5exd63e2vjpj8e7c5l2lwc60pl0huv6j2n9qdq8f3f5z4qcqzpgxqyz5vqsp5g7ueyychjnwdew48cr8ufcr2996cju0gccy0yqghc3tyh8pkuhlq9qyyssq3m2qx8cmd6rkk6ef5mv2n58ukun54qg7vuvlkggak2g04v3yvtjrxrlk3yllxwzzvd4xh56ednnqztfs0ylpnzkpjywg9cl6wffvhzcp8g8c8u
Payment hash: 9153ae8aa712b7b5ebcca64cdd472a648323e7d8a7d5f7634f0fdf7e335254ca
Description: LSAT
Amount (in satoshis): 10
Fee limit (in satoshis): 10
Destination: 03195ae574334bd5c673372cd7a7e416c901a3bc3709c20403df0a3a5a5d3d32f5
Confirm payment (yes/no): yes
+------------+--------------+--------------+--------------+-----+----------+----------+-------+
| HTLC_STATE | ATTEMPT_TIME | RESOLVE_TIME | RECEIVER_AMT | FEE | TIMELOCK | CHAN_OUT | ROUTE |
+------------+--------------+--------------+--------------+-----+----------+----------+-------+
+------------+--------------+--------------+--------------+-----+----------+----------+-------+
Amount + fee: 0 + 0 sat
Payment hash: 9153ae8aa712b7b5ebcca64cdd472a648323e7d8a7d5f7634f0fdf7e335254ca
Payment status: FAILED, reason: FAILURE_REASON_INSUFFICIENT_BALANCE
[lncli] FAILED
こうなった際に試してみることが、
- もう一度balance足りてるか確認する
- btcdのブロックを数ブロック分進める
3. 支払いが終わり、preimageも手に入れたが期待したレスポンスが返ってこない
原因として考えられるのは、
ヘッダーのAuthenticationに正しく情報が記述されていない
Header内のAuthenticationに支払い情報を記述したい場合は、
Authentication: LSAT <402レスポンスが返ってきた時についてきたmacaroon>:<支払い成功時レスポンスされてきたpreimage>
のように、
- LSAT という文字列
- 正しいmacaroon
-
正しいpreimage
が正しい形で書かれている必要があります。ご注意を。
Apertureの課題
- 準備に必要な工程が多く面倒(btcd,lnd,etcd,チャネル開設etc)
- エコシステムがまだまだ未熟
- そもそもBTCは手放したくない
おわりに
LSATという認証と支払いの管理を行なってくれるプロトコルをすでに実装に組み込める形にしてある、Apertureは、今後必ずマイクロペイメントとwebコンテンツが絡んだアプリケーションでは使われたり、応用した技術が出てくると思います。
今回は、かなりオーソドックスな設定でHelloworldしただけですが、もっと工夫していけば、
- 1ビュー単位で料金を徴収することができるブログ
- プラン変更の際に手動作業が不要でリクエストごとに請求額を変えられるAPI
- 3分の動画のうち、指定した1分の部分のみ購入して視聴できるような動画
等を提供できるサービスが作れるのではと思いました。
lightning networkのエコシステムには既存のウェブサービスやペイメント体験を変えるような面白いプロトコルがまだまだあるので、今後も引き続き追っていきたいと思います。
引き続きBitcoin周りの記事を見たい方はいいねとTwitterのフォロー、記事の拡散をお願いします!
no plan株式会社について
- no plan株式会社は、ブロックチェーン技術、Webサイト開発、ネイティブアプリ開発、チーム育成、などWebサービス全般の開発から運用や教育、支援などを行っています。よくわからない、ふわふわしたノープラン状態でも大丈夫!ご一緒にプランを立てていきましょう!
- no plan株式会社について
- no plan株式会社 | ブロックチェーン実績
- no plan株式会社 | ブログ一覧
Discussion