Skip to content

Commit

Permalink
Merge pull request #36 from kommitters/v0.5
Browse files Browse the repository at this point in the history
Release v0.5.0
  • Loading branch information
miguelnietoa authored Mar 21, 2024
2 parents 520793a + 5928c52 commit 95dbd93
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 52 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ jobs:
- name: Code Tests
run: |
cargo test
- run: cargo install --locked --version 20.3.0 soroban-cli
- name: Install Soroban CLI (latest)
run: |
cargo install --locked soroban-cli
- name: Contract Deployment did-contract to testnet
run: |
soroban contract deploy \
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ on:
env:
CARGO_TERM_COLOR: always

permissions:
contents: read

jobs:
build_and_test:
name: Rust project - latest
Expand Down Expand Up @@ -51,7 +54,7 @@ jobs:
uses: actions-rs/tarpaulin@044a1e5bdace8dd2f727b1af63c1d9a1d3572068 # v0.1.3
with:
version: 0.22.0
args: --all-features --fail-under 98.0 --out Lcov
args: --all-features --fail-under 97.0 --out Lcov
- name: Upload to Coveralls
uses: coverallsapp/github-action@09b709cf6a16e30b0808ba050c7a6e8a5ef13f8d # master
with:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.5.0 (21.03.2024)
- Feature: [Upgradeable contract](https://github.com/kommitters/soroban-did-contract/issues/32).
- [Remove `admin` from `update_did` function](https://github.com/kommitters/soroban-did-contract/pull/34)

## 0.4.0 (07.02.2024)
- [Bump `soroban-sdk` to `20.3.1`](https://github.com/kommitters/soroban-did-contract/issues/28)
- [Use persistent storage type for DIDDocument](https://github.com/kommitters/soroban-did-contract/issues/28)
Expand Down
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "soroban-did-contract"
version = "0.4.0"
version = "0.5.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -9,10 +9,10 @@ edition = "2021"
crate-type = ["cdylib"]

[dependencies]
soroban-sdk = "20.3.1"
soroban-sdk = "20.5.0"

[dev_dependencies]
soroban-sdk = { version = "20.3.1", features = ["testutils"] }
soroban-sdk = { version = "20.5.0", features = ["testutils"] }

[profile.release]
opt-level = "z"
Expand Down
55 changes: 50 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The DID contract enables you to manage a Decentralized Identifier within the Sor
- Create a DID.
- Update the DID attributes.
- Retrieve the DID document.
- Upgrade the contract.
- Get the contract version.

## Types

Expand Down Expand Up @@ -326,7 +328,6 @@ Verification Methods and Context must not be empty; otherwise, a contract error
```rust
fn update_did(
e: Env,
admin: Address,
context: Option<Vec<String>>,
verification_methods: Option<Vec<VerificationMethodEntry>>,
services: Option<Vec<Service>>
Expand All @@ -346,7 +347,6 @@ soroban contract invoke \
--network-passphrase 'Test SDF Network ; September 2015' \
-- \
update_did \
--admin ADMIN_PUBLIC_KEY \
--services '[{"id": "ChaincertsVault", "type_": "LinkedDomains", "service_endpoint": "https://vault.chaincerts.co"}]' \
--verification_methods '[{"id": "keys-1", "type_": "Ed25519VerificationKey2020", "controller": "", "public_key_multibase": "z6MkgpAN9rsVPXJ6DrrvxcsGzKwjdkVdvjNtbQsRiLfsqmuQ", "verification_relationships": ["Authentication", "AssertionMethod"]}]' \
--context '["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"]'
Expand Down Expand Up @@ -385,14 +385,59 @@ soroban contract invoke \
}
```

### Upgrade contract
Replaces the current contract code with a new one.

```rust
fn upgrade(e: Env, new_wasm_hash: BytesN<32>);
```

#### Example

```bash
soroban contract invoke \
--id CONTRACT_ID \
--source SOURCE_ACCOUNT_SECRET_KEY \
--rpc-url https://soroban-testnet.stellar.org:443 \
--network-passphrase 'Test SDF Network ; September 2015' \
-- \
upgrade \
--new_wasm_hash 4e3e2a3e6286149775c308c8420fd87c9e5f655549073506f72b917577ef1e33

```

### Get contract version
Returns the contract version.

```rust
fn version(e: Env) -> String;
```

#### Output
Returns the contract version as a string.

#### Example

```bash
soroban contract invoke \
--id CONTRACT_ID \
--source SOURCE_ACCOUNT_SECRET_KEY \
--rpc-url https://soroban-testnet.stellar.org:443 \
--network-passphrase 'Test SDF Network ; September 2015' \
-- \
version

# Output: CONTRACT VERSION
"0.5.0"
```

## Contract Errors

| Code | Error | Description |
| --- | --- | --- |
| 1 | `AlreadyInitialized` | Contract already initialized
| 2 | `NotAuthorized` | Invoker is not the contract admin
| 3 | `EmptyContext` | Context provided is an empty vector
| 4 | `EmptyVerificationMethods` | Verification Methods provided is an empty vector
| 2 | `EmptyContext` | Context provided is an empty vector
| 3 | `EmptyVerificationMethods` | Verification Methods provided is an empty vector


## Development
Expand Down
21 changes: 15 additions & 6 deletions src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ use crate::service::Service;
use crate::storage;
use crate::verification_method::VerificationMethodEntry;
use soroban_sdk::{
contract, contractimpl, contractmeta, panic_with_error, Address, Env, String, Vec,
contract, contractimpl, contractmeta, panic_with_error, Address, BytesN, Env, String, Vec,
};

const VERSION: &str = env!("CARGO_PKG_VERSION");

contractmeta!(
key = "Description",
val = "Smart contract for decentralized identifiers (DIDs)",
Expand Down Expand Up @@ -44,16 +46,12 @@ impl DIDTrait for DIDContract {

fn update_did(
e: Env,
admin: Address,
context: Option<Vec<String>>,
verification_methods: Option<Vec<VerificationMethodEntry>>,
services: Option<Vec<Service>>,
) -> DIDDocument {
let contract_admin = storage::read_admin(&e);
if contract_admin != admin {
panic_with_error!(e, ContractError::NotAuthorized)
}
admin.require_auth();
contract_admin.require_auth();

let mut did_document = storage::read_did_document(&e);

Expand All @@ -71,4 +69,15 @@ impl DIDTrait for DIDContract {
fn get_did(e: Env) -> DIDDocument {
storage::read_did_document(&e)
}

fn upgrade(e: Env, new_wasm_hash: BytesN<32>) {
let admin = storage::read_admin(&e);
admin.require_auth();

e.deployer().update_current_contract_wasm(new_wasm_hash);
}

fn version(e: Env) -> String {
String::from_str(&e, VERSION)
}
}
9 changes: 7 additions & 2 deletions src/did_trait.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::did_document::DIDDocument;
use crate::service::Service;
use crate::verification_method::VerificationMethodEntry;
use soroban_sdk::{Address, Env, String, Vec};
use soroban_sdk::{Address, BytesN, Env, String, Vec};

pub trait DIDTrait {
/// Initializes the DID Contract by generating the DID URI, setting the admin, and storing the DID Document.
Expand All @@ -18,12 +18,17 @@ pub trait DIDTrait {
/// Updates the DID Document. This function can only be called by the admin.
fn update_did(
e: Env,
admin: Address,
context: Option<Vec<String>>,
verification_methods: Option<Vec<VerificationMethodEntry>>,
services: Option<Vec<Service>>,
) -> DIDDocument;

/// Returns the DID Document.
fn get_did(e: Env) -> DIDDocument;

/// Upgrades WASM code.
fn upgrade(e: Env, new_wasm_hash: BytesN<32>);

/// Returns the version of the contract.
fn version(e: Env) -> String;
}
5 changes: 2 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use soroban_sdk::contracterror;
#[repr(u32)]
pub enum ContractError {
AlreadyInitialized = 1,
NotAuthorized = 2,
EmptyContext = 3,
EmptyVerificationMethods = 4,
EmptyContext = 2,
EmptyVerificationMethods = 3,
}
42 changes: 11 additions & 31 deletions src/test/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::verification_method::{
format_verification_method, VerificationMethodEntry, VerificationMethodType,
VerificationRelationship,
};
use soroban_sdk::{testutils::Address as _, vec, Address, String, Vec};
use soroban_sdk::{vec, String, Vec};

// Length of the Method Specific ID (MSI) encoded in Base32
const ENCODED_MSI_LEN: usize = 24;
Expand Down Expand Up @@ -75,7 +75,7 @@ fn test_initialize_an_already_initialized_contract() {
}

#[test]
#[should_panic(expected = "HostError: Error(Contract, #3)")]
#[should_panic(expected = "HostError: Error(Contract, #2)")]
fn test_initialize_with_empty_context() {
let DIDContractTest {
env,
Expand All @@ -99,7 +99,7 @@ fn test_initialize_with_empty_context() {
}

#[test]
#[should_panic(expected = "HostError: Error(Contract, #4)")]
#[should_panic(expected = "HostError: Error(Contract, #3)")]
fn test_initialize_with_empty_verification_methods() {
let DIDContractTest {
env,
Expand Down Expand Up @@ -174,7 +174,6 @@ fn test_update_context() {
];

contract.update_did(
&admin,
&Option::Some(new_context.clone()),
&Option::None,
&Option::None,
Expand All @@ -184,7 +183,7 @@ fn test_update_context() {
}

#[test]
#[should_panic(expected = "HostError: Error(Contract, #3)")]
#[should_panic(expected = "HostError: Error(Contract, #2)")]
fn test_update_context_with_empty_vec_should_panic() {
let DIDContractTest {
env,
Expand All @@ -204,12 +203,7 @@ fn test_update_context_with_empty_vec_should_panic() {
&services,
);

contract.update_did(
&admin,
&Option::Some(Vec::new(&env)),
&Option::None,
&Option::None,
);
contract.update_did(&Option::Some(Vec::new(&env)), &Option::None, &Option::None);
}

#[test]
Expand Down Expand Up @@ -251,7 +245,6 @@ fn test_update_verification_methods() {
];

contract.update_did(
&admin,
&Option::None,
&Option::Some(new_verification_methods.clone()),
&Option::None,
Expand All @@ -267,7 +260,7 @@ fn test_update_verification_methods() {
}

#[test]
#[should_panic(expected = "HostError: Error(Contract, #4)")]
#[should_panic(expected = "HostError: Error(Contract, #3)")]
fn test_update_verification_methods_with_empty_vec_should_panic() {
let DIDContractTest {
env,
Expand All @@ -287,12 +280,7 @@ fn test_update_verification_methods_with_empty_vec_should_panic() {
&services,
);

contract.update_did(
&admin,
&Option::None,
&Option::Some(Vec::new(&env)),
&Option::None,
);
contract.update_did(&Option::None, &Option::Some(Vec::new(&env)), &Option::None);
}

#[test]
Expand All @@ -318,7 +306,6 @@ fn test_update_services() {
let new_services = vec![&env];

contract.update_did(
&admin,
&Option::None,
&Option::None,
&Option::Some(new_services.clone()),
Expand All @@ -330,8 +317,7 @@ fn test_update_services() {
}

#[test]
#[should_panic(expected = "HostError: Error(Contract, #2)")]
fn test_update_did_with_invalid_admin() {
fn test_version() {
let DIDContractTest {
env,
admin,
Expand All @@ -350,13 +336,7 @@ fn test_update_did_with_invalid_admin() {
&services,
);

let invalid_admin = Address::generate(&env);
let new_services = vec![&env];

contract.update_did(
&invalid_admin,
&Option::None,
&Option::None,
&Option::Some(new_services),
);
let pkg_version: &str = env!("CARGO_PKG_VERSION");
let expected_version = String::from_str(&env, pkg_version);
assert_eq!(contract.version(), expected_version)
}

0 comments on commit 95dbd93

Please sign in to comment.