Loading proto/dlt_gateway.proto +2 −2 Original line number Diff line number Diff line Loading @@ -21,8 +21,8 @@ service DltGatewayService { rpc RecordToDlt (DltRecord ) returns ( DltRecordStatus ) {} rpc GetFromDlt (DltRecordId ) returns ( DltRecord ) {} rpc SubscribeToDlt(DltRecordSubscription ) returns (stream DltRecordEvent ) {} rpc GetDltStatus (context.TeraFlowController) returns ( DltPeerStatus ) {} // NEC is checkig if it is possible rpc GetDltPeers (context.Empty ) returns ( DltPeerStatusList) {} // NEC is checkig if it is possible rpc GetDltStatus (context.TeraFlowController) returns ( DltPeerStatus ) {} // NEC is checking if it is possible rpc GetDltPeers (context.Empty ) returns ( DltPeerStatusList) {} // NEC is checking if it is possible } enum DltRecordTypeEnum { Loading src/dlt/gateway/README.md +11 −20 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ duplication of the object or source code - either totally or in part - is strictly prohibited. Copyright (c) 2021 NEC Laboratories Europe GmbH Copyright (c) 2022 NEC Laboratories Europe GmbH All Rights Reserved. Authors: Konstantin Munichev <konstantin.munichev@neclab.eu> Loading Loading @@ -42,7 +42,7 @@ ## General information The DLT module is used to provide access to the underlying Fabric deployment. It allows clients to add, retrieve, modify and delete blockchain-backed data, essentially working as a key-value database. External clients should use REST API to communicate with this service, its detailed database. External clients should use gRPC API to communicate with this service, its detailed description available below. ## Code structure Loading @@ -59,26 +59,17 @@ CRUD interface. Other files contain auxiliary code for `FabricConnector` which allows it to register/enroll users and to obtain smart contract instances. ### HTTP package Contains server side HTTP handler. It accepts requests from the outside and performs the requested operation. For the detailed description see API description section. ### Grpc package Contains server side gRPC handler. It accepts requests from the outside and performs the requested operation. For the more detailed description see Proto package description right below. ### Proto package The proto package contains `Config.proto` file which contains messages for REST API. The most important ones are `DltConfig` (it defines the whole DLT configuration) and `DltRecord` which represents data to store in the blockchain. The proto package contains `dlt.proto` file which defines gRPC service `DltService` API and messages it uses. There are 3 main functions: `RecordToDlt` which allows to create/modify/delete data, `GetFromDlt` which returns already written data and `SubscribeToDlt` which allows clients subscribe for future create/modify/delete events with provided filters. Other proto files don't play any significant role and could be safely ignored by end users. ### Client example This code is not necessary to the service, but it could be used to test the service. It contains a sample REST client which connects the service and perform all the CRUD operations. ## REST API description | Method | URL | Input | Response code | Output | | --- | ----------- | --- | --- | --- | | POST | /dlt/configure | Configuration object | 201 or 400 | Status value | | GET | /dlt/configure | - | 200 or 404 | Configuration object | | POST | /dlt/record | Record object | 200, 201, 400 or 404 | Status value | | GET | /dlt/record | Record id | 200 or 404 | Record object | Record and configuration object are defined in `proto` package. a sample gRPC client which connects the service and perform all the CRUD operations. src/dlt/gateway/build.gradle.kts +45 −14 Original line number Diff line number Diff line Loading @@ -39,16 +39,19 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import com.google.protobuf.gradle.generateProtoTasks import com.google.protobuf.gradle.id import com.google.protobuf.gradle.plugins import com.google.protobuf.gradle.protobuf import com.google.protobuf.gradle.protoc ext["protobufVersion"] = "3.19.1" ext["grpcVersion"] = "1.47.0" ext["grpcKotlinVersion"] = "1.3.0" // CURRENT_GRPC_KOTLIN_VERSION ext["protobufVersion"] = "3.20.1" ext["ktorVersion"] = "1.6.5" plugins { kotlin("jvm") version "1.5.31" kotlin("jvm") version "1.6.21" kotlin("plugin.serialization") version "1.4.21" id("com.google.protobuf") version "0.8.17" id("com.google.protobuf") version "0.8.18" application } Loading @@ -56,22 +59,24 @@ group = "eu.neclab" version = "1.0-SNAPSHOT" repositories { mavenLocal() google() mavenCentral() } dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test:1.5.31") implementation("org.hyperledger.fabric:fabric-gateway-java:2.2.2") api("com.google.protobuf:protobuf-kotlin:${rootProject.ext["protobufVersion"]}") implementation("io.ktor:ktor-server-core:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-server-netty:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-serialization:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-client-serialization:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-client-core:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-client-cio:${rootProject.ext["ktorVersion"]}") implementation("ch.qos.logback:logback-classic:1.2.5") implementation(kotlin("stdlib-jdk8")) testImplementation("org.jetbrains.kotlin:kotlin-test:1.6.21") implementation("javax.annotation:javax.annotation-api:1.3.2") implementation("io.grpc:grpc-kotlin-stub:1.3.0") implementation("io.grpc:grpc-protobuf:1.47.0") implementation("com.google.protobuf:protobuf-kotlin:3.21.1") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3") implementation("org.hyperledger.fabric:fabric-gateway-java:2.2.5") implementation("ch.qos.logback:logback-classic:1.2.11") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.3.1") runtimeOnly("io.grpc:grpc-netty:${rootProject.ext["grpcVersion"]}") } tasks.test { Loading @@ -93,6 +98,12 @@ application { mainClass.set("MainKt") } task("runServer", JavaExec::class) { main = "grpc.FabricServerKt" classpath = sourceSets["main"].runtimeClasspath } sourceSets { main { proto { Loading @@ -101,12 +112,32 @@ sourceSets { } } sourceSets { val main by getting { } main.java.srcDirs("build/generated/source/proto/main/grpc") main.java.srcDirs("build/generated/source/proto/main/grpckt") main.java.srcDirs("build/generated/source/proto/main/java") main.java.srcDirs("build/generated/source/proto/main/kotlin") } protobuf { protoc { artifact = "com.google.protobuf:protoc:${rootProject.ext["protobufVersion"]}" } plugins { id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}" } id("grpckt") { artifact = "io.grpc:protoc-gen-grpc-kotlin:${rootProject.ext["grpcKotlinVersion"]}:jdk8@jar" } } generateProtoTasks { all().forEach { it.plugins { id("grpc") id("grpckt") } it.builtins { id("kotlin") } Loading src/dlt/gateway/config/ca.org1.example.com-cert.pem +8 −8 Original line number Diff line number Diff line -----BEGIN CERTIFICATE----- MIICJjCCAc2gAwIBAgIUWZ4l32loO9+FM0FYw61y3dUF5a0wCgYIKoZIzj0EAwIw MIICJjCCAc2gAwIBAgIUVSFCRQNScNJyIwJz89vi6tazYJ4wCgYIKoZIzj0EAwIw cDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH EwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzA1MDk0NDAwWhcNMzcwNzAxMDk0NDAw Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzEzMTQ1MjAwWhcNMzcwNzA5MTQ1MjAw WjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV BAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT Y2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNPg yfDxHr4ZmFp3HB19f27vfc1YTKBnznLqIFwVad2Y+eXfni8DnTRNGgwdkG9uIK2L 4Y9mwlKG/mTNx629G4GjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG AQH/AgEBMB0GA1UdDgQWBBSZlT6qe+DAGpEBXyMxzidqCkQ4PjAKBggqhkjOPQQD AgNHADBEAiAIG5jwBGddB9CwocmjAzFv8+e7+0bvNSwjrG229QogTgIgbTNoC33P mbR5ChlkUAW2t41hTOCSMIwLAlvEwpeCnAk= Y2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLg8 zJvOKBR1fS+hrrMc3xEhOalkSG+5vGGpwzgHv5NNMlDZcbQVuEBHPmRowbLWx4nw 2CIUSfkhtQGC5GmUncOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG AQH/AgEBMB0GA1UdDgQWBBRm7lBNvvkP8iy6f0cXwz9BTeSYDzAKBggqhkjOPQQD AgNHADBEAiB1p8QFXHszJsMqiShmyuTA6zGPfHlnan3dgYMCTNR7mwIgFx3SqSYk FizTEfVfOcdjIYGc3pTPTyK5PVbO1k2BW80= -----END CERTIFICATE----- src/dlt/gateway/config/connection-org1.json +8 −8 Original line number Diff line number Diff line Loading @@ -24,9 +24,9 @@ }, "peers": { "peer0.org1.example.com": { "url": "grpcs://s2:7051", "url": "grpcs://teraflow.nlehd.de:7051", "tlsCACerts": { "pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUWZ4l32loO9+FM0FYw61y3dUF5a0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzA1MDk0NDAwWhcNMzcwNzAxMDk0NDAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNPg\nyfDxHr4ZmFp3HB19f27vfc1YTKBnznLqIFwVad2Y+eXfni8DnTRNGgwdkG9uIK2L\n4Y9mwlKG/mTNx629G4GjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBSZlT6qe+DAGpEBXyMxzidqCkQ4PjAKBggqhkjOPQQD\nAgNHADBEAiAIG5jwBGddB9CwocmjAzFv8+e7+0bvNSwjrG229QogTgIgbTNoC33P\nmbR5ChlkUAW2t41hTOCSMIwLAlvEwpeCnAk=\n-----END CERTIFICATE-----\n" "pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUVSFCRQNScNJyIwJz89vi6tazYJ4wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzEzMTQ1MjAwWhcNMzcwNzA5MTQ1MjAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLg8\nzJvOKBR1fS+hrrMc3xEhOalkSG+5vGGpwzgHv5NNMlDZcbQVuEBHPmRowbLWx4nw\n2CIUSfkhtQGC5GmUncOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBRm7lBNvvkP8iy6f0cXwz9BTeSYDzAKBggqhkjOPQQD\nAgNHADBEAiB1p8QFXHszJsMqiShmyuTA6zGPfHlnan3dgYMCTNR7mwIgFx3SqSYk\nFizTEfVfOcdjIYGc3pTPTyK5PVbO1k2BW80=\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "peer0.org1.example.com", Loading @@ -34,9 +34,9 @@ } }, "peer0.org2.example.com": { "url": "grpcs://s2:9051", "url": "grpcs://teraflow.nlehd.de:9051", "tlsCACerts": { "pem": "-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUejv57h6dJkVIM2R1YnlqykkvG7gwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMjA3MDUwOTQ0MDBaFw0zNzA3MDEwOTQ0MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFZqoisCIgZyMM\n8e0YBA+jxH/+Fc4Y4OkEl5uGRXGl9s0OemCdvhlX9K+esX2DVk1st1PMfTEj/six\n9XPpVqzNo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUPEyzGBlZEjguoJB16wAmoH2bAh8wCgYIKoZIzj0EAwIDSAAwRQIh\nAL6DAWgrqRtbYoQ0oYAr/2vze0JtQcXoqiQKlyvYkUBbAiB/uSHBk3NwjzI8t8iW\nzQzr5eNy5JwOO0SWwPEv4Ev9iQ==\n-----END CERTIFICATE-----\n" "pem": "-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUOsbw943VjFitBzBEXAcxLlOLow8wCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMjA3MTMxNDUyMDBaFw0zNzA3MDkxNDUyMDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARKov9QrWe9dklr\nqYJxOOoqoO3EI18LtPizVCKYrG3IMqkaatM6DLc/2SBTSIqIDeTR6N8WZAPVgLKA\nboRt87Heo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUYe4sT8J0Y2iN/9Q14FcpmxK5dYcwCgYIKoZIzj0EAwIDSAAwRQIh\nAJh2+1QXc5/ZlPaN2qnh3TXbzPFeCDXjoMAoBsOYtRcMAiAF+tcoFY0NcLDfTZBm\nNuuiQDIasoTB9Wuu4PBv8T7I5w==\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "peer0.org2.example.com", Loading @@ -46,11 +46,11 @@ }, "certificateAuthorities": { "ca.org1.example.com": { "url": "https://s2:7054", "url": "https://teraflow.nlehd.de:7054", "caName": "ca-org1", "tlsCACerts": { "pem": [ "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUWZ4l32loO9+FM0FYw61y3dUF5a0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzA1MDk0NDAwWhcNMzcwNzAxMDk0NDAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNPg\nyfDxHr4ZmFp3HB19f27vfc1YTKBnznLqIFwVad2Y+eXfni8DnTRNGgwdkG9uIK2L\n4Y9mwlKG/mTNx629G4GjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBSZlT6qe+DAGpEBXyMxzidqCkQ4PjAKBggqhkjOPQQD\nAgNHADBEAiAIG5jwBGddB9CwocmjAzFv8+e7+0bvNSwjrG229QogTgIgbTNoC33P\nmbR5ChlkUAW2t41hTOCSMIwLAlvEwpeCnAk=\n-----END CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUVSFCRQNScNJyIwJz89vi6tazYJ4wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzEzMTQ1MjAwWhcNMzcwNzA5MTQ1MjAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLg8\nzJvOKBR1fS+hrrMc3xEhOalkSG+5vGGpwzgHv5NNMlDZcbQVuEBHPmRowbLWx4nw\n2CIUSfkhtQGC5GmUncOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBRm7lBNvvkP8iy6f0cXwz9BTeSYDzAKBggqhkjOPQQD\nAgNHADBEAiB1p8QFXHszJsMqiShmyuTA6zGPfHlnan3dgYMCTNR7mwIgFx3SqSYk\nFizTEfVfOcdjIYGc3pTPTyK5PVbO1k2BW80=\n-----END CERTIFICATE-----\n" ] }, "httpOptions": { Loading @@ -60,9 +60,9 @@ }, "orderers": { "orderer0.example.com": { "url": "grpcs://s2:7050", "url": "grpcs://teraflow.nlehd.de:7050", "tlsCACerts": { "pem": "-----BEGIN CERTIFICATE-----\nMIICCjCCAbGgAwIBAgIURV0KgZTOagIAIU7wRcSg/mKl5RUwCgYIKoZIzj0EAwIw\nYjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcg\nWW9yazEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUu\nY29tMB4XDTIyMDcwNTA5NDQwMFoXDTM3MDcwMTA5NDQwMFowYjELMAkGA1UEBhMC\nVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UE\nChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEWrOugtJgVLAKZRw9jaC15RUbVuTm0ZmsqNyiQrKQ\nYawLE6fs+QIU7WQ25fxlYtmGB2S8nofGCDuwaoTevW0GoaNFMEMwDgYDVR0PAQH/\nBAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFLKBzGXaQg2Irr57\npjoFYZ9F1NoNMAoGCCqGSM49BAMCA0cAMEQCIB1YdgOEsATw2GeaFmq6nqWg0JDT\np456JB/reFmnPWdJAiBPo5H9sMh+MpP4R5ue7nuwYK7SEJ1DOJqWMlPuNhVgtA==\n-----END CERTIFICATE-----\n" "pem": "-----BEGIN CERTIFICATE-----\nMIICCjCCAbGgAwIBAgIUA6RVRhhZD8pvcNAQJ6HWPUkbNNIwCgYIKoZIzj0EAwIw\nYjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcg\nWW9yazEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUu\nY29tMB4XDTIyMDcxMzE0NTIwMFoXDTM3MDcwOTE0NTIwMFowYjELMAkGA1UEBhMC\nVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UE\nChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEs7mmo5MY0oO9zCYcraUN/MXWxHiQ04xG6tWLaeWX\nqfSmFnfO8UBFq4OF5Li861UWGe+s9QxNXIELchBG8M7qLqNFMEMwDgYDVR0PAQH/\nBAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFBGG7kbCLEXzlQUF\nQfx845Qf2WKCMAoGCCqGSM49BAMCA0cAMEQCIAwABAqRopU+Qt3myyt4YiKQFpyO\nWTZifesVFe3fM/Q3AiA7oZ9XdQ5EuPhqFxSz7ASF45iyL3k078ilusjpc6IZ/g==\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "orderer0.example.com", Loading Loading
proto/dlt_gateway.proto +2 −2 Original line number Diff line number Diff line Loading @@ -21,8 +21,8 @@ service DltGatewayService { rpc RecordToDlt (DltRecord ) returns ( DltRecordStatus ) {} rpc GetFromDlt (DltRecordId ) returns ( DltRecord ) {} rpc SubscribeToDlt(DltRecordSubscription ) returns (stream DltRecordEvent ) {} rpc GetDltStatus (context.TeraFlowController) returns ( DltPeerStatus ) {} // NEC is checkig if it is possible rpc GetDltPeers (context.Empty ) returns ( DltPeerStatusList) {} // NEC is checkig if it is possible rpc GetDltStatus (context.TeraFlowController) returns ( DltPeerStatus ) {} // NEC is checking if it is possible rpc GetDltPeers (context.Empty ) returns ( DltPeerStatusList) {} // NEC is checking if it is possible } enum DltRecordTypeEnum { Loading
src/dlt/gateway/README.md +11 −20 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ duplication of the object or source code - either totally or in part - is strictly prohibited. Copyright (c) 2021 NEC Laboratories Europe GmbH Copyright (c) 2022 NEC Laboratories Europe GmbH All Rights Reserved. Authors: Konstantin Munichev <konstantin.munichev@neclab.eu> Loading Loading @@ -42,7 +42,7 @@ ## General information The DLT module is used to provide access to the underlying Fabric deployment. It allows clients to add, retrieve, modify and delete blockchain-backed data, essentially working as a key-value database. External clients should use REST API to communicate with this service, its detailed database. External clients should use gRPC API to communicate with this service, its detailed description available below. ## Code structure Loading @@ -59,26 +59,17 @@ CRUD interface. Other files contain auxiliary code for `FabricConnector` which allows it to register/enroll users and to obtain smart contract instances. ### HTTP package Contains server side HTTP handler. It accepts requests from the outside and performs the requested operation. For the detailed description see API description section. ### Grpc package Contains server side gRPC handler. It accepts requests from the outside and performs the requested operation. For the more detailed description see Proto package description right below. ### Proto package The proto package contains `Config.proto` file which contains messages for REST API. The most important ones are `DltConfig` (it defines the whole DLT configuration) and `DltRecord` which represents data to store in the blockchain. The proto package contains `dlt.proto` file which defines gRPC service `DltService` API and messages it uses. There are 3 main functions: `RecordToDlt` which allows to create/modify/delete data, `GetFromDlt` which returns already written data and `SubscribeToDlt` which allows clients subscribe for future create/modify/delete events with provided filters. Other proto files don't play any significant role and could be safely ignored by end users. ### Client example This code is not necessary to the service, but it could be used to test the service. It contains a sample REST client which connects the service and perform all the CRUD operations. ## REST API description | Method | URL | Input | Response code | Output | | --- | ----------- | --- | --- | --- | | POST | /dlt/configure | Configuration object | 201 or 400 | Status value | | GET | /dlt/configure | - | 200 or 404 | Configuration object | | POST | /dlt/record | Record object | 200, 201, 400 or 404 | Status value | | GET | /dlt/record | Record id | 200 or 404 | Record object | Record and configuration object are defined in `proto` package. a sample gRPC client which connects the service and perform all the CRUD operations.
src/dlt/gateway/build.gradle.kts +45 −14 Original line number Diff line number Diff line Loading @@ -39,16 +39,19 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import com.google.protobuf.gradle.generateProtoTasks import com.google.protobuf.gradle.id import com.google.protobuf.gradle.plugins import com.google.protobuf.gradle.protobuf import com.google.protobuf.gradle.protoc ext["protobufVersion"] = "3.19.1" ext["grpcVersion"] = "1.47.0" ext["grpcKotlinVersion"] = "1.3.0" // CURRENT_GRPC_KOTLIN_VERSION ext["protobufVersion"] = "3.20.1" ext["ktorVersion"] = "1.6.5" plugins { kotlin("jvm") version "1.5.31" kotlin("jvm") version "1.6.21" kotlin("plugin.serialization") version "1.4.21" id("com.google.protobuf") version "0.8.17" id("com.google.protobuf") version "0.8.18" application } Loading @@ -56,22 +59,24 @@ group = "eu.neclab" version = "1.0-SNAPSHOT" repositories { mavenLocal() google() mavenCentral() } dependencies { testImplementation("org.jetbrains.kotlin:kotlin-test:1.5.31") implementation("org.hyperledger.fabric:fabric-gateway-java:2.2.2") api("com.google.protobuf:protobuf-kotlin:${rootProject.ext["protobufVersion"]}") implementation("io.ktor:ktor-server-core:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-server-netty:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-serialization:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-client-serialization:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-client-core:${rootProject.ext["ktorVersion"]}") implementation("io.ktor:ktor-client-cio:${rootProject.ext["ktorVersion"]}") implementation("ch.qos.logback:logback-classic:1.2.5") implementation(kotlin("stdlib-jdk8")) testImplementation("org.jetbrains.kotlin:kotlin-test:1.6.21") implementation("javax.annotation:javax.annotation-api:1.3.2") implementation("io.grpc:grpc-kotlin-stub:1.3.0") implementation("io.grpc:grpc-protobuf:1.47.0") implementation("com.google.protobuf:protobuf-kotlin:3.21.1") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3") implementation("org.hyperledger.fabric:fabric-gateway-java:2.2.5") implementation("ch.qos.logback:logback-classic:1.2.11") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1") implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.3.1") runtimeOnly("io.grpc:grpc-netty:${rootProject.ext["grpcVersion"]}") } tasks.test { Loading @@ -93,6 +98,12 @@ application { mainClass.set("MainKt") } task("runServer", JavaExec::class) { main = "grpc.FabricServerKt" classpath = sourceSets["main"].runtimeClasspath } sourceSets { main { proto { Loading @@ -101,12 +112,32 @@ sourceSets { } } sourceSets { val main by getting { } main.java.srcDirs("build/generated/source/proto/main/grpc") main.java.srcDirs("build/generated/source/proto/main/grpckt") main.java.srcDirs("build/generated/source/proto/main/java") main.java.srcDirs("build/generated/source/proto/main/kotlin") } protobuf { protoc { artifact = "com.google.protobuf:protoc:${rootProject.ext["protobufVersion"]}" } plugins { id("grpc") { artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}" } id("grpckt") { artifact = "io.grpc:protoc-gen-grpc-kotlin:${rootProject.ext["grpcKotlinVersion"]}:jdk8@jar" } } generateProtoTasks { all().forEach { it.plugins { id("grpc") id("grpckt") } it.builtins { id("kotlin") } Loading
src/dlt/gateway/config/ca.org1.example.com-cert.pem +8 −8 Original line number Diff line number Diff line -----BEGIN CERTIFICATE----- MIICJjCCAc2gAwIBAgIUWZ4l32loO9+FM0FYw61y3dUF5a0wCgYIKoZIzj0EAwIw MIICJjCCAc2gAwIBAgIUVSFCRQNScNJyIwJz89vi6tazYJ4wCgYIKoZIzj0EAwIw cDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH EwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzA1MDk0NDAwWhcNMzcwNzAxMDk0NDAw Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzEzMTQ1MjAwWhcNMzcwNzA5MTQ1MjAw WjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV BAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT Y2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNPg yfDxHr4ZmFp3HB19f27vfc1YTKBnznLqIFwVad2Y+eXfni8DnTRNGgwdkG9uIK2L 4Y9mwlKG/mTNx629G4GjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG AQH/AgEBMB0GA1UdDgQWBBSZlT6qe+DAGpEBXyMxzidqCkQ4PjAKBggqhkjOPQQD AgNHADBEAiAIG5jwBGddB9CwocmjAzFv8+e7+0bvNSwjrG229QogTgIgbTNoC33P mbR5ChlkUAW2t41hTOCSMIwLAlvEwpeCnAk= Y2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLg8 zJvOKBR1fS+hrrMc3xEhOalkSG+5vGGpwzgHv5NNMlDZcbQVuEBHPmRowbLWx4nw 2CIUSfkhtQGC5GmUncOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG AQH/AgEBMB0GA1UdDgQWBBRm7lBNvvkP8iy6f0cXwz9BTeSYDzAKBggqhkjOPQQD AgNHADBEAiB1p8QFXHszJsMqiShmyuTA6zGPfHlnan3dgYMCTNR7mwIgFx3SqSYk FizTEfVfOcdjIYGc3pTPTyK5PVbO1k2BW80= -----END CERTIFICATE-----
src/dlt/gateway/config/connection-org1.json +8 −8 Original line number Diff line number Diff line Loading @@ -24,9 +24,9 @@ }, "peers": { "peer0.org1.example.com": { "url": "grpcs://s2:7051", "url": "grpcs://teraflow.nlehd.de:7051", "tlsCACerts": { "pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUWZ4l32loO9+FM0FYw61y3dUF5a0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzA1MDk0NDAwWhcNMzcwNzAxMDk0NDAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNPg\nyfDxHr4ZmFp3HB19f27vfc1YTKBnznLqIFwVad2Y+eXfni8DnTRNGgwdkG9uIK2L\n4Y9mwlKG/mTNx629G4GjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBSZlT6qe+DAGpEBXyMxzidqCkQ4PjAKBggqhkjOPQQD\nAgNHADBEAiAIG5jwBGddB9CwocmjAzFv8+e7+0bvNSwjrG229QogTgIgbTNoC33P\nmbR5ChlkUAW2t41hTOCSMIwLAlvEwpeCnAk=\n-----END CERTIFICATE-----\n" "pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUVSFCRQNScNJyIwJz89vi6tazYJ4wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzEzMTQ1MjAwWhcNMzcwNzA5MTQ1MjAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLg8\nzJvOKBR1fS+hrrMc3xEhOalkSG+5vGGpwzgHv5NNMlDZcbQVuEBHPmRowbLWx4nw\n2CIUSfkhtQGC5GmUncOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBRm7lBNvvkP8iy6f0cXwz9BTeSYDzAKBggqhkjOPQQD\nAgNHADBEAiB1p8QFXHszJsMqiShmyuTA6zGPfHlnan3dgYMCTNR7mwIgFx3SqSYk\nFizTEfVfOcdjIYGc3pTPTyK5PVbO1k2BW80=\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "peer0.org1.example.com", Loading @@ -34,9 +34,9 @@ } }, "peer0.org2.example.com": { "url": "grpcs://s2:9051", "url": "grpcs://teraflow.nlehd.de:9051", "tlsCACerts": { "pem": "-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUejv57h6dJkVIM2R1YnlqykkvG7gwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMjA3MDUwOTQ0MDBaFw0zNzA3MDEwOTQ0MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFZqoisCIgZyMM\n8e0YBA+jxH/+Fc4Y4OkEl5uGRXGl9s0OemCdvhlX9K+esX2DVk1st1PMfTEj/six\n9XPpVqzNo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUPEyzGBlZEjguoJB16wAmoH2bAh8wCgYIKoZIzj0EAwIDSAAwRQIh\nAL6DAWgrqRtbYoQ0oYAr/2vze0JtQcXoqiQKlyvYkUBbAiB/uSHBk3NwjzI8t8iW\nzQzr5eNy5JwOO0SWwPEv4Ev9iQ==\n-----END CERTIFICATE-----\n" "pem": "-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUOsbw943VjFitBzBEXAcxLlOLow8wCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMjA3MTMxNDUyMDBaFw0zNzA3MDkxNDUyMDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARKov9QrWe9dklr\nqYJxOOoqoO3EI18LtPizVCKYrG3IMqkaatM6DLc/2SBTSIqIDeTR6N8WZAPVgLKA\nboRt87Heo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUYe4sT8J0Y2iN/9Q14FcpmxK5dYcwCgYIKoZIzj0EAwIDSAAwRQIh\nAJh2+1QXc5/ZlPaN2qnh3TXbzPFeCDXjoMAoBsOYtRcMAiAF+tcoFY0NcLDfTZBm\nNuuiQDIasoTB9Wuu4PBv8T7I5w==\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "peer0.org2.example.com", Loading @@ -46,11 +46,11 @@ }, "certificateAuthorities": { "ca.org1.example.com": { "url": "https://s2:7054", "url": "https://teraflow.nlehd.de:7054", "caName": "ca-org1", "tlsCACerts": { "pem": [ "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUWZ4l32loO9+FM0FYw61y3dUF5a0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzA1MDk0NDAwWhcNMzcwNzAxMDk0NDAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNPg\nyfDxHr4ZmFp3HB19f27vfc1YTKBnznLqIFwVad2Y+eXfni8DnTRNGgwdkG9uIK2L\n4Y9mwlKG/mTNx629G4GjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBSZlT6qe+DAGpEBXyMxzidqCkQ4PjAKBggqhkjOPQQD\nAgNHADBEAiAIG5jwBGddB9CwocmjAzFv8+e7+0bvNSwjrG229QogTgIgbTNoC33P\nmbR5ChlkUAW2t41hTOCSMIwLAlvEwpeCnAk=\n-----END CERTIFICATE-----\n" "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUVSFCRQNScNJyIwJz89vi6tazYJ4wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjIwNzEzMTQ1MjAwWhcNMzcwNzA5MTQ1MjAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLg8\nzJvOKBR1fS+hrrMc3xEhOalkSG+5vGGpwzgHv5NNMlDZcbQVuEBHPmRowbLWx4nw\n2CIUSfkhtQGC5GmUncOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBRm7lBNvvkP8iy6f0cXwz9BTeSYDzAKBggqhkjOPQQD\nAgNHADBEAiB1p8QFXHszJsMqiShmyuTA6zGPfHlnan3dgYMCTNR7mwIgFx3SqSYk\nFizTEfVfOcdjIYGc3pTPTyK5PVbO1k2BW80=\n-----END CERTIFICATE-----\n" ] }, "httpOptions": { Loading @@ -60,9 +60,9 @@ }, "orderers": { "orderer0.example.com": { "url": "grpcs://s2:7050", "url": "grpcs://teraflow.nlehd.de:7050", "tlsCACerts": { "pem": "-----BEGIN CERTIFICATE-----\nMIICCjCCAbGgAwIBAgIURV0KgZTOagIAIU7wRcSg/mKl5RUwCgYIKoZIzj0EAwIw\nYjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcg\nWW9yazEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUu\nY29tMB4XDTIyMDcwNTA5NDQwMFoXDTM3MDcwMTA5NDQwMFowYjELMAkGA1UEBhMC\nVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UE\nChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEWrOugtJgVLAKZRw9jaC15RUbVuTm0ZmsqNyiQrKQ\nYawLE6fs+QIU7WQ25fxlYtmGB2S8nofGCDuwaoTevW0GoaNFMEMwDgYDVR0PAQH/\nBAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFLKBzGXaQg2Irr57\npjoFYZ9F1NoNMAoGCCqGSM49BAMCA0cAMEQCIB1YdgOEsATw2GeaFmq6nqWg0JDT\np456JB/reFmnPWdJAiBPo5H9sMh+MpP4R5ue7nuwYK7SEJ1DOJqWMlPuNhVgtA==\n-----END CERTIFICATE-----\n" "pem": "-----BEGIN CERTIFICATE-----\nMIICCjCCAbGgAwIBAgIUA6RVRhhZD8pvcNAQJ6HWPUkbNNIwCgYIKoZIzj0EAwIw\nYjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcg\nWW9yazEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUu\nY29tMB4XDTIyMDcxMzE0NTIwMFoXDTM3MDcwOTE0NTIwMFowYjELMAkGA1UEBhMC\nVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UE\nChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEs7mmo5MY0oO9zCYcraUN/MXWxHiQ04xG6tWLaeWX\nqfSmFnfO8UBFq4OF5Li861UWGe+s9QxNXIELchBG8M7qLqNFMEMwDgYDVR0PAQH/\nBAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFBGG7kbCLEXzlQUF\nQfx845Qf2WKCMAoGCCqGSM49BAMCA0cAMEQCIAwABAqRopU+Qt3myyt4YiKQFpyO\nWTZifesVFe3fM/Q3AiA7oZ9XdQ5EuPhqFxSz7ASF45iyL3k078ilusjpc6IZ/g==\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "orderer0.example.com", Loading