diff --git a/src/dlt/config/ca.org1.example.com-cert.pem b/src/dlt/config/ca.org1.example.com-cert.pem index 503077a9d3b54ee75c7daa13e1d4284a5d47e038..230cb04a1862d9b82f98b961e6238448d9b803a7 100644 --- a/src/dlt/config/ca.org1.example.com-cert.pem +++ b/src/dlt/config/ca.org1.example.com-cert.pem @@ -1,14 +1,14 @@ -----BEGIN CERTIFICATE----- -MIICJzCCAc2gAwIBAgIUPP8sE6DhhkVuX810ayyMK/77Zf0wCgYIKoZIzj0EAwIw +MIICJjCCAc2gAwIBAgIUUg8VnWZ4QPo0ohjSzLtOg5SnqbswCgYIKoZIzj0EAwIw cDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH EwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh -Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjExMTE2MTM1NTAwWhcNMzYxMTEyMTM1NTAw +Lm9yZzEuZXhhbXBsZS5jb20wHhcNMjExMTIyMTg0ODAwWhcNMzYxMTE4MTg0ODAw WjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV BAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT -Y2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBe+ -8KfXrwccQaq8BAkob7bFiDYOGQoHA/lilmpOHiowzW5NMbS6i+vRECK3t7T1QLV+ -P3sVCPaXtcFW34iDphqjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG -AQH/AgEBMB0GA1UdDgQWBBQXIoEUCo7pN9yWTKzuu5w2cgmxUjAKBggqhkjOPQQD -AgNIADBFAiEAlzGzFI91v9Ofbq2/GyhmD0ClMdIdhV4H9ZywL9iJ/wMCICPQYmRq -nx6WP9cTWh0HEVM8oWxlQJ8AtMQqNFHuLB1Y +Y2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIOo +NtC20scX8QGQgcSUvaau9RwQsKnq/t0914d3BoIqvBD94Ue1xX2VKEgFdQnQtIJq +/ZzT63f3QC0fG5BrSjmjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG +AQH/AgEBMB0GA1UdDgQWBBTQn8ZDeefPmduovU85c2bqzyzb8TAKBggqhkjOPQQD +AgNHADBEAiBXRKPF+MCMWIAzkHnbgeVrmKJBBjj6EeKU1IpdExDIogIgIw2PR2lx +KSoiemyU6hTEWbBmpkJbTIEiuGljYvd4uIQ= -----END CERTIFICATE----- diff --git a/src/dlt/config/connection-org1.json b/src/dlt/config/connection-org1.json index 5cd1dd90d1015fb5cd61ce1383605bd0598809fe..c22fe293394b93e40daf2544ed624bee786a9a73 100644 --- a/src/dlt/config/connection-org1.json +++ b/src/dlt/config/connection-org1.json @@ -26,7 +26,7 @@ "peer0.org1.example.com": { "url": "grpcs://s2:7051", "tlsCACerts": { - "pem": "-----BEGIN CERTIFICATE-----\nMIICJzCCAc2gAwIBAgIUPP8sE6DhhkVuX810ayyMK/77Zf0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjExMTE2MTM1NTAwWhcNMzYxMTEyMTM1NTAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBe+\n8KfXrwccQaq8BAkob7bFiDYOGQoHA/lilmpOHiowzW5NMbS6i+vRECK3t7T1QLV+\nP3sVCPaXtcFW34iDphqjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBQXIoEUCo7pN9yWTKzuu5w2cgmxUjAKBggqhkjOPQQD\nAgNIADBFAiEAlzGzFI91v9Ofbq2/GyhmD0ClMdIdhV4H9ZywL9iJ/wMCICPQYmRq\nnx6WP9cTWh0HEVM8oWxlQJ8AtMQqNFHuLB1Y\n-----END CERTIFICATE-----\n" + "pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUUg8VnWZ4QPo0ohjSzLtOg5SnqbswCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjExMTIyMTg0ODAwWhcNMzYxMTE4MTg0ODAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIOo\nNtC20scX8QGQgcSUvaau9RwQsKnq/t0914d3BoIqvBD94Ue1xX2VKEgFdQnQtIJq\n/ZzT63f3QC0fG5BrSjmjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBTQn8ZDeefPmduovU85c2bqzyzb8TAKBggqhkjOPQQD\nAgNHADBEAiBXRKPF+MCMWIAzkHnbgeVrmKJBBjj6EeKU1IpdExDIogIgIw2PR2lx\nKSoiemyU6hTEWbBmpkJbTIEiuGljYvd4uIQ=\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "peer0.org1.example.com", @@ -36,7 +36,7 @@ "peer0.org2.example.com": { "url": "grpcs://s2:9051", "tlsCACerts": { - "pem": "-----BEGIN CERTIFICATE-----\nMIICHjCCAcWgAwIBAgIUFKM/u+SoArOf8LaPzuNb+a/vyg8wCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMTExMTYxMzU1MDBaFw0zNjExMTIxMzU1MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQwFdmDU4/4Gzr6\nJjrbe6znK+QCbdt7wFbRDs3qn418MFgl4fs4x/LwDLCK/spQ4ovFSZpD7Cit8RLM\nzFT8a/rAo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUcHmxBBqyVYx0u5Gn2Av75fLB4twwCgYIKoZIzj0EAwIDRwAwRAIg\nNv/y6XtRg/k8PNdo1yOB6BAb+TuTStLs3WQOrcBMhgcCICCxl0jgIaYPXvxNE+8X\ntGKznq/sDoyzfz/dWUZh4Sdv\n-----END CERTIFICATE-----\n" + "pem": "-----BEGIN CERTIFICATE-----\nMIICHjCCAcWgAwIBAgIUMQ2ItO6SSHzsgvAJZFN0iG+Q+/QwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMTExMjIxODQ4MDBaFw0zNjExMTgxODQ4MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR3g4vdVJ87A6pG\nwTV5s0TSIC6lVfNKi0HbxhaMYhFcWHt2BBho8hgIAm6oWZ++J3x5zroejxApc8E5\n19Dpsr2ho0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUK2BKZZP6iV1b7eozbFe77GLv7y0wCgYIKoZIzj0EAwIDRwAwRAIg\nHsbOx6v9vCD+8Ef5Pkks+EpmPPT2opW3JJHcEvlqmzkCIGS1nOW1Rf97+8BsfCwP\ngsqR6Ye2X75ek2vTymVXVDFJ\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "peer0.org2.example.com", @@ -50,7 +50,7 @@ "caName": "ca-org1", "tlsCACerts": { "pem": [ - "-----BEGIN CERTIFICATE-----\nMIICJzCCAc2gAwIBAgIUPP8sE6DhhkVuX810ayyMK/77Zf0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjExMTE2MTM1NTAwWhcNMzYxMTEyMTM1NTAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBe+\n8KfXrwccQaq8BAkob7bFiDYOGQoHA/lilmpOHiowzW5NMbS6i+vRECK3t7T1QLV+\nP3sVCPaXtcFW34iDphqjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBQXIoEUCo7pN9yWTKzuu5w2cgmxUjAKBggqhkjOPQQD\nAgNIADBFAiEAlzGzFI91v9Ofbq2/GyhmD0ClMdIdhV4H9ZywL9iJ/wMCICPQYmRq\nnx6WP9cTWh0HEVM8oWxlQJ8AtMQqNFHuLB1Y\n-----END CERTIFICATE-----\n" + "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIUUg8VnWZ4QPo0ohjSzLtOg5SnqbswCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjExMTIyMTg0ODAwWhcNMzYxMTE4MTg0ODAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIOo\nNtC20scX8QGQgcSUvaau9RwQsKnq/t0914d3BoIqvBD94Ue1xX2VKEgFdQnQtIJq\n/ZzT63f3QC0fG5BrSjmjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBTQn8ZDeefPmduovU85c2bqzyzb8TAKBggqhkjOPQQD\nAgNHADBEAiBXRKPF+MCMWIAzkHnbgeVrmKJBBjj6EeKU1IpdExDIogIgIw2PR2lx\nKSoiemyU6hTEWbBmpkJbTIEiuGljYvd4uIQ=\n-----END CERTIFICATE-----\n" ] }, "httpOptions": { @@ -62,7 +62,7 @@ "orderer0.example.com": { "url": "grpcs://s2:7050", "tlsCACerts": { - "pem": "-----BEGIN CERTIFICATE-----\nMIICCjCCAbGgAwIBAgIUKks7IUGYSmAhC7w/iUjZCie5dr4wCgYIKoZIzj0EAwIw\nYjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcg\nWW9yazEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUu\nY29tMB4XDTIxMTExNjEzNTUwMFoXDTM2MTExMjEzNTUwMFowYjELMAkGA1UEBhMC\nVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UE\nChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEelV1EbjujRxVKnFnwWwVbZaO3t9xDRz4o9t7nHEb\nMIqCDuDEZ8wZ4N/Gt/9QToTgWvGOLW7w9x0QQ07AlPALoKNFMEMwDgYDVR0PAQH/\nBAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFGiNPnPOIpCVoe/9\nDW2DAPUuAXOsMAoGCCqGSM49BAMCA0cAMEQCICll0GyPnXN84B6otL8xl+22uXYg\nxqk61hoMTui3LIqfAiA7YMtlFfcjgJLwGoxEvjaW6S6eS548/OZH6X5IEFjTXA==\n-----END CERTIFICATE-----\n" + "pem": "-----BEGIN CERTIFICATE-----\nMIICCzCCAbGgAwIBAgIUVXJ8op9+t1XoWR3BDbodSHNA4WcwCgYIKoZIzj0EAwIw\nYjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcg\nWW9yazEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUu\nY29tMB4XDTIxMTEyMjE4NDgwMFoXDTM2MTExODE4NDgwMFowYjELMAkGA1UEBhMC\nVVMxETAPBgNVBAgTCE5ldyBZb3JrMREwDwYDVQQHEwhOZXcgWW9yazEUMBIGA1UE\nChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1wbGUuY29tMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAE3ZjdgxSVlZpHiFHRjd7Sct5YSFlPOuKePGT8i8SN\nWh5bZje2JHSQ4JMMgiiyALJCHUdBqnfs05D0ds4Hz4rJUaNFMEMwDgYDVR0PAQH/\nBAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFEsA2wOBKpjnILGy\nIPtNmvIrwAt4MAoGCCqGSM49BAMCA0gAMEUCIQDxg/NK2ZuNrzA6U/lRU6IWQbwt\nC9gWNlz55pCS2HlWsAIgCHLo4oaECBYmGosqrC5hZQ5NgdV60X9Td0QC6zdYmJk=\n-----END CERTIFICATE-----\n" }, "grpcOptions": { "ssl-target-name-override": "orderer0.example.com", diff --git a/src/dlt/src/main/kotlin/Main.kt b/src/dlt/src/main/kotlin/Main.kt index a3c21867fd260c849fc7d7d752dda4ac61ab26dd..d1e7e3076c0e12ed4578cccb05665d59138dc29b 100644 --- a/src/dlt/src/main/kotlin/Main.kt +++ b/src/dlt/src/main/kotlin/Main.kt @@ -3,38 +3,13 @@ import io.ktor.client.engine.cio.* import io.ktor.client.features.* import io.ktor.client.request.* import io.ktor.http.* +import io.ktor.utils.io.jvm.javaio.* import kotlinx.serialization.ExperimentalSerializationApi -import org.hyperledger.fabric.gateway.Gateway -import org.hyperledger.fabric.gateway.Wallets +import proto.Config import proto.Config.DltConfig -import java.nio.file.Paths - - -// helper function for getting connected to the gateway -fun connect(): Gateway { - // Load a file system based wallet for managing identities. - val walletPath = Paths.get("wallet") - val wallet = Wallets.newFileSystemWallet(walletPath) - // load a CCP - val networkConfigPath = Paths.get("config/connection-org1.json") - val builder = Gateway.createBuilder() - builder.identity(wallet, "appUser").networkConfig(networkConfigPath).discovery(true) - return builder.connect() -} @OptIn(ExperimentalSerializationApi::class) suspend fun main(args: Array<String>) { -// // connect to the network and invoke the smart contract -// connect().use { gateway -> -// // get the network and contract -// val network = gateway.getNetwork("dlt") -// val contract = network.getContract("basic") -// println("Submit Transaction: InitLedger creates the initial set of assets on the ledger.") -// contract.submitTransaction("InitLedger") -// val result = contract.evaluateTransaction("GetAllAssets") -// println("Evaluate Transaction: GetAllAssets, result: " + String(result)) -// } - // TODO: default configuration file val cfg = DltConfig.newBuilder().setWallet("wallet").setConnectionFile("config/connection-org1.json") .setUser("appUser") @@ -54,11 +29,11 @@ suspend fun main(args: Array<String>) { try { client.post<ByteArray>("http://localhost:8080/dlt/configure") { - contentType(ContentType.Any) body = cfgBytes } } catch (e: ClientRequestException) { println(e.response.status) + println(String(e.response.content.toInputStream().readAllBytes())) } try { @@ -66,5 +41,67 @@ suspend fun main(args: Array<String>) { println(DltConfig.parseFrom(config)) } catch (e: ClientRequestException) { println(e.response.status) + println(String(e.response.content.toInputStream().readAllBytes())) + } + + val uuid = "41f4d2e2-f4ef-4c81-872a-c32f2d26b2ca" + try { + val record = client.get<ByteArray>("http://localhost:8080/dlt/record") { + body = uuid + } + println(Config.DltRecord.parseFrom(record)) + } catch (e: ClientRequestException) { + println(e.response.status) + println(String(e.response.content.toInputStream().readAllBytes())) + } + + val id = Config.DltRecordId.newBuilder().setUuid(uuid).build() + val record = Config.DltRecord.newBuilder().setId(id).setOperation(Config.DltRecordOperation.ADD) + .setType(Config.DltRecordType.DEVICE).setJson("{}").build() + try { + val result = client.post<ByteArray>("http://localhost:8080/dlt/record") { + body = record.toByteArray() + } + println(String(result)) + val requestedRecord = client.get<ByteArray>("http://localhost:8080/dlt/record") { + body = uuid + } + println(Config.DltRecord.parseFrom(requestedRecord)) + } catch (e: ClientRequestException) { + println(e.response.status) + println(String(e.response.content.toInputStream().readAllBytes())) } + + try { + val newRecord = Config.DltRecord.newBuilder().setId(id).setOperation(Config.DltRecordOperation.UPDATE) + .setType(Config.DltRecordType.SLICE).setJson("{}").build() + val result = client.post<ByteArray>("http://localhost:8080/dlt/record") { + body = newRecord.toByteArray() + } + println(String(result)) + val requestedRecord = client.get<ByteArray>("http://localhost:8080/dlt/record") { + body = uuid + } + println(Config.DltRecord.parseFrom(requestedRecord)) + } catch (e: ClientRequestException) { + println(e.response.status) + println(String(e.response.content.toInputStream().readAllBytes())) + } + + try { + val newRecord = Config.DltRecord.newBuilder().setId(id).setOperation(Config.DltRecordOperation.DISABLE) + .setType(Config.DltRecordType.SLICE).setJson("{}").build() + val result = client.post<ByteArray>("http://localhost:8080/dlt/record") { + body = newRecord.toByteArray() + } + println(String(result)) + val requestedRecord = client.get<ByteArray>("http://localhost:8080/dlt/record") { + body = uuid + } + println(Config.DltRecord.parseFrom(requestedRecord)) + } catch (e: ClientRequestException) { + println(e.response.status) + println(String(e.response.content.toInputStream().readAllBytes())) + } + } \ No newline at end of file diff --git a/src/dlt/src/main/kotlin/fabric/ConnectGateway.kt b/src/dlt/src/main/kotlin/fabric/ConnectGateway.kt new file mode 100644 index 0000000000000000000000000000000000000000..62716ebfed1fcf9afa9c08c7bf73743b163ce85d --- /dev/null +++ b/src/dlt/src/main/kotlin/fabric/ConnectGateway.kt @@ -0,0 +1,17 @@ +package fabric + +import org.hyperledger.fabric.gateway.Contract +import org.hyperledger.fabric.gateway.Gateway +import org.hyperledger.fabric.gateway.Wallet +import java.nio.file.Paths + +// helper function for getting connected to the gateway +fun getContract(config: proto.Config.DltConfig, wallet: Wallet): Contract { + // load a CCP + val networkConfigPath = Paths.get(config.connectionFile) + val builder = Gateway.createBuilder() + builder.identity(wallet, config.user).networkConfig(networkConfigPath).discovery(true) + val gateway = builder.connect() + val network = gateway.getNetwork(config.channel) + return network.getContract(config.contract) +} \ No newline at end of file diff --git a/src/dlt/src/main/kotlin/fabric/FabricConnector.kt b/src/dlt/src/main/kotlin/fabric/FabricConnector.kt index fa5fdabab670beaa77865df39dac75f0498b17a6..45e86c869e32f9cba1095ace8f9c25e2e93b607f 100644 --- a/src/dlt/src/main/kotlin/fabric/FabricConnector.kt +++ b/src/dlt/src/main/kotlin/fabric/FabricConnector.kt @@ -1,5 +1,9 @@ package fabric +import com.google.protobuf.util.JsonFormat +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import org.hyperledger.fabric.gateway.Contract import org.hyperledger.fabric.gateway.Wallet import org.hyperledger.fabric.gateway.Wallets import org.hyperledger.fabric.sdk.security.CryptoSuiteFactory @@ -11,6 +15,8 @@ import java.util.* class FabricConnector(val config: Config.DltConfig) { private val caClient: HFCAClient private val wallet: Wallet + private val contract: Contract + init { // Create a CA client for interacting with the CA. val props = Properties() @@ -22,10 +28,48 @@ class FabricConnector(val config: Config.DltConfig) { // Create a wallet for managing identities wallet = Wallets.newFileSystemWallet(Paths.get(config.wallet)) + contract = connect() } - fun connect() { + fun connect(): Contract { enrollAdmin(config, caClient, wallet) registerUser(config, caClient, wallet) + return getContract(config, wallet) + } + + fun putData(record: Config.DltRecord): String { + println(record.type.toString()) + return String( + contract.submitTransaction( + "AddRecord", + record.id.uuid, + record.type.number.toString(), + record.json + ) + ) + } + + fun getData(uuid: String): Config.DltRecord { + // TODO: get rid of json encoding/decoding + val result = contract.evaluateTransaction("GetRecord", uuid) + println(String(result)) + val builder = Config.DltRecord.newBuilder() + val protoRes = JsonFormat.parser().merge(String(result), builder) + return builder.build() + } + + fun updateData(record: Config.DltRecord): String { + return String( + contract.submitTransaction( + "UpdateRecord", + record.id.uuid, + record.type.number.toString(), + record.json + ) + ) + } + + fun deleteData(uuid: String): String { + return String(contract.submitTransaction("DeactivateRecord", uuid)) } } \ No newline at end of file diff --git a/src/dlt/src/main/kotlin/http/Server.kt b/src/dlt/src/main/kotlin/http/Server.kt index 1aaf8edb0b4b07013585b80f4544e38a940cefcb..31aa3a2ad4858bc4363180ded0ed3885336052d0 100644 --- a/src/dlt/src/main/kotlin/http/Server.kt +++ b/src/dlt/src/main/kotlin/http/Server.kt @@ -12,7 +12,9 @@ import io.ktor.server.netty.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.withContext -import proto.Config.DltConfig.parseFrom +import proto.Config +import proto.Config.DltConfig +import proto.Config.DltRecord class Server { var connector: FabricConnector? = null @@ -20,6 +22,11 @@ class Server { val mutex = Mutex() } +fun checkException(e: Exception): String { + if (e.message == null) return "" + return e.message!! +} + fun main() { val server = Server() embeddedServer(Netty, port = server.port) { @@ -29,30 +36,88 @@ fun main() { withContext(Dispatchers.IO) { try { val data = call.receiveStream() - val config = parseFrom(data) + val config = DltConfig.parseFrom(data) println(config) server.mutex.lock() server.connector = FabricConnector(config) server.mutex.unlock() - server.connector!!.connect() call.response.status(HttpStatusCode.Created) } // TODO: catch exceptions one by one catch (e: Exception) { - call.response.status(HttpStatusCode.BadRequest) + call.respond(HttpStatusCode.BadRequest, checkException(e)) e.printStackTrace() } } } get("/dlt/configure") { - server.mutex.lock() - if (server.connector == null) { + withContext(Dispatchers.IO) { + server.mutex.lock() + if (server.connector == null) { + server.mutex.unlock() + call.respond(HttpStatusCode.NotFound, "Not initialized") + } else { + val configBytes = server.connector!!.config.toByteArray() + server.mutex.unlock() + call.respond(HttpStatusCode.OK, configBytes) + } + } + } + post("/dlt/record") { + withContext(Dispatchers.IO) { + server.mutex.lock() + try { + if (server.connector == null) { + call.respond(HttpStatusCode.NotFound, "Not initialized") + } else { + val record = DltRecord.parseFrom(call.receiveStream()) + when (record.operation) { + Config.DltRecordOperation.ADD -> { + val result = server.connector!!.putData(record) + call.respond(HttpStatusCode.Created, result) + } + Config.DltRecordOperation.UPDATE -> { + val result = server.connector!!.updateData(record) + call.respond(HttpStatusCode.OK, result) + } + // TODO: Disable should require only uuid + Config.DltRecordOperation.DISABLE -> { + val result = server.connector!!.deleteData(record.id.uuid) + call.respond(HttpStatusCode.OK, result) + } + else -> { + call.respond(HttpStatusCode.BadRequest, "Invalid operation") + } + } + } + } + // TODO: catch exceptions one by one + catch (e: Exception) { + call.respond(HttpStatusCode.BadRequest, checkException(e)) + e.printStackTrace() + } server.mutex.unlock() - call.respond(HttpStatusCode.NotFound) - } else { - val configBytes = server.connector!!.config.toByteArray() + } + } + get("/dlt/record") { + withContext(Dispatchers.IO) { + server.mutex.lock() + try { + if (server.connector == null) { + call.respond(HttpStatusCode.NotFound) + } else { + val uuid = call.receiveText() + println("Uuid request: $uuid") + val result = server.connector!!.getData(uuid) + call.respond(HttpStatusCode.OK, result.toByteArray()) + } + } + // TODO: catch exceptions one by one + catch (e: Exception) { + call.respond(HttpStatusCode.NotFound, checkException(e)) + e.printStackTrace() + } server.mutex.unlock() - call.respond(HttpStatusCode.OK, configBytes) } } } diff --git a/src/dlt/src/main/kotlin/proto/Config.proto b/src/dlt/src/main/kotlin/proto/Config.proto index 4345af4827ad3e74201ffca36fc3022cbdbb6ca8..2ccf8456f3448bc150500bd0e8a8a5b84339cf02 100644 --- a/src/dlt/src/main/kotlin/proto/Config.proto +++ b/src/dlt/src/main/kotlin/proto/Config.proto @@ -22,9 +22,8 @@ message DltRecordId { enum DltRecordOperation { ADD = 0; - GET = 1; - UPDATE = 2; - DISABLE = 3; + UPDATE = 1; + DISABLE = 2; } enum DltRecordType {