在本地创建节点

节点结构

每个 Corda 节点会包含以下的结构:

.
├── certificates            // 节点的证书
├── corda-webserver.jar     // 内置的节点 webserver
├── corda.jar               // Corda 核心类库
├── logs                    // 节点 logs
├── node.conf               // 节点的配置文件
├── persistence.mv.db       // 节点的数据库
└── plugins                 // 节点上安装的 CorDapps jar 文件

可以通过编辑 node.conf 文件来配置节点。你可以通过将 CorDapp JARs 放到 plugin 文件夹的方式来在节点上安装一个 CorDapp。

节点的命名

一个节点的名字必须是一个有效的 X.500 可区分的名字。为了同其他的实现方法兼容(特别是 TLS 实现),我们约束了允许使用的 X.500 的属性类型为最小被支持的 X.509 证书集合的一个子集(在 RFC 3280 中指定的),外加下边的本地属性:

  • Organization (O)
  • State (ST)
  • Locality (L)
  • Country (C)
  • Organizational-unit (OU)
  • Common name (CN) (仅仅作为 service 的标识符被使用)

命名还必须要遵守下边的约束:

  • Organisation、locality 和 country 属性必须要有
    • State、organisational-unit 和 common name 属性不是必须要有的
  • 名字的字段有以下最大长度的限制:
    • Common name: 64
    • Organisation: 128
    • Organisation unit: 64
    • Locality: 64
    • State: 64
  • 国家(Country) 属性必须是一个有效的大写的 ISO 3166-1 的两个英文字母
  • 名字中的 Organization 字段要满足以下的约束条件:
    • 首字母大写
    • 至少包含两个字符
    • 首部和尾部不能含有空格
    • 不包含双空格
    • 不能包含 “node” 或者 “server” 关键字
    • 必能包含以下字符:, , = , $ , , , \
    • 是 NFKC 常规化形式
    • 仅仅支持拉丁文、常见和继承的 unicode 脚本
      • 这是为了当我们没法在电话中读出名字,或者名字看起来很迷惑的时候,避免从右到左的问题以及 debugging 问题

Cordform 任务

Corda 提供了一个叫做 Cordform 的 gradle plugin,它允许你自动地生成和配置一套节点的信息。下边是一个叫做 deployNodesCordform 任务,它在 Kotlin CorDapp Template 项目中创建了 3 个节点:

task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
    directory "./build/nodes"
    networkMap "O=Controller,L=London,C=GB"
    node {
        name "O=Controller,L=London,C=GB"
        // The notary will offer a validating notary service.
        notary = [validating : true]
        p2pPort  10002
        rpcPort  10003
        // No webport property, so no webserver will be created.
        h2Port   10004
        // Includes the corda-finance CorDapp on our node.
        cordapps = ["net.corda:corda-finance:$corda_release_version"]
    }
    node {
        name "O=PartyA,L=London,C=GB"
        advertisedServices = []
        p2pPort  10005
        rpcPort  10006
        webPort  10007
        h2Port   10008
        cordapps = ["net.corda:corda-finance:$corda_release_version"]
        // Grants user1 all RPC permissions.
        rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
    }
    node {
        name "O=PartyB,L=New York,C=US"
        advertisedServices = []
        p2pPort  10009
        rpcPort  10010
        webPort  10011
        h2Port   10012
        cordapps = ["net.corda:corda-finance:$corda_release_version"]
        // Grants user1 the ability to start the MyFlow flow.
        rpcUsers = [[ user: "user1", "password": "test", "permissions": ["StartFlow.net.corda.flows.MyFlow"]]]
    }
}

运行这个任务会在 build/nodes 文件夹下创建 3 个节点:

  • 一个 Controller 节点:
    • 作为 network map service
    • 提供一个 validating notary 服务
    • 不会有 webserver(因为 webPort 没有定义)
    • 会运行 corda-finance CorDapp
  • PartyAPartyB 节点:
    • Controller 那里被指定,作为 network map service
    • 不提供任何服务
    • 会有一个 webserver(因为 webPort 被定义了)
    • 运行 corda-finance CorDapp
    • 有一个 RPC 用户 – user1,可以通过 RPC 登陆到节点

另外,所有的三个节点都会包含任何在项目的 source 文件夹中定义的任何 CorDapp,即使这些 CorDapps 没有被列在每个节点的 cordapps entry。这就意味着在 template CorDapp 中运行这个 deployNodes 任务会自动 build 并将这个 template CorDapp 添加到每个节点中。

你可以扩展这个 deployNodes 来生成更多的节点。唯一的要求是你必须要通过把节点的名字放到 networkMap 字段中来指定唯一的一个节点来运行 network map service。

注意:当添加节点的时候,要确保没有端口冲突!

运行 deployNodes

为了创建在 deployNodes 任务中定义的节点,在项目的根目录下,在终端窗口中运行下边的命令:

  • Linux/macOS:./gradlew deployNodes
  • Windows:gradlew.bat deployNodes

这会在 build/nodes 文件夹下创建节点。这里会为 depployNodes 任务中定义的每一个节点创建一个文件夹,和一个 runnodes 的 shell 脚本(在 Windows 中是 batch 文件)来同时运行所有的节点达到测试和开发的目的。如果你对你的 CorDapp source 或者 deployNodes 任务做了任何修改,你需要重新运行这个任务来使修改生效。

接下来你就可以按照在本地运行节点中的指导来运行你的节点了。