前人栽树后人乘凉 – 开放 LikeCoin Chain 节点的 API

开放 LikeCoin Chain 节点的 RPC 和 REST API 的方法。

其实还有 gRPC 的,但那个咱好像搞不定…… 😂

其实呢,汝要是问咱什么 RPC REST 都是啥的话呢,其实咱也不特别清楚,不如汝自己去网上搜索看看。不过有那么两点咱还是能说清楚的:

  • 汝在 LikeCoin Chain 上的各种活动,都要靠和这些 API 交互来完成,虽然汝自己并不一定需要直接面对它们而是交给各种软件和网页代劳。
  • 如果开放 API 的节点足够多的话,既可以提高性能(不用所有的请求挤在一个节点上)也可以提升网络整体的健壮性。

所以虽然咱还有像是有没有方法让应用使用不同的 API 地址一类的考虑,还是先把 API 访问开起来了,万一以后能用的上呢。(笑)

以及基于 Cosmos SDK 的 LikeCoin Chain 其实还有 gRPC 和 Rosetta API,但是前面那个咱没找到有什么不直接暴露 API 端口的方法,后面那个咱完全不知道是啥,所以这次就先打开了比较常用的 RPC 和 REST。如果哪位找到方法的话能不能分享给咱一下?

启用 API 终结点

其实启用还是挺容易的,只要修改 ~/.liked/config/app.toml 和 ~/.liked/config/config.toml 就行。

~/.liked/config/app.toml 的话,要修改的是 [api] 这个部分。

###############################################################################
###                           API Configuration                             ###
###############################################################################

[api]

# 要启用 REST API 的话,肯定要把这个改成 true 啦。
# Enable defines if the API server should be enabled.
enable = true

# 要不要启用通过 swagger 展示所有可用的路径?
# Swagger defines if swagger documentation should automatically be registered.
swagger = true

# API 服务器的监听地址,小于 1024 的端口通常需要 root 权限才能使用。
# 不过因为 Mozilla Infosec 教导咱们的 API 终结点要完全禁用 HTTP 
# 访问这回事,后面咱会用 Nginx 反向代理这个地址,所以之监听在本地也是 OK 的。
# Address defines the API server to listen on.
address = "tcp://127.0.0.1:1317"

~/.liked/config/config.toml 要修改的是 [rpc] 的部分:

#######################################################
###       RPC Server Configuration Options          ###
#######################################################
[rpc]

# RPC 服务器的监听地址,写法和上面的 address 是一样的。
# TCP or UNIX socket address for the RPC server to listen on
laddr = "tcp://127.0.0.1:26657"

保存然后重启 liked 服务,如果一切都 OK 的话,汝应该可以在汝的服务器上访问到 API:

