├── .dockerignore
├── .github
├── ISSUE_TEMPLATE
│ ├── backlog_item.md
│ ├── bug_issue.md
│ ├── config.yml
│ └── general_issue.md
├── dependabot.yml
├── pull_request_template.md
└── workflows
│ ├── check-licence.yml
│ ├── docker.yml
│ ├── publish.yml
│ └── tests.yml
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.md
├── filecoindot-cli
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── README.md
├── src
│ ├── lib.rs
│ └── main.rs
├── test_run.sh
└── tests
│ └── test_all.rs
├── filecoindot-io
├── Cargo.toml
├── README.md
└── src
│ └── lib.rs
├── filecoindot-nft
├── Cargo.toml
├── README.md
└── src
│ ├── lib.rs
│ ├── tests
│ ├── mint.rs
│ ├── mock.rs
│ └── mod.rs
│ └── types.rs
├── filecoindot-proofs
├── Cargo.toml
└── src
│ ├── amt.rs
│ ├── benchmarking.rs
│ ├── errors.rs
│ ├── forest_amt_adaptor.rs
│ ├── forest_hamt_adaptor.rs
│ ├── generate.rs
│ ├── hamt.rs
│ ├── lib.rs
│ ├── traits.rs
│ └── verify.rs
├── filecoindot-rpc
├── Cargo.toml
└── src
│ ├── lib.rs
│ └── result.rs
├── filecoindot
├── Cargo.toml
├── README.md
└── src
│ ├── benchmarking.rs
│ ├── crypto.rs
│ ├── lib.rs
│ ├── ocw
│ ├── api
│ │ ├── chain_head.rs
│ │ └── mod.rs
│ ├── de.rs
│ ├── mod.rs
│ ├── result.rs
│ ├── tests
│ │ ├── data.rs
│ │ ├── ext
│ │ │ ├── db.rs
│ │ │ ├── ext.rs
│ │ │ ├── mod.rs
│ │ │ ├── result.rs
│ │ │ └── state.rs
│ │ ├── get_tip_set_by_height.rs
│ │ └── mod.rs
│ └── types.rs
│ ├── tests
│ ├── mock.rs
│ ├── mod.rs
│ ├── ocw.rs
│ ├── relayer.rs
│ ├── verify.rs
│ └── vote.rs
│ └── types.rs
├── js
├── e2e
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── proof.json
│ ├── setup.ts
│ ├── src
│ │ ├── api.ts
│ │ ├── index.ts
│ │ ├── launch.ts
│ │ └── runner.ts
│ └── tsconfig.json
└── types
│ ├── .gitignore
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── lerna.json
├── package.json
├── resources
├── header.txt
└── types.json
├── scripts
├── setup.json
└── setup.sh
├── substrate-node-example
├── .editorconfig
├── LICENSE
├── README.md
├── node
│ ├── Cargo.toml
│ ├── build.rs
│ └── src
│ │ ├── chain_spec.rs
│ │ ├── cli.rs
│ │ ├── command.rs
│ │ ├── lib.rs
│ │ ├── main.rs
│ │ ├── rpc.rs
│ │ └── service.rs
└── runtime
│ ├── Cargo.toml
│ ├── build.rs
│ └── src
│ ├── lib.rs
│ └── weights
│ ├── filecoindot.rs
│ └── mod.rs
├── ui
├── .env.example
├── .eslintrc.json
├── .gitignore
├── .nvmrc
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.css
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── components
│ │ └── layout
│ │ │ └── Center.tsx
│ ├── constants
│ │ └── substrate.ts
│ ├── containers
│ │ ├── AccountSelect
│ │ │ └── index.tsx
│ │ ├── Header
│ │ │ └── index.tsx
│ │ ├── Settings
│ │ │ └── index.tsx
│ │ └── UserSpace
│ │ │ └── index.tsx
│ ├── contexts
│ │ ├── AccountsContext.tsx
│ │ ├── ApiContext.tsx
│ │ └── NftContext.tsx
│ ├── hooks
│ │ ├── usNft.tsx
│ │ ├── useBuckets.tsx
│ │ └── useDidUpdateEffect.tsx
│ ├── index.css
│ ├── index.tsx
│ ├── interfaces
│ │ ├── augment-api-consts.ts
│ │ ├── augment-api-errors.ts
│ │ ├── augment-api-events.ts
│ │ ├── augment-api-query.ts
│ │ ├── augment-api-rpc.ts
│ │ ├── augment-api-tx.ts
│ │ ├── augment-api.ts
│ │ ├── augment-types.ts
│ │ ├── definitions.ts
│ │ ├── index.ts
│ │ ├── lookup.ts
│ │ ├── types-lookup.ts
│ │ └── types.ts
│ ├── logo.svg
│ ├── logos
│ │ ├── Filecoin.png
│ │ ├── chainsafe.png
│ │ ├── rmrk.png
│ │ └── substrate.png
│ ├── pages
│ │ ├── MintNFT.tsx
│ │ └── VerifyBlock.tsx
│ ├── proof.ts
│ ├── react-app-env.d.ts
│ ├── reportWebVitals.ts
│ └── setupTests.ts
└── tsconfig.json
└── yarn.lock
/.dockerignore:
--------------------------------------------------------------------------------
1 | **/target
2 | **/node_modules
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/backlog_item.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Backlog Item
3 | about: Issue that has enough reasoning, research and information to be implemented
4 | title: ''
5 | labels: 'needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
12 | ## Implementation details
13 |
14 |
15 | ## Testing details
16 |
17 |
18 | ## Acceptance Criteria
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: 'bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Describe the bug
11 |
12 |
13 | -
14 |
15 |
16 | ## Expected Behavior
17 |
18 |
25 |
26 | -
27 |
28 |
29 | ## Current Behavior
30 |
31 |
39 |
40 | -
41 |
42 |
43 | ## Possible Solution
44 |
45 |
53 |
54 | -
55 |
56 |
57 | ## To Reproduce
58 | Steps to reproduce the behavior:
59 |
60 | 1.
61 | 2.
62 | 3.
63 |
64 |
65 | ## Log output
66 |
67 |
68 | Log Output
69 |
70 | ```Paste log output here
71 | paste log output...
72 | ```
73 |
74 |
75 |
76 | ## Specification
77 |
78 |
91 |
92 | - rustc version:
93 | - pint version:
94 | - commit tag:
95 | - commit hash:
96 | - operating system:
97 | - additional links:
98 |
99 |
100 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 |
2 | blank_issues_enabled: true
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/general_issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: General issue
3 | about: General purpose issue template
4 | title: ''
5 | labels: 'needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Issue summary
11 |
12 | -
13 |
14 |
15 | ## Other information and links
16 |
17 | -
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "cargo"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Changes
2 |
3 |
9 |
10 | -
11 | -
12 | -
13 |
14 | ## Tests
15 |
16 |
21 |
22 | ```
23 |
24 | ```
25 |
26 | ## Issues
27 |
28 |
34 |
35 | -
--------------------------------------------------------------------------------
/.github/workflows/check-licence.yml:
--------------------------------------------------------------------------------
1 | name: Check Licence
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | push:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | check-licence:
13 | runs-on: ubuntu-18.04
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Set up Golang
18 | uses: actions/setup-go@v2
19 | with:
20 | go-version: '^1.16'
21 | - name: Install addlicense
22 | run: |
23 | export PATH=${PATH}:`go env GOPATH`/bin
24 | go get -v -u github.com/google/addlicense
25 | - name: Check license
26 | run: |
27 | export PATH=${PATH}:`go env GOPATH`/bin
28 | addlicense -check -c "ChainSafe Systems" -f ./resources/header.txt -y 2021 $(find $PWD -type f -name '*.rs')
29 |
--------------------------------------------------------------------------------
/.github/workflows/docker.yml:
--------------------------------------------------------------------------------
1 | name: docker
2 |
3 | on:
4 | push:
5 | branches: main
6 | pull_request:
7 | types: [ opened, synchronize, reopened ]
8 |
9 | jobs:
10 | docker:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v2
15 | - name: Set up QEMU
16 | uses: docker/setup-qemu-action@v1
17 | - name: Set up Docker Buildx
18 | uses: docker/setup-buildx-action@v1
19 | - name: Login to Github Registry
20 | uses: docker/login-action@v1
21 | with:
22 | registry: ghcr.io
23 | username: ${{ github.actor }}
24 | password: ${{ secrets.GITHUB_TOKEN }}
25 | - name: PrepareReg Names
26 | run: echo IMAGE_REPOSITORY=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
27 | - name: Build and push
28 | id: docker_build
29 | uses: docker/build-push-action@v2
30 | with:
31 | push: ${{ github.event_name == 'push' }}
32 | tags: ghcr.io/chainsafe/filecoindot-template
33 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - "*"
7 | release:
8 | types: [ published ]
9 |
10 | jobs:
11 | publish:
12 | name: Publish
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout code
16 | uses: actions/checkout@v2
17 | - name: Setup Nodejs
18 | uses: actions/setup-node@v2
19 | with:
20 | node-version: '16.x'
21 | registry-url: 'https://registry.npmjs.org'
22 | - name: Build
23 | run: yarn build
24 | - name: Publish
25 | run: cd js/types && yarn publish --access public
26 | env:
27 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
28 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | pull_request:
5 | types: [ opened, synchronize, reopened ]
6 |
7 | jobs:
8 | test:
9 | name: Test Suite
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - uses: actions-rs/toolchain@v1
14 | with:
15 | profile: minimal
16 | target: wasm32-unknown-unknown
17 | # https://github.com/rust-osdev/uefi-rs/issues/329
18 | toolchain: nightly-2021-12-07
19 | override: true
20 | - run: cargo b --all-features --release
21 | - run: cargo t --all-features --release
22 | - run: ./target/release/filecoindot-template benchmark -p "*" -e "*" --wasm-execution compiled
23 | - uses: actions/setup-node@v2
24 | with:
25 | node-version: '16'
26 | - run: yarn e2e
27 |
28 | fmt:
29 | name: Rustfmt
30 | runs-on: ubuntu-latest
31 | steps:
32 | - uses: actions/checkout@v2
33 | - uses: actions-rs/toolchain@v1
34 | with:
35 | profile: minimal
36 | target: wasm32-unknown-unknown
37 | # https://github.com/rust-osdev/uefi-rs/issues/329
38 | toolchain: nightly-2021-12-07
39 | override: true
40 | - run: rustup component add rustfmt
41 | - uses: actions-rs/cargo@v1
42 | with:
43 | command: fmt
44 | args: --all -- --check
45 |
46 | clippy:
47 | name: Clippy
48 | runs-on: ubuntu-latest
49 | steps:
50 | - uses: actions/checkout@v2
51 | - uses: actions-rs/toolchain@v1
52 | with:
53 | profile: minimal
54 | target: wasm32-unknown-unknown
55 | # https://github.com/rust-osdev/uefi-rs/issues/329
56 | toolchain: nightly-2021-12-07
57 | override: true
58 | - run: rustup component add clippy
59 | - uses: actions-rs/cargo@v1
60 | with:
61 | command: clippy
62 | args: -- -D warnings
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .log
2 | .idea
3 | target
4 | node_modules
5 | lib
6 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "filecoindot",
4 | "filecoindot-io",
5 | "filecoindot-proofs",
6 | "filecoindot-rpc",
7 | # node-example
8 | "substrate-node-example/node",
9 | "substrate-node-example/runtime",
10 | "filecoindot-cli",
11 | ]
12 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # syntax=docker/dockerfile:experimental
2 | #
3 | # Copyright 2021 ChainSafe Systems
4 | # SPDX-License-Identifier: LGPL-3.0-only
5 | #
6 | # Building layer
7 | FROM paritytech/ci-linux:production as builder
8 | COPY . .
9 | ENV CARGO_TERM_COLOR=always
10 | RUN --mount=type=cache,target=/usr/local/cargo/git \
11 | --mount=type=cache,target=/usr/local/cargo/registry \
12 | --mount=type=cache,sharing=private,target=target \
13 | cargo +nightly build --release && \
14 | mv target/release/filecoindot-template /filecoindot-template
15 |
16 | # Release
17 | FROM debian:buster-slim
18 | ENV DEBIAN_FRONTEND=noninteractive
19 | LABEL description="The docker image of filecoindot template"
20 | COPY --from=builder /filecoindot-template /usr/local/bin/
21 | RUN apt-get update && \
22 | apt-get install -y --no-install-recommends ca-certificates && \
23 | apt-get autoremove -y && \
24 | apt-get clean && \
25 | rm -rf /var/lib/apt/lists/* && \
26 | useradd -m -u 1000 -U -s /bin/sh -d /filecoindot filecoindot && \
27 | mkdir -p /filecoindot/.local/share && \
28 | mkdir /data && \
29 | chown -R filecoindot:filecoindot /data && \
30 | ln -s /data /filecoindot/.local/share/filecoindot-template && \
31 | rm -rf /usr/bin /usr/sbin
32 |
33 | USER filecoindot
34 | # 30333 for p2p traffic
35 | # 9933 for RPC call
36 | # 9944 for Websocket
37 | # 9615 for Prometheus (metrics)
38 | EXPOSE 30333 9933 9944 9615
39 | VOLUME [ "/data" ]
40 | ENTRYPOINT [ "/usr/local/bin/filecoindot-template" ]
41 |
--------------------------------------------------------------------------------
/filecoindot-cli/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/filecoindot-cli/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "filecoindot-cli"
3 | description = 'Pallet that bridges Filecoin to substrate based chains.'
4 | version = '0.0.1'
5 | license = "GPL-3.0"
6 | homepage = 'https://github.com/ChainSafe/filecoindot'
7 | repository = 'https://github.com/ChainSafe/filecoindot'
8 | edition = "2021"
9 |
10 | [dependencies]
11 | type-cli = "0.0.3"
12 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
13 | hex = "0.4.3"
14 | anyhow = "1"
15 | thiserror = "1"
16 | filecoindot-proofs = { path = "../filecoindot-proofs" }
17 | cid = { package = "forest_cid", version = "0.3" }
18 |
19 |
20 | [features]
21 | default = ['std']
22 | std = [
23 | 'codec/std',
24 | 'hex/std',
25 | ]
26 |
--------------------------------------------------------------------------------
/filecoindot-cli/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | #![deny(warnings)]
5 | use codec::{Decode, Encode};
6 |
7 | #[derive(thiserror::Error, Debug)]
8 | pub enum DecodeError {
9 | #[error("Error decoding from hex: {0}")]
10 | FromHex(#[from] hex::FromHexError),
11 | #[error("codec error: {0}")]
12 | CodecError(#[from] codec::Error),
13 | }
14 |
15 | /// encode a Vec of Vec of bytes into a String using hex encoding
16 | pub fn hex_encode_proof(proof: Vec>) -> String {
17 | hex::encode(proof.encode())
18 | }
19 |
20 | /// decode a hex String into a Vec of Vec of bytes
21 | pub fn decode_proof_from_hex(hex: &str) -> Result>, DecodeError> {
22 | let p = hex::decode(hex)?;
23 | let decoded = Decode::decode(&mut &*p)?;
24 | Ok(decoded)
25 | }
26 |
27 | #[cfg(test)]
28 | mod test {
29 | use super::*;
30 |
31 | #[test]
32 | fn hex_encode_proof_works() {
33 | let p = vec![
34 | vec![
35 | 1, 113, 160, 228, 2, 32, 36, 124, 182, 126, 106, 187, 25, 199, 230, 181, 100, 214,
36 | 154, 77, 62, 109, 17, 9, 120, 21, 205, 111, 102, 96, 38, 79, 186, 148, 178, 110,
37 | 68, 137,
38 | ],
39 | vec![
40 | 1, 113, 160, 228, 2, 32, 181, 170, 59, 78, 87, 6, 123, 107, 23, 248, 104, 224, 201,
41 | 4, 132, 237, 73, 29, 249, 91, 139, 26, 156, 212, 179, 175, 127, 214, 118, 157, 251,
42 | 48,
43 | ],
44 | ];
45 |
46 | let expected = "08980171a0e40220247cb67e6abb19c7e6b564d69a4d3e6d11097815cd6f6660264fba94b26e4489980171a0e40220b5aa3b4e57067b6b17f868e0c90484ed491df95b8b1a9cd4b3af7fd6769dfb30";
47 | let hex_string = hex_encode_proof(p);
48 | assert_eq!(hex_string, expected);
49 | }
50 |
51 | #[test]
52 | fn decode_hex_works() {
53 | let input = "08980171a0e40220247cb67e6abb19c7e6b564d69a4d3e6d11097815cd6f6660264fba94b26e4489980171a0e40220b5aa3b4e57067b6b17f868e0c90484ed491df95b8b1a9cd4b3af7fd6769dfb30";
54 |
55 | let expected = vec![
56 | vec![
57 | 1, 113, 160, 228, 2, 32, 36, 124, 182, 126, 106, 187, 25, 199, 230, 181, 100, 214,
58 | 154, 77, 62, 109, 17, 9, 120, 21, 205, 111, 102, 96, 38, 79, 186, 148, 178, 110,
59 | 68, 137,
60 | ],
61 | vec![
62 | 1, 113, 160, 228, 2, 32, 181, 170, 59, 78, 87, 6, 123, 107, 23, 248, 104, 224, 201,
63 | 4, 132, 237, 73, 29, 249, 91, 139, 26, 156, 212, 179, 175, 127, 214, 118, 157, 251,
64 | 48,
65 | ],
66 | ];
67 | let proof = decode_proof_from_hex(input).expect("must not error");
68 | assert_eq!(proof, expected);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/filecoindot-cli/src/main.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | #![deny(warnings)]
5 | use anyhow::Result;
6 | use cid::Cid;
7 | use filecoindot_cli::{decode_proof_from_hex, DecodeError};
8 | use filecoindot_proofs::generic_verify;
9 | use std::convert::TryFrom;
10 | use thiserror::Error;
11 | use type_cli::CLI;
12 |
13 | #[derive(CLI)]
14 | enum Filecoindot {
15 | Verify {
16 | #[named]
17 | proof: String,
18 | #[named]
19 | cid: String,
20 | },
21 | }
22 |
23 | #[derive(Error, Debug)]
24 | enum CliError {
25 | #[error("CID error: {0}")]
26 | Cid(#[from] filecoindot_proofs::cid::Error),
27 | #[error("Verification Error: {0}")]
28 | Verification(#[from] filecoindot_proofs::Error),
29 | #[error("decode error: {0}")]
30 | Decode(#[from] DecodeError),
31 | }
32 |
33 | fn main() -> Result<(), CliError> {
34 | match Filecoindot::process() {
35 | Filecoindot::Verify { proof, cid } => {
36 | let proof = decode_proof_from_hex(&proof)?;
37 | let cid = Cid::try_from(&*cid)?;
38 | generic_verify(proof, &cid)?;
39 | println!("verification success");
40 | Ok(())
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/filecoindot-io/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "filecoindot-io"
3 | authors = ['tianyi@chainsafe.io']
4 | description = 'filecoindot runtime interfaces.'
5 | version = "0.0.1"
6 | license = "GPL-3.0"
7 | homepage = 'https://github.com/ChainSafe/filecoindot'
8 | repository = 'https://github.com/ChainSafe/filecoindot'
9 | edition = "2021"
10 |
11 | [dependencies]
12 | sp-std = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
13 | sp-runtime-interface = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
14 |
15 | # fileconidot deps
16 | filecoindot-proofs = { path = "../filecoindot-proofs", default-features = false, optional = true }
17 |
18 | [features]
19 | default = [ "std" ]
20 | std = [
21 | "sp-runtime-interface/std",
22 | "sp-std/std",
23 | "filecoindot-proofs"
24 | ]
25 |
--------------------------------------------------------------------------------
/filecoindot-io/README.md:
--------------------------------------------------------------------------------
1 | ## filecoindot-io
2 |
3 | fileconidot runtime interfaces
4 |
--------------------------------------------------------------------------------
/filecoindot-io/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | #![cfg_attr(not(feature = "std"), no_std)]
4 |
5 | use sp_runtime_interface::runtime_interface;
6 | use sp_std::vec::Vec;
7 |
8 | #[runtime_interface]
9 | pub trait ForestProofVerify {
10 | fn verify_receipt(proof: Vec>, cid: Vec) -> Option<()> {
11 | use filecoindot_proofs::{ForestAmtAdaptedNode, ProofVerify, Verify};
12 | ProofVerify::verify_proof::>(proof, cid).ok()
13 | }
14 |
15 | fn verify_state(proof: Vec>, cid: Vec) -> Option<()> {
16 | use filecoindot_proofs::{HAMTNodeType, ProofVerify, Verify};
17 | ProofVerify::verify_proof::(proof, cid).ok()
18 | }
19 |
20 | fn verify_message(proof: Vec>, cid: Vec) -> Option<()> {
21 | use filecoindot_proofs::{MessageNodeType, ProofVerify, Verify};
22 | ProofVerify::verify_proof::(proof, cid).ok()
23 | }
24 | }
25 |
26 | #[runtime_interface]
27 | pub trait Benchmarking {
28 | fn hamt_proof_generation() -> (Vec>, Vec) {
29 | filecoindot_proofs::benchmarking::hamt_proof_generation()
30 | }
31 |
32 | fn amt_proof_generation(n: u64) -> (Vec>, Vec) {
33 | filecoindot_proofs::benchmarking::amt_proof_generation(n as usize)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/filecoindot-nft/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = 'filecoindot-nft'
3 | authors = ['matthias@chainsafe.io']
4 | description = 'Pallet that bridges Filecoin to substrate based chains.'
5 | version = '0.0.1'
6 | license = "GPL-3.0"
7 | homepage = 'https://github.com/ChainSafe/filecoindot'
8 | repository = 'https://github.com/ChainSafe/filecoindot'
9 | edition = "2021"
10 |
11 | [package.metadata.docs.rs]
12 | targets = ['x86_64-unknown-linux-gnu']
13 |
14 | [dependencies]
15 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
16 | serde = { version = "1.0.130", features = [ "derive" ], default-features = false }
17 | serde_json = { version = "1.0", features = [ "alloc" ], default-features = false }
18 | derive_more = "^0.99"
19 |
20 | # substrate dependencies
21 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
22 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
23 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
24 | sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
25 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
26 |
27 | # filecoindot related
28 | filecoindot-io = { path = "../filecoindot-io", default-features = false }
29 |
30 | # orml dependencies
31 | orml-nft = { default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.13" }
32 |
33 | [dev-dependencies]
34 | serde = "1.0.130"
35 | bincode = "1.3.3"
36 | reqwest = { version = "0.11.6", features = [ "json" ] }
37 | parking_lot = "0.11"
38 | futures = "0.3"
39 | tokio = { version = "1.14", features = [ "full" ] }
40 | thiserror = "1.0.30"
41 | dirs = "4.0.0"
42 |
43 | sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
44 | sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
45 | sp-io = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
46 | sp-keystore = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
47 | ipld_hamt = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
48 | ipld_amt = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
49 | ipld_blockstore = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
50 | cid = { package = "forest_cid", version = "0.3" }
51 | serde_cbor = { version = "0.12", features = ["tags"], package = "cs_serde_cbor" }
52 | filecoindot-proofs = { path = "../filecoindot-proofs", default-features = false }
53 |
54 | [features]
55 | default = ['std']
56 | runtime-benchmarks = [
57 | 'frame-benchmarking',
58 | 'frame-support/runtime-benchmarks',
59 | 'frame-system/runtime-benchmarks',
60 | ]
61 | std = [
62 | 'codec/std',
63 | "scale-info/std",
64 | 'frame-support/std',
65 | 'frame-system/std',
66 | 'frame-benchmarking/std',
67 | 'filecoindot-io/std',
68 | ]
69 |
--------------------------------------------------------------------------------
/filecoindot-nft/README.md:
--------------------------------------------------------------------------------
1 | License: Unlicense
2 |
--------------------------------------------------------------------------------
/filecoindot-nft/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! # Filecoin NFT Pallet
5 | //!
6 | //! This pallet will enabled users to mint NFTs
7 | //! providing the cid and proof.
8 | //!
9 | #![cfg_attr(not(feature = "std"), no_std)]
10 |
11 | pub use self::pallet::*;
12 |
13 | mod types;
14 |
15 | #[cfg(test)]
16 | mod tests;
17 |
18 | #[frame_support::pallet]
19 | pub mod pallet {
20 | pub use crate::types::{ClassData, TokenData};
21 | use codec::alloc::vec;
22 | use frame_support::{pallet_prelude::*, sp_std::prelude::*};
23 | use frame_system::pallet_prelude::*;
24 |
25 | pub type TokenIdOf = ::TokenId;
26 | pub type ClassIdOf = ::ClassId;
27 |
28 | const MINT_QUANTITY: u32 = 1;
29 |
30 | /// Configure the pallet by specifying the parameters and types on which it depends.
31 | #[pallet::config]
32 | pub trait Config:
33 | frame_system::Config + orml_nft::Config
34 | {
35 | /// The overarching event type.
36 | type Event: From> + IsType<::Event>;
37 | /// The default class id of the NFT
38 | type DefaultClassId: Get>;
39 | /// The weight for this pallet's extrinsics.
40 | type WeightInfo: WeightInfo;
41 | }
42 |
43 | #[pallet::pallet]
44 | #[pallet::generate_store(pub (super) trait Store)]
45 | pub struct Pallet(_);
46 |
47 | #[pallet::event]
48 | #[pallet::generate_deposit(pub(crate) fn deposit_event)]
49 | pub enum Event {
50 | /// Minted NFT token. \[from, class_id, quantity\]
51 | MintedToken(T::AccountId, ClassIdOf, u32),
52 | /// Transferred NFT token. \[from, to, class_id, token_id\]
53 | TransferredToken(T::AccountId, T::AccountId, ClassIdOf, TokenIdOf),
54 | }
55 |
56 | // Errors inform users that something went wrong.
57 | #[pallet::error]
58 | pub enum Error {
59 | /// The requested token id does not exist
60 | TokenIdNotFound,
61 | }
62 |
63 | #[pallet::hooks]
64 | impl Hooks for Pallet {}
65 |
66 | #[pallet::genesis_config]
67 | pub struct GenesisConfig {
68 | pub default_class: (T::AccountId, Vec),
69 | }
70 |
71 | #[cfg(feature = "std")]
72 | impl Default for GenesisConfig {
73 | fn default() -> Self {
74 | Self {
75 | default_class: (Default::default(), Default::default()),
76 | }
77 | }
78 | }
79 |
80 | #[pallet::genesis_build]
81 | impl GenesisBuild for GenesisConfig {
82 | fn build(&self) {
83 | let (owner, data) = self.default_class.clone();
84 | // just panic if cannot create class
85 | orml_nft::Pallet::::create_class(&owner, vec![], ClassData::new(data))
86 | .expect("cannot create default nft class");
87 | }
88 | }
89 |
90 | #[pallet::call]
91 | impl Pallet {
92 | /// Mint the nft from cid and proof
93 | #[pallet::weight(T::WeightInfo::mint())]
94 | pub fn mint(origin: OriginFor, cid: Vec, proof: Vec>) -> DispatchResult {
95 | let who = ensure_signed(origin)?;
96 | orml_nft::Pallet::::mint(
97 | &who,
98 | T::DefaultClassId::get(),
99 | vec![],
100 | TokenData::new(cid, proof),
101 | )?;
102 | Self::deposit_event(Event::MintedToken(
103 | who,
104 | T::DefaultClassId::get(),
105 | MINT_QUANTITY,
106 | ));
107 | Ok(())
108 | }
109 |
110 | /// Transfer the nft specified with `token_id` from the sender to `to` account
111 | #[pallet::weight(T::WeightInfo::transfer())]
112 | pub fn transfer(
113 | origin: OriginFor,
114 | to: T::AccountId,
115 | token_id: TokenIdOf,
116 | ) -> DispatchResult {
117 | let from = ensure_signed(origin)?;
118 | orml_nft::Pallet::::tokens(T::DefaultClassId::get(), token_id)
119 | .ok_or(Error::::TokenIdNotFound)?;
120 | orml_nft::Pallet::::transfer(&from, &to, (T::DefaultClassId::get(), token_id))?;
121 | Self::deposit_event(Event::TransferredToken(
122 | from,
123 | to,
124 | T::DefaultClassId::get(),
125 | token_id,
126 | ));
127 | Ok(())
128 | }
129 | }
130 |
131 | impl Pallet {
132 | /// Get the balance of the account
133 | pub fn balance(who: &T::AccountId) -> u128 {
134 | orml_nft::TokensByOwner::::iter_prefix((who, T::DefaultClassId::get())).count()
135 | as u128
136 | }
137 |
138 | /// Get the list of token ids owned by the account.
139 | /// Quite expensive, invoke with care. Should use indexer for this.
140 | pub fn tokens(who: &T::AccountId) -> Vec> {
141 | orml_nft::TokensByOwner::::iter_prefix((who, T::DefaultClassId::get()))
142 | .map(|t| t.0)
143 | .collect::>()
144 | }
145 |
146 | /// Get the details of a specific token
147 | pub fn token_detail(token_id: TokenIdOf) -> Result> {
148 | let token = orml_nft::Pallet::::tokens(T::DefaultClassId::get(), token_id)
149 | .ok_or(Error::::TokenIdNotFound)?;
150 | Ok(token.data)
151 | }
152 | }
153 |
154 | pub trait WeightInfo {
155 | fn mint() -> Weight;
156 | fn transfer() -> Weight;
157 | }
158 |
159 | /// For backwards compatibility and tests
160 | impl WeightInfo for () {
161 | fn mint() -> Weight {
162 | Default::default()
163 | }
164 | fn transfer() -> Weight {
165 | Default::default()
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/filecoindot-nft/src/tests/mint.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use crate::tests::mock::*;
5 | use frame_support::assert_ok;
6 |
7 | #[test]
8 | fn mint_works() {
9 | ExtBuilder::default().build().execute_with(|| {
10 | assert_ok!(FilecoinNFT::mint(Origin::signed(ALICE), vec![], vec![]));
11 | });
12 | }
13 |
14 | #[test]
15 | fn tokens_works() {
16 | ExtBuilder::default().build().execute_with(|| {
17 | assert_ok!(FilecoinNFT::mint(Origin::signed(ALICE), vec![], vec![]));
18 | assert_ok!(FilecoinNFT::mint(Origin::signed(ALICE), vec![2], vec![]));
19 | FilecoinNFT::tokens(&ALICE);
20 | });
21 | }
22 |
23 | #[test]
24 | fn tokens_details_works() {
25 | ExtBuilder::default().build().execute_with(|| {
26 | let cid = vec![1u8];
27 | let proof = vec![vec![2u8]];
28 | assert_ok!(FilecoinNFT::mint(
29 | Origin::signed(ALICE),
30 | cid.clone(),
31 | proof.clone()
32 | ));
33 | assert_ok!(FilecoinNFT::mint(Origin::signed(ALICE), vec![2], vec![]));
34 | let r = FilecoinNFT::token_detail(0).unwrap();
35 |
36 | assert_eq!(r.cid, cid);
37 | assert_eq!(r.proof, proof);
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/filecoindot-nft/src/tests/mock.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use crate as pallet;
5 | use crate::{ClassData, TokenData};
6 | use frame_support::construct_runtime;
7 | use frame_support::pallet_prelude::GenesisBuild;
8 | use frame_support::parameter_types;
9 | use sp_core::{sr25519::Public, H256};
10 | use sp_runtime::{testing::Header, traits::IdentityLookup};
11 |
12 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
13 | type Block = frame_system::mocking::MockBlock;
14 |
15 | pub type AccountId = Public;
16 | pub const ALICE: AccountId = Public([1u8; 32]);
17 |
18 | // Configure a mock runtime to test the pallet.
19 | construct_runtime!(
20 | pub enum Test where
21 | Block = Block,
22 | NodeBlock = Block,
23 | UncheckedExtrinsic = UncheckedExtrinsic,
24 | {
25 | System: frame_system::{Pallet, Call, Config, Storage, Event},
26 | FilecoinNFT: pallet::{Pallet, Call, Storage, Event},
27 | NFT: orml_nft::{Pallet, Storage},
28 | }
29 | );
30 |
31 | parameter_types! {
32 | pub const BlockHashCount: u64 = 250;
33 | pub const SS58Prefix: u8 = 42;
34 | pub const OffchainWorkerTimeout: u64 = 1_000_000;
35 | }
36 |
37 | impl frame_system::Config for Test {
38 | type Origin = Origin;
39 | type Call = Call;
40 | type Index = u64;
41 | type BlockNumber = u64;
42 | type Hash = H256;
43 | type Hashing = ::sp_runtime::traits::BlakeTwo256;
44 | type AccountId = sp_core::sr25519::Public;
45 | type Lookup = IdentityLookup;
46 | type Header = Header;
47 | type Event = Event;
48 | type BlockHashCount = BlockHashCount;
49 | type BlockWeights = ();
50 | type BlockLength = ();
51 | type Version = ();
52 | type PalletInfo = PalletInfo;
53 | type AccountData = ();
54 | type OnNewAccount = ();
55 | type OnKilledAccount = ();
56 | type DbWeight = ();
57 | type BaseCallFilter = frame_support::traits::Everything;
58 | type SystemWeightInfo = ();
59 | type SS58Prefix = ();
60 | type OnSetCode = ();
61 | }
62 |
63 | parameter_types! {
64 | pub MaxClassMetadata: u32 = 1024;
65 | pub MaxTokenMetadata: u32 = 1024;
66 | }
67 |
68 | impl orml_nft::Config for Test {
69 | type ClassId = u32;
70 | type TokenId = u32;
71 | type ClassData = ClassData;
72 | type TokenData = TokenData;
73 | type MaxClassMetadata = MaxClassMetadata;
74 | type MaxTokenMetadata = MaxTokenMetadata;
75 | }
76 |
77 | parameter_types! {
78 | pub DefaultClassId: u32 = 0;
79 | }
80 |
81 | impl pallet::Config for Test {
82 | type Event = Event;
83 | type DefaultClassId = DefaultClassId;
84 | type WeightInfo = ();
85 | }
86 |
87 | pub struct ExtBuilder {
88 | pub default_class: (AccountId, Vec),
89 | }
90 |
91 | impl Default for ExtBuilder {
92 | fn default() -> Self {
93 | Self {
94 | default_class: (ALICE, vec![0]),
95 | }
96 | }
97 | }
98 |
99 | impl ExtBuilder {
100 | pub fn build(self) -> sp_io::TestExternalities {
101 | let mut t = frame_system::GenesisConfig::default()
102 | .build_storage::()
103 | .unwrap();
104 |
105 | pallet::GenesisConfig:: {
106 | default_class: (ALICE, vec![0]),
107 | }
108 | .assimilate_storage(&mut t)
109 | .unwrap();
110 | t.into()
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/filecoindot-nft/src/tests/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | mod mint;
5 | mod mock;
6 |
--------------------------------------------------------------------------------
/filecoindot-nft/src/types.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use frame_support::pallet_prelude::*;
5 | use frame_support::sp_std;
6 | use scale_info::TypeInfo;
7 | use serde::{Deserialize, Serialize};
8 | use sp_std::prelude::*;
9 |
10 | #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, Default)]
11 | #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
12 | pub struct ClassData {
13 | /// The data stored in the class
14 | pub data: Vec,
15 | }
16 |
17 | impl ClassData {
18 | pub fn new(data: Vec) -> Self {
19 | ClassData { data }
20 | }
21 | }
22 |
23 | #[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo)]
24 | #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
25 | pub struct TokenData {
26 | /// The cid of the data in filecoin
27 | pub cid: Vec,
28 | pub proof: Vec>,
29 | }
30 |
31 | impl TokenData {
32 | pub fn new(cid: Vec, proof: Vec>) -> Self {
33 | TokenData { cid, proof }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/filecoindot-proofs/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "filecoindot-proofs"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | serde = { version = "1.0", features = ["derive"] }
8 | byteorder = "1.3.2"
9 | cid = { package = "forest_cid", version = "0.3" }
10 | serde_bytes = { package = "cs_serde_bytes", version = "0.12" }
11 | thiserror = "1.0"
12 | sha2 = "0.9.1"
13 | once_cell = "1.5"
14 | parking_lot = "0.11"
15 | num-traits = "0.2.14"
16 | ipld_hamt = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
17 | ipld_amt = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
18 | forest_ipld = { version = "0.1.1" }
19 | forest_encoding = { version = "0.2.1" }
20 | forest_hash_utils = { version = "0.1" }
21 | forest_db = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
22 | ipld_blockstore = { git = "https://github.com/willeslau/forest", branch = "willes/filecoindot" }
23 | serde_cbor = { version = "0.12", features = ["tags"], package = "cs_serde_cbor" }
24 |
25 | [features]
26 | default = [ "std" ]
27 | std = []
28 |
--------------------------------------------------------------------------------
/filecoindot-proofs/src/amt.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2022 ChainSafe Systems
2 | // SPDX-License-Identifier: Apache-2.0, MIT
3 |
4 | use crate::errors::Error;
5 | use crate::traits::{AMTNode, BlockStore};
6 | use cid::Cid;
7 | use forest_encoding::de::Deserializer;
8 | use serde::Deserialize;
9 |
10 | pub fn nodes_for_height(bit_width: usize, height: usize) -> usize {
11 | let height_log_two = bit_width * height;
12 | if height_log_two >= 64 {
13 | return std::usize::MAX;
14 | }
15 | 1 << height_log_two
16 | }
17 |
18 | const MAX_HEIGHT: usize = 8;
19 | const MAX_INDEX: usize = (u64::MAX - 1) as usize;
20 |
21 | #[allow(dead_code)]
22 | #[derive(Debug)]
23 | pub struct Amt<'db, BS: BlockStore, N: AMTNode> {
24 | node: N,
25 | block_store: Option<&'db BS>,
26 | bit_width: usize,
27 | height: usize,
28 | count: usize,
29 | }
30 |
31 | impl<'db, 'de, BS: BlockStore, N: AMTNode + Deserialize<'de>> Deserialize<'de> for Amt<'db, BS, N> {
32 | fn deserialize(deserializer: D) -> Result
33 | where
34 | D: Deserializer<'de>,
35 | {
36 | let (bit_width, height, count, node): (_, _, _, N) =
37 | Deserialize::deserialize(deserializer)?;
38 | Ok(Self {
39 | bit_width,
40 | height,
41 | count,
42 | node,
43 | block_store: None,
44 | })
45 | }
46 | }
47 |
48 | impl<'db, BS, N> Amt<'db, BS, N>
49 | where
50 | BS: BlockStore,
51 | N: AMTNode + for<'de> Deserialize<'de>,
52 | {
53 | /// Constructs an AMT with a blockstore and a Cid of the root of the AMT
54 | pub fn load(cid: &Cid, block_store: &'db BS) -> Result {
55 | // Load root bytes from database
56 | let mut root = block_store.get::(cid)?;
57 |
58 | // Sanity check, this should never be possible.
59 | if root.height > MAX_HEIGHT {
60 | return Err(Error::MaxHeightExceeded);
61 | }
62 |
63 | root.block_store = Some(block_store);
64 | Ok(root)
65 | }
66 |
67 | /// Get value at index of AMT
68 | pub fn generate_proof(&self, i: usize) -> Result>, Error> {
69 | if i > MAX_INDEX {
70 | return Err(Error::NotFound);
71 | }
72 |
73 | if i >= nodes_for_height(self.bit_width, self.height + 1) {
74 | return Err(Error::NotFound);
75 | }
76 |
77 | let mut path = Vec::new();
78 | if self.node.path_to_key(
79 | *self.block_store.as_ref().unwrap(),
80 | self.bit_width,
81 | self.height,
82 | i,
83 | &mut path,
84 | )? {
85 | Ok(path)
86 | } else {
87 | Err(Error::NotFound)
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/filecoindot-proofs/src/benchmarking.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use crate::{
5 | deserialize_to_node, Amt, ForestAdaptedBlockStorage, ForestAdaptedHashAlgo,
6 | ForestAdaptedHashedBits, ForestAdaptedNode, ForestAmtAdaptedNode, GetCid, HAMTNodeType, Hamt,
7 | };
8 | use ipld_amt::Amt as ForestAmt;
9 | use ipld_blockstore::MemoryDB;
10 | use ipld_hamt::Hamt as ForestHamt;
11 | use serde_cbor::from_slice;
12 |
13 | #[allow(clippy::type_complexity)]
14 | pub fn hamt_proof_generation() -> (Vec>, Vec) {
15 | let bs = MemoryDB::default();
16 | let mut fhamt: ForestHamt<_, _, usize> = ForestHamt::new(&bs);
17 |
18 | let max = 1000;
19 | for i in 1..max {
20 | fhamt.set(i, i.to_string()).unwrap();
21 | }
22 |
23 | let cid = fhamt.flush().unwrap();
24 | let store = ForestAdaptedBlockStorage::new(bs);
25 | let hamt: Hamt<
26 | ForestAdaptedBlockStorage,
27 | usize,
28 | String,
29 | ForestAdaptedHashedBits,
30 | ForestAdaptedNode,
31 | ForestAdaptedHashAlgo,
32 | > = Hamt::new(&cid, &store, 8).unwrap();
33 | let mut p = hamt.generate_proof(&(max / 2)).unwrap();
34 | p.reverse();
35 | let raw_node = p.get(0).unwrap();
36 | let node: HAMTNodeType = deserialize_to_node(None, raw_node).unwrap();
37 | (p, node.cid().unwrap().to_bytes())
38 | }
39 |
40 | pub fn amt_proof_generation(n: usize) -> (Vec>, Vec) {
41 | let bs = MemoryDB::default();
42 | let mut famt = ForestAmt::new(&bs);
43 |
44 | let max = 1000;
45 | for i in 1..max {
46 | famt.set(i, i.to_string()).unwrap();
47 | }
48 |
49 | let cid = famt.flush().unwrap();
50 | let store = ForestAdaptedBlockStorage::new(bs);
51 | let amt: Amt, ForestAmtAdaptedNode> =
52 | Amt::load(&cid, &store).unwrap();
53 | let p = amt.generate_proof(n).unwrap();
54 | let raw_node = p.get(0).unwrap();
55 | let node: ForestAmtAdaptedNode = from_slice(raw_node).unwrap();
56 | (p, node.cid().unwrap().to_bytes())
57 | }
58 |
--------------------------------------------------------------------------------
/filecoindot-proofs/src/errors.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2022 ChainSafe Systems
2 | // SPDX-License-Identifier: Apache-2.0, MIT
3 |
4 | /// Database error
5 | #[derive(thiserror::Error, Debug)]
6 | pub enum Error {
7 | #[error("Invalid Hashbit length")]
8 | InvalidHashBitLen,
9 | #[error("MaxDepth error")]
10 | MaxDepth,
11 | #[error("Not found")]
12 | NotFound,
13 | #[error("Proof verification failed")]
14 | VerificationFailed,
15 | #[error("Max height exceeded")]
16 | MaxHeightExceeded,
17 | #[error("Cid not found `{0}`")]
18 | CidNotFound(String),
19 | #[error("IPLD AMT error `{0}`")]
20 | IPLDAmt(#[from] ipld_amt::Error),
21 | #[error("IPLD HAMT error `{0}`")]
22 | IPLDHamt(#[from] ipld_hamt::Error),
23 | #[error("ForestDB error `{0}`")]
24 | ForestDB(#[from] forest_db::Error),
25 | #[error("CborEncoding error `{0}`")]
26 | CborEncoding(#[from] serde_cbor::Error),
27 | #[error("IPLD blockstore error `{0}`")]
28 | BlockStore(#[from] ipld_blockstore::Error),
29 | #[error("Generic error `{0}`")]
30 | Other(String),
31 | }
32 |
--------------------------------------------------------------------------------
/filecoindot-proofs/src/generate.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Generation of proofs for AMT and HAMT tries
5 |
6 | // pub mod hamt {
7 | // use crate::errors::Error;
8 | // use crate::hamt::Hamt;
9 | //
10 | // /// Generate an inclusion proof for the value in the given HAMT.
11 | // pub fn generate_proof<'db, V, BS>(
12 | // hamt: &Hamt<'db, BS, V>,
13 | // value: V,
14 | // ) -> Result>, Error> {
15 | // // each node can have up to 32 children
16 | //
17 | // todo!()
18 | // }
19 | // }
20 |
--------------------------------------------------------------------------------
/filecoindot-proofs/src/hamt.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2019-2022 ChainSafe Systems
2 | // SPDX-License-Identifier: Apache-2.0, MIT
3 |
4 | use cid::Cid;
5 | use ipld_hamt::Hash;
6 | use std::marker::PhantomData;
7 |
8 | use crate::errors::Error;
9 | use crate::traits::{BlockStore, HAMTNode, HashAlgorithm, HashedBits};
10 |
11 | /// This is a simplified implementation of HAMT based on:
12 | /// http://lampwww.epfl.ch/papers/idealhashtrees.pdf
13 | ///
14 | /// This implementation has only implemented the read related functions
15 | /// as we only care about generating the path to the node
16 | #[derive(Debug)]
17 | pub struct Hamt<'a, BS, K: Eq, V, H: HashedBits, N: HAMTNode, HashAlgo> {
18 | root: N,
19 | store: &'a BS,
20 | bit_width: u8,
21 | hash: PhantomData,
22 | _k: PhantomData,
23 | _v: PhantomData,
24 | _h: PhantomData,
25 | }
26 |
27 | impl<'a, BS, K, V, H, N, HashAlgo> Hamt<'a, BS, K, V, H, N, HashAlgo>
28 | where
29 | K: Eq + Hash,
30 | H: HashedBits,
31 | HashAlgo: HashAlgorithm