diff --git a/.azure-pipelines-gh-pages.yml b/.azure-pipelines-gh-pages.yml
index b7477eb501ff..742c347bc18a 100644
--- a/.azure-pipelines-gh-pages.yml
+++ b/.azure-pipelines-gh-pages.yml
@@ -11,7 +11,7 @@ jobs:
variables:
Codeql.SkipTaskAutoInjection: true
skipComponentGovernanceDetection: true
- container: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ container: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
pool:
vmImage: ubuntu-20.04
diff --git a/.azure-pipelines-model-checking.yml b/.azure-pipelines-model-checking.yml
index 7ffe0658c1ae..d28f4495f347 100644
--- a/.azure-pipelines-model-checking.yml
+++ b/.azure-pipelines-model-checking.yml
@@ -21,7 +21,7 @@ schedules:
resources:
containers:
- container: virtual
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE
jobs:
diff --git a/.azure-pipelines-release.yml b/.azure-pipelines-release.yml
index 03d5e5778bb9..d6785a332921 100644
--- a/.azure-pipelines-release.yml
+++ b/.azure-pipelines-release.yml
@@ -8,15 +8,15 @@ pr: none
resources:
containers:
- container: virtual
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
- container: snp
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-snp-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-snp-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
- container: sgx
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-sgx
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-sgx
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx -v /lib/modules:/lib/modules:ro
variables:
diff --git a/.azure-pipelines-templates/deploy_aci.yml b/.azure-pipelines-templates/deploy_aci.yml
index 0a1dd04cbba4..79b8f435ea7d 100644
--- a/.azure-pipelines-templates/deploy_aci.yml
+++ b/.azure-pipelines-templates/deploy_aci.yml
@@ -54,7 +54,7 @@ jobs:
- script: |
set -ex
docker login -u $ACR_TOKEN_NAME -p $ACR_CI_PUSH_TOKEN_PASSWORD $ACR_REGISTRY
- docker pull $ACR_REGISTRY/ccf/ci:oe-0.19.6-0-snp-clang15
+ docker pull $ACR_REGISTRY/ccf/ci:2024-06-26-snp-clang15
docker build -f docker/ccf_ci_built . --build-arg="base=$BASE_IMAGE" --build-arg="platform=snp" -t $ACR_REGISTRY/ccf/ci:pr-`git rev-parse HEAD`
docker push $ACR_REGISTRY/ccf/ci:pr-`git rev-parse HEAD`
name: build_ci_image
@@ -63,7 +63,7 @@ jobs:
ACR_TOKEN_NAME: ci-push-token
ACR_CI_PUSH_TOKEN_PASSWORD: $(ACR_CI_PUSH_TOKEN_PASSWORD)
ACR_REGISTRY: ccfmsrc.azurecr.io
- BASE_IMAGE: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-snp-clang15
+ BASE_IMAGE: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-snp-clang15
- script: |
set -ex
diff --git a/.azure-pipelines-templates/matrix.yml b/.azure-pipelines-templates/matrix.yml
index 4950e65bab0f..01bcf56f8aba 100644
--- a/.azure-pipelines-templates/matrix.yml
+++ b/.azure-pipelines-templates/matrix.yml
@@ -69,20 +69,6 @@ parameters:
ctest_args: '-L "raft_scenario"'
jobs:
- # Debug
- - ${{ each target in parameters.target }}:
- - template: common.yml
- parameters:
- target: ${{ target }}
- env: ${{ parameters.env[target] }}
- cmake_args: "${{ parameters.build.common.cmake_args }} ${{ parameters.build.debug.cmake_args }} ${{ parameters.build[target].cmake_args }}"
- cmake_env: "${{ parameters.build[target].cmake_env }}"
- suffix: "Debug"
- artifact_name: "${{ target }}_Debug"
- ctest_filter: "${{ parameters.test[target].ctest_args }}"
- depends_on: configure
- installExtendedTestingTools: false
-
# Tracing
- template: common.yml
parameters:
@@ -97,57 +83,6 @@ jobs:
installExtendedTestingTools: false
ninja_targets: "${{ parameters.build.tracing.ninja_targets }}"
- # Performance
- - ${{ if eq(parameters.perf_tests, 'run') }}:
- - template: common.yml
- parameters:
- target: SGX
- env: ${{ parameters.env.SGX }}
- cmake_args: "${{ parameters.build.common.cmake_args }} ${{ parameters.build.perf.cmake_args }} ${{ parameters.build.SGX.cmake_args }}"
- suffix: "Perf"
- artifact_name: "SGX_Perf"
- ctest_filter: "${{ parameters.test.perf.ctest_args }}"
- depends_on: configure
- installExtendedTestingTools: false
-
- - ${{ if eq(parameters.perf_tests, 'run') }}:
- - template: common.yml
- parameters:
- target: Virtual
- env: ${{ parameters.env.Virtual }}
- cmake_args: "${{ parameters.build.common.cmake_args }} ${{ parameters.build.perf.cmake_args }} ${{ parameters.build.Virtual.cmake_args }}"
- cmake_env: "${{ parameters.build.Virtual.cmake_env }}"
- suffix: "Perf"
- artifact_name: "Virtual_Perf"
- ctest_filter: "${{ parameters.test.virtual_perf.ctest_args }}"
- depends_on: configure
- installExtendedTestingTools: false
-
- - ${{ if eq(parameters.perf_tests, 'run') }}:
- - template: common.yml
- parameters:
- target: Virtual
- env: ${{ parameters.env.Virtual }}
- cmake_args: "${{ parameters.build.common.cmake_args }} ${{ parameters.build.perf.cmake_args }} ${{ parameters.build.Virtual.cmake_args }} -DWORKER_THREADS=2"
- cmake_env: "${{ parameters.build.Virtual.cmake_env }}"
- suffix: "Perf_MultiThreaded"
- artifact_name: "Virtual_Perf_MultiThreaded"
- ctest_filter: "-R pi_basic_mt"
- depends_on: configure
- installExtendedTestingTools: false
-
- - ${{ if eq(parameters.perf_tests, 'run') }}:
- - template: common.yml
- parameters:
- target: SGX
- env: ${{ parameters.env.SGX }}
- cmake_args: "${{ parameters.build.common.cmake_args }} ${{ parameters.build.perf.cmake_args }} ${{ parameters.build.SGX.cmake_args }} -DWORKER_THREADS=2"
- suffix: "Perf_MultiThreaded"
- artifact_name: "SGX_Perf_MultiThreaded"
- ctest_filter: "-R pi_basic_mt"
- depends_on: configure
- installExtendedTestingTools: false
-
- ${{ if eq(parameters.perf_tests, 'run') }}:
- template: simulation.yml
parameters:
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index c8ff90eb3064..5ca38bc59176 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -30,15 +30,15 @@ schedules:
resources:
containers:
- container: virtual
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
- container: snp
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-snp-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-snp-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
- container: sgx
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-sgx
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-sgx
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx -v /lib/modules:/lib/modules:ro
variables:
diff --git a/.azure_pipelines_snp.yml b/.azure_pipelines_snp.yml
index 3708df528b85..1ffb3ec69635 100644
--- a/.azure_pipelines_snp.yml
+++ b/.azure_pipelines_snp.yml
@@ -32,7 +32,7 @@ schedules:
resources:
containers:
- container: virtual
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
jobs:
diff --git a/.daily.yml b/.daily.yml
index 378a37159c58..6977470ac796 100644
--- a/.daily.yml
+++ b/.daily.yml
@@ -27,15 +27,15 @@ schedules:
resources:
containers:
- container: virtual
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE
- container: snp
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-snp-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-snp-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
- container: sgx
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-sgx
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-sgx
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx
jobs:
diff --git a/.daily_canary b/.daily_canary
index a02a115d02e2..b0c8ecafff33 100644
--- a/.daily_canary
+++ b/.daily_canary
@@ -3,4 +3,4 @@
( V ) / . \ | +---=---'
/--x-m- /--n-n---xXx--/--yY------>>>----<<<>>]]{{}}---||-/\---..
2024__
-!..!
\ No newline at end of file
+!..!
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 1057f18e21a8..c20457d9c709 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,6 +1,6 @@
{
"name": "CCF Development Environment",
- "image": "ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15",
+ "image": "ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15",
"runArgs": [],
"extensions": [
"eamodio.gitlens",
diff --git a/.github/workflows/bencher.yml b/.github/workflows/bencher.yml
index 2096a34220e3..41ad6e61d681 100644
--- a/.github/workflows/bencher.yml
+++ b/.github/workflows/bencher.yml
@@ -11,7 +11,7 @@ jobs:
name: Continuous Benchmarking with Bencher
runs-on: [self-hosted, 1ES.Pool=gha-virtual-ccf-sub]
container:
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
steps:
- uses: actions/checkout@v4
with:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000000..d7cb0d6a1835
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,91 @@
+name: CI
+
+on:
+ push:
+ branches: [main]
+ pull_request:
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ actions: read
+ checks: write
+
+jobs:
+ build_and_test:
+ name: CI
+ strategy:
+ matrix:
+ platform:
+ - name: virtual
+ image: default
+ nodes: [self-hosted, 1ES.Pool=gha-virtual-ccf-sub]
+ options: --user root --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
+ - name: snp
+ image: default
+ nodes: [self-hosted, 1ES.Pool=gha-virtual-ccf-sub]
+ options: --user root --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
+ - name: sgx
+ image: sgx
+ nodes: [self-hosted, 1ES.Pool=gha-sgx-ccf-sub]
+ options: --user root --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx -v /lib/modules:/lib/modules:ro
+ runs-on: ${{ matrix.platform.nodes }}
+ container:
+ image: ghcr.io/microsoft/ccf/ci/${{ matrix.platform.image }}:build-26-06-2024
+ options: ${{ matrix.platform.options }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: "Build Debug ${{ matrix.platform.name }}"
+ run: |
+ set -ex
+ git config --global --add safe.directory /__w/CCF/CCF
+ mkdir build
+ cd build
+ cmake -GNinja -DCOMPILE_TARGET=${{ matrix.platform.name }} -DCMAKE_BUILD_TYPE=Debug -DLVI_MITIGATIONS=OFF -DVERBOSE_LOGGING=ON ..
+ ninja
+ shell: bash
+
+ - name: "Platform SGX"
+ run: |
+ sudo groupadd -fg $(/usr/bin/stat -Lc '%g' /dev/sgx/provision) sgx_prv
+ sudo usermod -a -G sgx_prv $(whoami)
+ samples/scripts/sgxinfo.sh
+ cat /proc/cpuinfo | grep flags | uniq
+ shell: bash
+ if: "${{ matrix.platform.name == 'sgx' }}"
+
+ - name: "Platform SNP"
+ run: |
+ samples/scripts/snpinfo.sh
+ shell: bash
+ if: "${{ matrix.platform.name == 'snp' }}"
+
+ - name: "Test ${{ matrix.platform.name }}"
+ run: |
+ set -ex
+ cd build
+ rm -rf /github/home/.cache
+ mkdir -p /github/home/.cache
+ export ASAN_SYMBOLIZER_PATH=$(realpath /usr/bin/llvm-symbolizer-15)
+ # Unit tests
+ ./tests.sh --output-on-failure -L unit -j$(nproc --all)
+ # All other acceptably fast tests, mostly end-to-end
+ ./tests.sh --timeout 360 --output-on-failure -LE "benchmark|perf|protocolstest|vegeta|suite|unit"
+ # Partitions tests
+ ./tests.sh --timeout 360 --output-on-failure -LE "benchmark|perf|protocolstest|vegeta|suite"
+ shell: bash
+ if: "${{ matrix.platform.name != 'snp' }}" # Needs 1ES Pool support
+
+ - name: "Upload logs for ${{ matrix.platform.name }}"
+ uses: actions/upload-artifact@v4
+ with:
+ name: logs-${{ matrix.platform.name }}
+ path: |
+ build/workspace/*/*.config.json
+ build/workspace/*/out
+ build/workspace/*/err
+ if-no-files-found: ignore
+ if: success() || failure()
diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml
index b99186c23065..10c322b4851d 100644
--- a/.github/workflows/ci-checks.yml
+++ b/.github/workflows/ci-checks.yml
@@ -12,7 +12,7 @@ permissions: read-all
jobs:
checks:
runs-on: ubuntu-latest
- container: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ container: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
steps:
- run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index b56a06200817..53b2a077c54c 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -21,6 +21,9 @@ jobs:
name: Analyze
# Insufficient space to run on public runner, so use custom pool
runs-on: [self-hosted, 1ES.Pool=gha-virtual-ccf-sub]
+ container:
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
+ options: --user root
permissions:
security-events: write
@@ -28,11 +31,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- # Override automatic language detection by changing the below list
- # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
language: ["cpp"]
- # Learn more...
- # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
steps:
- name: Checkout repository
@@ -40,48 +39,26 @@ jobs:
with:
fetch-depth: 0
- # Initializes the CodeQL tools for scanning.
+ # Done before CodeQL init to let it find the commit successfully
+ - name: Work around git warning
+ run: git config --global --add safe.directory /__w/CCF/CCF
+
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- #- name: Autobuild
- # uses: github/codeql-action/autobuild@v2
-
- # âšī¸ Command-line programs to run using the OS shell.
- # đ https://git.io/JvXDl
-
- # âī¸ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- #- run: |
- # make bootstrap
- # make release
- - run: |
- cd getting_started/setup_vm
- sudo apt update
- sudo apt install -y ansible software-properties-common bsdmainutils dnsutils
- sudo ansible-playbook ccf-dev.yml --extra-vars "platform=virtual" --extra-vars "require_open_enclave=false"
- name: Install dependencies
- run: |
+ set -ex
mkdir build
cd build
- cmake -DCOMPILE_TARGET=virtual -DREQUIRE_OPENENCLAVE=OFF -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=OFF -DLVI_MITIGATIONS=OFF -DCMAKE_C_COMPILER=`which clang-11` -DCMAKE_CXX_COMPILER=`which clang++-11` ..
+ cmake -DCOMPILE_TARGET=virtual -DREQUIRE_OPENENCLAVE=OFF -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=OFF -DLVI_MITIGATIONS=OFF ..
name: Run CMake
- run: |
cd build
- make
+ make -j16
name: Run Make
- name: Perform CodeQL Analysis
diff --git a/.github/workflows/tlaplus.yml b/.github/workflows/tlaplus.yml
index 546d9396b812..f561f76a7e07 100644
--- a/.github/workflows/tlaplus.yml
+++ b/.github/workflows/tlaplus.yml
@@ -2,8 +2,7 @@ name: "TLA+ Spec Verification"
on:
push:
- paths:
- - "tla/**"
+ branches: [main]
pull_request:
paths:
- "tla/**"
@@ -19,7 +18,7 @@ jobs:
name: Model Checking - Consistency
runs-on: [self-hosted, 1ES.Pool=gha-virtual-ccf-sub]
container:
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
steps:
- uses: actions/checkout@v4
diff --git a/.multi-thread.yml b/.multi-thread.yml
index d8ceba878f3c..40ed8ec0801b 100644
--- a/.multi-thread.yml
+++ b/.multi-thread.yml
@@ -20,7 +20,7 @@ pr:
resources:
containers:
- container: virtual
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-virtual-clang15
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-virtual-clang15
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --cap-add SYS_PTRACE -v /lib/modules:/lib/modules:ro
jobs:
diff --git a/.stress.yml b/.stress.yml
index 5fdf14ce6b42..9ad58f2451e8 100644
--- a/.stress.yml
+++ b/.stress.yml
@@ -24,7 +24,7 @@ schedules:
resources:
containers:
- container: sgx
- image: ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-sgx
+ image: ccfmsrc.azurecr.io/ccf/ci:2024-06-26-sgx
options: --publish-all --cap-add NET_ADMIN --cap-add NET_RAW --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /dev/sgx:/dev/sgx
jobs:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7257a126720d..392bfa76c680 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `::threading` is now `ccf::threading`, and `ccf/ds/thread_ids.h` has moved to `ccf/threading/thread_ids.h`
- `::consensus` is now `ccf::consensus`
- `::tls` is now `ccf::tls`
+ - `::http` is now `ccf::http`
+ - `::nonstd` is now `ccf::nonstd`
+ - `::crypto` is now `ccf::crypto`
+ - `::kv` is now `ccf::kv`
+ - `::logger` is now `ccf::logger`
+ - `::ccfapp` is now `::ccf`
+- The `programmability` sample app now demonstrates how applications can define their own extensions, creating bindings between C++ and JS state, and allowing JS endpoints to call functions implemented in C++.
+- Introduce `DynamicJSEndpointRegistry::record_action_for_audit_v1` and `DynamicJSEndpointRegistry::check_action_not_replayed_v1` to allow an application making use of the programmability feature to easily implement auditability, and protect users allowed to update the application against replay attacks (#6285).
+- Endpoints now support a `ToBackup` redirection strategy, for requests which should never be executed on a primary. These must also be read-only. These are configured similar to `ToPrimary` endpoints, with a `to_backup` object (specifying by-role or statically-addressed targets) in each node's configuration.
+
+## Changed
+
+- Updated Open Enclave to [0.19.7](https://github.com/openenclave/openenclave/releases/tag/v0.19.7).
### Changed
@@ -25,6 +38,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Removed
- Removed the existing metrics endpoint and API (`GET /api/metrics`, `get_metrics_v1`). Stats for request execution can instead be gathered by overriding the `EndpointRegistry::handle_event_request_completed()` method.
+- Removed automatic msgpack support from JSON endpoint adapters, and related `include/ccf/serdes.h` file.
## [5.0.0-dev18]
diff --git a/README.md b/README.md
index f9c38fec8be2..795eda54591e 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-- Continuous Build: [![Build Status](https://dev.azure.com/MSRC-CCF/CCF/_apis/build/status/CCF%20Github%20CI?branchName=main)](https://dev.azure.com/MSRC-CCF/CCF/_build/latest?definitionId=3&branchName=main)
+- Continuous Build: [![CI](https://github.com/microsoft/CCF/actions/workflows/build.yml/badge.svg)](https://github.com/microsoft/CCF/actions/workflows/build.yml)
- Daily Build: [![Build Status](https://dev.azure.com/MSRC-CCF/CCF/_apis/build/status/CCF%20GitHub%20Daily?branchName=main)](https://dev.azure.com/MSRC-CCF/CCF/_build/latest?definitionId=7&branchName=main)
- Doc Build: [![docs](https://dev.azure.com/MSRC-CCF/CCF/_apis/build/status/CCF%20GitHub%20Pages?branchName=main)](https://dev.azure.com/MSRC-CCF/CCF/_build/latest?definitionId=4&branchName=main)
- Containers: [![Build and Publish Release Containers](https://github.com/microsoft/CCF/actions/workflows/containers.yml/badge.svg)](https://github.com/microsoft/CCF/actions/workflows/containers.yml)
diff --git a/cmake/common.cmake b/cmake/common.cmake
index eebb8bb66933..c2f98c0cb74c 100644
--- a/cmake/common.cmake
+++ b/cmake/common.cmake
@@ -17,7 +17,7 @@ function(add_unit_test name)
set_property(
TEST ${name}
APPEND
- PROPERTY LABELS unit_test
+ PROPERTY LABELS unit
)
set_property(
diff --git a/cmake/cpack_settings.cmake b/cmake/cpack_settings.cmake
index c51e8485ac7d..a56dff24babd 100644
--- a/cmake/cpack_settings.cmake
+++ b/cmake/cpack_settings.cmake
@@ -24,7 +24,7 @@ message(STATUS "Debian package version: ${CPACK_DEBIAN_PACKAGE_VERSION}")
set(CCF_DEB_BASE_DEPENDENCIES "libuv1 (>= 1.34.2);openssl (>=1.1.1f)")
set(CCF_DEB_DEPENDENCIES ${CCF_DEB_BASE_DEPENDENCIES})
-set(OE_VERSION "0.19.6")
+set(OE_VERSION "0.19.7")
if(COMPILE_TARGET STREQUAL "sgx")
list(APPEND CCF_DEB_DEPENDENCIES
"libc++1-11;libc++abi1-11;open-enclave (>=${OE_VERSION})"
diff --git a/cmake/open_enclave.cmake b/cmake/open_enclave.cmake
index 4bb7b8fc0040..9ccb11b38dfa 100644
--- a/cmake/open_enclave.cmake
+++ b/cmake/open_enclave.cmake
@@ -13,7 +13,7 @@ if(REQUIRE_OPENENCLAVE)
endif()
# Find OpenEnclave package
- find_package(OpenEnclave 0.19.6 CONFIG REQUIRED)
+ find_package(OpenEnclave 0.19.7 CONFIG REQUIRED)
option(USE_OPENSSL_3 "Use OpenSSL 3.x for Open Enclave builds" ON)
if(USE_OPENSSL_3)
diff --git a/doc/architecture/ledger.rst b/doc/architecture/ledger.rst
index 1f4172bfd4ab..9bb636892be5 100644
--- a/doc/architecture/ledger.rst
+++ b/doc/architecture/ledger.rst
@@ -35,21 +35,21 @@ The following table describes the structure of a serialised transaction as it is
+ +------------------------------------------+-------------------------------------------------------------------------+
| | uint64_t | Length of serialised public domain |
+----------+------------------------------------------+-------------------------------------------------------------------------+
-| | :cpp:type:`kv::EntryType` | Snapshot, or a WriteSet variant |
+| | :cpp:type:`ccf::kv::EntryType` | Snapshot, or a WriteSet variant |
+ +------------------------------------------+-------------------------------------------------------------------------+
-| | :cpp:type:`kv::Version` | Transaction version |
+| | :cpp:type:`ccf::kv::Version` | Transaction version |
+ +------------------------------------------+-------------------------------------------------------------------------+
-| | :cpp:type:`crypto::Sha256Hash` | User-defined claims digest, when entry type is WriteSetWith.*Claims |
+| | :cpp:type:`ccf::crypto::Sha256Hash` | User-defined claims digest, when entry type is WriteSetWith.*Claims |
+ +------------------------------------------+-------------------------------------------------------------------------+
-| | :cpp:type:`crypto::Sha256Hash` | Commit evidence digest, when entry type is WriteSetWithCommitEvidence.* |
+| | :cpp:type:`ccf::crypto::Sha256Hash` | Commit evidence digest, when entry type is WriteSetWithCommitEvidence.* |
+ +------------------------------------------+-------------------------------------------------------------------------+
-| | :cpp:type:`kv::Version` | Unused, reserved for compatibility |
+| | :cpp:type:`ccf::kv::Version` | Unused, reserved for compatibility |
+ +------------------------------------------+-------------------------------------------------------------------------+
| | **Repeating [0..n]** | With ``n`` the number of maps in the transaction |
+ +-----+------------------------------------+-------------------------------------------------------------------------+
-| | | std::string | Name of the serialised :cpp:type:`kv::Map` |
+| | | std::string | Name of the serialised :cpp:type:`ccf::kv::Map` |
| +-----+------------------------------------+-------------------------------------------------------------------------+
-| | | :cpp:type:`kv::Version` | Read version |
+| | | :cpp:type:`ccf::kv::Version` | Read version |
| +-----+------------------------------------+-------------------------------------------------------------------------+
| | | uint64_t | Read count |
| | +------------------------------------+-------------------------------------------------------------------------+
diff --git a/doc/build_apps/api.rst b/doc/build_apps/api.rst
index f89b5ef8068e..7b944c5ede28 100644
--- a/doc/build_apps/api.rst
+++ b/doc/build_apps/api.rst
@@ -10,7 +10,7 @@ A CCF application is composed of the following:
Application Entry Point
-----------------------
-.. doxygenfunction:: ccfapp::make_user_endpoints
+.. doxygenfunction:: ccf::make_user_endpoints
:project: CCF
@@ -72,6 +72,9 @@ Policies
.. doxygenvariable:: ccf::jwt_auth_policy
:project: CCF
+.. doxygenvariable:: ccf::TypedUserCOSESign1AuthnPolicy
+ :project: CCF
+
Identities
~~~~~~~~~~
@@ -122,7 +125,7 @@ Historical Queries
.. doxygenclass:: ccf::historical::AbstractStateCache
:project: CCF
- :members: set_default_expiry_duration, get_state_at, get_store_at, get_store_range, drop_cached_states
+ :members: set_default_expiry_duration, set_soft_cache_limit, get_state_at, get_store_at, get_store_range, drop_cached_states
.. doxygenstruct:: ccf::historical::State
:project: CCF
@@ -146,7 +149,7 @@ Indexing
JavaScript FFI Plugins
----------------------
-.. doxygenfunction:: ccfapp::get_js_plugins
+.. doxygenfunction:: ccf::get_js_plugins
:project: CCF
HTTP Entity Tags Matching
diff --git a/doc/build_apps/crypto.rst b/doc/build_apps/crypto.rst
index 8d6b4512ab8c..16229e8f4ea1 100644
--- a/doc/build_apps/crypto.rst
+++ b/doc/build_apps/crypto.rst
@@ -8,17 +8,17 @@ For convenience, CCF provides access to commonly used cryptographic primitives t
Hashing
-------
-.. doxygenfunction:: crypto::sha256(const std::vector &data)
+.. doxygenfunction:: ccf::crypto::sha256(const std::vector &data)
:project: CCF
-.. doxygenfunction:: crypto::hmac(MDType, const std::vector&, const std::vector&)
+.. doxygenfunction:: ccf::crypto::hmac(MDType, const std::vector&, const std::vector&)
:project: CCF
-.. doxygenClass:: crypto::HashProvider
+.. doxygenClass:: ccf::crypto::HashProvider
:project: CCF
:members:
-.. doxygenfunction:: crypto::make_hash_provider
+.. doxygenfunction:: ccf::crypto::make_hash_provider
:project: CCF
@@ -27,49 +27,49 @@ Asymmetric Keys
CCF supports EC and RSA keys; public keys are held in (RSA)PublicKey objects and
private keys in (RSA)KeyPair objects. (RSA)KeyPairs automatically generate random
-keys when constructed via :cpp:func:`KeyPairPtr crypto::make_key_pair(CurveID)` or
-:cpp:func:`RSAKeyPairPtr crypto::make_rsa_key_pair(size_t, size_t)`.
+keys when constructed via :cpp:func:`KeyPairPtr ccf::crypto::make_key_pair(CurveID)` or
+:cpp:func:`RSAKeyPairPtr ccf::crypto::make_rsa_key_pair(size_t, size_t)`.
-.. doxygenclass:: crypto::PublicKey
+.. doxygenclass:: ccf::crypto::PublicKey
:project: CCF
:members:
-.. doxygenclass:: crypto::KeyPair
+.. doxygenclass:: ccf::crypto::KeyPair
:project: CCF
:members:
-.. doxygenclass:: crypto::RSAPublicKey
+.. doxygenclass:: ccf::crypto::RSAPublicKey
:project: CCF
:members:
-.. doxygenclass:: crypto::RSAKeyPair
+.. doxygenclass:: ccf::crypto::RSAKeyPair
:project: CCF
:members:
-.. doxygenenum:: crypto::CurveID
+.. doxygenenum:: ccf::crypto::CurveID
:project: CCF
-.. doxygenfunction:: crypto::make_key_pair(CurveID)
+.. doxygenfunction:: ccf::crypto::make_key_pair(CurveID)
:project: CCF
-.. doxygenfunction:: crypto::make_key_pair(const Pem&)
+.. doxygenfunction:: ccf::crypto::make_key_pair(const Pem&)
:project: CCF
-.. doxygenfunction:: crypto::make_rsa_key_pair(size_t, size_t)
+.. doxygenfunction:: ccf::crypto::make_rsa_key_pair(size_t, size_t)
:project: CCF
Symmetric Keys
--------------------
-Currently, only AES-GCM is supported for symmetric encryption. New keys are generated via :cpp:func:`crypto::Entropy::random`
+Currently, only AES-GCM is supported for symmetric encryption. New keys are generated via :cpp:func:`ccf::crypto::Entropy::random`
-.. doxygenfunction:: crypto::aes_gcm_encrypt
+.. doxygenfunction:: ccf::crypto::aes_gcm_encrypt
:project: CCF
-.. doxygenfunction:: crypto::aes_gcm_decrypt
+.. doxygenfunction:: ccf::crypto::aes_gcm_decrypt
:project: CCF
-.. doxygenclass:: crypto::Entropy
+.. doxygenclass:: ccf::crypto::Entropy
:project: CCF
:members:
@@ -78,7 +78,7 @@ Signatures
Verification of signatures is supported via the :cpp:class:`Verifier` class.
-.. doxygenclass:: crypto::Verifier
+.. doxygenclass:: ccf::crypto::Verifier
:project: CCF
:members:
@@ -88,36 +88,36 @@ Key Wrapping
PKCS11 2.1.8 CKM_RSA_PKCS_OAEP
-.. doxygenfunction:: crypto::ckm_rsa_pkcs_oaep_wrap(RSAPublicKeyPtr, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_pkcs_oaep_wrap(RSAPublicKeyPtr, const std::vector&, const std::optional>&)
:project: CCF
-.. doxygenfunction:: crypto::ckm_rsa_pkcs_oaep_wrap(const Pem&, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_pkcs_oaep_wrap(const Pem&, const std::vector&, const std::optional>&)
:project: CCF
-.. doxygenfunction:: crypto::ckm_rsa_pkcs_oaep_unwrap(RSAKeyPairPtr, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_pkcs_oaep_unwrap(RSAKeyPairPtr, const std::vector&, const std::optional>&)
:project: CCF
-.. doxygenfunction:: crypto::ckm_rsa_pkcs_oaep_unwrap(const Pem&, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_pkcs_oaep_unwrap(const Pem&, const std::vector&, const std::optional>&)
:project: CCF
PKCS11 2.14.3 CKM_AES_KEY_WRAP_PAD (RFC 5649)
-.. doxygenfunction:: crypto::ckm_aes_key_wrap_pad
+.. doxygenfunction:: ccf::crypto::ckm_aes_key_wrap_pad
:project: CCF
-.. doxygenfunction:: crypto::ckm_aes_key_unwrap_pad
+.. doxygenfunction:: ccf::crypto::ckm_aes_key_unwrap_pad
:project: CCF
PKCS11 2.1.21 CKM_RSA_AES_KEY_WRAP
-.. doxygenfunction:: crypto::ckm_rsa_aes_key_wrap(size_t, RSAPublicKeyPtr, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_aes_key_wrap(size_t, RSAPublicKeyPtr, const std::vector&, const std::optional>&)
:project: CCF
-.. doxygenfunction:: crypto::ckm_rsa_aes_key_wrap(size_t, const Pem&, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_aes_key_wrap(size_t, const Pem&, const std::vector&, const std::optional>&)
:project: CCF
-.. doxygenfunction:: crypto::ckm_rsa_aes_key_unwrap(RSAKeyPairPtr, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_aes_key_unwrap(RSAKeyPairPtr, const std::vector&, const std::optional>&)
:project: CCF
-.. doxygenfunction:: crypto::ckm_rsa_aes_key_unwrap(const Pem&, const std::vector&, const std::optional>&)
+.. doxygenfunction:: ccf::crypto::ckm_rsa_aes_key_unwrap(const Pem&, const std::vector&, const std::optional>&)
:project: CCF
\ No newline at end of file
diff --git a/doc/build_apps/example_cpp.rst b/doc/build_apps/example_cpp.rst
index 9cc5f748bde2..cf06f4b352d0 100644
--- a/doc/build_apps/example_cpp.rst
+++ b/doc/build_apps/example_cpp.rst
@@ -19,7 +19,7 @@ The Logging example application simply has:
.. note::
- :cpp:type:`kv::Map` tables are the only interface between CCF and the replicated application, and the sole mechanism for it to have distributed state.
+ :cpp:type:`ccf::kv::Map` tables are the only interface between CCF and the replicated application, and the sole mechanism for it to have distributed state.
The Logging application keeps its state in a pair of tables, one containing private encrypted logs and the other containing public unencrypted logs. Their type is defined as:
@@ -46,7 +46,7 @@ The Logging example application simply has:
Application Endpoints
~~~~~~~~~~~~~~~~~~~~~
-The implementation of :cpp:func:`ccfapp::make_user_endpoints()` should return a subclass of :cpp:class:`ccf::endpoints::EndpointRegistry`, containing the endpoints that constitute the app.
+The implementation of :cpp:func:`ccf::make_user_endpoints()` should return a subclass of :cpp:class:`ccf::endpoints::EndpointRegistry`, containing the endpoints that constitute the app.
.. literalinclude:: ../../samples/apps/logging/logging.cpp
:language: cpp
@@ -54,7 +54,7 @@ The implementation of :cpp:func:`ccfapp::make_user_endpoints()` should return a
:lines: 1
:dedent:
-The logging app defines :cpp:class:`ccfapp::LoggerHandlers`, which creates and installs handler functions or lambdas for several different HTTP endpoints. Each of these functions takes as input the details of the current request (such as the URI which was called, the query string, the request body), interacts with the KV tables using the given :cpp:class:`kv::Tx` object, and returns a result:
+The logging app defines :cpp:class:`ccf::LoggerHandlers`, which creates and installs handler functions or lambdas for several different HTTP endpoints. Each of these functions takes as input the details of the current request (such as the URI which was called, the query string, the request body), interacts with the KV tables using the given :cpp:class:`ccf::kv::Tx` object, and returns a result:
.. literalinclude:: ../../samples/apps/logging/logging.cpp
:language: cpp
diff --git a/doc/build_apps/kv/api.rst b/doc/build_apps/kv/api.rst
index e498bcb6d4fc..7bcfba652fbb 100644
--- a/doc/build_apps/kv/api.rst
+++ b/doc/build_apps/kv/api.rst
@@ -3,84 +3,84 @@ Key-Value Store API
This page presents the API that a CCF application must use to access and mutate the replicated key-value store.
-A CCF application should store its data in one or more :cpp:type:`kv::Map`. The name, type, and serialisation of these maps is under the application's control. Each invocation of an :cpp:class:`ccf::EndpointRegistry::Endpoint` is given a :cpp:class:`kv::Tx` transaction object, through which it can read and write to its :cpp:type:`kv::Map`.
+A CCF application should store its data in one or more :cpp:type:`ccf::kv::Map`. The name, type, and serialisation of these maps is under the application's control. Each invocation of an :cpp:class:`ccf::EndpointRegistry::Endpoint` is given a :cpp:class:`ccf::kv::Tx` transaction object, through which it can read and write to its :cpp:type:`ccf::kv::Map`.
Map
---
-.. doxygentypedef:: kv::Version
+.. doxygentypedef:: ccf::kv::Version
:project: CCF
-.. doxygenvariable:: kv::NoVersion
+.. doxygenvariable:: ccf::kv::NoVersion
:project: CCF
-.. doxygenclass:: kv::TypedMap
+.. doxygenclass:: ccf::kv::TypedMap
:project: CCF
-.. doxygentypedef:: kv::Map
+.. doxygentypedef:: ccf::kv::Map
:project: CCF
-.. doxygenclass:: kv::TypedValue
+.. doxygenclass:: ccf::kv::TypedValue
:project: CCF
-.. doxygentypedef:: kv::Value
+.. doxygentypedef:: ccf::kv::Value
:project: CCF
-.. doxygenclass:: kv::TypedSet
+.. doxygenclass:: ccf::kv::TypedSet
:project: CCF
-.. doxygentypedef:: kv::Set
+.. doxygentypedef:: ccf::kv::Set
:project: CCF
Transaction
-----------
-.. doxygenclass:: kv::ReadOnlyTx
+.. doxygenclass:: ccf::kv::ReadOnlyTx
:project: CCF
:members: ro
-.. doxygenclass:: kv::Tx
+.. doxygenclass:: ccf::kv::Tx
:project: CCF
:members: rw, wo
Handles
-------
-.. doxygenclass:: kv::ReadableMapHandle
+.. doxygenclass:: ccf::kv::ReadableMapHandle
:project: CCF
:members:
-.. doxygenclass:: kv::WriteableMapHandle
+.. doxygenclass:: ccf::kv::WriteableMapHandle
:project: CCF
:members:
-.. doxygenclass:: kv::MapHandle
+.. doxygenclass:: ccf::kv::MapHandle
:project: CCF
-.. doxygenclass:: kv::ReadableValueHandle
+.. doxygenclass:: ccf::kv::ReadableValueHandle
:project: CCF
:members:
-.. doxygenclass:: kv::WriteableValueHandle
+.. doxygenclass:: ccf::kv::WriteableValueHandle
:project: CCF
:members:
-.. doxygenclass:: kv::ValueHandle
+.. doxygenclass:: ccf::kv::ValueHandle
:project: CCF
-.. doxygenclass:: kv::ReadableSetHandle
+.. doxygenclass:: ccf::kv::ReadableSetHandle
:project: CCF
:members:
-.. doxygenclass:: kv::WriteableSetHandle
+.. doxygenclass:: ccf::kv::WriteableSetHandle
:project: CCF
:members:
-.. doxygenclass:: kv::SetHandle
+.. doxygenclass:: ccf::kv::SetHandle
:project: CCF
Serialisation
-------------
-.. doxygenenum:: kv::EntryType
+.. doxygenenum:: ccf::kv::EntryType
:project: CCF
\ No newline at end of file
diff --git a/doc/build_apps/kv/kv_how_to.rst b/doc/build_apps/kv/kv_how_to.rst
index f97570189602..1667454fac06 100644
--- a/doc/build_apps/kv/kv_how_to.rst
+++ b/doc/build_apps/kv/kv_how_to.rst
@@ -1,70 +1,70 @@
Key-Value Store How-To
======================
-The `Key-Value Store` (KV) consists of a set of :cpp:type:`kv::Map` objects that are available to the endpoints of an application. Endpoint handlers create handles which allow them to read and write from these :cpp:type:`kv::Map` objects. The framework handles conflicts between concurrent execution of multiple transactions, and produces a consistent order of transactions which is replicated between nodes, allowing the entries to be read from multiple nodes. This page outlines the core concepts and C++ APIs used to interact with the KV.
+The `Key-Value Store` (KV) consists of a set of :cpp:type:`ccf::kv::Map` objects that are available to the endpoints of an application. Endpoint handlers create handles which allow them to read and write from these :cpp:type:`ccf::kv::Map` objects. The framework handles conflicts between concurrent execution of multiple transactions, and produces a consistent order of transactions which is replicated between nodes, allowing the entries to be read from multiple nodes. This page outlines the core concepts and C++ APIs used to interact with the KV.
Map Naming
----------
-A :cpp:type:`kv::Map` (often referred to as a `Table`) is a collection of key-value pairs of a given type. The :cpp:type:`kv::Map` itself is identified by its name, which is used to lookup the map :cpp:type:`kv::Map` from the local store during a transaction.
+A :cpp:type:`ccf::kv::Map` (often referred to as a `Table`) is a collection of key-value pairs of a given type. The :cpp:type:`ccf::kv::Map` itself is identified by its name, which is used to lookup the map :cpp:type:`ccf::kv::Map` from the local store during a transaction.
-If a :cpp:type:`kv::Map` with the given name did not previously exist, it will be created in this transaction.
+If a :cpp:type:`ccf::kv::Map` with the given name did not previously exist, it will be created in this transaction.
-A :cpp:type:`kv::Map` can either be created as private (default) or public. Public map's names begin with a ``public:`` prefix, any any other name indicates a private map. For instance the name ``public:foo`` to a public map, while ``foo`` refers to a private map. Transactions on private maps are written to the ledger in encrypted form and can only be decrypted in the enclave of nodes that have joined the network. Transactions on public maps are written to the ledger as plaintext and can be read from outside the enclave; only their integrity is protected. The security domain of a map (public or private) cannot be changed after its creation, since this is encoded in the map's name. Public and private maps with similar names in different domains are distinct; writes to ``public:foo`` have no impact on ``foo``, and vice versa.
+A :cpp:type:`ccf::kv::Map` can either be created as private (default) or public. Public map's names begin with a ``public:`` prefix, any any other name indicates a private map. For instance the name ``public:foo`` to a public map, while ``foo`` refers to a private map. Transactions on private maps are written to the ledger in encrypted form and can only be decrypted in the enclave of nodes that have joined the network. Transactions on public maps are written to the ledger as plaintext and can be read from outside the enclave; only their integrity is protected. The security domain of a map (public or private) cannot be changed after its creation, since this is encoded in the map's name. Public and private maps with similar names in different domains are distinct; writes to ``public:foo`` have no impact on ``foo``, and vice versa.
Some table names are reserved for governance of a CCF service and cannot be modified by application code. For more information, see :doc:`/audit/read_write_restrictions`.
Transaction Semantics
---------------------
-A transaction (:cpp:class:`kv::Tx`) encapsulates an individual endpoint invocation's atomic interaction with the KV. Transactions may read from and write to multiple :cpp:type:`kv::Map`, and each is automatically ordered, applied, serialised, and committed by the framework.
+A transaction (:cpp:class:`ccf::kv::Tx`) encapsulates an individual endpoint invocation's atomic interaction with the KV. Transactions may read from and write to multiple :cpp:type:`ccf::kv::Map`, and each is automatically ordered, applied, serialised, and committed by the framework.
-A reference to a new :cpp:class:`kv::Tx` is passed to each endpoint handler, and used to interact with the KV.
+A reference to a new :cpp:class:`ccf::kv::Tx` is passed to each endpoint handler, and used to interact with the KV.
-Each :cpp:class:`kv::Tx` gets a consistent, opaque view of the KV, including the values which have been left by previous writes. Any writes produced by this transaction will be visible to all future transactions.
+Each :cpp:class:`ccf::kv::Tx` gets a consistent, opaque view of the KV, including the values which have been left by previous writes. Any writes produced by this transaction will be visible to all future transactions.
-When the endpoint handler indicates that its :cpp:class:`kv::Tx` should be applied (see :ref:`this section ` for details), the executing node attempts to apply the changes to its local KV. If this produces conflicts with concurrently executing transactions, it will be automatically re-executed. Once the transaction is applied successfully, it is automatically replicated to other nodes and will, if the network is healthy, eventually be committed.
+When the endpoint handler indicates that its :cpp:class:`ccf::kv::Tx` should be applied (see :ref:`this section ` for details), the executing node attempts to apply the changes to its local KV. If this produces conflicts with concurrently executing transactions, it will be automatically re-executed. Once the transaction is applied successfully, it is automatically replicated to other nodes and will, if the network is healthy, eventually be committed.
-For each :cpp:type:`kv::Map` that a transaction wants to write to or read from, a :cpp:class:`kv::MapHandle` must first be acquired. These are acquired from the :cpp:func:`kv::Tx::rw` (`read-write`) method. These may be acquired either by name (in which case the desired type must be explicitly specified as a template parameter), or by using a :cpp:type:`kv::Map` instance which defines both the map's name and key-value types.
+For each :cpp:type:`ccf::kv::Map` that a transaction wants to write to or read from, a :cpp:class:`ccf::kv::MapHandle` must first be acquired. These are acquired from the :cpp:func:`ccf::kv::Tx::rw` (`read-write`) method. These may be acquired either by name (in which case the desired type must be explicitly specified as a template parameter), or by using a :cpp:type:`ccf::kv::Map` instance which defines both the map's name and key-value types.
By name:
.. code-block:: cpp
// Handle for map1
- auto map1_handle = tx.rw>("map1");
+ auto map1_handle = tx.rw>("map1");
// Handles for 2 other maps, one public and one private, with different types
- auto map2_handle = tx.rw>("public:map2");
- auto map3_handle = tx.rw>("map3");
+ auto map2_handle = tx.rw>("public:map2");
+ auto map3_handle = tx.rw>("map3");
-By :cpp:type:`kv::Map`:
+By :cpp:type:`ccf::kv::Map`:
.. code-block:: cpp
- kv::Map map_priv("map1");
+ ccf::kv::Map map_priv("map1");
auto map1_handle = tx.rw(map_priv);
- kv::Map map_pub("public:map2");
+ ccf::kv::Map map_pub("public:map2");
auto map2_handle = tx.rw(map_pub);
- kv::Map map_priv_int("map3");
+ ccf::kv::Map map_priv_int("map3");
auto map3_handle = tx.rw(map_priv_int);
The latter approach introduces a named binding between the map's name and the types of its keys and values, reducing the chance for errors where code attempts to read a map with the wrong type.
-.. note:: As mentioned above, there is no need to explicitly declare a :cpp:type:`kv::Map` before it is used. The first write to a :cpp:type:`kv::Map` implicitly creates it in the underlying KV. Within a transaction, a newly created :cpp:type:`kv::Map` behaves exactly the same as an existing :cpp:type:`kv::Map` with no keys - the framework views these as semantically identical, and offers no way for the application logic to tell them apart. Any writes to a newly created :cpp:type:`kv::Map` will be persisted when the transaction commits, and future transactions will be able to access this :cpp:type:`kv::Map` by name to read those writes.
+.. note:: As mentioned above, there is no need to explicitly declare a :cpp:type:`ccf::kv::Map` before it is used. The first write to a :cpp:type:`ccf::kv::Map` implicitly creates it in the underlying KV. Within a transaction, a newly created :cpp:type:`ccf::kv::Map` behaves exactly the same as an existing :cpp:type:`ccf::kv::Map` with no keys - the framework views these as semantically identical, and offers no way for the application logic to tell them apart. Any writes to a newly created :cpp:type:`ccf::kv::Map` will be persisted when the transaction commits, and future transactions will be able to access this :cpp:type:`ccf::kv::Map` by name to read those writes.
Accessing Map content via a Handle
----------------------------------
-Once a :cpp:class:`kv::MapHandle` on a specific :cpp:type:`kv::Map` has been obtained, it is possible to:
+Once a :cpp:class:`ccf::kv::MapHandle` on a specific :cpp:type:`ccf::kv::Map` has been obtained, it is possible to:
-- test (:cpp:func:`kv::ReadableMapHandle::has`) whether a key has any associated value;
-- read (:cpp:func:`kv::ReadableMapHandle::get`) the value associated with a key;
-- write (:cpp:func:`kv::WriteableMapHandle::put`) a new value for a key;
-- delete (:cpp:func:`kv::WriteableMapHandle::remove`) a key and its current value;
-- iterate (:cpp:func:`kv::ReadableMapHandle::foreach`) through all key-value pairs.
+- test (:cpp:func:`ccf::kv::ReadableMapHandle::has`) whether a key has any associated value;
+- read (:cpp:func:`ccf::kv::ReadableMapHandle::get`) the value associated with a key;
+- write (:cpp:func:`ccf::kv::WriteableMapHandle::put`) a new value for a key;
+- delete (:cpp:func:`ccf::kv::WriteableMapHandle::remove`) a key and its current value;
+- iterate (:cpp:func:`ccf::kv::ReadableMapHandle::foreach`) through all key-value pairs.
.. code-block:: cpp
@@ -91,7 +91,7 @@ Once a :cpp:class:`kv::MapHandle` on a specific :cpp:type:`kv::Map` has been obt
Read/Write safety
-----------------
-If you are only reading from or only writing to a given :cpp:type:`kv::Map` you can retrieve a `read-only` or `write-only` handle for it. This will turn unexpected reads/writes (which would introduce unintended dependencies between transactions) into compile-time errors. Instead of calling :cpp:func:`kv::Tx::rw` to get a handle which can both read and write, you can call :cpp:func:`kv::ReadOnlyTx::ro` to acquire a `read-only` handle or :cpp:func:`kv::Tx::wo` to acquire a `write-only` handle.
+If you are only reading from or only writing to a given :cpp:type:`ccf::kv::Map` you can retrieve a `read-only` or `write-only` handle for it. This will turn unexpected reads/writes (which would introduce unintended dependencies between transactions) into compile-time errors. Instead of calling :cpp:func:`ccf::kv::Tx::rw` to get a handle which can both read and write, you can call :cpp:func:`ccf::kv::ReadOnlyTx::ro` to acquire a `read-only` handle or :cpp:func:`ccf::kv::Tx::wo` to acquire a `write-only` handle.
.. code-block:: cpp
@@ -122,7 +122,7 @@ Note that, as in the sample above, it is possible to acquire different kinds of
Removing a key
--------------
-If a Key-Value pair was written to a :cpp:type:`kv::Map` by a previous :cpp:class:`kv::Tx`, it is possible to delete this key. Because of the append-only nature of the KV, this Key-Value pair is not actually removed from the :cpp:type:`kv::Map` but instead explicitly marked as deleted in the version that the deleting :cpp:class:`kv::Tx` is applied at.
+If a Key-Value pair was written to a :cpp:type:`ccf::kv::Map` by a previous :cpp:class:`ccf::kv::Tx`, it is possible to delete this key. Because of the append-only nature of the KV, this Key-Value pair is not actually removed from the :cpp:type:`ccf::kv::Map` but instead explicitly marked as deleted in the version that the deleting :cpp:class:`ccf::kv::Tx` is applied at.
.. code-block:: cpp
@@ -141,7 +141,7 @@ Global commit
A transaction is automatically (globally) committed once the consensus protocol has established that a majority of nodes in the CCF network have successfully received and acknowledged that transaction. To operate on durable state, an application may want to query the globally committed state rather than the *current* state of the KV.
-The :cpp:func:`kv::MapHandle::get_globally_committed` member function returns the value of a key that we know has been globally committed.
+The :cpp:func:`ccf::kv::MapHandle::get_globally_committed` member function returns the value of a key that we know has been globally committed.
.. code-block:: cpp
@@ -166,9 +166,9 @@ Miscellaneous
``foreach()``
~~~~~~~~~~~~~
-Values can only be retrieved directly (:cpp:func:`kv::MapHandle::get`) for a given target key. However, it is sometimes necessary to access unknown keys, or to iterate through all Key-Value pairs.
+Values can only be retrieved directly (:cpp:func:`ccf::kv::MapHandle::get`) for a given target key. However, it is sometimes necessary to access unknown keys, or to iterate through all Key-Value pairs.
-CCF offers a member function :cpp:func:`kv::MapHandle::foreach` to iterate over all the elements written to that :cpp:type:`kv::Map` so far, and run a lambda function for each Key-Value pair. Note that a :cpp:class:`kv::MapHandle::foreach` loop can be ended early by returning ``false`` from this lambda, while ``true`` should be returned to continue iteration.
+CCF offers a member function :cpp:func:`ccf::kv::MapHandle::foreach` to iterate over all the elements written to that :cpp:type:`ccf::kv::Map` so far, and run a lambda function for each Key-Value pair. Note that a :cpp:class:`ccf::kv::MapHandle::foreach` loop can be ended early by returning ``false`` from this lambda, while ``true`` should be returned to continue iteration.
.. code-block:: cpp
@@ -192,7 +192,7 @@ CCF offers a member function :cpp:func:`kv::MapHandle::foreach` to iterate over
Applying and reverting writes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Changes to the KV are made by atomic transactions. For a given :cpp:class:`kv::Tx`, either all of its writes are applied, or none are. Only applied writes are replicated and may be globally committed. Transactions may be abandoned without applying their writes - their changes will never be seen by other transactions.
+Changes to the KV are made by atomic transactions. For a given :cpp:class:`ccf::kv::Tx`, either all of its writes are applied, or none are. Only applied writes are replicated and may be globally committed. Transactions may be abandoned without applying their writes - their changes will never be seen by other transactions.
By default CCF decides which transactions are successful (so should be applied to the persistent store) by looking at the status code contained in the response: all transactions producing ``2xx`` status codes will be applied, while any other status code will be treated as an error and will `not` be applied to the persistent store. If this behaviour is not desired, for instance when an app wants to log incoming requests even though they produce an error, then it can be dynamically overridden by explicitly telling CCF whether it should apply a given transaction:
diff --git a/doc/build_apps/kv/kv_serialisation.rst b/doc/build_apps/kv/kv_serialisation.rst
index ace926c4d064..9f2c0aa69cd8 100644
--- a/doc/build_apps/kv/kv_serialisation.rst
+++ b/doc/build_apps/kv/kv_serialisation.rst
@@ -1,14 +1,14 @@
Key-Value Serialisation
=======================
-Every transaction executed by the primary on its Key-Value store is serialised before being replicated to all backups of the CCF network and written to the ledger. The serialisation format is defined per :cpp:type:`kv::Map` and distinctly for the key and value types.
+Every transaction executed by the primary on its Key-Value store is serialised before being replicated to all backups of the CCF network and written to the ledger. The serialisation format is defined per :cpp:type:`ccf::kv::Map` and distinctly for the key and value types.
-.. tip:: Selecting the right serialision format for a KV map depends on the application logic but is generally a trade-off between performance and auditability of the ledger. For example, the default serialisation format for :cpp:type:`kv::Map` is JSON and allows for easy parsing of transactions in the `public` ledger. For more performance sensitive use cases, apps may define or use their own serialisers.
+.. tip:: Selecting the right serialision format for a KV map depends on the application logic but is generally a trade-off between performance and auditability of the ledger. For example, the default serialisation format for :cpp:type:`ccf::kv::Map` is JSON and allows for easy parsing of transactions in the `public` ledger. For more performance sensitive use cases, apps may define or use their own serialisers.
Custom key and value types
--------------------------
-User-defined types can be used for both the key and value types of a :cpp:type:`kv::Map`. It must be possible to use the key type as the key of an ``std::map`` (so it must be copyable, assignable, and less-comparable), and both types must be serialisable. By default, when using a :cpp:type:`kv::Map`, serialisation converts to JSON. To add support to your custom types, it should usually be possible to use the ``DECLARE_JSON_...`` macros:
+User-defined types can be used for both the key and value types of a :cpp:type:`ccf::kv::Map`. It must be possible to use the key type as the key of an ``std::map`` (so it must be copyable, assignable, and less-comparable), and both types must be serialisable. By default, when using a :cpp:type:`ccf::kv::Map`, serialisation converts to JSON. To add support to your custom types, it should usually be possible to use the ``DECLARE_JSON_...`` macros:
.. literalinclude:: ../../../src/kv/test/kv_serialisation.cpp
:language: cpp
@@ -22,7 +22,7 @@ Custom serialisers can also be defined. The serialiser itself must be a type imp
:start-after: SNIPPET_START: CustomSerialiser definition
:end-before: SNIPPET_END: CustomSerialiser definition
-To use these serialised for a specific map declare the map as a :cpp:class:`kv::TypedMap`, adding the appropriate serialiser types for the key and value types:
+To use these serialised for a specific map declare the map as a :cpp:class:`ccf::kv::TypedMap`, adding the appropriate serialiser types for the key and value types:
.. literalinclude:: ../../../src/kv/test/kv_serialisation.cpp
:language: cpp
diff --git a/doc/build_apps/migration_4_x_to_5_0.rst b/doc/build_apps/migration_4_x_to_5_0.rst
index 23e8d467265f..5fe99db9c543 100644
--- a/doc/build_apps/migration_4_x_to_5_0.rst
+++ b/doc/build_apps/migration_4_x_to_5_0.rst
@@ -117,3 +117,48 @@ The default value for both is ``ToPrimary``/``"to_primary"``, meaning that all r
- ``ToPrimary`` / ``"to_primary"``
While ``Never`` and ``Always`` have clear analogs in redirection, the session consistency-preserving ``Sometimes`` value is more complicated. All writes should be redirected to a primary, as attempting to execute them on a backup will result in an error. For reads, you may choose to redirect to retain simple consistency, but to support scaling (by reading on backups), we recommend you choose ``None`` for redirections. Where between-request consistency is a strong requirement, we recommend you enforce it at the application level (eg - ETags, request IDs, etc).
+
+ToBackup
+~~~~~~~~
+
+A third ``RedirectionStrategy`` exists named ``ToBackup`` (represented by ``"redirection_strategy": "to_backup"`` in ``app.json``). This is a mirror of the ``ToPrimary`` strategy - if such a request is processed by a node which is currently a primary, that node will produce a HTTP redirect response directing to a backup node. The choice of backup is arbitrary. The redirection address which is inserted can be configured per-node by the operator, in the ``redirections.to_backup`` object.
+
+For example, to redirect directly to a backup by their unique accessible hostname:
+
+.. code-block:: json
+
+ {
+ "network": {
+ "rpc_interfaces": {
+ "interface_name": {
+ "redirections": {
+ "to_backup": {
+ "kind": "NodeByRole",
+ "target": { "role": "backup" }
+ }
+ }
+ }
+ }
+ }
+ }
+
+To redirect to a static address (such as a load balancer):
+
+.. code-block:: json
+
+ {
+ "network": {
+ "rpc_interfaces": {
+ "interface_name": {
+ "redirections": {
+ "to_backup": {
+ "kind": "StaticAddress",
+ "target": {
+ "address": "backup.ccf.example.com"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
diff --git a/doc/host_config_schema/cchost_config.json b/doc/host_config_schema/cchost_config.json
index d273433048eb..c9993ee7d1f0 100644
--- a/doc/host_config_schema/cchost_config.json
+++ b/doc/host_config_schema/cchost_config.json
@@ -169,6 +169,10 @@
"to_primary": {
"$ref": "#/$defs/RedirectionResolver",
"description": "Configures how the Location header should be populated, when requests arrive on this interface that must be served by a primary while the receiving node is not a primary"
+ },
+ "to_backup": {
+ "$ref": "#/$defs/RedirectionResolver",
+ "description": "Configures how the Location header should be populated, when requests arrive on this interface that must be served by a backup while the receiving node is currently a primary"
}
},
"additionalProperties": false
@@ -724,7 +728,7 @@
"type": "object",
"properties": {
"role": {
- "enum": ["primary"],
+ "enum": ["primary", "backup"],
"default": "primary"
}
},
diff --git a/doc/overview/glossary.rst b/doc/overview/glossary.rst
index ebdc7e015329..72016a58b34a 100644
--- a/doc/overview/glossary.rst
+++ b/doc/overview/glossary.rst
@@ -79,7 +79,7 @@ Glossary
`Transport Layer Security `_ is an IETF cryptographic protocol standard designed to secure communications between a client and a server over a computer network.
Transaction ID
- Unique transaction identifier in CCF, composed of a View and a Sequence Number separated by a period. Sequence Numbers start from 1, and are contiguous. Views are monotonic. E.g. The transaction ID ``2.15`` indicates the View is ``2`` and the Sequence Number is ``15``. Sequence Numbers are also referred to as a :cpp:type:`kv::Version` in the context of the Key-Value store.
+ Unique transaction identifier in CCF, composed of a View and a Sequence Number separated by a period. Sequence Numbers start from 1, and are contiguous. Views are monotonic. E.g. The transaction ID ``2.15`` indicates the View is ``2`` and the Sequence Number is ``15``. Sequence Numbers are also referred to as a :cpp:type:`ccf::kv::Version` in the context of the Key-Value store.
Users
Directly interact with the application running in CCF. Their public identity should be voted in by members before they are allowed to issue requests.
diff --git a/doc/schemas/app_openapi.json b/doc/schemas/app_openapi.json
index e711e6655b81..f87cd88370f6 100644
--- a/doc/schemas/app_openapi.json
+++ b/doc/schemas/app_openapi.json
@@ -648,6 +648,46 @@
}
}
},
+ "/app/log/private/backup": {
+ "get": {
+ "parameters": [
+ {
+ "in": "query",
+ "name": "id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/uint64"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/LoggingGet__Out"
+ }
+ }
+ },
+ "description": "Default response description"
+ },
+ "default": {
+ "$ref": "#/components/responses/default"
+ }
+ },
+ "security": [
+ {
+ "jwt": []
+ },
+ {
+ "user_cose_sign1": []
+ }
+ ],
+ "x-ccf-forwarding": {
+ "$ref": "#/components/x-ccf-forwarding/sometimes"
+ }
+ }
+ },
"/app/log/private/committed": {
"get": {
"parameters": [
@@ -1079,6 +1119,46 @@
}
}
},
+ "/app/log/public/backup": {
+ "get": {
+ "parameters": [
+ {
+ "in": "query",
+ "name": "id",
+ "required": true,
+ "schema": {
+ "$ref": "#/components/schemas/uint64"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/LoggingGet__Out"
+ }
+ }
+ },
+ "description": "Default response description"
+ },
+ "default": {
+ "$ref": "#/components/responses/default"
+ }
+ },
+ "security": [
+ {
+ "jwt": []
+ },
+ {
+ "user_cose_sign1": []
+ }
+ ],
+ "x-ccf-forwarding": {
+ "$ref": "#/components/x-ccf-forwarding/sometimes"
+ }
+ }
+ },
"/app/log/public/count": {
"get": {
"responses": {
diff --git a/doc/schemas/gov_openapi.json b/doc/schemas/gov_openapi.json
index 9ce989aa261c..855144deeb4a 100644
--- a/doc/schemas/gov_openapi.json
+++ b/doc/schemas/gov_openapi.json
@@ -645,6 +645,22 @@
},
"redirections": {
"properties": {
+ "to_backup": {
+ "properties": {
+ "kind": {
+ "enum": [
+ "NodeByRole",
+ "StaticAddress"
+ ],
+ "type": "string"
+ },
+ "target": {}
+ },
+ "required": [
+ "kind"
+ ],
+ "type": "object"
+ },
"to_primary": {
"properties": {
"kind": {
@@ -768,6 +784,22 @@
},
"redirections": {
"properties": {
+ "to_backup": {
+ "properties": {
+ "kind": {
+ "enum": [
+ "NodeByRole",
+ "StaticAddress"
+ ],
+ "type": "string"
+ },
+ "target": {}
+ },
+ "required": [
+ "kind"
+ ],
+ "type": "object"
+ },
"to_primary": {
"properties": {
"kind": {
@@ -968,7 +1000,8 @@
"RedirectionStrategy": {
"enum": [
"none",
- "to_primary"
+ "to_primary",
+ "to_backup"
],
"type": "string"
},
diff --git a/doc/schemas/node_openapi.json b/doc/schemas/node_openapi.json
index 6ad3058a4009..53602354c9d4 100644
--- a/doc/schemas/node_openapi.json
+++ b/doc/schemas/node_openapi.json
@@ -552,6 +552,9 @@
},
"NodeInfoNetwork_v2__NetInterface__Redirections": {
"properties": {
+ "to_backup": {
+ "$ref": "#/components/schemas/RedirectionResolverConfig"
+ },
"to_primary": {
"$ref": "#/components/schemas/RedirectionResolverConfig"
}
diff --git a/docker/ccf_ci_built b/docker/ccf_ci_built
index 95dd5807741f..4362f14b0428 100644
--- a/docker/ccf_ci_built
+++ b/docker/ccf_ci_built
@@ -4,7 +4,7 @@
# Latest image as of this change
ARG platform=sgx
-ARG base=ccfmsrc.azurecr.io/ccf/ci:oe-0.19.6-0-snp-clang-15
+ARG base=ccfmsrc.azurecr.io/ccf/ci:2024-06-26-snp-clang-15
FROM ${base}
# SSH. Note that this could (should) be done in the base ccf_ci image instead
diff --git a/getting_started/setup_vm/roles/openenclave/vars/common.yml b/getting_started/setup_vm/roles/openenclave/vars/common.yml
index b02747bb80b9..1d7f01c20215 100644
--- a/getting_started/setup_vm/roles/openenclave/vars/common.yml
+++ b/getting_started/setup_vm/roles/openenclave/vars/common.yml
@@ -1,6 +1,6 @@
-oe_ver: "0.19.6"
+oe_ver: "0.19.7"
# Usually the same, except for rc, where ver is -rc and ver_ is _rc
-oe_ver_: "0.19.6"
+oe_ver_: "0.19.7"
# Source install
workspace: "/tmp/"
diff --git a/include/ccf/app_interface.h b/include/ccf/app_interface.h
index f5c9ed702f9e..03498766c1ce 100644
--- a/include/ccf/app_interface.h
+++ b/include/ccf/app_interface.h
@@ -17,7 +17,7 @@ namespace ccf
class RpcFrontend;
}
-namespace kv
+namespace ccf::kv
{
class Store;
}
@@ -27,7 +27,7 @@ namespace ccf
class UserEndpointRegistry : public CommonEndpointRegistry
{
public:
- UserEndpointRegistry(ccfapp::AbstractNodeContext& context) :
+ UserEndpointRegistry(ccf::AbstractNodeContext& context) :
CommonEndpointRegistry(get_actor_prefix(ActorsType::users), context)
{}
@@ -48,7 +48,7 @@ namespace ccf
};
}
-namespace ccfapp
+namespace ccf
{
// SNIPPET_START: app_interface
/** To be implemented by the application. Creates a collection of endpoints
@@ -59,7 +59,7 @@ namespace ccfapp
* @return Unique pointer to the endpoint registry instance
*/
std::unique_ptr make_user_endpoints(
- ccfapp::AbstractNodeContext& context);
+ ccf::AbstractNodeContext& context);
/** To be implemented by the application.
*
diff --git a/include/ccf/base_endpoint_registry.h b/include/ccf/base_endpoint_registry.h
index 17487562b145..a1999d251167 100644
--- a/include/ccf/base_endpoint_registry.h
+++ b/include/ccf/base_endpoint_registry.h
@@ -63,6 +63,47 @@ namespace ccf
}
}
+ /** Lists possible reasons for an ApiResult::InvalidArgs being return in @c
+ * ccf::BaseEndpointRegistry
+ */
+ enum class InvalidArgsReason
+ {
+ NoReason = 0,
+ /** Views start at 1 (one) in CCF */
+ ViewSmallerThanOne,
+ /** Action has already been applied on this instance */
+ ActionAlreadyApplied,
+ /** Action created_at is older than the median of recent action */
+ StaleActionCreatedTimestamp,
+ };
+
+ constexpr char const* invalid_args_reason_to_str(InvalidArgsReason reason)
+ {
+ switch (reason)
+ {
+ case InvalidArgsReason::NoReason:
+ {
+ return "NoReason";
+ }
+ case InvalidArgsReason::ViewSmallerThanOne:
+ {
+ return "ViewSmallerThanOne";
+ }
+ case InvalidArgsReason::ActionAlreadyApplied:
+ {
+ return "ActionAlreadyApplied";
+ }
+ case InvalidArgsReason::StaleActionCreatedTimestamp:
+ {
+ return "StaleActionCreatedTimestamp";
+ }
+ default:
+ {
+ return "Unhandled InvalidArgsReason";
+ }
+ }
+ }
+
/** Extends the basic @ref ccf::endpoints::EndpointRegistry with helper API
* methods for retrieving core CCF properties.
*
@@ -79,11 +120,11 @@ namespace ccf
class BaseEndpointRegistry : public ccf::endpoints::EndpointRegistry
{
protected:
- ccfapp::AbstractNodeContext& context;
+ ccf::AbstractNodeContext& context;
public:
BaseEndpointRegistry(
- const std::string& method_prefix_, ccfapp::AbstractNodeContext& context_);
+ const std::string& method_prefix_, ccf::AbstractNodeContext& context_);
/** Get the history of the consensus view changes.
*
@@ -96,6 +137,19 @@ namespace ccf
ApiResult get_view_history_v1(
std::vector& history, ccf::View since = 1);
+ /** Get the history of the consensus view changes.
+ *
+ * Returns the history of view changes since the given view, which defaults
+ * to the start of time.
+ *
+ * A view change is characterised by the first sequence number in the new
+ * view.
+ */
+ ApiResult get_view_history_v2(
+ std::vector& history,
+ ccf::View since,
+ ccf::InvalidArgsReason& reason);
+
/** Get the status of a transaction by ID, provided as a view+seqno pair.
*
* Note that this value is the node's local understanding of the status
@@ -134,7 +188,7 @@ namespace ccf
* does not affect the OpenAPI version of the format of the document.
*/
ApiResult generate_openapi_document_v1(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::string& title,
const std::string& description,
const std::string& document_version,
@@ -143,7 +197,7 @@ namespace ccf
/** Get a quote attesting to the hardware this node is running on.
*/
ApiResult get_quote_for_this_node_v1(
- kv::ReadOnlyTx& tx, QuoteInfo& quote_info);
+ ccf::kv::ReadOnlyTx& tx, QuoteInfo& quote_info);
/** Get the id of the currently executing node.
*/
@@ -153,7 +207,7 @@ namespace ccf
* running on.
*/
ApiResult get_quotes_for_all_trusted_nodes_v1(
- kv::ReadOnlyTx& tx, std::map& quotes);
+ ccf::kv::ReadOnlyTx& tx, std::map& quotes);
/** Get the view associated with a given seqno, to construct a valid TxID.
*/
@@ -162,26 +216,30 @@ namespace ccf
/** Get the user data associated with a given user id.
*/
ApiResult get_user_data_v1(
- kv::ReadOnlyTx& tx, const UserId& user_id, nlohmann::json& user_data);
+ ccf::kv::ReadOnlyTx& tx,
+ const UserId& user_id,
+ nlohmann::json& user_data);
/** Get the member data associated with a given member id.
*/
ApiResult get_member_data_v1(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const MemberId& member_id,
nlohmann::json& member_data);
/** Get the certificate (PEM) of a given user id.
*/
ApiResult get_user_cert_v1(
- kv::ReadOnlyTx& tx, const UserId& user_id, crypto::Pem& user_cert_pem);
+ ccf::kv::ReadOnlyTx& tx,
+ const UserId& user_id,
+ ccf::crypto::Pem& user_cert_pem);
/** Get the certificate (PEM) of a given member id.
*/
ApiResult get_member_cert_v1(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const MemberId& member_id,
- crypto::Pem& member_cert_pem);
+ ccf::crypto::Pem& member_cert_pem);
/** Get untrusted time from the host of the currently executing node.
*/
diff --git a/include/ccf/claims_digest.h b/include/ccf/claims_digest.h
index 6eb6de405f4f..005c9707f1ba 100644
--- a/include/ccf/claims_digest.h
+++ b/include/ccf/claims_digest.h
@@ -9,7 +9,7 @@ namespace ccf
class ClaimsDigest
{
public:
- using Digest = crypto::Sha256Hash;
+ using Digest = ccf::crypto::Sha256Hash;
private:
bool is_set = false;
diff --git a/include/ccf/common_endpoint_registry.h b/include/ccf/common_endpoint_registry.h
index a9dffa4c7feb..377baf311628 100644
--- a/include/ccf/common_endpoint_registry.h
+++ b/include/ccf/common_endpoint_registry.h
@@ -16,7 +16,7 @@ namespace ccf
{
public:
CommonEndpointRegistry(
- const std::string& method_prefix_, ccfapp::AbstractNodeContext& context_);
+ const std::string& method_prefix_, ccf::AbstractNodeContext& context_);
void init_handlers() override;
diff --git a/include/ccf/crypto/base64.h b/include/ccf/crypto/base64.h
index 19175df8106f..f145ee770772 100644
--- a/include/ccf/crypto/base64.h
+++ b/include/ccf/crypto/base64.h
@@ -5,7 +5,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
std::vector raw_from_b64(const std::string_view& b64_string);
diff --git a/include/ccf/crypto/cose_verifier.h b/include/ccf/crypto/cose_verifier.h
index 0d30c270a413..e4d403661912 100644
--- a/include/ccf/crypto/cose_verifier.h
+++ b/include/ccf/crypto/cose_verifier.h
@@ -9,7 +9,7 @@
#include
-namespace crypto
+namespace ccf::crypto
{
class COSEVerifier
{
diff --git a/include/ccf/crypto/curve.h b/include/ccf/crypto/curve.h
index 77151db53bba..088dd2c6946d 100644
--- a/include/ccf/crypto/curve.h
+++ b/include/ccf/crypto/curve.h
@@ -11,7 +11,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
// SNIPPET_START: supported_curves
enum class CurveID
diff --git a/include/ccf/crypto/ecdsa.h b/include/ccf/crypto/ecdsa.h
index 57066a9510e7..e61b3ad24b74 100644
--- a/include/ccf/crypto/ecdsa.h
+++ b/include/ccf/crypto/ecdsa.h
@@ -6,7 +6,7 @@
#include
-namespace crypto
+namespace ccf::crypto
{
/** Converts R and S signature parameters to RFC 3279 DER
* encoding.
diff --git a/include/ccf/crypto/eddsa_key_pair.h b/include/ccf/crypto/eddsa_key_pair.h
index 3eab20ee690f..d1e7008a4000 100644
--- a/include/ccf/crypto/eddsa_key_pair.h
+++ b/include/ccf/crypto/eddsa_key_pair.h
@@ -16,7 +16,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class EdDSAKeyPair
{
diff --git a/include/ccf/crypto/eddsa_public_key.h b/include/ccf/crypto/eddsa_public_key.h
index 588777aa433d..628fae63f7b6 100644
--- a/include/ccf/crypto/eddsa_public_key.h
+++ b/include/ccf/crypto/eddsa_public_key.h
@@ -10,7 +10,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class EdDSAPublicKey
{
diff --git a/include/ccf/crypto/entropy.h b/include/ccf/crypto/entropy.h
index 7641627d941f..33d03ca638a4 100644
--- a/include/ccf/crypto/entropy.h
+++ b/include/ccf/crypto/entropy.h
@@ -27,7 +27,7 @@
// issue.`
#define RDRAND_RETRIES 10
-namespace crypto
+namespace ccf::crypto
{
using rng_func_t = int (*)(void* ctx, unsigned char* output, size_t len);
diff --git a/include/ccf/crypto/hash_bytes.h b/include/ccf/crypto/hash_bytes.h
index 015156a5f075..939ee3a765df 100644
--- a/include/ccf/crypto/hash_bytes.h
+++ b/include/ccf/crypto/hash_bytes.h
@@ -5,7 +5,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
using HashBytes = std::vector;
}
\ No newline at end of file
diff --git a/include/ccf/crypto/hash_provider.h b/include/ccf/crypto/hash_provider.h
index 55c5f425e0c3..c767fe8438d7 100644
--- a/include/ccf/crypto/hash_provider.h
+++ b/include/ccf/crypto/hash_provider.h
@@ -11,7 +11,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class HashProvider
{
diff --git a/include/ccf/crypto/hkdf.h b/include/ccf/crypto/hkdf.h
index d2b2a438c86a..47fcb8da00a2 100644
--- a/include/ccf/crypto/hkdf.h
+++ b/include/ccf/crypto/hkdf.h
@@ -7,7 +7,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
/** Perform HKDF key derivation */
std::vector hkdf(
diff --git a/include/ccf/crypto/hmac.h b/include/ccf/crypto/hmac.h
index d96da1aec1d5..8efe0896c506 100644
--- a/include/ccf/crypto/hmac.h
+++ b/include/ccf/crypto/hmac.h
@@ -5,7 +5,7 @@
#include "ccf/crypto/hash_bytes.h"
#include "ccf/crypto/md_type.h"
-namespace crypto
+namespace ccf::crypto
{
/** Compute the HMAC of @p key and @p data
*/
diff --git a/include/ccf/crypto/jwk.h b/include/ccf/crypto/jwk.h
index 42556572a4d0..926740a4eb4e 100644
--- a/include/ccf/crypto/jwk.h
+++ b/include/ccf/crypto/jwk.h
@@ -8,7 +8,7 @@
#include
-namespace crypto
+namespace ccf::crypto
{
enum class JsonWebKeyType
{
diff --git a/include/ccf/crypto/key_pair.h b/include/ccf/crypto/key_pair.h
index c8dae8e27a12..cda9710be53e 100644
--- a/include/ccf/crypto/key_pair.h
+++ b/include/ccf/crypto/key_pair.h
@@ -13,7 +13,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class KeyPair
{
diff --git a/include/ccf/crypto/key_wrap.h b/include/ccf/crypto/key_wrap.h
index b6acc0cfb6ef..bda51b22cc4b 100644
--- a/include/ccf/crypto/key_wrap.h
+++ b/include/ccf/crypto/key_wrap.h
@@ -9,7 +9,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
/// PKCS11 2.1.8 CKM_RSA_PKCS_OAEP wrap
/// @param wrapping_key The wrapping (encryption) key
diff --git a/include/ccf/crypto/md_type.h b/include/ccf/crypto/md_type.h
index fd7008ea91bc..8462cb35926e 100644
--- a/include/ccf/crypto/md_type.h
+++ b/include/ccf/crypto/md_type.h
@@ -4,7 +4,7 @@
#include "ccf/ds/json.h"
-namespace crypto
+namespace ccf::crypto
{
enum class MDType
{
diff --git a/include/ccf/crypto/pem.h b/include/ccf/crypto/pem.h
index ef7ba7a6c8b6..f0bd6debef68 100644
--- a/include/ccf/crypto/pem.h
+++ b/include/ccf/crypto/pem.h
@@ -11,7 +11,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
// Convenience class ensuring null termination of PEM-encoded certificates
class Pem
@@ -139,11 +139,11 @@ namespace crypto
return "Pem";
}
- static std::vector split_x509_cert_bundle(
+ static std::vector split_x509_cert_bundle(
const std::string_view& pem)
{
std::string separator("-----END CERTIFICATE-----");
- std::vector pems;
+ std::vector pems;
auto separator_end = 0;
auto next_separator_start = pem.find(separator);
while (next_separator_start != std::string_view::npos)
@@ -165,9 +165,9 @@ namespace crypto
namespace std
{
template <>
- struct hash
+ struct hash
{
- size_t operator()(const crypto::Pem& pem) const
+ size_t operator()(const ccf::crypto::Pem& pem) const
{
return std::hash()(pem.str());
}
diff --git a/include/ccf/crypto/public_key.h b/include/ccf/crypto/public_key.h
index 6a205be67938..a2116c862a4c 100644
--- a/include/ccf/crypto/public_key.h
+++ b/include/ccf/crypto/public_key.h
@@ -13,7 +13,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class PublicKey
{
diff --git a/include/ccf/crypto/rsa_key_pair.h b/include/ccf/crypto/rsa_key_pair.h
index e3ba6b93f60f..ac0f9eca6cf1 100644
--- a/include/ccf/crypto/rsa_key_pair.h
+++ b/include/ccf/crypto/rsa_key_pair.h
@@ -12,7 +12,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class RSAKeyPair
{
diff --git a/include/ccf/crypto/rsa_public_key.h b/include/ccf/crypto/rsa_public_key.h
index fe265dd0e983..d37463da9447 100644
--- a/include/ccf/crypto/rsa_public_key.h
+++ b/include/ccf/crypto/rsa_public_key.h
@@ -10,7 +10,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
class RSAPublicKey
{
diff --git a/include/ccf/crypto/san.h b/include/ccf/crypto/san.h
index ee10739ba964..aa20a48a970d 100644
--- a/include/ccf/crypto/san.h
+++ b/include/ccf/crypto/san.h
@@ -9,7 +9,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
static const std::string IP_ADDRESS_PREFIX = "iPAddress:";
static const std::string DNS_NAME_PREFIX = "dNSName:";
@@ -56,7 +56,7 @@ namespace crypto
FMT_BEGIN_NAMESPACE
template <>
-struct formatter
+struct formatter
{
template
constexpr auto parse(ParseContext& ctx)
@@ -65,7 +65,7 @@ struct formatter
}
template
- auto format(const crypto::SubjectAltName& san, FormatContext& ctx) const
+ auto format(const ccf::crypto::SubjectAltName& san, FormatContext& ctx) const
-> decltype(ctx.out())
{
std::string prefix;
diff --git a/include/ccf/crypto/sha256.h b/include/ccf/crypto/sha256.h
index 97fac504517f..eb6f4b89654d 100644
--- a/include/ccf/crypto/sha256.h
+++ b/include/ccf/crypto/sha256.h
@@ -6,7 +6,7 @@
#include
-namespace crypto
+namespace ccf::crypto
{
/** Compute the SHA256 hash of @p data
* @param data The data to compute the hash of
diff --git a/include/ccf/crypto/sha256_hash.h b/include/ccf/crypto/sha256_hash.h
index 40ae2ddc7388..cf4cde1a0f15 100644
--- a/include/ccf/crypto/sha256_hash.h
+++ b/include/ccf/crypto/sha256_hash.h
@@ -10,7 +10,7 @@
#define FMT_HEADER_ONLY
#include
-namespace crypto
+namespace ccf::crypto
{
class Sha256Hash
{
@@ -36,7 +36,7 @@ namespace crypto
const Sha256Hash& third);
friend std::ostream& operator<<(
- std::ostream& os, const crypto::Sha256Hash& h);
+ std::ostream& os, const ccf::crypto::Sha256Hash& h);
std::string hex_str() const;
@@ -60,7 +60,7 @@ namespace crypto
FMT_BEGIN_NAMESPACE
template <>
-struct formatter
+struct formatter
{
template
constexpr auto parse(ParseContext& ctx)
@@ -69,28 +69,28 @@ struct formatter
}
template
- auto format(const crypto::Sha256Hash& p, FormatContext& ctx) const
+ auto format(const ccf::crypto::Sha256Hash& p, FormatContext& ctx) const
{
return format_to(ctx.out(), "", fmt::join(p.h, ""));
}
};
FMT_END_NAMESPACE
-namespace kv::serialisers
+namespace ccf::kv::serialisers
{
template <>
- struct BlitSerialiser
+ struct BlitSerialiser
{
- static SerialisedEntry to_serialised(const crypto::Sha256Hash& h)
+ static SerialisedEntry to_serialised(const ccf::crypto::Sha256Hash& h)
{
auto hex_str = h.hex_str();
return SerialisedEntry(hex_str.begin(), hex_str.end());
}
- static crypto::Sha256Hash from_serialised(const SerialisedEntry& data)
+ static ccf::crypto::Sha256Hash from_serialised(const SerialisedEntry& data)
{
auto data_str = std::string{data.begin(), data.end()};
- crypto::Sha256Hash ret;
+ ccf::crypto::Sha256Hash ret;
return ret.from_hex_string(data_str);
}
};
diff --git a/include/ccf/crypto/symmetric_key.h b/include/ccf/crypto/symmetric_key.h
index fcf25ba8e606..367a580d309b 100644
--- a/include/ccf/crypto/symmetric_key.h
+++ b/include/ccf/crypto/symmetric_key.h
@@ -7,7 +7,7 @@
#include
#include
-namespace crypto
+namespace ccf::crypto
{
constexpr size_t GCM_DEFAULT_KEY_SIZE = 32;
@@ -44,7 +44,7 @@ namespace crypto
return GCM_SIZE_TAG + IV_SIZE;
}
- void set_random_iv(EntropyPtr entropy = crypto::get_entropy())
+ void set_random_iv(EntropyPtr entropy = ccf::crypto::get_entropy())
{
iv = entropy->random(IV_SIZE);
}
diff --git a/include/ccf/crypto/verifier.h b/include/ccf/crypto/verifier.h
index ed74d3b3623b..b57017514ac9 100644
--- a/include/ccf/crypto/verifier.h
+++ b/include/ccf/crypto/verifier.h
@@ -9,7 +9,7 @@
#include
-namespace crypto
+namespace ccf::crypto
{
class Verifier
{
@@ -252,13 +252,13 @@ namespace crypto
*/
VerifierPtr make_verifier(const Pem& pem);
- crypto::Pem cert_der_to_pem(const std::vector& der);
+ ccf::crypto::Pem cert_der_to_pem(const std::vector& der);
std::vector cert_pem_to_der(const Pem& pem);
std::vector public_key_der_from_cert(
const std::vector& der);
- crypto::Pem public_key_pem_from_cert(const std::vector& der);
+ ccf::crypto::Pem public_key_pem_from_cert(const std::vector& der);
std::string get_subject_name(const Pem& cert);
}
diff --git a/include/ccf/ds/json.h b/include/ccf/ds/json.h
index c840c273860f..45c47638caf6 100644
--- a/include/ccf/ds/json.h
+++ b/include/ccf/ds/json.h
@@ -66,7 +66,7 @@ namespace std
{
if constexpr (std::is_same_v)
{
- j = crypto::b64_from_raw(t);
+ j = ccf::crypto::b64_from_raw(t);
}
else
{
@@ -87,7 +87,7 @@ namespace std
{
try
{
- t = crypto::raw_from_b64(j.get());
+ t = ccf::crypto::raw_from_b64(j.get());
return;
}
catch (const std::exception& e)
diff --git a/include/ccf/ds/json_schema.h b/include/ccf/ds/json_schema.h
index c79b417ba37a..d8216726df90 100644
--- a/include/ccf/ds/json_schema.h
+++ b/include/ccf/ds/json_schema.h
@@ -97,11 +97,11 @@ namespace ccf::ds
template
inline std::string schema_name()
{
- if constexpr (nonstd::is_specialization::value)
+ if constexpr (ccf::nonstd::is_specialization::value)
{
return schema_name();
}
- else if constexpr (nonstd::is_specialization::value)
+ else if constexpr (ccf::nonstd::is_specialization::value)
{
if constexpr (std::is_same>::value)
{
@@ -113,20 +113,20 @@ namespace ccf::ds
return fmt::format("{}_array", schema_name());
}
}
- else if constexpr (nonstd::is_specialization::value)
+ else if constexpr (ccf::nonstd::is_specialization::value)
{
return fmt::format("{}_set", schema_name());
}
else if constexpr (
- nonstd::is_specialization::value ||
- nonstd::is_specialization::value)
+ ccf::nonstd::is_specialization::value ||
+ ccf::nonstd::is_specialization::value)
{
return fmt::format(
"{}_to_{}",
schema_name(),
schema_name());
}
- else if constexpr (nonstd::is_specialization::value)
+ else if constexpr (ccf::nonstd::is_specialization::value)
{
return fmt::format(
"{}_and_{}",
@@ -198,13 +198,13 @@ namespace ccf::ds
template
inline void fill_schema(nlohmann::json& schema)
{
- if constexpr (nonstd::is_specialization::value)
+ if constexpr (ccf::nonstd::is_specialization::value)
{
fill_schema(schema);
}
else if constexpr (
- nonstd::is_specialization::value ||
- nonstd::is_specialization::value)
+ ccf::nonstd::is_specialization::value ||
+ ccf::nonstd::is_specialization::value)
{
if constexpr (std::is_same>::value)
{
@@ -219,8 +219,8 @@ namespace ccf::ds
}
}
else if constexpr (
- nonstd::is_specialization::value ||
- nonstd::is_specialization::value)
+ ccf::nonstd::is_specialization::value ||
+ ccf::nonstd::is_specialization::value)
{
// Nlohmann JSON serialises some maps as objects, if the keys can be
// converted to strings. This should detect those cases. The others are
@@ -247,7 +247,7 @@ namespace ccf::ds
schema["items"] = items;
}
}
- else if constexpr (nonstd::is_specialization::value)
+ else if constexpr (ccf::nonstd::is_specialization::value)
{
schema["type"] = "array";
auto items = nlohmann::json::array();
diff --git a/include/ccf/ds/logger.h b/include/ccf/ds/logger.h
index 003bd4f9ef46..9d677820d960 100644
--- a/include/ccf/ds/logger.h
+++ b/include/ccf/ds/logger.h
@@ -15,7 +15,7 @@
#include
#include
-namespace logger
+namespace ccf::logger
{
static constexpr LoggerLevel MOST_VERBOSE =
#ifdef CCF_DISABLE_VERBOSE_LOGGING
@@ -356,9 +356,9 @@ namespace logger
// This allows:
// CCF_LOG_OUT(DEBUG, "foo") << "this " << "msg";
#define CCF_LOG_OUT(LVL, TAG) \
- logger::config::ok(LoggerLevel::LVL) && \
- logger::Out() == \
- logger::LogLine(LoggerLevel::LVL, TAG, __FILE__, __LINE__)
+ ccf::logger::config::ok(LoggerLevel::LVL) && \
+ ccf::logger::Out() == \
+ ccf::logger::LogLine(LoggerLevel::LVL, TAG, __FILE__, __LINE__)
// To avoid repeating the (s, ...) args for every macro, we cheat with a curried
// macro here by ending the macro with another macro name, which then accepts
@@ -376,7 +376,7 @@ namespace logger
};
#ifndef CCF_LOGGER_NO_DEPRECATE
-# define CCF_LOGGER_DEPRECATE(MACRO) logger::macro::MACRO;
+# define CCF_LOGGER_DEPRECATE(MACRO) ccf::logger::macro::MACRO;
#else
# define CCF_LOGGER_DEPRECATE(MACRO)
#endif
diff --git a/include/ccf/ds/nonstd.h b/include/ccf/ds/nonstd.h
index 55c7dfced6be..97ba29c13f25 100644
--- a/include/ccf/ds/nonstd.h
+++ b/include/ccf/ds/nonstd.h
@@ -17,7 +17,7 @@
* some are proposed, some are purely custom. They are defined here to avoid
* repetition in other locations.
*/
-namespace nonstd
+namespace ccf::nonstd
{
/** is_specialization detects type-specialized templates. This does not work
* for value-dependent types (eg - std::array)
@@ -96,7 +96,7 @@ namespace nonstd
}
/* split_1 wraps split and allows writing things like:
- * auto [host, port] = nonstd::split_1("1.2.3.4:8000", ":")
+ * auto [host, port] = ccf::nonstd::split_1("1.2.3.4:8000", ":")
*/
static inline std::tuple split_1(
const std::string_view& s, const std::string_view& separator)
@@ -153,7 +153,7 @@ namespace nonstd
/* rsplit_1 wraps rsplit _and reverses the result order_ and allows writing
* things like:
- * auto [host, port] = nonstd::rsplit_1("[1:2:3:4]:8000", ":")
+ * auto [host, port] = ccf::nonstd::rsplit_1("[1:2:3:4]:8000", ":")
*/
static inline std::tuple rsplit_1(
const std::string_view& s, const std::string_view& separator)
diff --git a/include/ccf/ds/openapi.h b/include/ccf/ds/openapi.h
index 0874ea92568b..c53722fdbd92 100644
--- a/include/ccf/ds/openapi.h
+++ b/include/ccf/ds/openapi.h
@@ -94,7 +94,7 @@ namespace ccf::ds
{
// HTTP_GET becomes the string "get"
std::string s = llhttp_method_name(verb);
- nonstd::to_lower(s);
+ ccf::nonstd::to_lower(s);
auto& po = access::get_object(path, s);
if (default_responses)
@@ -275,13 +275,13 @@ namespace ccf::ds
nlohmann::json add_schema_component()
{
nlohmann::json schema;
- if constexpr (nonstd::is_specialization::value)
+ if constexpr (ccf::nonstd::is_specialization::value)
{
return add_schema_component();
}
else if constexpr (
- nonstd::is_specialization::value ||
- nonstd::is_specialization::value)
+ ccf::nonstd::is_specialization::value ||
+ ccf::nonstd::is_specialization::value)
{
if constexpr (std::is_same>::value)
{
@@ -299,8 +299,8 @@ namespace ccf::ds
document, ccf::ds::json::schema_name(), schema);
}
else if constexpr (
- nonstd::is_specialization::value ||
- nonstd::is_specialization::value)
+ ccf::nonstd::is_specialization::value ||
+ ccf::nonstd::is_specialization::value)
{
if constexpr (nlohmann::detail::
is_compatible_object_type::value)
@@ -330,7 +330,7 @@ namespace ccf::ds
return add_schema_to_components(
document, ccf::ds::json::schema_name(), schema);
}
- else if constexpr (nonstd::is_specialization::value)
+ else if constexpr (ccf::nonstd::is_specialization::value)
{
schema["type"] = "array";
auto items = nlohmann::json::array();
diff --git a/include/ccf/ds/unit_strings.h b/include/ccf/ds/unit_strings.h
index d5a7fb729f94..e74b9a9f710c 100644
--- a/include/ccf/ds/unit_strings.h
+++ b/include/ccf/ds/unit_strings.h
@@ -34,7 +34,7 @@ namespace ccf::ds
}
auto unit = std::string(unit_begin, input.end());
- nonstd::to_lower(unit);
+ ccf::nonstd::to_lower(unit);
auto value = std::string(input.begin(), unit_begin);
size_t ret = 0;
diff --git a/include/ccf/endpoint.h b/include/ccf/endpoint.h
index 3ad91549217c..610f0a073902 100644
--- a/include/ccf/endpoint.h
+++ b/include/ccf/endpoint.h
@@ -30,7 +30,7 @@ namespace ccf::endpoints
};
}
-namespace kv::serialisers
+namespace ccf::kv::serialisers
{
template <>
struct BlitSerialiser
@@ -101,7 +101,12 @@ namespace ccf::endpoints
a primary, it should attempt to redirect to the primary, or else return
an error. Any write operations must be executed on a primary, so should
be marked as ToPrimary. */
- ToPrimary
+ ToPrimary,
+
+ /** This operation should be executed on a backup. If the current node is
+ not a backup, it should attempt to redirect to a backup, or else return
+ an error. Only read operations can be marked as ToBackup. */
+ ToBackup,
};
enum class Mode
@@ -126,7 +131,8 @@ namespace ccf::endpoints
DECLARE_JSON_ENUM(
RedirectionStrategy,
{{RedirectionStrategy::None, "none"},
- {RedirectionStrategy::ToPrimary, "to_primary"}});
+ {RedirectionStrategy::ToPrimary, "to_primary"},
+ {RedirectionStrategy::ToBackup, "to_backup"}});
DECLARE_JSON_ENUM(
Mode,
diff --git a/include/ccf/endpoint_context.h b/include/ccf/endpoint_context.h
index 0f55e53cef35..eca44c2299cb 100644
--- a/include/ccf/endpoint_context.h
+++ b/include/ccf/endpoint_context.h
@@ -53,12 +53,12 @@ namespace ccf::endpoints
struct EndpointContext : public CommandEndpointContext
{
- EndpointContext(const std::shared_ptr& r, kv::Tx& t) :
+ EndpointContext(const std::shared_ptr& r, ccf::kv::Tx& t) :
CommandEndpointContext(r),
tx(t)
{}
- kv::Tx& tx;
+ ccf::kv::Tx& tx;
};
using EndpointFunction = std::function;
@@ -69,12 +69,12 @@ namespace ccf::endpoints
struct ReadOnlyEndpointContext : public CommandEndpointContext
{
ReadOnlyEndpointContext(
- const std::shared_ptr& r, kv::ReadOnlyTx& t) :
+ const std::shared_ptr& r, ccf::kv::ReadOnlyTx& t) :
CommandEndpointContext(r),
tx(t)
{}
- kv::ReadOnlyTx& tx;
+ ccf::kv::ReadOnlyTx& tx;
};
using ReadOnlyEndpointFunction =
std::function;
diff --git a/include/ccf/endpoint_registry.h b/include/ccf/endpoint_registry.h
index d9575399018e..ab991ee0785b 100644
--- a/include/ccf/endpoint_registry.h
+++ b/include/ccf/endpoint_registry.h
@@ -5,7 +5,6 @@
#include "ccf/ds/json_schema.h"
#include "ccf/endpoint.h"
#include "ccf/endpoint_context.h"
-#include "ccf/pal/locking.h"
#include "ccf/rpc_context.h"
#include "ccf/tx.h"
@@ -16,7 +15,7 @@
#include
#include
-namespace kv
+namespace ccf::kv
{
class Consensus;
class TxHistory;
@@ -162,8 +161,8 @@ namespace ccf::endpoints
std::map>>
templated_endpoints;
- kv::Consensus* consensus = nullptr;
- kv::TxHistory* history = nullptr;
+ ccf::kv::Consensus* consensus = nullptr;
+ ccf::kv::TxHistory* history = nullptr;
public:
EndpointRegistry(const std::string& method_prefix_) :
@@ -255,12 +254,12 @@ namespace ccf::endpoints
* internally, so must be able to populate the document
* with the supported endpoints however it defines them.
*/
- virtual void build_api(nlohmann::json& document, kv::ReadOnlyTx&);
+ virtual void build_api(nlohmann::json& document, ccf::kv::ReadOnlyTx&);
virtual void init_handlers();
virtual EndpointDefinitionPtr find_endpoint(
- kv::Tx&, ccf::RpcContext& rpc_ctx);
+ ccf::kv::Tx&, ccf::RpcContext& rpc_ctx);
virtual void execute_endpoint(
EndpointDefinitionPtr e, EndpointContext& args);
@@ -269,7 +268,7 @@ namespace ccf::endpoints
EndpointDefinitionPtr e, CommandEndpointContext& args, const TxID& tx_id);
virtual std::set get_allowed_verbs(
- kv::Tx&, const ccf::RpcContext& rpc_ctx);
+ ccf::kv::Tx&, const ccf::RpcContext& rpc_ctx);
virtual bool request_needs_root(const ccf::RpcContext& rpc_ctx);
@@ -279,9 +278,9 @@ namespace ccf::endpoints
virtual void tick(std::chrono::milliseconds);
- void set_consensus(kv::Consensus* c);
+ void set_consensus(ccf::kv::Consensus* c);
- void set_history(kv::TxHistory* h);
+ void set_history(ccf::kv::TxHistory* h);
// Override these methods to log or report request metrics.
virtual void handle_event_request_completed(
diff --git a/include/ccf/endpoints/authentication/all_of_auth.h b/include/ccf/endpoints/authentication/all_of_auth.h
index f6bef98c8ede..f278bd882e40 100644
--- a/include/ccf/endpoints/authentication/all_of_auth.h
+++ b/include/ccf/endpoints/authentication/all_of_auth.h
@@ -37,7 +37,7 @@ namespace ccf
const std::vector>& _policies);
std::unique_ptr authenticate(
- kv::ReadOnlyTx&,
+ ccf::kv::ReadOnlyTx&,
const std::shared_ptr&,
std::string&) override;
diff --git a/include/ccf/endpoints/authentication/authentication_types.h b/include/ccf/endpoints/authentication/authentication_types.h
index 81f63d6e0180..d22d2535344f 100644
--- a/include/ccf/endpoints/authentication/authentication_types.h
+++ b/include/ccf/endpoints/authentication/authentication_types.h
@@ -30,7 +30,7 @@ namespace ccf
virtual ~AuthnPolicy() = default;
virtual std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) = 0;
diff --git a/include/ccf/endpoints/authentication/cert_auth.h b/include/ccf/endpoints/authentication/cert_auth.h
index 3a84091820dc..6624cc01c059 100644
--- a/include/ccf/endpoints/authentication/cert_auth.h
+++ b/include/ccf/endpoints/authentication/cert_auth.h
@@ -38,7 +38,7 @@ namespace ccf
virtual ~UserCertAuthnPolicy();
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
@@ -72,7 +72,7 @@ namespace ccf
virtual ~MemberCertAuthnPolicy();
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
@@ -99,7 +99,7 @@ namespace ccf
static constexpr auto SECURITY_SCHEME_NAME = "node_cert";
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
diff --git a/include/ccf/endpoints/authentication/cose_auth.h b/include/ccf/endpoints/authentication/cose_auth.h
index b714154c205e..03a59bb0fe6e 100644
--- a/include/ccf/endpoints/authentication/cose_auth.h
+++ b/include/ccf/endpoints/authentication/cose_auth.h
@@ -22,6 +22,12 @@ namespace ccf
uint64_t gov_msg_created_at;
};
+ struct TimestampedProtectedHeader : ProtectedHeader
+ {
+ std::optional msg_type;
+ std::optional msg_created_at;
+ };
+
struct COSESign1AuthnIdentity : public AuthnIdentity
{
/** COSE Content */
@@ -55,7 +61,7 @@ namespace ccf
MemberId member_id;
/** Member certificate, used to sign this request, described by keyId */
- crypto::Pem member_cert;
+ ccf::crypto::Pem member_cert;
/** COSE Protected Header */
GovernanceProtectedHeader protected_header;
@@ -65,7 +71,7 @@ namespace ccf
const std::span& envelope_,
const std::span& signature_,
const MemberId& member_id_,
- const crypto::Pem& member_cert_,
+ const ccf::crypto::Pem& member_cert_,
const GovernanceProtectedHeader& protected_header_) :
COSESign1AuthnIdentity(content_, envelope_, signature_),
member_id(member_id_),
@@ -80,18 +86,18 @@ namespace ccf
UserId user_id;
/** User certificate, used to sign this request, described by keyId */
- crypto::Pem user_cert;
+ ccf::crypto::Pem user_cert;
/** COSE Protected Header */
- ProtectedHeader protected_header;
+ TimestampedProtectedHeader protected_header;
UserCOSESign1AuthnIdentity(
const std::span& content_,
const std::span& envelope_,
const std::span& signature_,
const UserId& user_id_,
- const crypto::Pem& user_cert_,
- const ProtectedHeader& protected_header_) :
+ const ccf::crypto::Pem& user_cert_,
+ const TimestampedProtectedHeader& protected_header_) :
COSESign1AuthnIdentity(content_, envelope_, signature_),
user_id(user_id_),
user_cert(user_cert_),
@@ -119,7 +125,7 @@ namespace ccf
~MemberCOSESign1AuthnPolicy();
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
@@ -152,7 +158,7 @@ namespace ccf
using MemberCOSESign1AuthnPolicy::MemberCOSESign1AuthnPolicy;
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
@@ -163,20 +169,36 @@ namespace ccf
};
/** User COSE Sign1 Authentication Policy
+ *
+ * Allows parametrising two optional protected header entries
+ * which are exposed to the endpoint if present.
*/
class UserCOSESign1AuthnPolicy : public AuthnPolicy
{
+ std::string msg_type_name;
+ std::string msg_created_at_name;
+
protected:
static const OpenAPISecuritySchema security_schema;
+ virtual std::unique_ptr _authenticate(
+ ccf::kv::ReadOnlyTx& tx,
+ const std::shared_ptr& ctx,
+ std::string& error_reason);
+
public:
static constexpr auto SECURITY_SCHEME_NAME = "user_cose_sign1";
- UserCOSESign1AuthnPolicy();
+ UserCOSESign1AuthnPolicy(
+ const std::string& msg_type_name_ = "ccf.msg.type",
+ const std::string& msg_created_at_name_ = "ccf.msg.created_at") :
+ msg_type_name(msg_type_name_),
+ msg_created_at_name(msg_created_at_name_)
+ {}
~UserCOSESign1AuthnPolicy();
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
@@ -195,4 +217,36 @@ namespace ccf
return SECURITY_SCHEME_NAME;
}
};
-}
+
+ /** Typed User COSE Sign1 Authentication Policy
+ *
+ * Extends UserCOSESign1AuthPolicy, to require that a specific message
+ * type is present in the corresponding protected header.
+ */
+ class TypedUserCOSESign1AuthnPolicy : public UserCOSESign1AuthnPolicy
+ {
+ private:
+ std::string expected_msg_type;
+
+ public:
+ static constexpr auto SECURITY_SCHEME_NAME = "typed_user_cose_sign1";
+
+ TypedUserCOSESign1AuthnPolicy(
+ const std::string& expected_msg_type_,
+ const std::string& msg_type_name_ = "ccf.msg.type",
+ const std::string& msg_created_at_name_ = "ccf.msg.created_at") :
+ UserCOSESign1AuthnPolicy(msg_type_name_, msg_created_at_name_),
+ expected_msg_type(expected_msg_type_)
+ {}
+
+ std::unique_ptr authenticate(
+ ccf::kv::ReadOnlyTx& tx,
+ const std::shared_ptr& ctx,
+ std::string& error_reason) override;
+
+ std::string get_security_scheme_name() override
+ {
+ return SECURITY_SCHEME_NAME;
+ }
+ };
+}
\ No newline at end of file
diff --git a/include/ccf/endpoints/authentication/empty_auth.h b/include/ccf/endpoints/authentication/empty_auth.h
index 11d1e44d8562..f5ec3870e575 100644
--- a/include/ccf/endpoints/authentication/empty_auth.h
+++ b/include/ccf/endpoints/authentication/empty_auth.h
@@ -17,7 +17,7 @@ namespace ccf
static constexpr auto SECURITY_SCHEME_NAME = "no_auth";
std::unique_ptr authenticate(
- kv::ReadOnlyTx&,
+ ccf::kv::ReadOnlyTx&,
const std::shared_ptr&,
std::string&) override;
diff --git a/include/ccf/endpoints/authentication/jwt_auth.h b/include/ccf/endpoints/authentication/jwt_auth.h
index 3413dff4b8b8..3a44ee55a73a 100644
--- a/include/ccf/endpoints/authentication/jwt_auth.h
+++ b/include/ccf/endpoints/authentication/jwt_auth.h
@@ -37,7 +37,7 @@ namespace ccf
virtual ~JwtAuthnPolicy();
std::unique_ptr authenticate(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
const std::shared_ptr& ctx,
std::string& error_reason) override;
diff --git a/include/ccf/entity_id.h b/include/ccf/entity_id.h
index 3b26668d7042..0c0f961df367 100644
--- a/include/ccf/entity_id.h
+++ b/include/ccf/entity_id.h
@@ -202,7 +202,7 @@ struct formatter>
};
FMT_END_NAMESPACE
-namespace kv::serialisers
+namespace ccf::kv::serialisers
{
template
struct BlitSerialiser>
diff --git a/include/ccf/historical_queries_adapter.h b/include/ccf/historical_queries_adapter.h
index 837c9d3eed1f..d51308cdd178 100644
--- a/include/ccf/historical_queries_adapter.h
+++ b/include/ccf/historical_queries_adapter.h
@@ -9,7 +9,7 @@
#include "ccf/tx_id.h"
#include "ccf/tx_status.h"
-namespace kv
+namespace ccf::kv
{
class Consensus;
}
@@ -51,26 +51,26 @@ namespace ccf::historical
ccf::View view, ccf::SeqNo seqno, std::string& error_reason)>;
HistoricalTxStatus is_tx_committed_v2(
- kv::Consensus* consensus,
+ ccf::kv::Consensus* consensus,
ccf::View view,
ccf::SeqNo seqno,
std::string& error_reason);
ccf::endpoints::EndpointFunction adapter_v3(
const HandleHistoricalQuery& f,
- ccfapp::AbstractNodeContext& node_context,
+ ccf::AbstractNodeContext& node_context,
const CheckHistoricalTxStatus& available,
const TxIDExtractor& extractor = txid_from_header);
ccf::endpoints::ReadOnlyEndpointFunction read_only_adapter_v3(
const HandleReadOnlyHistoricalQuery& f,
- ccfapp::AbstractNodeContext& node_context,
+ ccf::AbstractNodeContext& node_context,
const CheckHistoricalTxStatus& available,
const ReadOnlyTxIDExtractor& extractor = txid_from_header);
ccf::endpoints::EndpointFunction read_write_adapter_v3(
const HandleReadWriteHistoricalQuery& f,
- ccfapp::AbstractNodeContext& node_context,
+ ccf::AbstractNodeContext& node_context,
const CheckHistoricalTxStatus& available,
const TxIDExtractor& extractor = txid_from_header);
}
\ No newline at end of file
diff --git a/include/ccf/historical_queries_interface.h b/include/ccf/historical_queries_interface.h
index 32a2a4e8d91e..f4bc6ba9f4d4 100644
--- a/include/ccf/historical_queries_interface.h
+++ b/include/ccf/historical_queries_interface.h
@@ -16,14 +16,14 @@ namespace ccf::historical
struct State
{
/// Read-only historical store at transaction_id
- kv::ReadOnlyStorePtr store = nullptr;
+ ccf::kv::ReadOnlyStorePtr store = nullptr;
/// Receipt for ledger entry at transaction_id
TxReceiptImplPtr receipt = nullptr;
/// View and Sequence Number for the State
ccf::TxID transaction_id;
State(
- const kv::ReadOnlyStorePtr& store_,
+ const ccf::kv::ReadOnlyStorePtr& store_,
const TxReceiptImplPtr& receipt_,
const ccf::TxID& transaction_id_) :
store(store_),
@@ -49,6 +49,8 @@ namespace ccf::historical
using ExpiryDuration = std::chrono::seconds;
+ using CacheSize = size_t;
+
/** Stores the progress of historical query requests.
*
* A request will generally need to be made multiple times (with the same
@@ -79,6 +81,13 @@ namespace ccf::historical
virtual void set_default_expiry_duration(
ExpiryDuration seconds_until_expiry) = 0;
+ /** Set the cache limit (in bytes) to evict least recently used requests
+ * from the cache after its size grows beyond this limit. The limit is not
+ * strict. It is estimated based on serialized states' sizes approximation
+ * and is checked once per tick, and so it can overflow for a short time.
+ */
+ virtual void set_soft_cache_limit(CacheSize cache_limit) = 0;
+
/** EXPERIMENTAL: Set the tracking of deletes on missing keys for historical
* queries.
*
@@ -93,7 +102,7 @@ namespace ccf::historical
* is equivalent to get_store_at(handle, seqno, seqno), but returns nullptr
* if the state is currently unavailable.
*/
- virtual kv::ReadOnlyStorePtr get_store_at(
+ virtual ccf::kv::ReadOnlyStorePtr get_store_at(
RequestHandle handle,
ccf::SeqNo seqno,
ExpiryDuration seconds_until_expiry) = 0;
@@ -101,7 +110,7 @@ namespace ccf::historical
/** Same as @c get_store_at but uses default expiry value.
* @see get_store_at
*/
- virtual kv::ReadOnlyStorePtr get_store_at(
+ virtual ccf::kv::ReadOnlyStorePtr get_store_at(
RequestHandle handle, ccf::SeqNo seqno) = 0;
/** Retrieve a full state at a given seqno, including the Store, the TxID
@@ -135,7 +144,7 @@ namespace ccf::historical
* vector will be of length (end_seqno - start_seqno + 1) and will contain
* no nullptrs.
*/
- virtual std::vector get_store_range(
+ virtual std::vector get_store_range(
RequestHandle handle,
ccf::SeqNo start_seqno,
ccf::SeqNo end_seqno,
@@ -144,7 +153,7 @@ namespace ccf::historical
/** Same as @c get_store_range but uses default expiry value.
* @see get_store_range
*/
- virtual std::vector get_store_range(
+ virtual std::vector get_store_range(
RequestHandle handle, ccf::SeqNo start_seqno, ccf::SeqNo end_seqno) = 0;
/** Retrieve a range of states at the given indices, including the Store,
@@ -165,11 +174,11 @@ namespace ccf::historical
/** Retrieve stores for a set of given indices.
*/
- virtual std::vector get_stores_for(
+ virtual std::vector get_stores_for(
RequestHandle handle,
const SeqNoCollection& seqnos,
ExpiryDuration seconds_until_expiry) = 0;
- virtual std::vector get_stores_for(
+ virtual std::vector get_stores_for(
RequestHandle handle, const SeqNoCollection& seqnos) = 0;
/** Retrieve states for a set of given indices.
diff --git a/include/ccf/historical_queries_utils.h b/include/ccf/historical_queries_utils.h
index 9d1f375ad4d5..133dcd10b996 100644
--- a/include/ccf/historical_queries_utils.h
+++ b/include/ccf/historical_queries_utils.h
@@ -19,7 +19,7 @@ namespace ccf::historical
// additional entries have been requested, in which case the caller should
// retry later.
bool populate_service_endorsements(
- kv::ReadOnlyTx& tx,
+ ccf::kv::ReadOnlyTx& tx,
ccf::historical::StatePtr& state,
AbstractStateCache& state_cache,
std::shared_ptr
diff --git a/include/ccf/http_configuration.h b/include/ccf/http_configuration.h
index 2c1e068c27e0..ebe03a465100 100644
--- a/include/ccf/http_configuration.h
+++ b/include/ccf/http_configuration.h
@@ -7,7 +7,7 @@
#include
-namespace http
+namespace ccf::http
{
// Default parser limits, used as a DoS protection against
// requests that are too large.
diff --git a/include/ccf/http_consts.h b/include/ccf/http_consts.h
index 8b021b4fff14..7f93b217b647 100644
--- a/include/ccf/http_consts.h
+++ b/include/ccf/http_consts.h
@@ -2,72 +2,74 @@
// Licensed under the Apache 2.0 License.
#pragma once
-namespace http
+namespace ccf
{
- namespace headers
+ namespace http
{
- // All HTTP headers are expected to be lowercase
- static constexpr auto ACCEPT = "accept";
- static constexpr auto ALLOW = "allow";
- static constexpr auto AUTHORIZATION = "authorization";
- static constexpr auto CACHE_CONTROL = "cache-control";
- static constexpr auto CONTENT_LENGTH = "content-length";
- static constexpr auto CONTENT_TYPE = "content-type";
- static constexpr auto DATE = "date";
- static constexpr auto DIGEST = "digest";
- static constexpr auto HOST = "host";
- static constexpr auto LOCATION = "location";
- static constexpr auto RETRY_AFTER = "retry-after";
- static constexpr auto TRAILER = "trailer";
- static constexpr auto WWW_AUTHENTICATE = "www-authenticate";
+ namespace headers
+ {
+ // All HTTP headers are expected to be lowercase
+ static constexpr auto ACCEPT = "accept";
+ static constexpr auto ALLOW = "allow";
+ static constexpr auto AUTHORIZATION = "authorization";
+ static constexpr auto CACHE_CONTROL = "cache-control";
+ static constexpr auto CONTENT_LENGTH = "content-length";
+ static constexpr auto CONTENT_TYPE = "content-type";
+ static constexpr auto DATE = "date";
+ static constexpr auto DIGEST = "digest";
+ static constexpr auto HOST = "host";
+ static constexpr auto LOCATION = "location";
+ static constexpr auto RETRY_AFTER = "retry-after";
+ static constexpr auto TRAILER = "trailer";
+ static constexpr auto WWW_AUTHENTICATE = "www-authenticate";
- static constexpr auto CCF_TX_ID = "x-ms-ccf-transaction-id";
- }
+ static constexpr auto CCF_TX_ID = "x-ms-ccf-transaction-id";
+ }
- namespace headervalues
- {
- namespace contenttype
+ namespace headervalues
{
- static constexpr auto JSON = "application/json";
- static constexpr auto MSGPACK = "application/msgpack";
- static constexpr auto TEXT = "text/plain";
- static constexpr auto OCTET_STREAM = "application/octet-stream";
- static constexpr auto GRPC = "application/grpc";
- static constexpr auto COSE = "application/cose";
- static constexpr auto JAVASCRIPT = "text/javascript";
+ namespace contenttype
+ {
+ static constexpr auto JSON = "application/json";
+ static constexpr auto TEXT = "text/plain";
+ static constexpr auto OCTET_STREAM = "application/octet-stream";
+ static constexpr auto GRPC = "application/grpc";
+ static constexpr auto COSE = "application/cose";
+ static constexpr auto JAVASCRIPT = "text/javascript";
+ }
}
- }
- namespace auth
- {
- static constexpr auto DIGEST_SHA256 = "SHA-256";
+ namespace auth
+ {
+ static constexpr auto DIGEST_SHA256 = "SHA-256";
- static constexpr auto SIGN_AUTH_SCHEME = "Signature";
- static constexpr auto SIGN_PARAMS_KEYID = "keyId";
- static constexpr auto SIGN_PARAMS_SIGNATURE = "signature";
- static constexpr auto SIGN_PARAMS_ALGORITHM = "algorithm";
- static constexpr auto SIGN_PARAMS_HEADERS = "headers";
- static constexpr auto SIGN_ALGORITHM_ECDSA_SHA256 = "ecdsa-sha256";
- static constexpr auto SIGN_ALGORITHM_HS_2019 = "hs2019";
+ static constexpr auto SIGN_AUTH_SCHEME = "Signature";
+ static constexpr auto SIGN_PARAMS_KEYID = "keyId";
+ static constexpr auto SIGN_PARAMS_SIGNATURE = "signature";
+ static constexpr auto SIGN_PARAMS_ALGORITHM = "algorithm";
+ static constexpr auto SIGN_PARAMS_HEADERS = "headers";
+ static constexpr auto SIGN_ALGORITHM_ECDSA_SHA256 = "ecdsa-sha256";
+ static constexpr auto SIGN_ALGORITHM_HS_2019 = "hs2019";
- static constexpr auto SIGN_HEADER_REQUEST_TARGET = "(request-target)";
+ static constexpr auto SIGN_HEADER_REQUEST_TARGET = "(request-target)";
- static constexpr auto SIGN_PARAMS_DELIMITER = ",";
- static constexpr auto SIGN_PARAMS_HEADERS_DELIMITER = " ";
+ static constexpr auto SIGN_PARAMS_DELIMITER = ",";
+ static constexpr auto SIGN_PARAMS_HEADERS_DELIMITER = " ";
- static constexpr auto BEARER_AUTH_SCHEME = "Bearer";
- }
+ static constexpr auto BEARER_AUTH_SCHEME = "Bearer";
+ }
- static constexpr char const* required_signature_headers[] = {
- auth::SIGN_HEADER_REQUEST_TARGET, headers::DIGEST};
-}
+ static constexpr char const* required_signature_headers[] = {
+ auth::SIGN_HEADER_REQUEST_TARGET, ccf::http::headers::DIGEST};
+ }
-namespace http2
-{
- namespace headers
+ namespace http2
{
- static constexpr auto PATH = ":path";
- static constexpr auto STATUS = ":status";
- static constexpr auto METHOD = ":method";
+ namespace headers
+ {
+ static constexpr auto PATH = ":path";
+ static constexpr auto STATUS = ":status";
+ static constexpr auto METHOD = ":method";
+ }
}
}
\ No newline at end of file
diff --git a/include/ccf/http_header_map.h b/include/ccf/http_header_map.h
index c7d55d27d594..476075ca4591 100644
--- a/include/ccf/http_header_map.h
+++ b/include/ccf/http_header_map.h
@@ -5,7 +5,7 @@
#include