本节列举了用 Java 编写与 lnd 通信的客户端所需执行的操作。我们将使用 Maven 作为我们的构建工具。
前提条件
- Maven
- 运行中的 lnd
- 运行中的 btcd
设置和安装
项目结构
.
├── pom.xml
└── src
├── main
├── java
│ └── Main.java
├── proto
└── lnrpc
└── lightning.proto
注意 proto 文件夹,所有 proto 文件都保存在这里。
pom.xml
<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>
Main.java
使用以下代码设置通道和客户端以连接到你的 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/
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] ------------------------------------------------------------------------
Java proto 选项
lightning.proto 文件中有 2 个可用选项:
- option java_multiple_files = true;
- option java_package = "network.lightning.rpc";
你想要为生成的 Java 类使用的包。 如果在 .proto 文件中没有给出明确的 java_package 选项,那么默认情况下将使用 proto 包(使用 .proto 文件中的 “package” 关键字指定)。 但是,proto 包通常不能很好地用作 Java 包,因为 proto 包不应以反向域名开头。 如果不生成 Java 代码,则此选项无效。