Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geofence, AgeVerified #11

Merged
merged 15 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ Cargo.lock
/cache/
/etc/contracts/substrate-contracts-node
/etc/contracts/ev/
/etc/contracts/simple_abac/.idea/
/etc/contracts/*/.idea/
/apple-app-site-association.json
/dump.rdb
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "arkavo-rs"
version = "0.9.0"
version = "0.9.1"
edition = "2021"
rust-version = "1.80.0"

Expand Down Expand Up @@ -45,6 +45,9 @@ async-nats = "0.36.0"
serde_json = "1.0.128"
redis = { version = "0.27.2", features = ["tokio-comp"] }
flatbuffers = "24.3.25"
scale = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] }
scale-info = { version = "2.11.3", default-features = false, features = ["derive"], optional = true }
bs58 = "0.5.1"

[dev-dependencies]
criterion = "0.5.1"
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ brew install nats-server redis flatbuffers

```shell
flatc --binary --rust idl/event.fbs
flatc --binary --rust idl/entity.fbs
flatc --binary --rust idl/metadata.fbs
```

### Installation
Expand Down Expand Up @@ -123,9 +125,9 @@ redis-server

#### Start backend

```shell
cargo run
```
```shell
cargo run
```

The server will start and listen on the configured port.

Expand Down
36 changes: 36 additions & 0 deletions etc/contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,42 @@ cargo contract build --features e2e-tests

### Deploy

#### Content Rating

```text
Code hash 0xcee0206b80f939ec9da4c69a62284e22e0fa05c98e0c7341deeb3a7e835ef261
Contract 5HKLo6CKbt1Z5dU4wZ3MiufeZzjM6JGwKUWUQ6a91fmuA6RB
```

#### Geofence

```text
Code hash 0x63a3ec45fd3ab905924a38227917e278de277c9b80d6865190d18d0d64f560bb
Contract 5H6sLwXKBv3cdm5VVRxrvA8p5cux2Rrni5CQ4GRyYKo4b9B4
```

#### Timestamp

```text
Code hash 0xee2250ba4215f273e571ecdfc2a373ccc96de5f82c19fcdaca889218fac5ac39
Contract 5D35jFeQboveKiaQSxyLKENGqrnjgUc7B4D23QbhJK4Yr7jT
```

```shell
cargo contract upload --url ws://127.0.0.1:9944 --suri //Alice content_rating/target/ink/content_rating.wasm
cargo contract instantiate --url ws://127.0.0.1:9944 --suri //Alice content_rating/target/ink/content_rating.wasm --execute
```

```shell
cargo contract upload --url ws://127.0.0.1:9944 --suri //Alice timestamp_validator/target/ink/timestamp_validator.wasm
cargo contract instantiate --url ws://127.0.0.1:9944 --suri //Alice timestamp_validator/target/ink/timestamp_validator.wasm --execute
```

```shell
cargo contract upload --url ws://127.0.0.1:9944 --suri //Alice geo_fence_contract/target/ink/geo_fence_contract.wasm
cargo contract instantiate --url ws://127.0.0.1:9944 --suri //Alice geo_fence_contract/target/ink/geo_fence_contract.wasm --execute
```

```shell
cargo contract upload --url ws://127.0.0.1:9944 --suri //Alice simple_abac/target/ink/simple_abac.wasm
cargo contract instantiate --url ws://127.0.0.1:9944 --suri //Alice simple_abac/target/ink/simple_abac.wasm --execute
Expand Down
26 changes: 26 additions & 0 deletions etc/contracts/content_rating/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "content_rating"
version = "0.1.0"
authors = ["[your_name] <[your_email]>"]
edition = "2021"

[dependencies]
ink = { version = "5.0.0", default-features = false }
scale = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] }
scale-info = { version = "2.11.3", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
ink_e2e = { version = "5.0.0" }

[lib]
path = "lib.rs"

[features]
default = ["std"]
std = [
"ink/std",
"scale/std",
"scale-info/std",
]
ink-as-dependency = []
e2e-tests = []
218 changes: 218 additions & 0 deletions etc/contracts/content_rating/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
#![cfg_attr(not(feature = "std"), no_std, no_main)]
#![allow(unexpected_cfgs)]
#[ink::contract]
mod content_rating {
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum RatingLevel {
Unused = 0,
None = 1,
Mild = 2,
Moderate = 3,
Severe = 4,
}

#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub struct Rating {
violent: RatingLevel,
sexual: RatingLevel,
profane: RatingLevel,
substance: RatingLevel,
hate: RatingLevel,
harm: RatingLevel,
mature: RatingLevel,
bully: RatingLevel,
}

#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum AgeLevel {
Kids, // Under 13
Teens, // 13 to 17
Adults, // 18 and above
}

#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
ViolentContentTooHigh,
SexualContentNotAllowed,
ProfaneContentNotAllowed,
SubstanceContentNotAllowed,
HateContentNotAllowed,
HarmContentNotAllowed,
MatureContentNotAllowed,
BullyingContentNotAllowed,
}

#[ink(storage)]
pub struct ContentRating {
// Contract storage (empty for this case)
}

impl ContentRating {
#[ink(constructor)]
pub fn new() -> Self {
Self {}
}

#[ink(message)]
pub fn validate_content(&self, age_level: AgeLevel, rating: Rating) -> Result<(), Error> {
match age_level {
AgeLevel::Kids => self.validate_kids_content(&rating),
AgeLevel::Teens => self.validate_teens_content(&rating),
AgeLevel::Adults => Ok(()), // Everything is allowed for adults
}
}

fn validate_kids_content(&self, rating: &Rating) -> Result<(), Error> {
// For kids, only mild violence is allowed, everything else must be none
if !matches!(rating.violent, RatingLevel::None | RatingLevel::Mild) {
return Err(Error::ViolentContentTooHigh);
}
if !matches!(rating.sexual, RatingLevel::None) {
return Err(Error::SexualContentNotAllowed);
}
if !matches!(rating.profane, RatingLevel::None) {
return Err(Error::ProfaneContentNotAllowed);
}
if !matches!(rating.substance, RatingLevel::None) {
return Err(Error::SubstanceContentNotAllowed);
}
if !matches!(rating.hate, RatingLevel::None) {
return Err(Error::HateContentNotAllowed);
}
if !matches!(rating.harm, RatingLevel::None) {
return Err(Error::HarmContentNotAllowed);
}
if !matches!(rating.mature, RatingLevel::None) {
return Err(Error::MatureContentNotAllowed);
}
if !matches!(rating.bully, RatingLevel::None) {
return Err(Error::BullyingContentNotAllowed);
}
Ok(())
}

fn validate_teens_content(&self, rating: &Rating) -> Result<(), Error> {
// For teens, certain content must be none, others can be up to mild
if matches!(rating.violent, RatingLevel::Moderate | RatingLevel::Severe) {
return Err(Error::ViolentContentTooHigh);
}
if matches!(rating.sexual, RatingLevel::Moderate | RatingLevel::Severe) {
return Err(Error::SexualContentNotAllowed);
}
if matches!(rating.profane, RatingLevel::Moderate | RatingLevel::Severe) {
return Err(Error::ProfaneContentNotAllowed);
}
// These must be none for teens
if !matches!(rating.substance, RatingLevel::None) {
return Err(Error::SubstanceContentNotAllowed);
}
if !matches!(rating.hate, RatingLevel::None) {
return Err(Error::HateContentNotAllowed);
}
if !matches!(rating.harm, RatingLevel::None) {
return Err(Error::HarmContentNotAllowed);
}
if matches!(rating.mature, RatingLevel::Moderate | RatingLevel::Severe) {
return Err(Error::MatureContentNotAllowed);
}
if !matches!(rating.bully, RatingLevel::None) {
return Err(Error::BullyingContentNotAllowed);
}
Ok(())
}

#[ink(message)]
pub fn check_content(&self, age_level: AgeLevel, rating: Rating) -> bool {
self.validate_content(age_level, rating).is_ok()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[ink::test]
fn kids_content_validation_works() {
let contract = ContentRating::new();

// Valid kids content
let valid_kids_rating = Rating {
violent: RatingLevel::Mild,
sexual: RatingLevel::None,
profane: RatingLevel::None,
substance: RatingLevel::None,
hate: RatingLevel::None,
harm: RatingLevel::None,
mature: RatingLevel::None,
bully: RatingLevel::None,
};
assert!(contract.check_content(AgeLevel::Kids, valid_kids_rating));

// Invalid kids content (too violent)
let invalid_kids_rating = Rating {
violent: RatingLevel::Moderate,
sexual: RatingLevel::None,
profane: RatingLevel::None,
substance: RatingLevel::None,
hate: RatingLevel::None,
harm: RatingLevel::None,
mature: RatingLevel::None,
bully: RatingLevel::None,
};
assert!(!contract.check_content(AgeLevel::Kids, invalid_kids_rating));
}

#[ink::test]
fn teens_content_validation_works() {
let contract = ContentRating::new();

// Valid teens content
let valid_teens_rating = Rating {
violent: RatingLevel::Mild,
sexual: RatingLevel::Mild,
profane: RatingLevel::Mild,
substance: RatingLevel::None,
hate: RatingLevel::None,
harm: RatingLevel::None,
mature: RatingLevel::Mild,
bully: RatingLevel::None,
};
assert!(contract.check_content(AgeLevel::Teens, valid_teens_rating));

// Invalid teens content (substance use)
let invalid_teens_rating = Rating {
violent: RatingLevel::Mild,
sexual: RatingLevel::Mild,
profane: RatingLevel::Mild,
substance: RatingLevel::Mild,
hate: RatingLevel::None,
harm: RatingLevel::None,
mature: RatingLevel::Mild,
bully: RatingLevel::None,
};
assert!(!contract.check_content(AgeLevel::Teens, invalid_teens_rating));
}

#[ink::test]
fn adult_content_validation_works() {
let contract = ContentRating::new();

// All content levels are valid for adults
let adult_rating = Rating {
violent: RatingLevel::Severe,
sexual: RatingLevel::Severe,
profane: RatingLevel::Severe,
substance: RatingLevel::Severe,
hate: RatingLevel::Severe,
harm: RatingLevel::Severe,
mature: RatingLevel::Severe,
bully: RatingLevel::Severe,
};
assert!(contract.check_content(AgeLevel::Adults, adult_rating));
}
}
}
29 changes: 29 additions & 0 deletions etc/contracts/geo_fence_contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "geo_fence_contract"
version = "0.1.0"
authors = ["[your_name] <[your_email]>"]
edition = "2021"

[dependencies]
ink = { version = "5.0.0", default-features = false }
scale = { package = "parity-scale-codec", version = "3.6.12", default-features = false, features = ["derive"] }
scale-info = { version = "2.11.3", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
ink_e2e = { version = "5.0.0" }

[lib]
path = "lib.rs"

[features]
default = ["std"]
std = [
"ink/std",
"scale/std",
"scale-info/std",
]
ink-as-dependency = []
e2e-tests = []
# do not add
#__ink_dylint_Constructor = []
#__ink_dylint_Storage = []
Loading