mirror of
https://github.com/fluencelabs/trust-graph
synced 2025-07-04 17:11:41 +00:00
Compare commits
82 Commits
v0.1.6-hl-
...
keypair-v0
Author | SHA1 | Date | |
---|---|---|---|
106bff637e | |||
120bedfafb | |||
48351d5562 | |||
0b66f4e053 | |||
ed5bd2c0ec | |||
2f336f73cf | |||
d378fe2509 | |||
80bf4aa4ff | |||
80757e6352 | |||
f2c3b2a13c | |||
4f657f9dae | |||
725d3f8f48 | |||
1fb02e4827 | |||
a37bda37a2 | |||
ee330a715a | |||
c22eab38c1 | |||
3692d6898d | |||
3a5f23741f | |||
b10991501d | |||
d80a43bcff | |||
a7ea41ed4d | |||
d04120bacf | |||
3ba3855892 | |||
f7ef0f8da0 | |||
2001f900fa | |||
412b8ba725 | |||
a7abe87c09 | |||
1a26a6809e | |||
93161afe0c | |||
11fd2de7b6 | |||
a8fdb4472e | |||
56d0ea27bd | |||
d0c6c62ca4 | |||
b6df3fe548 | |||
a747b9cc75 | |||
d567848cba | |||
9b942eacca | |||
c85fb16de3 | |||
97ce5bbac7 | |||
864b7f5c13 | |||
da38a41ba7 | |||
7493eed216 | |||
e9399b7d0c | |||
81eb924476 | |||
fe902acc50 | |||
f5994b33d1 | |||
554bb60256 | |||
080503dcfa | |||
757145fffc | |||
8e58f56190 | |||
664552d4f9 | |||
c717e4dc73 | |||
015422efcc | |||
0c1398b377 | |||
bc638ddda3 | |||
8cf640c9b5 | |||
55c8cb72a2 | |||
249f2f25f2 | |||
789b7124e3 | |||
5a2c4aa1c1 | |||
a5a36a672c | |||
d45796b846 | |||
570428c8fe | |||
017c134cf3 | |||
a6ce8d9eee | |||
7db85cbece | |||
f860884da8 | |||
cd471cd683 | |||
47b65e277a | |||
a162fa3583 | |||
2a5e324dd5 | |||
edc7dc404f | |||
b9a996eba8 | |||
7fbaaaa8f9 | |||
aa72fdab64 | |||
b9fbbbcafb | |||
7c72a59bef | |||
5609740216 | |||
58648d7037 | |||
048406aa02 | |||
b76954782b | |||
c2f63cb41e |
6
.cargo/config
Normal file
6
.cargo/config
Normal file
@ -0,0 +1,6 @@
|
||||
[http]
|
||||
timeout = 30 # timeout for each HTTP request, in seconds
|
||||
multiplexing = false # HTTP/2 multiplexing
|
||||
|
||||
[net]
|
||||
retry = 50 # network retries
|
@ -1,38 +0,0 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
docker: circleci/docker@1.5.0
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
resource_class: xlarge
|
||||
environment:
|
||||
RUST_BACKTRACE: 1
|
||||
steps:
|
||||
- checkout
|
||||
- run: |
|
||||
sudo bash .github/download_marine.sh
|
||||
- restore_cache:
|
||||
keys:
|
||||
- trust-graph00-{{ checksum "./Cargo.lock" }}-{{ checksum "./keypair/Cargo.lock" }}
|
||||
- run: |
|
||||
rustup target add wasm32-wasi
|
||||
cargo test --no-fail-fast --release --all-features --
|
||||
cd ./service
|
||||
./build.sh
|
||||
mkdir data
|
||||
cargo test --no-fail-fast --release --all-features -- --test-threads=1
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/.cargo
|
||||
- ~/.rustup
|
||||
key: trust-graph00-{{ checksum "./Cargo.lock" }-{{ checksum "./service/Cargo.lock" }}}-{{ checksum "./keypair/Cargo.lock" }}
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
CircleCI:
|
||||
jobs:
|
||||
- Build
|
3
.github/actionlint.yaml
vendored
Normal file
3
.github/actionlint.yaml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
self-hosted-runner:
|
||||
labels:
|
||||
- builder
|
14
.github/download_marine.sh
vendored
14
.github/download_marine.sh
vendored
@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -o pipefail -o errexit -o nounset
|
||||
set -x
|
||||
|
||||
MARINE_RELEASE="https://api.github.com/repos/fluencelabs/marine/releases/latest"
|
||||
OUT_DIR=/usr/local/bin
|
||||
|
||||
# get metadata about release
|
||||
curl -s -H "Accept: application/vnd.github.v3+json" $MARINE_RELEASE |
|
||||
# extract url and name for asset with name "marine"
|
||||
# also append $OUT_DIR to each name so file is saved to $OUT_DIR
|
||||
jq -r ".assets | .[] | select(.name == \"marine\") | \"\(.browser_download_url) $OUT_DIR/\(.name)\"" |
|
||||
# download assets
|
||||
xargs -n2 bash -c 'curl -L $0 -o $1 && chmod +x $1'
|
40
.github/release-please/config.json
vendored
Normal file
40
.github/release-please/config.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"boostrap-sha": "015422efcce41530a6cd84a25091598bc459d2e6",
|
||||
"release-type": "rust",
|
||||
"bump-minor-pre-major": true,
|
||||
"bump-patch-for-minor-pre-major": true,
|
||||
"plugins": [
|
||||
{
|
||||
"type": "cargo-workspace",
|
||||
"merge": false
|
||||
},
|
||||
{
|
||||
"type": "linked-versions",
|
||||
"groupName": "trust-graph, wasm and api",
|
||||
"components": [
|
||||
"trust-graph",
|
||||
"trust-graph-api",
|
||||
"trust-graph-wasm",
|
||||
"distro"
|
||||
]
|
||||
}
|
||||
],
|
||||
"packages": {
|
||||
"trust-graph": {
|
||||
"component": "trust-graph"
|
||||
},
|
||||
"aqua": {
|
||||
"release-type": "node",
|
||||
"component": "trust-graph-api"
|
||||
},
|
||||
"service": {
|
||||
"component": "trust-graph-wasm"
|
||||
},
|
||||
"keypair": {
|
||||
"component": "keypair"
|
||||
},
|
||||
"distro": {
|
||||
"component": "distro"
|
||||
}
|
||||
}
|
||||
}
|
7
.github/release-please/manifest.json
vendored
Normal file
7
.github/release-please/manifest.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"trust-graph": "0.4.8",
|
||||
"aqua": "0.4.8",
|
||||
"service": "0.4.8",
|
||||
"keypair": "0.10.4",
|
||||
"distro": "0.4.8"
|
||||
}
|
38
.github/renovate.json
vendored
Normal file
38
.github/renovate.json
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base",
|
||||
":semanticCommitTypeAll(chore)"
|
||||
],
|
||||
"enabledManagers": ["cargo", "npm", "github-actions", "pip_requirements"],
|
||||
"rangeStrategy": "pin",
|
||||
"schedule": "every weekend",
|
||||
"packageRules": [
|
||||
{
|
||||
"matchManagers": ["cargo", "npm"],
|
||||
"matchPackagePatterns": [
|
||||
"@fluencelabs/.*",
|
||||
"fluence-.*",
|
||||
"marine-.*"
|
||||
],
|
||||
"semanticCommitType": "fix",
|
||||
"semanticCommitScope": "deps",
|
||||
"schedule": "at any time"
|
||||
},
|
||||
{
|
||||
"matchDepTypes": ["devDependencies"],
|
||||
"prPriority": -1,
|
||||
"semanticCommitType": "chore",
|
||||
"semanticCommitScope": "deps"
|
||||
},
|
||||
{
|
||||
"matchUpdateTypes": ["major"],
|
||||
"prConcurrentLimit": 1
|
||||
},
|
||||
{
|
||||
"matchManagers": ["github-actions"],
|
||||
"groupName": "all github-actions",
|
||||
"prPriority": -1
|
||||
}
|
||||
]
|
||||
}
|
5
.github/workflows/changelog_config.json
vendored
5
.github/workflows/changelog_config.json
vendored
@ -1,5 +0,0 @@
|
||||
{
|
||||
"template": "${{CHANGELOG}}\n\n${{UNCATEGORIZED}}",
|
||||
"pr_template": "- #${{NUMBER}} ${{TITLE}}",
|
||||
"empty_template": "- no changes"
|
||||
}
|
35
.github/workflows/lint.yml
vendored
Normal file
35
.github/workflows/lint.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
name: Validate PR title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
reviewdog:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Lint actions
|
||||
uses: reviewdog/action-actionlint@v1
|
||||
env:
|
||||
SHELLCHECK_OPTS: "-e SC2086 -e SC2207 -e SC2128"
|
||||
with:
|
||||
reporter: github-pr-check
|
||||
fail_on_error: true
|
266
.github/workflows/release.yml
vendored
266
.github/workflows/release.yml
vendored
@ -1,159 +1,153 @@
|
||||
name: "publish-release"
|
||||
name: "release"
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||
|
||||
jobs:
|
||||
npm-publish:
|
||||
name: "Publish"
|
||||
release-please:
|
||||
runs-on: ubuntu-latest
|
||||
container: rust
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
outputs:
|
||||
releases-created: ${{ steps.release.outputs['releases_created'] }}
|
||||
trust-graph-api-release-created: ${{ steps.release.outputs['aqua--release_created'] }}
|
||||
trust-graph-release-created: ${{ steps.release.outputs['trust-graph--release_created'] }}
|
||||
trust-graph-tag-name: ${{ steps.release.outputs['trust-graph--tag_name'] }}
|
||||
trust-graph-version: ${{ steps.release.outputs['trust-graph--version'] }}
|
||||
|
||||
steps:
|
||||
### Setup
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set env
|
||||
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Download jq
|
||||
run: |
|
||||
curl -L https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 -o /usr/local/bin/jq
|
||||
chmod +x /usr/local/bin/jq
|
||||
|
||||
- name: Download marine
|
||||
run: bash $GITHUB_WORKSPACE/.github/download_marine.sh
|
||||
|
||||
- name: Cache npm
|
||||
uses: actions/cache@v2
|
||||
- name: Run release-please
|
||||
id: release
|
||||
uses: google-github-actions/release-please-action@v3
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-v01-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-v01-
|
||||
token: ${{ secrets.FLUENCEBOT_RELEASE_PLEASE_PAT }}
|
||||
command: manifest
|
||||
config-file: .github/release-please/config.json
|
||||
manifest-file: .github/release-please/manifest.json
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- name: Show output from release-please
|
||||
if: steps.release.outputs.releases_created
|
||||
env:
|
||||
RELEASE_PLEASE_OUTPUT: ${{ toJSON(steps.release.outputs) }}
|
||||
run: echo "${RELEASE_PLEASE_OUTPUT}" | jq
|
||||
|
||||
publish:
|
||||
runs-on: builder
|
||||
|
||||
needs: release-please
|
||||
if: needs.release-please.outputs.releases-created
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Import secrets
|
||||
uses: hashicorp/vault-action@v2.4.3
|
||||
with:
|
||||
node-version: "15"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
url: https://vault.fluence.dev
|
||||
path: jwt/github
|
||||
role: ci
|
||||
method: jwt
|
||||
jwtGithubAudience: "https://github.com/fluencelabs"
|
||||
jwtTtl: 300
|
||||
exportToken: false
|
||||
secrets: |
|
||||
kv/npmjs/fluencebot token | NODE_AUTH_TOKEN ;
|
||||
kv/crates.io/fluencebot token | CARGO_REGISTRY_TOKEN
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Setup Rust toolchain
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
|
||||
- name: Install toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2021-09-01
|
||||
target: wasm32-wasi
|
||||
override: true
|
||||
- name: Setup marine
|
||||
uses: fluencelabs/setup-marine@v1
|
||||
|
||||
### Build
|
||||
- name: trust-graph.wasm
|
||||
working-directory: ./service
|
||||
- name: Build
|
||||
run: ./build.sh
|
||||
|
||||
- name: Check Aqua compiles
|
||||
working-directory: ./aqua
|
||||
- name: Install cargo-workspaces
|
||||
uses: baptiste0928/cargo-install@v1.3.0
|
||||
with:
|
||||
crate: cargo-workspaces
|
||||
|
||||
- name: Publish to crates.io
|
||||
run: |
|
||||
npm i
|
||||
npm run build
|
||||
cargo ws publish \
|
||||
--no-git-commit \
|
||||
--allow-dirty \
|
||||
--from-git \
|
||||
--skip-published \
|
||||
--yes
|
||||
|
||||
- name: Create builtin distribution package
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
cache-dependency-path: "aqua/package-lock.json"
|
||||
cache: "npm"
|
||||
|
||||
- run: npm i
|
||||
working-directory: aqua
|
||||
|
||||
- run: npm run build
|
||||
working-directory: aqua
|
||||
|
||||
- name: Publish to NPM registry
|
||||
if: needs.release-please.outputs.trust-graph-api-release-created
|
||||
run: npm publish --access public
|
||||
working-directory: aqua
|
||||
|
||||
slack:
|
||||
if: always()
|
||||
name: "Notify"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- release-please
|
||||
- publish
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: lwhiteley/dependent-jobs-result-check@v1
|
||||
id: status
|
||||
with:
|
||||
statuses: failure
|
||||
dependencies: ${{ toJSON(needs) }}
|
||||
|
||||
- name: Log output
|
||||
run: |
|
||||
./builtin-package/package.sh
|
||||
echo "statuses:" "${{ steps.status.outputs.statuses }}"
|
||||
echo "jobs:" "${{ steps.status.outputs.jobs }}"
|
||||
echo "found any?:" "${{ steps.status.outputs.found }}"
|
||||
|
||||
- name: Build Changelog
|
||||
id: changelog
|
||||
uses: mikepenz/release-changelog-builder-action@v1
|
||||
- name: Import secrets
|
||||
uses: hashicorp/vault-action@v2.4.3
|
||||
with:
|
||||
configuration: ".github/workflows/changelog_config.json"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
url: https://vault.fluence.dev
|
||||
path: jwt/github
|
||||
role: ci
|
||||
method: jwt
|
||||
jwtGithubAudience: "https://github.com/fluencelabs"
|
||||
jwtTtl: 300
|
||||
exportToken: false
|
||||
secrets: |
|
||||
kv/slack/release-please webhook | SLACK_WEBHOOK_URL
|
||||
|
||||
## Publish
|
||||
- name: Release
|
||||
id: release
|
||||
uses: softprops/action-gh-release@v1
|
||||
- uses: ravsamhq/notify-slack-action@v2
|
||||
if: steps.status.outputs.found == 'true'
|
||||
with:
|
||||
name: trust-graph ${{ env.RELEASE_VERSION }}
|
||||
tag_name: ${{ env.RELEASE_VERSION }}
|
||||
files: |
|
||||
trust-graph.tar.gz
|
||||
body: ${{steps.changelog.outputs.changelog}}
|
||||
draft: false
|
||||
prerelease: false
|
||||
fail_on_unmatched_files: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
### Publish Aqua API
|
||||
- name: Publish Aqua API
|
||||
run: |
|
||||
npm version ${{ env.RELEASE_VERSION }} --allow-same-version
|
||||
npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
working-directory: ./aqua
|
||||
|
||||
## Update node-distro repo
|
||||
- name: Calculate SHA256
|
||||
run: |
|
||||
du -hs trust-graph.tar.gz
|
||||
echo $(sha256sum trust-graph.tar.gz)
|
||||
echo "SHA256=$(sha256sum trust-graph.tar.gz | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||
|
||||
- name: Get tar.gz URL
|
||||
id: package-url
|
||||
uses: actions/github-script@v4
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
result-encoding: string
|
||||
script: |
|
||||
try {
|
||||
let assets = await github.repos.listReleaseAssets({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: "${{ steps.release.outputs.id }}",
|
||||
});
|
||||
console.dir(assets);
|
||||
let package = assets.data.find((a) => a.name === 'trust-graph.tar.gz');
|
||||
let url = package.browser_download_url;
|
||||
console.log("URL: " + url);
|
||||
return url;
|
||||
} catch (e) {
|
||||
console.log("Err: " + e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
- name: Update version in node-distro repo
|
||||
uses: benc-uk/workflow-dispatch@v1
|
||||
with:
|
||||
workflow: update_service
|
||||
repo: fluencelabs/node-distro
|
||||
ref: 'tg-hl-api'
|
||||
token: ${{ secrets.PERSONAL_TOKEN }}
|
||||
inputs: '{
|
||||
"name": "trust-graph",
|
||||
"version": "${{ env.RELEASE_VERSION }}",
|
||||
"url": "${{ steps.package-url.outputs.result }}",
|
||||
"sha256": "${{ env.SHA256 }}"
|
||||
}'
|
||||
|
||||
- name: Log notice
|
||||
uses: actions/github-script@v4
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
console.dir(core);
|
||||
core.info("trust-graph was updated to ${{ env.RELEASE_VERSION }} in node-distro repo");
|
||||
status: "failure"
|
||||
notification_title: "*{workflow}* has {status_message}"
|
||||
message_format: "${{ steps.status.outputs.jobs }} {status_message} in <{repo_url}|{repo}>"
|
||||
footer: "<{run_url}>"
|
||||
|
35
.github/workflows/run-tests.yml
vendored
Normal file
35
.github/workflows/run-tests.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Run tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.ref }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
trust-graph:
|
||||
uses: ./.github/workflows/tests.yml
|
||||
|
||||
lints:
|
||||
name: lints
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup rust toolchain
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
|
||||
- name: Run cargo fmt
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: fmt
|
||||
args: --all -- --check
|
17
.github/workflows/tag.yml
vendored
17
.github/workflows/tag.yml
vendored
@ -1,17 +0,0 @@
|
||||
name: "tag"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
tag:
|
||||
name: "Tag"
|
||||
runs-on: "ubuntu-latest"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Bump version and push tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v5.5
|
||||
with:
|
||||
github_token: ${{ secrets.PERSONAL_TOKEN }}
|
58
.github/workflows/tests.yml
vendored
Normal file
58
.github/workflows/tests.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
name: Run tests with workflow_call
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
trust-graph:
|
||||
name: "cargo nextest"
|
||||
runs-on: builder
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
|
||||
- name: Setup marine
|
||||
uses: fluencelabs/setup-marine@v1
|
||||
with:
|
||||
artifact-name: marine
|
||||
|
||||
- name: Build
|
||||
run: ./build.sh
|
||||
|
||||
- name: Run cargo clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
args: -Z unstable-options --all
|
||||
|
||||
- name: Setup nextest
|
||||
uses: taiki-e/install-action@nextest
|
||||
|
||||
- name: Run cargo nextest
|
||||
env:
|
||||
NEXTEST_RETRIES: 10
|
||||
NEXTEST_TEST_THREADS: 10
|
||||
# exclude distro since at this point we don't have compiled wasms which are required for compilation
|
||||
run: cargo nextest run --release --all-features --no-fail-fast --workspace --exclude trust-graph-distro
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
cache-dependency-path: "aqua/package-lock.json"
|
||||
cache: "npm"
|
||||
|
||||
- run: npm i
|
||||
working-directory: aqua
|
||||
|
||||
- run: npm run build
|
||||
working-directory: aqua
|
13
.gitignore
vendored
13
.gitignore
vendored
@ -2,6 +2,8 @@ service/target
|
||||
service/artifacts
|
||||
builtin-package/*.wasm
|
||||
trust-graph.tar.gz
|
||||
distro/trust-graph-service
|
||||
distro/target
|
||||
|
||||
**/*.rs.bk
|
||||
**/.idea
|
||||
@ -16,3 +18,14 @@ example/src/generated/**
|
||||
example/generated/**
|
||||
admin/src/generated/**
|
||||
admin/generated/**
|
||||
|
||||
target
|
||||
|
||||
# recommended by Fluence Labs:
|
||||
.idea
|
||||
.DS_Store
|
||||
.fluence
|
||||
Cargo.lock
|
||||
**/target/
|
||||
.vscode/settings.json
|
||||
.repl_history
|
||||
|
3780
Cargo.lock
generated
3780
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
34
Cargo.toml
34
Cargo.toml
@ -1,32 +1,10 @@
|
||||
[package]
|
||||
name = "trust-graph"
|
||||
version = "0.3.0"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
description = "trust graph"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/fluencelabs/trust-graph"
|
||||
|
||||
[dependencies]
|
||||
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.27.2", features = ["secp256k1"] }
|
||||
serde = { version = "=1.0.118", features = ["derive"] }
|
||||
|
||||
fluence-keypair = { path = "./keypair", version = "0.5.0" }
|
||||
serde_json = "1.0.58"
|
||||
bs58 = "0.3.1"
|
||||
failure = "0.1.6"
|
||||
log = "0.4.11"
|
||||
ref-cast = "1.0.2"
|
||||
derivative = "2.1.1"
|
||||
signature = "1.3.0"
|
||||
serde_with = "1.6.0"
|
||||
thiserror = "1.0.23"
|
||||
sha2 = "0.9.5"
|
||||
rand = "0.7.0"
|
||||
nonempty = "0.7.0"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"trust-graph",
|
||||
"keypair",
|
||||
"service"
|
||||
"service",
|
||||
"distro"
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
libp2p-identity = { version = "0.2.1", default-features = false }
|
||||
|
347
README.md
347
README.md
@ -1,20 +1,303 @@
|
||||
# Trust Graph
|
||||
|
||||
Trust Graph is network-wide peer relationship layer. It's designed to be used to prioritize resources and control permissions in open networks. Being a decentralized graph of relationships, basically a Web of Trust, Trust Graph is distributed among all network peers.
|
||||
- [Trust Graph](#trust-graph)
|
||||
- [Overview](#overview)
|
||||
- [Why is it important?](#why-is-it-important)
|
||||
- [What is it?](#what-is-it)
|
||||
- [How to Use it in Aqua](#how-to-use-it-in-aqua)
|
||||
- [How to import](#how-to-import)
|
||||
- [How to add roots](#how-to-add-roots)
|
||||
- [How to issue and add trust](#how-to-issue-and-add-trust)
|
||||
- [How to revoke the trust](#how-to-revoke-the-trust)
|
||||
- [How to get certificates](#how-to-get-certificates)
|
||||
- [How to get weights](#how-to-get-weights)
|
||||
- [How to use it in TS/JS](#how-to-use-it-in-tsjs)
|
||||
- [Use cases](#use-cases)
|
||||
- [Create a trusted subnetwork](#create-a-trusted-subnetwork)
|
||||
- [Service permission management](#service-permission-management)
|
||||
- [Label trusted peers and execute computation only on this peers](#label-trusted-peers-and-execute-computation-only-on-this-peers)
|
||||
- [FAQ](#faq)
|
||||
- [API](#api)
|
||||
- [Directory structure](#directory-structure)
|
||||
- [Learn Aqua](#learn-aqua)
|
||||
|
||||
Specifically, Trust Graph is used to prioritize connections from known peers to counteract Sybil attacks while still keeping network open by reserving resources for unknown peers.
|
||||
## Overview
|
||||
The problem of access control and permissions is solved with centralized CAs (Certificate Authority) in web 2.0. However, such problem is urgent and becomes even more challenging considering a decentralized nature of web 3.0. TrustGraph is our point of view on the solution for this challenge.
|
||||
|
||||
At the same time, Trust Graph can be used at the application level in various ways such as prioritization of service execution on authorized peers or to define an interconnected subnetwork among peers of a single protocol.
|
||||
TrustGraph is a bottom layer of trust for open p2p networks: every peer may be provided with SSL-like certificates that promoted over the network. Service providers and peers can treat certificate holders differently based on their certificate set.
|
||||
|
||||
## How to Use it in TypeScript
|
||||
TrustGraph is a basic component that allows storing and managing certificates without additional logic about how to decide whom to trust and whom to treat as unreliable.
|
||||
|
||||
## Why is it important?
|
||||
|
||||
The problem of peer choice and prioritization is very urgent in p2p networks. We can't use the network reliably and predictably without trust to any network participant. We also should mark and avoid malicious peers. In addition we need to control our application access and permissions in runtime, so it performs continuously without interruptions and redeployments.
|
||||
|
||||
## What is it?
|
||||
|
||||
TrustGraph is basically a directed graph with one root at least, vertices are peer ids, and edges are one of the two types of cryptographic relations: trust and revocation.
|
||||
|
||||
**Root** is a peer id that we unconditionally trust until it is removed, and is defined by the node owner. Every root has characteristics that represent the maximum length for a chain of trusts.
|
||||
|
||||
As a **path to the root**, we consider a path with only trust edges, given the following rule: chain `R -> A -> ...-> C` is not a path if A revoked C.
|
||||
|
||||
**Trust** is a cryptographic relation representing that peer A trusts peer B until this trust expires or is revoked. Trust relation is transitive. If peer A trusts peer B, and peer B trusts peer C, it results in peer A trusts peer C transitively. Trust relation means that you trust to connect, compute or store based on your business logic and chosen metrics. For example, if you want to perform some computation and some well-known peers do that, and are trusted by others you trust, so you can safely use them for computing but not to store sensitive information (personal keys, etc).
|
||||
|
||||
Trust data structure contains the following fields:
|
||||
- peer id, trust is issued to
|
||||
- creation timestamp
|
||||
- expiration timestamp
|
||||
- a signature of the issuer that contains all of the previous fields signed
|
||||
|
||||
So the trust is signed and tamperproof by design.
|
||||
|
||||
**Certificate** is a chain of trusts started with a self-signed root trust. Considering Trust and Certificate data structures, it is possible to track the chain of trust relations: the `issued_for` field of the first trust in a chain indicates a root peer id, second — whom root trusts, etc. So if we have a chain `R->A->B->C` in the certificate it looks like a chain of the following trusts: `R->R`, `R->A`, `A->B`, `B->C`. A certificate is tamperproof since it is a composition of signed trusts.
|
||||
|
||||

|
||||
|
||||
So peerA is trusted by peerB if there is a path between them in the instance of TrustGraph. The selection of certificates is subjective and defined by a node owner by choice of roots and maximum chain lengths. For now, there are no default metrics for a general case.
|
||||
|
||||
**Revocation** is a cryptographic relation representing that a peer A considers a peer C malicious or unreliable. For example, all chains containing paths from A to C will not be treated as valid. So if A trusts a peer B, and B trusts C, a peer A has no trust to C transitively, it would have otherwise.
|
||||
|
||||

|
||||
|
||||
Every peer has a **weight**. A weight signifies a power of 2 or zero. If there is no path from any root to a peer, given revocations, its weight equals zero. The closer to the root, the bigger the weight. Weights are also subjective and relevant in the scope of a local TrustGraph.
|
||||
|
||||

|
||||
|
||||
TrustGraph is a builtin meaning that every node is bundled with a TrustGraph instance and predefined certificates.
|
||||
|
||||
Trust is transitive in terms of cryptographic relations. On the other hand, a subset of trusts and certificates is subjective for each network participant because of the choice of roots.
|
||||
|
||||
|
||||
## How to Use it in Aqua
|
||||
### How to import
|
||||
```
|
||||
import "@fluencelabs/trust-graph/trust-graph-api.aqua"
|
||||
import "@fluencelabs/trust-graph/trust-graph.aqua"
|
||||
|
||||
func my_function(peer_id: string) -> u32:
|
||||
on HOST_PEER_ID:
|
||||
result <- get_weight(peer_id)
|
||||
<- result
|
||||
```
|
||||
|
||||
### How to add roots
|
||||
- `set_root(peer_id: PeerId, max_chain_len: u32) -> SetRootResult`
|
||||
- `add_root_trust(node: PeerId, peer_id: PeerId, max_chain_len: u32) -> ?Error`
|
||||
|
||||
Let's set our peer id as a root on our relay and add self-signed trust:
|
||||
```rust
|
||||
func set_me_as_root(max_chain_len):
|
||||
result <- add_root_trust(HOST_PEER_ID, INIT_PEER_ID, max_chain_len)
|
||||
|
||||
-- if you use peer_id different from INIT_PEER_ID
|
||||
-- you should add keypair in your Sig service
|
||||
if result.success:
|
||||
-- do smth
|
||||
Op.noop()
|
||||
else:
|
||||
-- handle failure
|
||||
Op.noop()
|
||||
```
|
||||
- also you can use `set_root` + `add_trust` to achieve the same goal
|
||||
- [how to add keypair to Sig service](https://doc.fluence.dev/docs/fluence-js/3_in_depth#signing-service)
|
||||
- roots can be added only by the service owner
|
||||
- `max_chain_len` specifies a number of trusts in a chain for the root. Zero for chains that contain only root trust.
|
||||
|
||||
### How to issue and add trust
|
||||
|
||||
- `issue_trust(issuer: PeerId, issued_for: PeerId, expires_at_sec: u64) -> ?Trust, ?Error`
|
||||
- `import_trust(trust: Trust, issuer: PeerId) -> ?Error`
|
||||
- `add_trust(node: PeerId, issuer: PeerId, issued_for: PeerId, expires_at_sec: u64) -> ?Error`
|
||||
|
||||
Let's issue trust, and import it to our relay:
|
||||
```rust
|
||||
func issue_trust_by_me(issued_for: PeerId, expires_at_sec: u64):
|
||||
trust, error <- issue_trust(INIT_PEER_ID, issued_for, expires_at_sec)
|
||||
if trust == nil:
|
||||
-- handle failure
|
||||
Op.noop()
|
||||
else:
|
||||
on HOST_PEER_ID:
|
||||
error <- import_trust(trust!, INIT_PEER_ID)
|
||||
-- handle error
|
||||
```
|
||||
|
||||
|
||||
- `add_trust` is a combination of `issue_trust` and `import_trust`
|
||||
- if you want to issue trust not by `INIT_PEER_ID` check the Sig service [docs](https://doc.fluence.dev/docs/fluence-js/3_in_depth#signing-service)
|
||||
|
||||
### How to revoke the trust
|
||||
|
||||
- `issue_revocation(revoked_by: PeerId, revoked: PeerId) -> ?Revocation, ?Error`
|
||||
- `import_revocation(revocation: Revocation) -> ?Error`
|
||||
- `revoke(node: PeerId, revoked_by: PeerId, revoked: PeerId) -> ?Error`
|
||||
|
||||
Let's revoke some peers by our peer id:
|
||||
```rust
|
||||
func revoke_peer(revoked: PeerId):
|
||||
revocation, error <- issue_revocation(INIT_PEER_ID, revoked)
|
||||
if revocation == nil:
|
||||
-- handle failure
|
||||
Op.noop()
|
||||
else:
|
||||
on HOST_PEER_ID:
|
||||
error <- import_revocation(revocation!)
|
||||
-- handle error
|
||||
```
|
||||
|
||||
- `revoke` is a combination of `issue_revocation` and `import_revocation`
|
||||
- if you want to issue revocation not by `INIT_PEER_ID` check the Sig service [docs](https://doc.fluence.dev/docs/fluence-js/3_in_depth#signing-service)
|
||||
|
||||
|
||||
### How to get certificates
|
||||
|
||||
- `get_all_certs(issued_for: PeerId) -> AllCertsResult`
|
||||
- `get_all_certs_from(issued_for: PeerId, issuer: PeerId) -> AllCertsResult`
|
||||
- `get_host_certs() -> AllCertsResult`
|
||||
- `get_host_certs_from(issuer: PeerId) -> AllCertsResult`
|
||||
|
||||
Let's get all certificates issued by us to our relay peer id (HOST_PEER_ID):
|
||||
```rust
|
||||
func get_certs_issued_by_me() -> AllCertsResult:
|
||||
on HOST_PEER_ID:
|
||||
result <- get_host_certs_from(INIT_PEER_ID)
|
||||
<- result
|
||||
```
|
||||
- `get_host_certs` is just an alias for `get_all_certs(HOST_PEER_ID)`
|
||||
- `_from` calls results contain only certificates with trust issued by `issuer`
|
||||
|
||||
### How to get weights
|
||||
- `get_weight(peer_id: PeerId) -> WeightResult`
|
||||
- `get_weight_from(peer_id: PeerId, issuer: PeerId) -> WeightResult`
|
||||
|
||||
Let's get our weight for certificates which contain trust by our relay
|
||||
```rust
|
||||
func get_our_weight() -> ?u32, ?string:
|
||||
weight: ?u32
|
||||
error: ?string
|
||||
on HOST_PEER_ID:
|
||||
result <- get_weight_from(INIT_PEER_ID, HOST_PEER_ID)
|
||||
if result.success:
|
||||
weight <<- result.weight
|
||||
else:
|
||||
error <<- result.error
|
||||
<- weight, error
|
||||
```
|
||||
|
||||
- `get_weight` returns result among all the certificates, on the other hand, `get_weight_from` return certificates containing trust by the issuer only
|
||||
|
||||
## How to use it in TS/JS
|
||||
1. Add `export.aqua` as in the Aqua [documentation](https://doc.fluence.dev/aqua-book/libraries#in-typescript-and-javascript)
|
||||
2. Add the following to your dependencies
|
||||
- `@fluencelabs/trust-graph`
|
||||
- `@fluencelabs/aqua`
|
||||
- `@fluencelabs/aqua-lib`
|
||||
- `@fluencelabs/fluence`
|
||||
- `@fluencelabs/fluence-network-environment`
|
||||
|
||||
3. Import dependencies
|
||||
```typescript
|
||||
import * as tg from "./generated/export";
|
||||
import { Fluence, KeyPair } from "@fluencelabs/fluence";
|
||||
import { krasnodar, Node } from "@fluencelabs/fluence-network-environment";
|
||||
```
|
||||
4. Create a client (specify keypair if you are node owner
|
||||
[link](https://github.com/fluencelabs/node-distro/blob/main/fluence/Config.default.toml#L9))
|
||||
|
||||
```typescript
|
||||
await Fluence.start({ connectTo: relay /*, KeyPair: builtins_keypair*/});
|
||||
```
|
||||
5. Add a root and issue root trust.
|
||||
```typescript
|
||||
let peer_id = Fluence.getStatus().peerId;
|
||||
let relay = Fluence.getStatus().relayPeerId;
|
||||
assert(peer_id !== null);
|
||||
assert(relay !== null);
|
||||
let max_chain_len = 2;
|
||||
let far_future = 99999999999999;
|
||||
let error = await tg.add_root_trust(relay, peer_id, max_chain_len, far_future);
|
||||
if (error !== null) {
|
||||
console.log(error);
|
||||
}
|
||||
```
|
||||
6. By default, trusts/revocations signed with the client's private key. To sign with different keys see the Sig service [documentation](https://doc.fluence.dev/docs/fluence-js/3_in_depth#signing-service).
|
||||
```typescript
|
||||
// issue signed trust
|
||||
let error = await tg.issue_trust(relay, peer_id, issued_for_peer_id, expires_at_sec);
|
||||
if (error !== null) {
|
||||
console.log(error);
|
||||
}
|
||||
```
|
||||
|
||||
## Use cases
|
||||
|
||||
### Create a trusted subnetwork
|
||||
|
||||
You can organize a subnetwork with peers trusted by your choice or chosen metrics. So you can treat trusts given by a peer (or a key) as evidence.
|
||||
|
||||
Let's consider we have peers A, B and C:
|
||||
- Choose a peer A as an authority, set it as a root for the local TrustGraphs on all peers
|
||||
- Issue and put self-signed by a peer A trust as a root trust
|
||||
- Issue trusts by a peer A a to peer B and a peer C, and put them on all peers
|
||||
- So for a call `get_weight_from(targetPeer, peerA)` will reflect whether targetPeer is in a subnetwork ABC
|
||||
|
||||
### Service permission management
|
||||
|
||||
You can specify in runtime who can access service functionality based on the local TrustGraph (certificates, weights). It's possible to check where the proof comes from based on [tetraplets](https://doc.fluence.dev/docs/knowledge_security). For example, only peers that have a non-zero weight can execute a service function `trusted_call(weight: WeightResult) -> u8`.
|
||||
|
||||
So if you want to have service permission management you should follow the steps:
|
||||
- Pass `WeightResult` from TrustGraph to the function that you need to control:
|
||||
```rust
|
||||
...
|
||||
weight_result <- get_weight(INIT_PEER_ID)
|
||||
result <- MyService.trusted_call(weight_result)
|
||||
...
|
||||
```
|
||||
- Inside your service you need to check tetraplets like [this](https://github.com/fluencelabs/registry/blob/main/service/src/misc.rs#L37) to be sure that they are resulted from the local TrustGraph
|
||||
- Add `INIT_PEER_ID` or another choosen key as a root
|
||||
- Issue trust to peers that can call this function:
|
||||
```rust
|
||||
func grant_access(issued_for: PeerId, expires_at_sec: u64):
|
||||
error <- add_trust(INIT_PEER_ID, issued_for, expires_at_sec)
|
||||
if error != nil
|
||||
-- handle error
|
||||
```
|
||||
|
||||
### Label trusted peers and execute computation only on this peers
|
||||
|
||||
See [example](./example):
|
||||
- How to call [`trust-graph`](./example/index.ts) functions in TS/JS
|
||||
- How to call [`trust-graph`](./example/index.ts) functions in TS/JS
|
||||
- Step-by-step description [`README`](./example/README.md)
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
- Can a weight change during time?
|
||||
- If the shortest path to a root changes, in case of trust expiration, importing or revocation, a weight also changes.
|
||||
|
||||
- What does a zero weight mean?
|
||||
- A zero weight means there is no trust and path from any roots to the target peer.
|
||||
|
||||
- How we can interpret a certificate and/or a peer weight?
|
||||
- A certificate contains a path from the root to the target peer we are looking for. A weight represents the presence of these certificates and peers' closeness to the root.
|
||||
|
||||
- How are weights calculated and based on what feedback?
|
||||
- Weights are calculated based on the existence of a chain of trusts from the roots. For example, if we have a root with a maximum chain length equal 4 and have a chain `R -> A -> B -> C`, so the corresponding weights of peers are `8`, `4`, `2`, `1`. Weights are the same if there are no changes in the paths.
|
||||
As long as we have no metrics, all trust/revocation logic is a TrustGraph user's responsibility.
|
||||
|
||||
- How do I set all weights to untrusted and then increase trust in a peer over time?
|
||||
- All peers are untrusted by default. Trust is unmeasured, weight represents how far the peer is from the root, the bigger weight, the closer to the root, so if you want to increase the weight of the target peer, you should obtain the trust from the root or peers who are closer to the root than this peer.
|
||||
|
||||
- How do I know that other peers are using the same processes to update weights?
|
||||
- Weights calculated **locally** based on certificates that contain immutable signed trusts. Weights are subjective and have meaning only locally to this exact peer.
|
||||
|
||||
- Can I start my own instance of a trust graph or is there only a global version available?
|
||||
- Every Fluence node is bundled with a builtin TrustGraph instance, but you can change or remove any service you want if you're a node owner.
|
||||
|
||||
## API
|
||||
|
||||
High-level API is defined in the [trust-graph-api.aqua](./aqua/trust-graph-api.aqua) module.
|
||||
High-level API is defined in the [trust-graph-api.aqua](./aqua/trust-graph-api.aqua) module. API Reference soon will be available in the documentation.
|
||||
|
||||
## Directory structure
|
||||
|
||||
@ -22,7 +305,7 @@ High-level API is defined in the [trust-graph-api.aqua](./aqua/trust-graph-api.a
|
||||
|
||||
- [`keypair`](./keypair) directory is an abstracted cryptographical layer (key pairs, public keys, signatures, etc.)
|
||||
|
||||
- [`service`](./service) is a package that provides `marine` API and could be compiled to a Wasm file. It is uses `SQLite` as storage
|
||||
- [`service`](./service) is a package that provides `marine` API and could be compiled to a Wasm file. It uses` SQLite` as storage
|
||||
|
||||
- [`example`](./example) is a `js` script that shows how to use Trust Graph to label peers
|
||||
|
||||
@ -35,53 +318,3 @@ High-level API is defined in the [trust-graph-api.aqua](./aqua/trust-graph-api.a
|
||||
* [Aqua Book](https://fluence.dev/aqua-book/)
|
||||
* [Aqua Playground](https://github.com/fluencelabs/aqua-playground)
|
||||
* [Aqua repo](https://github.com/fluencelabs/aqua)
|
||||
|
||||
## How to use in Aqua
|
||||
|
||||
```
|
||||
import "@fluencelabs/trust-graph/trust-graph-api.aqua"
|
||||
import "@fluencelabs/trust-graph/trust-graph.aqua"
|
||||
|
||||
func my_function(peer_id: string) -> u32:
|
||||
on HOST_PEER_ID:
|
||||
result <- get_weight(peer_id)
|
||||
<- result
|
||||
```
|
||||
|
||||
## How to use is js
|
||||
1. Add the following to your dependencies
|
||||
- `@fluencelabs/trust-graph`
|
||||
- `@fluencelabs/aqua`
|
||||
- `@fluencelabs/aqua-lib`
|
||||
- `@fluencelabs/fluence`
|
||||
- `@fluencelabs/fluence-network-environment`
|
||||
|
||||
2. Import dependencies
|
||||
```typescript
|
||||
import * as tg from "./generated/export";
|
||||
import { Fluence, KeyPair } from "@fluencelabs/fluence";
|
||||
import { krasnodar, Node } from "@fluencelabs/fluence-network-environment";
|
||||
```
|
||||
3. Create client (specify keypair if you are node owner
|
||||
[link](https://github.com/fluencelabs/node-distro/blob/main/fluence/Config.default.toml#L9))
|
||||
|
||||
```typescript
|
||||
await Fluence.start({ connectTo: relay /*, KeyPair: builtins_keypair*/});
|
||||
```
|
||||
4. Add root and issue root trust.
|
||||
```typescript
|
||||
let peer_id = Fluence.getStatus().peerId;
|
||||
let relay = Fluence.getStatus().relayPeerId;
|
||||
assert(peer_id !== null);
|
||||
assert(relay !== null);
|
||||
let max_chain_len = 2;
|
||||
let far_future = tg.timestamp_sec() + 9999999999;
|
||||
let error = await tg.add_root_trust(relay, peer_id, max_chain_len, far_future);
|
||||
assert(error == null)
|
||||
```
|
||||
5. For now, trusts/revocations can only be signed with the client's private key.
|
||||
Keypair specification will be available soon.
|
||||
```typescript
|
||||
// issue signed trust
|
||||
let error = await tg.issue_trust(relay, peer_id, issued_for_peer_id, expires_at_sec);
|
||||
```
|
||||
|
@ -60,22 +60,23 @@ async function main(environment: Node[]) {
|
||||
console.log("Issuer private key: %s", issuer_sk_b58);
|
||||
|
||||
let cur_time = await timestamp_sec(node);
|
||||
let expires_at = cur_time + 60 * 60 * 24 * 365;
|
||||
let expires_at = cur_time + 60 * 60 * 24 * 365 * 2;
|
||||
let certificates = [];
|
||||
let common_chain = [] as any;
|
||||
// self-signed root trust
|
||||
common_chain.push(await issue_trust_helper(node, root_kp, root_kp.Libp2pPeerId.toB58String(), root_kp.Libp2pPeerId.toB58String(), expires_at, cur_time));
|
||||
let root_trust = await issue_trust_helper(node, root_kp, root_kp.Libp2pPeerId.toB58String(), root_kp.Libp2pPeerId.toB58String(), expires_at, cur_time);
|
||||
// from root to issuer
|
||||
common_chain.push(await issue_trust_helper(node, root_kp, root_kp.Libp2pPeerId.toB58String(), issuer_kp.Libp2pPeerId.toB58String(), expires_at, cur_time));
|
||||
let issuer_trust = await issue_trust_helper(node, root_kp, root_kp.Libp2pPeerId.toB58String(), issuer_kp.Libp2pPeerId.toB58String(), expires_at, cur_time);
|
||||
// from root to example
|
||||
let trust = await issue_trust_helper(node, root_kp, root_kp.Libp2pPeerId.toB58String(), example_kp.Libp2pPeerId.toB58String(), expires_at, cur_time);
|
||||
let cert = {chain: [common_chain[0], trust]};
|
||||
certificates.push(cert);
|
||||
let example_trust = await issue_trust_helper(node, root_kp, root_kp.Libp2pPeerId.toB58String(), example_kp.Libp2pPeerId.toB58String(), expires_at, cur_time);
|
||||
|
||||
// cert for example key
|
||||
certificates.push({chain: [root_trust, example_trust]});
|
||||
|
||||
for (let i = 0; i < krasnodar.length; i++) {
|
||||
// from issuer to node
|
||||
let trust = await issue_trust_helper(node, issuer_kp, issuer_kp.Libp2pPeerId.toB58String(), krasnodar[i].peerId, expires_at, cur_time);
|
||||
let cert = {chain: [...common_chain, trust]};
|
||||
let node_trust = await issue_trust_helper(node, issuer_kp, issuer_kp.Libp2pPeerId.toB58String(), krasnodar[i].peerId, expires_at, cur_time);
|
||||
// cert for every krasnodar node
|
||||
let cert = {chain: [root_trust, issuer_trust, node_trust]};
|
||||
certificates.push(cert);
|
||||
}
|
||||
|
||||
|
11085
admin/package-lock.json
generated
11085
admin/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,12 @@
|
||||
"author": "Fluence Labs",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua": "^0.5.2-257",
|
||||
"@fluencelabs/aqua-lib": "^0.3.2",
|
||||
"@fluencelabs/fluence": "^0.18.0",
|
||||
"@fluencelabs/fluence-network-environment": "^1.0.10",
|
||||
"@fluencelabs/aqua": "^0.10.0",
|
||||
"@fluencelabs/aqua-lib": "^0.6.0",
|
||||
"@fluencelabs/fluence": "^0.27.5",
|
||||
"@fluencelabs/fluence-network-environment": "^1.0.13",
|
||||
"@fluencelabs/trust-graph": "file:../aqua",
|
||||
"bs58": "^4.0.1"
|
||||
"bs58": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.4.3"
|
||||
|
58
aqua/CHANGELOG.md
Normal file
58
aqua/CHANGELOG.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Changelog
|
||||
|
||||
## [0.4.8](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.7...trust-graph-api-v0.4.8) (2023-12-20)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-api:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.7](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.6...trust-graph-api-v0.4.7) (2023-07-04)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-api:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.6](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.5...trust-graph-api-v0.4.6) (2023-06-30)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* release master ([#110](https://github.com/fluencelabs/trust-graph/issues/110)) ([d80a43b](https://github.com/fluencelabs/trust-graph/commit/d80a43bcff721aff8fadf3d2d5c252804ce27a6c))
|
||||
|
||||
## [0.4.5](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.4...trust-graph-api-v0.4.5) (2023-05-09)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-api:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.4](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.3...trust-graph-api-v0.4.4) (2023-05-09)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-api:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.3](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.1...trust-graph-api-v0.4.3) (2023-05-08)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-api:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.1](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.4.0...trust-graph-api-v0.4.1) (2023-04-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update aqua to 0.10.3 ([fe902ac](https://github.com/fluencelabs/trust-graph/commit/fe902acc50a6b4c6bf97c487f3e47ae0f5ef8a95))
|
||||
* **deps:** update aqua-lib to 0.7.0 ([fe902ac](https://github.com/fluencelabs/trust-graph/commit/fe902acc50a6b4c6bf97c487f3e47ae0f5ef8a95))
|
||||
|
||||
## [0.4.0](https://github.com/fluencelabs/trust-graph/compare/trust-graph-api-v0.3.2...trust-graph-api-v0.4.0) (2023-03-15)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-api:** Synchronize trust-graph, wasm and api versions
|
39
aqua/labelling.aqua
Normal file
39
aqua/labelling.aqua
Normal file
@ -0,0 +1,39 @@
|
||||
import "misc.aqua"
|
||||
import get_host_certs_from from "trust-graph-api.aqua"
|
||||
|
||||
alias Error: string
|
||||
|
||||
-- TrustGraph builtin distributed with predefined certificates which used to identify Fluence Labs peers.
|
||||
-- Each certificate contains 3 trusts: self-signed fluence root trust, trust for label trust and trust to target peer.
|
||||
--
|
||||
-- Usage:
|
||||
-- on target_node:
|
||||
-- result, error <- isFluencePeer()
|
||||
--
|
||||
-- Returns:
|
||||
-- `true, nil` if `target_node` is identified as official Fluence Labs peer
|
||||
-- `false, nil` otherwise
|
||||
--
|
||||
-- Errors:
|
||||
-- if get_host_certs_from failed, `nil, error_msg` is returned
|
||||
func isFluencePeer() -> ?bool, ?Error:
|
||||
fluence_root_peer_id = "12D3KooWNbZKaPWRZ8wgjGvrxdJFz9Fq5uVwkR6ERV1f74HhPdyB"
|
||||
label_peer_id = "12D3KooWM45u7AQxsb4MuQJNYT3NWHHMLU7JTbBV66RTfF3KSzdR"
|
||||
|
||||
result: ?bool
|
||||
error: *Error
|
||||
-- get all certs issued by `label_peer_id` to current host
|
||||
certs_result <- get_host_certs_from(label_peer_id)
|
||||
|
||||
if certs_result.success:
|
||||
for cert <- certs_result.certificates:
|
||||
len <- TrustOp.array_length(cert.chain)
|
||||
if len == 3:
|
||||
if cert.chain!0.issued_for == fluence_root_peer_id:
|
||||
if cert.chain!1.issued_for == label_peer_id:
|
||||
result <<- true
|
||||
if result == nil:
|
||||
result <<- false
|
||||
else:
|
||||
error <<- certs_result.error
|
||||
<- result, error
|
@ -1,8 +1,15 @@
|
||||
import "trust-graph.aqua"
|
||||
|
||||
alias Error: string
|
||||
|
||||
-- helpers for isFluencePeer
|
||||
service TrustOp("op"):
|
||||
array_length(a: []Trust) -> u32
|
||||
|
||||
service BoolOp("op"):
|
||||
array_length(a: []bool) -> u32
|
||||
|
||||
-- check if error is not nil and append to error_stream
|
||||
func append_error(error_stream: *Error, error: ?Error):
|
||||
if error != nil:
|
||||
error_stream <<- error!
|
||||
|
11993
aqua/package-lock.json
generated
11993
aqua/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@fluencelabs/trust-graph",
|
||||
"version": "0.2.2",
|
||||
"version": "0.4.8",
|
||||
"description": "Aqua Trust Graph API library",
|
||||
"files": [
|
||||
"*.aqua"
|
||||
],
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua-lib": "^0.3.1"
|
||||
"@fluencelabs/aqua-lib": "^0.7.0"
|
||||
},
|
||||
"scripts": {
|
||||
"generate-aqua": "../service/build.sh",
|
||||
@ -31,6 +31,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/fluencelabs/trust-graph#readme",
|
||||
"devDependencies": {
|
||||
"@fluencelabs/aqua": "^0.5.2-257"
|
||||
"@fluencelabs/aqua": "^0.10.3"
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import "trust-graph.aqua"
|
||||
import Sig, Peer, PeerId from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
import "misc.aqua"
|
||||
import Sig, Peer from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
import "trust-graph.aqua"
|
||||
|
||||
alias PeerId: string
|
||||
alias Error: string
|
||||
|
||||
-- Set peer_id as a root to TG instance on current node
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Set `peer_id` as a root
|
||||
-- Self-signed trust should be added in next call for correct behaviour
|
||||
-- `max_chain_len` specifies maximum chain length after root trust,
|
||||
-- if `max_chain_len` is zero there is no trusts except self-signed root trust in certificates for this root
|
||||
@ -13,126 +13,146 @@ func set_root(peer_id: PeerId, max_chain_len: u32) -> SetRootResult:
|
||||
result <- TrustGraph.set_root(peer_id, max_chain_len)
|
||||
<- result
|
||||
|
||||
-- Create and sign trust
|
||||
-- Call context: %init_peer_id%
|
||||
-- Create on relay and sign trust on client
|
||||
-- If `issuer` is not %init_peer_id%, Sig service with `issuer` peer id as service id should be defined
|
||||
-- Errors:
|
||||
-- If TrustGraph.get_trust_bytes or TrustGraph.issue_trust fails, (nil, error) is returned.
|
||||
func issue_trust(issuer: PeerId, issued_for: PeerId, expires_at_sec: u64) -> ?Trust, ?Error:
|
||||
-- after marine-web release this will be done on %init_peer_id%
|
||||
on HOST_PEER_ID:
|
||||
issued_at_sec <- Peer.timestamp_sec()
|
||||
bytes <- TrustGraph.get_trust_bytes(issued_for, expires_at_sec, issued_at_sec)
|
||||
|
||||
result: ?Trust
|
||||
error: ?string
|
||||
error: *Error
|
||||
if bytes.success:
|
||||
if issuer != %init_peer_id%:
|
||||
Sig issuer
|
||||
else:
|
||||
Sig "sig"
|
||||
Sig issuer
|
||||
sig_res <- Sig.sign(bytes.result)
|
||||
|
||||
signature <- Sig.sign(bytes.result)
|
||||
|
||||
on HOST_PEER_ID:
|
||||
issue_result <- TrustGraph.issue_trust(issued_for, expires_at_sec, issued_at_sec, signature)
|
||||
if issue_result.success:
|
||||
result <<- issue_result.trust
|
||||
if sig_res.success:
|
||||
on HOST_PEER_ID:
|
||||
issue_result <- TrustGraph.issue_trust(issued_for, expires_at_sec, issued_at_sec, sig_res.signature!)
|
||||
if issue_result.success:
|
||||
result <<- issue_result.trust
|
||||
else:
|
||||
error <<- issue_result.error
|
||||
else:
|
||||
error <<- issue_result.error
|
||||
error <<- sig_res.error!
|
||||
else:
|
||||
error <<- bytes.error
|
||||
<- result, error
|
||||
|
||||
-- Add trust to TG instance on current node
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Add trust to TG
|
||||
-- Errors:
|
||||
-- If TrustGraph.add_trust fails, error is returned.
|
||||
func import_trust(trust: Trust, issuer: PeerId) -> ?Error:
|
||||
error: ?string
|
||||
error: *Error
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
add_result <- TrustGraph.add_trust(trust, issuer, timestamp_sec)
|
||||
if add_result.success != true:
|
||||
error <<- add_result.error
|
||||
<- error
|
||||
|
||||
-- Call context: %init_peer_id%
|
||||
-- Issue trust and add to TG instance on `node`
|
||||
-- If `issuer` is not %init_peer_id%, Sig service with `issuer` peer id as service id should be defined
|
||||
-- Errors:
|
||||
-- If issue_trust or import_trust fails, error is returned.
|
||||
func add_trust(node: PeerId, issuer: PeerId, issued_for: PeerId, expires_at_sec: u64) -> ?Error:
|
||||
trust, issue_error <- issue_trust(issuer, issued_for, expires_at_sec)
|
||||
|
||||
error: *?Error
|
||||
if trust == nil:
|
||||
error <<- issue_error
|
||||
error: *Error
|
||||
if issue_error != nil:
|
||||
error <<- issue_error!
|
||||
else:
|
||||
on node:
|
||||
error <- import_trust(trust!, issuer)
|
||||
|
||||
<- error!
|
||||
import_error <- import_trust(trust!, issuer)
|
||||
append_error(error, import_error)
|
||||
<- error
|
||||
|
||||
-- Call context: %init_peer_id%
|
||||
-- Set `peer_id` as a root and add self-signed trust to TG instance on `node`
|
||||
-- If `peer_id` is not %init_peer_id%, Sig service with `peer_id` as service id should be defined
|
||||
-- Errors:
|
||||
-- If issue_trust, import_trust or set_root fails, error is returned.
|
||||
func add_root_trust(node: PeerId, peer_id: PeerId, max_chain_len: u32, expires_at_sec: u64) -> ?Error:
|
||||
trust, issue_error <- issue_trust(peer_id, peer_id, expires_at_sec)
|
||||
|
||||
error: *?Error
|
||||
if trust == nil:
|
||||
error <<- issue_error
|
||||
error: *Error
|
||||
if issue_error != nil:
|
||||
error <<- issue_error!
|
||||
else:
|
||||
on node:
|
||||
set_root_result <- set_root(peer_id, max_chain_len)
|
||||
if set_root_result.success:
|
||||
error <- import_trust(trust!, peer_id)
|
||||
import_error <- import_trust(trust!, peer_id)
|
||||
append_error(error, import_error)
|
||||
else:
|
||||
-- converting string to ?string
|
||||
tmp: *string
|
||||
tmp <<- set_root_result.error
|
||||
error <<- tmp
|
||||
error <<- set_root_result.error
|
||||
|
||||
<- error!
|
||||
<- error
|
||||
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Check signature and expiration time of trust
|
||||
func verify_trust(trust: Trust, issuer: PeerId) -> VerifyTrustResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.verify_trust(trust, issuer, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Get the maximum weight of trust for one peer id
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Get the maximum weight of trust for `peer_id`
|
||||
-- Trust has weight if there is at least 1 trust chain from one of the roots
|
||||
func get_weight(peer_id: PeerId) -> WeightResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.get_weight(peer_id, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Get maximum weight of trust among all chains which contain trust from `issuer`
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Get maximum weight of trust for `peer_id` among all chains which contain trust from `issuer`
|
||||
func get_weight_from(peer_id: PeerId, issuer: PeerId) -> WeightResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.get_weight_from(peer_id, issuer, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Call context: %init_peer_id%
|
||||
-- Create revocation signed by %init_peer_id%
|
||||
-- If `revoked_by` is not %init_peer_id%, Sig service with `revoked_by` peer id as service id should be defined
|
||||
-- Errors:
|
||||
-- If TrustGraph.get_revocation_bytes or TrustGraph.issue_revocation fails, (nil, error) is returned.
|
||||
func issue_revocation(revoked_by: PeerId, revoked: PeerId) -> ?Revocation, ?Error:
|
||||
-- after marine-web release this will be done on %init_peer_id%
|
||||
on HOST_PEER_ID:
|
||||
issued_at_sec <- Peer.timestamp_sec()
|
||||
bytes <- TrustGraph.get_revocation_bytes(revoked, issued_at_sec)
|
||||
|
||||
result: ?Revocation
|
||||
error: ?string
|
||||
error: *Error
|
||||
if bytes.success:
|
||||
if revoked_by != %init_peer_id%:
|
||||
Sig revoked_by
|
||||
else:
|
||||
Sig "sig"
|
||||
Sig revoked_by
|
||||
|
||||
signature <- Sig.sign(bytes.result)
|
||||
sig_res <- Sig.sign(bytes.result)
|
||||
|
||||
on HOST_PEER_ID:
|
||||
issue_result <- TrustGraph.issue_revocation(revoked_by, revoked, issued_at_sec, signature)
|
||||
if issue_result.success:
|
||||
result <<- issue_result.revocation
|
||||
if sig_res.success:
|
||||
on HOST_PEER_ID:
|
||||
issue_result <- TrustGraph.issue_revocation(revoked_by, revoked, issued_at_sec, sig_res.signature!)
|
||||
if issue_result.success:
|
||||
result <<- issue_result.revocation
|
||||
else:
|
||||
error <<- issue_result.error
|
||||
else:
|
||||
error <<- issue_result.error
|
||||
error <<- sig_res.error!
|
||||
else:
|
||||
error <<- bytes.error
|
||||
<- result, error
|
||||
|
||||
-- Import revocation to current node's TG instance
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Import revocation to TG
|
||||
-- Errors:
|
||||
-- If TrustGraph.revoke fails, error is returned.
|
||||
func import_revocation(revocation: Revocation) -> ?Error:
|
||||
error: ?string
|
||||
error: *Error
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
add_result <- TrustGraph.revoke(revocation, timestamp_sec)
|
||||
if add_result.success != true:
|
||||
@ -140,68 +160,55 @@ func import_revocation(revocation: Revocation) -> ?Error:
|
||||
|
||||
<- error
|
||||
|
||||
-- Call context: %init_peer_id%
|
||||
-- Revoke all certificates on `node` TG instance
|
||||
-- which contain path from %init_peer_id% to `revoked_peer_id`
|
||||
-- If `revoked_by` is not %init_peer_id%, Sig service with `revoked_by` peer id as service id should be defined
|
||||
-- Errors:
|
||||
-- if issue_revocation or import_revocation fails, error is returned.
|
||||
func revoke(node: PeerId, revoked_by: PeerId, revoked: PeerId) -> ?Error:
|
||||
revocation, issue_error <- issue_revocation(revoked_by, revoked)
|
||||
|
||||
error: *?string
|
||||
error: *Error
|
||||
if revocation == nil:
|
||||
error <<- issue_error
|
||||
error <<- issue_error!
|
||||
else:
|
||||
on node:
|
||||
error <- import_revocation(revocation!)
|
||||
|
||||
<- error!
|
||||
|
||||
|
||||
import_error <- import_revocation(revocation!)
|
||||
append_error(error, import_error)
|
||||
<- error
|
||||
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Return all certificates issued for current node which contains trust from `issuer`
|
||||
func get_host_certs_from(issuer: PeerId) -> AllCertsResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.get_host_certs_from(issuer, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Return all certificates issued for given peer id
|
||||
func get_all_certs(issued_for: PeerId) -> AllCertsResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.get_all_certs(issued_for, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Return all certificates issued for given peer id which contains trust from `issuer`
|
||||
func get_all_certs_from(issued_for: PeerId, issuer: PeerId) -> AllCertsResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.get_all_certs_from(issued_for, issuer, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Return all certificates issued for current node
|
||||
func get_host_certs() -> AllCertsResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.get_host_certs(timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- Call context: any node with registered `trust-graph` service
|
||||
-- Insert certificate to TG instance on current node
|
||||
func insert_cert(certificate: Certificate) -> InsertResult:
|
||||
timestamp_sec <- Peer.timestamp_sec()
|
||||
result <- TrustGraph.insert_cert(certificate, timestamp_sec)
|
||||
<- result
|
||||
|
||||
-- returns `true` if current node is identified as official Fluence Labs peer
|
||||
-- returns `false` otherwise
|
||||
func isFluencePeer() -> ?bool, ?Error:
|
||||
certs_result <- get_host_certs_from("12D3KooWM45u7AQxsb4MuQJNYT3NWHHMLU7JTbBV66RTfF3KSzdR")
|
||||
result: ?bool
|
||||
error: ?string
|
||||
if certs_result.success:
|
||||
for cert <- certs_result.certificates:
|
||||
len <- TrustOp.array_length(cert.chain)
|
||||
if len == 3:
|
||||
if cert.chain!0.issued_for == "12D3KooWNbZKaPWRZ8wgjGvrxdJFz9Fq5uVwkR6ERV1f74HhPdyB":
|
||||
if cert.chain!1.issued_for == "12D3KooWM45u7AQxsb4MuQJNYT3NWHHMLU7JTbBV66RTfF3KSzdR":
|
||||
result <<- true
|
||||
if result == nil:
|
||||
result <<- false
|
||||
else:
|
||||
error <<- certs_result.error
|
||||
<- result, error
|
||||
|
15
build.sh
Executable file
15
build.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
# set current working directory to script directory to run script from everywhere
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
./service/build.sh
|
||||
|
||||
TARGET="distro/trust-graph-service/"
|
||||
|
||||
mkdir -p "$TARGET"
|
||||
cp -v ./distro/init_certs.json service/artifacts/trust-graph.wasm service/artifacts/sqlite3.wasm distro/Config.toml "$TARGET"
|
||||
|
||||
cd distro
|
||||
cargo build
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "trust-graph",
|
||||
"dependencies": [
|
||||
"name:sqlite3",
|
||||
"name:trust-graph"
|
||||
]
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
(seq
|
||||
(seq
|
||||
; set fluence root peer id as TG root
|
||||
(call relay ("trust-graph" "set_root") ["12D3KooWNbZKaPWRZ8wgjGvrxdJFz9Fq5uVwkR6ERV1f74HhPdyB" 5] add_root_res)
|
||||
(xor
|
||||
(match add_root_res.$.success! true
|
||||
@ -14,6 +15,7 @@
|
||||
(seq
|
||||
(seq
|
||||
(call relay ("peer" "timestamp_sec") [] cur_time)
|
||||
; insert all certificates from on_start.json
|
||||
(call relay ("trust-graph" "insert_cert") [i cur_time] insert_result)
|
||||
)
|
||||
(xor
|
||||
|
File diff suppressed because one or more lines are too long
@ -3,20 +3,39 @@ set -o pipefail -o nounset -o errexit
|
||||
|
||||
# set current working directory to script directory to run script from everywhere
|
||||
cd "$(dirname "$0")"
|
||||
SCRIPT_DIR="$(pwd)"
|
||||
PACKAGE_DIR="$(pwd)/../package/trust-graph"
|
||||
|
||||
(
|
||||
rm -rf $PACKAGE_DIR/*
|
||||
mkdir -p $PACKAGE_DIR
|
||||
)
|
||||
|
||||
(
|
||||
echo "*** copy wasm files ***"
|
||||
cd ../service
|
||||
cp artifacts/*.wasm "$SCRIPT_DIR"
|
||||
cp artifacts/*.wasm "$PACKAGE_DIR"
|
||||
)
|
||||
|
||||
(
|
||||
echo "*** copy on_start script ***"
|
||||
cp on_start.json "$PACKAGE_DIR"
|
||||
cp on_start.air "$PACKAGE_DIR"
|
||||
)
|
||||
|
||||
TRUST_GRAPH_CID=$(ipfs add -q --only-hash --cid-version=1 --chunker=size-262144 $PACKAGE_DIR/trust-graph.wasm)
|
||||
SQLITE_CID=$(ipfs add -q --only-hash --cid-version=1 --chunker=size-262144 $PACKAGE_DIR/sqlite3.wasm)
|
||||
mv $PACKAGE_DIR/trust-graph.wasm "$PACKAGE_DIR"/"$TRUST_GRAPH_CID".wasm
|
||||
mv $PACKAGE_DIR/sqlite3.wasm "$PACKAGE_DIR"/"$SQLITE_CID".wasm
|
||||
cp trust-graph_config.json "$PACKAGE_DIR"/"$TRUST_GRAPH_CID"_config.json
|
||||
cp sqlite3_config.json "$PACKAGE_DIR"/"$SQLITE_CID"_config.json
|
||||
|
||||
# write blueprint.json
|
||||
echo "{}" | jq --arg trust_graph_cid "$TRUST_GRAPH_CID" --arg sqlite_cid "$SQLITE_CID" '{"name": "trust-graph", "dependencies":[{"/":$sqlite_cid},{"/":$trust_graph_cid}]}' > "$PACKAGE_DIR/blueprint.json"
|
||||
|
||||
(
|
||||
echo "*** create builtin distribution package ***"
|
||||
cd ..
|
||||
mv builtin-package trust-graph
|
||||
tar --exclude="package.sh" -f trust-graph.tar.gz -zcv ./trust-graph
|
||||
mv trust-graph builtin-package
|
||||
cd $PACKAGE_DIR/..
|
||||
tar -f ../trust-graph.tar.gz -zcv ./trust-graph
|
||||
)
|
||||
|
||||
echo "*** done ***"
|
||||
|
27
distro/CHANGELOG.md
Normal file
27
distro/CHANGELOG.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
## [0.4.8](https://github.com/fluencelabs/trust-graph/compare/distro-v0.4.7...distro-v0.4.8) (2023-12-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update marine sdk's, configs and sqlite connector ([#129](https://github.com/fluencelabs/trust-graph/issues/129)) ([0b66f4e](https://github.com/fluencelabs/trust-graph/commit/0b66f4e0536633879de46f69ac8391c72ece7e77))
|
||||
|
||||
## [0.4.7](https://github.com/fluencelabs/trust-graph/compare/distro-v0.4.6...distro-v0.4.7) (2023-07-04)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **distro:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.6](https://github.com/fluencelabs/trust-graph/compare/distro-v0.4.5...distro-v0.4.6) (2023-06-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add distro crate [fixes NET-463] ([#93](https://github.com/fluencelabs/trust-graph/issues/93)) ([3ba3855](https://github.com/fluencelabs/trust-graph/commit/3ba3855892ae355962212a0a42099dd9f9820800))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* release master ([#110](https://github.com/fluencelabs/trust-graph/issues/110)) ([d80a43b](https://github.com/fluencelabs/trust-graph/commit/d80a43bcff721aff8fadf3d2d5c252804ce27a6c))
|
18
distro/Cargo.toml
Normal file
18
distro/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "trust-graph-distro"
|
||||
version = "0.4.8"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
license = "Apache-2.0"
|
||||
include = [ "/src", "build.rs", "Cargo.toml", "trust-graph-service"]
|
||||
description = "Distribution package for the trust-graph service"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[dependencies]
|
||||
maplit = "1.0.2"
|
||||
serde = "1.0.160"
|
||||
serde_json = "1.0.96"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[build-dependencies]
|
||||
built = "0.6.0"
|
15
distro/Config.toml
Normal file
15
distro/Config.toml
Normal file
@ -0,0 +1,15 @@
|
||||
modules_dir = "."
|
||||
total_memory_limit = "Infinity"
|
||||
|
||||
[[module]]
|
||||
name = "sqlite3"
|
||||
logger_enabled = true
|
||||
|
||||
[module.wasi]
|
||||
mapped_dirs = { "tmp" = "data" }
|
||||
[[module]]
|
||||
name = "trust-graph"
|
||||
logger_enabled = true
|
||||
|
||||
[module.wasi]
|
||||
mapped_dirs = { "tmp" = "data" }
|
3
distro/build.rs
Normal file
3
distro/build.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
built::write_built_file().expect("Failed to acquire build-time information")
|
||||
}
|
1
distro/init_certs.json
Normal file
1
distro/init_certs.json
Normal file
File diff suppressed because one or more lines are too long
60
distro/src/lib.rs
Normal file
60
distro/src/lib.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(not(feature = "cargo-clippy"))]
|
||||
pub const TRUST_GRAPH_WASM: &[u8] = include_bytes!("../trust-graph-service/trust-graph.wasm");
|
||||
#[cfg(feature = "cargo-clippy")]
|
||||
pub const TRUST_GRAPH_WASM: &[u8] = &[];
|
||||
|
||||
#[cfg(not(feature = "cargo-clippy"))]
|
||||
pub const SQLITE_WASM: &[u8] = include_bytes!("../trust-graph-service/sqlite3.wasm");
|
||||
#[cfg(feature = "cargo-clippy")]
|
||||
pub const SQLITE_WASM: &[u8] = &[];
|
||||
|
||||
#[cfg(not(feature = "cargo-clippy"))]
|
||||
pub const CONFIG: &[u8] = include_bytes!("../trust-graph-service/Config.toml");
|
||||
#[cfg(feature = "cargo-clippy")]
|
||||
pub const CONFIG: &[u8] = &[];
|
||||
|
||||
#[cfg(not(feature = "cargo-clippy"))]
|
||||
pub const KRAS_CERTS_JSON: &str = include_str!("../trust-graph-service/init_certs.json");
|
||||
#[cfg(feature = "cargo-clippy")]
|
||||
pub const KRAS_CERTS_JSON: &str = "{}";
|
||||
|
||||
pub mod build_info {
|
||||
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
||||
}
|
||||
|
||||
pub use build_info::PKG_VERSION as VERSION;
|
||||
|
||||
pub fn modules() -> std::collections::HashMap<&'static str, &'static [u8]> {
|
||||
maplit::hashmap! {
|
||||
"sqlite3" => SQLITE_WASM,
|
||||
"trust-graph" => TRUST_GRAPH_WASM,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Certs {
|
||||
pub root_node: String,
|
||||
pub max_chain_length: u32,
|
||||
pub certs: Vec<Cert>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Cert {
|
||||
pub chain: Vec<Trust>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct Trust {
|
||||
pub issued_for: String,
|
||||
pub expires_at: u64,
|
||||
pub signature: String,
|
||||
pub sig_type: String,
|
||||
pub issued_at: u64,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref KRAS_CERTS: Certs = serde_json::from_str(KRAS_CERTS_JSON).unwrap();
|
||||
}
|
@ -1,10 +1,49 @@
|
||||
## Description
|
||||
This example shows how to use Trust Graph to label peers. There are some `trusted_computation` which can only be executed
|
||||
on labeled peer. The label is determined by the presence of certificate from `%init_peer_id` to this peer.
|
||||
This example shows how to use Trust Graph for code execution only on trusted peers. There are some `trusted_computation` which can only be performed on a trusted peer. The label is determined by the presence of the certificate from `INIT_PEER_ID` to this peer. We use peer id from [`example_secret_key.ed25519`](../example_secret_key.ed25519) as `INIT_PEER_ID` since every node bundled with the certificate issued to this key, it should be used only for test purposes.
|
||||
|
||||
## Run example on network
|
||||
|
||||
1. Run `npm i`
|
||||
2. Run `npm run start`
|
||||
|
||||
|
||||
## Run example on network
|
||||
1. Run `npm i`
|
||||
2. Run `npm run start`
|
||||
|
||||
## Run example locally
|
||||
|
||||
1. Go to `local-network`
|
||||
2. Run `docker compose up -d` to start Fluence node
|
||||
3. Go back to `../example`
|
||||
4. Run `npm i`
|
||||
5. Run `npm run start`
|
||||
3. It takes some time depending on your machine for node to start and builtin services deployed. Wait for this log line: `[2022-07-06T11:33:50.782054Z INFO particle_node] Fluence has been successfully started.`
|
||||
4. Go back to `../example`
|
||||
5. Run `npm i`
|
||||
6. Run `npm run start local`
|
||||
|
||||
## Expected output
|
||||
|
||||
After successful execution you will get this result:
|
||||
```
|
||||
In this example we try to execute some trusted computations based on trusts
|
||||
📘 Will connect to testNet
|
||||
📗 created a fluence peer 12D3KooWD2vAZva1u3TQgoxebBUBsaGMNawKjVkp57M6UcwNwXNv with relay 12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9
|
||||
|
||||
📕 Trusted computation on node 12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9 failed, error: there is no certs for this peer
|
||||
📕 Trusted computation on node 12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz failed, error: there is no certs for this peer
|
||||
📕 Trusted computation on node 12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er failed, error: there is no certs for this peer
|
||||
|
||||
🌀 Issue trust to nodeB 12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz and nodeC: 12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er
|
||||
Trust issued for 12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz successfully added
|
||||
Trust issued for 12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er successfully added
|
||||
|
||||
📕 Trusted computation on node 12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9 failed, error: there is no certs for this peer
|
||||
📗 Trusted computation on node 12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz successful, result is 5
|
||||
📗 Trusted computation on node 12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er successful, result is 5
|
||||
|
||||
🚫 Revoke trust to nodeB
|
||||
Trust issued for 12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz revoked
|
||||
|
||||
📕 Trusted computation on node 12D3KooWEXNUbCXooUwHrHBbrmjsrpHXoEphPwbjQXEGyzbqKnE9 failed, error: there is no certs for this peer
|
||||
📕 Trusted computation on node 12D3KooWMhVpgfQxBLkQkJed8VFNvgN4iE6MD7xCybb1ZYWW2Gtz failed, error: there is no certs for this peer
|
||||
📗 Trusted computation on node 12D3KooWHk9BjDQBUqnavciRPhAYFvqKBe4ZiPPvde7vDaqgn5er successful, result is 5
|
||||
```
|
||||
|
@ -11,8 +11,9 @@ service CertOp("op"):
|
||||
service TrustedComputation("op"):
|
||||
identity(s: u64) -> u64
|
||||
|
||||
func trusted_computation(node: string) -> ?u64:
|
||||
func trusted_computation(node: string) -> ?u64, ?string:
|
||||
result: ?u64
|
||||
error: ?string
|
||||
-- on our trusted relay
|
||||
on HOST_PEER_ID:
|
||||
-- get all certificates issued for given node by our client's peer id
|
||||
@ -20,8 +21,11 @@ func trusted_computation(node: string) -> ?u64:
|
||||
if certs_result.success:
|
||||
len <- CertOp.array_length(certs_result.certificates)
|
||||
-- if there is any certificate node is trusted and computation is possible
|
||||
if len != 0:
|
||||
on node:
|
||||
result <- TrustedComputation.identity(5)
|
||||
|
||||
<- result
|
||||
if len != 0:
|
||||
on node:
|
||||
result <- TrustedComputation.identity(5)
|
||||
else:
|
||||
error <<- "there is no certs for this peer"
|
||||
else:
|
||||
error <<- certs_result.error
|
||||
<- result, error
|
||||
|
@ -1,5 +1,6 @@
|
||||
module Export
|
||||
import add_root_trust, add_trust, revoke from "@fluencelabs/trust-graph/trust-graph-api.aqua"
|
||||
export add_root_trust, add_trust, revoke
|
||||
export add_root_trust, add_trust, revoke, timestamp_sec
|
||||
import Peer from "@fluencelabs/aqua-lib/builtin.aqua"
|
||||
|
||||
alias PeerId: string
|
||||
@ -8,6 +9,3 @@ func timestamp_sec() -> u64:
|
||||
on HOST_PEER_ID:
|
||||
result <- Peer.timestamp_sec()
|
||||
<- result
|
||||
|
||||
service Sig:
|
||||
sign(msg: []u8) -> []u8
|
||||
|
@ -14,12 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {trusted_computation} from "./generated/computation";
|
||||
import { trusted_computation } from "./generated/computation";
|
||||
import * as tg from "./generated/export";
|
||||
import {Fluence, FluencePeer, KeyPair} from "@fluencelabs/fluence";
|
||||
import {krasnodar, Node, testNet, stage} from "@fluencelabs/fluence-network-environment";
|
||||
import { Fluence, FluencePeer, KeyPair } from "@fluencelabs/fluence";
|
||||
import { krasnodar, Node, testNet, stage } from "@fluencelabs/fluence-network-environment";
|
||||
import assert from "assert";
|
||||
import {add_root_trust, registerSig} from "./generated/export";
|
||||
const bs58 = require('bs58');
|
||||
|
||||
let local: Node[] = [
|
||||
@ -40,19 +39,14 @@ let local: Node[] = [
|
||||
},
|
||||
];
|
||||
|
||||
async function revoke_all(relay: string, revoked_by: string) {
|
||||
for (var node of local) {
|
||||
async function revoke_all(relay: string, revoked_by: string, nodes: Node[]) {
|
||||
for (var node of nodes) {
|
||||
let error = await tg.revoke(relay, revoked_by, node.peerId);
|
||||
console.log(error)
|
||||
assert(error == null);
|
||||
if (error !== null) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
async function add_root(relay: string, peer_id: string) {
|
||||
let current_time = await tg.timestamp_sec();
|
||||
let far_future = current_time + 9999999;
|
||||
let error = await tg.add_root_trust(relay, peer_id, 2, far_future);
|
||||
assert(error == null);
|
||||
}
|
||||
|
||||
async function add_new_trust_checked(relay: string, issuer: string, issued_for_peer_id: string, expires_at_sec: number) {
|
||||
let error = await tg.add_trust(relay, issuer, issued_for_peer_id, expires_at_sec);
|
||||
@ -73,24 +67,23 @@ async function revoke_checked(relay: string, revoked_by: string, revoked_peer_id
|
||||
}
|
||||
|
||||
async function exec_trusted_computation(node: string) {
|
||||
let result = await trusted_computation(node)
|
||||
let [result, error] = await trusted_computation(node)
|
||||
|
||||
if (result !== null) {
|
||||
console.log("📗 Trusted computation on node %s successful, result is %s", node, result)
|
||||
} else {
|
||||
console.log("📕 Trusted computation on node %s failed", node)
|
||||
console.log("📕 Trusted computation on node %s failed, error:", node, error)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log("In this example we try to execute some trusted computations based on trusts");
|
||||
console.log("📘 Will connect to local nodes");
|
||||
// key from local-network/builtins_secret_key.ed25519 to connect as builtins owner
|
||||
let sk = bs58.decode("5FwE32bDcphFzuMca7Y2qW1gdR64fTBYoRNvD4MLE1hecDGhCMQGKn8aseMr5wRo4Xo2CRFdrEAawUNLYkgQD78K").slice(0, 32); // first 32 bytes - secret key, second - public key
|
||||
async function main(nodes: Node[]) {
|
||||
// example_secret_key.ed25519
|
||||
let sk = bs58.decode("E5ay3731i4HN8XjJozouV92RDMGAn3qSnb9dKSnujiWv");
|
||||
|
||||
let builtins_keypair = await KeyPair.fromEd25519SK(sk);
|
||||
|
||||
let relay = local[0];
|
||||
await Fluence.start({ connectTo: relay, KeyPair: builtins_keypair});
|
||||
let relay = nodes[0];
|
||||
await Fluence.start({ connectTo: relay, KeyPair: builtins_keypair });
|
||||
console.log(
|
||||
"📗 created a fluence peer %s with relay %s",
|
||||
Fluence.getStatus().peerId,
|
||||
@ -103,41 +96,55 @@ async function main() {
|
||||
let far_future = current_time + 9999999;
|
||||
|
||||
// clear all trusts from our peer id on relay
|
||||
await revoke_all(relay.peerId, local_peer_id);
|
||||
await revoke_all(relay.peerId, local_peer_id, nodes.slice(0, 3));
|
||||
|
||||
// wait to be sure that last revocation will be older than future trusts at least on 1 second (because timestamp in secs)
|
||||
await new Promise(f => setTimeout(f, 1000));
|
||||
|
||||
// set our peer id as root to our relay
|
||||
await add_root(relay.peerId, local_peer_id);
|
||||
|
||||
let nodeA = local[0].peerId
|
||||
let nodeB = local[1].peerId
|
||||
let nodeC = local[2].peerId
|
||||
let nodeA = nodes[0].peerId
|
||||
let nodeB = nodes[1].peerId
|
||||
let nodeC = nodes[2].peerId
|
||||
|
||||
console.log();
|
||||
// try to exec computation on every node, will fail
|
||||
await exec_trusted_computation(nodeA); // fail
|
||||
await exec_trusted_computation(nodeB); // fail
|
||||
await exec_trusted_computation(nodeC); // fail
|
||||
|
||||
console.log("🌀 Issue trust to nodeB: %s", nodeB);
|
||||
console.log();
|
||||
console.log("🌀 Issue trust to nodeB %s and nodeC: %s", nodeB, nodeC);
|
||||
await add_new_trust_checked(relay.peerId, local_peer_id, nodeB, far_future);
|
||||
await add_new_trust_checked(relay.peerId, local_peer_id, nodeC, far_future);
|
||||
|
||||
console.log();
|
||||
await exec_trusted_computation(nodeA); // fail
|
||||
await exec_trusted_computation(nodeB); // success
|
||||
await exec_trusted_computation(nodeC); // fail
|
||||
await exec_trusted_computation(nodeC); // success
|
||||
console.log();
|
||||
|
||||
await new Promise(f => setTimeout(f, 1000));
|
||||
console.log("🚫 Revoke trust to nodeB");
|
||||
await revoke_checked(relay.peerId, local_peer_id, nodeB);
|
||||
|
||||
console.log();
|
||||
await exec_trusted_computation(nodeA); // fail
|
||||
await exec_trusted_computation(nodeB); // fail
|
||||
await exec_trusted_computation(nodeC); // fail
|
||||
await exec_trusted_computation(nodeC); // success
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("In this example we try to execute some trusted computations based on trusts");
|
||||
let args = process.argv.slice(2);
|
||||
var environment: Node[];
|
||||
if (args.length >= 1 && args[0] == "local") {
|
||||
environment = local;
|
||||
console.log("📘 Will connect to local nodes");
|
||||
} else {
|
||||
environment = testNet;
|
||||
console.log("📘 Will connect to testNet");
|
||||
}
|
||||
|
||||
main()
|
||||
main(environment)
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
9687
example/package-lock.json
generated
9687
example/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -13,14 +13,14 @@
|
||||
"author": "Fluence Labs",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fluencelabs/aqua": "^0.5.2-257",
|
||||
"@fluencelabs/aqua-lib": "^0.3.2",
|
||||
"@fluencelabs/fluence": "^0.18.0",
|
||||
"@fluencelabs/aqua-lib": "^0.6.0",
|
||||
"@fluencelabs/fluence": "^0.23.0",
|
||||
"@fluencelabs/fluence-network-environment": "^1.0.10",
|
||||
"@fluencelabs/trust-graph": "file:../aqua",
|
||||
"bs58": "^4.0.1"
|
||||
"@fluencelabs/trust-graph": "3.1.2",
|
||||
"bs58": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.5.2"
|
||||
"typescript": "^4.5.2",
|
||||
"@fluencelabs/aqua": "^0.10.0"
|
||||
}
|
||||
}
|
||||
|
BIN
images/diagram.png
Normal file
BIN
images/diagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 295 KiB |
BIN
images/revocation.png
Normal file
BIN
images/revocation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
BIN
images/weights.png
Normal file
BIN
images/weights.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
75
keypair/CHANGELOG.md
Normal file
75
keypair/CHANGELOG.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.10.4](https://github.com/fluencelabs/trust-graph/compare/keypair-v0.10.3...keypair-v0.10.4) (2023-12-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **fluence-keypair:** bump ed25519-dalek to 0.2.0 ([#127](https://github.com/fluencelabs/trust-graph/issues/127)) ([ed5bd2c](https://github.com/fluencelabs/trust-graph/commit/ed5bd2c0ec50bef5ac7a12deacb73da491666912))
|
||||
* update marine sdk's, configs and sqlite connector ([#129](https://github.com/fluencelabs/trust-graph/issues/129)) ([0b66f4e](https://github.com/fluencelabs/trust-graph/commit/0b66f4e0536633879de46f69ac8391c72ece7e77))
|
||||
|
||||
## [0.10.3](https://github.com/fluencelabs/trust-graph/compare/keypair-v0.10.2...keypair-v0.10.3) (2023-07-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **keypair:** deserialize libp2p keypair from secret key ([#116](https://github.com/fluencelabs/trust-graph/issues/116)) ([ee330a7](https://github.com/fluencelabs/trust-graph/commit/ee330a715a902e48fc9b61d662ffcd950a26379c))
|
||||
|
||||
## [0.10.2](https://github.com/fluencelabs/trust-graph/compare/keypair-v0.10.1...keypair-v0.10.2) (2023-06-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update libp2p identity ([#109](https://github.com/fluencelabs/trust-graph/issues/109)) ([d04120b](https://github.com/fluencelabs/trust-graph/commit/d04120bacf802a7e1127f4955b7391b0a4353128))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **keypair:** update description ([#105](https://github.com/fluencelabs/trust-graph/issues/105)) ([f7ef0f8](https://github.com/fluencelabs/trust-graph/commit/f7ef0f8da095fe1fef80faaa0b0c2d5ef854bd16))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* release master ([#110](https://github.com/fluencelabs/trust-graph/issues/110)) ([d80a43b](https://github.com/fluencelabs/trust-graph/commit/d80a43bcff721aff8fadf3d2d5c252804ce27a6c))
|
||||
|
||||
## [0.10.1](https://github.com/fluencelabs/trust-graph/compare/keypair-v0.10.0...keypair-v0.10.1) (2023-05-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **keypair:** Make `KeyFormat` more convenient ([#91](https://github.com/fluencelabs/trust-graph/issues/91)) ([9b942ea](https://github.com/fluencelabs/trust-graph/commit/9b942eacca49d0468b4d7512667102363a6c9aa3))
|
||||
|
||||
## [0.10.0](https://github.com/fluencelabs/trust-graph/compare/keypair-v0.9.0...keypair-v0.10.0) (2023-03-15)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **deps:** update libp2p to 0.39.1 and other deps ([#77](https://github.com/fluencelabs/trust-graph/issues/77))
|
||||
|
||||
### Features
|
||||
|
||||
* **deps:** update libp2p to 0.39.1 and other deps ([#77](https://github.com/fluencelabs/trust-graph/issues/77)) ([080503d](https://github.com/fluencelabs/trust-graph/commit/080503dcfa2ecf8d09167ff9fe7f750fadf49035))
|
||||
* **keypair:** add KeyPair::from_secret_key ([#50](https://github.com/fluencelabs/trust-graph/issues/50)) ([a6ce8d9](https://github.com/fluencelabs/trust-graph/commit/a6ce8d9eee20e1ea24eb27c38ac6df6d878292ae))
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.8.1] - 2022-10-06
|
||||
|
||||
### Added
|
||||
- *(keypair)* add KeyPair::from_secret_key (#50)
|
||||
|
||||
### Other
|
||||
- set version of fluence-keypair to 0.8.0
|
||||
- fluence-keypair 0.8.0
|
||||
- libp2p-core 0.33.0 (#49)
|
||||
- remove circle, update gh, add lints; remove warnings (#43)
|
||||
- fluence-keypair 0.6.0
|
||||
- libp2p-core 0.31.0 (from crates.io) (#37)
|
||||
- Remove serde version lock (#15)
|
||||
- Fix revocations logic (#34)
|
||||
- Trust Graph: implement WASM built-in (#18)
|
||||
- Move fluence-identity to fluence-keypair (#17)
|
1497
keypair/Cargo.lock
generated
1497
keypair/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,33 +1,30 @@
|
||||
[package]
|
||||
name = "fluence-keypair"
|
||||
version = "0.5.1"
|
||||
version = "0.10.4"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
description = "identity"
|
||||
edition = "2021"
|
||||
description = "unified keypair API based on libp2p-identity"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/fluencelabs/trust-graph"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "=1.0.118", features = ["derive"] }
|
||||
serde_json = "1.0.58"
|
||||
bs58 = "0.3.1"
|
||||
ed25519-dalek = { version = "1.0.1", features = ["serde", "std"] }
|
||||
rand = "0.7.0"
|
||||
signature = "1.3.0"
|
||||
ed25519 = "1.0.3"
|
||||
serde_with = "1.6.0"
|
||||
serde = { version = "1.0.118", features = ["derive"] }
|
||||
bs58 = "0.5.0"
|
||||
ed25519-dalek = { version = "2.0.0", features = ["serde", "std", "rand_core"] }
|
||||
rand = "0.8.5"
|
||||
thiserror = "1.0.23"
|
||||
lazy_static = "1.2"
|
||||
libsecp256k1 = "0.3.1"
|
||||
lazy_static = "1.4"
|
||||
libsecp256k1 = "0.7.1"
|
||||
asn1_der = "0.6.1"
|
||||
sha2 = "0.9.1"
|
||||
sha2 = "0.10.6"
|
||||
zeroize = "1"
|
||||
serde_bytes = "0.11"
|
||||
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.27.2", features = ["secp256k1"]}
|
||||
eyre = "0.6.5"
|
||||
libp2p-identity = { workspace = true, default-features = false, features = ["peerid", "rsa", "ed25519", "secp256k1"] }
|
||||
multihash = { version = "0.18.0", features = ["identity"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
ring = { version = "0.16.9", features = ["alloc", "std"], default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.9.0"
|
||||
quickcheck = "1.0.3"
|
||||
|
3
keypair/rust-toolchain.toml
Normal file
3
keypair/rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-12-06"
|
||||
targets = [ "x86_64-apple-darwin", "x86_64-unknown-linux-gnu" ]
|
@ -19,16 +19,16 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
//! Ed25519 keys.
|
||||
use crate::error::{DecodingError, SigningError, VerificationError};
|
||||
use crate::error::{DecodingError, DecodingError::InvalidLength, SigningError, VerificationError};
|
||||
use core::fmt;
|
||||
use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
|
||||
use rand::RngCore;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
use zeroize::Zeroize;
|
||||
|
||||
/// An Ed25519 keypair.
|
||||
pub struct Keypair(ed25519::Keypair);
|
||||
/// An Ed25519 keypair
|
||||
#[derive(Clone)]
|
||||
pub struct Keypair(ed25519::SigningKey);
|
||||
|
||||
impl Keypair {
|
||||
/// Generate a new Ed25519 keypair.
|
||||
@ -40,13 +40,15 @@ impl Keypair {
|
||||
/// of the secret scalar and the compressed public point,
|
||||
/// an informal standard for encoding Ed25519 keypairs.
|
||||
pub fn encode(&self) -> [u8; 64] {
|
||||
self.0.to_bytes()
|
||||
self.0.to_keypair_bytes()
|
||||
}
|
||||
|
||||
/// Decode a keypair from the format produced by `encode`,
|
||||
/// zeroing the input on success.
|
||||
pub fn decode(kp: &mut [u8]) -> Result<Self, DecodingError> {
|
||||
ed25519::Keypair::from_bytes(kp)
|
||||
let bytes = <[u8; 64]>::try_from(&*kp).map_err(InvalidLength)?;
|
||||
|
||||
ed25519::SigningKey::from_keypair_bytes(&bytes)
|
||||
.map(|k| {
|
||||
kp.zeroize();
|
||||
Keypair(k)
|
||||
@ -61,12 +63,12 @@ impl Keypair {
|
||||
|
||||
/// Get the public key of this keypair.
|
||||
pub fn public(&self) -> PublicKey {
|
||||
PublicKey(self.0.public)
|
||||
PublicKey(self.0.verifying_key())
|
||||
}
|
||||
|
||||
/// Get the secret key of this keypair.
|
||||
pub fn secret(&self) -> SecretKey {
|
||||
SecretKey::from_bytes(&mut self.0.secret.to_bytes())
|
||||
SecretKey::from_bytes(&mut self.0.to_bytes())
|
||||
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
|
||||
}
|
||||
}
|
||||
@ -74,26 +76,14 @@ impl Keypair {
|
||||
impl fmt::Debug for Keypair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Keypair")
|
||||
.field("public", &self.0.public)
|
||||
.field("public", &self.0.verifying_key())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Keypair {
|
||||
fn clone(&self) -> Self {
|
||||
let mut sk_bytes = self.0.secret.to_bytes();
|
||||
let secret = SecretKey::from_bytes(&mut sk_bytes)
|
||||
.expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
|
||||
.0;
|
||||
let public = ed25519::PublicKey::from_bytes(&self.0.public.to_bytes())
|
||||
.expect("ed25519::PublicKey::from_bytes(to_bytes(k)) != k");
|
||||
Keypair(ed25519::Keypair { secret, public })
|
||||
}
|
||||
}
|
||||
|
||||
/// Build keypair from existing ed25519 keypair
|
||||
impl From<ed25519::Keypair> for Keypair {
|
||||
fn from(kp: ed25519::Keypair) -> Self {
|
||||
impl From<ed25519::SigningKey> for Keypair {
|
||||
fn from(kp: ed25519::SigningKey) -> Self {
|
||||
Keypair(kp)
|
||||
}
|
||||
}
|
||||
@ -101,25 +91,21 @@ impl From<ed25519::Keypair> for Keypair {
|
||||
/// Demote an Ed25519 keypair to a secret key.
|
||||
impl From<Keypair> for SecretKey {
|
||||
fn from(kp: Keypair) -> Self {
|
||||
SecretKey(kp.0.secret)
|
||||
SecretKey(kp.0.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
/// Promote an Ed25519 secret key into a keypair.
|
||||
impl From<SecretKey> for Keypair {
|
||||
fn from(sk: SecretKey) -> Self {
|
||||
let secret: ed25519::ExpandedSecretKey = (&sk.0).into();
|
||||
let public = ed25519::PublicKey::from(&secret);
|
||||
Keypair(ed25519::Keypair {
|
||||
secret: sk.0,
|
||||
public,
|
||||
})
|
||||
let signing = ed25519::SigningKey::from_bytes(&sk.0);
|
||||
Keypair(signing)
|
||||
}
|
||||
}
|
||||
|
||||
/// An Ed25519 public key.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct PublicKey(ed25519::PublicKey);
|
||||
pub struct PublicKey(ed25519::VerifyingKey);
|
||||
|
||||
impl PublicKey {
|
||||
/// Verify the Ed25519 signature on a message using the public key.
|
||||
@ -143,26 +129,21 @@ impl PublicKey {
|
||||
|
||||
/// Decode a public key from a byte array as produced by `encode`.
|
||||
pub fn decode(bytes: &[u8]) -> Result<Self, DecodingError> {
|
||||
ed25519::PublicKey::from_bytes(bytes)
|
||||
let bytes = <[u8; 32]>::try_from(bytes).map_err(InvalidLength)?;
|
||||
ed25519::VerifyingKey::from_bytes(&bytes)
|
||||
.map_err(DecodingError::Ed25519)
|
||||
.map(PublicKey)
|
||||
}
|
||||
}
|
||||
|
||||
/// An Ed25519 secret key.
|
||||
#[derive(Clone)]
|
||||
pub struct SecretKey(pub ed25519::SecretKey);
|
||||
|
||||
/// View the bytes of the secret key.
|
||||
impl AsRef<[u8]> for SecretKey {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for SecretKey {
|
||||
fn clone(&self) -> Self {
|
||||
let mut sk_bytes = self.0.to_bytes();
|
||||
Self::from_bytes(&mut sk_bytes).expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,13 +156,8 @@ impl fmt::Debug for SecretKey {
|
||||
impl SecretKey {
|
||||
/// Generate a new Ed25519 secret key.
|
||||
pub fn generate() -> Self {
|
||||
let mut bytes = [0u8; 32];
|
||||
rand::thread_rng().fill_bytes(&mut bytes);
|
||||
SecretKey(
|
||||
ed25519::SecretKey::from_bytes(&bytes).expect(
|
||||
"this returns `Err` only if the length is wrong; the length is correct; qed",
|
||||
),
|
||||
)
|
||||
let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
|
||||
SecretKey(signing.to_bytes())
|
||||
}
|
||||
|
||||
/// Create an Ed25519 secret key from a byte slice, zeroing the input on success.
|
||||
@ -189,7 +165,7 @@ impl SecretKey {
|
||||
/// returned.
|
||||
pub fn from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<Self, DecodingError> {
|
||||
let sk_bytes = sk_bytes.as_mut();
|
||||
let secret = ed25519::SecretKey::from_bytes(&*sk_bytes).map_err(DecodingError::Ed25519)?;
|
||||
let secret = <[u8; 32]>::try_from(&*sk_bytes).map_err(InvalidLength)?;
|
||||
sk_bytes.zeroize();
|
||||
Ok(SecretKey(secret))
|
||||
}
|
||||
@ -201,10 +177,11 @@ pub struct Signature(pub Vec<u8>);
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::KeyPair;
|
||||
use quickcheck::*;
|
||||
|
||||
fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
|
||||
kp1.public() == kp2.public() && kp1.0.secret.as_bytes() == kp2.0.secret.as_bytes()
|
||||
kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -218,11 +195,22 @@ mod tests {
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ed25519_keypair_convert() {
|
||||
fn prop() -> bool {
|
||||
let kp1 = KeyPair::generate_ed25519();
|
||||
let libp2p_kp: libp2p_identity::Keypair = kp1.clone().into();
|
||||
let kp2: KeyPair = libp2p_kp.into();
|
||||
kp1.public() == kp2.public() && kp1.secret().unwrap() == kp2.secret().unwrap()
|
||||
}
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ed25519_keypair_from_secret() {
|
||||
fn prop() -> bool {
|
||||
let kp1 = Keypair::generate();
|
||||
let mut sk = kp1.0.secret.to_bytes();
|
||||
let mut sk = kp1.0.to_bytes();
|
||||
let kp2 = Keypair::from(SecretKey::from_bytes(&mut sk).unwrap());
|
||||
eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ pub enum Error {
|
||||
/// An error during decoding of key material.
|
||||
#[derive(ThisError, Debug)]
|
||||
pub enum DecodingError {
|
||||
#[error("Failed to decode, invalid length: {0}")]
|
||||
InvalidLength(#[from] std::array::TryFromSliceError),
|
||||
#[error("Failed to decode with ed25519: {0}")]
|
||||
Ed25519(
|
||||
#[from]
|
||||
@ -68,7 +70,7 @@ pub enum SigningError {
|
||||
Secp256k1(
|
||||
#[from]
|
||||
#[source]
|
||||
secp256k1::Error,
|
||||
libsecp256k1::Error,
|
||||
),
|
||||
}
|
||||
|
||||
@ -83,5 +85,5 @@ pub enum VerificationError {
|
||||
Rsa(#[source] ring::error::Unspecified, String, String),
|
||||
|
||||
#[error("Failed to verify signature {1} with {2} secp256k1 public key: {0}")]
|
||||
Secp256k1(#[source] secp256k1::Error, String, String),
|
||||
Secp256k1(#[source] libsecp256k1::Error, String, String),
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use crate::public_key::PublicKey;
|
||||
use crate::rsa;
|
||||
use crate::secp256k1;
|
||||
use crate::signature::Signature;
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_identity::{KeyType, Keypair, PeerId};
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -47,7 +47,7 @@ use std::str::FromStr;
|
||||
/// let keypair = Keypair::rsa_from_pkcs8(&mut bytes);
|
||||
/// ```
|
||||
///
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum KeyFormat {
|
||||
Ed25519,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -105,6 +105,7 @@ impl From<KeyFormat> for String {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum KeyPair {
|
||||
/// An Ed25519 keypair.
|
||||
@ -168,6 +169,18 @@ impl KeyPair {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the key format of this keypair.
|
||||
pub fn key_format(&self) -> KeyFormat {
|
||||
use KeyPair::*;
|
||||
|
||||
match self {
|
||||
Ed25519(_) => KeyFormat::Ed25519,
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Rsa(_) => KeyFormat::Rsa,
|
||||
Secp256k1(_) => KeyFormat::Secp256k1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the public key of this keypair.
|
||||
pub fn public(&self) -> PublicKey {
|
||||
use KeyPair::*;
|
||||
@ -182,7 +195,7 @@ impl KeyPair {
|
||||
pub fn secret(&self) -> eyre::Result<Vec<u8>> {
|
||||
use KeyPair::*;
|
||||
match self {
|
||||
Ed25519(pair) => Ok(pair.secret().0.to_bytes().to_vec()),
|
||||
Ed25519(pair) => Ok(pair.secret().0.to_vec()),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Rsa(_) => Err(eyre::eyre!("secret key is not available for RSA")),
|
||||
Secp256k1(pair) => Ok(pair.secret().to_bytes().to_vec()),
|
||||
@ -219,47 +232,81 @@ impl KeyPair {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_secret_key(bytes: Vec<u8>, format: KeyFormat) -> Result<Self, DecodingError> {
|
||||
use KeyPair::*;
|
||||
|
||||
match format {
|
||||
KeyFormat::Ed25519 => Ok(Ed25519(ed25519::SecretKey::from_bytes(bytes)?.into())),
|
||||
KeyFormat::Secp256k1 => Ok(Secp256k1(secp256k1::SecretKey::from_bytes(bytes)?.into())),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
KeyFormat::Rsa => Err(DecodingError::KeypairDecodingIsNotSupported),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_peer_id(&self) -> PeerId {
|
||||
self.public().to_peer_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<libp2p_core::identity::Keypair> for KeyPair {
|
||||
fn from(key: libp2p_core::identity::Keypair) -> Self {
|
||||
use libp2p_core::identity::Keypair::*;
|
||||
|
||||
match key {
|
||||
Ed25519(kp) => KeyPair::Ed25519(ed25519::Keypair::decode(&mut kp.encode()).unwrap()),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
// safety: these Keypair structures are identical
|
||||
Rsa(kp) => KeyPair::Rsa(unsafe {
|
||||
std::mem::transmute::<libp2p_core::identity::rsa::Keypair, rsa::Keypair>(kp)
|
||||
}),
|
||||
Secp256k1(kp) => KeyPair::Secp256k1(secp256k1::Keypair::from(
|
||||
secp256k1::SecretKey::from_bytes(kp.secret().to_bytes()).unwrap(),
|
||||
)),
|
||||
impl From<libp2p_identity::Keypair> for KeyPair {
|
||||
fn from(key: libp2p_identity::Keypair) -> Self {
|
||||
fn convert_keypair(key: Keypair) -> eyre::Result<KeyPair> {
|
||||
match key.key_type() {
|
||||
KeyType::Ed25519 => {
|
||||
let kp = key.try_into_ed25519()?;
|
||||
let raw_kp = ed25519::Keypair::decode(&mut kp.to_bytes())?;
|
||||
Ok(KeyPair::Ed25519(raw_kp))
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
KeyType::RSA => {
|
||||
let kp = key.try_into_rsa()?;
|
||||
let raw_kp = unsafe {
|
||||
std::mem::transmute::<libp2p_identity::rsa::Keypair, rsa::Keypair>(kp)
|
||||
};
|
||||
Ok(KeyPair::Rsa(raw_kp))
|
||||
}
|
||||
KeyType::Secp256k1 => {
|
||||
let kp = key.try_into_secp256k1()?;
|
||||
let raw_kp = secp256k1::SecretKey::from_bytes(kp.secret().to_bytes())?;
|
||||
Ok(KeyPair::Secp256k1(secp256k1::Keypair::from(raw_kp)))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
convert_keypair(key).expect("Could not convert keypair")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyPair> for libp2p_core::identity::Keypair {
|
||||
impl From<KeyPair> for libp2p_identity::Keypair {
|
||||
fn from(key: KeyPair) -> Self {
|
||||
use libp2p_core::identity;
|
||||
use libp2p_core::identity::Keypair;
|
||||
use KeyPair::*;
|
||||
|
||||
match key {
|
||||
Ed25519(kp) => Keypair::Ed25519(
|
||||
identity::ed25519::Keypair::decode(kp.encode().to_vec().as_mut_slice()).unwrap(),
|
||||
),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
// safety: these Keypair structures are identical
|
||||
Rsa(kp) => Keypair::Rsa(unsafe {
|
||||
std::mem::transmute::<rsa::Keypair, libp2p_core::identity::rsa::Keypair>(kp)
|
||||
}),
|
||||
Secp256k1(kp) => Keypair::Secp256k1(identity::secp256k1::Keypair::from(
|
||||
identity::secp256k1::SecretKey::from_bytes(kp.secret().to_bytes()).unwrap(),
|
||||
)),
|
||||
fn convert_keypair(key: KeyPair) -> eyre::Result<libp2p_identity::Keypair> {
|
||||
match key {
|
||||
KeyPair::Ed25519(kp) => {
|
||||
// for some reason, libp2p takes SecretKey's 32 bytes here instead of Keypair's 64 bytes
|
||||
let secret_bytes = kp.secret().0;
|
||||
let kp = libp2p_identity::Keypair::ed25519_from_bytes(secret_bytes)?;
|
||||
Ok(kp)
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
// safety: these Keypair structures are identical
|
||||
KeyPair::Rsa(kp) => {
|
||||
let kp = unsafe {
|
||||
std::mem::transmute::<rsa::Keypair, libp2p_identity::rsa::Keypair>(kp)
|
||||
};
|
||||
let kp = Keypair::from(kp);
|
||||
Ok(kp)
|
||||
}
|
||||
KeyPair::Secp256k1(kp) => {
|
||||
let sk = libp2p_identity::secp256k1::SecretKey::try_from_bytes(
|
||||
kp.secret().to_bytes(),
|
||||
)?;
|
||||
let kp = libp2p_identity::secp256k1::Keypair::from(sk);
|
||||
let kp = Keypair::from(kp);
|
||||
Ok(kp)
|
||||
}
|
||||
}
|
||||
}
|
||||
convert_keypair(key).expect("Could not convert key pair")
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ pub use key_pair::KeyFormat;
|
||||
pub use key_pair::KeyPair;
|
||||
|
||||
pub mod peerid_serializer {
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_identity::PeerId;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -58,7 +58,7 @@ pub mod peerid_serializer {
|
||||
{
|
||||
let str = String::deserialize(deserializer)?;
|
||||
PeerId::from_str(&str).map_err(|e| {
|
||||
serde::de::Error::custom(format!("peer id deserialization failed for {:?}", e))
|
||||
serde::de::Error::custom(format!("peer id deserialization failed for {e:?}"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ use crate::secp256k1;
|
||||
use crate::signature::Signature;
|
||||
|
||||
use crate::key_pair::KeyFormat;
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_identity::{KeyType, PeerId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
@ -109,7 +109,7 @@ impl PublicKey {
|
||||
}
|
||||
|
||||
pub fn to_peer_id(&self) -> PeerId {
|
||||
PeerId::from_public_key(self.clone().into())
|
||||
PeerId::from_public_key(&self.clone().into())
|
||||
}
|
||||
|
||||
pub fn get_key_format(&self) -> KeyFormat {
|
||||
@ -124,53 +124,85 @@ impl PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<libp2p_core::identity::PublicKey> for PublicKey {
|
||||
fn from(key: libp2p_core::identity::PublicKey) -> Self {
|
||||
use libp2p_core::identity::PublicKey::*;
|
||||
|
||||
match key {
|
||||
Ed25519(key) => {
|
||||
PublicKey::Ed25519(ed25519::PublicKey::decode(&key.encode()[..]).unwrap())
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Rsa(key) => PublicKey::Rsa(rsa::PublicKey::from_pkcs1(key.encode_pkcs1()).unwrap()),
|
||||
Secp256k1(key) => {
|
||||
PublicKey::Secp256k1(secp256k1::PublicKey::decode(&key.encode()[..]).unwrap())
|
||||
impl From<libp2p_identity::PublicKey> for PublicKey {
|
||||
fn from(key: libp2p_identity::PublicKey) -> Self {
|
||||
fn convert_key(key: libp2p_identity::PublicKey) -> eyre::Result<PublicKey> {
|
||||
match key.key_type() {
|
||||
KeyType::Ed25519 => {
|
||||
let pk = key.try_into_ed25519()?;
|
||||
let raw_pk = ed25519::PublicKey::decode(&pk.to_bytes())?;
|
||||
Ok(PublicKey::Ed25519(raw_pk))
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
KeyType::RSA => {
|
||||
let pk = key.try_into_rsa()?;
|
||||
let raw_pk = rsa::PublicKey::from_pkcs1(pk.encode_pkcs1())?;
|
||||
Ok(PublicKey::Rsa(raw_pk))
|
||||
}
|
||||
KeyType::Secp256k1 => {
|
||||
let pk = key.try_into_secp256k1()?;
|
||||
let raw_pk = secp256k1::PublicKey::decode(&pk.to_bytes())?;
|
||||
Ok(PublicKey::Secp256k1(raw_pk))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
convert_key(key).expect("Could not convert public key")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PublicKey> for libp2p_core::identity::PublicKey {
|
||||
impl From<PublicKey> for libp2p_identity::PublicKey {
|
||||
fn from(key: PublicKey) -> Self {
|
||||
use libp2p_core::identity as libp2p_identity;
|
||||
|
||||
match key {
|
||||
PublicKey::Ed25519(key) => libp2p_identity::PublicKey::Ed25519(
|
||||
libp2p_identity::ed25519::PublicKey::decode(&key.encode()[..]).unwrap(),
|
||||
),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
PublicKey::Rsa(key) => libp2p_identity::PublicKey::Rsa(
|
||||
libp2p_identity::rsa::PublicKey::decode_x509(&key.encode_x509()).unwrap(),
|
||||
),
|
||||
PublicKey::Secp256k1(key) => libp2p_identity::PublicKey::Secp256k1(
|
||||
libp2p_identity::secp256k1::PublicKey::decode(&key.encode()[..]).unwrap(),
|
||||
),
|
||||
fn convert_key(key: PublicKey) -> eyre::Result<libp2p_identity::PublicKey> {
|
||||
match key {
|
||||
PublicKey::Ed25519(key) => {
|
||||
let raw_pk =
|
||||
libp2p_identity::ed25519::PublicKey::try_from_bytes(&key.encode())?;
|
||||
let pk = libp2p_identity::PublicKey::from(raw_pk);
|
||||
Ok(pk)
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
PublicKey::Rsa(key) => {
|
||||
let raw_pk =
|
||||
libp2p_identity::rsa::PublicKey::try_decode_x509(&key.encode_x509())?;
|
||||
let pk = libp2p_identity::PublicKey::from(raw_pk);
|
||||
Ok(pk)
|
||||
}
|
||||
PublicKey::Secp256k1(key) => {
|
||||
let raw_pk =
|
||||
libp2p_identity::secp256k1::PublicKey::try_from_bytes(&key.encode())?;
|
||||
let pk = libp2p_identity::PublicKey::from(raw_pk);
|
||||
Ok(pk)
|
||||
}
|
||||
}
|
||||
}
|
||||
convert_key(key).expect("Could not convert key")
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<libp2p_core::PeerId> for PublicKey {
|
||||
impl TryFrom<PeerId> for PublicKey {
|
||||
type Error = DecodingError;
|
||||
|
||||
fn try_from(peer_id: libp2p_core::PeerId) -> Result<Self, Self::Error> {
|
||||
Ok(peer_id
|
||||
.as_public_key()
|
||||
.ok_or(DecodingError::PublicKeyNotInlined(peer_id.to_base58()))?
|
||||
fn try_from(peer_id: PeerId) -> Result<Self, Self::Error> {
|
||||
Ok(as_public_key(&peer_id)
|
||||
.ok_or_else(|| DecodingError::PublicKeyNotInlined(peer_id.to_base58()))?
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert PeerId to libp2p's PublicKey
|
||||
fn as_public_key(peer_id: &PeerId) -> Option<libp2p_identity::PublicKey> {
|
||||
let mhash = peer_id.as_ref();
|
||||
|
||||
match multihash::Code::try_from(mhash.code()) {
|
||||
Ok(multihash::Code::Identity) => {
|
||||
libp2p_identity::PublicKey::try_decode_protobuf(mhash.digest()).ok()
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -196,8 +228,8 @@ mod tests {
|
||||
fn public_key_peer_id_conversions() {
|
||||
let kp = KeyPair::generate_secp256k1();
|
||||
let fluence_pk = kp.public();
|
||||
let libp2p_pk: libp2p_core::PublicKey = fluence_pk.clone().into();
|
||||
let peer_id = PeerId::from_public_key(libp2p_pk);
|
||||
let libp2p_pk: libp2p_identity::PublicKey = fluence_pk.clone().into();
|
||||
let peer_id = PeerId::from_public_key(&libp2p_pk);
|
||||
let fluence_pk_converted = PublicKey::try_from(peer_id).unwrap();
|
||||
|
||||
assert_eq!(fluence_pk, fluence_pk_converted);
|
||||
|
@ -127,7 +127,7 @@ impl fmt::Debug for PublicKey {
|
||||
let mut hex = String::with_capacity(bytes.len() * 2);
|
||||
|
||||
for byte in bytes {
|
||||
write!(hex, "{:02x}", byte).expect("Can't fail on writing to string");
|
||||
write!(hex, "{byte:02x}").expect("Can't fail on writing to string");
|
||||
}
|
||||
|
||||
f.debug_struct("PublicKey").field("pkcs1", &hex).finish()
|
||||
@ -234,7 +234,6 @@ pub struct Signature(pub Vec<u8>);
|
||||
mod tests {
|
||||
use super::*;
|
||||
use quickcheck::*;
|
||||
use rand::seq::SliceRandom;
|
||||
use std::fmt;
|
||||
|
||||
const KEY1: &'static [u8] = include_bytes!("test/rsa-2048.pk8");
|
||||
@ -251,8 +250,8 @@ mod tests {
|
||||
}
|
||||
|
||||
impl Arbitrary for SomeKeypair {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> SomeKeypair {
|
||||
let mut key = [KEY1, KEY2, KEY3].choose(g).unwrap().to_vec();
|
||||
fn arbitrary(g: &mut Gen) -> SomeKeypair {
|
||||
let mut key = g.choose(&[KEY1, KEY2, KEY3]).unwrap().to_vec();
|
||||
SomeKeypair(Keypair::from_pkcs8(&mut key).unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ use crate::error::{DecodingError, SigningError, VerificationError};
|
||||
|
||||
use asn1_der::{DerObject, FromDerObject};
|
||||
use core::fmt;
|
||||
use libsecp256k1::Message;
|
||||
use rand::RngCore;
|
||||
use secp256k1::Message;
|
||||
use serde::de::Error as SerdeError;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_bytes::{ByteBuf as SerdeByteBuf, Bytes as SerdeBytes};
|
||||
@ -66,7 +66,7 @@ impl fmt::Debug for Keypair {
|
||||
/// Promote a Secp256k1 secret key into a keypair.
|
||||
impl From<SecretKey> for Keypair {
|
||||
fn from(secret: SecretKey) -> Self {
|
||||
let public = PublicKey(secp256k1::PublicKey::from_secret_key(&secret.0));
|
||||
let public = PublicKey(libsecp256k1::PublicKey::from_secret_key(&secret.0));
|
||||
Keypair { secret, public }
|
||||
}
|
||||
}
|
||||
@ -80,7 +80,7 @@ impl From<Keypair> for SecretKey {
|
||||
|
||||
/// A Secp256k1 secret key.
|
||||
#[derive(Clone)]
|
||||
pub struct SecretKey(secp256k1::SecretKey);
|
||||
pub struct SecretKey(libsecp256k1::SecretKey);
|
||||
|
||||
impl fmt::Debug for SecretKey {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -92,12 +92,12 @@ impl SecretKey {
|
||||
/// Generate a new Secp256k1 secret key.
|
||||
pub fn generate() -> Self {
|
||||
let mut r = rand::thread_rng();
|
||||
let mut b = [0; secp256k1::util::SECRET_KEY_SIZE];
|
||||
let mut b = [0; libsecp256k1::util::SECRET_KEY_SIZE];
|
||||
// This is how it is done in `secp256k1::SecretKey::random` which
|
||||
// we do not use here because it uses `rand::Rng` from rand-0.4.
|
||||
loop {
|
||||
r.fill_bytes(&mut b);
|
||||
if let Ok(k) = secp256k1::SecretKey::parse(&b) {
|
||||
if let Ok(k) = libsecp256k1::SecretKey::parse(&b) {
|
||||
return SecretKey(k);
|
||||
}
|
||||
}
|
||||
@ -108,8 +108,8 @@ impl SecretKey {
|
||||
/// error is returned.
|
||||
pub fn from_bytes(mut sk: impl AsMut<[u8]>) -> Result<Self, DecodingError> {
|
||||
let sk_bytes = sk.as_mut();
|
||||
let secret =
|
||||
secp256k1::SecretKey::parse_slice(&*sk_bytes).map_err(|_| DecodingError::Secp256k1)?;
|
||||
let secret = libsecp256k1::SecretKey::parse_slice(&*sk_bytes)
|
||||
.map_err(|_| DecodingError::Secp256k1)?;
|
||||
sk_bytes.zeroize();
|
||||
Ok(SecretKey(secret))
|
||||
}
|
||||
@ -122,7 +122,7 @@ impl SecretKey {
|
||||
// TODO: Stricter parsing.
|
||||
let der_obj = der.as_mut();
|
||||
let obj: Vec<DerObject> =
|
||||
FromDerObject::deserialize((&*der_obj).iter()).map_err(|_| DecodingError::Secp256k1)?;
|
||||
FromDerObject::deserialize((*der_obj).iter()).map_err(|_| DecodingError::Secp256k1)?;
|
||||
der_obj.zeroize();
|
||||
let sk_obj = obj.into_iter().nth(1).ok_or(DecodingError::Secp256k1)?;
|
||||
let mut sk_bytes: Vec<u8> =
|
||||
@ -149,7 +149,7 @@ impl SecretKey {
|
||||
/// ECDSA signature.
|
||||
pub fn sign_hashed(&self, msg: &[u8]) -> Result<Vec<u8>, SigningError> {
|
||||
let m = Message::parse_slice(msg).map_err(SigningError::Secp256k1)?;
|
||||
Ok(secp256k1::sign(&m, &self.0)
|
||||
Ok(libsecp256k1::sign(&m, &self.0)
|
||||
.0
|
||||
.serialize_der()
|
||||
.as_ref()
|
||||
@ -159,7 +159,7 @@ impl SecretKey {
|
||||
|
||||
/// A Secp256k1 public key.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct PublicKey(secp256k1::PublicKey);
|
||||
pub struct PublicKey(libsecp256k1::PublicKey);
|
||||
|
||||
impl PublicKey {
|
||||
/// Verify the Secp256k1 signature on a message using the public key.
|
||||
@ -171,7 +171,8 @@ impl PublicKey {
|
||||
pub fn verify_hashed(&self, msg: &[u8], sig: &[u8]) -> Result<(), VerificationError> {
|
||||
Message::parse_slice(msg)
|
||||
.and_then(|m| {
|
||||
secp256k1::Signature::parse_der(sig).map(|s| secp256k1::verify(&m, &s, &self.0))
|
||||
libsecp256k1::Signature::parse_der(sig)
|
||||
.map(|s| libsecp256k1::verify(&m, &s, &self.0))
|
||||
})
|
||||
.map_err(|e| {
|
||||
VerificationError::Secp256k1(
|
||||
@ -197,7 +198,7 @@ impl PublicKey {
|
||||
/// Decode a public key from a byte slice in the the format produced
|
||||
/// by `encode`.
|
||||
pub fn decode(bytes: &[u8]) -> Result<Self, DecodingError> {
|
||||
secp256k1::PublicKey::parse_slice(bytes, Some(secp256k1::PublicKeyFormat::Compressed))
|
||||
libsecp256k1::PublicKey::parse_slice(bytes, Some(libsecp256k1::PublicKeyFormat::Compressed))
|
||||
.map_err(|_| DecodingError::Secp256k1)
|
||||
.map(PublicKey)
|
||||
}
|
||||
@ -228,6 +229,12 @@ pub struct Signature(pub Vec<u8>);
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{key_pair, KeyFormat};
|
||||
use quickcheck::QuickCheck;
|
||||
|
||||
fn eq_keypairs(kp1: key_pair::KeyPair, kp2: key_pair::KeyPair) -> bool {
|
||||
kp1.public() == kp2.public() && kp1.secret().unwrap() == kp2.secret().unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secp256k1_secret_from_bytes() {
|
||||
@ -238,4 +245,15 @@ mod tests {
|
||||
assert_eq!(sk1.0.serialize(), sk2.0.serialize());
|
||||
assert_eq!(sk_bytes, [0; 32]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secp256k1_keypair_encode_decode() {
|
||||
fn prop() -> bool {
|
||||
let kp1 = key_pair::KeyPair::generate(KeyFormat::Secp256k1);
|
||||
let kp1_enc = libp2p_identity::Keypair::from(kp1.clone());
|
||||
let kp2 = key_pair::KeyPair::from(kp1_enc);
|
||||
eq_keypairs(kp1, kp2)
|
||||
}
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ services:
|
||||
RUST_BACKTRACE: full
|
||||
RUST_LOG: info,network=trace,aquamarine=info,aquamarine::actor=info,tokio_threadpool=info,tokio_reactor=info,mio=info,tokio_io=info,soketto=info,yamux=info,multistream_select=info,libp2p_secio=info,libp2p_websocket::framed=info,libp2p_ping=info,libp2p_core::upgrade::apply=info,libp2p_kad::kbucket=info,cranelift_codegen=info,wasmer_wasi=info,async_io=info,polling=info,wasmer_interface_types_fl=info,cranelift_codegen=info,wasmer_wasi=info,async_io=info,polling=info,wasmer_interface_types_fl=info,particle_server::behaviour::identify=info,libp2p_mplex=info,libp2p_identify=info,walrus=info,particle_protocol::libp2p_protocol::upgrade=info,kademlia::behaviour=info
|
||||
WASM_LOG: info
|
||||
image: fluencelabs/node:tg-hl-api_v345
|
||||
image: fluencelabs/node:latest
|
||||
ports:
|
||||
- 7770:7770 # tcp
|
||||
- 9990:9990 # ws
|
||||
@ -29,7 +29,7 @@ services:
|
||||
RUST_BACKTRACE: full
|
||||
RUST_LOG: info,network=trace,aquamarine=info,aquamarine::actor=info,tokio_threadpool=info,tokio_reactor=info,mio=info,tokio_io=info,soketto=info,yamux=info,multistream_select=info,libp2p_secio=info,libp2p_websocket::framed=info,libp2p_ping=info,libp2p_core::upgrade::apply=info,libp2p_kad::kbucket=info,cranelift_codegen=info,wasmer_wasi=info,async_io=info,polling=info,wasmer_interface_types_fl=info,cranelift_codegen=info,wasmer_wasi=info,async_io=info,polling=info,wasmer_interface_types_fl=info,particle_server::behaviour::identify=info,libp2p_mplex=info,libp2p_identify=info,walrus=info,particle_protocol::libp2p_protocol::upgrade=info,kademlia::behaviour=info
|
||||
WASM_LOG: info
|
||||
image: fluencelabs/node:tg-hl-api_v345
|
||||
image: fluencelabs/node:latest
|
||||
ports:
|
||||
- 7771:7771 # tcp
|
||||
- 9991:9991 # ws
|
||||
@ -51,7 +51,7 @@ services:
|
||||
RUST_BACKTRACE: full
|
||||
RUST_LOG: info,network=trace,aquamarine=info,aquamarine::actor=info,tokio_threadpool=info,tokio_reactor=info,mio=info,tokio_io=info,soketto=info,yamux=info,multistream_select=info,libp2p_secio=info,libp2p_websocket::framed=info,libp2p_ping=info,libp2p_core::upgrade::apply=info,libp2p_kad::kbucket=info,cranelift_codegen=info,wasmer_wasi=info,async_io=info,polling=info,wasmer_interface_types_fl=info,cranelift_codegen=info,wasmer_wasi=info,async_io=info,polling=info,wasmer_interface_types_fl=info,particle_server::behaviour::identify=info,libp2p_mplex=info,libp2p_identify=info,walrus=info,particle_protocol::libp2p_protocol::upgrade=info,kademlia::behaviour=info
|
||||
WASM_LOG: info
|
||||
image: fluencelabs/node:tg-hl-api_v345
|
||||
image: fluencelabs/node:latest
|
||||
ports:
|
||||
- 7772:7772 # tcp
|
||||
- 9992:9992 # ws
|
||||
|
@ -1,3 +1,4 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2021-09-01"
|
||||
targets = [ "x86_64-apple-darwin", "x86_64-unknown-linux-gnu" ]
|
||||
channel = "nightly-2023-12-06"
|
||||
targets = [ "x86_64-apple-darwin", "wasm32-wasi", "wasm32-unknown-unknown", "x86_64-unknown-linux-gnu" ]
|
||||
components = [ "rustfmt", "clippy" ]
|
||||
|
156
service/CHANGELOG.md
Normal file
156
service/CHANGELOG.md
Normal file
@ -0,0 +1,156 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.1 to 0.4.2
|
||||
* fluence-keypair bumped from 0.10.0 to 0.10.1
|
||||
|
||||
## [0.4.8](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.7...trust-graph-wasm-v0.4.8) (2023-12-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update marine sdk's, configs and sqlite connector ([#129](https://github.com/fluencelabs/trust-graph/issues/129)) ([0b66f4e](https://github.com/fluencelabs/trust-graph/commit/0b66f4e0536633879de46f69ac8391c72ece7e77))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.7 to 0.4.8
|
||||
* fluence-keypair bumped from 0.10.3 to 0.10.4
|
||||
|
||||
## [0.4.7](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.6...trust-graph-wasm-v0.4.7) (2023-07-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update rust crate marine-rs-sdk-test to 0.10.0 ([#106](https://github.com/fluencelabs/trust-graph/issues/106)) ([725d3f8](https://github.com/fluencelabs/trust-graph/commit/725d3f8f48b3bf1ed8605e9ba2da5c966a145f0d))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.6 to 0.4.7
|
||||
* fluence-keypair bumped from 0.10.2 to 0.10.3
|
||||
|
||||
## [0.4.6](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.5...trust-graph-wasm-v0.4.6) (2023-06-30)
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* release master ([#110](https://github.com/fluencelabs/trust-graph/issues/110)) ([d80a43b](https://github.com/fluencelabs/trust-graph/commit/d80a43bcff721aff8fadf3d2d5c252804ce27a6c))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.5 to 0.4.6
|
||||
* fluence-keypair bumped from 0.10.1 to 0.10.2
|
||||
|
||||
## [0.4.5](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.4...trust-graph-wasm-v0.4.5) (2023-05-09)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-wasm:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.4 to 0.4.5
|
||||
|
||||
## [0.4.4](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.3...trust-graph-wasm-v0.4.4) (2023-05-09)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-wasm:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.3 to 0.4.4
|
||||
|
||||
## [0.4.3](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.2...trust-graph-wasm-v0.4.3) (2023-05-08)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph-wasm:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.2 to 0.4.3
|
||||
|
||||
## [0.4.1](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.4.0...trust-graph-wasm-v0.4.1) (2023-04-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** Add trust-graph to workspace and bump sqlite-wasm version ([#87](https://github.com/fluencelabs/trust-graph/issues/87)) ([da38a41](https://github.com/fluencelabs/trust-graph/commit/da38a41ba727a14774a71bba6612b1bf1f498db9))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.4.0 to 0.4.1
|
||||
|
||||
## [0.4.0](https://github.com/fluencelabs/trust-graph/compare/trust-graph-wasm-v0.3.2...trust-graph-wasm-v0.4.0) (2023-03-15)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **deps:** update libp2p to 0.39.1 and other deps ([#77](https://github.com/fluencelabs/trust-graph/issues/77))
|
||||
|
||||
### Features
|
||||
|
||||
* **deps:** update libp2p to 0.39.1 and other deps ([#77](https://github.com/fluencelabs/trust-graph/issues/77)) ([080503d](https://github.com/fluencelabs/trust-graph/commit/080503dcfa2ecf8d09167ff9fe7f750fadf49035))
|
||||
* **keypair:** add KeyPair::from_secret_key ([#50](https://github.com/fluencelabs/trust-graph/issues/50)) ([a6ce8d9](https://github.com/fluencelabs/trust-graph/commit/a6ce8d9eee20e1ea24eb27c38ac6df6d878292ae))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* trust-graph bumped from 0.3.0 to 0.4.0
|
||||
* fluence-keypair bumped from 0.9.0 to 0.10.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.3.1] - 2022-10-06
|
||||
|
||||
### Added
|
||||
- *(keypair)* add KeyPair::from_secret_key (#50)
|
||||
|
||||
### Fixed
|
||||
- fix bug get_all_certs_from, update example (#44)
|
||||
- fix db paths (#28)
|
||||
|
||||
### Other
|
||||
- set version of fluence-keypair to 0.8.0
|
||||
- fluence-keypair 0.8.0
|
||||
- libp2p-core 0.33.0 (#49)
|
||||
- remove circle, update gh, add lints; remove warnings (#43)
|
||||
- Add memory leak temporary mitigation (#42)
|
||||
- High-level Aqua API (#35)
|
||||
- fluence-keypair 0.6.0
|
||||
- libp2p-core 0.31.0 (from crates.io) (#37)
|
||||
- Fix revocations logic (#34)
|
||||
- Remove mutex from TG instance (#31)
|
||||
- refactoring (#30)
|
||||
- Trust Graph: implement WASM built-in (#18)
|
@ -1,38 +1,36 @@
|
||||
[package]
|
||||
name = "trust-graph-wasm"
|
||||
version = "0.3.0"
|
||||
version = "0.4.8"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
description = "trust graph wasm"
|
||||
license = "Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
name = "trust-graph"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
trust-graph = { version = "0.3.0", path = "../." }
|
||||
fluence-keypair = { version = "0.5.0", path = "../keypair" }
|
||||
marine-rs-sdk = { version = "0.6.14", features = ["logger"] }
|
||||
marine-sqlite-connector = "0.5.2"
|
||||
trust-graph = { version = "0.4.8", path = "../trust-graph" }
|
||||
fluence-keypair = { version = "0.10.4", path = "../keypair" }
|
||||
marine-rs-sdk = { version = "0.10.2", features = ["logger"] }
|
||||
marine-sqlite-connector = "0.9.2"
|
||||
|
||||
libp2p-core = { package = "fluence-fork-libp2p-core", version = "0.27.2", features = ["secp256k1"]}
|
||||
libp2p-identity = { workspace = true }
|
||||
|
||||
log = "0.4.8"
|
||||
anyhow = "1.0.31"
|
||||
boolinator = "2.4.0"
|
||||
once_cell = "1.4.1"
|
||||
parking_lot = "0.11.1"
|
||||
once_cell = "1.18.0"
|
||||
serde_json = "1.0"
|
||||
bs58 = "0.3.1"
|
||||
rmp-serde = "0.15.0"
|
||||
bs58 = "0.4.0"
|
||||
rmp-serde = "1.1.1"
|
||||
bincode = "1.3.1"
|
||||
serde_bencode = "^0.2.3"
|
||||
thiserror = "1.0.23"
|
||||
|
||||
[dev-dependencies]
|
||||
marine-rs-sdk-test = "0.4.0"
|
||||
rusqlite = "0.26.1"
|
||||
marine-rs-sdk-test = "0.12.1"
|
||||
rusqlite = "0.28.0"
|
||||
|
||||
[build-dependencies]
|
||||
marine-rs-sdk-test = "0.4.0"
|
||||
marine-rs-sdk-test = "0.12.1"
|
||||
|
@ -1,16 +1,15 @@
|
||||
modules_dir = "artifacts/"
|
||||
total_memory_limit = "Infinity"
|
||||
|
||||
[[module]]
|
||||
name = "sqlite3"
|
||||
logger_enabled = true
|
||||
|
||||
[module.wasi]
|
||||
preopened_files = ["/tmp"]
|
||||
mapped_dirs = { "tmp" = "/tmp" }
|
||||
mapped_dirs = { "/tmp" = "data" }
|
||||
[[module]]
|
||||
name = "trust-graph"
|
||||
logger_enabled = true
|
||||
|
||||
[module.wasi]
|
||||
preopened_files = ["/tmp"]
|
||||
mapped_dirs = { "tmp" = "/tmp" }
|
||||
mapped_dirs = { "/tmp" = "data" }
|
||||
|
@ -13,7 +13,7 @@ mkdir -p artifacts
|
||||
cp ../target/wasm32-wasi/release/trust-graph.wasm artifacts/
|
||||
|
||||
# download SQLite 3 to use in tests
|
||||
curl -L https://github.com/fluencelabs/sqlite/releases/download/v0.15.0_w/sqlite3.wasm -o artifacts/sqlite3.wasm
|
||||
curl -sS -L https://github.com/fluencelabs/sqlite/releases/download/sqlite-wasm-v0.18.1/sqlite3.wasm -o artifacts/sqlite3.wasm
|
||||
|
||||
# generate Aqua bindings
|
||||
marine aqua artifacts/trust-graph.wasm -s TrustGraph -i trust-graph > ../aqua/trust-graph.aqua
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2021-09-01"
|
||||
targets = [ "x86_64-apple-darwin", "x86_64-unknown-linux-gnu" ]
|
||||
channel = "nightly-2023-12-06"
|
||||
targets = [ "x86_64-apple-darwin", "wasm32-wasi", "wasm32-unknown-unknown", "x86_64-unknown-linux-gnu" ]
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::dto::DtoConversionError::PeerIdDecodeError;
|
||||
use fluence_keypair::error::DecodingError;
|
||||
use fluence_keypair::{KeyFormat, PublicKey, Signature};
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_identity::PeerId;
|
||||
use marine_rs_sdk::marine;
|
||||
use std::convert::TryFrom;
|
||||
use std::str::FromStr;
|
||||
@ -40,7 +40,7 @@ pub struct Certificate {
|
||||
impl From<trust_graph::Certificate> for Certificate {
|
||||
fn from(c: trust_graph::Certificate) -> Self {
|
||||
let chain: Vec<Trust> = c.chain.into_iter().map(|t| t.into()).collect();
|
||||
return Certificate { chain };
|
||||
Certificate { chain }
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,10 +51,10 @@ impl TryFrom<Certificate> for trust_graph::Certificate {
|
||||
let chain: Result<Vec<trust_graph::Trust>, DtoConversionError> = c
|
||||
.chain
|
||||
.into_iter()
|
||||
.map(|t| trust_graph::Trust::try_from(t))
|
||||
.map(trust_graph::Trust::try_from)
|
||||
.collect();
|
||||
let chain = chain?;
|
||||
return Ok(trust_graph::Certificate { chain });
|
||||
Ok(trust_graph::Certificate { chain })
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,19 +78,19 @@ impl TryFrom<Trust> for trust_graph::Trust {
|
||||
|
||||
fn try_from(t: Trust) -> Result<Self, Self::Error> {
|
||||
let issued_for = PublicKey::try_from(
|
||||
PeerId::from_str(&t.issued_for).map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?,
|
||||
PeerId::from_str(&t.issued_for).map_err(|e| PeerIdDecodeError(format!("{e:?}")))?,
|
||||
)
|
||||
.map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?;
|
||||
let signature = bs58::decode(&t.signature).into_vec()?;
|
||||
let signature = Signature::from_bytes(KeyFormat::from_str(&t.sig_type)?, signature);
|
||||
let expires_at = Duration::from_secs(t.expires_at);
|
||||
let issued_at = Duration::from_secs(t.issued_at);
|
||||
return Ok(trust_graph::Trust {
|
||||
Ok(trust_graph::Trust {
|
||||
issued_for,
|
||||
expires_at,
|
||||
signature,
|
||||
issued_at,
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,13 +101,13 @@ impl From<trust_graph::Trust> for Trust {
|
||||
let signature = bs58::encode(raw_signature.bytes).into_string();
|
||||
let expires_at = t.expires_at.as_secs();
|
||||
let issued_at = t.issued_at.as_secs();
|
||||
return Trust {
|
||||
Trust {
|
||||
issued_for,
|
||||
expires_at,
|
||||
signature,
|
||||
sig_type: raw_signature.sig_type.into(),
|
||||
issued_at,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,22 +132,22 @@ impl TryFrom<Revocation> for trust_graph::Revocation {
|
||||
fn try_from(r: Revocation) -> Result<Self, Self::Error> {
|
||||
let revoked_pk = PublicKey::try_from(
|
||||
PeerId::from_str(&r.revoked_peer_id)
|
||||
.map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?,
|
||||
.map_err(|e| PeerIdDecodeError(format!("{e:?}")))?,
|
||||
)
|
||||
.map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?;
|
||||
let revoked_by_pk = PublicKey::try_from(
|
||||
PeerId::from_str(&r.revoked_by).map_err(|e| PeerIdDecodeError(format!("{:?}", e)))?,
|
||||
PeerId::from_str(&r.revoked_by).map_err(|e| PeerIdDecodeError(format!("{e:?}")))?,
|
||||
)
|
||||
.map_err(|e| DtoConversionError::PeerIdDecodeError(e.to_string()))?;
|
||||
let signature = bs58::decode(&r.signature).into_vec()?;
|
||||
let signature = Signature::from_bytes(KeyFormat::from_str(&r.sig_type)?, signature);
|
||||
let revoked_at = Duration::from_secs(r.revoked_at);
|
||||
return Ok(trust_graph::Revocation {
|
||||
Ok(trust_graph::Revocation {
|
||||
pk: revoked_pk,
|
||||
revoked_at,
|
||||
revoked_by: revoked_by_pk,
|
||||
signature,
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,12 +158,12 @@ impl From<trust_graph::Revocation> for Revocation {
|
||||
let raw_signature = r.signature.get_raw_signature();
|
||||
let signature = bs58::encode(raw_signature.bytes).into_string();
|
||||
let revoked_at = r.revoked_at.as_secs();
|
||||
return Revocation {
|
||||
Revocation {
|
||||
revoked_peer_id,
|
||||
revoked_at,
|
||||
signature,
|
||||
sig_type: raw_signature.sig_type.into(),
|
||||
revoked_by,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use crate::error::ServiceError::*;
|
||||
use crate::storage_impl::{SQLiteStorage, DB_PATH};
|
||||
use crate::TRUSTED_TIMESTAMP;
|
||||
use fluence_keypair::PublicKey;
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_identity::PeerId;
|
||||
use marine_rs_sdk::CallParameters;
|
||||
use std::cell::RefCell;
|
||||
use std::convert::TryFrom;
|
||||
@ -27,6 +27,7 @@ use std::str::FromStr;
|
||||
use trust_graph::TrustGraph;
|
||||
|
||||
/// Check timestamps are generated on the current host with builtin ("peer" "timestamp_sec")
|
||||
#[allow(clippy::unnecessary_lazy_evaluations)]
|
||||
pub(crate) fn check_timestamp_tetraplets(
|
||||
call_parameters: &CallParameters,
|
||||
arg_number: usize,
|
||||
@ -36,17 +37,17 @@ pub(crate) fn check_timestamp_tetraplets(
|
||||
.get(arg_number)
|
||||
.ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", call_parameters.tetraplets)))?;
|
||||
let tetraplet = tetraplets
|
||||
.get(0)
|
||||
.first()
|
||||
.ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", call_parameters.tetraplets)))?;
|
||||
(TRUSTED_TIMESTAMP.eq(&(&tetraplet.service_id, &tetraplet.function_name))
|
||||
&& tetraplet.peer_pk == call_parameters.host_id)
|
||||
.then(|| ())
|
||||
.ok_or_else(|| InvalidTimestampTetraplet(format!("{:?}", tetraplet)))
|
||||
.ok_or_else(|| InvalidTimestampTetraplet(format!("{tetraplet:?}")))
|
||||
}
|
||||
|
||||
fn parse_peer_id(peer_id: String) -> Result<PeerId, ServiceError> {
|
||||
libp2p_core::PeerId::from_str(&peer_id)
|
||||
.map_err(|e| ServiceError::PeerIdParseError(format!("{:?}", e)))
|
||||
libp2p_identity::PeerId::from_str(&peer_id)
|
||||
.map_err(|e| ServiceError::PeerIdParseError(format!("{e:?}")))
|
||||
}
|
||||
|
||||
thread_local!(static INSTANCE: RefCell<TrustGraph<SQLiteStorage>> = RefCell::new(TrustGraph::new(
|
||||
|
@ -17,7 +17,7 @@ impl From<Result<(), ServiceError>> for InsertResult {
|
||||
},
|
||||
Err(e) => InsertResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ impl From<Result<(u32, String), ServiceError>> for WeightResult {
|
||||
success: false,
|
||||
weight: 0u32,
|
||||
peer_id: "".to_string(),
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,7 @@ impl From<Result<Vec<Certificate>, ServiceError>> for AllCertsResult {
|
||||
Err(e) => AllCertsResult {
|
||||
success: false,
|
||||
certificates: vec![],
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -89,7 +89,7 @@ impl From<Result<(), ServiceError>> for SetRootResult {
|
||||
},
|
||||
Err(e) => SetRootResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -112,7 +112,7 @@ impl From<Result<Vec<u8>, ServiceError>> for GetTrustBytesResult {
|
||||
},
|
||||
Err(e) => GetTrustBytesResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
result: vec![],
|
||||
},
|
||||
}
|
||||
@ -136,7 +136,7 @@ impl From<Result<Trust, ServiceError>> for IssueTrustResult {
|
||||
},
|
||||
Err(e) => IssueTrustResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
trust: Trust::default(),
|
||||
},
|
||||
}
|
||||
@ -158,7 +158,7 @@ impl From<Result<(), ServiceError>> for VerifyTrustResult {
|
||||
},
|
||||
Err(e) => VerifyTrustResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -181,7 +181,7 @@ impl From<Result<u32, ServiceError>> for AddTrustResult {
|
||||
},
|
||||
Err(e) => AddTrustResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
weight: u32::default(),
|
||||
},
|
||||
}
|
||||
@ -205,7 +205,7 @@ impl From<Result<Vec<u8>, ServiceError>> for GetRevokeBytesResult {
|
||||
},
|
||||
Err(e) => GetRevokeBytesResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
result: vec![],
|
||||
},
|
||||
}
|
||||
@ -229,7 +229,7 @@ impl From<Result<Revocation, ServiceError>> for IssueRevocationResult {
|
||||
},
|
||||
Err(e) => IssueRevocationResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
revocation: Revocation::default(),
|
||||
},
|
||||
}
|
||||
@ -251,7 +251,7 @@ impl From<Result<(), ServiceError>> for RevokeResult {
|
||||
},
|
||||
Err(e) => RevokeResult {
|
||||
success: false,
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -275,7 +275,7 @@ impl From<Result<Vec<Revocation>, ServiceError>> for ExportRevocationsResult {
|
||||
Err(e) => ExportRevocationsResult {
|
||||
success: false,
|
||||
revocations: vec![],
|
||||
error: format!("{}", e),
|
||||
error: format!("{e}"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use std::time::Duration;
|
||||
use trust_graph::TrustGraph;
|
||||
|
||||
#[marine]
|
||||
/// could set only a owner of a trust graph service
|
||||
/// Only service owner can set roots
|
||||
fn set_root(peer_id: String, max_chain_len: u32) -> SetRootResult {
|
||||
let call_parameters: CallParameters = marine_rs_sdk::get_call_parameters();
|
||||
let init_peer_id = call_parameters.init_peer_id;
|
||||
@ -27,10 +27,10 @@ fn set_root(peer_id: String, max_chain_len: u32) -> SetRootResult {
|
||||
})
|
||||
.into()
|
||||
} else {
|
||||
return SetRootResult {
|
||||
SetRootResult {
|
||||
success: false,
|
||||
error: ServiceError::NotOwner.to_string(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ fn get_all_certs(issued_for: String, timestamp_sec: u64) -> AllCertsResult {
|
||||
fn get_all_certs_from(issued_for: String, issuer: String, timestamp_sec: u64) -> AllCertsResult {
|
||||
with_tg(|tg| {
|
||||
let cp = get_call_parameters();
|
||||
check_timestamp_tetraplets(&cp, 1)?;
|
||||
check_timestamp_tetraplets(&cp, 2)?;
|
||||
get_certs_from(tg, issued_for, issuer, timestamp_sec)
|
||||
})
|
||||
.into()
|
||||
|
@ -100,7 +100,7 @@ impl SQLiteStorage {
|
||||
.cursor();
|
||||
|
||||
cursor.bind(&[
|
||||
Value::String(format!("{}", issued_for)),
|
||||
Value::String(format!("{issued_for}")),
|
||||
Value::Integer(relation_type),
|
||||
])?;
|
||||
let mut relations: Vec<TrustRelation> = vec![];
|
||||
@ -206,8 +206,8 @@ impl Storage for SQLiteStorage {
|
||||
.cursor();
|
||||
|
||||
cursor.bind(&[
|
||||
Value::String(format!("{}", issued_by)),
|
||||
Value::String(format!("{}", issued_for)),
|
||||
Value::String(format!("{issued_by}")),
|
||||
Value::String(format!("{issued_for}")),
|
||||
])?;
|
||||
|
||||
if let Some(row) = cursor.next()? {
|
||||
@ -272,7 +272,7 @@ impl Storage for SQLiteStorage {
|
||||
statement.bind(6, &Value::Binary(relation.signature().encode()))?;
|
||||
|
||||
statement.next()?;
|
||||
Ok({})
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_root_weight_factor(&self, pk: &PK) -> Result<Option<WeightFactor>, Self::Error> {
|
||||
@ -281,7 +281,7 @@ impl Storage for SQLiteStorage {
|
||||
.prepare("SELECT public_key, weight_factor FROM roots WHERE public_key = ?")?
|
||||
.cursor();
|
||||
|
||||
cursor.bind(&[Value::String(format!("{}", pk))])?;
|
||||
cursor.bind(&[Value::String(format!("{pk}"))])?;
|
||||
|
||||
if let Some(row) = cursor.next()? {
|
||||
let w = u32::try_from(row[1].as_integer().ok_or(WeightFactorConversionDB)?)
|
||||
@ -304,12 +304,12 @@ impl Storage for SQLiteStorage {
|
||||
.cursor();
|
||||
|
||||
cursor.bind(&[
|
||||
Value::String(format!("{}", pk)),
|
||||
Value::String(format!("{pk}")),
|
||||
Value::Integer(i64::from(weight_factor)),
|
||||
])?;
|
||||
|
||||
cursor.next()?;
|
||||
Ok({})
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn root_keys(&self) -> Result<Vec<PK>, Self::Error> {
|
||||
|
@ -18,18 +18,18 @@
|
||||
mod service_tests {
|
||||
marine_rs_sdk_test::include_test_env!("/marine_test_env.rs");
|
||||
use crate::error::ServiceError;
|
||||
use crate::storage_impl::DB_PATH;
|
||||
use crate::TRUSTED_TIMESTAMP;
|
||||
use fluence_keypair::KeyPair;
|
||||
use libp2p_core::PeerId;
|
||||
use libp2p_identity::PeerId;
|
||||
use marine_rs_sdk::{CallParameters, SecurityTetraplet};
|
||||
use marine_test_env::trust_graph::{Certificate, Revocation, ServiceInterface, Trust};
|
||||
use rusqlite::Connection;
|
||||
use std::collections::HashMap;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
static HOST_ID: &str = "some_host_id";
|
||||
|
||||
static TEST_DB_PATH: &str = "data/trust-graph.sqlite";
|
||||
|
||||
struct Auth {
|
||||
issuer: PeerId,
|
||||
trust: Trust,
|
||||
@ -55,12 +55,7 @@ mod service_tests {
|
||||
}
|
||||
|
||||
fn clear_env() {
|
||||
let connection = Connection::open(DB_PATH).unwrap();
|
||||
|
||||
connection
|
||||
.execute("DELETE FROM trust_relations", [])
|
||||
.unwrap();
|
||||
connection.execute("DELETE FROM roots", []).unwrap();
|
||||
std::fs::remove_file(TEST_DB_PATH).unwrap_or_default();
|
||||
}
|
||||
|
||||
fn get_correct_timestamp_cp(arg_number: usize) -> CallParameters {
|
||||
@ -445,32 +440,32 @@ mod service_tests {
|
||||
let mut trust_graph = marine_test_env::trust_graph::ServiceInterface::new();
|
||||
clear_env();
|
||||
|
||||
let peerA_kp = KeyPair::generate_ed25519();
|
||||
let peer_a_kp = KeyPair::generate_ed25519();
|
||||
let mut cur_time = 100u64;
|
||||
add_root_with_trust(&mut trust_graph, &peerA_kp, cur_time, cur_time + 9999, 10);
|
||||
add_root_with_trust(&mut trust_graph, &peer_a_kp, cur_time, cur_time + 9999, 10);
|
||||
|
||||
let peerB_kp = KeyPair::generate_ed25519();
|
||||
let peer_b_kp = KeyPair::generate_ed25519();
|
||||
add_trust(
|
||||
&mut trust_graph,
|
||||
&peerA_kp,
|
||||
&peerB_kp.get_peer_id(),
|
||||
&peer_a_kp,
|
||||
&peer_b_kp.get_peer_id(),
|
||||
cur_time,
|
||||
cur_time + 99999,
|
||||
);
|
||||
|
||||
let weight = get_weight(&mut trust_graph, peerB_kp.get_peer_id(), cur_time);
|
||||
let weight = get_weight(&mut trust_graph, peer_b_kp.get_peer_id(), cur_time);
|
||||
assert_ne!(weight, 0u32);
|
||||
|
||||
cur_time += 1;
|
||||
// A revokes B and cancels trust
|
||||
revoke(
|
||||
&mut trust_graph,
|
||||
&peerA_kp,
|
||||
&peerB_kp.get_peer_id(),
|
||||
&peer_a_kp,
|
||||
&peer_b_kp.get_peer_id(),
|
||||
cur_time,
|
||||
);
|
||||
|
||||
let weight = get_weight(&mut trust_graph, peerB_kp.get_peer_id(), cur_time);
|
||||
let weight = get_weight(&mut trust_graph, peer_b_kp.get_peer_id(), cur_time);
|
||||
assert_eq!(weight, 0u32);
|
||||
}
|
||||
|
||||
@ -887,4 +882,40 @@ mod service_tests {
|
||||
assert_eq!(*trust, trusts[i].trust);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_all_cert_from() {
|
||||
let mut trust_graph = ServiceInterface::new();
|
||||
clear_env();
|
||||
let (key_pairs, trusts) =
|
||||
generate_trust_chain_with_len(&mut trust_graph, 5, HashMap::new());
|
||||
|
||||
let cur_time = current_time();
|
||||
let root_peer_id = key_pairs[0].get_peer_id();
|
||||
set_root_peer_id(&mut trust_graph, root_peer_id, 10);
|
||||
|
||||
for auth in trusts.iter() {
|
||||
add_trust_checked(&mut trust_graph, auth.trust.clone(), auth.issuer, cur_time);
|
||||
}
|
||||
|
||||
let cp = get_correct_timestamp_cp_with_host_id(
|
||||
2,
|
||||
key_pairs.last().unwrap().get_peer_id().to_base58(),
|
||||
);
|
||||
let certs = trust_graph.get_all_certs_from_cp(
|
||||
key_pairs[4].get_peer_id().to_base58(),
|
||||
key_pairs[3].get_peer_id().to_base58(),
|
||||
cur_time,
|
||||
cp,
|
||||
);
|
||||
|
||||
assert!(certs.success, "{}", certs.error);
|
||||
let certs = certs.certificates;
|
||||
assert_eq!(certs.len(), 1);
|
||||
assert_eq!(certs[0].chain.len(), 5);
|
||||
|
||||
for (i, trust) in certs[0].chain.iter().enumerate() {
|
||||
assert_eq!(*trust, trusts[i].trust);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
105
trust-graph/CHANGELOG.md
Normal file
105
trust-graph/CHANGELOG.md
Normal file
@ -0,0 +1,105 @@
|
||||
# Changelog
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* fluence-keypair bumped from 0.10.0 to 0.10.1
|
||||
|
||||
## [0.4.8](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.7...trust-graph-v0.4.8) (2023-12-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update marine sdk's, configs and sqlite connector ([#129](https://github.com/fluencelabs/trust-graph/issues/129)) ([0b66f4e](https://github.com/fluencelabs/trust-graph/commit/0b66f4e0536633879de46f69ac8391c72ece7e77))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* fluence-keypair bumped from 0.10.3 to 0.10.4
|
||||
|
||||
## [0.4.7](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.6...trust-graph-v0.4.7) (2023-07-04)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* fluence-keypair bumped from 0.10.2 to 0.10.3
|
||||
|
||||
## [0.4.6](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.5...trust-graph-v0.4.6) (2023-06-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update rust crate derivative to 2.2.0 ([2001f90](https://github.com/fluencelabs/trust-graph/commit/2001f900fa13a949decd513d8cbe15e3f006a7fc))
|
||||
* **deps:** update rust crate derivative to 2.2.0 ([#88](https://github.com/fluencelabs/trust-graph/issues/88)) ([2001f90](https://github.com/fluencelabs/trust-graph/commit/2001f900fa13a949decd513d8cbe15e3f006a7fc))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* release master ([#110](https://github.com/fluencelabs/trust-graph/issues/110)) ([d80a43b](https://github.com/fluencelabs/trust-graph/commit/d80a43bcff721aff8fadf3d2d5c252804ce27a6c))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* fluence-keypair bumped from 0.10.1 to 0.10.2
|
||||
|
||||
## [0.4.5](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.4...trust-graph-v0.4.5) (2023-05-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* dummy to trigger release ([#101](https://github.com/fluencelabs/trust-graph/issues/101)) ([1a26a68](https://github.com/fluencelabs/trust-graph/commit/1a26a6809ea9a90ca8ff3829a76257779a8767d5))
|
||||
|
||||
## [0.4.4](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.3...trust-graph-v0.4.4) (2023-05-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* fix trust-graph package ([#98](https://github.com/fluencelabs/trust-graph/issues/98)) ([a8fdb44](https://github.com/fluencelabs/trust-graph/commit/a8fdb4472ef1676724e4bfab1b4419f07faae2d9))
|
||||
|
||||
## [0.4.3](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.2...trust-graph-v0.4.3) (2023-05-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* dummy change for release ([#95](https://github.com/fluencelabs/trust-graph/issues/95)) ([b6df3fe](https://github.com/fluencelabs/trust-graph/commit/b6df3fe5484b0adcad0c88abe170317a837142b3))
|
||||
|
||||
## [0.4.1](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.4.0...trust-graph-v0.4.1) (2023-04-13)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* **trust-graph:** Synchronize trust-graph, wasm and api versions
|
||||
|
||||
## [0.4.0](https://github.com/fluencelabs/trust-graph/compare/trust-graph-v0.3.2...trust-graph-v0.4.0) (2023-03-15)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **deps:** update libp2p to 0.39.1 and other deps ([#77](https://github.com/fluencelabs/trust-graph/issues/77))
|
||||
|
||||
### Features
|
||||
|
||||
* **deps:** update libp2p to 0.39.1 and other deps ([#77](https://github.com/fluencelabs/trust-graph/issues/77)) ([080503d](https://github.com/fluencelabs/trust-graph/commit/080503dcfa2ecf8d09167ff9fe7f750fadf49035))
|
||||
* **keypair:** add KeyPair::from_secret_key ([#50](https://github.com/fluencelabs/trust-graph/issues/50)) ([a6ce8d9](https://github.com/fluencelabs/trust-graph/commit/a6ce8d9eee20e1ea24eb27c38ac6df6d878292ae))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** Update libp2p-core to 0.38 ([#51](https://github.com/fluencelabs/trust-graph/issues/51)) ([015422e](https://github.com/fluencelabs/trust-graph/commit/015422efcce41530a6cd84a25091598bc459d2e6))
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
* The following workspace dependencies were updated
|
||||
* dependencies
|
||||
* fluence-keypair bumped from 0.9.0 to 0.10.0
|
22
trust-graph/Cargo.toml
Normal file
22
trust-graph/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
name = "trust-graph"
|
||||
version = "0.4.8"
|
||||
authors = ["Fluence Labs"]
|
||||
edition = "2021"
|
||||
description = "trust graph"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/fluencelabs/trust-graph"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.118", features = ["derive"] }
|
||||
|
||||
fluence-keypair = { path = "../keypair", version = "0.10.4" }
|
||||
bs58 = "0.4.0"
|
||||
failure = "0.1.6"
|
||||
log = "0.4.11"
|
||||
ref-cast = "1.0.2"
|
||||
derivative = "2.2.0"
|
||||
thiserror = "1.0.23"
|
||||
sha2 = "0.10.6"
|
||||
nonempty = "0.8.1"
|
||||
rand = "0.8.5"
|
@ -74,14 +74,26 @@ impl Certificate {
|
||||
Self { chain }
|
||||
}
|
||||
|
||||
pub fn new_from_root_trust(root_trust: Trust, issued_trust: Trust, cur_time: Duration) -> Result<Self, CertificateError> {
|
||||
pub fn new_from_root_trust(
|
||||
root_trust: Trust,
|
||||
issued_trust: Trust,
|
||||
cur_time: Duration,
|
||||
) -> Result<Self, CertificateError> {
|
||||
Trust::verify(&root_trust, &root_trust.issued_for, cur_time).map_err(MalformedRoot)?;
|
||||
Trust::verify(&issued_trust, &root_trust.issued_for, cur_time).map_err(|e| VerificationError(1, e))?;
|
||||
Trust::verify(&issued_trust, &root_trust.issued_for, cur_time)
|
||||
.map_err(|e| VerificationError(1, e))?;
|
||||
|
||||
Ok(Self { chain: vec![root_trust, issued_trust] })
|
||||
Ok(Self {
|
||||
chain: vec![root_trust, issued_trust],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn issue_with_trust(issued_by: PublicKey, trust: Trust, extend_cert: &Certificate, cur_time: Duration) -> Result<Self, CertificateError> {
|
||||
pub fn issue_with_trust(
|
||||
issued_by: PublicKey,
|
||||
trust: Trust,
|
||||
extend_cert: &Certificate,
|
||||
cur_time: Duration,
|
||||
) -> Result<Self, CertificateError> {
|
||||
if trust.expires_at.lt(&trust.issued_at) {
|
||||
return Err(ExpirationError {
|
||||
expires_at: format!("{:?}", trust.expires_at),
|
||||
@ -89,7 +101,11 @@ impl Certificate {
|
||||
});
|
||||
}
|
||||
|
||||
Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?;
|
||||
Certificate::verify(
|
||||
extend_cert,
|
||||
&[extend_cert.chain[0].issued_for.clone()],
|
||||
cur_time,
|
||||
)?;
|
||||
// check if `issued_by` is allowed to issue a certificate (i.e., there’s a trust for it in a chain)
|
||||
let mut previous_trust_num: i32 = -1;
|
||||
for pk_id in 0..extend_cert.chain.len() {
|
||||
@ -114,7 +130,6 @@ impl Certificate {
|
||||
Ok(Self { chain: new_chain })
|
||||
}
|
||||
|
||||
|
||||
/// Creates new certificate with root trust (self-signed public key) from a key pair.
|
||||
#[allow(dead_code)]
|
||||
pub fn issue_root(
|
||||
@ -145,13 +160,17 @@ impl Certificate {
|
||||
) -> Result<Self, CertificateError> {
|
||||
if expires_at.lt(&issued_at) {
|
||||
return Err(ExpirationError {
|
||||
expires_at: format!("{:?}", expires_at),
|
||||
issued_at: format!("{:?}", issued_at),
|
||||
expires_at: format!("{expires_at:?}"),
|
||||
issued_at: format!("{issued_at:?}"),
|
||||
});
|
||||
}
|
||||
|
||||
// first, verify given certificate
|
||||
Certificate::verify(extend_cert, &[extend_cert.chain[0].issued_for.clone()], cur_time)?;
|
||||
Certificate::verify(
|
||||
extend_cert,
|
||||
&[extend_cert.chain[0].issued_for.clone()],
|
||||
cur_time,
|
||||
)?;
|
||||
|
||||
let issued_by_pk = issued_by.public();
|
||||
|
||||
@ -309,7 +328,7 @@ impl FromStr for Certificate {
|
||||
str_lines[i + 2],
|
||||
str_lines[i + 3],
|
||||
)
|
||||
.map_err(|e| DecodeTrustError(i, e))?;
|
||||
.map_err(|e| DecodeTrustError(i, e))?;
|
||||
|
||||
trusts.push(trust);
|
||||
}
|
||||
@ -353,7 +372,7 @@ mod tests {
|
||||
cur_time,
|
||||
cur_time,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let serialized = new_cert.to_string();
|
||||
let deserialized = Certificate::from_str(&serialized);
|
||||
@ -380,7 +399,7 @@ mod tests {
|
||||
cur_time,
|
||||
cur_time,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
let serialized = new_cert.encode();
|
||||
let deserialized = Certificate::decode(serialized.as_slice());
|
||||
@ -468,7 +487,7 @@ mod tests {
|
||||
cur_time.checked_sub(one_minute()).unwrap(),
|
||||
cur_time,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
|
||||
assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_err());
|
||||
}
|
||||
@ -490,7 +509,7 @@ mod tests {
|
||||
cur_time,
|
||||
cur_time,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
let new_cert = Certificate::issue(
|
||||
&third_kp,
|
||||
fourth_kp.public(),
|
||||
@ -528,7 +547,7 @@ mod tests {
|
||||
cur_time,
|
||||
cur_time,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap();
|
||||
let new_cert = Certificate::issue(
|
||||
&second_kp,
|
||||
fourth_kp.public(),
|
@ -35,7 +35,7 @@ mod single {
|
||||
{
|
||||
let str = String::deserialize(deserializer)?;
|
||||
Certificate::from_str(&str)
|
||||
.map_err(|e| Error::custom(format!("certificate deserialization failed for {:?}", e)))
|
||||
.map_err(|e| Error::custom(format!("certificate deserialization failed for {e:?}")))
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ pub mod vec {
|
||||
v.into_iter()
|
||||
.map(|e| {
|
||||
Certificate::from_str(&e).map_err(|e| {
|
||||
Error::custom(format!("certificate deserialization failed for {:?}", e))
|
||||
Error::custom(format!("certificate deserialization failed for {e:?}"))
|
||||
})
|
||||
})
|
||||
.collect()
|
@ -5,6 +5,6 @@ pub fn current_time() -> Duration {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as u64,
|
||||
.as_secs(),
|
||||
)
|
||||
}
|
@ -29,7 +29,7 @@ use std::{
|
||||
#[repr(transparent)]
|
||||
pub struct PublicKeyHashable(PublicKey);
|
||||
|
||||
#[allow(clippy::derive_hash_xor_eq)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
impl Hash for PublicKeyHashable {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write(&self.0.encode());
|
||||
@ -120,10 +120,10 @@ impl<'de> serde::Deserialize<'de> for PublicKeyHashable {
|
||||
{
|
||||
bs58::decode(s)
|
||||
.into_vec()
|
||||
.map_err(|err| Error::custom(format!("Invalid string '{}': {}", s, err)))
|
||||
.map_err(|err| Error::custom(format!("Invalid string '{s}': {err}")))
|
||||
.and_then(|v| self.visit_bytes(v.as_slice()))
|
||||
.map_err(|err: E| {
|
||||
Error::custom(format!("Parsed string '{}' as base58, but {}", s, err))
|
||||
Error::custom(format!("Parsed string '{s}' as base58, but {err}"))
|
||||
})
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ impl<'de> serde::Deserialize<'de> for PublicKeyHashable {
|
||||
E: Error,
|
||||
{
|
||||
let pk = PublicKey::decode(b)
|
||||
.map_err(|err| Error::custom(format!("Invalid bytes {:?}: {}", b, err)))?;
|
||||
.map_err(|err| Error::custom(format!("Invalid bytes {b:?}: {err}")))?;
|
||||
Ok(PublicKeyHashable::from(pk))
|
||||
}
|
||||
}
|
@ -48,7 +48,6 @@ pub struct Revocation {
|
||||
}
|
||||
|
||||
impl Revocation {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(
|
||||
revoked_by: PublicKey,
|
||||
pk: PublicKey,
|
||||
@ -64,7 +63,6 @@ impl Revocation {
|
||||
}
|
||||
|
||||
/// Creates new revocation signed by a revoker.
|
||||
#[allow(dead_code)]
|
||||
pub fn create(revoker: &KeyPair, to_revoke: PublicKey, revoked_at: Duration) -> Self {
|
||||
let msg = Revocation::signature_bytes(&to_revoke, revoked_at);
|
||||
let signature = revoker.sign(&msg).unwrap();
|
||||
@ -77,7 +75,7 @@ impl Revocation {
|
||||
let pk_bytes = &pk.encode();
|
||||
metadata.push(pk_bytes.len() as u8);
|
||||
metadata.extend(pk_bytes);
|
||||
metadata.extend_from_slice(&(revoked_at.as_secs() as u64).to_le_bytes());
|
||||
metadata.extend_from_slice(&revoked_at.as_secs().to_le_bytes());
|
||||
|
||||
sha2::Sha256::digest(&metadata).to_vec()
|
||||
}
|
@ -144,8 +144,8 @@ impl Trust {
|
||||
|
||||
pub fn signature_bytes(pk: &PublicKey, expires_at: Duration, issued_at: Duration) -> Vec<u8> {
|
||||
let pk_encoded = pk.encode();
|
||||
let expires_at_encoded: [u8; EXPIRATION_LEN] = (expires_at.as_secs() as u64).to_le_bytes();
|
||||
let issued_at_encoded: [u8; ISSUED_LEN] = (issued_at.as_secs() as u64).to_le_bytes();
|
||||
let expires_at_encoded: [u8; EXPIRATION_LEN] = expires_at.as_secs().to_le_bytes();
|
||||
let issued_at_encoded: [u8; ISSUED_LEN] = issued_at.as_secs().to_le_bytes();
|
||||
let mut metadata = Vec::new();
|
||||
|
||||
metadata.extend(pk_encoded);
|
||||
@ -165,8 +165,8 @@ impl Trust {
|
||||
vec.append(&mut issued_for);
|
||||
vec.push(signature.len() as u8);
|
||||
vec.append(&mut signature);
|
||||
vec.extend_from_slice(&(self.expires_at.as_secs() as u64).to_le_bytes());
|
||||
vec.extend_from_slice(&(self.issued_at.as_secs() as u64).to_le_bytes());
|
||||
vec.extend_from_slice(&self.expires_at.as_secs().to_le_bytes());
|
||||
vec.extend_from_slice(&self.issued_at.as_secs().to_le_bytes());
|
||||
|
||||
vec
|
||||
}
|
||||
@ -260,13 +260,10 @@ impl ToString for Trust {
|
||||
fn to_string(&self) -> String {
|
||||
let issued_for = bs58::encode(self.issued_for.encode()).into_string();
|
||||
let signature = bs58::encode(self.signature.encode()).into_string();
|
||||
let expires_at = (self.expires_at.as_secs() as u64).to_string();
|
||||
let issued_at = (self.issued_at.as_secs() as u64).to_string();
|
||||
let expires_at = self.expires_at.as_secs().to_string();
|
||||
let issued_at = self.issued_at.as_secs().to_string();
|
||||
|
||||
format!(
|
||||
"{}\n{}\n{}\n{}",
|
||||
issued_for, signature, expires_at, issued_at
|
||||
)
|
||||
format!("{issued_for}\n{signature}\n{expires_at}\n{issued_at}")
|
||||
}
|
||||
}
|
||||
|
@ -90,12 +90,12 @@ impl<T: StorageError + 'static> From<T> for TrustGraphError {
|
||||
|
||||
impl From<TrustGraphError> for String {
|
||||
fn from(err: TrustGraphError) -> Self {
|
||||
format!("{}", err)
|
||||
format!("{err}")
|
||||
}
|
||||
}
|
||||
|
||||
fn get_weight_factor(max_chain_len: u32) -> u32 {
|
||||
MAX_WEIGHT_FACTOR.checked_sub(max_chain_len).unwrap_or(0u32)
|
||||
MAX_WEIGHT_FACTOR.saturating_sub(max_chain_len)
|
||||
}
|
||||
|
||||
pub fn get_weight_from_factor(wf: WeightFactor) -> u32 {
|
||||
@ -154,7 +154,7 @@ where
|
||||
C: Borrow<Certificate>,
|
||||
{
|
||||
let chain = &cert.borrow().chain;
|
||||
let mut issued_by = chain.get(0).ok_or(EmptyChain)?.issued_for.clone();
|
||||
let mut issued_by = chain.first().ok_or(EmptyChain)?.issued_for.clone();
|
||||
|
||||
// TODO: optimize to check only root weight
|
||||
for trust in chain {
|
||||
@ -374,8 +374,7 @@ where
|
||||
// Certificate with one trust means nothing, gotta be a bug. Checking for it here.
|
||||
debug_assert!(
|
||||
c.chain.len() > 1,
|
||||
"certificate with chain of len 1 arose: {:#?}",
|
||||
c
|
||||
"certificate with chain of len 1 arose: {c:#?}",
|
||||
);
|
||||
c.chain.len() > 1
|
||||
})
|
Reference in New Issue
Block a user