# 一个 RPC 请求的例子 , RPC 服务器的根路径(/)有所有路径的列表。
$ curl http://localhost:26657/status
{
  "jsonrpc": "2.0",
  "id": -1,
  "result": {
    "node_info": {
      "protocol_version": {
        "p2p": "8",
        "block": "11",
        "app": "0"
      },
      "id": "a1b98d239ed4b0d3cfc55f28e4bbf988a8bacf35",
      "listen_addr": "tcp://0.0.0.0:26656",
      "network": "likecoin-mainnet-2",
      "version": "0.34.19",
      "channels": "40202122233038606100",
      "moniker": "Yoitsu",
      "other": {
        "tx_index": "on",
        "rpc_address": "tcp://0.0.0.0:26657"
      }
    },
    "sync_info": {
      "latest_block_hash": "29AFD11FE27392594EF9D68BCA0D444802564E02AAEC9848D4D3FA0D53AB6560",
      "latest_app_hash": "D36D8F5D1E5B77AB78AE5B1D4E9434C8388FCE678B4567BD2C94C419A1E735C1",
      "latest_block_height": "7899104",
      "latest_block_time": "2023-02-20T08:11:15.359941991Z",
      "earliest_block_hash": "77A14BB37CCB6E426D521229A564E4AB37672915F97C47976EA56E165D35B618",
      "earliest_app_hash": "41D0A50BB85AAAE7789C8DFBD0C3ED4B99A84F0A8A0E6F2FAEC9F4824AA47B7C",
      "earliest_block_height": "4709200",
      "earliest_block_time": "2022-07-14T13:07:40.67338786Z",
      "catching_up": false
    },
    "validator_info": {
      "address": "353558D7C7D69DF83A6C9D37BB8204B38561217C",
      "pub_key": {
        "type": "tendermint/PubKeyEd25519",
        "value": "cEwyDK/M1mJ+fJHXASeA0kaXRlVXYE1Ma4Ldne3Wh68="
      },
      "voting_power": "109783021"
    }
  }
# 一个 REST 请求的例子。
# REST API 的响应没有格式化,如果想看的舒服一些的话,可以用 jq 一类的命令先格式化一下。
$ curl "http://localhost:1317/node_info" | jq
{
  "node_info": {
    "protocol_version": {
      "p2p": "8",
      "block": "11",
      "app": "0"
    },
    "id": "a1b98d239ed4b0d3cfc55f28e4bbf988a8bacf35",
    "listen_addr": "tcp://0.0.0.0:26656",
    "network": "likecoin-mainnet-2",
    "version": "0.34.19",
    "channels": "40202122233038606100",
    "moniker": "Yoitsu",
    "other": {
      "tx_index": "on",
      "rpc_address": "tcp://0.0.0.0:26657"
    }
  },
  "application_version": {
    "name": "likecoin-chain",
    "server_name": "liked",
    "version": "v3.0.1",
    "commit": "36fc4c93961fb1a667a7e2a7cd206f38acbfb88f",
    "build_tags": "netgo,ledger",
    "go": "go version go1.18.3 linux/amd64",
    "build_deps": [
      "filippo.io/edwards25519@v1.0.0-beta.2",
      "github.com/99designs/keyring@v1.1.6 => github.com/cosmos/keyring@v1.1.7-0.20210622111912-ef00f8ac3d76",
      "github.com/ChainSafe/go-schnorrkel@v0.0.0-20200405005733-88cbf1b4c40d",
      "github.com/Workiva/go-datastructures@v1.0.53",
      "github.com/armon/go-metrics@v0.3.10",
      "github.com/beorn7/perks@v1.0.1",
      "github.com/bgentry/speakeasy@v0.1.0",
      "github.com/btcsuite/btcd@v0.22.0-beta",
      "github.com/cespare/xxhash/v2@v2.1.2",
      "github.com/coinbase/rosetta-sdk-go@v0.7.0",
      "github.com/confio/ics23/go@v0.7.0 => ./ics23/@(devel)",
      "github.com/cosmos/btcutil@v1.0.4",
      "github.com/cosmos/cosmos-sdk@v0.45.6 => github.com/likecoin/cosmos-sdk@v0.45.6-dual-prefix",
      "github.com/cosmos/go-bip39@v1.0.0",
      "github.com/cosmos/iavl@v0.17.3",
      "github.com/cosmos/ibc-go/v2@v2.3.0",
      "github.com/cosmos/ledger-cosmos-go@v0.11.1",
      "github.com/cosmos/ledger-go@v0.9.2",
      "github.com/davecgh/go-spew@v1.1.1",
      "github.com/desertbit/timer@v0.0.0-20180107155436-c41aec40b27f",
      "github.com/dvsekhvalnov/jose2go@v0.0.0-20200901110807-248326c1351b",
      "github.com/felixge/httpsnoop@v1.0.1",
      "github.com/fsnotify/fsnotify@v1.5.1",
      "github.com/go-kit/kit@v0.12.0",
      "github.com/go-kit/log@v0.2.0",
      "github.com/go-logfmt/logfmt@v0.5.1",
      "github.com/godbus/dbus@v0.0.0-20190726142602-4481cbc300e2",
      "github.com/gogo/gateway@v1.1.0",
      "github.com/gogo/protobuf@v1.3.3 => github.com/regen-network/protobuf@v1.3.3-alpha.regen.1",
      "github.com/golang/protobuf@v1.5.2",
      "github.com/golang/snappy@v0.0.3",
      "github.com/google/btree@v1.0.0",
      "github.com/google/orderedcode@v0.0.1",
      "github.com/gorilla/handlers@v1.5.1",
      "github.com/gorilla/mux@v1.8.0",
      "github.com/gorilla/websocket@v1.5.0",
      "github.com/grpc-ecosystem/go-grpc-middleware@v1.3.0",
      "github.com/grpc-ecosystem/grpc-gateway@v1.16.0",
      "github.com/gsterjov/go-libsecret@v0.0.0-20161001094733-a6f4afe4910c",
      "github.com/gtank/merlin@v0.1.1",
      "github.com/gtank/ristretto255@v0.1.2",
      "github.com/hashicorp/go-immutable-radix@v1.3.1",
      "github.com/hashicorp/golang-lru@v0.5.4",
      "github.com/hashicorp/hcl@v1.0.0",
      "github.com/hdevalence/ed25519consensus@v0.0.0-20210204194344-59a8610d2b87",
      "github.com/improbable-eng/grpc-web@v0.14.1",
      "github.com/ipfs/go-cid@v0.0.7",
      "github.com/klauspost/compress@v1.13.6",
      "github.com/klauspost/cpuid/v2@v2.0.4",
      "github.com/lib/pq@v1.10.4",
      "github.com/libp2p/go-buffer-pool@v0.0.2",
      "github.com/magiconair/properties@v1.8.5",
      "github.com/mattn/go-isatty@v0.0.14",
      "github.com/matttproud/golang_protobuf_extensions@v1.0.1",
      "github.com/mimoo/StrobeGo@v0.0.0-20181016162300-f8f6d4d2b643",
      "github.com/minio/blake2b-simd@v0.0.0-20160723061019-3f5f724cb5b1",
      "github.com/minio/highwayhash@v1.0.2",
      "github.com/minio/sha256-simd@v1.0.0",
      "github.com/mitchellh/mapstructure@v1.4.3",
      "github.com/mr-tron/base58@v1.2.0",
      "github.com/mtibben/percent@v0.2.1",
      "github.com/multiformats/go-base32@v0.0.3",
      "github.com/multiformats/go-base36@v0.1.0",
      "github.com/multiformats/go-multibase@v0.0.3",
      "github.com/multiformats/go-multihash@v0.0.15",
      "github.com/multiformats/go-varint@v0.0.6",
      "github.com/pelletier/go-toml@v1.9.4",
      "github.com/pkg/errors@v0.9.1",
      "github.com/pmezard/go-difflib@v1.0.0",
      "github.com/prometheus/client_golang@v1.12.1",
      "github.com/prometheus/client_model@v0.2.0",
      "github.com/prometheus/common@v0.32.1",
      "github.com/prometheus/procfs@v0.7.3",
      "github.com/rakyll/statik@v0.1.7",
      "github.com/rcrowley/go-metrics@v0.0.0-20200313005456-10cdbea86bc0",
      "github.com/regen-network/cosmos-proto@v0.3.1",
      "github.com/rs/cors@v1.8.2",
      "github.com/rs/zerolog@v1.23.0",
      "github.com/spf13/afero@v1.6.0",
      "github.com/spf13/cast@v1.4.1",
      "github.com/spf13/cobra@v1.4.0",
      "github.com/spf13/jwalterweatherman@v1.1.0",
      "github.com/spf13/pflag@v1.0.5",
      "github.com/spf13/viper@v1.10.1",
      "github.com/stretchr/testify@v1.8.0",
      "github.com/subosito/gotenv@v1.2.0",
      "github.com/syndtr/goleveldb@v1.0.1-0.20200815110645-5c35d600f0ca",
      "github.com/tendermint/btcd@v0.1.1",
      "github.com/tendermint/crypto@v0.0.0-20191022145703-50d29ede1e15",
      "github.com/tendermint/go-amino@v0.16.0",
      "github.com/tendermint/tendermint@v0.34.19",
      "github.com/tendermint/tm-db@v0.6.6",
      "github.com/zondax/hid@v0.9.0",
      "golang.org/x/crypto@v0.0.0-20210915214749-c084706c2272",
      "golang.org/x/net@v0.0.0-20211208012354-db4efeb81f4b",
      "golang.org/x/sys@v0.0.0-20220114195835-da31bd327af9",
      "golang.org/x/term@v0.0.0-20201126162022-7de9c90e9dd1",
      "golang.org/x/text@v0.3.7",
      "google.golang.org/genproto@v0.0.0-20211223182754-3ac035c7e7cb",
      "google.golang.org/grpc@v1.45.0 => google.golang.org/grpc@v1.33.2",
      "google.golang.org/protobuf@v1.27.1",
      "gopkg.in/ini.v1@v1.66.2",
      "gopkg.in/yaml.v2@v2.4.0",
      "gopkg.in/yaml.v3@v3.0.1",
      "nhooyr.io/websocket@v1.8.6"
    ],
    "cosmos_sdk_version": "v0.45.6"
  }
}

~/.liked/config/config.toml 里似乎提供了指定证书和私钥的选项,但是咱还是更习惯用 Nginx 来反向代理了。以及汝还需要一个域名来申请证书,这里咱用 certbot 来申请 Let’s Encrypt 证书,方法在这里 : https://certbot.eff.org/instructions

Nginx 的配置文件看起来像这样。(可以参考 Mozilla SSL Config Generator?)

# generated 2023-02-20, Mozilla Guideline v5.6, nginx 1.17.7, OpenSSL 1.1.1k, intermediate configuration, no HSTS
# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1k&hsts=false&guideline=5.6
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
    ssl_dhparam /path/to/dhparam;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    # replace with the IP address of your resolver
    resolver 127.0.0.1;

    location / {
        # 这里指向的是 REST API 的监听位置,如果汝要反向代理 RPC API 的话,
        # 修改这里就好啦。
	proxy_pass          http://localhost:1317/;
        proxy_redirect      off;
	proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
    }
}

