├── source
├── release
│ ├── Source code.zip
│ └── Source code.tar.gz
└── did-fabric-contract
│ ├── chaincode
│ ├── data
│ │ ├── data_type.go
│ │ ├── credential_schema.go
│ │ ├── provider.go
│ │ ├── service.go
│ │ ├── vcmeta.go
│ │ ├── status.go
│ │ ├── verification_method.go
│ │ └── document.go
│ ├── validate
│ │ └── custom_validator.go
│ ├── utility
│ │ ├── json_util.go
│ │ └── crypto.go
│ ├── repository
│ │ ├── vcmeta_repository.go
│ │ └── document_repository.go
│ ├── service
│ │ ├── vcmeta_service.go
│ │ └── document_service.go
│ ├── error
│ │ └── error.go
│ └── opendid.go
│ ├── main.go
│ ├── go.mod
│ ├── README_ko.md
│ ├── README.md
│ └── go.sum
├── CHANGELOG.md
├── signatures
└── version1
│ └── cla.json
├── .gitignore
├── .github
├── pull_request_template.yml
├── workflows
│ ├── fabric_contract_ci.yml
│ ├── auto_assign.yml
│ ├── fabric_contract_release.yml
│ └── cla.yml
└── ISSUE_TEMPLATE
│ ├── bug_report.yaml
│ └── feature_request.yaml
├── MAINTAINERS.md
├── dependencies-license.md
├── SECURITY.md
├── README_ko.md
├── README.md
├── RELEASE-PROCESS.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── docs
└── api
│ └── ContractError.md
├── CLA.md
└── LICENSE
/source/release/Source code.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmniOneID/did-fabric-contract/HEAD/source/release/Source code.zip
--------------------------------------------------------------------------------
/source/release/Source code.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OmniOneID/did-fabric-contract/HEAD/source/release/Source code.tar.gz
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## v1.0.0 (2024-10-18)
4 |
5 | ### 🚀 New Features
6 |
7 | - DID Document transaction management
8 | - VerifiableCredential Metadata transaction management
9 |
--------------------------------------------------------------------------------
/signatures/version1/cla.json:
--------------------------------------------------------------------------------
1 | {
2 | "signedContributors": [
3 | {
4 | "name": "jhkim5981",
5 | "id": 180237641,
6 | "comment_id": 2406640378,
7 | "created_at": "2024-10-11T06:28:52Z",
8 | "repoId": 808509241,
9 | "pullRequestNo": 2
10 | }
11 | ]
12 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # If you prefer the allow list template instead of the deny list, see community template:
2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3 | #
4 | # Binaries for programs and plugins
5 | *.exe
6 | *.exe~
7 | *.dll
8 | *.so
9 | *.dylib
10 |
11 | # Test binary, built with `go test -c`
12 | *.test
13 |
14 | # Output of the go coverage tool, specifically when used with LiteIDE
15 | *.out
16 |
17 | # Dependency directories (remove the comment below to include it)
18 | vendor/
19 |
20 | # Go workspace file
21 | go.work
22 | go.work.sum
23 |
--------------------------------------------------------------------------------
/.github/pull_request_template.yml:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 | ## Related Issue (Optional)
5 |
6 | - Issue # (e.g., #123)
7 |
8 | ## Changes
9 |
10 | - Change 1
11 | - Change 2
12 |
13 | ## Screenshots (Optional)
14 |
15 |
16 | ## Additional Comments (Optional)
17 |
18 |
--------------------------------------------------------------------------------
/MAINTAINERS.md:
--------------------------------------------------------------------------------
1 | # Maintainers
2 |
3 | ## Overview
4 |
5 | This file lists the maintainers for this project. Maintainers are responsible for reviewing and merging pull requests, ensuring code quality, and managing releases.
6 | If you have any questions or require support, please reach out to the maintainers listed below.
7 |
8 |
9 | ## Maintainers
10 | | Name | GitHub | email |
11 | |------------------ |-----------------|-------------------------------------|
12 | | Jeongheon Kim | jhkim5981 | jhkim5981@raoncorp.com |
13 | | Minyong Kim | black-billed-magpie | mykim@raoncorp.com |
--------------------------------------------------------------------------------
/.github/workflows/fabric_contract_ci.yml:
--------------------------------------------------------------------------------
1 | name: Fabric Contract CI
2 |
3 | on:
4 | push:
5 | branches: [ main, develop ]
6 | pull_request:
7 | branches: [ main, develop ]
8 |
9 | jobs:
10 | fabric-contract-build:
11 | runs-on: ubuntu-latest
12 | timeout-minutes: 60
13 |
14 | defaults:
15 | run:
16 | working-directory: source/did-fabric-contract
17 |
18 | steps:
19 | - uses: actions/checkout@v4
20 |
21 | - name: Set up Go 1.22
22 | uses: actions/setup-go@v5
23 | with:
24 | go-version: '1.22'
25 |
26 | - name: Install dependencies
27 | run: |
28 | go mod tidy
29 | go mod vendor
30 |
31 | - name: Build the project
32 | run: go build ./...
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/data_type.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | type URL string
18 | type Multibase string
19 | type UTCDateTime string
20 |
--------------------------------------------------------------------------------
/dependencies-license.md:
--------------------------------------------------------------------------------
1 | # License Information
2 |
3 | ### This project uses the following third-party libraries, each under its own license:
4 |
5 |
6 |
7 | **Btcutil: ISC License**
8 | `github.com/btcsuite/btcutil v1.0.2`
9 | (http://github.com/btcsuite/btcutil)
10 |
11 |
12 |
13 | **CCKit: Apache License 2.0**
14 | `github.com/hyperledger-labs/cckit v1.0.5`
15 | (http://github.com/hyperledger-labs/cckit)
16 |
17 |
18 |
19 | **Fabric Chaincode Go: Apache License 2.0**
20 | `github.com/hyperledger/fabric-chaincode-go v0.0.0-20240704073638-9fb89180dc17`
21 | (http://github.com/hyperledger/fabric-chaincode-go)
22 |
23 |
24 |
25 | **Validator.v9: MIT License**
26 | `gopkg.in/go-playground/validator.v9 v9.31.0`
27 | (https://github.com/go-playground/validator)
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/credential_schema.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | type CREDENTIAL_SCHEMA_TYPE string
18 |
19 | type CredentialSchema struct {
20 | Id URL `validate:"url" json:"id"`
21 | Type CREDENTIAL_SCHEMA_TYPE `validate:"oneof=OsdSchemaCredential" json:"type"`
22 | }
23 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/main.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package main
16 |
17 | import (
18 | "did-fabric-contract/chaincode"
19 | "fmt"
20 |
21 | "github.com/hyperledger/fabric-chaincode-go/shim"
22 | )
23 |
24 | func main() {
25 | if err := shim.Start(chaincode.NewOpenDIDCC()); err != nil {
26 | fmt.Printf("error starting cc : %s", err)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 | In this project, the following versions have undergone security vulnerability assessments:
5 |
6 | | Version | Supported |
7 | | ------- | ------------------ |
8 | | 1.0.0 | ✅ |
9 |
10 | ## Reporting a Vulnerability
11 | If you discover a new security vulnerability, please report it via [technology@omnione.net](mailto:technology@omnione.net).
12 |
13 | ## Sensitive Information Protection
14 | Please ensure that sensitive information, such as API keys, passwords, and personal data, is never included in the code or documentation. Such information should be managed outside the code, preferably using environment variables.
15 |
16 | ## Security Policy Configuration
17 | - Vulnerability Management: If a vulnerability is discovered, follow the security reporting procedures and collaborate to apply security patches as quickly as possible.
18 | - Code Review: Any changes related to security must always go through the review process, and multiple contributors should be involved in the review to ensure thorough checks.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yaml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: File a bug report.
3 | title: "[Bug]: "
4 | labels: ["bug", "triage"]
5 | assignees: [""]
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for taking the time to fill out this bug report!
11 | - type: textarea
12 | id: what-happened
13 | attributes:
14 | label: What happened?
15 | description: Also tell us, what did you expect to happen?
16 | placeholder: Tell us what you see!
17 | validations:
18 | required: true
19 | - type: input
20 | id: version
21 | attributes:
22 | label: Version
23 | description: What version of our software are you running?
24 | validations:
25 | required: true
26 | - type: textarea
27 | id: logs
28 | attributes:
29 | label: Relevant log output
30 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
31 | render: shell
32 | - type: checkboxes
33 | id: terms
34 | attributes:
35 | label: Code of Conduct
36 | description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md).
37 | options:
38 | - label: I agree to follow this project's Code of Conduct
39 | required: true
40 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/go.mod:
--------------------------------------------------------------------------------
1 | module did-fabric-contract
2 |
3 | go 1.22
4 |
5 | require (
6 | github.com/btcsuite/btcutil v1.0.2
7 | github.com/hyperledger-labs/cckit v1.0.5
8 | github.com/hyperledger/fabric-chaincode-go v0.0.0-20240704073638-9fb89180dc17
9 | gopkg.in/go-playground/validator.v9 v9.31.0
10 | )
11 |
12 | require (
13 | github.com/go-playground/locales v0.14.1 // indirect
14 | github.com/go-playground/universal-translator v0.18.1 // indirect
15 | github.com/gogo/protobuf v1.3.2 // indirect
16 | github.com/golang/protobuf v1.5.4 // indirect
17 | github.com/hyperledger/fabric-protos-go v0.3.3 // indirect
18 | github.com/leodido/go-urn v1.4.0 // indirect
19 | github.com/mwitkow/go-proto-validators v0.3.2 // indirect
20 | github.com/onsi/ginkgo v1.16.5 // indirect
21 | github.com/onsi/gomega v1.34.2 // indirect
22 | github.com/pkg/errors v0.8.1 // indirect
23 | go.uber.org/atomic v1.6.0 // indirect
24 | go.uber.org/multierr v1.5.0 // indirect
25 | go.uber.org/zap v1.14.1 // indirect
26 | golang.org/x/net v0.28.0 // indirect
27 | golang.org/x/sys v0.24.0 // indirect
28 | golang.org/x/text v0.17.0 // indirect
29 | google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
30 | google.golang.org/grpc v1.65.0 // indirect
31 | google.golang.org/protobuf v1.34.1 // indirect
32 | gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
33 | )
34 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/validate/custom_validator.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package validate
16 |
17 | import (
18 | "gopkg.in/go-playground/validator.v9"
19 | )
20 |
21 | func isParentExist(fl validator.FieldLevel) bool {
22 | return !fl.Parent().IsZero()
23 | }
24 |
25 | func optionalRequiredValidator(fl validator.FieldLevel) bool {
26 | if isParentExist(fl) && fl.Field().String() == "" {
27 | return false
28 | }
29 | return true
30 | }
31 |
32 | func RegisterDocumentValidator() *validator.Validate {
33 | v := validator.New()
34 | v.RegisterValidation("optionalRequired", optionalRequiredValidator)
35 | return v
36 | }
37 |
38 | func RegisterVcMetaValidator() *validator.Validate {
39 | v := validator.New()
40 | v.RegisterValidation("optionalRequired", optionalRequiredValidator)
41 | return v
42 | }
43 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/utility/json_util.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package utility
16 |
17 | import (
18 | "encoding/json"
19 | "sort"
20 | )
21 |
22 | func SortJson(jsonData []byte) []byte {
23 | var jsonMap map[string]interface{}
24 | json.Unmarshal(jsonData, &jsonMap)
25 |
26 | sortedJsonMap := SortJsonKeys(jsonMap)
27 | sortedJsonData, _ := json.Marshal(sortedJsonMap)
28 | return sortedJsonData
29 | }
30 |
31 | func SortJsonKeys(data map[string]interface{}) map[string]interface{} {
32 | sortedMap := make(map[string]interface{})
33 | keys := make([]string, 0, len(data))
34 | for k := range data {
35 | keys = append(keys, k)
36 | }
37 | sort.Strings(keys)
38 | for _, k := range keys {
39 | value := data[k]
40 | if nestedMap, ok := value.(map[string]interface{}); ok {
41 | sortedMap[k] = SortJsonKeys(nestedMap)
42 | } else {
43 | sortedMap[k] = value
44 | }
45 | }
46 | return sortedMap
47 | }
48 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/provider.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | const (
18 | TAS ROLE_TYPE = "Tas"
19 | Wallet ROLE_TYPE = "Wallet"
20 | Issuer ROLE_TYPE = "Issuer"
21 | WalletProvider ROLE_TYPE = "WalletProvider"
22 | AppProvider ROLE_TYPE = "AppProvider"
23 | ListProvider ROLE_TYPE = "ListProvider"
24 | OpProvider ROLE_TYPE = "OpProvider"
25 | KycProvider ROLE_TYPE = "KycProvider"
26 | NotificationProvider ROLE_TYPE = "NotificationProvider"
27 | LogProvider ROLE_TYPE = "LogProvider"
28 | PortalProvider ROLE_TYPE = "PortalProvider"
29 | DelegationProvider ROLE_TYPE = "DelegationProvider"
30 | StorageProvider ROLE_TYPE = "StorageProvider"
31 | BackupProvider ROLE_TYPE = "BackupProvider"
32 | Etc ROLE_TYPE = "Etc"
33 | )
34 |
35 | type Provider struct {
36 | Did string `validate:"required" json:"did"`
37 | CertVcRef URL `validate:"required,url" json:"certVcRef"`
38 | }
39 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/service.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | type DID_SERVICE_TYPE string
18 | type DID_SERVICE_ID string
19 |
20 | const (
21 | LinkedDomains DID_SERVICE_TYPE = "LinkedDomains"
22 | Credentialregistry DID_SERVICE_TYPE = "Credentialregistry"
23 | )
24 |
25 | type Service struct {
26 | Id DID_SERVICE_ID `validate:"required" json:"id"`
27 | Type DID_SERVICE_TYPE `validate:"required,oneof=Credentialregistry LinkedDomains" json:"type"`
28 | ServiceEndpoint []URL `validate:"required" json:"serviceEndpoint"`
29 | }
30 |
31 | func (a *Service) IsEqual(b *Service) bool {
32 | if a.Id != b.Id {
33 | return false
34 | }
35 |
36 | if a.Type != b.Type {
37 | return false
38 | }
39 |
40 | if len(a.ServiceEndpoint) != len(b.ServiceEndpoint) {
41 | return false
42 | }
43 |
44 | var baseServiceEndpointLength = len(a.ServiceEndpoint)
45 | for i := 0; i <= baseServiceEndpointLength; i++ {
46 | if a.ServiceEndpoint[i] != b.ServiceEndpoint[i] {
47 | return false
48 | }
49 | }
50 |
51 | return true
52 | }
53 |
--------------------------------------------------------------------------------
/.github/workflows/auto_assign.yml:
--------------------------------------------------------------------------------
1 | name: PR assignment
2 | on:
3 | pull_request_target:
4 | types: [opened, edited, synchronize, reopened, ready_for_review]
5 |
6 | permissions:
7 | contents: read
8 | issues: write
9 | pull-requests: write
10 |
11 | jobs:
12 | auto-assign:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Request Reviewers
16 | uses: actions/github-script@v6
17 | with:
18 | script: |
19 | const author = context.payload.pull_request.user.login;
20 | let reviewers = ['black-billed-magpie','jhkim5981'];
21 |
22 | if (reviewers.includes(author)) {
23 | if(reviewers.length === 1)
24 | reviewers = reviewers.map(reviewer => reviewer === author ? 'mikyung-lee' : reviewer);
25 | else {
26 | reviewers = reviewers.filter(reviewer => reviewer !== author);
27 | }
28 | }
29 |
30 | await github.rest.pulls.requestReviewers({
31 | owner: context.repo.owner,
32 | repo: context.repo.repo,
33 | pull_number: context.payload.pull_request.number,
34 | reviewers: reviewers
35 | });
36 | - name: Request Assignees
37 | uses: actions/github-script@v6
38 | with:
39 | script: |
40 | const assignees = ['jhkim5981', 'mikyung-lee']; // assignees
41 |
42 | await github.rest.issues.addAssignees({
43 | owner: context.repo.owner,
44 | repo: context.repo.repo,
45 | issue_number: context.payload.pull_request.number,
46 | assignees: assignees
47 | });
--------------------------------------------------------------------------------
/.github/workflows/fabric_contract_release.yml:
--------------------------------------------------------------------------------
1 | name: Build and Upload JAR to GitHub Releases
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | types: [closed]
8 |
9 | jobs:
10 | build:
11 | if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/QA-')
12 | runs-on: ubuntu-latest
13 | permissions:
14 | contents: write
15 | pull-requests: write
16 | repository-projects: write
17 |
18 | defaults:
19 | run:
20 | working-directory: source/did-fabric-contract
21 | steps:
22 | - name: Checkout code
23 | uses: actions/checkout@v4
24 | with:
25 | fetch-depth: 0
26 |
27 | - name: Set release title
28 | id: set_release_title
29 | run: |
30 | release_tag=${GITHUB_HEAD_REF#release/QA-}
31 | echo "Release tag: $release_tag"
32 | echo "::set-output name=release_tag::$release_tag"
33 |
34 | - name: Get commit messages
35 | id: get_commit_messages
36 | run: |
37 | commits=$(git log ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} --pretty=format:"* %s")
38 | echo "$commits" > commit_messages.txt
39 | echo "::set-output name=commits::$commits"
40 |
41 | - name: Create GitHub Release
42 | id: create_release
43 | uses: actions/create-release@v1
44 | env:
45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46 | with:
47 | tag_name: ${{ steps.set_release_title.outputs.release_tag }}
48 | release_name: ${{ steps.set_release_title.outputs.release_tag }}
49 | body: |
50 | ## Changes:
51 | ${{ steps.get_commit_messages.outputs.commits }}
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yaml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest an idea for this project
3 | title: "[Feature]: "
4 | labels: ["enhancement"]
5 |
6 | body:
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Thanks for taking the time to fill out this feature request!
11 |
12 | - type: textarea
13 | id: feature
14 | attributes:
15 | label: Feature Description
16 | description: Please provide a detailed description of the feature.
17 | placeholder: Describe the feature you are requesting.
18 | validations:
19 | required: true
20 |
21 | - type: textarea
22 | id: purpose
23 | attributes:
24 | label: Purpose
25 | description: What is the main purpose of this feature? Why is it needed?
26 | placeholder: Explain the purpose of the feature.
27 | validations:
28 | required: true
29 |
30 | - type: textarea
31 | id: background
32 | attributes:
33 | label: Background
34 | description: Provide any relevant context or background information for this feature.
35 | placeholder: Provide background information.
36 | validations:
37 | required: false
38 |
39 | - type: textarea
40 | id: expected_outcome
41 | attributes:
42 | label: Expected Outcome
43 | description: What are the expected results of implementing this feature?
44 | placeholder: Explain the expected results or impact.
45 | validations:
46 | required: true
47 |
48 | - type: checkboxes
49 | id: terms
50 | attributes:
51 | label: Code of Conduct
52 | description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md).
53 | options:
54 | - label: I agree to follow this project's Code of Conduct
55 | required: true
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/vcmeta.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | const (
18 | VCMETA_PREFIX = "open:vcmeta:"
19 | )
20 |
21 | type VC_STATUS string
22 |
23 | const (
24 | VC_ACTIVE VC_STATUS = "ACTIVE"
25 | VC_INACTIVE VC_STATUS = "INACTIVE"
26 | VC_REVOKED VC_STATUS = "REVOKED"
27 | )
28 |
29 | type VcMeta struct {
30 | Id string `validate:"required" json:"id"`
31 | Issuer Provider `validate:"required" json:"issuer"`
32 | Subject string `validate:"required" json:"subject"`
33 | CredentialSchema CredentialSchema `validate:"required" json:"credentialSchema"`
34 | Status VC_STATUS `validate:"required" json:"status"`
35 | IssuanceDate string `validate:"required" json:"issuanceDate"`
36 | ValidFrom string `validate:"required" json:"validFrom"`
37 | ValidUntil string `validate:"required" json:"validUntil"`
38 | FormatVersion string `validate:"required" json:"formatVersion"`
39 | Language string `validate:"required" json:"language"`
40 | }
41 |
42 | func (v VcMeta) Key() ([]string, error) {
43 | return []string{VCMETA_PREFIX, v.Id}, nil
44 | }
45 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/status.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | import (
18 | "fmt"
19 | )
20 |
21 | type DIDDOC_STATUS string
22 | type ROLE_TYPE string
23 |
24 | const (
25 | DOC_ACTIVATED DIDDOC_STATUS = "ACTIVATED"
26 | DOC_DEACTIVATED DIDDOC_STATUS = "DEACTIVATED"
27 | DOC_REVOKED DIDDOC_STATUS = "REVOKED"
28 | DOC_TERMINATED DIDDOC_STATUS = "TERMINATED"
29 |
30 | DIDDOC_STATUS_PREFIX = "open:did:status:"
31 | )
32 |
33 | type DocumentStatus struct {
34 | Id string `json:"did"`
35 | Status DIDDOC_STATUS `json:"status"`
36 | Version string `json:"version"`
37 | Type ROLE_TYPE `json:"type"`
38 | TerminatedTime UTCDateTime `json:"cancelled_time,omitempty"`
39 | }
40 |
41 | func (s *DocumentStatus) Key() ([]string, error) {
42 | return []string{DIDDOC_STATUS_PREFIX, s.Id}, nil
43 | }
44 |
45 | func (s *DocumentStatus) Revoke() error {
46 | if s.Status == DOC_ACTIVATED || s.Status == DOC_DEACTIVATED {
47 | s.Status = DOC_REVOKED
48 | return nil
49 | }
50 | return fmt.Errorf("cannot update status from %s to %s", s.Status, DOC_REVOKED)
51 | }
52 |
53 | func (s *DocumentStatus) Terminated(terminatedTime UTCDateTime) error {
54 | if s.Status == DOC_REVOKED {
55 | s.Status = DOC_TERMINATED
56 | s.TerminatedTime = terminatedTime
57 | return nil
58 | }
59 | return fmt.Errorf("cannot update status from %s to %s", s.Status, DOC_TERMINATED)
60 | }
61 |
62 | func MakeDocumentStatus(didDoc *DidDoc, roleType ROLE_TYPE) *DocumentStatus {
63 | return &DocumentStatus{
64 | Id: didDoc.Id,
65 | Status: DOC_ACTIVATED,
66 | Version: didDoc.VersionId,
67 | Type: roleType,
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/README_ko.md:
--------------------------------------------------------------------------------
1 | # Fabric Contract
2 | Fabric Contract Repository에 오신 것을 환영합니다.
3 | 이 리포지토리는 Hyperledger Fabric 블록체인에서 스마트 계약을 개발하고 관리하기 위한 도구와 리소스를 제공합니다.
4 |
5 | ## 폴더 구조
6 | ```
7 | did-fabric-contract
8 | ├── CHANGELOG.md
9 | ├── CLA.md
10 | ├── CODE_OF_CONDUCT.md
11 | ├── CONTRIBUTING.md
12 | ├── LICENSE
13 | ├── dependencies-license.md
14 | ├── MAINTAINERS.md
15 | ├── README.md
16 | ├── README_ko.md
17 | ├── RELEASE-PROCESS.md
18 | ├── SECURITY.md
19 | ├── docs
20 | │ └── api
21 | │ └── ContractError.md
22 | └── source
23 | ├── did-fabric-contract
24 | │ ├── README.md
25 | │ ├── README_ko.md
26 | │ ├── chaincode
27 | │ ├── go.mod
28 | │ ├── go.sum
29 | │ └── main.go
30 | └── release
31 | ├── Source code.tar.gz
32 | └── Source code.zip
33 | ```
34 |
35 | | 이름 | 역할 |
36 | | -------------------------- | ------------------------------------------ |
37 | | CHANGELOG.md | 프로젝트 버전별 변경사항 |
38 | | CLA.md | Contributor License Agreement |
39 | | CODE_OF_CONDUCT.md | 기여자의 행동강령 |
40 | | CONTRIBUTING.md | 기여 절차 및 방법 |
41 | | LICENSE | Apache 2.0 |
42 | | dependencies-license.md | 프로젝트 의존성 라이브러리에 대한 라이선스 |
43 | | MAINTAINERS.md | 유지관리 가이드 |
44 | | README.md | 프로젝트의 전체적인 개요 설명 |
45 | | RELEASE-PROCESS.md | 릴리즈 절차 |
46 | | SECURITY.md | 보안취약점 보고 및 보안정책 |
47 | | docs | 문서 |
48 | | ┖ api | API 가이드 문서 |
49 | | source | Chaincode 소스코드 프로젝트 |
50 |
51 | ## 릴리즈
52 | 릴리즈는 [Releases](https://github.com/OmniOneID/did-fabric-contract/releases)에서 찾을 수 있습니다.
53 |
54 | ## Change Log
55 | Change Log에는 버전별 변경 사항과 업데이트가 자세히 기록되어 있습니다. 다음에서 확인할 수 있습니다:
56 | - [Change Log](./CHANGELOG.md)
57 |
58 | ## 데모 영상
59 | OpenDID 시스템의 실제 동작을 보여주는 데모 영상은 [Demo Repository](https://github.com/OmniOneID/did-demo-server)에서 확인하실 수 있습니다.
60 | 사용자 등록, VC 발급, VP 제출 등 주요 기능들을 영상으로 확인하실 수 있습니다.
61 |
62 | ## 기여
63 | Contributing 및 pull request 제출 절차에 대한 자세한 내용은 [CONTRIBUTING.md](CONTRIBUTING.md)와 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) 를 참조하세요.
64 |
65 | ## 라이선스
66 | [Apache 2.0](LICENSE)
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/verification_method.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | import (
18 | "bytes"
19 | "crypto/sha256"
20 | "encoding/json"
21 | "fmt"
22 | )
23 |
24 | type AUTH_TYPE int
25 |
26 | const (
27 | Free AUTH_TYPE = 1
28 | PIN AUTH_TYPE = 2
29 | BIO AUTH_TYPE = 4
30 | )
31 |
32 | const (
33 | RSA KEY_TYPE = "RsaVerificationKey2018"
34 | K1 KEY_TYPE = "Secp256k1VerificationKey2018"
35 | R1 KEY_TYPE = "Secp256r1VerificationKey2018"
36 | )
37 |
38 | type VerificationMethod struct {
39 | Id DID_KEY_ID `validate:"required" json:"id"`
40 | Type KEY_TYPE `validate:"required" json:"type"`
41 | Controller string `validate:"required" json:"controller"`
42 | PublicKeyMultibase Multibase `validate:"required" json:"publicKeyMultibase"`
43 | AuthType AUTH_TYPE `validate:"required" json:"authType"`
44 | }
45 |
46 | func (a *VerificationMethod) IsEqual(b *VerificationMethod) (bool, error) {
47 | hashData, err := a.ToHash()
48 | if err != nil {
49 | return false, fmt.Errorf("failed to hash the first verificationMethod : %w", err)
50 | }
51 |
52 | comparedHashData, err := b.ToHash()
53 | if err != nil {
54 | return false, fmt.Errorf("failed to hash the second verificationMethod : %w", err)
55 | }
56 |
57 | return bytes.Equal(hashData, comparedHashData), nil
58 | }
59 |
60 | func (v *VerificationMethod) ToJson() ([]byte, error) {
61 | jsonData, err := json.Marshal(v)
62 | if err != nil {
63 | return nil, err
64 | }
65 |
66 | return jsonData, nil
67 | }
68 |
69 | func (v *VerificationMethod) ToObject(data []byte) error {
70 | return json.Unmarshal(data, v)
71 | }
72 |
73 | func (v *VerificationMethod) ToHash() ([]byte, error) {
74 | hash := sha256.New()
75 |
76 | jsonData, err := v.ToJson()
77 | if err != nil {
78 | return nil, err
79 | }
80 |
81 | hash.Write(jsonData)
82 | md := hash.Sum(nil)
83 |
84 | return md, nil
85 | }
86 |
--------------------------------------------------------------------------------
/.github/workflows/cla.yml:
--------------------------------------------------------------------------------
1 | name: "CLA Assistant"
2 | on:
3 | issue_comment:
4 | types: [created]
5 | pull_request_target:
6 | types: [opened,closed,synchronize]
7 |
8 | # explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings
9 | permissions:
10 | actions: write
11 | contents: write # this can be 'read' if the signatures are in remote repository
12 | pull-requests: write
13 | statuses: write
14 |
15 | jobs:
16 | CLAAssistant:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: "CLA Assistant"
20 | if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
21 | uses: contributor-assistant/github-action@v2.6.1
22 | env:
23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24 | # the below token should have repo scope and must be manually added by you in the repository's secret
25 | # This token is required only if you have configured to store the signatures in a remote repository/organization
26 | # PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
27 | with:
28 | path-to-signatures: 'signatures/version1/cla.json'
29 | path-to-document: 'https://github.com/OmniOneID/did-fabric-contract/blob/main/CLA.md' # e.g. a CLA document
30 | # branch should not be protected
31 | branch: 'main'
32 | allowlist: user1,bot*
33 |
34 | # the followings are the optional inputs - If the optional inputs are not given, then default values will be taken
35 | #remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository)
36 | #remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository)
37 | #create-file-commit-message: 'For example: Creating file for storing CLA Signatures'
38 | #signed-commit-message: 'For example: $contributorName has signed the CLA in $owner/$repo#$pullRequestNo'
39 | #custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign'
40 | #custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA'
41 | #custom-allsigned-prcomment: 'pull request comment when all contributors has signed, defaults to **CLA Assistant Lite bot** All Contributors have signed the CLA.'
42 | #lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true)
43 | #use-dco-flag: true - If you are using DCO instead of CLA
44 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/repository/vcmeta_repository.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package repository
16 |
17 | import (
18 | "did-fabric-contract/chaincode/data"
19 | . "did-fabric-contract/chaincode/error"
20 | "encoding/json"
21 |
22 | "github.com/hyperledger-labs/cckit/router"
23 | )
24 |
25 | // InsertVcMeta
26 | /*
27 | The function inserts the provided VC metadata into the ledger.
28 |
29 | * @param ctx The router context used for state management.
30 | * @param vcMeta The VC metadata to be inserted into the ledger.
31 |
32 | * @return An error if the insertion fails, otherwise nil.
33 | */
34 | func InsertVcMeta(ctx router.Context, vcMeta *data.VcMeta) error {
35 | if err := ctx.State().Insert(vcMeta); err != nil {
36 | return GetContractError(VCMETA_INSERT_ERROR, err)
37 | }
38 | return nil
39 | }
40 |
41 | // PutVcMeta
42 | /*
43 | The function updates or inserts the VC metadata in the ledger. If the VC metadata already exists, it is updated; otherwise, it is inserted.
44 |
45 | * @param ctx The router context used for state management.
46 | * @param vcMeta The VC metadata to be updated or inserted into the ledger.
47 |
48 | * @return An error if the update or insertion fails, otherwise nil.
49 | */
50 | func PutVcMeta(ctx router.Context, vcMeta *data.VcMeta) error {
51 | if err := ctx.State().Put(vcMeta); err != nil {
52 | return GetContractError(VCMETA_PUT_ERROR, err)
53 | }
54 | return nil
55 | }
56 |
57 | // GetVcMeta
58 | /*
59 | The function retrieves the VC metadata for the specified VC ID from the ledger.
60 |
61 | * @param ctx The router context used for state management.
62 | * @param vcId The VC ID of the VC metadata to retrieve.
63 |
64 | * @return The VC metadata associated with the specified VC ID if found.
65 | * @return An error if the retrieval fails or if there is an issue converting the data.
66 | */
67 | func GetVcMeta(ctx router.Context, vcId string) (*data.VcMeta, error) {
68 | result, err := ctx.State().Get(&data.VcMeta{Id: vcId})
69 | var vcMeta *data.VcMeta
70 | if err != nil {
71 | return nil, GetContractError(VCMETA_GET_ERROR, err)
72 | }
73 | if err = json.Unmarshal(result.([]uint8), &vcMeta); err != nil {
74 | return nil, GetContractError(VCMETA_CONVERT_ERROR, err)
75 | }
76 | return vcMeta, nil
77 | }
78 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fabric Contract
2 | Welcome to the Fabric Contract Repository.
3 | This repository provides resources for developing and managing smart contracts on the Hyperledger Fabric blockchain.
4 |
5 | ## Folder Structure
6 | ```
7 | did-fabric-contract
8 | ├── CHANGELOG.md
9 | ├── CLA.md
10 | ├── CODE_OF_CONDUCT.md
11 | ├── CONTRIBUTING.md
12 | ├── LICENSE
13 | ├── dependencies-license.md
14 | ├── MAINTAINERS.md
15 | ├── README.md
16 | ├── README_ko.md
17 | ├── RELEASE-PROCESS.md
18 | ├── SECURITY.md
19 | ├── docs
20 | │ └── api
21 | │ └── ContractError.md
22 | └── source
23 | ├── did-fabric-contract
24 | │ ├── README.md
25 | │ ├── README_ko.md
26 | │ ├── chaincode
27 | │ ├── go.mod
28 | │ ├── go.sum
29 | │ └── main.go
30 | └── release
31 | ├── Source code.tar.gz
32 | └── Source code.zip
33 | ```
34 |
35 | | Name | Description |
36 | | ----------------------- | ----------------------------------------------- |
37 | | CHANGELOG.md | Version-specific changes in the project |
38 | | CLA.md | Contributor License Agreement |
39 | | CODE_OF_CONDUCT.md | Code of conduct for contributors |
40 | | CONTRIBUTING.md | Contribution guidelines and procedures |
41 | | LICENSE | Apache 2.0 |
42 | | dependencies-license.md | Licenses for the project’s dependency libraries |
43 | | MAINTAINERS.md | General guidelines for maintaining |
44 | | README.md | Overview and description of the project |
45 | | RELEASE-PROCESS.md | Release process |
46 | | SECURITY.md | Security policies and vulnerability reporting |
47 | | docs | Documentation |
48 | | ┖ api | API guide documentation |
49 | | source | Chaincode source code project |
50 |
51 |
52 | ## Releases
53 | Releases can be found in the [Releases](https://github.com/OmniOneID/did-fabric-contract/releases).
54 |
55 | ## Change Log
56 | The Change Log provides a detailed record of version-specific changes and updates. You can find it here:
57 | - [Change Log](./CHANGELOG.md)
58 |
59 | ## OpenDID Demonstration Videos
60 | To watch our demonstration videos of the OpenDID system in action, please visit our [Demo Repository](https://github.com/OmniOneID/did-demo-server).
61 | These videos showcase key features including user registration, VC issuance, and VP submission processes.
62 |
63 | ## Contributing
64 |
65 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for details on our code of conduct, and the process for submitting pull requests to us.
66 |
67 |
68 | ## License
69 | [Apache 2.0](LICENSE)
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/service/vcmeta_service.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package service
16 |
17 | import (
18 | "did-fabric-contract/chaincode/data"
19 | . "did-fabric-contract/chaincode/error"
20 | "did-fabric-contract/chaincode/repository"
21 | "did-fabric-contract/chaincode/validate"
22 | "fmt"
23 | "strings"
24 |
25 | "github.com/hyperledger-labs/cckit/state"
26 |
27 | "github.com/hyperledger-labs/cckit/router"
28 | )
29 |
30 | // RegisterVcMetadata
31 | /*
32 | The function registers the provided VC metadata into the ledger after validating it.
33 |
34 | * @param ctx The router context used for state management.
35 | * @param vcMeta The VC metadata to be registered in the ledger.
36 |
37 | * @return An error if any issue occurred during validation or insertion, otherwise nil.
38 | */
39 | func RegisterVcMetadata(ctx router.Context, vcMeta data.VcMeta) error {
40 | v := validate.RegisterVcMetaValidator()
41 | if err := v.Struct(vcMeta); err != nil {
42 | return GetContractError(VCMETA_CONVERT_ERROR, err)
43 | }
44 |
45 | if err := repository.InsertVcMeta(ctx, &vcMeta); err != nil {
46 | return err
47 | }
48 | return nil
49 | }
50 |
51 | // GetVcMetadata
52 | /*
53 | The function retrieves the VC metadata for the specified VC ID from the ledger.
54 |
55 | * @param ctx The router context used for state management.
56 | * @param vcId The VC ID of the VC metadata to retrieve.
57 |
58 | * @return The VC metadata associated with the specified VC ID if found.
59 | * @return An error if any issue occurred during retrieval or if the key is not found.
60 | */
61 | func GetVcMetadata(ctx router.Context, vcId string) (*data.VcMeta, error) {
62 | vcMeta, err := repository.GetVcMeta(ctx, vcId)
63 | if err != nil && !strings.Contains(err.Error(), state.ErrKeyNotFound.Error()) {
64 | return nil, err
65 | }
66 | return vcMeta, nil
67 | }
68 |
69 | // UpdateVcStatus
70 | /*
71 | The function updates the status of the VC metadata associated with the specified VC ID.
72 |
73 | * @param ctx The router context used for state management.
74 | * @param vcId The VC ID of the VC metadata to update.
75 | * @param vcStatus The new status to set for the VC metadata.
76 |
77 | * @return An error if any issue occurred during retrieval or update, or if the status update is invalid.
78 | */
79 | func UpdateVcStatus(ctx router.Context, vcId string, vcStatus data.VC_STATUS) error {
80 | vcMeta, err := repository.GetVcMeta(ctx, vcId)
81 | if err != nil {
82 | return err
83 | }
84 | if vcMeta.Status == vcStatus || vcMeta.Status == data.VC_REVOKED {
85 | return GetContractError(VCMETA_STATUS_INVALID, fmt.Errorf("cannot update status from %s to %s", vcMeta.Status, vcStatus))
86 | }
87 | vcMeta.Status = vcStatus
88 | if err := repository.PutVcMeta(ctx, vcMeta); err != nil {
89 | return err
90 | }
91 | return nil
92 | }
93 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/error/error.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package error
16 |
17 | const (
18 | // Prefix code used for error codes.
19 | PREFIX_CODE = "SSRVFCC"
20 |
21 | // DID Document error codes.
22 | DIDDOC_INSERT_ERROR = "01001"
23 | DIDDOC_GET_ERROR = "01002"
24 | DIDDOC_PUT_ERROR = "01003"
25 | DIDDOC_PROVIDER_INVALID = "01004"
26 | DIDDOC_CONVERT_ERROR = "01005"
27 | DIDDOC_SIGNATURE_VERIFICATION_ERROR = "01006"
28 | DID_KEY_URL_PARSING_ERROR = "01007"
29 | DIDDOC_VERSIONID_INVAILD = "01008"
30 |
31 | // DID Document Status error codes.
32 | DIDDOC_STATUS_INSERT_ERROR = "02001"
33 | DIDDOC_STATUS_GET_ERROR = "02002"
34 | DIDDOC_STATUS_PUT_ERROR = "02003"
35 | DIDDOC_STATUS_CONVERT_ERROR = "02004"
36 | DIDDOC_STATUS_INVALID = "02005"
37 |
38 | // VC Meta error codes.
39 | VCMETA_INSERT_ERROR = "03001"
40 | VCMETA_GET_ERROR = "03002"
41 | VCMETA_PUT_ERROR = "03003"
42 | VCMETA_CONVERT_ERROR = "03004"
43 | VCMETA_STATUS_INVALID = "03005"
44 | )
45 |
46 | // Mapping of error codes to error messages.
47 | var errMsg = map[string]string{
48 | DIDDOC_INSERT_ERROR: "Failed to insert did document",
49 | DIDDOC_GET_ERROR: "Failed to get did document",
50 | DIDDOC_PUT_ERROR: "Failed to update did document",
51 | DIDDOC_PROVIDER_INVALID: "Provider is invalid",
52 | DIDDOC_CONVERT_ERROR: "Failed to convert json data to did document",
53 | DIDDOC_SIGNATURE_VERIFICATION_ERROR: "Failed to signature verification",
54 | DID_KEY_URL_PARSING_ERROR: "VerificationMethod is invalid",
55 | DIDDOC_VERSIONID_INVAILD: "VersionId is inavlid",
56 |
57 | DIDDOC_STATUS_INSERT_ERROR: "Failed to insert did document status",
58 | DIDDOC_STATUS_GET_ERROR: "Failed to get did document status",
59 | DIDDOC_STATUS_PUT_ERROR: "Failed to update did document status",
60 | DIDDOC_STATUS_CONVERT_ERROR: "Failed to convert json data to did document status",
61 | DIDDOC_STATUS_INVALID: "Did document status is invalid",
62 |
63 | VCMETA_INSERT_ERROR: "Failed to insert vc meta",
64 | VCMETA_GET_ERROR: "Failed to get vc meta",
65 | VCMETA_PUT_ERROR: "Failed to update vc meta",
66 | VCMETA_CONVERT_ERROR: "Failed to convert json data to vc meta",
67 | VCMETA_STATUS_INVALID: "Vc meta status is invalid",
68 | }
69 |
70 | type ContractError struct {
71 | Code string
72 | Message string
73 | }
74 |
75 | func (c *ContractError) Error() string {
76 | return "ErrorCode : " + c.Code + ", Message : " + c.Message
77 | }
78 |
79 | func GetContractError(code string, err error) *ContractError {
80 |
81 | return &ContractError{
82 | Code: PREFIX_CODE + code,
83 | Message: errMsg[code] + " => " + err.Error(),
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/RELEASE-PROCESS.md:
--------------------------------------------------------------------------------
1 | # Release Process
2 |
3 | This document describes the Release Process for QA validation and deployment of feature additions and modifications for each repository. It covers version management and QA validation procedures for each module, as well as the process for managing the integrated Release of all modules.
4 |
5 | ## 1. Versioning
6 |
7 | The project follows a versioning rule in the format "X.Y.Z" where:
8 | - X (Major): Significant changes that are not backward compatible
9 | - Y (Minor): New features that are backward compatible
10 | - Z (Patch): Bug fixes or minor improvements that are backward compatible
11 |
12 | > When the Major version is updated, both Minor and Patch are reset to 0.
13 | >
14 | > When the Minor version is updated, the Patch is reset to 0.
15 |
16 | The integrated module version follows a four-digit format "W.X.Y.Z" assigned after QA approval.
17 |
18 | - W.X: Official product number
19 | - Y: Release
20 | - Z: Bug fix
21 |
22 | ## 2. Release Procedure for Each Repository
23 |
24 | Each module (repository) is managed independently, following these steps:
25 |
26 | 1. **Change Log Review**
27 | Review the [CHANGE LOG](CHANGELOG.md) for each module to ensure all changes are recorded.
28 |
29 | 2. **Create a Release Branch**
30 | If there are changes or modifications, create a branch "release/QA-VX.Y.Z" for QA validation.
31 | - Example: If there are bug fixes or minor improvements for V1.0.0, create a branch "release/QA-V1.0.1".
32 |
33 | For modules without changes, use the existing version (V1.0.0) and the already distributed JAR or library.
34 |
35 | 3. **QA Validation**
36 | - Perform QA validation on the Release branch, addressing any issues identified during the process.
37 | - Approve the Release once QA validation is complete.
38 |
39 | 4. **Merge into Main and Develop Branches**
40 | - Merge the validated Release branch (release/QA-VX.Y.Z) into both `main` and `develop` branches.
41 |
42 | 5. **Create a Release for Each Repository**
43 | - When the validated branch is merged into `main`, trigger the [CI/CD pipeline](https://github.com/OmniOneID/did-release/blob/main/docs/CI_CD_PIPELINE.md) using GitHub Actions to create the Release and perform version tagging. The generated [Release](https://github.com/OmniOneID/did-fabric-contract/releases) includes the following:
44 | - Version name
45 | - Summary of the changelog
46 | - Source code archive
47 | - Distributed files
48 | - Delete the release/QA-VX.Y.Z branch after the release.
49 |
50 | ## 3. Integrated Release Management (did-release Repository)
51 |
52 | After QA approval, manage the complete version control of all modules in a separate repository called [did-release](https://github.com/OmniOneID/did-release/).
53 |
54 | 1. **Managing QA Request Branches**
55 | - Create a directory for the QA request version (format: W.X.Y.Z, e.g., V1.0.1.0). The directory name should be /release-VW.X.Y.Z (e.g., /release-V1.0.1.0).
56 | - Gather the version names of the branches created for QA validation (release/QA-VX.Y.Z) and document version information and modifications in a table within the directory. Name the file 'QA-PLAN-VW.X.Y.Z.md' and register it in the issue menu of the `did-release` repository.
57 | - Include versions of unchanged modules as well.
58 |
59 | 2. **Individual Releases After QA Approval**
60 | - Once all modules have passed QA validation, and their respective `release/QA-VX.Y.Z` branches are merged into `main` and `develop`, create releases for each repository.
61 |
62 | 3. **Publishing the Integrated Release**
63 | - After all modules are approved and released, manage the integrated Release in the `did-release` repository.
64 | - Retrieve the latest version tags for each module and post them in the Release menu of the `did-release`.
65 | - Document the release information in a file named release-VW.X.Y.Z.md within the previously created directory.
66 |
67 | - Example:
68 |
69 | ## Release Note V1.0.1.0
70 |
71 | | Repository | Version | Changelog | Release |
72 | | ------------------ | --------------- | --------------------------- | --------------------------- |
73 | | did-fabric-contract | V1.0.1 | [Changelog](https://github.com/OmniOneID/did-fabric-contract/blob/main/CHANGELOG.md) |
74 | | .. | .. | .. |
75 |
76 |
77 |
78 | ## 4. Automating Integrated Release Script
79 |
80 | Use GitHub Actions or Shell scripts to automate the following tasks:
81 | - Retrieve the release tag information for each module and publish the integrated Release.
82 | - Once all module releases are completed, gather the latest Release information for each module and publish the final version in the `did-release` repository to manage the overall project release.
83 | - The integrated release version follows the "W.X.Y.Z" format, based on the most significant changes.
84 |
85 | This process enables efficient management of individual module versions and the overall integrated project release.
86 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/data/document.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package data
16 |
17 | import (
18 | "fmt"
19 | )
20 |
21 | type DID_KEY_ID string
22 | type KEY_TYPE string
23 | type VersionID string
24 | type PROOF_PURPOSE string
25 | type DID_KEY_URL string
26 |
27 | const (
28 | DIDDOC_PREFIX = "open:did:doc:"
29 | LATEST = ":latest"
30 | )
31 |
32 | const (
33 | RSASignature KEY_TYPE = "RsaSignature2018"
34 | Secp256k1 KEY_TYPE = "Secp256k1Signature2018"
35 | Secp256r1 KEY_TYPE = "Secp256r1Signature2018"
36 | )
37 |
38 | const (
39 | AssertionMethod PROOF_PURPOSE = "assertionMethod"
40 | Authentication PROOF_PURPOSE = "authentication"
41 | KeyAgreement PROOF_PURPOSE = "keyAgreement"
42 | CapabilityInvocation PROOF_PURPOSE = "capabilityInvocation"
43 | CapabilityDelegation PROOF_PURPOSE = "capabilityDelegation"
44 | )
45 |
46 | type DidDoc struct {
47 | Context []URL `validate:"required" json:"@context"`
48 | Id string `validate:"required" json:"id"`
49 | Controller string `validate:"required" json:"controller"`
50 | Created UTCDateTime `validate:"required" json:"created"`
51 | Updated UTCDateTime `validate:"required" json:"updated"`
52 | VersionId string `validate:"required" json:"versionId"`
53 | Deactivated bool `json:"deactivated"`
54 | VerificationMethod []VerificationMethod `validate:"required" json:"verificationMethod"`
55 | AssertionMethod []DID_KEY_ID `json:"assertionMethod,omitempty"`
56 | Authentication []DID_KEY_ID `json:"authentication,omitempty"`
57 | KeyAgreement []DID_KEY_ID `json:"keyAgreement,omitempty"`
58 | CapabilityInvocation []DID_KEY_ID `json:"capabilityInvocation,omitempty"`
59 | CapabilityDelegation []DID_KEY_ID `json:"capabilityDelegation,omitempty"`
60 | Service []Service `json:"service,omitempty"`
61 | }
62 |
63 | type DidDocWithVersionId struct {
64 | DidDoc
65 | }
66 |
67 | type InvokedDidDoc struct {
68 | DidDoc Multibase `json:"didDoc"`
69 | Proof InvokeProof `json:"proof"`
70 | Controller Provider `json:"controller"`
71 | Nonce Multibase `json:"nonce"`
72 | }
73 |
74 | type DidDocAndStatus struct {
75 | DidDoc DidDoc `json:"document"`
76 | Status DIDDOC_STATUS `json:"status"`
77 | }
78 |
79 | type InvokeProof struct {
80 | Type KEY_TYPE `json:"type"`
81 | Created UTCDateTime `json:"created"`
82 | VerificationMethod DID_KEY_URL `json:"verificationMethod"`
83 | ProofPurpose PROOF_PURPOSE `json:"proofPurpose"`
84 | ProofValue Multibase `json:"proofValue,omitempty"`
85 | }
86 |
87 | func (d *DidDoc) GetVerificationMethod(id string) (*VerificationMethod, error) {
88 | if !d.isCapabilityInvocation(DID_KEY_ID(id)) {
89 | return nil, fmt.Errorf("cannot found key in capabilityInvocation")
90 | }
91 |
92 | for i := 0; i < len(d.VerificationMethod); i++ {
93 | if d.VerificationMethod[i].Id == DID_KEY_ID(id) {
94 | return &d.VerificationMethod[i], nil
95 | }
96 | }
97 |
98 | return nil, fmt.Errorf("cannot found key in verificationMethod")
99 | }
100 |
101 | func (d *DidDoc) isCapabilityInvocation(id DID_KEY_ID) bool {
102 | for i := 0; i < len(d.CapabilityInvocation); i++ {
103 | if d.CapabilityInvocation[i] == DID_KEY_ID(id) {
104 | return true
105 | }
106 | }
107 | return false
108 | }
109 |
110 | func (d *DidDoc) SwitchStatus(status DIDDOC_STATUS) error {
111 | switch status {
112 | case DOC_ACTIVATED:
113 | d.Deactivated = false
114 | return nil
115 | case DOC_DEACTIVATED:
116 | d.Deactivated = true
117 | return nil
118 | default:
119 | return fmt.Errorf("unsupported status: %s", status)
120 | }
121 | }
122 |
123 | func (d DidDoc) Key() ([]string, error) {
124 | return []string{DIDDOC_PREFIX, d.Id, LATEST}, nil
125 | }
126 |
127 | func (d DidDocWithVersionId) Key() ([]string, error) {
128 | return []string{DIDDOC_PREFIX, d.Id, ":versionId:" + d.VersionId}, nil
129 | }
130 |
131 | func MakeDidDocWithVersionId(didDoc *DidDoc) *DidDocWithVersionId {
132 | return &DidDocWithVersionId{
133 | DidDoc: *didDoc,
134 | }
135 | }
136 |
137 | func MakeDidDocAndStatus(didDoc *DidDoc, status DIDDOC_STATUS) *DidDocAndStatus {
138 | return &DidDocAndStatus{
139 | DidDoc: *didDoc,
140 | Status: status,
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/README_ko.md:
--------------------------------------------------------------------------------
1 | # Fabric Contract Guide
2 | 본 문서는 OpenDID Chaincode 사용을 위한 가이드로,
3 | Open DID에 필요한 DID Document(DID 문서), Verifiable Credential Metadata(이하 VC Meta) 정보를 블록체인에 저장하고 관리하는 기능을 제공합니다. Chaincode는 Blockchain SDK로부터 받은 요청을 처리하여 트랜잭션을 생성 및 기록합니다.
4 |
5 | ## S/W 사양
6 | | 구분 | 내용 |
7 | |------|----------------------------|
8 | | Language | Golang 1.22 |
9 |
10 |
11 |
12 | ## 체인코드 기능
13 | OpenDID Chaincode는 DID 문서 및 VC Meta 데이터와 관련된 트랜잭션 처리 기능을 제공합니다. 라우팅 함수 `NewOpenDIDCC`를 통해 호출하는 함수명과 기능은 다음과 같습니다:
14 |
15 | * document_registerDidDoc: 새로운 DID 문서를 등록/변경하고 상태를 저장합니다.
16 | * document_getDidDoc: 특정 DID 문서와 해당 DID 문서 상태를 조회합니다.
17 | * document_updateDidDocStatusInService: In-Service 간 DID 문서 상태를 변경합니다.
18 | * document_updateDidDocStatusRevocation: DID 문서를 Revocation 상태로 변경합니다.
19 | * vcMeta_registerVcMetadata: VC 메타데이터를 등록합니다.
20 | * vcMeta_getVcMetadata: 특정 VC 메타데이터를 조회합니다.
21 | * vcMeta_updateVcStatus: VC 메타데이터의 상태를 변경합니다.
22 |
23 |
24 |
25 | ## 설치 및 배포
26 | Hyperledger Fabric에서 제공하는 test-network를 사용하여 손쉽게 Fabric 네트워크를 구축할 수 있습니다.
27 | 아래 단계에서 안내하고 있는 네트워크 실행 및 체인코드 배포 과정은 [Hyperledger Fabric 공식 문서 - Using the Fabric test network](https://hyperledger-fabric.readthedocs.io/en/latest/test_network.html)를 참조하십시오.
28 |
29 | 1. **테스트 네트워크 실행**
30 | 다음 명령어를 사용하여 두 개의 peer organization과 하나의 order organization으로 구성된 `test-network`를 구축하고 channel을 생성할 수 있습니다.
31 | ```bash
32 | $ cd fabric-sample/test-network
33 | $ ./network.sh up createChannel -c [channel name] -ca -s couchdb
34 | ```
35 | 2. **체인코드 배포**
36 | `fabric-sample` 디렉터리 하위에 `did-fabric-contract` 프로젝트를 복제합니다.
37 | ```bash
38 | $ cd fabric-sample
39 | $ git clone https://github.com/OmniOneID/did-fabric-contract.git
40 | ```
41 | `test-network` 디렉터리로 돌아와서 체인코드 배포를 위해 다음 명령어를 실행합니다.
42 | ```bash
43 | $ cd ./test-network
44 | $ ./network.sh deployCC -c [channel name] -ccn [chaincode name] -ccp ../did-fabric-contract/source/did-fabric-contract -ccl go -ccs 1
45 | ```
46 |
47 |
48 |
49 | ## 실행 예시
50 | OpenDID Chaincode는 `CCKit Framework`를 활용하여 기존 낮은 수준의 체인코드 상태 작업, 복잡한 데이터 처리 작업 등의 문제점을 개선하고 있습니다.
51 | `did-fabric-contract/source/did-fabric-contract/chaincode/opendid.go` 파일의 `NewOpenDIDCC` 함수 내부에서 `CCKit router` 기능을 사용하여 정의되어 있는 다양한 라우팅 경로와 메서드를 확인할 수 있습니다.
52 | (CCKit에 대한 자세한 내용은 [CCKit Github Repository](https://github.com/hyperledger-labs/cckit)를 참조하십시오.)
53 |
54 | ```go
55 | package chaincode
56 |
57 | import (
58 | "fmt"
59 |
60 | "opendid/chaincode/data"
61 | "opendid/chaincode/service"
62 |
63 | "github.com/hyperledger-labs/cckit/router"
64 | "github.com/hyperledger-labs/cckit/router/param"
65 | )
66 |
67 | func NewOpenDIDCC() *router.Chaincode {
68 |
69 | r := router.New(`OpenDID`)
70 |
71 | r.Init(Init)
72 |
73 | r.Group(`document_`).
74 | Invoke(`registDidDoc`, registerDidDoc,
75 | param.Struct("InvokedDidDoc", &data.InvokedDidDoc{}),
76 | param.String("roleType")).
77 | Query(`getDidDoc`, getDidDoc,
78 | param.String("da"),
79 | param.String("versionId")).
80 | Invoke(`updateDidDocStatusInService`, updateDidDocStatusInService,
81 | param.String("da"),
82 | param.String("status"),
83 | param.String("versionId")).
84 | Invoke(`updateDidDocStatusRevocation`, updateDidDocStatusRevocation,
85 | param.String("da"),
86 | param.String("status"),
87 | param.String("terminatedTime"))
88 |
89 | r.Group("vcMeta_").
90 | Invoke("registVcMetadata", registerVcMetadata,
91 | param.Struct("vcMeta", &data.VcMeta{})).
92 | Query("getVcMetadata", getVcMetadata,
93 | param.String("vcId")).
94 | Invoke("updateVcStatus", updateVcStatus,
95 | param.String("vcId"),
96 | param.String("vcStatus"))
97 |
98 | return router.NewChaincode(r)
99 | }
100 | ```
101 |
102 |
103 | 다음은 `peer` CLI를 사용하여 DID 문서를 블록체인에서 조회하기 위한 `document_getDidDoc` API를 호출하는 예시입니다.
104 | 1. **환경변수 설정**
105 | `peer` CLI 명령어를 사용하기 위해 `test-network` 디렉터리에서 환경변수를 설정합니다.
106 | ```bash
107 | $ export PATH=${PWD}/../bin:$PATH
108 | $ export FABRIC_CFG_PATH=$PWD/../config/
109 |
110 | $ export CORE_PEER_TLS_ENABLED=true
111 | $ export CORE_PEER_LOCALMSPID=Org1MSP
112 | $ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
113 | $ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
114 | $ export CORE_PEER_ADDRESS=localhost:7051
115 | ```
116 | 2. **체인코드 호출**
117 | `document_getDidDoc` 함수를 호출하여 DID와 versionId가 각각 `did:open:user` ,`1`에 해당하는 특정 DID 문서를 조회하고 있습니다.
118 | ```bash
119 | $ peer chaincode query -C [channel name] -n [chaincode name] -c '{"Args":["document_getDidDoc","did:open:user","1"]}'
120 | ```
121 | 3. **결괏값 반환**
122 | 명령이 성공하면 Base64로 인코딩된 `payload`로 결과값이 반환됩니다. 예시 출력은 다음과 같습니다:
123 | ```bash
124 | {"status":200,"payload":"eyJkb2N1...iXX1dfSwic3RhdHVzIjoiQUNUSVZBVEVEIn0"}
125 | ```
126 | `payload` 값을 디코딩하면, 아래와 같이 조회된 특정 DID 문서를 확인할 수 있습니다.
127 | ```json
128 | {
129 | "document": {
130 | "@context": [
131 | "https://www.w3.org/ns/did/v1"
132 | ],
133 | "id": "did:opendid:user",
134 | ...
135 | "versionId": "1",
136 | "deactivated": false,
137 | ...
138 | },
139 | "status": "ACTIVATED"
140 | }
141 | ```
142 | 위의 예시 출력은 이전에 등록된 DID 문서가 있다고 가정합니다. 등록된 DID 문서가 없는 경우, `null`값이 Base64 인코딩 되어 `payload` 값으로 반환됩니다.
143 | ```bash
144 | {"status":200,"payload":"bnVsbA=="}
145 | ```
146 |
147 |
148 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported at [technology@omnione.net](mailto:technology@omnione.net).
63 | to the community leaders responsible for enforcement.
64 |
65 | All complaints will be reviewed and investigated promptly and fairly.
66 |
67 | All community leaders are obligated to respect the privacy and security of the
68 | reporter of any incident.
69 |
70 | ## Enforcement Guidelines
71 |
72 | Community leaders will follow these Community Impact Guidelines in determining
73 | the consequences for any action they deem in violation of this Code of Conduct:
74 |
75 | ### 1. Correction
76 |
77 | **Community Impact**: Use of inappropriate language or other behavior deemed
78 | unprofessional or unwelcome in the community.
79 |
80 | **Consequence**: A private, written warning from community leaders, providing
81 | clarity around the nature of the violation and an explanation of why the
82 | behavior was inappropriate. A public apology may be requested.
83 |
84 | ### 2. Warning
85 |
86 | **Community Impact**: A violation through a single incident or series
87 | of actions.
88 |
89 | **Consequence**: A warning with consequences for continued behavior. No
90 | interaction with the people involved, including unsolicited interaction with
91 | those enforcing the Code of Conduct, for a specified period of time. This
92 | includes avoiding interactions in community spaces as well as external channels
93 | like social media. Violating these terms may lead to a temporary or
94 | permanent ban.
95 |
96 | ### 3. Temporary Ban
97 |
98 | **Community Impact**: A serious violation of community standards, including
99 | sustained inappropriate behavior.
100 |
101 | **Consequence**: A temporary ban from any sort of interaction or public
102 | communication with the community for a specified period of time. No public or
103 | private interaction with the people involved, including unsolicited interaction
104 | with those enforcing the Code of Conduct, is allowed during this period.
105 | Violating these terms may lead to a permanent ban.
106 |
107 | ### 4. Permanent Ban
108 |
109 | **Community Impact**: Demonstrating a pattern of violation of community
110 | standards, including sustained inappropriate behavior, harassment of an
111 | individual, or aggression toward or disparagement of classes of individuals.
112 |
113 | **Consequence**: A permanent ban from any sort of public interaction within
114 | the community.
115 |
116 | ## Attribution
117 |
118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119 | version 2.0, available at
120 | [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
121 |
122 | Community Impact Guidelines were inspired by
123 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124 |
125 | For answers to common questions about this code of conduct, see the FAQ at
126 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available
127 | at [https://www.contributor-covenant.org/translations][translations].
128 |
129 | [homepage]: https://www.contributor-covenant.org
130 |
131 | [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
132 |
133 | [Mozilla CoC]: https://github.com/mozilla/diversity
134 |
135 | [FAQ]: https://www.contributor-covenant.org/faq
136 |
137 | [translations]: https://www.contributor-covenant.org/translations
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/opendid.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package chaincode
16 |
17 | import (
18 | "fmt"
19 |
20 | "did-fabric-contract/chaincode/data"
21 | "did-fabric-contract/chaincode/service"
22 |
23 | "github.com/hyperledger-labs/cckit/router"
24 | "github.com/hyperledger-labs/cckit/router/param"
25 | )
26 |
27 | const (
28 | CC_VERSION = "did-fabric-contract-1.0.0"
29 | )
30 |
31 | // NewOpenDIDCC init chaincode function.
32 | func NewOpenDIDCC() *router.Chaincode {
33 |
34 | r := router.New(`OpenDID`)
35 |
36 | r.Init(Init)
37 |
38 | // temp
39 | r.Group(`remove`).
40 | Invoke(``, func(ctx router.Context) (interface{}, error) {
41 | index := string(ctx.GetArgs()[1])
42 | if err := service.RemoveIndex(ctx, index); err != nil {
43 | return ctx.Response().Error(err), err
44 | }
45 | return ctx.Response().Success(fmt.Sprintf("remove '%s' success", index)), nil
46 | }).
47 | Invoke(`All`, func(ctx router.Context) (interface{}, error) {
48 | if err := service.RemoveAll(ctx); err != nil {
49 | return ctx.Response().Error(err), err
50 | }
51 | return ctx.Response().Success("remove all data success"), nil
52 | })
53 |
54 | r.Group(`document_`).
55 | Invoke(`registDidDoc`, registerDidDoc,
56 | param.Struct("InvokedDidDoc", &data.InvokedDidDoc{}),
57 | param.String("roleType")).
58 | Query(`getDidDoc`, getDidDoc,
59 | param.String("da"),
60 | param.String("versionId")).
61 | Invoke(`updateDidDocStatusInService`, updateDidDocStatusInService,
62 | param.String("da"),
63 | param.String("status"),
64 | param.String("versionId")).
65 | Invoke(`updateDidDocStatusRevocation`, updateDidDocStatusRevocation,
66 | param.String("da"),
67 | param.String("status"),
68 | param.String("terminatedTime"))
69 |
70 | r.Group("vcMeta_").
71 | Invoke("registVcMetadata", registerVcMetadata,
72 | param.Struct("vcMeta", &data.VcMeta{})).
73 | Query("getVcMetadata", getVcMetadata,
74 | param.String("vcId")).
75 | Invoke("updateVcStatus", updateVcStatus,
76 | param.String("vcId"),
77 | param.String("vcStatus"))
78 |
79 | return router.NewChaincode(r)
80 | }
81 |
82 | // register a new document router function definition.
83 | func registerDidDoc(ctx router.Context) (interface{}, error) {
84 | invokedDidDoc := ctx.Param("InvokedDidDoc").(data.InvokedDidDoc)
85 | roleType := ctx.ParamString("roleType")
86 |
87 | err := service.RegisterDidDoc(ctx, &invokedDidDoc, data.ROLE_TYPE(roleType))
88 | if err != nil {
89 | return ctx.Response().Error(err), err
90 | }
91 | return ctx.Response().Success(fmt.Sprintf("document registration successful\n")), nil
92 | }
93 |
94 | // get document in ledger router function definition.
95 | func getDidDoc(ctx router.Context) (interface{}, error) {
96 | da := ctx.ParamString("da")
97 | versionId := ctx.ParamString("versionId")
98 |
99 | result, err := service.GetDidDocAndStatus(ctx, da, versionId)
100 | if err != nil {
101 | return ctx.Response().Error(err), err
102 | }
103 | return ctx.Response().Success(result), nil
104 | }
105 |
106 | // update document in-service status router function definition.
107 | func updateDidDocStatusInService(ctx router.Context) (interface{}, error) {
108 | da := ctx.ParamString("da")
109 | status := ctx.ParamString("status")
110 | versionId := ctx.ParamString("versionId")
111 |
112 | result, err := service.UpdateDidDocStatusInService(ctx, da, versionId, data.DIDDOC_STATUS(status))
113 | if err != nil {
114 | return ctx.Response().Error(err), err
115 | }
116 | return ctx.Response().Success(result), nil
117 | }
118 |
119 | // update document revocation status router function definition.
120 | func updateDidDocStatusRevocation(ctx router.Context) (interface{}, error) {
121 | da := ctx.ParamString("da")
122 | status := ctx.ParamString("status")
123 | terminatedTime := ctx.ParamString("terminatedTime")
124 |
125 | result, err := service.UpdateDidDocStatusRevocation(ctx, da, data.DIDDOC_STATUS(status), data.UTCDateTime(terminatedTime))
126 | if err != nil {
127 | return ctx.Response().Error(err), err
128 | }
129 | return ctx.Response().Success(result), nil
130 | }
131 |
132 | // register vcMeta router function definition.
133 | func registerVcMetadata(ctx router.Context) (interface{}, error) {
134 | vcMeta := ctx.Param("vcMeta").(data.VcMeta)
135 | if err := service.RegisterVcMetadata(ctx, vcMeta); err != nil {
136 | return ctx.Response().Error(err), err
137 | }
138 | return ctx.Response().Success(fmt.Sprintf("vc meta registration successful: vcId = %s\n", vcMeta.Id)), nil
139 | }
140 |
141 | // get vcMeta router function definition.
142 | func getVcMetadata(ctx router.Context) (interface{}, error) {
143 | result, err := service.GetVcMetadata(ctx, ctx.ParamString("vcId"))
144 | if err != nil {
145 | return ctx.Response().Error(err), err
146 | }
147 | return ctx.Response().Success(result), nil
148 | }
149 |
150 | // update vcStatus router function definition.
151 | func updateVcStatus(ctx router.Context) (interface{}, error) {
152 | vcId := ctx.ParamString("vcId")
153 | if err := service.UpdateVcStatus(ctx, vcId, data.VC_STATUS(ctx.ParamString("vcStatus"))); err != nil {
154 | return ctx.Response().Error(err), err
155 | }
156 | return ctx.Response().Success(fmt.Sprintf("vc meta update successful: vcId = %s\n", vcId)), nil
157 | }
158 |
159 | func Init(ctx router.Context) (interface{}, error) {
160 | ctx.Logger().Info(fmt.Sprintf("Init open DID CC => version %s", CC_VERSION))
161 | return fmt.Sprintf("Init open DID CC => version %s", CC_VERSION), nil
162 | }
163 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guidelines
2 | We appreciate your contributions! We want to make contributing to this project as easy and transparent as possible, whether it's:
3 |
4 | - Reporting a bug
5 | - Discussing the current state of the code
6 | - Submitting a fix
7 | - Proposing new features
8 |
9 | ## Contribution Process
10 | Thank you for contributing to the project! This guide explains how to contribute to the project, the code style rules, and the review criteria. Please familiarize yourself with the following content before making any contributions.
11 |
12 | 1. **Creating an Issue**
13 | - Before starting any work, create an issue related to the task you wish to work on. All work, including bug fixes, feature improvements, and new proposals, should be initiated after the issue is registered.
14 | - When creating an issue, use the provided issue template and fill in accurate information.
15 | 2. **Issue Assignment**
16 | - Once the issue is created, the administrator will review and may assign the issue to an external contributor.
17 | - Before being assigned, make sure that the same task is not already in progress.
18 | 3. **Fork and Branch Creation**
19 | - Refer to [Pull Request Guidelines](#pull-request-guidelines)
20 | 4. **Writing Code**
21 | - Ensure that the code strictly follows the project's [Coding Style](#coding-style) guidelines.
22 | - Submit the PR after confirming that all tests pass successfully.
23 | 5. **Creating a Pull Request (PR)**
24 | - Commit your work and create a PR.
25 | - In the PR description, provide detailed information about the changes and link the related issue number to connect it to the issue.
26 | - Write concise and clear commit messages.
27 | - Refer to [Commit Message Guideline](#commit-message-guidelines)
28 | 6. **Code Review**
29 | - Once the PR is created, the administrator will review the code. Update the PR by incorporating the reviewer’s feedback.
30 | - Once the review is complete, the administrator will merge the PR.
31 |
32 | ## Detailed Contribution Guide via GitHub
33 | Please refer to [Detailed Contribution Guide via GitHub](https://github.com/OmniOneID/did-doc-architecture/blob/main/how_to_contribute_to_open_did.md) for detailed instructions on how to contribute to the project. This guide includes command examples and screenshots to help you better understand the process.
34 |
35 | ## Code Review Standards
36 | We conduct code reviews based on the following standards to ensure that your contribution maintains consistency with the project and upholds quality:
37 |
38 | 1. **Code Quality**
39 | - Write code that is easy to read and maintain.
40 | - Avoid overly complex logic, and if possible, suggest better solutions.
41 | - Minimize duplicated code and check if the code can be refactored into reusable modules.
42 | 2. **Feature Verification**
43 | - Test the new feature or bug fix to ensure it works as intended.
44 | - All tests must pass before submitting the PR.
45 | - Include any additional necessary tests in the PR.
46 | 3. **Code Style Compliance**
47 | - Ensure that your code follows the project's [Coding Style](#coding-style).
48 | - Feedback will be given if there are formatting issues or violations of naming conventions.
49 | 4. **Commit Messages**
50 | - Ensure that commit messages clearly describe the changes made.
51 | - Avoid including too many modifications in a single commit. If possible, divide changes into smaller commits.
52 | 5. **Documentation**
53 | - If new features, APIs, or configuration changes are introduced, make sure to update or add relevant documentation.
54 | - Write appropriate comments in the code, especially for explaining complex logic.
55 |
56 | ## Code of Conduct
57 | We are committed to fostering a contribution environment where everyone is treated with respect. Please make sure to read and follow the [Code of Conduct](CODE_OF_CONDUCT.md) before starting your contribution.
58 |
59 | ## Issue Reporting Guidelines
60 | We use GitHub Issues to track and manage bugs.
61 | If you encounter a bug, please open a new issue on GitHub. When reporting an issue, please use the provided issue template to clearly describe the problem. This helps us resolve the issue more quickly.
62 |
63 | ### Writing a Good Bug Report
64 | A good bug report includes the following:
65 | - A quick summary or background of the issue.
66 | - Steps to reproduce the bug (be specific and detailed).
67 | - Expected vs. actual results.
68 | - Any additional context or information that could help us diagnose the issue.
69 |
70 | ## Pull Request Guidelines
71 | 1. **Fork** from the `develop` branch of the remote repository.
72 | 2. **Develop the feature**, and ensure the code has been properly tested.
73 | 3. If necessary, update the **documentation** to reflect the changes.
74 | 4. Verify that all tests pass and that the code adheres to our coding style and linting rules.
75 | 5. Once the work is complete, submit a **pull request** to the `develop` branch.
76 | 6. When creating the pull request, assign an appropriate **reviewer** to review the code changes.
77 | It is recommended to choose someone familiar with the codebase, considering their availability for providing feedback.
78 | 7. Also, assign **assignees** to clarify responsibility for the task.
79 | Assign **all maintainers of the repository** as assignees to ensure accountability and a smooth review process.
80 |
81 | > **Note**: Assignees are responsible for ensuring the pull request is reviewed and merged appropriately. Assigning all maintainers as assignees is a crucial step to ensure they are aware of the changes and can respond quickly.
82 |
83 | ## Coding Style
84 | Our coding style is based on the [OpenDID Coding Style](https://github.com/OmniOneID/did-doc-architecture/blob/main/docs/rules/coding_style.md). Adhering to these guidelines ensures that the code is clean, readable, and maintainable.
85 |
86 | ## Document Creation and Editing Guide
87 | Our document creation process follows the [OpenDID Document Guide](https://github.com/OmniOneID/did-doc-architecture/blob/main/docs/guide/docs/write_document_guide.md). Most of the design documents we create use the Markdown (*.md) format, ensuring consistency and ease of collaboration.
88 |
89 | ## Commit Message Guidelines
90 | Our commit messages follow the [OpenDID Commit Rule](https://github.com/OmniOneID/did-doc-architecture/blob/main/docs/rules/git_code_commit_rule.md). Well-structured commit messages help others understand the intent behind your changes and make it easier to navigate the code history.
91 |
92 | ## Signing the CLA
93 | Before we can accept your pull request, you must submit a CLA. This only needs to be done once. Complete your CLA here: [Contributor License Agreement](CLA.md)
94 |
95 | ## License
96 | [Apache 2.0](LICENSE)
--------------------------------------------------------------------------------
/source/did-fabric-contract/chaincode/utility/crypto.go:
--------------------------------------------------------------------------------
1 | // Copyright 2024 OmniOne.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package utility
16 |
17 | import (
18 | "crypto/ecdsa"
19 | "crypto/elliptic"
20 | "crypto/rand"
21 | "crypto/sha256"
22 | "did-fabric-contract/chaincode/data"
23 | "encoding/base32"
24 | "encoding/base64"
25 | "encoding/hex"
26 | "fmt"
27 | "math/big"
28 |
29 | "github.com/btcsuite/btcutil/base58"
30 | )
31 |
32 | func CreateNewEcdsaPrivateKey() (*ecdsa.PrivateKey, error) {
33 | return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
34 | }
35 |
36 | func Sign(data []byte, privateKey *ecdsa.PrivateKey) ([]byte, error) {
37 | digest := sha256.Sum256(data)
38 |
39 | r, s, err := ecdsa.Sign(rand.Reader, privateKey, digest[:])
40 | if err != nil {
41 | return nil, err
42 | }
43 |
44 | params := privateKey.Curve.Params()
45 | curveOrderByteSize := params.P.BitLen() / 8
46 |
47 | rBytes := r.Bytes()
48 | sBytes := s.Bytes()
49 |
50 | signature := make([]byte, curveOrderByteSize*2)
51 | copy(signature[curveOrderByteSize-len(rBytes):], rBytes)
52 | copy(signature[curveOrderByteSize*2-len(sBytes):], sBytes)
53 |
54 | return signature, nil
55 | }
56 |
57 | func Verify(data, signature []byte, publicKey *ecdsa.PublicKey) bool {
58 | digest := sha256.Sum256(data)
59 |
60 | curveOrderByteSize := publicKey.Curve.Params().P.BitLen() / 8
61 |
62 | r, s := new(big.Int), new(big.Int)
63 | r.SetBytes(signature[:curveOrderByteSize])
64 | s.SetBytes(signature[curveOrderByteSize:])
65 |
66 | return ecdsa.Verify(publicKey, digest[:], r, s)
67 | }
68 |
69 | func DecompressPublicKeyFromString(publicKeyHexString string) (*ecdsa.PublicKey, error) {
70 | publicKeyBytes, err := hex.DecodeString(publicKeyHexString)
71 | if err != nil {
72 | return nil, err
73 | }
74 |
75 | return DecompressPublicKey(publicKeyBytes)
76 | }
77 |
78 | func DecompressPublicKey(publicKey []byte) (*ecdsa.PublicKey, error) {
79 | if len(publicKey) != 33 {
80 | return nil, fmt.Errorf("invalid public key size: %d, expected 33", len(publicKey))
81 | }
82 |
83 | if publicKey[0] != 0x02 && publicKey[0] != 0x03 {
84 | return nil, fmt.Errorf("invalid public key format: first byte must be 0x02 or 0x03")
85 | }
86 |
87 | x := new(big.Int).SetBytes(publicKey[1:])
88 | xx := new(big.Int).Mul(x, x)
89 | xxx := new(big.Int).Mul(xx, x)
90 |
91 | ax := new(big.Int).Mul(big.NewInt(3), x)
92 |
93 | yy := new(big.Int).Sub(xxx, ax)
94 | yy.Add(yy, elliptic.P256().Params().B)
95 |
96 | y1 := new(big.Int).ModSqrt(yy, elliptic.P256().Params().P)
97 | if y1 == nil {
98 | return nil, fmt.Errorf("can not recovery public key")
99 | }
100 |
101 | y2 := new(big.Int).Neg(y1)
102 | y2.Mod(y2, elliptic.P256().Params().P)
103 |
104 | y := new(big.Int)
105 | if publicKey[0] == 0x02 {
106 | if y1.Bit(0) == 0 {
107 | y = y1
108 | } else {
109 | y = y2
110 | }
111 | } else {
112 | if y1.Bit(0) == 1 {
113 | y = y1
114 | } else {
115 | y = y2
116 | }
117 | }
118 |
119 | return &ecdsa.PublicKey{X: x, Y: y, Curve: elliptic.P256()}, nil
120 | }
121 |
122 | func CompressPublicKey(publicKey *ecdsa.PublicKey) []byte {
123 | params := publicKey.Curve.Params()
124 | curveOrderByteSize := params.P.BitLen() / 8
125 |
126 | xBytes := publicKey.X.Bytes()
127 | signature := make([]byte, curveOrderByteSize+1)
128 |
129 | if publicKey.Y.Bit(0) == 1 {
130 | signature[0] = 0x03
131 | } else {
132 | signature[0] = 0x02
133 | }
134 |
135 | copy(signature[1+curveOrderByteSize-len(xBytes):], xBytes)
136 | return signature
137 | }
138 |
139 | func RecoveryEcdsa(data []byte, rawSign []byte) (*ecdsa.PublicKey, *ecdsa.PublicKey, error) {
140 | signLength := len(rawSign)
141 | halfSignLength := signLength / 2
142 |
143 | r := new(big.Int).SetBytes(rawSign[:halfSignLength])
144 | s := new(big.Int).SetBytes(rawSign[halfSignLength:])
145 | curve := elliptic.P256().Params()
146 |
147 | expY := new(big.Int).Sub(curve.N, big.NewInt(2))
148 | rInv := new(big.Int).Exp(r, expY, curve.N)
149 | z := new(big.Int).SetBytes(data)
150 |
151 | xx := new(big.Int).Mul(r, r)
152 | xxx := xx.Mul(xx, r)
153 |
154 | ax := new(big.Int).Mul(big.NewInt(3), r)
155 |
156 | yy := new(big.Int).Sub(xxx, ax)
157 | yy.Add(yy, elliptic.P256().Params().B)
158 |
159 | y1 := new(big.Int).ModSqrt(yy, curve.P)
160 | if y1 == nil {
161 | return nil, nil, fmt.Errorf("cannot recover public key")
162 | }
163 |
164 | y2 := new(big.Int).Neg(y1)
165 | y2.Mod(y2, curve.P)
166 |
167 | rInvBytes := rInv.Bytes()
168 |
169 | p1, p2 := elliptic.P256().ScalarMult(r, y1, s.Bytes())
170 | p3, p4 := elliptic.P256().ScalarBaseMult(z.Bytes())
171 |
172 | p5 := new(big.Int).Neg(p4)
173 | p5.Mod(p5, curve.P)
174 |
175 | q1, q2 := elliptic.P256().Add(p1, p2, p3, p5)
176 | q3, q4 := elliptic.P256().ScalarMult(q1, q2, rInvBytes)
177 |
178 | n1, n2 := elliptic.P256().ScalarMult(r, y2, s.Bytes())
179 | n3, n4 := elliptic.P256().ScalarBaseMult(z.Bytes())
180 |
181 | n5 := new(big.Int).Neg(n4)
182 | n5.Mod(n5, curve.P)
183 |
184 | q5, q6 := elliptic.P256().Add(n1, n2, n3, n5)
185 | q7, q8 := elliptic.P256().ScalarMult(q5, q6, rInvBytes)
186 |
187 | key1 := ecdsa.PublicKey{Curve: elliptic.P256(), X: q3, Y: q4}
188 | key2 := ecdsa.PublicKey{Curve: elliptic.P256(), X: q7, Y: q8}
189 |
190 | return &key1, &key2, nil
191 | }
192 |
193 | func ComparePublicKey(key1, key2 *ecdsa.PublicKey) bool {
194 | x := key1.X.Cmp(key2.X)
195 | y := key1.Y.Cmp(key2.Y)
196 |
197 | if x == 0 && y == 0 {
198 | return true
199 | }
200 |
201 | return false
202 | }
203 |
204 | func DecodeMultibase(input data.Multibase) ([]byte, error) {
205 | multibaseData := string(input)
206 | if len(multibaseData) < 1 {
207 | return nil, fmt.Errorf("input data is too short")
208 | }
209 |
210 | encodingType := multibaseData[0]
211 | encodingData := multibaseData[1:]
212 |
213 | switch encodingType {
214 | case 'f', 'F':
215 | return hex.DecodeString(encodingData)
216 | case 'z':
217 | return base58.Decode(encodingData), nil
218 | case 'b':
219 | return base32.StdEncoding.DecodeString(encodingData)
220 | case 'm':
221 | return base64.RawStdEncoding.DecodeString(encodingData)
222 | case 'u':
223 | return base64.URLEncoding.DecodeString(encodingData)
224 | default:
225 | return nil, fmt.Errorf("unsupported encoding : %c", encodingType)
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/source/did-fabric-contract/README.md:
--------------------------------------------------------------------------------
1 | # Fabric Contract Guide
2 | This document is a guide for using the OpenDID Chaincode. The Chaincode provides functionality to store and manage the necessary DID Document and Verifiable Credential Metadata(hereafter VC Meta) information for OpenDID on the blockchain. The Chaincode processes requests received from the Blockchain SDK to generate and record transactions.
3 |
4 | ## S/W Specifications
5 | | Category | Details |
6 | |----------|------------------------|
7 | | Language | Golang 1.22 |
8 |
9 |
10 |
11 | ## Chaincode Features
12 | The OpenDID Chaincode provides transaction processing functions related to DID documents and VC metadata. The functions called via the routing function NewOpenDIDCC are as follows:
13 |
14 | * document_registerDidDoc: Registers/updates a new DID document and saves its state.
15 | * document_getDidDoc: Retrieves a specific DID document and its state.
16 | * document_updateDidDocStatusInService: Changes the status of a DID document to "In-Service".
17 | * document_updateDidDocStatusRevocation: Changes the status of a DID document to "Revocation".
18 | * vcMeta_registerVcMetadata: Registers VC metadata.
19 | * vcMeta_getVcMetadata: Retrieves specific VC metadata.
20 | * vcMeta_updateVcStatus: Changes the status of VC metadata.
21 |
22 |
23 |
24 | ## Installation and Deployment
25 | You can easily set up a Fabric network using the test network provided by Hyperledger Fabric.
26 | Refer to the [Hyperledger Fabric official documentation - Using the Fabric test network](https://hyperledger-fabric.readthedocs.io/en/latest/test_network.html) for more details on the network setup and chaincode deployment process outlined below.
27 | 1. **Start the Test Network**
28 | Use the following command to set up the `test-network` composed of two peer organizations and one orderer organization, and create a channel.
29 | ```bash
30 | $ cd fabric-sample/test-network
31 | $ ./network.sh up createChannel -c [channel name] -ca -s couchdb
32 | ```
33 | 2. **Deploy Chaincode**
34 | Clone the `did-fabric-contract` project under the `fabric-sample` directory.
35 | ```bash
36 | $ cd fabric-sample
37 | $ git clone https://github.com/OmniOneID/did-fabric-contract.git
38 | ```
39 | Go back to the `test-network` directory and execute the following command to deploy the chaincode.
40 | ```bash
41 | $ cd ./test-network
42 | $ ./network.sh deployCC -c [channel name] -ccn [chaincode name] -ccp ../did-fabric-contract/source/did-fabric-contract -ccl go -ccs 1
43 | ```
44 |
45 |
46 |
47 | ## Example Execution
48 | The OpenDID Chaincode improves issues such as low-level chaincode state operations and complex data processing tasks by utilizing the `CCKit Framework`.
49 | In the `NewOpenDIDCC` function inside the `did-fabric-contract/source/did-fabric-contract/chaincode/opendid.go` file, you can see the various routing paths and methods defined using the `CCKit router` functionality.
50 | (For more details on CCKit, refer to the [CCKit Github Repository](https://github.com/hyperledger-labs/cckit).)
51 |
52 | ```go
53 | package chaincode
54 |
55 | import (
56 | "fmt"
57 |
58 | "opendid/chaincode/data"
59 | "opendid/chaincode/service"
60 |
61 | "github.com/hyperledger-labs/cckit/router"
62 | "github.com/hyperledger-labs/cckit/router/param"
63 | )
64 |
65 | func NewOpenDIDCC() *router.Chaincode {
66 |
67 | r := router.New(`OpenDID`)
68 |
69 | r.Init(Init)
70 |
71 | r.Group(`document_`).
72 | Invoke(`registDidDoc`, registerDidDoc,
73 | param.Struct("InvokedDidDoc", &data.InvokedDidDoc{}),
74 | param.String("roleType")).
75 | Query(`getDidDoc`, getDidDoc,
76 | param.String("da"),
77 | param.String("versionId")).
78 | Invoke(`updateDidDocStatusInService`, updateDidDocStatusInService,
79 | param.String("da"),
80 | param.String("status"),
81 | param.String("versionId")).
82 | Invoke(`updateDidDocStatusRevocation`, updateDidDocStatusRevocation,
83 | param.String("da"),
84 | param.String("status"),
85 | param.String("terminatedTime"))
86 |
87 | r.Group("vcMeta_").
88 | Invoke("registVcMetadata", registerVcMetadata,
89 | param.Struct("vcMeta", &data.VcMeta{})).
90 | Query("getVcMetadata", getVcMetadata,
91 | param.String("vcId")).
92 | Invoke("updateVcStatus", updateVcStatus,
93 | param.String("vcId"),
94 | param.String("vcStatus"))
95 |
96 | return router.NewChaincode(r)
97 | }
98 | ```
99 |
100 |
101 | Below is an example of calling the `document_getDidDoc` API to retrieve a DID document from the blockchain using the `peer` CLI.
102 | 1. **Set Environment Variables**
103 | Set the environment variables in the `test-network` directory to use the `peer` CLI commands.
104 | ```bash
105 | $ export PATH=${PWD}/../bin:$PATH
106 | $ export FABRIC_CFG_PATH=$PWD/../config/
107 |
108 | $ export CORE_PEER_TLS_ENABLED=true
109 | $ export CORE_PEER_LOCALMSPID=Org1MSP
110 | $ export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
111 | $ export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
112 | $ export CORE_PEER_ADDRESS=localhost:7051
113 | ```
114 | 2. **Invoke Chaincode**
115 | The `document_getDidDoc` function is called to retrieve a specific DID document where the DID is `did:open:user` and the versionId is `1`.
116 | ```bash
117 | $ peer chaincode query -C [channel name] -n [chaincode name] -c '{"Args":["document_getDidDoc","did:open:user","1"]}'
118 | ```
119 | 3. **Return Result**
120 | If the command is successful, the result is returned as a `payload` encoded in Base64. The example output is as follows:
121 | ```bash
122 | {"status":200,"payload":"eyJkb2N1...iXX1dfSwic3RhdHVzIjoiQUNUSVZBVEVEIn0"}
123 | ```
124 | Decoding the `payload` value will reveal the retrieved specific DID document as shown below:
125 | ```json
126 | {
127 | "document": {
128 | "@context": [
129 | "https://www.w3.org/ns/did/v1"
130 | ],
131 | "id": "did:opendid:user",
132 | ...
133 | "versionId": "1",
134 | "deactivated": false,
135 | ...
136 | },
137 | "status": "ACTIVATED"
138 | }
139 | ```
140 | The above example output assumes that there is a previously registered DID document. If no DID document is registered, a `null` value is encoded in Base64 and returned as the `payload`.
141 | ```bash
142 | {"status":200,"payload":"bnVsbA=="}
143 | ```
144 |
--------------------------------------------------------------------------------
/docs/api/ContractError.md:
--------------------------------------------------------------------------------
1 | ---
2 | puppeteer:
3 | pdf:
4 | format: A4
5 | displayHeaderFooter: true
6 | landscape: false
7 | scale: 0.8
8 | margin:
9 | top: 1.2cm
10 | right: 1cm
11 | bottom: 1cm
12 | left: 1cm
13 | image:
14 | quality: 100
15 | fullPage: false
16 | ---
17 |
18 | ContractError
19 | ==
20 |
21 | - Topic: ContractError
22 | - Author: Kim Jeong-heon, Kim Min-yong
23 | - Date: 2024-08-29
24 | - Version: v1.0.0
25 |
26 | | Version | Date | Changes |
27 | | ---------------- | ---------- | ------------------------ |
28 | | v1.0.0 | 2024-08-29 | Initial version |
29 |
30 |