该文章介绍了如何使用Java编写gRPC客户端与Lightning Network Daemon (LND) 交互。文章提供了详细的设置、安装步骤,包括项目结构、pom.xml配置,以及Main.java的示例代码。通过这些步骤,开发者可以建立与LND节点的连接,并进行基本的信息查询操作。
本节列举了用 Java 编写与 lnd 通信的客户端所需执行的操作。我们将使用 Maven 作为我们的构建工具。
.
├── pom.xml
└── src
├── main
├── java
│ └── Main.java
├── proto
└── lnrpc
└── lightning.proto
注意 proto 文件夹,所有 proto 文件都保存在这里。
<properties>
<grpc.version>1.36.0</grpc.version>
</properties>
以下依赖是必需的。
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>2.0.28.Final</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
在构建部分,我们需要配置以下内容:
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
使用以下代码设置通道和客户端以连接到你的 lnd
节点。
请注意,当使用 IP 地址连接到节点时(例如,使用 192.168.1.21 而不是 localhost),你需要将 --tlsextraip=192.168.1.21
添加到你的 lnd
配置中,并重新生成证书(删除 tls.cert 和 tls.key 并重启 lnd)。
import io.grpc.Attributes;
import io.grpc.CallCredentials;
import io.grpc.ManagedChannel;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.SslContext;
import lnrpc.LightningGrpc;
import lnrpc.LightningGrpc.LightningBlockingStub;
import lnrpc.Rpc.GetInfoRequest;
import lnrpc.Rpc.GetInfoResponse;
import org.apache.commons.codec.binary.Hex;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.Executor;
public class Main {
static class MacaroonCallCredential extends CallCredentials {
private final String macaroon;
MacaroonCallCredential(String macaroon) {
this.macaroon = macaroon;
}
@Override
public void applyRequestMetadata(RequestInfo requestInfo, Executor executor, MetadataApplier metadataApplier) {
executor.execute(() -> {
try {
Metadata headers = new Metadata();
Metadata.Key<String> macaroonKey = Metadata.Key.of("macaroon", Metadata.ASCII_STRING_MARSHALLER);
headers.put(macaroonKey, macaroon);
metadataApplier.apply(headers);
} catch (Throwable e) {
metadataApplier.fail(Status.UNAUTHENTICATED.withCause(e));
}
});
}
@Override
public void thisUsesUnstableApi() {
}
}
private static final String CERT_PATH = "/Users/<username>/Library/Application Support/Lnd/tls.cert";
private static final String MACAROON_PATH = "/Users/<username>/Library/Application Support/Lnd/data/chain/bitcoin/simnet/admin.macaroon";
private static final String HOST = "localhost";
private static final int PORT = 10009;
public static void main(String...args) throws IOException {
SslContext sslContext = GrpcSslContexts.forClient().trustManager(new File(CERT_PATH)).build();
NettyChannelBuilder channelBuilder = NettyChannelBuilder.forAddress(HOST, PORT);
ManagedChannel channel = channelBuilder.sslContext(sslContext).build();
String macaroon =
Hex.encodeHexString(
Files.readAllBytes(Paths.get(MACAROON_PATH))
);
LightningBlockingStub stub = LightningGrpc
.newBlockingStub(channel)
.withCallCredentials(new MacaroonCallCredential(macaroon));
GetInfoResponse response = stub.getInfo(GetInfoRequest.getDefaultInstance());
System.out.println(response.getIdentityPubkey());
}
}
在 pom.xml 文件所在的目录中执行以下命令。
$ mvn compile exec:java -Dexec.mainClass="Main" -Dexec.cleanupDaemonThreads=false
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Detecting the operating system and CPU architecture
[INFO] ------------------------------------------------------------------------
[INFO] os.detected.name: osx
[INFO] os.detected.arch: x86_64
[INFO] os.detected.version: 10.15
[INFO] os.detected.version.major: 10
[INFO] os.detected.version.minor: 15
[INFO] os.detected.classifier: osx-x86_64
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building lightning-client 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- protobuf-maven-plugin:0.6.1:compile (default) @ lightning-client ---
[INFO] Compiling 3 proto file(s) to /Users/<username>/Documents/Projects/lightningclient/target/generated-sources/protobuf/java
[INFO]
[INFO] --- protobuf-maven-plugin:0.6.1:compile-custom (default) @ lightning-client ---
[INFO] Compiling 3 proto file(s) to /Users/<username>/Documents/Projects/lightningclient/target/generated-sources/protobuf/grpc-java
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ lightning-client ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO] Copying 3 resources
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ lightning-client ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 12 source files to /Users/<username>/Documents/Projects/lightningclient/target/classes
[INFO]
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ lightning-client ---
032562215c38dede6f1f2f262ff4c8db58a38ecf889e8e907eee8e4c320e0b5e81
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.408 s
[INFO] Finished at: 2018-01-13T19:05:49+01:00
[INFO] Final Memory: 30M/589M
[INFO] ------------------------------------------------------------------------
lightning.proto 文件中有 2 个可用选项:
你想要为生成的 Java 类使用的包。 如果在 .proto 文件中没有给出明确的 java_package 选项,那么默认情况下将使用 proto 包(使用 .proto 文件中的 “package” 关键字指定)。 但是,proto 包通常不能很好地用作 Java 包,因为 proto 包不应以反向域名开头。 如果不生成 Java 代码,则此选项无效。
- 原文链接: github.com/lightningnetw...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!