如果 Nginx 和 DNS 的配置没问题的话,汝现在应该可以在汝设置的位置访问到汝开启的 API 了。例如咱的 https://likecoin-rest.yoitsu.xyz/https://likecoin-rpc.yoitsu.xyz/

提供 State Sync 快照

就是 https://docs.like.co/validator/likecoin-chain-node/setup-a-node#state-sync 这一步用到的啦。要让自己的节点也能提供 State Sync 的快照的话,要修改的是 ~/.liked/config/app.toml 里 [state-sync] 的部分。

###############################################################################
###                        State Sync Configuration                         ###
###############################################################################

# State sync snapshots allow other nodes to rapidly join the network without replaying historical
# blocks, instead downloading and applying a snapshot of the application state at a given height.
[state-sync]

# 间隔多少区块保存快照?
# 要让自己的节点提供快照的话,这个应该大于 0 而且是 pruning-keep-every 的倍数。
# 如果 pruning = "default" 的话,因为默认策略是保留每 500 个区块的状态,
# 所以是 500 的倍数。以及显然的 pruning = "everything" 的话是不行的,
# 记得规划一下硬盘空间。
# snapshot-interval specifies the block interval at which local state sync snapshots are
# taken (0 to disable). Must be a multiple of pruning-keep-every.
snapshot-interval = 1000

# 要在本地保留多少快照?
# 设置成 0 的话,会保留所有生成的快照,当然占用的硬盘空间也会更多。
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
snapshot-keep-recent = 2

接下来其他人要用到 State Sync 的时候,就能填写汝的 RPC 地址了。(虽然现在好像并没有新节点的样子……)

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据