Skip to content

Commit 5346ee0

Browse files
authored
Add JavaScript sample app (#8)
1 parent 60c4016 commit 5346ee0

17 files changed

+267
-63
lines changed

.github/workflows/ci.yml

+12-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: [main]
88

99
jobs:
10-
build-app:
10+
build-cpp-app:
1111
runs-on: ubuntu-20.04
1212
container: mcr.microsoft.com/ccf/app/dev:lts-devcontainer
1313

@@ -17,6 +17,7 @@ jobs:
1717

1818
- name: Build app
1919
run: mkdir -p build && cd build && CC="/opt/oe_lvi/clang-10" CXX="/opt/oe_lvi/clang++-10" cmake -GNinja .. && ninja
20+
working-directory: cpp
2021

2122
build-containers:
2223
runs-on: ubuntu-20.04
@@ -26,8 +27,14 @@ jobs:
2627
- name: Checkout repository
2728
uses: actions/checkout@v3
2829

29-
- name: Build enclave container
30-
run: docker build -t ccf-app-template:enclave -f docker/ccf_app.enclave .
30+
- name: Build C++ enclave container
31+
run: docker build -t ccf-app-template:cpp-enclave -f docker/ccf_app_cpp.enclave .
3132

32-
- name: Build virtual container
33-
run: docker build -t ccf-app-template:virtual -f docker/ccf_app.virtual .
33+
- name: Build C++ virtual container
34+
run: docker build -t ccf-app-template:cpp-virtual -f docker/ccf_app_cpp.virtual .
35+
36+
- name: Build JS enclave container
37+
run: docker build -t ccf-app-template:js-enclave -f docker/ccf_app_js.enclave .
38+
39+
- name: Build JS virtual container
40+
run: docker build -t ccf-app-template:js-virtual -f docker/ccf_app_js.virtual .

.gitignore

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
build/**
2-
*.deb
1+
**/build/**
2+
*.deb
3+
/.venv_ccf_sandbox/
4+
**/workspace/

.tours/sample-cpp-app.tour

+14-24
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
"title": "Sample C++ App Tour",
44
"steps": [
55
{
6-
"file": "src/app/app.cpp",
6+
"file": "cpp/app/app.cpp",
77
"description": "This file defines a sample CCF C++ application. \n\nThe sample application is simple and does not make use of all CCF features (e.g. historical queries). However, it is a great starting point for new CCF developers.",
88
"line": 1
99
},
1010
{
11-
"file": "src/app/app.cpp",
11+
"file": "cpp/app/app.cpp",
1212
"description": "Here, the application is instantiated. \n\nThis lets CCF know that the application handlers should be registered and available on each CCF node starting this application. ",
1313
"line": 120,
1414
"selection": {
@@ -23,22 +23,22 @@
2323
}
2424
},
2525
{
26-
"file": "src/app/app.cpp",
26+
"file": "cpp/app/app.cpp",
2727
"description": "The application logic is defined in this namespace.\n\nIn particular, it defines:\n1. The types used by the app to record its state in the key-value store.\n2. The API schema for each endpoint.\n3. The HTTP endpoints that contain the business logic of the application and that can be invoked by client requests.",
2828
"line": 12
2929
},
3030
{
31-
"file": "src/app/app.cpp",
31+
"file": "cpp/app/app.cpp",
3232
"description": "The application makes use of a single key-value store map, which maps a `size_t` key to a `std::string` value (e.g. 0 -> \"hello world\").\n\nAll `put` operations on this map are recorded in the CCF ledger. ",
3333
"line": 15
3434
},
3535
{
36-
"file": "src/app/app.cpp",
36+
"file": "cpp/app/app.cpp",
3737
"description": "This defines the name of the `kv::Map` declared above. \n\nNote that the name is *not* prefixed with `public:` so all data written to this map is encrypted in the ledger. If the table was prefixed with `public:`, all writes to the map would be recorded in clear in the ledger, which is useful for auditable public data.",
3838
"line": 16
3939
},
4040
{
41-
"file": "src/app/app.cpp",
41+
"file": "cpp/app/app.cpp",
4242
"description": "CCF applications automatically generate their own OpenAPI specification (accessible via `GET /app/api`).\n\nThese lines specify metadata for the entire application.",
4343
"line": 37,
4444
"selection": {
@@ -53,12 +53,12 @@
5353
}
5454
},
5555
{
56-
"file": "src/app/app.cpp",
56+
"file": "cpp/app/app.cpp",
5757
"description": "This is the first HTTP handler defined by the application.\n\nIt lets users record an arbitrary message in the \"records\" private key-value map. The unique key of the message is set by the user as the `id` query parameter. \n\nEach handler is given a single transaction object (`ctx.tx`) that needs to be used to mutate and read from the key-value store.",
5858
"line": 43
5959
},
6060
{
61-
"file": "src/app/app.cpp",
61+
"file": "cpp/app/app.cpp",
6262
"description": "This is the CCF key-value store API to write to a specific map. \n\nA \"handle\" should be first retrieved on the map, using the `rw<Map>(RECORDS)` method on the unique transaction object `ctx.tx`. Then, a value (`in.msg`) can be recorded at a specific key (`id`) using the `put(key, value)` call. \n\nSee https://microsoft.github.io/CCF/release/2.x/build_apps/kv/index.html for the full key-value store API.",
6363
"line": 66,
6464
"selection": {
@@ -73,7 +73,7 @@
7373
}
7474
},
7575
{
76-
"file": "src/app/app.cpp",
76+
"file": "cpp/app/app.cpp",
7777
"description": "This installs the `write` handler as an HTTP endpoint.\n\nIt specifies:\n- The URI of the HTTP endpoint. In this case, `POST /app/log`. Note that all CCF application endpoints are prefixed with `/app`.\n- The content type of the HTTP request and response, in this case JSON.\n- The user authentication scheme. In this case, unauthenticated users are allowed to invoke the endpoint. See https://microsoft.github.io/CCF/release/2.x/build_apps/auth/index.html for the list of all supported authentication schemes.\n- The API schema to use in the generated OpenAPI specification.\n- The `id` query parameter at which the user message will be recorded. ",
7878
"line": 71,
7979
"selection": {
@@ -88,12 +88,12 @@
8888
}
8989
},
9090
{
91-
"file": "src/app/app.cpp",
91+
"file": "cpp/app/app.cpp",
9292
"description": "This is the second handler for this sample application.\n\nIt is similar to the first handler except that it only reads from the key-value store.",
9393
"line": 77
9494
},
9595
{
96-
"file": "src/app/app.cpp",
96+
"file": "cpp/app/app.cpp",
9797
"description": "Note that `make_read_only_endpoint` is used to specify that the endpoint does not write to the key-value store. \n\nThe endpoint is accessible at `GET /app/log` and as such, does not accept any request body.\n\n",
9898
"line": 103,
9999
"selection": {
@@ -108,29 +108,19 @@
108108
}
109109
},
110110
{
111-
"file": "src/app/app.cpp",
111+
"file": "cpp/app/app.cpp",
112112
"description": "That's it! \n\nFor more information on how to build CCF C++ applications, see https://microsoft.github.io/CCF/release/2.x/build_apps/example.html. \n\nFor any questions or bugs, please open an issue on Github: https://github.com/microsoft/CCF/issues/new/choose.",
113113
"line": 122
114114
},
115115
{
116116
"file": "README.md",
117117
"description": "You can build the sample application by running the following steps.\n\nMake sure the dependencies have been installed, or that you have checked out this repository in a VSCode development container (see above).",
118-
"line": 19
118+
"line": 59
119119
},
120120
{
121121
"file": "README.md",
122122
"description": "Finally, you can run the application locally using the CCF sandbox script.\n\nYou can then interact with the application with `curl`.",
123-
"line": 34,
124-
"selection": {
125-
"start": {
126-
"line": 56,
127-
"character": 3
128-
},
129-
"end": {
130-
"line": 56,
131-
"character": 172
132-
}
133-
}
123+
"line": 75
134124
}
135125
],
136126
"ref": "main"

README.md

+71-22
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,83 @@
44

55
[![CCF App Template CI](https://github.com/microsoft/ccf-app-template/actions/workflows/ci.yml/badge.svg)](https://github.com/microsoft/ccf-app-template/actions/workflows/ci.yml)
66

7-
Template repository for CCF applications.
7+
Template repository for JavaScript and C++ CCF applications.
88

99
## Quickstart
1010

1111
**The quickest way to build and run this sample CCF app is to checkout this repository locally in its development container by clicking:
1212
[![Open in VSCode](https://img.shields.io/static/v1?label=Open+in&message=VSCode&logo=visualstudiocode&color=007ACC&logoColor=007ACC&labelColor=2C2C32)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/ccf-app-template)**
1313

14-
All dependencies will be automatically installed (takes ~2 mins on first checkout) and the app can be quickly [built](#build) and [run](#run) by following [the steps below](#build).
14+
All dependencies will be automatically installed (takes ~2 mins on first checkout).
1515

16+
Alternatively, if your organisation supports it, you can checkout this repository in a Github codespace: [![Open in Github codespace](https://img.shields.io/static/v1?label=Open+in&message=GitHub+codespace&logo=github&color=2F363D&logoColor=white&labelColor=2C2C32)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=496290904&machine=basicLinux32gb&devcontainer_path=.devcontainer.json&location=WestEurope)
1617

17-
Also check out the [code tour](#code-tour) to get an overview of the app.
18+
---
19+
20+
## JavaScript
21+
22+
CCF apps can be written in JavaScript/TypeScript. This is the quickest way to develop new apps as this does not require any compilation step and the app can be updated on the fly, via [a governance proposal](https://microsoft.github.io/CCF/main/build_apps/js_app_bundle.html#deployment).
23+
24+
The JavaScript sample bundle is located in the [`js/`](js/) directory.
25+
26+
### Run JS app
27+
28+
```bash
29+
$ /opt/ccf/bin/sandbox.sh --js-app-bundle ./js/
30+
[12:00:00.000] Virtual mode enabled
31+
[12:00:00.000] Starting 1 CCF node...
32+
[12:00:00.000] Started CCF network with the following nodes:
33+
[12:00:00.000] Node [0] = https://127.0.0.1:8000
34+
[12:00:00.000] You can now issue business transactions to the libjs_generic application
35+
[12:00:00.000] Loaded JS application: ./js/
36+
[12:00:00.000] Keys and certificates have been copied to the common folder: .../ccf-app-template/workspace/sandbox_common
37+
[12:00:00.000] See https://microsoft.github.io/CCF/main/use_apps/issue_commands.html for more information
38+
[12:00:00.000] Press Ctrl+C to shutdown the network
39+
```
40+
41+
In another terminal:
42+
43+
```bash
44+
$ curl -X POST https://127.0.0.1:8000/app/log?id=1 --cacert ./workspace/sandbox_common/service_cert.pem -H "Content-Type: application/json" --data '{"msg": "hello world"}'
45+
$ curl https://127.0.0.1:8000/app/log?id=1 --cacert ./workspace/sandbox_common/service_cert.pem
46+
hello world
47+
```
1848

19-
Alternatively, if your organisation supports it, you can checkout this repository in a Github Codespace: [![Open in Github codespace](https://img.shields.io/static/v1?label=Open+in&message=GitHub+codespace&logo=github&color=2F363D&logoColor=white&labelColor=2C2C32)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=496290904&machine=basicLinux32gb&devcontainer_path=.devcontainer.json&location=WestEurope)
49+
### Docker
50+
51+
It is possible to build a runtime image of the JavaScript application via docker:
52+
53+
```bash
54+
$ docker build -t ccf-app-template:js-enclave -f docker/ccf_app_js.enclave .
55+
$ docker run --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx ccf-app-template:js-enclave
56+
...
57+
2022-01-01T12:00:00.000000Z -0.000 0 [info ] ../src/node/node_state.h:1790 | Network TLS connections now accepted
58+
# It is then possible to interact with the service
59+
```
60+
61+
Or, for the non-SGX (a.k.a. virtual) variant:
62+
63+
```bash
64+
$ docker build -t ccf-app-template:js-virtual -f docker/ccf_app_js.virtual .
65+
$ docker run ccf-app-template:virtual
66+
```
2067

2168
---
2269

23-
## Build
70+
## C++
71+
72+
CCF apps can also be written in C++. This offers better performance than JavaScript apps but requires a compilation step and a restart of the CCF node for deployment.
73+
74+
The C++ sample app is located in the [`cpp/`](cpp/) directory.
75+
76+
Also check out the [code tour](#code-tour) to get an overview of the C++ app.
77+
78+
### Build C++ app
2479

2580
In the checkout of this repository:
2681

2782
```bash
83+
$ cd cpp/
2884
$ mkdir build && cd build
2985
$ CC="/opt/oe_lvi/clang-10" CXX="/opt/oe_lvi/clang++-10" cmake -GNinja ..
3086
$ ninja
@@ -35,7 +91,7 @@ libccf_app.virtual.so # Virtual application (i.e. insecure!)
3591

3692
See [docs](https://microsoft.github.io/CCF/main/build_apps) for complete instructions on how to build a CCF app.
3793

38-
## Run
94+
### Run C++ app
3995

4096
```bash
4197
$ /opt/ccf/bin/sandbox.sh -p ./libccf_app.virtual.so
@@ -53,22 +109,13 @@ Python environment successfully setup
53109

54110
Or, for an SGX-enabled application (unavailable in development container): `$ /opt/ccf/bin/sandbox.sh -p ./libccf_app.enclave.so.signed -e release`
55111

56-
In another terminal:
112+
### Docker
57113

58-
```bash
59-
$ cd build
60-
$ curl -X POST https://127.0.0.1:8000/app/log?id=1 --cacert ./workspace/sandbox_common/service_cert.pem -H "Content-Type: application/json" --data '{"msg": "hello world"}'
61-
$ curl https://127.0.0.1:8000/app/log?id=1 --cacert ./workspace/sandbox_common/service_cert.pem
62-
"hello world"
63-
```
64-
65-
## Docker
66-
67-
It is possible to build a runtime image of this application via docker:
114+
It is possible to build a runtime image of the C++ application via docker:
68115

69116
```bash
70-
$ docker build -t ccf-app-template:enclave -f docker/ccf_app.enclave .
71-
$ docker run --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx ccf-app-template:enclave
117+
$ docker build -t ccf-app-template:cpp-enclave -f docker/ccf_app_cpp.enclave .
118+
$ docker run --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx ccf-app-template:cpp-enclave
72119
...
73120
2022-01-01T12:00:00.000000Z -0.000 0 [info ] ../src/node/node_state.h:1790 | Network TLS connections now accepted
74121
# It is then possible to interact with the service
@@ -77,13 +124,15 @@ $ docker run --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provis
77124
Or, for the non-SGX (a.k.a. virtual) variant:
78125

79126
```bash
80-
$ docker build -t ccf-app-template:virtual -f docker/ccf_app.virtual .
127+
$ docker build -t ccf-app-template:cpp-virtual -f docker/ccf_app_cpp.virtual .
81128
$ docker run ccf-app-template:virtual
82129
```
83130

131+
---
132+
84133
## Dependencies
85134

86-
If this repository is checked out on a bare VM (e.g. [for SGX deployments](https://docs.microsoft.com/en-us/azure/confidential-computing/quick-create-portal)), the dependencies required to build and run the CCF app can be installed as follows:
135+
If this repository is checked out on a bare VM (e.g. [for SGX deployments](https://docs.microsoft.com/en-us/azure/confidential-computing/quick-create-portal)), the dependencies required to build and run the C++ app can be installed as follows:
87136

88137
```bash
89138
$ wget https://github.com/microsoft/CCF/releases/download/ccf-2.0.0/ccf_2.0.7_amd64.deb
@@ -97,4 +146,4 @@ See the [CCF official docs](https://microsoft.github.io/CCF/main/build_apps/inst
97146

98147
## Code Tour
99148

100-
In VSCode, a [code tour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) of this app can be started with: Ctrl + P, `> CodeTour: Start Tour`
149+
In VSCode, a [code tour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) of the C++ app can be started with: Ctrl + P, `> CodeTour: Start Tour`
File renamed without changes.

config/cchost_config_enclave_js.json

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"enclave": {
3+
"file": "/usr/lib/ccf/libjs_generic.enclave.so.signed",
4+
"type": "Release"
5+
},
6+
"network": {
7+
"node_to_node_interface": { "bind_address": "127.0.0.1:8081" },
8+
"rpc_interfaces": {
9+
"main_interface": {
10+
"bind_address": "0.0.0.0:8080"
11+
}
12+
}
13+
},
14+
"command": {
15+
"type": "Start",
16+
"service_certificate_file": "/app/service_cert.pem",
17+
"start": {
18+
"constitution_files": [
19+
"/app/validate.js",
20+
"/app/apply.js",
21+
"/app/resolve.js",
22+
"/app/actions.js"
23+
],
24+
"members": [
25+
{
26+
"certificate_file": "/app/member0_cert.pem",
27+
"encryption_public_key_file": "/app/member0_enc_pubk.pem"
28+
}
29+
]
30+
}
31+
}
32+
}
File renamed without changes.

config/cchost_config_virtual_js.json

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"enclave": {
3+
"file": "/usr/lib/ccf/libjs_generic.virtual.so",
4+
"type": "Virtual"
5+
},
6+
"network": {
7+
"node_to_node_interface": { "bind_address": "127.0.0.1:8081" },
8+
"rpc_interfaces": {
9+
"main_interface": {
10+
"bind_address": "0.0.0.0:8080"
11+
}
12+
}
13+
},
14+
"command": {
15+
"type": "Start",
16+
"service_certificate_file": "/app/service_cert.pem",
17+
"start": {
18+
"constitution_files": [
19+
"/app/validate.js",
20+
"/app/apply.js",
21+
"/app/resolve.js",
22+
"/app/actions.js"
23+
],
24+
"members": [
25+
{
26+
"certificate_file": "/app/member0_cert.pem",
27+
"encryption_public_key_file": "/app/member0_enc_pubk.pem"
28+
}
29+
]
30+
}
31+
}
32+
}

CMakeLists.txt cpp/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ if(NOT TARGET ccf)
99
find_package(ccf REQUIRED)
1010
endif()
1111

12-
add_ccf_app(ccf_app SRCS src/app/app.cpp)
12+
add_ccf_app(ccf_app SRCS ${CMAKE_CURRENT_SOURCE_DIR}/app/app.cpp)
1313

1414
# Generate an ephemeral signing key
1515
add_custom_command(
1616
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/signing_key.pem
1717
COMMAND openssl genrsa -out ${CMAKE_CURRENT_BINARY_DIR}/signing_key.pem -3
18-
3072
18+
3072
1919
)
2020
add_custom_target(
2121
app_signing_key ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/signing_key.pem

src/app/app.cpp cpp/app/app.cpp

File renamed without changes.

oe_sign.conf cpp/oe_sign.conf

File renamed without changes.

0 commit comments

Comments
 (0)