Update prd/pcd
This commit is contained in:
parent
0ea4c5f118
commit
97df8ea13d
@ -1,10 +1,9 @@
|
||||
use serde_json::Value;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tsify::Tsify;
|
||||
use uuid::Uuid;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use sp_client::{silentpayments::utils::SilentPaymentAddress, spclient::SpWallet};
|
||||
use sp_client::spclient::SpWallet;
|
||||
|
||||
use crate::pcd::Member;
|
||||
|
||||
@ -13,8 +12,7 @@ use crate::pcd::Member;
|
||||
pub struct Device {
|
||||
sp_wallet: SpWallet,
|
||||
pairing_process_uuid: Option<String>,
|
||||
paired_devices: Vec<String>, // map an address to the pairing process
|
||||
latest_known_state: Value
|
||||
paired_member: Option<Member>,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
@ -22,8 +20,7 @@ impl Device {
|
||||
Self {
|
||||
sp_wallet,
|
||||
pairing_process_uuid: None,
|
||||
paired_devices: vec![],
|
||||
latest_known_state: Value::Null
|
||||
paired_member: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,33 +40,12 @@ impl Device {
|
||||
self.pairing_process_uuid.clone()
|
||||
}
|
||||
|
||||
pub fn set_process_uuid(&mut self, uuid: Uuid) {
|
||||
pub fn pair(&mut self, uuid: Uuid, member: Member) {
|
||||
self.pairing_process_uuid = Some(uuid.to_string());
|
||||
self.paired_member = Some(member);
|
||||
}
|
||||
|
||||
pub fn get_paired_devices(&self) -> Vec<String> {
|
||||
self.paired_devices.clone()
|
||||
}
|
||||
|
||||
pub fn push_paired_device(&mut self, new_device_address: SilentPaymentAddress) {
|
||||
self.paired_devices.push(new_device_address.into())
|
||||
}
|
||||
|
||||
pub fn to_member(&self) -> anyhow::Result<Member> {
|
||||
if !self.is_linked() {
|
||||
return Err(anyhow::Error::msg("device is not linked"));
|
||||
}
|
||||
|
||||
let member = self.latest_known_state.as_object().unwrap().get("member").unwrap().clone();
|
||||
let res: Member = serde_json::from_value(member)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn get_latest_state(&self) -> Value {
|
||||
self.latest_known_state.clone()
|
||||
}
|
||||
|
||||
pub fn update_latest_state(&mut self, update: Value) {
|
||||
self.latest_known_state = update;
|
||||
pub fn to_member(&self) -> Option<Member> {
|
||||
self.paired_member.clone()
|
||||
}
|
||||
}
|
96
src/pcd.rs
96
src/pcd.rs
@ -1,4 +1,4 @@
|
||||
use std::str::FromStr;
|
||||
use std::{collections::{HashMap, HashSet}, str::FromStr};
|
||||
use anyhow::{Result, Error};
|
||||
|
||||
use aes_gcm::{aead::{Aead, Payload}, AeadCore, Aes256Gcm, KeyInit};
|
||||
@ -11,47 +11,38 @@ use tsify::Tsify;
|
||||
|
||||
use crate::crypto::AAD;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Tsify, PartialEq, Eq, Hash, PartialOrd)]
|
||||
pub enum Role {
|
||||
User,
|
||||
Manager,
|
||||
Admin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct Member {
|
||||
nym: String,
|
||||
sp_address_a: String,
|
||||
sp_address_b: String,
|
||||
role: Role,
|
||||
sp_addresses: Vec<String>
|
||||
}
|
||||
|
||||
impl Member {
|
||||
pub fn new(
|
||||
nym: String,
|
||||
sp_address_a: SilentPaymentAddress,
|
||||
sp_address_b: SilentPaymentAddress,
|
||||
role: Role,
|
||||
) -> Self {
|
||||
Self {
|
||||
nym,
|
||||
sp_address_a: sp_address_a.into(),
|
||||
sp_address_b: sp_address_b.into(),
|
||||
role,
|
||||
sp_addresses: Vec<SilentPaymentAddress>,
|
||||
) -> Result<Self> {
|
||||
if sp_addresses.is_empty() {
|
||||
return Err(Error::msg("empty address set"));
|
||||
}
|
||||
|
||||
let mut seen = HashSet::new();
|
||||
for s in sp_addresses.iter() {
|
||||
if !seen.insert(s.clone()) {
|
||||
return Err(Error::msg("Duplicate addresses found"));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_nym(&self) -> String {
|
||||
self.nym.clone()
|
||||
let res: Vec<String> = sp_addresses.iter()
|
||||
.map(|a| Into::<String>::into(*a))
|
||||
.collect();
|
||||
|
||||
Ok(Self {
|
||||
sp_addresses: res
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_addresses(&self) -> (String, String) {
|
||||
(self.sp_address_a.clone(), self.sp_address_b.clone())
|
||||
}
|
||||
|
||||
pub fn get_role(&self) -> Role {
|
||||
self.role
|
||||
pub fn get_addresses(&self) -> Vec<String> {
|
||||
self.sp_addresses.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,3 +136,48 @@ pub trait Pcd<'a>: Serialize + Deserialize<'a> {
|
||||
}
|
||||
|
||||
impl Pcd<'_> for Value {}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct ValidationRule {
|
||||
quorum: f32, // Must be >= 0.0, <= 1.0, 0.0 means reading right
|
||||
pub fields: Vec<String>, // Which fields are concerned by this rule
|
||||
min_sig_member: f32, // Must be >= 0.0, <= 1.0, does each member need to sign with all it's devices?
|
||||
}
|
||||
|
||||
impl ValidationRule {
|
||||
pub fn new(quorum: f32, fields: Vec<String>, min_sig_member: f32) -> Result<Self> {
|
||||
if quorum < 0.0 || quorum > 1.0 {
|
||||
return Err(Error::msg("quorum must be 0.0 < quorum <= 1.0"));
|
||||
}
|
||||
|
||||
if min_sig_member < 0.0 || min_sig_member > 1.0 {
|
||||
return Err(Error::msg("min_signatures_member must be 0.0 < min_signatures_member <= 1.0"));
|
||||
}
|
||||
|
||||
if fields.is_empty() {
|
||||
return Err(Error::msg("Fields can't be empty"));
|
||||
}
|
||||
|
||||
let res = Self {
|
||||
quorum,
|
||||
fields,
|
||||
min_sig_member,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct RoleDefinition {
|
||||
pub members: Vec<Member>,
|
||||
pub validation_rules: Vec<ValidationRule>,
|
||||
}
|
||||
|
||||
// #[derive(Debug, Clone, Serialize, Deserialize, Tsify)]
|
||||
// #[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
// pub struct Roles {
|
||||
// pub roles: HashMap<String, RoleDefinition>
|
||||
// }
|
||||
|
28
src/prd.rs
28
src/prd.rs
@ -1,3 +1,4 @@
|
||||
use std::collections::HashSet;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Result, Error};
|
||||
@ -5,6 +6,7 @@ use serde::{Serialize, Deserialize};
|
||||
|
||||
use serde_json::{Map, Value};
|
||||
use sp_client::bitcoin::secp256k1::SecretKey;
|
||||
use sp_client::bitcoin::XOnlyPublicKey;
|
||||
use sp_client::silentpayments::utils::SilentPaymentAddress;
|
||||
use sp_client::spclient::SpWallet;
|
||||
use sp_client::bitcoin::secp256k1::schnorr::Signature;
|
||||
@ -77,8 +79,7 @@ impl AnkValidationNoHash {
|
||||
pub struct ValidationToken {
|
||||
member: Member,
|
||||
message: [u8; 32],
|
||||
sig_a: Signature,
|
||||
sig_b: Signature, // User must sign with its 2 paired devices
|
||||
sigs: Vec<Signature>, // User must sign with the requested number of devices
|
||||
}
|
||||
|
||||
sha256t_hash_newtype! {
|
||||
@ -146,13 +147,22 @@ impl Prd {
|
||||
// check that the proof is consistent
|
||||
let sender: Member = serde_json::from_str(&prd.sender)?;
|
||||
if let Some(proof) = prd.proof {
|
||||
// take the 2 spending keys in sender
|
||||
let (address_a, address_b) = sender.get_addresses();
|
||||
let spend_key_a = <SilentPaymentAddress>::try_from(address_a)?.get_spend_key().x_only_public_key().0;
|
||||
let spend_key_b = <SilentPaymentAddress>::try_from(address_b)?.get_spend_key().x_only_public_key().0;
|
||||
// The key in proof must be one of the 2 sender keys
|
||||
// take the spending keys in sender
|
||||
let addresses = sender.get_addresses();
|
||||
let mut spend_keys: Vec<XOnlyPublicKey> = vec![];
|
||||
for address in addresses {
|
||||
spend_keys.push(<SilentPaymentAddress>::try_from(address)?.get_spend_key().x_only_public_key().0);
|
||||
}
|
||||
// The key in proof must be one of the sender keys
|
||||
let proof_key = proof.get_key();
|
||||
if spend_key_a != proof_key && spend_key_b != proof_key {
|
||||
let mut known_key = false;
|
||||
for key in spend_keys {
|
||||
if key == proof_key {
|
||||
known_key = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !known_key {
|
||||
return Err(anyhow::Error::msg("Proof signed with an unknown key"));
|
||||
}
|
||||
proof.verify()?;
|
||||
@ -168,7 +178,7 @@ impl Prd {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn filter_keys(&mut self, to_keep: Vec<String>) {
|
||||
pub fn filter_keys(&mut self, to_keep: HashSet<String>) {
|
||||
let current_keys = self.keys.clone();
|
||||
let filtered_keys: Map<String, Value> = current_keys.into_iter()
|
||||
.filter(|(field, _)| to_keep.contains(field))
|
||||
|
@ -1,59 +1,35 @@
|
||||
use std::str::FromStr;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{Error, Result};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use sp_client::{bitcoin::OutPoint, silentpayments::utils::SilentPaymentAddress};
|
||||
use serde_json::{Map, Value};
|
||||
use sp_client::bitcoin::OutPoint;
|
||||
use tsify::Tsify;
|
||||
use uuid::Uuid;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::pcd::Role;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct ValidationRules {
|
||||
quorum: f32, // Must be > 0.0, <= 1.0
|
||||
min_permission: Role, // Only users with at least that Role can send a token
|
||||
min_signatures_member: f32, // Must be > 0.0, <= 1.0, does each member need to sign with all it's devices?
|
||||
}
|
||||
|
||||
impl ValidationRules {
|
||||
pub fn new(quorum: f32, min_permission: Role, min_signatures_member: f32) -> Self {
|
||||
Self {
|
||||
quorum,
|
||||
min_permission,
|
||||
min_signatures_member,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct Process {
|
||||
pub uuid: String,
|
||||
pub name: String,
|
||||
pub validation_rules: ValidationRules,
|
||||
pub html: String,
|
||||
pub style: String,
|
||||
pub script: String,
|
||||
pub init_state: Value,
|
||||
pub init_state: Map<String, Value>,
|
||||
pub commited_in: OutPoint,
|
||||
}
|
||||
|
||||
impl Process {
|
||||
pub fn new(
|
||||
name: String,
|
||||
validation_rules: ValidationRules,
|
||||
html: String,
|
||||
style: String,
|
||||
script: String,
|
||||
init_state: Value,
|
||||
init_state: Map<String, Value>,
|
||||
commited_in: OutPoint,
|
||||
) -> Self {
|
||||
Self {
|
||||
uuid: Uuid::new_v4().to_string(),
|
||||
name,
|
||||
validation_rules,
|
||||
html,
|
||||
style,
|
||||
script,
|
||||
|
Loading…
x
Reference in New Issue
Block a user