继续阅读无标题" /> 继续阅读无标题">

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

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

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

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

所以虽然咱还有像是有没有方法让应用使用不同的 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 地址了。(虽然现在好像并没有新节点的样子……)