Chaincerts Governance is a set of smart contracts designed for the creation, distribution, and revocation of digital certificates on the blockchain. The goal of this project is to provide a decentralized and secure way to issue and manage certificates using Soroban smart contracts for Chaincerts.
This repository contains two smart contracts:
-
Cert Governance Contract: The
cert_governance
contract is responsible for defining the governance rules for Chaincerts. With this contract, organizations can set the revocability and expiration of certificates, define which users can receive a certificate, and restrict the distribution of certificates. Additionally, thecert_governance
contract is responsible for executing the distribution and revocation actions for certificates to different users. -
Cert Wallet Contract: The
cert_wallet
contract stores the Chaincerts of a specific user, and each user must have their owncert_wallet
. This contract allows users to view their Chaincerts, add organizations authorized to issue certificates to them, and execute distribution and revocation actions on their certificates. Only functions that can be executed by thecert_governance
contract can modify certificates in acert_wallet
.
The following image illustrates how the smart contracts manage the certificate governance process.
- In order to deploy the contracts, we require an account that can be created on the Stellar laboratory using the Friendbot tool.
- Two key aspects are involved in this process: the wallet contract, which enables users to hold and manage their certificates, and the governance contract, which allows organizations to issue, verify, and distribute certificates to user wallets.
- Both contracts need to be initialized to add the fundamental configuration to them.
- To enable organizations to distribute certificates to the wallet, wallets must include these organizations on their Access Control List for authorization purposes.
- Once a wallet authorizes an organization, it can proceed with certificate distribution using the governance contract.
- Organizations can revoke certificates as well, provided that revocability is allowed by the governance contract.
- Certificates can be set to expire if an expiration_time is specified during the contract initialization.
- Revocation of a certificate is only permissible by the organization that distributed it.
To work with the contracts, Rust and Soroban need to be installed. The process for installation is detailed in the Soroban setup.
# Clone the repository
git clone git@github.com:kommitters/chaincerts_governance.git
# Build the project and get dependencies
cd chaincerts_governance
cargo build
To test the contract run cargo test -- --show-output
All this steps require the Pre-requirements and Setup
-
Build both contracts (Wallet & Governance) with
cargo build --target wasm32-unknown-unknown --release
-
Create the deployer account with the Friendbot
-
Deploy certs_governance contract
soroban contract deploy \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --wasm target/wasm32-unknown-unknown/release/certs_governance.wasm SUCCESS SUCCESS <governance_contract_id>
-
To initialize the certs_governance contract, we can either send the addresses of the receivers who will receive the contract or specify the number of certificates that can be distributed through this contract. If both values are null, the contract will be initialized with a distribution limit of 10.
Note The arguments of type
Bytes
must be in hexadecimal format.- name: "senior developer"
- name converted: 73656e696f7220646576656c6f706572
- file_storage: "Filebase"
- file_storage converted: 46696c6562617365
- organization id: "org_id_123"
- organization id converted: 6f72675f69645f313233
Initialize without expiration_date
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- initialize \ --file_storage 46696c6562617365 \ --name 73656e696f7220646576656c6f706572 \ --receivers null \ --distribution_limit 5 \ --governance_rules '{ "vec": [{ "bool": true }, { "vec": [{ "symbol": "None" }] }] }' \ --organization '{"id": "6f72675f69645f313233" , "admin": "<org-account-public-key>"}'
Note The
governance_rules
argument is a tuple with two fields. The first field is abool
value that indicates whether the contract isrevocable
or not. The second field is theexpiration_time
, a field of typeOptionU64
that represents the duration of validity of the issued certificate, which is managed inEpoch Time
format. For this example, we will use the value of31556926
, which equals one year. This means that the certificate will only be valid for one year after distribution. For more information on this date format, please visit the following website: https://www.unixtimestamp.com/initialize with distribution_limit and expiration_date
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- initialize \ --file_storage 4669726562617365 \ --name 73656e696f7220646576656c6f706572 \ --receivers null \ --distribution_limit 5 \ --governance_rules '{ "vec": [{ "bool": true }, { "vec": [{ "symbol": "Some" }, {"u64": 31556926}] }] }' \ --organization '{"id": "6f72675f69645f313233" , "admin": "<org-account-public-key>"}'
Initialize with receivers and expiration_date
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- initialize \ --file_storage 4669726562617365 \ --name 73656e696f7220646576656c6f706572 \ --receivers '["<user-account-public-key-1>","<user-account-public-key-2>"]' \ --distribution_limit null \ --governance_rules '{ "vec": [{ "bool": true }, { "vec": [{ "symbol": "Some" }, {"u64": 31556926}] }] }' \ --organization '{"id": "6f72675f69645f313233" , "admin": "<org-account-public-key>"}'
-
Create user account with the Friendbot
-
Deploy certs_wallet contract
soroban contract deploy \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --wasm target/wasm32-unknown-unknown/release/certs_wallet.wasm SUCCESS SUCCESS <wallet_contract_id>
-
Initialize certs_wallet contract
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <wallet_contract_id> \ -- initialize \ --owner <user-account-public-key>
-
Include the organization on the wallet Access Control List.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <wallet_contract_id> \ -- add_organization \ --org_id 6f72675f69645f313233
-
Verify organization was succesfully included.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <wallet_contract_id> \ -- get_access_control_list
-
Verify there aren't chaincerts on the wallet.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <wallet_contract_id> \ -- get_chaincerts
-
Once the organization has been added to the Access Control List of the wallet, we can proceed with distributing a certificate from the certs_governance contract.
Note The cid argument refers to the IPFS content id, it must be in hexadecimal format.
- CID: QmerTm8dYitCQQSGd33saPFyMWgd2de8KV63KhYUL9hC7S
- CID converted: 516d6572546d3864596974435151534764333373615046794d576764326465384b5636334b6859554c3968433753
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- distribute \ --admin <org-account-public-key> \ --receiver <user-account-public-key> \ --wallet_contract_id <wallet_contract_id> \ --cid 516d6572546d3864596974435151534764333373615046794d576764326465384b5636334b6859554c3968433753 \ --distribution_date 1681414979
-
Verify that the supply increase one
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- supply
-
Verify the wallet now contains a certificate.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <wallet_contract_id> \ -- get_chaincerts
-
Revoke the certificate using the Governance contract.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- revoke \ --admin <org-account-public-key> \ --holder <user-account-public-key> \ --wallet_contract_id <wallet_contract_id>
-
Verify certificate is marked as revoked on the wallet.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <wallet_contract_id> \ -- get_chaincerts
- This function returns the name of the certificate
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- name
- This function returns whether the certificate is revocable or not.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- is_revocable
- This function returns the expiration time used to calculate the expiration_date.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- expiration_time
- This function returns the number of certificates the contract allows to distribute.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- distribution_limit
- This function return then name of decentralized storage service used for storing the certificates data.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- file_storage
- This function returns the receivers stored in the contract.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- receivers
- This function returns the contract information provided during the initialization.
soroban contract invoke \ --source-account <source-account-secret-key> \ --rpc-url https://rpc-futurenet.stellar.org:443 \ --network-passphrase 'Test SDF Future Network ; October 2022' \ --id <governance_contract_id> \ -- info
This function allows us to remove an organization from the Access Control List.
soroban contract invoke \
--source-account <source-account-secret-key> \
--rpc-url https://rpc-futurenet.stellar.org:443 \
--network-passphrase 'Test SDF Future Network ; October 2022' \
--id <wallet_contract_id> \
-- remove_organization \
--org_id 6f72675f69645f313233
For ease of error handling, it was decided to use error codes. The meaning of each of these codes will be explained below.
Code | Error | Description |
---|---|---|
1 | AlreadyInit | Contract already initialized |
2 | NotAuthorized | Does not have administrator permissions |
3 | LimitReached | It is not possible to issue more chaincerts |
4 | AlreadyInACL | The organization is already in the ACL |
5 | AlreadyIssued | Chaincert has already beend issued to the entered address |
6 | NoOrganizationsInACL | There are no organizations in the ACL |
7 | NoRevocable | Chaincert cannot be revoked |
8 | OrganizationNotFound | The organization doen's exist in the ACL |
9 | ChaincertAlreadyInTheWallet | The chaincert is already deposited in the wallet |
10 | ChaincertDoesNotExist | The chaincer doesn't exist |
11 | WalletDoesNotOwnChaincerts | This wallet doesn't own any chaincert for the moment |
Features and bug fixes are listed in the CHANGELOG file.
We welcome everyone to contribute. Make sure you have read the CODE_OF_CONDUCT before.
For information on how to contribute, please refer to our CONTRIBUTING guide.
This library is licensed under a GNU AGPLv3 license. See LICENSE for details.
Made with 💙 by kommitters Open Source